aboutsummaryrefslogtreecommitdiffstats
path: root/README.md
diff options
context:
space:
mode:
authorDanilo M. <danix@danix.xyz>2026-10-02 20:34:45 +0200
committerDanilo M. <danix@danix.xyz>2026-10-02 20:34:45 +0200
commit0687e489e0e2b273f8c3c466ad77cb2066bc168f (patch)
tree8a1b7481b7e475fe1ea96f208f5abc2887003b6e /README.md
downloadak820-upload-0687e489e0e2b273f8c3c466ad77cb2066bc168f.tar.gz
ak820-upload-0687e489e0e2b273f8c3c466ad77cb2066bc168f.zip
Add ak820-upload: AK820 Pro screen uploader over hidraw
Std-only Rust CLI. ffmpeg decodes any image/GIF/video to 128x128 RGB565LE frames; the upload follows a USB capture of the official Windows software: report-ID-0 feature reports each followed by a 64-byte GET_REPORT, IMAGE sub 0x02 with chunk count, 4096-byte chunks on interface 2 paced by the keyboard's acks on EP 0x84, then SAVE. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Diffstat (limited to 'README.md')
-rw-r--r--README.md57
1 files changed, 57 insertions, 0 deletions
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..680e683
--- /dev/null
+++ b/README.md
@@ -0,0 +1,57 @@
+# ak820-upload
+
+Upload an image, GIF or video to the 128x128 TFT screen of the AJAZZ AK820 Pro
+keyboard from Linux, without the official Windows software or a browser.
+
+Any input ffmpeg can read works. It is center-cropped to a square, scaled to
+128x128, resampled to the chosen frame rate and capped at 255 frames, then
+written to the keyboard's stored animation (the "GIF" page, Fn + knob press
+to switch pages).
+
+## Requirements
+
+- Rust (build only, no crates)
+- ffmpeg at runtime
+- the keyboard on the USB-C cable in wired mode (VID:PID `0c45:8009`)
+- read/write access to its `/dev/hidraw*` nodes (desktop sessions usually
+ grant this through `uaccess`; otherwise add a udev rule for `0c45:8009`)
+
+## Build and usage
+
+```sh
+cargo build --release
+./target/release/ak820-upload <image|gif|video> [fps]
+```
+
+`fps` defaults to 15 and must be between 2 and 50: the keyboard stores each
+frame's delay in 2 ms units in one byte, so no frame can last longer than
+about 510 ms. At 15 fps the 255-frame limit gives about 17 seconds.
+
+## Protocol
+
+Taken from a USB capture of the official software (v1.0.0.5):
+
+1. On interface 3, feature reports with report ID 0 and 64 bytes of data:
+ `04 18` (start), then `04 72 02 .. .. .. .. .. <chunks lo> <chunks hi>`.
+ Every SET_REPORT is followed by a 64-byte GET_REPORT, without which the
+ keyboard ignores the upload.
+2. On interface 2 (interrupt OUT endpoint 0x03), the payload in 4096-byte
+ chunks. The keyboard acks each chunk with `01 5a 02` on endpoint 0x84, and
+ the next chunk is only sent after the ack.
+3. `04 02` (save) on interface 3.
+
+Payload: a 256-byte header (frame count, one delay byte per frame in 2 ms
+units, 0xFF padding), then every frame as 128x128 RGB565 little-endian, padded
+with 0xFF to a whole number of chunks.
+
+## License
+
+GPL-2.0-only. See [LICENSE](LICENSE).
+
+## Development Approach
+
+This project is developed using AI-assisted tools. Code is generated with the help of AI based on human-provided specifications, design decisions, and iterative feedback.
+
+All contributions are reviewed, tested, and curated by the maintainer before being included in the codebase. AI is used as a productivity and exploration tool, while human oversight remains central to all decisions.
+
+The goal is to combine the flexibility of AI-assisted development with standard open-source practices such as transparency, review, and accountability.