{"id":47616803,"url":"https://github.com/mornepousse/kesp_firmware","last_synced_at":"2026-04-11T10:12:49.590Z","repository":{"id":326762857,"uuid":"892752919","full_name":"mornepousse/KeSp_firmware","owner":"mornepousse","description":"Open-source keyboard firmware framework for ESP32-S3, designed for custom mechanical keyboards with display, USB HID, Bluetooth HID and multi-layer keymaps.","archived":false,"fork":false,"pushed_at":"2026-04-01T07:23:53.000Z","size":104684,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-04-02T05:06:38.096Z","etag":null,"topics":["ble-hid","esp-idf","esp32s3","firmware","freertos","keyboard","keyboard-firmware","keymapping","lvgl","mechanical-keyboard","split-keyboard","usb-hid"],"latest_commit_sha":null,"homepage":"","language":"C","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"other","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/mornepousse.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2024-11-22T17:57:02.000Z","updated_at":"2026-04-01T07:23:58.000Z","dependencies_parsed_at":null,"dependency_job_id":"3ae92ab1-89e8-4470-8d92-a01e5fdbc687","html_url":"https://github.com/mornepousse/KeSp_firmware","commit_stats":null,"previous_names":["mornepousse/kase_code","mornepousse/kase_firmware"],"tags_count":17,"template":false,"template_full_name":null,"purl":"pkg:github/mornepousse/KeSp_firmware","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mornepousse%2FKeSp_firmware","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mornepousse%2FKeSp_firmware/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mornepousse%2FKeSp_firmware/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mornepousse%2FKeSp_firmware/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/mornepousse","download_url":"https://codeload.github.com/mornepousse/KeSp_firmware/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mornepousse%2FKeSp_firmware/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":31549900,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-07T16:28:08.000Z","status":"online","status_checked_at":"2026-04-08T02:00:06.127Z","response_time":54,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["ble-hid","esp-idf","esp32s3","firmware","freertos","keyboard","keyboard-firmware","keymapping","lvgl","mechanical-keyboard","split-keyboard","usb-hid"],"created_at":"2026-04-01T21:33:41.454Z","updated_at":"2026-04-08T10:00:48.487Z","avatar_url":"https://github.com/mornepousse.png","language":"C","funding_links":[],"categories":[],"sub_categories":[],"readme":"# KeSp — Keyboard ESP32 Framework\n\nOpen-source keyboard firmware framework for ESP32-S3, designed for custom mechanical keyboards with display, USB HID, Bluetooth HID, advanced keycodes, and a virtual pet.\n\n\u003e KeSp provides the framework. Your board definition provides the hardware specifics.\n\n---\n\n## Features\n\n### Keyboard\n- **Multi-layer keymaps** — Up to 10 layers with per-key mapping, persistent in NVS\n- **Mod-Tap / Layer-Tap** — Hold for modifier/layer, tap for keycode\n- **One-Shot Modifier/Layer** — Apply modifier or layer for next key only\n- **Tap Dance** — Multiple taps on same key trigger different actions (16 slots)\n- **Combos** — Press two keys simultaneously for a different keycode (16 slots)\n- **Leader Key** — Key sequences that trigger actions with modifiers (16 entries)\n- **Caps Word** — Auto-shift letters, deactivate on space/punctuation\n- **Repeat Key** — Repeat the last keypress\n- **Macros** — Up to 20 macros with sequences, modifiers, and delays\n\n### Hardware\n- **Board abstraction** — All hardware config in `boards/\u003cname\u003e/board.h`\n- **Key matrix scanning** — Event-driven with configurable debounce\n- **USB HID** — Keyboard + mouse composite device via TinyUSB\n- **Bluetooth HID** — BLE HID with automatic fallback to USB\n- **Display support** — I2C OLED (SSD1306) and SPI round (GC9A01) via LVGL\n- **Display backend abstraction** — Add new display types with one file\n- **WS2812 LED strip** — Reactive animations (breathe, chase, KPM bar)\n- **OTA firmware update** — Flash new firmware over USB CDC, no programmer needed\n- **Deep sleep** — Configurable inactivity timeout\n\n### Statistics \u0026 Pet\n- **Key statistics** — Per-key press counts and bigram tracking, auto-saved to NVS\n- **Tamagotchi** — Virtual pet on both displays, driven by keyboard usage\n  - 20 evolution stages (OpenCritter sprites, MIT)\n  - Stats: hunger, happiness, energy, health\n  - Keyboard interactions: feed, play, sleep, medicine\n  - \"Tama time\" = keypresses (pauses when inactive, no penalty)\n\n### CDC Serial Protocol\n- **Binary-only protocol** — KS/KR frames with CRC-8, no ASCII fallback\n- **Full configuration** — Keymaps, macros, tap dance, combos, leader, tama\n- **Statistics** — Binary heatmap data + text format via binary frames\n- **OTA firmware update** — Binary OTA over CDC with chunked transfer\n\n---\n\n## Project structure\n\n```\nboards/\n  kase_v1/              # Round SPI display, LED strip\n  kase_v2/              # I2C OLED\n  kase_v2_debug/        # V2 with debug GPIO overrides\nmain/\n  input/                # Matrix scan, key processing, HID reports\n    keyboard_task.c     # Main coordinator (ISR → process → send)\n    key_processor.c     # Keycode building, layers, advanced features\n    hid_report.c        # HID queue + sender task\n    matrix_scan.c       # Physical key scanning\n    key_stats.c         # Keystroke stats + bigrams\n    tap_hold.c          # Tap/Hold engine (MT, LT, OSM)\n    tap_dance.c         # Tap Dance engine\n    combo.c             # Simultaneous key combos\n    leader.c            # Leader key sequences\n    key_features.c      # OSM, OSL, Caps Word, Repeat Key\n  comm/\n    hid_transport.c     # USB/BLE routing abstraction\n    cdc/\n      cdc_acm_com.c     # CDC core (binary protocol dispatch)\n      cdc_binary_cmds.c # All command handlers (KS/KR protocol)\n      cdc_binary_protocol.c # Frame parser, CRC-8, response helpers\n      cdc_ota.c         # OTA firmware update (binary only)\n    ble/                # Bluetooth HID stack\n    usb/                # USB HID (TinyUSB)\n  display/\n    status_display.c    # Backend-agnostic coordinator\n    display_backend.h   # Backend interface (vtable)\n    oled/               # I2C OLED backend\n    round/              # SPI round display + tamagotchi\n  tama/\n    tama_engine.c       # Game logic (display-agnostic)\n    tama_render.c       # LVGL sprite renderer\n    tama_sprites.h      # OpenCritter sprite data (MIT)\n  led/                  # WS2812 LED strip animations\n  sys/                  # NVS helpers, CPU monitoring\n  config/               # Version\ntest/                   # Host-side unit tests (1008 tests)\ndocs/                   # Protocol documentation\nscripts/                # Build automation, sprite conversion\n```\n\n---\n\n## Quick start\n\n### Build\n\nRequires [ESP-IDF v5.x](https://docs.espressif.com/projects/esp-idf/en/latest/esp32s3/get-started/).\n\n```bash\nsource ~/esp/esp-idf/export.sh\n\n# Build for a specific board\nidf.py -DBOARD=kase_v2_debug build\nidf.py -DBOARD=kase_v1 build\n\n# Full flash (required for first flash or partition table change)\nesptool --chip esp32s3 -p /dev/ttyUSB0 -b 460800 write-flash \\\n  0x0 build/bootloader/bootloader.bin \\\n  0x8000 build/partition_table/partition-table.bin \\\n  0xf000 build/ota_data_initial.bin \\\n  0x20000 build/KeSp.bin \\\n  0x420000 build/storage.bin\n\n# After first flash, use OTA via CDC (no programmer needed)\n```\n\n### Tests\n\n```bash\ncd test \u0026\u0026 mkdir -p build \u0026\u0026 cd build \u0026\u0026 cmake .. \u0026\u0026 make \u0026\u0026 ./test_runner\n# 1008 tests, 0 failures\n```\n\n---\n\n## Advanced keycodes\n\nAll keycodes are 16-bit, configurable via CDC serial or the remapping software.\n\n| Feature | Keycode | Behavior |\n|---------|---------|----------|\n| Mod-Tap | `K_MT(mod, key)` | Hold = modifier, Tap = keycode |\n| Layer-Tap | `K_LT(layer, key)` | Hold = layer, Tap = keycode |\n| Layer-Mod | `K_LM(layer, mods)` | Hold = layer + modifiers |\n| One-Shot Mod | `K_OSM(mod)` | Tap = next key gets modifier |\n| One-Shot Layer | `K_OSL(layer)` | Next key uses that layer |\n| Caps Word | `K_CAPS_WORD` | Auto-shift letters until space |\n| Repeat | `K_REPEAT` | Repeat last keypress |\n| Leader | `K_LEADER` | Start key sequence |\n| Tap Dance | `K_TD(index)` | 1/2/3 taps + hold = 4 actions |\n| Tama Feed | `K_TAMA_FEED` | Feed the virtual pet |\n\nFull encoding spec: [`docs/KEYCODE_MAP.md`](docs/KEYCODE_MAP.md)\n\n---\n\n## CDC binary protocol\n\nThe keyboard exposes a USB CDC serial port for configuration using a binary frame protocol (KS/KR).\n\n```\nRequest:  [0x4B][0x53][cmd:u8][len:u16 LE][payload...][crc8]\nResponse: [0x4B][0x52][cmd:u8][status:u8][len:u16 LE][payload...][crc8]\n```\n\n```python\nimport serial, struct\n\ndef crc8(data):\n    crc = 0\n    for b in data:\n        crc ^= b\n        for _ in range(8):\n            crc = ((crc \u003c\u003c 1) ^ 0x31) \u0026 0xFF if crc \u0026 0x80 else (crc \u003c\u003c 1) \u0026 0xFF\n    return crc\n\nser = serial.Serial(\"/dev/ttyACM0\", timeout=2)\n\n# Ping\nser.write(bytes([0x4B, 0x53, 0x04, 0, 0, 0]))\n\n# Get version (cmd 0x01)\nser.write(bytes([0x4B, 0x53, 0x01, 0, 0, 0]))\n```\n\nFull protocol reference: [`docs/CDC_BINARY_PROTOCOL.md`](docs/CDC_BINARY_PROTOCOL.md)\n\n---\n\n## Adding a new board\n\n1. Create `boards/\u003cname\u003e/board.h` with hardware macros (GPIOs, display, USB IDs, etc.)\n2. Create `boards/\u003cname\u003e/board_keymap.c` with default keymaps\n3. Build: `idf.py -DBOARD=\u003cname\u003e build`\n\nSee `boards/kase_v2/board.h` for a minimal example, `CONTRIBUTING.md` for conventions.\n\n---\n\n## Documentation\n\n| Document | Description |\n|----------|-------------|\n| [`CONTRIBUTING.md`](CONTRIBUTING.md) | Development guide, architecture, conventions |\n| [`docs/CDC_BINARY_PROTOCOL.md`](docs/CDC_BINARY_PROTOCOL.md) | Binary protocol reference (all commands) |\n| [`docs/KEYCODE_MAP.md`](docs/KEYCODE_MAP.md) | Keycode encoding specification |\n| [`docs/CDC_KEYSTATS_PROTOCOL.md`](docs/CDC_KEYSTATS_PROTOCOL.md) | Stats/bigrams binary format details |\n| [`docs/TAMA_SPRITE_GUIDE.md`](docs/TAMA_SPRITE_GUIDE.md) | Sprite design guide for artists |\n\n---\n\n## Related projects\n\n- **KaSe PCB** — Hardware, schematics, mechanical design: https://github.com/mornepousse/KaSe_PCB\n- **KeSp Controller** — Desktop remapping software: https://github.com/mornepousse/KeSp_controller\n\n---\n\n## License\n\n**GPL-3.0** — See [LICENSE](LICENSE).\n\nTamagotchi sprites from [OpenCritter](https://github.com/SuperMechaCow/OpenCritter) (MIT License).\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmornepousse%2Fkesp_firmware","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmornepousse%2Fkesp_firmware","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmornepousse%2Fkesp_firmware/lists"}