ArduinoLibs
IRreceiver.cpp
00001 /*
00002  * Copyright (C) 2012 Southern Storm Software, Pty Ltd.
00003  *
00004  * Permission is hereby granted, free of charge, to any person obtaining a
00005  * copy of this software and associated documentation files (the "Software"),
00006  * to deal in the Software without restriction, including without limitation
00007  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
00008  * and/or sell copies of the Software, and to permit persons to whom the
00009  * Software is furnished to do so, subject to the following conditions:
00010  *
00011  * The above copyright notice and this permission notice shall be included
00012  * in all copies or substantial portions of the Software.
00013  *
00014  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
00015  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
00016  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
00017  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
00018  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
00019  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
00020  * DEALINGS IN THE SOFTWARE.
00021  */
00022 
00023 #include "IRreceiver.h"
00024 #if defined(ARDUINO) && ARDUINO >= 100
00025 #include <Arduino.h>
00026 #else
00027 #include <WProgram.h>
00028 #endif
00029 
00159 static IRreceiver *receiver = 0;
00160 
00161 void _IR_receive_interrupt(void)
00162 {
00163     receiver->handleInterrupt();
00164 }
00165 
00176 IRreceiver::IRreceiver(int interruptNumber)
00177     : _system(0)
00178     , _systemFilter(-1)
00179     , started(false)
00180     , halfChange(false)
00181     , lastChange(0)
00182     , bits(0)
00183     , bitCount(0)
00184     , buffer(0)
00185     , lastBuffer(0)
00186 {
00187     switch (interruptNumber) {
00188     case 0: default:    pin = 2; break;
00189     case 1:             pin = 3; break;
00190     case 2:             pin = 21; break;    // Arduino Mega only
00191     case 3:             pin = 20; break;    // Arduino Mega only
00192     case 4:             pin = 19; break;    // Arduino Mega only
00193     case 5:             pin = 18; break;    // Arduino Mega only
00194     }
00195     receiver = this;
00196     attachInterrupt(interruptNumber, _IR_receive_interrupt, CHANGE);
00197 }
00198 
00220 int IRreceiver::command()
00221 {
00222     unsigned buf;
00223 
00224     // Read the last-delivered sequence from the buffer and clear it.
00225     cli();
00226     buf = buffer;
00227     buffer = 0;
00228     sei();
00229 
00230     // Bail out if no sequence or it is not for us.
00231     if (!buf) {
00232         _system = -1;
00233         return -1;
00234     }
00235     if (_systemFilter != -1) {
00236         if (((buf >> 6) & 0x1F) != _systemFilter) {
00237             _system = -1;
00238             return -1;
00239         }
00240     }
00241 
00242     // Extract the command.
00243     int cmd = buf & 0x3F;
00244     if ((buf & 0x1000) == 0)
00245         cmd += 64;
00246 
00247     // Is this a new command or an auto-repeat of the previous command?
00248     // Bit 11 will toggle whenever a new button press is started.
00249     if (lastBuffer == buf)
00250         cmd += AUTO_REPEAT;
00251     else
00252         lastBuffer = buf;
00253     _system = (buf >> 6) & 0x1F;
00254     return cmd;
00255 }
00256 
00304 // Number of microseconds that the signal is HIGH or LOW for
00305 // indicating a bit.  A 1 bit is transmitted as LOW for 889us
00306 // followed by HIGH for 889us.  A 0 bit is HIGH, then LOW.
00307 #define IR_BIT_TIME 889
00308 
00309 // Number of microseconds to detect a long gap in the coding
00310 // corresponding to 2 time units HIGH or LOW.  We actually check
00311 // for at least 1.5 time units to allow for slight variations
00312 // in timing on different remote controls.
00313 #define IR_LONG_BIT_TIME (889 * 6 / 4)
00314 
00315 // Maximum timeout for a single bit.  If we don't see a rising edge
00316 // within this time, then we have lost sync and need to restart.
00317 #define IR_MAX_TIME (IR_BIT_TIME * 4)
00318 
00319 // Protocol details from http://en.wikipedia.org/wiki/RC-5
00320 void IRreceiver::handleInterrupt()
00321 {
00322     bool value = digitalRead(pin);
00323     unsigned long currentTime = micros();
00324     if (!value) {
00325         // Rising edge (input is active-LOW)
00326         if (started && (currentTime - lastChange) > IR_MAX_TIME) {
00327             // Too long since the last received bit, so restart the process.
00328             started = false;
00329         }
00330         if (started) {
00331             // We recognize bits on the falling edges, so merely
00332             // adjust the "changed at last half-cycle" flag.
00333             if ((currentTime - lastChange) > IR_LONG_BIT_TIME) {
00334                 // Long time since last falling edge indicates that the
00335                 // next bit will definitely be a 1.
00336                 halfChange = true;
00337             } else {
00338                 halfChange = !halfChange;
00339             }
00340             lastChange = currentTime;
00341         } else {
00342             // Encountered the start bit - start receiving up to 14 bits.
00343             lastChange = currentTime;
00344             started = true;
00345             halfChange = true;
00346             bits = 0;
00347             bitCount = 14;
00348         }
00349     } else if (started) {
00350         // Falling edge
00351         if ((currentTime - lastChange) > IR_LONG_BIT_TIME) {
00352             // Long time since last rise indicates 1 followed by 0.
00353             bits = (bits << 2) | 0x02;
00354             --bitCount;
00355             halfChange = true;
00356         } else if (halfChange) {
00357             // Rise was halfway through, so falling edge indicates a 1.
00358             bits = (bits << 1) | 0x01;
00359             halfChange = false;
00360         } else {
00361             // Rise was at the start, so falling edge indicates a 0.
00362             bits <<= 1;
00363             halfChange = true;
00364         }
00365         lastChange = currentTime;
00366         --bitCount;
00367         if (bitCount <= 0) {
00368             // All 14 bits have been received, so deliver the value.
00369             started = false;
00370             buffer = bits;
00371         }
00372     }
00373 }
 All Classes Files Functions Variables Typedefs Enumerations Enumerator