ArduinoLibs
|
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 }