Infrared remote library for Arduino: send and receive infrared signals with multiple protocols Port from Arduino-IRremote https://github.com/z3t0/Arduino-IRremote
irRecv.cpp@0:70c8e56bac45, 2016-01-23 (annotated)
- Committer:
- yuhki50
- Date:
- Sat Jan 23 06:16:48 2016 +0000
- Revision:
- 0:70c8e56bac45
- Child:
- 3:17440cf7ab90
import https://github.com/z3t0/Arduino-IRremote e3ec11d
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
yuhki50 | 0:70c8e56bac45 | 1 | #include "IRremote.h" |
yuhki50 | 0:70c8e56bac45 | 2 | #include "IRremoteInt.h" |
yuhki50 | 0:70c8e56bac45 | 3 | |
yuhki50 | 0:70c8e56bac45 | 4 | //+============================================================================= |
yuhki50 | 0:70c8e56bac45 | 5 | // Decodes the received IR message |
yuhki50 | 0:70c8e56bac45 | 6 | // Returns 0 if no data ready, 1 if data ready. |
yuhki50 | 0:70c8e56bac45 | 7 | // Results of decoding are stored in results |
yuhki50 | 0:70c8e56bac45 | 8 | // |
yuhki50 | 0:70c8e56bac45 | 9 | int IRrecv::decode (decode_results *results) |
yuhki50 | 0:70c8e56bac45 | 10 | { |
yuhki50 | 0:70c8e56bac45 | 11 | results->rawbuf = irparams.rawbuf; |
yuhki50 | 0:70c8e56bac45 | 12 | results->rawlen = irparams.rawlen; |
yuhki50 | 0:70c8e56bac45 | 13 | |
yuhki50 | 0:70c8e56bac45 | 14 | results->overflow = irparams.overflow; |
yuhki50 | 0:70c8e56bac45 | 15 | |
yuhki50 | 0:70c8e56bac45 | 16 | if (irparams.rcvstate != STATE_STOP) return false ; |
yuhki50 | 0:70c8e56bac45 | 17 | |
yuhki50 | 0:70c8e56bac45 | 18 | #if DECODE_NEC |
yuhki50 | 0:70c8e56bac45 | 19 | DBG_PRINTLN("Attempting NEC decode"); |
yuhki50 | 0:70c8e56bac45 | 20 | if (decodeNEC(results)) return true ; |
yuhki50 | 0:70c8e56bac45 | 21 | #endif |
yuhki50 | 0:70c8e56bac45 | 22 | |
yuhki50 | 0:70c8e56bac45 | 23 | #if DECODE_SONY |
yuhki50 | 0:70c8e56bac45 | 24 | DBG_PRINTLN("Attempting Sony decode"); |
yuhki50 | 0:70c8e56bac45 | 25 | if (decodeSony(results)) return true ; |
yuhki50 | 0:70c8e56bac45 | 26 | #endif |
yuhki50 | 0:70c8e56bac45 | 27 | |
yuhki50 | 0:70c8e56bac45 | 28 | #if DECODE_SANYO |
yuhki50 | 0:70c8e56bac45 | 29 | DBG_PRINTLN("Attempting Sanyo decode"); |
yuhki50 | 0:70c8e56bac45 | 30 | if (decodeSanyo(results)) return true ; |
yuhki50 | 0:70c8e56bac45 | 31 | #endif |
yuhki50 | 0:70c8e56bac45 | 32 | |
yuhki50 | 0:70c8e56bac45 | 33 | #if DECODE_MITSUBISHI |
yuhki50 | 0:70c8e56bac45 | 34 | DBG_PRINTLN("Attempting Mitsubishi decode"); |
yuhki50 | 0:70c8e56bac45 | 35 | if (decodeMitsubishi(results)) return true ; |
yuhki50 | 0:70c8e56bac45 | 36 | #endif |
yuhki50 | 0:70c8e56bac45 | 37 | |
yuhki50 | 0:70c8e56bac45 | 38 | #if DECODE_RC5 |
yuhki50 | 0:70c8e56bac45 | 39 | DBG_PRINTLN("Attempting RC5 decode"); |
yuhki50 | 0:70c8e56bac45 | 40 | if (decodeRC5(results)) return true ; |
yuhki50 | 0:70c8e56bac45 | 41 | #endif |
yuhki50 | 0:70c8e56bac45 | 42 | |
yuhki50 | 0:70c8e56bac45 | 43 | #if DECODE_RC6 |
yuhki50 | 0:70c8e56bac45 | 44 | DBG_PRINTLN("Attempting RC6 decode"); |
yuhki50 | 0:70c8e56bac45 | 45 | if (decodeRC6(results)) return true ; |
yuhki50 | 0:70c8e56bac45 | 46 | #endif |
yuhki50 | 0:70c8e56bac45 | 47 | |
yuhki50 | 0:70c8e56bac45 | 48 | #if DECODE_PANASONIC |
yuhki50 | 0:70c8e56bac45 | 49 | DBG_PRINTLN("Attempting Panasonic decode"); |
yuhki50 | 0:70c8e56bac45 | 50 | if (decodePanasonic(results)) return true ; |
yuhki50 | 0:70c8e56bac45 | 51 | #endif |
yuhki50 | 0:70c8e56bac45 | 52 | |
yuhki50 | 0:70c8e56bac45 | 53 | #if DECODE_LG |
yuhki50 | 0:70c8e56bac45 | 54 | DBG_PRINTLN("Attempting LG decode"); |
yuhki50 | 0:70c8e56bac45 | 55 | if (decodeLG(results)) return true ; |
yuhki50 | 0:70c8e56bac45 | 56 | #endif |
yuhki50 | 0:70c8e56bac45 | 57 | |
yuhki50 | 0:70c8e56bac45 | 58 | #if DECODE_JVC |
yuhki50 | 0:70c8e56bac45 | 59 | DBG_PRINTLN("Attempting JVC decode"); |
yuhki50 | 0:70c8e56bac45 | 60 | if (decodeJVC(results)) return true ; |
yuhki50 | 0:70c8e56bac45 | 61 | #endif |
yuhki50 | 0:70c8e56bac45 | 62 | |
yuhki50 | 0:70c8e56bac45 | 63 | #if DECODE_SAMSUNG |
yuhki50 | 0:70c8e56bac45 | 64 | DBG_PRINTLN("Attempting SAMSUNG decode"); |
yuhki50 | 0:70c8e56bac45 | 65 | if (decodeSAMSUNG(results)) return true ; |
yuhki50 | 0:70c8e56bac45 | 66 | #endif |
yuhki50 | 0:70c8e56bac45 | 67 | |
yuhki50 | 0:70c8e56bac45 | 68 | #if DECODE_WHYNTER |
yuhki50 | 0:70c8e56bac45 | 69 | DBG_PRINTLN("Attempting Whynter decode"); |
yuhki50 | 0:70c8e56bac45 | 70 | if (decodeWhynter(results)) return true ; |
yuhki50 | 0:70c8e56bac45 | 71 | #endif |
yuhki50 | 0:70c8e56bac45 | 72 | |
yuhki50 | 0:70c8e56bac45 | 73 | #if DECODE_AIWA_RC_T501 |
yuhki50 | 0:70c8e56bac45 | 74 | DBG_PRINTLN("Attempting Aiwa RC-T501 decode"); |
yuhki50 | 0:70c8e56bac45 | 75 | if (decodeAiwaRCT501(results)) return true ; |
yuhki50 | 0:70c8e56bac45 | 76 | #endif |
yuhki50 | 0:70c8e56bac45 | 77 | |
yuhki50 | 0:70c8e56bac45 | 78 | #if DECODE_DENON |
yuhki50 | 0:70c8e56bac45 | 79 | DBG_PRINTLN("Attempting Denon decode"); |
yuhki50 | 0:70c8e56bac45 | 80 | if (decodeDenon(results)) return true ; |
yuhki50 | 0:70c8e56bac45 | 81 | #endif |
yuhki50 | 0:70c8e56bac45 | 82 | |
yuhki50 | 0:70c8e56bac45 | 83 | // decodeHash returns a hash on any input. |
yuhki50 | 0:70c8e56bac45 | 84 | // Thus, it needs to be last in the list. |
yuhki50 | 0:70c8e56bac45 | 85 | // If you add any decodes, add them before this. |
yuhki50 | 0:70c8e56bac45 | 86 | if (decodeHash(results)) return true ; |
yuhki50 | 0:70c8e56bac45 | 87 | |
yuhki50 | 0:70c8e56bac45 | 88 | // Throw away and start over |
yuhki50 | 0:70c8e56bac45 | 89 | resume(); |
yuhki50 | 0:70c8e56bac45 | 90 | return false; |
yuhki50 | 0:70c8e56bac45 | 91 | } |
yuhki50 | 0:70c8e56bac45 | 92 | |
yuhki50 | 0:70c8e56bac45 | 93 | //+============================================================================= |
yuhki50 | 0:70c8e56bac45 | 94 | IRrecv::IRrecv (int recvpin) |
yuhki50 | 0:70c8e56bac45 | 95 | { |
yuhki50 | 0:70c8e56bac45 | 96 | irparams.recvpin = recvpin; |
yuhki50 | 0:70c8e56bac45 | 97 | irparams.blinkflag = 0; |
yuhki50 | 0:70c8e56bac45 | 98 | } |
yuhki50 | 0:70c8e56bac45 | 99 | |
yuhki50 | 0:70c8e56bac45 | 100 | IRrecv::IRrecv (int recvpin, int blinkpin) |
yuhki50 | 0:70c8e56bac45 | 101 | { |
yuhki50 | 0:70c8e56bac45 | 102 | irparams.recvpin = recvpin; |
yuhki50 | 0:70c8e56bac45 | 103 | irparams.blinkpin = blinkpin; |
yuhki50 | 0:70c8e56bac45 | 104 | pinMode(blinkpin, OUTPUT); |
yuhki50 | 0:70c8e56bac45 | 105 | irparams.blinkflag = 0; |
yuhki50 | 0:70c8e56bac45 | 106 | } |
yuhki50 | 0:70c8e56bac45 | 107 | |
yuhki50 | 0:70c8e56bac45 | 108 | |
yuhki50 | 0:70c8e56bac45 | 109 | |
yuhki50 | 0:70c8e56bac45 | 110 | //+============================================================================= |
yuhki50 | 0:70c8e56bac45 | 111 | // initialization |
yuhki50 | 0:70c8e56bac45 | 112 | // |
yuhki50 | 0:70c8e56bac45 | 113 | void IRrecv::enableIRIn ( ) |
yuhki50 | 0:70c8e56bac45 | 114 | { |
yuhki50 | 0:70c8e56bac45 | 115 | cli(); |
yuhki50 | 0:70c8e56bac45 | 116 | // Setup pulse clock timer interrupt |
yuhki50 | 0:70c8e56bac45 | 117 | // Prescale /8 (16M/8 = 0.5 microseconds per tick) |
yuhki50 | 0:70c8e56bac45 | 118 | // Therefore, the timer interval can range from 0.5 to 128 microseconds |
yuhki50 | 0:70c8e56bac45 | 119 | // Depending on the reset value (255 to 0) |
yuhki50 | 0:70c8e56bac45 | 120 | TIMER_CONFIG_NORMAL(); |
yuhki50 | 0:70c8e56bac45 | 121 | |
yuhki50 | 0:70c8e56bac45 | 122 | // Timer2 Overflow Interrupt Enable |
yuhki50 | 0:70c8e56bac45 | 123 | TIMER_ENABLE_INTR; |
yuhki50 | 0:70c8e56bac45 | 124 | |
yuhki50 | 0:70c8e56bac45 | 125 | TIMER_RESET; |
yuhki50 | 0:70c8e56bac45 | 126 | |
yuhki50 | 0:70c8e56bac45 | 127 | sei(); // enable interrupts |
yuhki50 | 0:70c8e56bac45 | 128 | |
yuhki50 | 0:70c8e56bac45 | 129 | // Initialize state machine variables |
yuhki50 | 0:70c8e56bac45 | 130 | irparams.rcvstate = STATE_IDLE; |
yuhki50 | 0:70c8e56bac45 | 131 | irparams.rawlen = 0; |
yuhki50 | 0:70c8e56bac45 | 132 | |
yuhki50 | 0:70c8e56bac45 | 133 | // Set pin modes |
yuhki50 | 0:70c8e56bac45 | 134 | pinMode(irparams.recvpin, INPUT); |
yuhki50 | 0:70c8e56bac45 | 135 | } |
yuhki50 | 0:70c8e56bac45 | 136 | |
yuhki50 | 0:70c8e56bac45 | 137 | //+============================================================================= |
yuhki50 | 0:70c8e56bac45 | 138 | // Enable/disable blinking of pin 13 on IR processing |
yuhki50 | 0:70c8e56bac45 | 139 | // |
yuhki50 | 0:70c8e56bac45 | 140 | void IRrecv::blink13 (int blinkflag) |
yuhki50 | 0:70c8e56bac45 | 141 | { |
yuhki50 | 0:70c8e56bac45 | 142 | irparams.blinkflag = blinkflag; |
yuhki50 | 0:70c8e56bac45 | 143 | if (blinkflag) pinMode(BLINKLED, OUTPUT) ; |
yuhki50 | 0:70c8e56bac45 | 144 | } |
yuhki50 | 0:70c8e56bac45 | 145 | |
yuhki50 | 0:70c8e56bac45 | 146 | //+============================================================================= |
yuhki50 | 0:70c8e56bac45 | 147 | // Return if receiving new IR signals |
yuhki50 | 0:70c8e56bac45 | 148 | // |
yuhki50 | 0:70c8e56bac45 | 149 | bool IRrecv::isIdle ( ) |
yuhki50 | 0:70c8e56bac45 | 150 | { |
yuhki50 | 0:70c8e56bac45 | 151 | return (irparams.rcvstate == STATE_IDLE || irparams.rcvstate == STATE_STOP) ? true : false; |
yuhki50 | 0:70c8e56bac45 | 152 | } |
yuhki50 | 0:70c8e56bac45 | 153 | //+============================================================================= |
yuhki50 | 0:70c8e56bac45 | 154 | // Restart the ISR state machine |
yuhki50 | 0:70c8e56bac45 | 155 | // |
yuhki50 | 0:70c8e56bac45 | 156 | void IRrecv::resume ( ) |
yuhki50 | 0:70c8e56bac45 | 157 | { |
yuhki50 | 0:70c8e56bac45 | 158 | irparams.rcvstate = STATE_IDLE; |
yuhki50 | 0:70c8e56bac45 | 159 | irparams.rawlen = 0; |
yuhki50 | 0:70c8e56bac45 | 160 | } |
yuhki50 | 0:70c8e56bac45 | 161 | |
yuhki50 | 0:70c8e56bac45 | 162 | //+============================================================================= |
yuhki50 | 0:70c8e56bac45 | 163 | // hashdecode - decode an arbitrary IR code. |
yuhki50 | 0:70c8e56bac45 | 164 | // Instead of decoding using a standard encoding scheme |
yuhki50 | 0:70c8e56bac45 | 165 | // (e.g. Sony, NEC, RC5), the code is hashed to a 32-bit value. |
yuhki50 | 0:70c8e56bac45 | 166 | // |
yuhki50 | 0:70c8e56bac45 | 167 | // The algorithm: look at the sequence of MARK signals, and see if each one |
yuhki50 | 0:70c8e56bac45 | 168 | // is shorter (0), the same length (1), or longer (2) than the previous. |
yuhki50 | 0:70c8e56bac45 | 169 | // Do the same with the SPACE signals. Hash the resulting sequence of 0's, |
yuhki50 | 0:70c8e56bac45 | 170 | // 1's, and 2's to a 32-bit value. This will give a unique value for each |
yuhki50 | 0:70c8e56bac45 | 171 | // different code (probably), for most code systems. |
yuhki50 | 0:70c8e56bac45 | 172 | // |
yuhki50 | 0:70c8e56bac45 | 173 | // http://arcfn.com/2010/01/using-arbitrary-remotes-with-arduino.html |
yuhki50 | 0:70c8e56bac45 | 174 | // |
yuhki50 | 0:70c8e56bac45 | 175 | // Compare two tick values, returning 0 if newval is shorter, |
yuhki50 | 0:70c8e56bac45 | 176 | // 1 if newval is equal, and 2 if newval is longer |
yuhki50 | 0:70c8e56bac45 | 177 | // Use a tolerance of 20% |
yuhki50 | 0:70c8e56bac45 | 178 | // |
yuhki50 | 0:70c8e56bac45 | 179 | int IRrecv::compare (unsigned int oldval, unsigned int newval) |
yuhki50 | 0:70c8e56bac45 | 180 | { |
yuhki50 | 0:70c8e56bac45 | 181 | if (newval < oldval * .8) return 0 ; |
yuhki50 | 0:70c8e56bac45 | 182 | else if (oldval < newval * .8) return 2 ; |
yuhki50 | 0:70c8e56bac45 | 183 | else return 1 ; |
yuhki50 | 0:70c8e56bac45 | 184 | } |
yuhki50 | 0:70c8e56bac45 | 185 | |
yuhki50 | 0:70c8e56bac45 | 186 | //+============================================================================= |
yuhki50 | 0:70c8e56bac45 | 187 | // Use FNV hash algorithm: http://isthe.com/chongo/tech/comp/fnv/#FNV-param |
yuhki50 | 0:70c8e56bac45 | 188 | // Converts the raw code values into a 32-bit hash code. |
yuhki50 | 0:70c8e56bac45 | 189 | // Hopefully this code is unique for each button. |
yuhki50 | 0:70c8e56bac45 | 190 | // This isn't a "real" decoding, just an arbitrary value. |
yuhki50 | 0:70c8e56bac45 | 191 | // |
yuhki50 | 0:70c8e56bac45 | 192 | #define FNV_PRIME_32 16777619 |
yuhki50 | 0:70c8e56bac45 | 193 | #define FNV_BASIS_32 2166136261 |
yuhki50 | 0:70c8e56bac45 | 194 | |
yuhki50 | 0:70c8e56bac45 | 195 | long IRrecv::decodeHash (decode_results *results) |
yuhki50 | 0:70c8e56bac45 | 196 | { |
yuhki50 | 0:70c8e56bac45 | 197 | long hash = FNV_BASIS_32; |
yuhki50 | 0:70c8e56bac45 | 198 | |
yuhki50 | 0:70c8e56bac45 | 199 | // Require at least 6 samples to prevent triggering on noise |
yuhki50 | 0:70c8e56bac45 | 200 | if (results->rawlen < 6) return false ; |
yuhki50 | 0:70c8e56bac45 | 201 | |
yuhki50 | 0:70c8e56bac45 | 202 | for (int i = 1; (i + 2) < results->rawlen; i++) { |
yuhki50 | 0:70c8e56bac45 | 203 | int value = compare(results->rawbuf[i], results->rawbuf[i+2]); |
yuhki50 | 0:70c8e56bac45 | 204 | // Add value into the hash |
yuhki50 | 0:70c8e56bac45 | 205 | hash = (hash * FNV_PRIME_32) ^ value; |
yuhki50 | 0:70c8e56bac45 | 206 | } |
yuhki50 | 0:70c8e56bac45 | 207 | |
yuhki50 | 0:70c8e56bac45 | 208 | results->value = hash; |
yuhki50 | 0:70c8e56bac45 | 209 | results->bits = 32; |
yuhki50 | 0:70c8e56bac45 | 210 | results->decode_type = UNKNOWN; |
yuhki50 | 0:70c8e56bac45 | 211 | |
yuhki50 | 0:70c8e56bac45 | 212 | return true; |
yuhki50 | 0:70c8e56bac45 | 213 | } |