Commit 7fbb6527 authored by Robey Pointer's avatar Robey Pointer
Browse files

add a readme to document some of these features, especially the HID report "commands"

parent 272fbcc1
# MNT Reform Keyboard/OLED firmware
- ATmega32U4: 16 MHz, 32 KB flash, 2 KB SRAM
## Building
You need the AVR toolkit and flash programmer. If you're building on the Reform:
apt install gcc-avr avr-libc dfu-programmer
Instructions for flashing the firmware are in the manual. You need only remove the keyboard frame, on the top face. Additionally, the `./flash.sh` command must be run as root.
## Sending commands
The keyboard understands special commands that can be sent to the "raw HID" interface: usually `/dev/hidraw0` but possibly `/dev/hidraw2` if you booted with an external keyboard attached.
Each command should start with a "type" (an ignored byte) and four-letter command, followed by any arguments. For example, to set the keyboard backlight to its highest setting ("9"):
echo -ne "xLITE9" > /dev/hidraw0
The commands are:
- `PWR0`
Ask the power controller to turn off the power rails (in the laptop), which will power the laptop down.
- `PWR3`
Ask the power controller to turn off aux power (in the laptop).
- `PWR4`
Ask the power controller to turn on aux power (in the laptop).
- `UAR0`
Ask the power controller to turn off UART reporting (in the laptop).
- `UAR1`
Ask the power controller to turn on UART reporting (in the laptop).
- `RPRT`
Display the raw status output of the power controller.
- `LITE` _digit_
Set the keyboard backlight level, using an ASCII digit from `0` (off) to `9` (max).
- `UXPW`
Display the detailed power screen as if the user pressed B in the circle menu.
- `UXST`
Display the detailed status screen as if the user pressed S in the circle menu.
- `OLED` _text..._
Clear the OLED screen and fill it with the provided ASCII text (up to 32 bytes with the large font, and up to 84 bytes with the normal font).
- `WCLR`
Clear the OLED display and move the (invisible) cursor to the top left.
- `FONT` _digit_
Set the OLED font: ASCII `0` for the normal (6x8) font that can display 21 characters across and 4 down, or ASCII `1` for the large (8x16) font that can display 16 characters across and 2 down.
- `WRIT` _text..._
Write to the OLED screen as if it were a very tiny terminal. It follows an (invisible) cursor which wraps to the next line when it reaches the end of a line, and will scroll up if it reaches the end of the screen. The linefeed character (0x0a, or `\n`) will move to the beginning of the next line. In addition, there are escape codes that start with 0xff, described below.
- `WBIT` _offset:u16_ _data..._
Write raw bytes into the OLED framebuffer, starting at an offset from 0 to 511. Each byte covers 8 vertical pixels, with bit 0 (LSB) at the top and bit 7 (MSB) at the bottom. The bytes start in the upper left, moving right and then down, so offset 127 is the pixels from (127, 0) to (127, 7) and offset 128 is the pixels from (0, 8) to (0, 15).
The offset must be encoded as 2 bytes in LSB order, so offset 511 would be `FF 01` (or `\xff\x01`).
- `WRLE` _offset:u16_ _data..._
Write RLE-encoded bytes into the OLED framebuffer. The offset is encoded the same way as in `WBIT`, but the data bytes use a compressed encoding described below.
For example, to draw a tiny square in the upper right corner, using `WBIT`:
echo -ne "xWBIT\x78\x00\xff\x81\x81\x81\x81\x81\x81\xff" > /dev/hidraw0
### Escape codes for `WRIT`
In the `WRIT` command, a sequence of 0xff followed by another byte is interpreted as a special code, with the second byte specifying the command. For example, to switch to the large font, clear the OLED screen, and print "hello":
echo -ne "xWRIT\xff+\xffChello" > /dev/hidraw0
The escape code commands are:
- `C` : Clear the display.
- `I` : Turn on inverted text mode.
- `N` : Turn off inverted text mode.
- `+` : Switch to the large 8x16 font.
- `-` : Switch to the default 6x8 font.
- `B` : Insert a 2-character-wide battery icon showing overall battery level.
- `A` : Insert a 1-character-wide lightning bolt if the battery is charging, or a space otherwise.
- `P` : Insert a 3-character-wide battery percentage (` 0` to `100`).
### RLE bitmap encoding format
Run-length encoding (RLE) is a very primitive compression algorithm which turns repeating bytes into a special code, so that instead of 10 bytes of `0xfe` in a row, it might encode `repeat 10: 0xfe`. This is used to minimize flash space consumed for the splash screen and the low battery warning, but you can also use it to render any 128x32 bitmap with the `WRLE` HID command.
This RLE encoding is made up of frames. Each frame starts with a single byte, where the highest bit (bit 7) indicates the frame type, and the remaining 7 bits indicate the count.
TNNNNNNN
T = 0: uncompressed frame: N is the count of uncompressed bytes that follow
T = 1: repeat: N is the number of times to repeat the following byte
For example, to draw a tiny 8x8 square, the bitmap data would be:
FF 81 81 81 81 81 81 FF
This would be encoded with RLE as:
01 FF 86 81 01 FF
^ ^ ^
| | `-- 1 uncompressed byte: FF
| `-- repeat 81, 6 times
`-- 1 uncompressed byte: FF
There is a python script in `assets/` which will generate the RLE encoding for a 128x32 BMP file:
./assets/packbmp.sh --help
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment