HDMI CEC to USB Keyboard adapter

Similar projects worth following
Small adapter board to use a TV remote as a keyboard for a HTPC. Also provides Hyperion/Ambilight capabilities.

It is cheap, simple, hackable, ...
Some of the nice features:

  • Instead of requiring a host software (like cec-client) it acts as a standard keyboard.
  • Provides Hyperion-compatible interface for Ambilight setups

It's not a dedicated development board, but it provides some nice development/debug features:

  • a LED
  • a DFU bootloader (can be enabled/disabled with a solder jumper)
  • ICSP header is broken out in case you break with the DFU feature or want to flash the AVR often...
  • Test pads for all interesting signals
    • CEC
    • CEC input
    • CEC output
    • HPD
    • I2C SCL/SDA
    • 5v
    • 3.3v
    • GND
  • ICSP header is broken out in case you break with the DFU feature or
    want to - SPI Port is broken out ( mostly for the WS2811 LED strip )
  • SPI Port is broken out ( mostly for the WS2811 LED strip )
  • Input 5v can be selected from USB (default) or HDMI. In case you want to develop an autonomous device.
  • TWI/I2C is wired to the HDMI bus. The goal is to be able to read the Physical address of the HTPC (currently hard-coded in firmware). Tested and working.
  • Hotplug Detection (HPD) is wired to the HDMI bus. Tested and might be a dead-end for detect TV state...

Firmware status is a bit less advanced:

  • Working
    • CEC spy-mode
    • CEC read/write
    • RawHID USB debug
    • Keyboard emulation
    • Physical address
  • Partially working
    • Ambilight. Limited to only a few (< 100) LEDs
  • ToDo
    • Currently hardcoded
      • Device name
      • Keys mapping between CEC and Keyboard (ie: Currently only for my TV and Kodi)
    • Missing features
      • TV control (turn off, turn on, switch source)



Adobe Portable Document Format - 51.54 kB - 12/01/2019 at 15:07


  • 1 × Atmega32u2-AU Microprocessors, Microcontrollers, DSPs / ARM, RISC-Based Microcontrollers

  • A few upgrades !

    RedoX04/23/2020 at 20:04 1 comment

    I had a few hours to spend on this today and am glad to report a minor improvement.

    Previsouly, the Physical Address (~HDMI port) was hardcoded in the firmware, which lead to some issues, like the TV switching to the wrong HDMI source.

    The firmware now uses the I2C port on the HDMI link to get the Physical Address directly from the EDID info.

    I tested it on three screens:

    - Computer screen, only one input.

    - Small Grundig TV, two HDMI inputs. Both give the same Physical address, but it's a TV bug. I might try to reprogram the EDID info to fix this, eventually.

    - Large LG TV, three or four HDMI inputs. Best result since all the HDMI ports have a different address.

    A few other improvements in both the firmware and the hardware files have also been submitted, improving the behaviour or ease of use. Last hardware revision adds a switch to reboot in DFU mode. It's way faster than ICSP and does not require any soldering, which is nice.

    Note that the Github repo has been reset to also include the hardware/KiCAD files.

View project log

  • 1
    Assembly notes
    • All passive are 0603
    • Most values can be approximated ( I tried not to change them too much on he CEC part though, not really knowing what whas going on there)
    • R5 must not be placed (well, at least, it didn't work when I tried)
    • I2C pullups (R11/R12) should not be placed (I didn't ttry this yet...)
  • 2
    Programming notes
    • DFU upgrade
      • Solder the jumper on the board
      • Plug the USB port in your computer
      • Reset the board by shorting the 2nd (GND) and 3rd (/RST) pads on the ICSP header
      • I use "dfu-programmer" from the Debian repository
        • Sometimes, an "erase" command is required before the "flash" command
    • ICSP upgrade:
      • Pinout for the ICSP header is the following:
        1. Vcc
          • If the USB port is not connected, you can put 3.3v or 5v here, the Atmega32u2 supports both.
          • If the USB port is connected, it is better to leave this unconnected
        2. Gnd
        3. /RST
        4. SCLK
        5. MOSI
        6. MISO
      • I use a DIY UsbtinyISP clone and never had any issue with it.
      • Be aware that you might end up erasing the DFU bootloader on the chip. Good luck finding a replacement ^^

View all instructions

Enjoy this project?



Sean wrote 11/24/2020 at 11:39 point

I was looking to convert your project over to function with an Xbox One (It mostly works!). Would I just need to modify the handlers.c file for the correct keypad commands? Also does this support the use of "&" to have multiple key commands at the same time? One of the commands is Windows key and M for the menu which I'm guessing I could use "KEY_CTRL&KEY_ESC&KEY_M"?  I also modified common.h to change the name of the board to Xbox One. Am I missing anything? I haven't set up to program the board quite yet, but I'm a little unfamiliar with the process. Do I just need to boot the Firmware using the process you outlined (DFU jumper solder etc.)? If that's the case, what is the sw folder for? Do I install both?

Something I noticed is that if I'm on a different input, the keyboard shortcuts still override the TV controls which isn't ideal (maybe just the select button?) and it is difficult to change inputs on the TV.  Maybe a future feature could be "muting" the keyboard and allow for normal functionality of the remote if a menu is present or if it isn't on the proper input, or could there be something else at hand. I've programmed in the past, but forgive me, it has been a while so I'm a little slow going through the code, but I have some training in computer science.

  Are you sure? yes | no

RedoX wrote 11/25/2020 at 10:52 point


You can define new handlers, and then associate them to a CEC opcode in main.c. If you just need to remap keys, you can change the content/length of the array in handlers.c. I just adapted the keyboard library from teensyduino with a Lookup Table, as a quick'n'dirty keyboard implementation. I am pretty sure it doesn't support multiple keypresses at the same time as is. The keyboard library does support up to 6 keys with modifiers though. You would have to change the mapping table and the cecKeyDown function. Changing the call to usb_keyboard_press() may be enough., but I never tried it... Otherwise, I guess you would have to use the usb_keyboard_send() function instead of usb_keyboard_press().

Changing the name is alright. I planned to have some kind of EEPROM configuration for that, but I have yet to find the time and an easy way to do it.

To boot the board in DFU, you need to solder the jumper on the board, and trigger a reset (you can either solder the on-board switch or just short the reset to ground with tweezers). The process is outlined in this app note: I planned to add a feature to reboot in bootloader, but it is still on my ToDo list. To flash the board, I use the dfu-programmer tool (installed from apt in Debian). There is also an ICSP connector, for more serious programming, but I find DFU easier and faster to use. If you plan to do a lot of programming, soldering the switch to boot in DFU is a nice option.

The sw/ folder was just for testing HID stuff, for the configuration features that I planned to develop. For debugging output, you can use the hid_listen tool from PJRC.

I never had the issue you mention with the different inputs, since I only have one thing connected to my TV, but it makes sense since the CEC bus is shared by all the devices. There is a notification for the current input and the board is able to identify its own input using the EDID features, it shouldn't be really difficult to match the two and "disable" some features when on a different input.

Actually, in this project, I really focused on the difficult part, the CEC communication. I tried to make an easy to use library and then I built some "demo firmware" around that. It's free for people to use and modify to their needs. Feedback is always welcome, and I will try to improve the "demo" when I manage to find some spare time, but I really can't estimate when. It's also difficult to develop vendor-specific features or workaround since I don't have many TVs. Feel free to send me an email or open a github issue or pull request if you have a specific issue or question or a new feature you find would be nice to merge in the main project, I am always happy to help :)

  Are you sure? yes | no

Kyle Brinkerhoff wrote 04/23/2020 at 21:44 point

this little do-dad is pretty cool, would love to see an IR  LED on this so we can intercept cec commands and do cool stuff over ir

  Are you sure? yes | no

RedoX wrote 11/11/2020 at 17:18 point


Sorry I did'nt reply earlier, I didn't get a notification and I lacked time for hobby projects these past months.

There are some GPIOs broken out, initially to control WS2812 LED strips, but you can wire an IR LED instead and write some firmware to send IR codes.

  Are you sure? yes | no

Michael R Colton wrote 01/06/2020 at 22:13 point

I would like my TV to behave like a monitor, that is, to turn on when the computer is on and awake, and off when it is off or asleep. I can handle the PC side of that (sending a command when the screen saver activates, for example) would this board work to send the relevant power on and power off commands to the TV? Thanks!

  Are you sure? yes | no

RedoX wrote 01/12/2020 at 09:47 point


If your TV supports CEC commands, you should be able to send turn on/off commands with this board. Some firmware development is required though, since the firmware currently only support TV => PC communication (using a keyboard emulation).

To make sure your TV supports the CEC features your need, you can try with a RaspberryPi if you happen to already have one, and the cec-utils package.

  Are you sure? yes | no

Vladimir wrote 12/13/2019 at 22:30 point

Hello. I am interested in your project. I spent a lot of time finding it. On the Internet there are projects with arduino but they are all outdated and no one is discussing them. There are schemes for connecting to the CEC line but without I2C. I’m interested in whether it is possible to make a CEC to UART converter on the basis of your device. Why do I have this, I have an HDMI ARC board that is controlled by an IR remote and a bluetooth TV. I would like to grab the volume control signal on the CEC bus and pass it to the amplifier controller.

  Are you sure? yes | no

RedoX wrote 12/14/2019 at 11:18 point


UART is not straightforward with this design... I use the hardware UART pins to read/drive the CEC line. You could probably use a software UART library if you don't have too high requirements.

I haven't tried the I2C part yet, so I can't say for sure that it works. Since the Atmega32u2 doesn't have any hardware I2C, I will have to use a software implementation but I have already done it on an other project and it went fine, so I believe it should work.

You can probably use the same schematic as a base for a more elaborate board. The hardest part on this project was the firmware/CEC library. As you mentioned, there a very few similar projects available, and most of them look unmaintained/dead, so I had to rewrite one from scratch, in C.

I don't have much time to work on the firmware right now, but the upcoming holidays should help and I will finally be able to release the firmware...

  Are you sure? yes | no

Tim Ansell wrote 12/05/2019 at 10:30 point

What part is that upside down HDMI connector? I've never seen one like it before but seems super useful for passthrough devices like this!

  Are you sure? yes | no

RedoX wrote 12/07/2019 at 09:52 point

Hello !

The upside down HDMI connector is the hardest part to find actually. Molex used to make them, TE Connectivity is phasing them out, ... Sales were too low I guess.

I may have to change the design in the future if I don't manage to get a reliable source for theses parts though...

You can find them as "reverse HDMI connectors" on eBay or Aliexpress. Another good source/option seems to be to look for "PS4 HDMI connector", then you can find them on eBay, Amazon, ... but the footprint is a bit different.

Making a pass-through double sided board would be way more difficult without them.

Side note, this is not required for the CEC stuff to work. CEC is a multipoint bus shared by all the HDMI ports of the TVs. Assuming you have a free HDMI port, you can make a board with just the common HDMI connector, plug it in the unused port, and it should work the same way CEC2Usb does.

  Are you sure? yes | no

Paul Fernquist wrote 12/25/2019 at 03:40 point

I've seen feed through with two vertical connectors.

  Are you sure? yes | no

Mike Szczys wrote 12/02/2019 at 21:24 point

Very clever approach. I've often wondered about hacking in CEC for some of my devices... I have a TV that claims to have CEC but it doesn't seem to work wiht a Fire TV Stick. This would be a fun way to play around -- sniffing what the TV is sending and finding a way to make it actually work.

  Are you sure? yes | no

RedoX wrote 12/04/2019 at 11:10 point

Hello and thanks for you kind comment. The hardware part is quite simple, I just adapted it from the datasheet of the TDA9950. I think it should be possible to simplify it a little bit to use one I/O instead of two (but I have plenty, so I don't really care). The tricky part is the software. Fortunately, CEC is quite slow (in the milliseconds range) and supported in open logic analyzer softwares, like sigrok, which makes debugging easier.

I am currently refactoring the software to be able to reconfigure it at runtime and/or use the special modes, like the CEC-spy; but I haven't figured the best way yet. I plan post an update and to release the sources as soon as I have improved this.

  Are you sure? yes | no

Similar Projects

Does this project spark your interest?

Become a member to follow this project and never miss any updates