While I was waiting for my HDMI to RS232 converter to do it’s thing, I did some more googling and discovered this forum post (big thanks qwerty_UK for posting!) of Yamaha/NEC IR codes for my Yamaha RX-V767 AV receiver. The scans listed several of the codes I was after, but I had no way to covert them to LIRC format. Since I already knew some of the AV receiver IR codes in LIRC format from irrecord, I thought I’d have a look at converting between the two.

The Yamaha/NEC (YN) codes come in 4 types:

  • xx-xx (eg 7E-2A)
  • xx-xxxx (eg 7A-532C)
  • xxxx-xx (eg 7F01-5A)
  • xxxx-xxxx (eg 7F01-5E21)

LIRC required a 32bit number for the Yamaha IR codes. When you match them up, it doesn’t make a lot of sense:

  • KEY_POWER: 0x7E8154AB  ->  7E-2A
  • KEY_AV1: 0x5EA1CA34  ->  7A-532C
  • KEY_1: 0xFE808A75  ->  7F01-5A
  • KEY_PRESET-: 0xFE807A84  ->  7F01-5E21

In binary however, patterns start to emerge (the xxxx’s are explained later, and the colon is just to split the 32bit number for ease of reading):

  • KEY_POWER: 0111 1110 xxxx xxxx : 0101 0100 xxxx xxxx    ->   0111 1110 – 0010 1010
  • KEY_AV1: 0101 1110 xxxx xxxx : 1100 1010 0011 0100  ->  0111 1010 – 0101 0011 0010 1100
  • KEY_1: 1111 1110 1000 0000 : 1000 1010 xxxx xxxx  -> 0111 1111 0000 0001 – 0101 1010
  • KEY_PRESET-: 1111 1110 1000 0000 : 0111 1010 1000 0100  ->  0111 1111 0000 0001 – 0101 1110 0010 0001

So from this, some rules can be deduced.

For the YN 16bit codes (xx-xx):

  • LIRC Byte 1 is YN Byte 1 with nibbles swapped, and nibble bit orders reversed
  • LIRC Byte 2 is 0xFF – LIRC Byte 1
  • LIRC Byte 3 is YN Byte 2 with nibbles swapped, and nibble bit orders reversed
  • LIRC Byte 4 is 0xFF – LIRC Byte 3

For the 2-4 YN 24bit codes (xx-xxxx):

  • LIRC Byte 1 is YN Byte 1 with nibbles swapped, and nibble bit orders reversed
  • LIRC Byte 2 is 0xFF – LIRC Byte 1
  • LIRC Byte 3 is YN Byte 2 with nibbles swapped, and nibble bit orders reversed
  • LIRC Byte 4 is YN Byte 3 with nibbles swapped, and nibble bit orders reversed

For the 4-2 YN 24bit codes (xxxx-xx):

  • LIRC Byte 1 is YN Byte 1 with nibbles swapped, and nibble bit orders reversed
  • LIRC Byte 2 is YN Byte 2 with nibbles swapped, and nibble bit orders reversed
  • LIRC Byte 3 is YN Byte 3 with nibbles swapped, and nibble bit orders reversed
  • LIRC Byte 4 is 0xFF – LIRC Byte 3

For the YN 32bit codes (xxxx-xxxx):

  • LIRC Byte 1 is YN Byte 1 with nibbles swapped, and nibble bit orders reversed
  • LIRC Byte 2 is YN Byte 2 with nibbles swapped, and nibble bit orders reversed
  • LIRC Byte 3 is YN Byte 3 with nibbles swapped, and nibble bit orders reversed
  • LIRC Byte 3 is YN Byte 4 with nibbles swapped, and nibble bit orders reversed

Unfortunately the post is a jpeg scan of a service manual, so I had to enter the codes manually. After a lot of typing, here is the resulting CSV file. To the end of the file I added some extra codes I’d found from my testing.

With the translation figured out, and the codes entered, it was a simple matter to dodgy up some python to generate LIRC codes from the Yamaha/NEC codes.

The program generates a separate LIRC “remote” for each of the zones supported by the chosen receiver, plus an ALL “remote” for codes that don’t apply to specific zone.

Invoking the script is done as follows:

python yamahanec2lirc.py <infile> <device> <product> <id_code> > <output_file>

where:

  • infile is the CSV file containing the Yamaha/NEC codes
  • device is used to filter the codes for a specific system. Most codes apply to RECEIVER
  • product is the receiver to filter the codes for. Valid options are 667, 767, 867, 1067, 2067, 3067
  • id_code is the code set to generate (either 1 or 2). The default is 1. The receiver can be configured to accept either the ID1 or ID2 code set, which would allow 2 receivers to work alongside each other without interference.

The generated remote definitions are printed to stdout, and it’s a simple matter to pipe them into a file. For example:

python yamahanec2lirc.py yamaha_rxv.csv RECEIVER 767 1 > yamaha_rxv767.lircd

The resulting output file can be seen here. This is then included into the lircd configuration file (usually /etc/lirc/lircd.conf):

include "/home/nobbin/yamaha_rxv767.lircd"

After restarting lircd, you can use irsend to send these codes to your receiver:

irsend SEND_ONCE RECEIVER_767_MAIN POWER_POWER_ON

Enjoy…

Notes:

The codes have been tested for the RX-V767. The other supported receivers are the RX-V667, RX-V867, RX-V1067, RX-V2067, RX-V3067. However as I don’t have access to any of these, I haven’t tested them.

The ID2 codes haven’t been tested either.

The last column (Export Comment) in the CSV file allows comments to be added to the generated LIRC config file, any text here will appear as a LIRC comment on the line preceding the remote code. If the “export comment” column entry is prefixed with “#”, then the actual remote code will be commented out in the LIRC config file. This allows potentially dangerous codes, like the “self test mode” code, to be commented out, so they can’t be sent accidentally.

The python script contains functions to convert from lirc format into Yamaha/NEC format. Checkout the source if that interests you.

htmi2serial_smallWARNING: The following is dodgy, and if you try it and blow up your receiver, HDMI port, or whatever, you should remember that the internetz are full of dodgy advice, and don’t come crying.

I’m looking to automate turning on my HTPC, AV receiver and TV. The current setup involves three remotes and, while it works, is rather less than ideal. There are a great many buttons, most of which I’ve never used.  I’ll explain the master plan in another post, but the gist of it is to use LIRC and a Microsoft MCE IR blaster to send IR codes to the TV and receiver.

Anyway, the first step is to capture all the keys from the remote into a form LIRC using irrecord. This utility makes it all quite simple and generates a LIRC config file for the particular remote.

However, the remotes I have only have a toggle button for switching power on to the TV and AV receiver. Ie sending the IR code once turns on the device, sending it again turns off the device. This presents a problem when automating stuff. Without feedback, it’s not possible to know if sending the toggle code turned the device on or off. If something (temporarily) obstructs the IR beam, then you could end up with a situation of turning the TV off and turning the receiver on, and so on.

Luckily most (some) TVs and receivers support IR codes to “power on” and to “power off”. These are called discrete codes. Sending the “power on” code multiple times has no effect once the device has powered up. I went digging around on the internetz and turned up this. It was then a simple matter of running the relavent codes through pronto2lirc then irrecord -a and I had a working LIRC configuration for my TV (Panasonic Viera).

My Yamaha receiver proved to be not quite so simple. Yamaha don’t seem quite so forthcoming with their IR codes. Never the less, internet peeps have published some Yamaha codes. However the discrete power on and power off codes I found turned on both zones of my receiver, which I didn’t really want.

So I thought I’ll just hack up some python to run through a list of IR codes and blat them at the receiver. Eventually one will turn it on, and I’ll have found it. However 16bits corresponds to 65536 possible codes, and at one per second that’s going to take 18ish hours, and I’d get a bit bored sitting in front of the receiver for that long.

If only there was a way to signal to the PC that the receiver has powered up. Looking on the back of the reciever there was roughly 1 million connectors as is the way with receivers, including some fancy Yamaha to iProduct connector.

The HDMI out connector attracted my attention. HDMI has a 5v line that gets energised when the receiver powers up (pinout here). Now all I needed was  a way to monitor it from the PC. A serial port seemed like the simplest solution. The RS232 specification says that +3v to +15v is a logic 0, and -3v to -15v is a logic 1, and -3v to 3v as undefined, but in reality most RS232 receivers return 0v as logic 1 (dodgy I know). By cutting the end off a cheap HDMI cable and wiring the HDMI +5v (pin 18) to the RS232 CTS line (DB9 pin 8), and HDMI ground (pin 17) to the RS232 ground line (DB9 pin 5), I’d made myself a wonderful new HDMI to RS232 cable.

Rather than risk blowing my receiver up, I tested the cable on a cheap video card. Realterm (Windows) or statserial (Linux) are handy utilities for checking line states.

Once I was satisfied that the cable was working, and the video card hadn’t blown up, it was time to go IR code hunting.

The first step was to generate an lircd remote configuration file containing all 65536 IR codes for the range I wanted to test. There were 3 ranges that the codes captured from irrecord appeared in: 0x5EA10000, 0x7E810000, and 0xFE800000. So it was necessary to repeat the process below 3 times (once for each offset).

First set the offset (high order 16bits) in makeir.py:

offset=0x5EA10000

Then generate the 65536 codes for that range:

python makeir.py > /home/nobbin/InfraRed/testcodes_5ea1.lircd

Next, tell lircd about this remote in its configuration file (usually /etc/lirc/lircd.conf):

include "/home/nobbin/InfraRed/testcodes_5ea1.lircd"

And then send each IR code via the blaster to the receiver (see sendir.py):

python sendir.py 0000 10000 /dev/ttyUSB0

If the receiver turns on, the script will halt, and I can note down the relavent IR code:

CTS change detected at TEST7E81

So what did I find? It turns out that any of the four “scene” keys will turn on the receiver, before switching to the appropriate input. Then I discovered two codes to enter the self test mode. Then finally I found the zone 2 and main zone power on codes.

In the 0x5EA10000 range:

  • TEST00FE corresponding to SCENE1 (BD/DVD) turned the receiver on, and switched to BD/DVD scene
  • TEST609E corresponding to SCENE3 (CD) turned the receiver on, and switched to CD scene
  • TEST906E corresponding to SCENE4 (RADIO) turned the receiver on, and switched to RADIO scene
  • TEST1B847 turned on all zones on the receiver
  • TESTC03E corresponding to SCENE2 (TV) turned the receiver on, and switched to TV scene
  • TEST1FB04 put the receiver into self test mode
  • TEST1FB84 put the receiver into self test mode

In the 0x7E810000 range:

  • TEST5DA2 turned on zone 2 of the receiver
  • TEST7E81 turned on the main zone of the receiver

This was what I was after, but now I needed the power off codes, and sending lots of codes to a powered up receiver could change any number of settings, so I needed a different approach. Luckily during the time spent waiting, I found the codes I was looking for, but in Yamaha/NEC format.

Note: It turns out the RX-V767 has a trigger output that outputs 12v when receiver turns on. This could be used instead of the HDMI 5v line.