Netduino home hardware projects downloads community

Jump to content


The Netduino forums have been replaced by new forums at community.wildernesslabs.co. This site has been preserved for archival purposes only and the ability to make new accounts or posts has been turned off.

Bondolon

Member Since 18 May 2011
Offline Last Active Mar 02 2012 12:35 AM
-----

Posts I've Made

In Topic: NEC Protocol IR Decoder

28 February 2012 - 05:22 AM

Awesome post darko. I had a remote that implemented this protocol and one of the 38kHz IR receivers from Radio Shack (276-640), and used your code to help decode it. That said, I noticed that I was getting a number of incorrect values (the most common being that the number was shifted two bits too many to the left, though I was getting some just random outliers), and revamped the code a little to clean up the integrity of the received signals. I only know that it works with the Apple Remote (the only one I have on hand that implements this protocol), though I saw the same 9000->4500 control sequence on a completely different remote--a JP1.3 from SuddenLink. Either way, the modifications below have a bit more overhead in terms of memory, but they seemed to constrain the values very closely to what I was expecting (e.g. my first test with them replaced the OnIrCommandReceived call with a debug block for breaking when >50 valid values had been retrieved, and it stopped after exactly 51 button clicks).

namespace NecDecoder
{
    class NecProtocolDecoder
    {
        public event IRCommandEventHandler OnIRCommandReceived;

        private Timer _timeout;
        private InterruptPort _input;

        private long[] _pulses;
        private int _currentIndex;

        public NecProtocolDecoder(Cpu.Pin irReceiverPin)
        {
            _timeout = new Timer(new TimerCallback(PulseTimedOut), null, Timeout.Infinite, Timeout.Infinite);

            _input = new InterruptPort(irReceiverPin, false, Port.ResistorMode.Disabled, Port.InterruptMode.InterruptEdgeBoth);
            _input.OnInterrupt += new NativeEventHandler(OnInterrupt);

            _pulses = new long[200];
            _currentIndex = 0;
       }

        private void OnInterrupt(uint data1, uint data2, DateTime time)
        {
            if (_currentIndex >= 200)
            {
                _currentIndex = 0;
            }

            _pulses[_currentIndex++] = time.Ticks;

            _timeout.Change(10, Timeout.Infinite);
        }

        private void PulseTimedOut(object state)
        {
            const long toMicrosecondsDivisor = TimeSpan.TicksPerMillisecond / 1000;

            var firstValue = _pulses[0] / toMicrosecondsDivisor;
            var lastValue = firstValue;

            for (int i = 1; i < _currentIndex; i++)
            {
                var currentValue = _pulses[i] / toMicrosecondsDivisor;
                _pulses[i - 1] = currentValue - lastValue;
                lastValue = currentValue;
            }

            uint result = 0;

            int controlIndex = 0;
            int collectedLength = 0;
            bool isCollecting = false;

            for (int i = 0; i < _currentIndex; i++)
            {
                if (!isCollecting && (IsInRange(_pulses[i], 9000, 200) && IsInRange(_pulses[i + 1], 4500, 200)))
                {
                    controlIndex = i;
                    i = i + 2;
                    isCollecting = true;
                }
                else if (isCollecting && collectedLength < 32)
                {
                    if ((i - controlIndex) % 2 == 1)
                    {
                        result <<= 1;
                        collectedLength++;

                        if (IsInRange(_pulses[i], 1690, 200))
                        {
                            result |= 1;
                        }
                    }
                }
            }

            _currentIndex = 0;

            if (OnIRCommandReceived != null)
            {
                OnIRCommandReceived(result);
            }
        }

        private static bool IsInRange(long pulse, long expected, long tolerance)
        {
            return (expected + tolerance > pulse && expected - tolerance < pulse);
        }
    }

    public delegate void IRCommandEventHandler(uint command);
}

home    hardware    projects    downloads    community    where to buy    contact Copyright © 2016 Wilderness Labs Inc.  |  Legal   |   CC BY-SA
This webpage is licensed under a Creative Commons Attribution-ShareAlike License.