BB Q10 Keyboard-to-I2C Software

This software is designed to interface a BB Q10 keyboard matrix as a I2C slave.

The key presses are put on a FIFO, which can be queried over I2C.

The software also allows for basic configuration of the behaviour.

The software also controls the backlight of the keyboard and one additional device.

There is also a GPIO expander functionality where the MCU pins can be controlled over I2C. The pin direction (in/out), output value (high, low), and pull (none/up/down) can be controlled.

See Protocol for details.

Building

See the targets directory for a list of available targets.

git clone https://github.com/arturo182/bbq10kbd_i2c_sw.git
cd bbq10kbd_i2c_sw
make TARGET=<target>

You can also add DEBUG=1 to make to enable the debug UART prints. Make sure to clean when switching debug on or off.

Implementations

Here are libraries that allow interaction with the boards running this software:

Protocol

The device uses I2C slave interface to communicate, the address can be configured in app/config/conf_app.h, the default is 0x1F.

You can read the values of all the registers, the number of returned bytes depends on the register. It's also possible to write to the registers, to do that, apply the write mask 0x80 to the register ID (for example, the backlight register 0x05 becomes 0x85).

The FW Version register (REG_VER = 0x01)

Data written to this register is discarded. Reading this register returns 1 byte, the first nibble contains the major version and the second nibble contains the minor version of the firmware.

The configuration register (REG_CFG = 0x02)

This register can be read and written to, it's 1 byte in size.

This register is a bit map of various settings that can be changed to customize the behaviour of the firmware.

Bit Name Description
7 CFG_USE_MODS Should Alt, Sym and the Shift keys modify the keys being reported.
6 CFG_REPORT_MODS Should Alt, Sym and the Shift keys be reported as well.
5 CFG_PANIC_INT Currently not implemented.
4 CFG_KEY_INT Should an interrupt be generated when a key is pressed.
3 CFG_NUMLOCK_INT Should an interrupt be generated when Num Lock is toggled.
2 CFG_CAPSLOCK_INT Should an interrupt be generated when Caps Lock is toggled.
1 CFG_OVERFLOW_INT Should an interrupt be generated when a FIFO overflow happens.
0 CFG_OVERFLOW_ON When a FIFO overflow happens, should the new entry still be pushed, overwriting the oldest one. If 0 then new entry is lost.

Defaut value: CFG_OVERFLOW_INT | CFG_KEY_INT | CFG_USE_MODS

Interrupt status register (REG_INT = 0x03)

When an interrupt happens, the register can be read to check what caused the interrupt. It's 1 byte in size.

Bit Name Description
7 N/A Currently not implemented.
6 N/A Currently not implemented.
5 INT_GPIO The interrupt was generated by a input GPIO changing level.
4 INT_PANIC Currently not implemented.
3 INT_KEY The interrupt was generated by a key press.
2 INT_NUMLOCK The interrupt was generated by Num Lock.
1 INT_CAPSLOCK The interrupt was generated by Caps Lock.
0 INT_OVERFLOW The interrupt was generated by FIFO overflow.

After reading the register, it has to manually be reset to 0x00.

For INT_GPIO check the bits in REG_GIN to see which GPIO triggered the interrupt. The GPIO interrupt must first be enabled in REG_GIC.

Key status register (REG_KEY = 0x04)

This register contains information about the state of the fifo as well as modified keys. It is 1 byte in size.

Bit Name Description
7 N/A Currently not implemented.
6 KEY_NUMLOCK Is Num Lock on at the moment.
5 KEY_CAPSLOCK Is Caps Lock on at the moment.
0-4 KEY_COUNT Number of items in the FIFO waiting to be read.

Backlight control register (REG_BKL = 0x05)

Internally a PWM signal is generated to control the keyboard backlight, this register allows changing the brightness of the backlight. It is 1 byte in size, 0x00 being off and 0xFF being the brightest.

Default value: 0xFF.

Debounce configuration register (REG_DEB = 0x06)

Currently not implemented.

Default value: 10

Poll frequency configuration register (REG_FRQ = 0x07)

Currently not implemented.

Default value: 5

Chip reset register (REG_RST = 0x08)

Reading or writing to this register will cause a SW reset of the chip.

FIFO access register (REG_FIF = 0x09)

This register can be used to read the top of the key FIFO. It returns two bytes, a key state and a key code.

Possible key states:

Value State
1 Pressed
2 Pressed and Held
3 Released

Secondary backlight control register (REG_BK2 = 0x0A)

Internally a PWM signal is generated to control a secondary backlight (for example, a screen), this register allows changing the brightness of the backlight. It is 1 byte in size, 0x00 being off and 0xFF being the brightest.

Default value: 0xFF.

GPIO direction register (REG_DIR = 0x0B)

This register controls the direction of the GPIO expander pins, each bit corresponding to one pin. It is 1 byte in size.

The actual pin[7..0] to MCU pin assignment depends on the target, see conf_target.h of the target for the assignments.

Any bit set to 1 means the GPIO is configured as input, any bit set to 0 means the GPIO is configured as output.

Default value: 0xFF (all GPIOs configured as input)

GPIO input pull enable register (REG_PUE = 0x0C)

If a GPIO is configured as an input (using REG_DIR), a optional pull-up/pull-down can be enabled.

This register controls the pull enable status, each bit corresponding to one pin. It is 1 byte in size.

The actual pin[7..0] to MCU pin assignment depends on the target, see conf_target.h of the target for the assignments.

Any bit set to 1 means the input pull for that pin is enabled, any bit set to 0 means the input pull for that pin is disabled.

The direction of the pull is done in REG_PUD.

When a pin is configured as output, its bit in this register has no effect.

Default value: 0 (all pulls disabled)

GPIO input pull direction register (REG_PUD = 0x0D)

If a GPIO is configured as an input (using REG_DIR), a optional pull-up/pull-down can be configured.

The pull functionality is enabled using REG_PUE and the direction of the pull is configured using this register, each bit corresponding to one pin. This register is 1 byte in size.

The actual pin[7..0] to MCU pin assignment depends on the target, see conf_target.h of the target for the assignments.

Any bit set to 1 means the input pull is set to pull-up, any bit set to 0 means the input pul is set to pull-down.

When a pin is configured as output, its bit in this register has no effect.

Default value: 0xFF (all pulls set to pull-up, if enabled in REG_PUE and set to input in REG_DIR)

GPIO value register (REG_GIO = 0x0E)

This register contains the values of the GPIO Expander pins, each bit corresponding to one pin. It is 1 byte in size.

The actual pin[7..0] to MCU pin assignment depends on the target, see conf_target.h of the target for the assignments.

If a pin is configured as an output (via REG_DIR), writing to this register will change the value of that pin.

Reading from this register will return the values for both input and output pins.

Default value: Depends on pin values

GPIO interrupt config register (REG_GIC = 0x0F)

If a GPIO is configured as an input (using REG_DIR), an interrupt can be configured to trigger when the pin's value changes.

This register controls the interrupt, each bit corresponding to one pin.

The actual pin[7..0] to MCU pin assignment depends on the target, see conf_target.h of the target for the assignments.

Any bit set to 1 means the input pin will trigger and interrupt when changing value, any bit set to 0 means no interrupt for that pin is triggered.

When an interrupt happens, the GPIO that triggered the interrupt can be determined by reading REG_GIN. Additionally, the INT_GPIO bit will be set in REG_INT.

Default value: 0x00

GPIO interrupt status register (REG_GIN = 0x10)

When an interrupt happens, the register can be read to check which GPIO caused the interrupt, each bit corresponding to one pin. This register is 1 byte in size.

The actual pin[7..0] to MCU pin assignment depends on the target, see conf_target.h of the target for the assignments.

After reading the register, it has to manually be reset to 0x00.

Default value: 0x00

Version history

v0.4:
- Add secondary backlight support (REG_BK2)
- Add GPIO Expander functionality
	- Add GPIO direction configuration (REG_DIR)
	- Add GPIO input pull configuration (REG_PUE and REG_PUD)
	- Add GPIO value control (REG_GIO)
	- Add GPIO interrupt configuration and status (REG_GIC and REG_GIN)
- Add `INT_GPIO` to `REG_INT` to show that a GPIO triggered the interrupt
- Add support for building a debug build directly from command line
- Add an extra print on boot to show version info

v0.3:
- Change values sent for mods if CFG_REPORT_MODS is enabled so they don't overlap the buttons
- Send different value for left and right shifts if CFG_REPORT_MODS is enabled
- Change FIFO size to 31 so it's reported correctly in REG_KEY if FIFO is full

v0.2:
- Add support for KEY_LEFT2 and KEY_RIGHT2
- Add the Keyboard FeatherWing target

v0.1:
- Initial release