Infrared TV remote control (RC5 type)

The exemplary driver GHI Infrared receiver I have adapted to use a TV remote control (RC5 type).
It has been tested with the Panda II

The main code


using System;
using System.Threading;
using Microsoft.SPOT;
using Microsoft.SPOT.Hardware;
using GHIElectronics.NETMF.FEZ;

namespace RC5
{
    public class Program
    {
        public static void Main()
        {
            new Thread(() => flashOnboardLed(200)).Start();
            FEZ_Components.EasyRemote myRemote = new FEZ_Components.EasyRemote(FEZ_Pin.Interrupt.An1);
            myRemote.ButtonPressEvent += new FEZ_Components.EasyRemote.ButtonPressEventHandler(myRemote_ButtonPressEvent);
            Debug.Print("FEZ has nothing to do but waiting to receive the Easy Remote IR signal on the IRM Component");
            Thread.Sleep(Timeout.Infinite);
        }

        static void myRemote_ButtonPressEvent(uint btn, bool new_press)
        {
            if (new_press) // we want to ensure that the button is newly pressed (not a continuous pressing on the button).
                Debug.Print("Button pressed: " + btn.ToString());
//          else
//              Debug.Print("Button continuous pressing: " + btn.ToString());
        }

        public static void flashOnboardLed(object flashTime)
        {
            OutputPort led = new OutputPort((Cpu.Pin)FEZ_Pin.Digital.LED, false);
            while (true)
            {
                led.Write(!led.Read());
                Thread.Sleep((int)flashTime);
            }
        }
    }
}

The EasyRemote code


/*
Copyright 2010 GHI Electronics LLC
Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.
*/

using System;
using Microsoft.SPOT;
using Microsoft.SPOT.Hardware;

namespace GHIElectronics.NETMF.FEZ
{
    public static partial class FEZ_Components
    {
        public class EasyRemote : IDisposable
        {
            InterruptPort IRM;
            long last_tick;
            long bit_time;
            uint pattern;
            bool streaming;
            uint shiftBit;
            uint toggle;
//          const int half_bittime = 8890;  // = 889 us

            public uint Button;

            public void Dispose()
            {
                IRM.Dispose();
            }

            public EasyRemote(FEZ_Pin.Interrupt pin)
            {
                IRM = new InterruptPort((Cpu.Pin)pin, false, Port.ResistorMode.Disabled, Port.InterruptMode.InterruptEdgeBoth);
                IRM.OnInterrupt += new NativeEventHandler(IRM_OnInterrupt);
                last_tick = DateTime.Now.Ticks;
            }

            public delegate void ButtonPressEventHandler(uint button, bool new_press);
            public event ButtonPressEventHandler ButtonPressEvent = delegate { };

            void IRM_OnInterrupt(uint port, uint state, DateTime time)
            {
                bit_time = time.Ticks - last_tick;
                last_tick = time.Ticks;
                if (bit_time > 240000)
                {
                    bit_time = 0;
                    pattern = 0;
                    if (state == 0)
                    {
                        streaming = true;
                        shiftBit = 1;
                        pattern |= shiftBit;
                    }
                    else
                        streaming = false;
                    return;
                }

                if (streaming)
                {
                    if (bit_time > 10668)  // = half_bittime * 1.2
                    {
                        if (state == 0)
                            shiftBit = 1;
                        else
                            shiftBit = 0;
                        pattern <<= 1;
                        pattern |= shiftBit;
                    }
                    else
                    {
                        if (state == 0)
                        {
                            pattern <<= 1;
                            pattern |= shiftBit;
                        }
                    }

                    if ((pattern & 0x2000) > 0)  // 14 bits
                    {
                        uint T = (pattern >> 11) & 0x01; 
                        uint S = (pattern >> 6) & 0x1F;
                        uint C = pattern & 0x3F;
                        bool N;
                        if (T != toggle)
                        {
                            toggle = T;
                            N = true;
                        } 
                        else
                        {
                            N = false;
                        }
//                      Debug.Print("T=" + T.ToString() + " S=" + S.ToString() + " C=" + C.ToString());
                        ButtonPressEvent(C, N);
                        pattern = 0;
                        bit_time = 0;
//                      streaming = false;
                    }
                }
            }
        }
    }
}

Thanks, Hinnie.
Yesterday I thought it would be cool to add remote to my project and today You post this. Now thats a coinsidence :o

The website [url]SB Projects the general IR theory described. I use the RC5 protocol is explained there as well (but also other protocols accessible via the sidebar).
If there are participants on this forum are in need of another protocol, then I have to cooperate together to build a universal IR driver.
Apart from a possible extension, I would welcome comments to improve the quality of the driver.

Put it on http://code.tinyclr.com please.

[Completely off-topic sorry]
Hinnie, your avatar here, is it from a stamp you had made, or just an image ?
Looks a lot like mine, although mine is from a stamp, would be a cool coincidence
[sorry for the off-topic]

[quote][Completely off-topic sorry]
Hinnie, your avatar here, is it from a stamp you had made, or just an image ?
Looks a lot like mine, although mine is from a stamp, would be a cool coincidence
[sorry for the off-topic][/quote]
Five years ago I made ​​a trip to China and as a jade stamp with my name purchased. Previously in China instead of a signature stamp. My avatar is a stamp.

In general, I would like to see general and simple usage surface. Something like below.
Remote side just have Send api to send cmd array. The receiver basically just has an event that gets called when new cmds come in. User code, then just needs to act on codes. Maybe your already doing this?

public class IRRemote
{
public void Send(byte[] codes) { }
}

public class IRReceiver
{
public delegate void ReceivedDelegate(byte[] codes);
public event ReceivedDelegate Received;
}

public static void TestIR()
{
// Send
IRRemote remote = new IRRemote();
remote.Send(new byte[]{1,2,3,4});

// Receiver.
IRReceiver rec = new IRReceiver();
rec.Received += new IRReceiver.ReceivedDelegate((byte[] ba) =>
{
    Debug.Print("Received cmd. Do something here.");
});

}

@ William I incorporated your recommendations and the driver testing program TinyCLR CODE placed under the name "Driver - TV REMOTE (RC5) FOR DRIVING A FEZ (PANDA).

A video is now added