I've seen many intelligent apartment concepts and technologies, including Microsoft super apartment located here in Prague. In fact all these concepts are nothing but pile of silicon crap collected in one apartment with 15 different remote controllers laying around. I believe that final solution has to be one remote controller for all devices. I also believe that all devices should be powered by .NET Micro Framework. This means there must be a way how to connect Infra Red receiver with .NET Micro Framework.


How does TV Remote works

TV Remotes in these days uses infra-red beam modulated on given frequency. Modulated signal can transfer information that represents command button and address of the target device. So, it's all about PWM modulation. Unfortunately, every electronics vendor is using different PWM format and communication protocol.

Luckily, most of the TV Remote controllers has something common. Every transfer starts with some starting sequence which is nothing else than "very" long pulse. Then two groups of bit's are transferred, first group represents command and second group represents address. The length of address field and command field is different for every brand. See SB Projects for more details on communication protocols.

Sony SIRC protocol
Figure 1. Sony SIRC data transfer

Sony SIRC protocol

Protocol of the Sony devices is very simple to decode and uses reasonably fast pulse length, which makes it easy to implement in .NET Micro Framework. See figure 1. for typical Sony data transmission. Start sequence takes 2.4ms and then the data bits follows. Logical 1 is represented by pulse of 1200us while logical 0 is 600us long. Standard Sony data message consist of 12 bits (7 bits for command, 5 bits for address).

Since commands are more or less same for all devices, address field is important to recognize the target. Most common Sony commands and addresses are in the table. For complete list go to: www.hifi-remote.com/sony

Device Address Command Function
TV 1 0 Key 1
VCR 2 1 Key 2
Cassete 14 2 Key 3
CD 17 3 Key 4
4 Key 5
5 Key 6
6 Key 7
7 Key 8
8 Key 9
9 Key 0
16 Channel Up
17 Channel Down
18 Volume Up
19 Volume Down

Connecting the IR Receiver with CPU

Key part is the infra red receiver. There are many infra red receivers on the market and it's price is about one dollar. It's important to buy IR receiver for the right frequency, most remote controllers operates on 38Khz. Even if Sony standard is 40Khz, surpsinigly 38Khz receiver works very well.

I've started with popular IR receiver SFH5110-38 but then drop it, because this receiver is very sensitive to input voltage. Even if it should operate from 4.5 to 5.5 volts, when voltage is not at least 5.2V sensor is very unstable. SFH5110-38 powered from USB operated Tahoe-I was unusable.

Then I went for TSOP4838 IR receiver and everything was fine. All these IR receivers works on the same principle and have same pin-out. The control pin is tight high until the signal of 38Khz frequency arrives. Then the pin is grounded and remains grounded till the signal is present. As a verification of the communication, LED is connected between power and control pin. As the signal is being transferred LED flashes.

Complete list of components:

  • 38Khz IR receiver TSOP4838 (or other)
  • Low current LED (2 mA)
  • Resistor before LED (~700 ohms)

Connection IR receiver
Figure 2. IR Receiver circuit

Using the SonyReceiver class

From the paragraph above is obvious that decoding TV Remote signal is nothing but measuring the pulses. Instead of writing class specifically for Sony TV Remotes, I've decided to create general "infrastructure" for future extensibility. All remote controllers are derived from TVRemoteReceiver abstract class, which triggers DataReceived event whenever the valid data are received.

abstract public class TVRemoteReceiver : IDisposable
{
    public Cpu.Pin ReceiverPin;
    public abstract void Dispose();
    public delegate void TVRemoteDataHandler(TVRemote sender, int command, int address);
    public event TVRemoteDataHandler DataReceived;
    protected virtual void OnDataReceived(int command, int address)
}

SonyReceiver class is just the filling for the interface above, which triggers the event when Sony data packet arrived. Usage of SonyReceiver is in the listing bellow.

public static void Main()
{
    TVRemoteReceiver sony = new SonyReceiver(Meridian.Pins.GPIO1);
    sony.DataReceived += new TVRemoteReceiver.TVRemoteDataHandler(sony_OnDataReceived);

    while (true)
    {
        Thread.Sleep(20);
    }
}

static void sony_OnDataReceived(TVRemote sender, int command, int address)
{
    Debug.Print("----");
    Debug.Print(address.ToString());
    Debug.Print(command.ToString());
}

TV Remote as the WPF input

To make things even better I've implemented TVRemoteInputProvider, which translates Remote Controller commands into WPF button events. This makes it perfect alternative method to standard GpioButtonInputProvider, because application can use as many InputProviders as developer needs.

Constructor of TVRemoteInputProvider takes four arguments. First agument is the presentation source, second argument is the TVRemoteReceiver driver, third argument is the target address of the device, passing -1 into 3rd argument makes input provider to ignore address field completely. In that case commands from all Sony remotes will be accepted (TV, VCR, Stereo etc.). Last argument is the button map, which binds TV Remote commands into WPF buttons.

Beside described constructor arguments, the TVRemoteInputProvider has one public property ButtonAction represented by the RawButtonActions value, which will be passed in the WPF event. It's obvious that ButtonUp and ButtonDown can't be recognized in the infra red data packet. By default ButtonAction is set to RawButtonActions.ButtonUp.

Following code snippet is taken from Tetris games controlled by TV Remote as seen on the video above. By the way, this was the only thing necessary to add into Tetris source at all!

SonyReceiver sonyRemote = new SonyReceiver(Meridian.Pins.GPIO1);

TVRemoteButtonPad[] buttons = new TVRemoteButtonPad[]
{
    new TVRemoteButtonPad(116, Button.VK_UP),
    new TVRemoteButtonPad(117, Button.VK_DOWN),
    new TVRemoteButtonPad(051, Button.VK_RIGHT),
    new TVRemoteButtonPad(052, Button.VK_LEFT),
    new TVRemoteButtonPad(101, Button.VK_RETURN),
};

// Create the object that configures the TV Remote commands to buttons.
TVRemoteInputProvider sonyProvider = new TVRemoteInputProvider(null, 
                                              sonyRemote, 
                                              (int)SonyReceiver.Devices.TV, 
                                              buttons);
                                              
sonyProvider.ButtonAction = RawButtonActions.ButtonDown;

// Create the object that configures the GPIO pins to buttons.
GPIOButtonInputProvider inputProvider = new GPIOButtonInputProvider(null);

Imagine how cool it would be, if IrDA Tetris will be connected with GHI VGA expansion board.

Conclusion

Infra red transfer is very interesting topic but to successfully implement it in .NET MF device several factors are necessary to consider. Most important fact is, that infra red light is part of other light sources as well, not only the IR diode of TV Remote. This means that day light or flickering light tube is possible source of noise for IR transfers. It's good to place IR receiver in the black box and put filter on the input side. Most TVs and other devices has IR receivers placed behind the dark red plastic filter.

Feel free to download my IrDA library and source codes: Bansky.SPOT.IrDA.zip [162 Kb]