Marko Mäkelä’s electronics projects: Wake on RC5

Background

I set up a VDR system with the DVB-T tuner Hauppauge Nova-T PCI 90002 that is shipped with a bundled infrared remote control unit.

The bundled remote control of the Hauppauge DVB-T tuner card generates Philips RC5 codes. The backplate of the card has a 2.5 mm stereo jack for connecting a infrared receiver module. The module has three contacts: power, ground and signal output (active low). Although the radio frequency amplifier for the pass-through antenna connector on the tuner card is always powered on, the infrared receiver module is not. Thus, an extra module will be needed in order to be able to power on the computer from the remote control.

Why power on the computer from the remote control?

First, the computer might be installed in a hard-to-reach place or in a different room to reduce noise.

Second, you might want to disable audio and video output and decoding when the computer is doing timed recordings. This requires the ability to distinguish the way how the computer has been powered on. As this information is not easily available from the motherboard, this module will try to provide the information. When the computer is started up by the remote control, the pass-through infrared output of this module will be held low until a button is pressed on the remote control unit. It is up to the software on the computer to detect this condition. Other than that, this module is completely independent of the firmware and software running on the computer.

Features

When the computer is powered on by remote control unit, the pass-through infrared output will be driven to logic 0 level until another key is pressed on the remote control unit. When the computer is powered on because of some other reason, such as timed recording (via nvram-wakeup) or a magic Wake-on-LAN Ethernet packet, the output will be driven to logic 1 level.

With some software modifications, the computer will know if it was powered up by remote control and, for instance, only start video and audio playback and power on the screen and speakers (by a solid state relay) if the system was started by remote control.

[Wake-on-RC5 module][Wake-on-RC5 cables]Hardware

Bill of Materials

Schematic Diagram

[WORC5 Schematic Diagram]The schematic diagram has been drawn with CadSoft EAGLE 4.11.

As the connectors have not been defined in the EAGLE library, there is no circuit board design. If you prefer to have a circuit board, you would probably want to attach it on the tuner card with a blob of hot glue or surface mount it with some blobs of solder. In this way, the wake-on-LAN cables do not need to be routed outside the computer case.

In-Circuit Programming

For in-circuit programming of the ATtiny12 firmware, you may want to build a cable with a stereo jack, a stereo plug, a DB-25P connector for an IBM PC style parallel port, and a 5-volt power supply, using some common layout. You will need to connect the RESET line with a separate wire between the DB-25P connector and the ATtiny12.

In the pictures above, you can see two alligator clips on the module. One is connected to the RESET line of the ATtiny12 microcontroller, needed for programming the firmware. The other clip is connected to the 5-volt power input from the tuner card. You should control this signal when testing the module. For testing purposes, you can connect a 5-volt power supply to the WoL out connector and short the green wake input signal of the WoL in connector to ground.

Hardware version 2

[WORC5 PCI Schematic Diagram][WORC5 PCI Circuit Board]The schematic diagram and the circuit board layout were designed with CadSoft EAGLE.

This simplified design features only one 2×5 pin header that is almost compatible with the Atmel ISP connector layout. Pin 10 is ground in the Atmel layout, but here it is wired to one of the I/O pins.

The schematic diagram says +5V, but the installed circuit really works with 3.3 volts. The ATtiny12 has a wide input voltage range.

The prototype was built on a larger circuit board that features two pin headers. I have some of those circuit boards left, in case someone is interested.

Firmware

I first wrote an interrupt-driven RC5 decoder for the ATmega103-driven STK300 evaluation board. Once I got it working, I ported it to the ATtiny12.

rc5-mega103.s
Interrupt-driven RC5 decoder for the Atmel STK300 evaluation board
worc5.s
Source code of the WORC5 firmware, available under the GNU General Public License (GPL). Please read the comments in the beginning of the source file. Search for Power key in order to adapt the expected RC5 code value of the key. It is hard-coded at system=11110 and command=111101.
worc5-1.hex
Compiled binary of the firmware for circuit version 1 (external installation, with WoL pass-through)
worc5-2.hex
Compiled binary of the firmware for circuit version 2 (internal installation, with PCI PME# signal)

When the computer is started up by the remote control, the WORC5 firmware will hold the pass-through infrared output low until a button is pressed on the remote control unit (more precisely, until ten seconds have passed and a pulse arrives from the infrared receiver module). At that point, it will switch to pulse repeat mode.

I programmed the firmware using a program of my own production, CISP. It should work at least on GNU/Linux, FreeBSD and Win32 systems.

To do

Modifications to Linux

This is a quick hack and proof-of-concept. A proper way would be to implement some ioctl(2) interface for this in video4linux.

First, I modified the cx88 driver to display the status of infrared line (connected to GPIO[16] on the CX23882) when the driver is loaded.

--- linux-2.6.11.6/drivers/media/video/cx88/cx88-video.c	2005-04-04 22:28:29.000000000 +0300
+++ cx88-video.c	2005-07-23 14:08:10.000000000 +0300
@@ -2116,6 +2116,7 @@
 	down(&dev->lock);
 	init_controls(dev);
 	cx88_set_tvnorm(dev->core,tvnorms);
+printk(KERN_INFO "%s: suspended=%d\n", core->name, cx_read(MO_GP2_IO) & 1);
 	video_mux(dev,0);
 	up(&dev->lock);
 

My runvdr script for the vdr-suspend patch examines dmesg output to determine if playback should be suspended, i.e., the computer was started by something else than the remote control unit. The script then passes the appropriate --suspend parameter to the patched vdr. My vdr-shutdown script is pretty standard.

See also my RS-232 solid state relay that powers the display on and off based on whether the playback has been suspended.

Originally, I used the register MO_SAMPLE_IO, which is a 32-bit shift register that can be programmed to collect samples from the I/O line connected to the infrared receiver module. However, the register can read 0, even if the infrared line is in the logic 1 state. I suspect that either the shift register has not been started or it has not been running long enough at the point the register was sampled.

It would be better to take 32 samples with MO_SAMPLE_IO instead of one sample with MO_GP2_IO, because the infrared sensor can report random pulses due to stray light and thus deliver wrong results when the WORC5 module is not connected. This could probably be implemented by adding a static variable to the interrupt handler in cx88-input.c. While doing it, one could as well implement an ioctl(2) interface for querying the status of the input.

[Modifications on the solder side][Modifications on the component side]Modifying the Hauppauge Nova-T PCI 90002

The hardware version 2 is a small circuit board that can be installed to the Hauppauge tuner card inside the computer. The modifications for the Hauppauge Nova-T PCI 90002 are indicated in the nearby pictures. Note that I take no responsibility for these instructions. You’d better double-check all signals using a continuity tester on a disconnected circuit board and a voltage meter on a running system.

On the solder side of the Hauppauge Nova-T PCI 90002, the wake-up signal PME# is not connected. It is PCI signal A19, the edge contact that is marked green in the nearby picture. I soldered a thin wire on it and routed it through the hole of TP26.

On the component side, the power supply of the infrared receiver module is routed through R47 near the PCI connector, marked with a red X on the bottom right of the nearby picture. Remove it. The bottom contact of R47 is at +5V, and the top contact should be wired to +3.3Vaux, which is available at PCI bus signal A14 or the red LED that is lit when the computer is switched on or in standby mode. You can remove the LED if you like. Connect +3.3Vaux (and ground) also to the power supply of the daughter board.

To the left of R47, the demodulated infrared signal is routed through FB7. Remove it. The left-hand-side should be connected to IR_IN# and the right-hand-side to IR_OUT# of the daughter board.

One more signal needs to be connected to the daughter board: VCC_IN, a power supply that lets the WORC5 module know if the computer is powered on. (The signals STATUS and RESET# on the pin header are only for in-circuit programming.)

Initially, I wired the VCC_IN signal of the daughter board to a 3.3-volt power supply that was conveniently found at a small chip, U8. However, for some reason this supply delivered 130 mA at 1.2 V when the computer was in ACPI S5 standby mode, which the ATtiny12 could not tell apart from 3.3 volts. I do not know which is to blame for this apparent leakage current: the power supply unit, the motherboard or one of the PCI cards.

Luckily, the +5V supply at R47 is at only 0.5 volts when my computer is in standby mode. Obviously, the 5-volt supply cannot be fed directly to a component running at 3.3 volts. We can halve the voltage with a simple resistor divider circuit. Connect two resistors of the same value (preferrably tens of kilo-ohms; I used 17 kΩ) in series between the ground and the +5V supply at R47. Between the resistors, there will be 2.5 V when the computer is switched on, and 0.25 V when it is in standby mode. These reside well within the defined logic voltage ranges for 1 and 0 when the daughter board is running at 3.3 V.

For installing the resistors, there is place for a connector J6 near the back plate of the card, marked green in the picture. The center left hole is at ground, and the center right hole is not connected to anything. (You should verify that its resistance against ground and any power supply is infinite.)

Note that the bundled Hauppauge infrared receiver does not work at 3.3 volts. You will probably want to replace it with a better component; read on.

[The Hauppauge IR receiver
and Everlight IRM3638N3]Improving the reception of the Hauppauge remote control unit

The range of the remote control unit bundled with the Hauppauge Nova-T PCI 90002 is miserably short. This is most likely due to the fact that the bundled infrared receiver is fed with a power supply of slightly under 5 volts, while its output is connected to an input that expects 3.3 volt logic. I rerouted the power supply of the infrared receiver to 3.3 volts (please consult the section on modifying the PCI card) and replaced the module with an Everlight IRM-3638N3. Any receiver module with around 38 kHz bandpass frequency and 3.3 volt power supply should be fine.

[The back side of the receiver][The front side of the receiver]As the data sheet suggests, a small RC filter was added to the power supply pins. The 49.9 Ω resistor is the R47 that was removed from the Hauppauge card, and the capacitor was recycled from a broken circuit board.

The data sheet promises a range of 14 meters, which is not far from the truth. Now the remote control unit works anywhere in the visible range, and thanks to a longer cable, the receiver could be mounted near the ceiling to improve visibility.

Related Work

Before implementing this solution, I had a look of Mark Hämmerling’s Wake-on-LIRC project.

The Wake-on-LIRC circuit is based on the ATtiny12 like mine, but the RC5 decoder has been copied verbatim from the manufacturer’s application notes, more precisely AVR410: RC5 IR Remote Control Receiver. The Wake-on-LIRC circuit has one benefit over WORC5: the power-on code can be taught to the microcontroller without reprogramming the firmware. On the other hand, the Wake-on-LIRC hardware does not allow in-circuit programming of the firmware, like the WORC5 does.

The decoder implementation listed in AVR410 polls the infrared input instead of exploiting the external interrupt triggers available in most AVR devices. I managed to do without a virtual timer as well: in my implementation, the timer overflow interrupt is just a watchdog that resets the decoder when an overly long pulse arrives. I believe that thanks to the sleep mode my implementation activates, the microcontroller uses about a quarter of the power it would consume with AVR410.