Skip to content

Brisk4t/TossedTheTVKeptTheRemote

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

35 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Tossed The TV — Kept The Remote

Raspberry Pi C++ JavaScript PlatformIO Arduino

There are way too many old TV remotes in the garbage dump.... And way too many overpriced "powerpoint clickers" on Amazon. Its quite appalling.

All you need is $5, an RP2040 and 5 minutes to turn that old, suspiciously sticky T.V. remote into a fully functional USB Keyboard / Clicker / Thingy that you can reprogram on the fly like your favorite hackerman keyboard.

App

App

The firmware receives IR codes from a standard 38 kHz receiver and translates them to USB HID reports based on a JSON configuration stored on the device's filesystem. A browser-based config tool communicates over Web Serial to let you map buttons, learn IR codes, and arrange layouts.

Features

App

Feature Description
Custom Keybindings UI in a browser A browser-based editor for assigning remote buttons to keys, media controls, or custom actions.
Multiple Layers for one remote One physical remote can switch between several layers, so the same buttons do different things.
RGB LED for layers (and vibes) 🔴🟢🔵 Layer-aware RGB lighting that changes color per mode, giving clear visual indication of the current layer.
Complex Combos Support for multi-step inputs, including modifier combinations, repeated presses, and chained actions.
Layouts Visually distinct way of telling different IR remotes apart

Hardware 🛠️

  • USB-Capable microcontroller / dev board RP2040 board Pico, Pico W, RP2040-Zero, etc.
  • IR receiver 38 kHz module (TSOPxx or equivalent).
  • NeoPixel LED Single WS2812 for layer colour feedback.

The TTVKTR uses a Raspberry Pi Pico (RP2040) and an IR receiver to read the codes sent by almost any commercial IR remote and maps them to USB Human Interface Device (HID) commands like Vol + , Play/Pause, or even custom combos.

RP2040 Zero

Wiring (defaults — all configurable in settings)

RP2040 Pin Component Component Pin
GPIO 28 IR receiver OUT
GPIO 16 NeoPixel DIN

Quick Start

Note

Web Serial is Chromium only must use a Chromium-based browser (Chrome / Edge / Brave). Firefox does not support Web Serial.

Tip

Pre-built firmware_with_fs.uf2 images are available on the Releases page — download the latest and drag it onto the board's USB mass-storage drive.

  1. Download the most recently leased firmware_with_fs.uf2 file.
  2. Hold the BOOTSEL / BOOT button on the RP20xx board and plug it in to your computer / press reset (if already plugged in)
  3. Copy the firmware_with_fs.uf2 to the newly discovered USB-Drive
  4. Navigate to The TTVKTR webapp.
  5. Connect and start adding buttons to the layout, press LEARN to record an IR code.
  6. *If you used non-default wiring you can also change the pins used here.

Note

Some RGB leds use different byte orders for their colors i.e. BGR instead of RGB. Use the JSON editor on the webapp to change this setting.

Config UI

Customize

The config UI is deployed to GitHub Pages at https://brisk4t.github.io/TossedTheTVKeptTheRemote/. You can also open web/index.html locally in any Chromium-based browser (Chrome, Edge) — Web Serial is required.

  1. Click Click to Connect and select the device's serial port.
  2. Settings load automatically from the device.
  3. Use the Layers tabs to switch between mapping contexts.
  4. Select a button in the grid, then assign a key from the dropdown or compose a custom combo.
  5. Click Apply to write changes back to the device.

Layout editing

Layouts

Each layer can have one or more layouts — named grids of buttons. Enter edit mode with Edit Layout to drag buttons around, add/remove slots, or use Auto-Add to rapidly bind IR codes to keys by pressing remote buttons followed by the target keyboard key.

Key types

Type Description
Preset Single keyboard or consumer HID key from the dropdown
Custom Compose a sequence of keys and modifiers using the combo editor
Mode Switch Advance to the next layer

Combos:

Combos

  • Modifier chips (Ctrl / Shift / Alt / Win) toggled before capturing a key
  • Multiple steps chained with (e.g. Ctrl+A → Delete → Tab)
  • Text steps that type a literal string character by character

It's been done before right? Right????

I was surprised that this didn't exist already. An IR remote reader is one of the things any hobbyist tests out when they first get started.

There have been attempts like this one by wagiminator and Adafruit's pIRkey but they both need you to weave in and out of code just to paste in a string, and any complex behaviors are up to you. I wanted a way to quickly map the remote buttons to keys and combos like VIA based keyboards, AFAIK this is the only solution that removes that last bit of friction.

For the early version of this code, I pulled an XKCD 927 and built another less-code-but-not-really solution, and called it a day.

XKCD 927 - Standards

But after using it for a while and having to still move a JSON file around I started itching for something more like how VIA and ZMK work for custom mechanical keyboards.

VIA

Note

I did build a ZMK module as well but quickly realized that ZMK studio isn't mature enough for this level of customization and it would need a LOT of work to even get something like runtime RGB led config working from the UI.

Build from source & flash

To build from source, requires PlatformIO.

cd firmware
pio run -t upload              # build and upload firmware
pio run -t uploadfs            # build and upload data partition (settings.json)

For UF2 boards: pio run -e pico and pio run -e pico -t buildfs produce firmware.uf2 and littlefs.uf2 inside .pio/build/pico/. Concatenate them (cat firmware.uf2 littlefs.uf2 > firmware_with_fs.uf2) and drag the combined file onto the board's mass-storage drive.

Settings format

Settings are stored as JSON on LittleFS at /settings.json. The web UI reads and writes this format over serial.

{
  "ir": {
    "modeChangeCode": "0xC40387EE",
    "modeCount": 2,
    "receivePin": 28,
    "handleRepeat": true,
    "repeatInitialDelayReports": 5
  },
  "led": {
    "pin": 16,
    "modeColors": ["0xFF0040", "0x0080FF"],
    "brightnessPercent": 10
  },
  "modes": [
    {
      "name": "Layer 1",
      "slots": [
        { "irCode": "0xC40387EE", "type": "consumer", "key": "0xCD" },
        { "irCode": "0x...",      "type": "keyboard",  "key": "0x28" },
        { "irCode": "0x...",      "type": "keyboard",  "key": "0x1D", "mods": "0x01" },
        { "irCode": "0x...",      "type": "mode_switch" },
        { "irCode": "0x...",      "type": "text",  "value": "hello world" },
        { "irCode": "0x...",      "type": "combo", "steps": [
          { "type": "keyboard", "key": "0x04", "mods": "0x01" },
          { "type": "keyboard", "key": "0x4C" }
        ]}
      ]
    }
  ],
  "layouts": [
    {
      "name": "Default Layout",
      "buttons": [
        { "irCode": "0x...", "x": 0, "y": 0 },
        { "irCode": "0x...", "x": 1, "y": 0 }
      ]
    }
  ]
}

Slot types

type Required fields Notes
keyboard key (USB HID usage ID) Optional mods byte (Ctrl=0x01, Shift=0x02, Alt=0x04, Win=0x08)
consumer key (USB HID consumer usage ID) Volume, media, etc.
mode_switch Cycles to the next layer
text value (string) Sends each character as individual keystrokes
combo steps (array) Each step is a keyboard/consumer/text entry

Firmware limits

Limit Value
Max layers 5
Max buttons per layer 20
Max steps per combo 8
Max text length per step 48 characters

Troubleshooting

No IR codes received — check receiver wiring (VCC/GND/OUT) and ensure the module is running at 3.3 V, not 5 V.

Settings not persisting — ensure the data partition was flashed (pio run -t uploadfs). The firmware falls back to defaults if settings.json is absent.

HID not recognised — verify the correct PlatformIO environment is selected for your board. RP2040 boards require TinyUSB; check platformio.ini.

Acknowledgements (Praise the open source)

  • IRremote — IR receive/decode library by the Arduino-IRremote team
  • ArduinoJson — JSON serialisation library by Benoît Blanchon
  • Adafruit NeoPixel — WS2812 driver library by Adafruit
  • arduino-pico — RP2040 Arduino core (TinyUSB, LittleFS) by Earle F. Philhower III
  • platform-raspberrypi — PlatformIO platform for RP2040 by Maxim Gerhardt
  • Adafruit pIRkey — They tried but alas, not everyone wants to learn micropython.