├── .gitignore ├── .travis.yml ├── Contributing.md ├── Contributors.md ├── IRremote.cpp ├── IRremote.h ├── IRremoteInt.h ├── ISSUE_TEMPLATE.md ├── LICENSE.txt ├── README.md ├── arduino-irremote.sublime-workspace ├── boarddefs.h ├── changelog.md ├── examples ├── AiwaRCT501SendDemo │ └── AiwaRCT501SendDemo.ino ├── IRrecord │ └── IRrecord.ino ├── IRrecvDemo │ └── IRrecvDemo.ino ├── IRrecvDump │ └── IRrecvDump.ino ├── IRrecvDumpV2 │ └── IRrecvDumpV2.ino ├── IRrelay │ └── IRrelay.ino ├── IRremoteInfo │ └── IRremoteInfo.ino ├── IRsendDemo │ └── IRsendDemo.ino ├── IRsendRawDemo │ └── IRsendRawDemo.ino ├── IRtest │ └── IRtest.ino ├── IRtest2 │ └── IRtest2.ino ├── JVCPanasonicSendDemo │ └── JVCPanasonicSendDemo.ino ├── LGACSendDemo │ ├── LGACSendDemo.ino │ └── LGACSendDemo.md ├── LegoPowerFunctionsSendDemo │ └── LegoPowerFunctionsSendDemo.ino └── LegoPowerFunctionsTests │ └── LegoPowerFunctionsTests.ino ├── irPronto.cpp ├── irRecv.cpp ├── irSend.cpp ├── ir_Aiwa.cpp ├── ir_Denon.cpp ├── ir_Dish.cpp ├── ir_JVC.cpp ├── ir_LG.cpp ├── ir_Lego_PF.cpp ├── ir_Lego_PF_BitStreamEncoder.h ├── ir_Mitsubishi.cpp ├── ir_NEC.cpp ├── ir_Panasonic.cpp ├── ir_RC5_RC6.cpp ├── ir_Samsung.cpp ├── ir_Sanyo.cpp ├── ir_Sharp.cpp ├── ir_Sony.cpp ├── ir_Template.cpp ├── ir_Whynter.cpp ├── keywords.txt ├── library.json ├── library.properties ├── readmdFrench.md └── test ├── ir_atmega328p_4_base-carrier.PNG ├── ir_esp32_4_base-carrier.PNG └── ir_esp32_4_base-carrier_afterFix.PNG /.gitignore: -------------------------------------------------------------------------------- 1 | *.un~ 2 | *.sublime-project 3 | *.sublime-workspace -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: python 2 | python: 3 | - "2.7" 4 | 5 | # Cache PlatformIO packages using Travis CI container-based infrastructure 6 | sudo: false 7 | cache: 8 | directories: 9 | - "~/.platformio" 10 | 11 | env: 12 | - PLATFORMIO_CI_SRC=examples/AiwaRCT501SendDemo PLATFORMIO_BUILD_FLAGS="-DSEND_AIWA_RC_T501" 13 | - PLATFORMIO_CI_SRC=examples/IRrecord PLATFORMIO_BUILD_FLAGS="-DSEND_NEC -DSEND_SONY -DSEND_RC5 -DSEND_RC6" 14 | - PLATFORMIO_CI_SRC=examples/IRrecvDemo 15 | - PLATFORMIO_CI_SRC=examples/IRrecvDump 16 | - PLATFORMIO_CI_SRC=examples/IRrecvDumpV2 17 | - PLATFORMIO_CI_SRC=examples/IRrelay 18 | - PLATFORMIO_CI_SRC=examples/IRsendDemo PLATFORMIO_BUILD_FLAGS="-DSEND_SONY" 19 | - PLATFORMIO_CI_SRC=examples/IRtest PLATFORMIO_BUILD_FLAGS="-DSEND_NEC -DSEND_SONY -DSEND_RC5 -DSEND_RC6" 20 | - PLATFORMIO_CI_SRC=examples/IRtest2 PLATFORMIO_BUILD_FLAGS="-DSEND_NEC -DSEND_SONY -DSEND_RC5 -DSEND_RC6" 21 | - PLATFORMIO_CI_SRC=examples/JVCPanasonicSendDemo PLATFORMIO_BUILD_FLAGS="-DSEND_JVC -DSEND_PANASONIC" 22 | - PLATFORMIO_CI_SRC=examples/LegoPowerFunctionsSendDemo PLATFORMIO_BUILD_FLAGS="-DSEND_LEGO_PF" 23 | - PLATFORMIO_CI_SRC=examples/LegoPowerFunctionsTests PLATFORMIO_BUILD_FLAGS="-DSEND_LEGO_PF" 24 | - PLATFORMIO_CI_SRC=examples/IRremoteInfo 25 | 26 | install: 27 | - pip install -U platformio 28 | 29 | script: 30 | - platformio ci --lib="." --board=uno --board=leonardo --board=pro16MHzatmega168 --board=btatmega328 31 | -------------------------------------------------------------------------------- /Contributing.md: -------------------------------------------------------------------------------- 1 | # Contribution Guidlines 2 | 3 | This library is the culmination of the expertise of many members of the open source community who have dedicated their time and hard work. The best way to ask for help or propose a new idea is to [create a new issue](https://github.com/z3t0/Arduino-IRremote/issues/new) while creating a Pull Request with your code changes allows you to share your own innovations with the rest of the community. 4 | 5 | The following are some guidelines to observe when creating issues or PRs: 6 | - Be friendly; it is important that we can all enjoy a safe space as we are all working on the same project and it is okay for people to have different ideas 7 | - [Use code blocks](https://github.com/adam-p/markdown-here/wiki/Markdown-Cheatsheet#code); it helps us help you when we can read your code! On that note also refrain from pasting more than 30 lines of code in a post, instead [create a gist](https://gist.github.com/) if you need to share large snippets 8 | - Use reasonable titles; refrain from using overly long or capitalized titles as they are usually annoying and do little to encourage others to help :smile: 9 | - Be detailed; refrain from mentioning code problems without sharing your source code and always give information regarding your board and version of the library 10 | 11 | If there is any need to contact me then you can find my email on the README, I do not mind responding to emails but it would be in your own interests to create issues if you need help with the library as responses would be from a larger community with greater knowledge! -------------------------------------------------------------------------------- /Contributors.md: -------------------------------------------------------------------------------- 1 | ## Contributors 2 | These are the active contributors of this project that you may contact if there is anything you need help with or if you have suggestions. 3 | 4 | - [z3t0](https://github.com/z3t0) : Active Contributor and currently also the main contributor. 5 | * Email: zetoslab@gmail.com 6 | - [shirriff](https://github.com/shirriff) : An amazing person who worked to create this awesome library and provide unending support 7 | - [AnalysIR](https:/github.com/AnalysIR): Active contributor and is amazing with providing support! 8 | - [Informatic](https://github.com/Informatic) : Active contributor 9 | - [fmeschia](https://github.com/fmeschia) : Active contributor 10 | - [PaulStoffregen](https://github.com/paulstroffregen) : Active contributor 11 | - [crash7](https://github.com/crash7) : Active contributor 12 | - [Neco777](https://github.com/neco777) : Active contributor 13 | - [Lauszus](https://github.com/lauszus) : Active contributor 14 | - [csBlueChip](https://github.com/csbluechip) : Active contributor, who contributed major and vital changes to the code base. 15 | - [Sebazzz](https://github.com/sebazz): Contributor 16 | - [lumbric](https://github.com/lumbric): Contributor 17 | - [ElectricRCAircraftGuy](https://github.com/electricrcaircraftguy): Active Contributor 18 | - [philipphenkel](https://github.com/philipphenkel): Active Contributor 19 | - [MCUdude](https://github.com/MCUdude): Contributor 20 | - [marcmerlin](https://github.com/marcmerlin): Contributor (ESP32 port) 21 | 22 | Note: This list is being updated constantly so please let [z3t0](https://github.com/z3t0) know if you have been missed. 23 | -------------------------------------------------------------------------------- /IRremote.cpp: -------------------------------------------------------------------------------- 1 | //****************************************************************************** 2 | // IRremote 3 | // Version 2.0.1 June, 2015 4 | // Copyright 2009 Ken Shirriff 5 | // For details, see http://arcfn.com/2009/08/multi-protocol-infrared-remote-library.html 6 | // 7 | // Modified by Paul Stoffregen to support other boards and timers 8 | // Modified by Mitra Ardron 9 | // Added Sanyo and Mitsubishi controllers 10 | // Modified Sony to spot the repeat codes that some Sony's send 11 | // 12 | // Interrupt code based on NECIRrcv by Joe Knapp 13 | // http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1210243556 14 | // Also influenced by http://zovirl.com/2008/11/12/building-a-universal-remote-with-an-arduino/ 15 | // 16 | // JVC and Panasonic protocol added by Kristian Lauszus (Thanks to zenwheel and other people at the original blog post) 17 | // LG added by Darryl Smith (based on the JVC protocol) 18 | // Whynter A/C ARC-110WD added by Francesco Meschia 19 | //****************************************************************************** 20 | 21 | // Defining IR_GLOBAL here allows us to declare the instantiation of global variables 22 | #define IR_GLOBAL 23 | #include "IRremote.h" 24 | #include "IRremoteInt.h" 25 | #undef IR_GLOBAL 26 | 27 | #ifndef IR_TIMER_USE_ESP32 28 | #include 29 | #endif 30 | 31 | //+============================================================================= 32 | // The match functions were (apparently) originally MACROs to improve code speed 33 | // (although this would have bloated the code) hence the names being CAPS 34 | // A later release implemented debug output and so they needed to be converted 35 | // to functions. 36 | // I tried to implement a dual-compile mode (DEBUG/non-DEBUG) but for some 37 | // reason, no matter what I did I could not get them to function as macros again. 38 | // I have found a *lot* of bugs in the Arduino compiler over the last few weeks, 39 | // and I am currently assuming that one of these bugs is my problem. 40 | // I may revisit this code at a later date and look at the assembler produced 41 | // in a hope of finding out what is going on, but for now they will remain as 42 | // functions even in non-DEBUG mode 43 | // 44 | int MATCH(int measured, int desired) 45 | { 46 | DBG_PRINT(F("Testing: ")); 47 | DBG_PRINT(TICKS_LOW(desired), DEC); 48 | DBG_PRINT(F(" <= ")); 49 | DBG_PRINT(measured, DEC); 50 | DBG_PRINT(F(" <= ")); 51 | DBG_PRINT(TICKS_HIGH(desired), DEC); 52 | 53 | bool passed = ((measured >= TICKS_LOW(desired)) && (measured <= TICKS_HIGH(desired))); 54 | if (passed) 55 | DBG_PRINTLN(F("?; passed")); 56 | else 57 | DBG_PRINTLN(F("?; FAILED")); 58 | return passed; 59 | } 60 | 61 | //+======================================================== 62 | // Due to sensor lag, when received, Marks tend to be 100us too long 63 | // 64 | int MATCH_MARK(int measured_ticks, int desired_us) 65 | { 66 | DBG_PRINT(F("Testing mark (actual vs desired): ")); 67 | DBG_PRINT(measured_ticks * USECPERTICK, DEC); 68 | DBG_PRINT(F("us vs ")); 69 | DBG_PRINT(desired_us, DEC); 70 | DBG_PRINT("us"); 71 | DBG_PRINT(": "); 72 | DBG_PRINT(TICKS_LOW(desired_us + MARK_EXCESS) * USECPERTICK, DEC); 73 | DBG_PRINT(F(" <= ")); 74 | DBG_PRINT(measured_ticks * USECPERTICK, DEC); 75 | DBG_PRINT(F(" <= ")); 76 | DBG_PRINT(TICKS_HIGH(desired_us + MARK_EXCESS) * USECPERTICK, DEC); 77 | 78 | bool passed = ((measured_ticks >= TICKS_LOW(desired_us + MARK_EXCESS)) && (measured_ticks <= TICKS_HIGH(desired_us + MARK_EXCESS))); 79 | if (passed) 80 | DBG_PRINTLN(F("?; passed")); 81 | else 82 | DBG_PRINTLN(F("?; FAILED")); 83 | return passed; 84 | } 85 | 86 | //+======================================================== 87 | // Due to sensor lag, when received, Spaces tend to be 100us too short 88 | // 89 | int MATCH_SPACE(int measured_ticks, int desired_us) 90 | { 91 | DBG_PRINT(F("Testing space (actual vs desired): ")); 92 | DBG_PRINT(measured_ticks * USECPERTICK, DEC); 93 | DBG_PRINT(F("us vs ")); 94 | DBG_PRINT(desired_us, DEC); 95 | DBG_PRINT("us"); 96 | DBG_PRINT(": "); 97 | DBG_PRINT(TICKS_LOW(desired_us - MARK_EXCESS) * USECPERTICK, DEC); 98 | DBG_PRINT(F(" <= ")); 99 | DBG_PRINT(measured_ticks * USECPERTICK, DEC); 100 | DBG_PRINT(F(" <= ")); 101 | DBG_PRINT(TICKS_HIGH(desired_us - MARK_EXCESS) * USECPERTICK, DEC); 102 | 103 | bool passed = ((measured_ticks >= TICKS_LOW(desired_us - MARK_EXCESS)) && (measured_ticks <= TICKS_HIGH(desired_us - MARK_EXCESS))); 104 | if (passed) 105 | DBG_PRINTLN(F("?; passed")); 106 | else 107 | DBG_PRINTLN(F("?; FAILED")); 108 | return passed; 109 | } 110 | 111 | //+============================================================================= 112 | // Interrupt Service Routine - Fires every 50uS 113 | // TIMER2 interrupt code to collect raw data. 114 | // Widths of alternating SPACE, MARK are recorded in rawbuf. 115 | // Recorded in ticks of 50uS [microseconds, 0.000050 seconds] 116 | // 'rawlen' counts the number of entries recorded so far. 117 | // First entry is the SPACE between transmissions. 118 | // As soon as a the first [SPACE] entry gets long: 119 | // Ready is set; State switches to IDLE; Timing of SPACE continues. 120 | // As soon as first MARK arrives: 121 | // Gap width is recorded; Ready is cleared; New logging starts 122 | // 123 | #ifdef IR_TIMER_USE_ESP32 124 | void IRTimer() 125 | #else 126 | ISR(TIMER_INTR_NAME) 127 | #endif 128 | { 129 | TIMER_RESET; 130 | 131 | // Read if IR Receiver -> SPACE [xmt LED off] or a MARK [xmt LED on] 132 | // digitalRead() is very slow. Optimisation is possible, but makes the code unportable 133 | uint8_t irdata = (uint8_t)digitalRead(irparams.recvpin); 134 | 135 | irparams.timer++; // One more 50uS tick 136 | if (irparams.rawlen >= RAWBUF) 137 | irparams.rcvstate = STATE_OVERFLOW; // Buffer overflow 138 | 139 | switch (irparams.rcvstate) 140 | { 141 | //...................................................................... 142 | case STATE_IDLE: // In the middle of a gap 143 | if (irdata == MARK) 144 | { 145 | if (irparams.timer < GAP_TICKS) 146 | { // Not big enough to be a gap. 147 | irparams.timer = 0; 148 | } 149 | else 150 | { 151 | // Gap just ended; Record duration; Start recording transmission 152 | irparams.overflow = false; 153 | irparams.rawlen = 0; 154 | irparams.rawbuf[irparams.rawlen++] = irparams.timer; 155 | irparams.timer = 0; 156 | irparams.rcvstate = STATE_MARK; 157 | } 158 | } 159 | break; 160 | //...................................................................... 161 | case STATE_MARK: // Timing Mark 162 | if (irdata == SPACE) 163 | { // Mark ended; Record time 164 | irparams.rawbuf[irparams.rawlen++] = irparams.timer; 165 | irparams.timer = 0; 166 | irparams.rcvstate = STATE_SPACE; 167 | } 168 | break; 169 | //...................................................................... 170 | case STATE_SPACE: // Timing Space 171 | if (irdata == MARK) 172 | { // Space just ended; Record time 173 | irparams.rawbuf[irparams.rawlen++] = irparams.timer; 174 | irparams.timer = 0; 175 | irparams.rcvstate = STATE_MARK; 176 | } 177 | else if (irparams.timer > GAP_TICKS) 178 | { // Space 179 | // A long Space, indicates gap between codes 180 | // Flag the current code as ready for processing 181 | // Switch to STOP 182 | // Don't reset timer; keep counting Space width 183 | irparams.rcvstate = STATE_STOP; 184 | } 185 | break; 186 | //...................................................................... 187 | case STATE_STOP: // Waiting; Measuring Gap 188 | if (irdata == MARK) 189 | irparams.timer = 0; // Reset gap timer 190 | break; 191 | //...................................................................... 192 | case STATE_OVERFLOW: // Flag up a read overflow; Stop the State Machine 193 | irparams.overflow = true; 194 | irparams.rcvstate = STATE_STOP; 195 | break; 196 | } 197 | 198 | // If requested, flash LED while receiving IR data 199 | if (irparams.blinkflag) 200 | { 201 | if (irdata == MARK) 202 | { 203 | if (irparams.blinkpin) 204 | digitalWrite(irparams.blinkpin, HIGH); // Turn user defined pin LED on 205 | //else BLINKLED_ON(); // if no user defined LED pin, turn default LED pin for the hardware on 206 | } 207 | else 208 | { 209 | if (irparams.blinkpin) 210 | digitalWrite(irparams.blinkpin, LOW); // Turn user defined pin LED on 211 | //else BLINKLED_OFF(); // if no user defined LED pin, turn default LED pin for the hardware on 212 | } 213 | } 214 | } 215 | -------------------------------------------------------------------------------- /IRremote.h: -------------------------------------------------------------------------------- 1 | 2 | //****************************************************************************** 3 | // IRremote 4 | // Version 2.0.1 June, 2015 5 | // Copyright 2009 Ken Shirriff 6 | // For details, see http://arcfn.com/2009/08/multi-protocol-infrared-remote-library.html 7 | // Edited by Mitra to add new controller SANYO 8 | // 9 | // Interrupt code based on NECIRrcv by Joe Knapp 10 | // http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1210243556 11 | // Also influenced by http://zovirl.com/2008/11/12/building-a-universal-remote-with-an-arduino/ 12 | // 13 | // JVC and Panasonic protocol added by Kristian Lauszus (Thanks to zenwheel and other people at the original blog post) 14 | // LG added by Darryl Smith (based on the JVC protocol) 15 | // Whynter A/C ARC-110WD added by Francesco Meschia 16 | //****************************************************************************** 17 | 18 | #ifndef IRremote_h 19 | #define IRremote_h 20 | 21 | //------------------------------------------------------------------------------ 22 | // The ISR header contains several useful macros the user may wish to use 23 | // 24 | #include "IRremoteInt.h" 25 | 26 | //------------------------------------------------------------------------------ 27 | // Supported IR protocols 28 | // Each protocol you include costs memory and, during decode, costs time 29 | // Disable (set to 0) all the protocols you do not need/want! 30 | // 31 | #define DECODE_RC5 1 32 | #define SEND_RC5 1 33 | 34 | #define DECODE_RC6 1 35 | #define SEND_RC6 1 36 | 37 | #define DECODE_NEC 1 38 | #define SEND_NEC 1 39 | 40 | #define DECODE_SONY 1 41 | #define SEND_SONY 1 42 | 43 | #define DECODE_PANASONIC 1 44 | #define SEND_PANASONIC 1 45 | 46 | #define DECODE_JVC 1 47 | #define SEND_JVC 1 48 | 49 | #define DECODE_SAMSUNG 1 50 | #define SEND_SAMSUNG 1 51 | 52 | #define DECODE_WHYNTER 1 53 | #define SEND_WHYNTER 1 54 | 55 | #define DECODE_AIWA_RC_T501 1 56 | #define SEND_AIWA_RC_T501 1 57 | 58 | #define DECODE_LG 1 59 | #define SEND_LG 1 60 | 61 | #define DECODE_SANYO 1 62 | #define SEND_SANYO 0 // NOT WRITTEN 63 | 64 | #define DECODE_MITSUBISHI 1 65 | #define SEND_MITSUBISHI 0 // NOT WRITTEN 66 | 67 | #define DECODE_DISH 0 // NOT WRITTEN 68 | #define SEND_DISH 1 69 | 70 | #define DECODE_SHARP 0 // NOT WRITTEN 71 | #define SEND_SHARP 1 72 | 73 | #define DECODE_DENON 1 74 | #define SEND_DENON 1 75 | 76 | #define DECODE_PRONTO 0 // This function doe not logically make sense 77 | #define SEND_PRONTO 1 78 | 79 | #define DECODE_LEGO_PF 0 // NOT WRITTEN 80 | #define SEND_LEGO_PF 1 81 | 82 | //------------------------------------------------------------------------------ 83 | // When sending a Pronto code we request to send either the "once" code 84 | // or the "repeat" code 85 | // If the code requested does not exist we can request to fallback on the 86 | // other code (the one we did not explicitly request) 87 | // 88 | // I would suggest that "fallback" will be the standard calling method 89 | // The last paragraph on this page discusses the rationale of this idea: 90 | // http://www.remotecentral.com/features/irdisp2.htm 91 | // 92 | #define PRONTO_ONCE false 93 | #define PRONTO_REPEAT true 94 | #define PRONTO_FALLBACK true 95 | #define PRONTO_NOFALLBACK false 96 | 97 | //------------------------------------------------------------------------------ 98 | // An enumerated list of all supported formats 99 | // You do NOT need to remove entries from this list when disabling protocols! 100 | // 101 | typedef 102 | enum { 103 | UNKNOWN = -1, 104 | UNUSED = 0, 105 | RC5, 106 | RC6, 107 | NEC, 108 | SONY, 109 | PANASONIC, 110 | JVC, 111 | SAMSUNG, 112 | WHYNTER, 113 | AIWA_RC_T501, 114 | LG, 115 | SANYO, 116 | MITSUBISHI, 117 | DISH, 118 | SHARP, 119 | DENON, 120 | PRONTO, 121 | LEGO_PF, 122 | } 123 | decode_type_t; 124 | 125 | //------------------------------------------------------------------------------ 126 | // Set DEBUG to 1 for lots of lovely debug output 127 | // 128 | #define DEBUG 0 129 | 130 | //------------------------------------------------------------------------------ 131 | // Debug directives 132 | // 133 | #if DEBUG 134 | # define DBG_PRINT(...) Serial.print(__VA_ARGS__) 135 | # define DBG_PRINTLN(...) Serial.println(__VA_ARGS__) 136 | #else 137 | # define DBG_PRINT(...) 138 | # define DBG_PRINTLN(...) 139 | #endif 140 | 141 | //------------------------------------------------------------------------------ 142 | // Mark & Space matching functions 143 | // 144 | int MATCH (int measured, int desired) ; 145 | int MATCH_MARK (int measured_ticks, int desired_us) ; 146 | int MATCH_SPACE (int measured_ticks, int desired_us) ; 147 | 148 | //------------------------------------------------------------------------------ 149 | // Results returned from the decoder 150 | // 151 | class decode_results 152 | { 153 | public: 154 | decode_type_t decode_type; // UNKNOWN, NEC, SONY, RC5, ... 155 | unsigned int address; // Used by Panasonic & Sharp [16-bits] 156 | unsigned long value; // Decoded value [max 32-bits] 157 | int bits; // Number of bits in decoded value 158 | volatile unsigned int *rawbuf; // Raw intervals in 50uS ticks 159 | int rawlen; // Number of records in rawbuf 160 | int overflow; // true iff IR raw code too long 161 | }; 162 | 163 | //------------------------------------------------------------------------------ 164 | // Decoded value for NEC when a repeat code is received 165 | // 166 | #define REPEAT 0xFFFFFFFF 167 | 168 | //------------------------------------------------------------------------------ 169 | // Main class for receiving IR 170 | // 171 | class IRrecv 172 | { 173 | public: 174 | IRrecv (int recvpin) ; 175 | IRrecv (int recvpin, int blinkpin); 176 | 177 | void blink13 (int blinkflag) ; 178 | int decode (decode_results *results) ; 179 | void enableIRIn ( ) ; 180 | bool isIdle ( ) ; 181 | void resume ( ) ; 182 | 183 | private: 184 | long decodeHash (decode_results *results) ; 185 | int compare (unsigned int oldval, unsigned int newval) ; 186 | 187 | //...................................................................... 188 | # if (DECODE_RC5 || DECODE_RC6) 189 | // This helper function is shared by RC5 and RC6 190 | int getRClevel (decode_results *results, int *offset, int *used, int t1) ; 191 | # endif 192 | # if DECODE_RC5 193 | bool decodeRC5 (decode_results *results) ; 194 | # endif 195 | # if DECODE_RC6 196 | bool decodeRC6 (decode_results *results) ; 197 | # endif 198 | //...................................................................... 199 | # if DECODE_NEC 200 | bool decodeNEC (decode_results *results) ; 201 | # endif 202 | //...................................................................... 203 | # if DECODE_SONY 204 | bool decodeSony (decode_results *results) ; 205 | # endif 206 | //...................................................................... 207 | # if DECODE_PANASONIC 208 | bool decodePanasonic (decode_results *results) ; 209 | # endif 210 | //...................................................................... 211 | # if DECODE_JVC 212 | bool decodeJVC (decode_results *results) ; 213 | # endif 214 | //...................................................................... 215 | # if DECODE_SAMSUNG 216 | bool decodeSAMSUNG (decode_results *results) ; 217 | # endif 218 | //...................................................................... 219 | # if DECODE_WHYNTER 220 | bool decodeWhynter (decode_results *results) ; 221 | # endif 222 | //...................................................................... 223 | # if DECODE_AIWA_RC_T501 224 | bool decodeAiwaRCT501 (decode_results *results) ; 225 | # endif 226 | //...................................................................... 227 | # if DECODE_LG 228 | bool decodeLG (decode_results *results) ; 229 | # endif 230 | //...................................................................... 231 | # if DECODE_SANYO 232 | bool decodeSanyo (decode_results *results) ; 233 | # endif 234 | //...................................................................... 235 | # if DECODE_MITSUBISHI 236 | bool decodeMitsubishi (decode_results *results) ; 237 | # endif 238 | //...................................................................... 239 | # if DECODE_DISH 240 | bool decodeDish (decode_results *results) ; // NOT WRITTEN 241 | # endif 242 | //...................................................................... 243 | # if DECODE_SHARP 244 | bool decodeSharp (decode_results *results) ; // NOT WRITTEN 245 | # endif 246 | //...................................................................... 247 | # if DECODE_DENON 248 | bool decodeDenon (decode_results *results) ; 249 | # endif 250 | //...................................................................... 251 | # if DECODE_LEGO_PF 252 | bool decodeLegoPowerFunctions (decode_results *results) ; 253 | # endif 254 | } ; 255 | 256 | //------------------------------------------------------------------------------ 257 | // Main class for sending IR 258 | // 259 | class IRsend 260 | { 261 | public: 262 | byte timerPwmPin=3; 263 | IRsend(byte pin){ 264 | timerPwmPin=pin; 265 | IRsend (); 266 | } 267 | IRsend () { } 268 | 269 | void custom_delay_usec (unsigned long uSecs); 270 | void enableIROut (int khz) ; 271 | void mark (unsigned int usec) ; 272 | void space (unsigned int usec) ; 273 | void sendRaw (const unsigned int buf[], unsigned int len, unsigned int hz) ; 274 | 275 | //...................................................................... 276 | # if SEND_RC5 277 | void sendRC5 (unsigned long data, int nbits) ; 278 | # endif 279 | # if SEND_RC6 280 | void sendRC6 (unsigned long data, int nbits) ; 281 | # endif 282 | //...................................................................... 283 | # if SEND_NEC 284 | void sendNEC (unsigned long data, int nbits) ; 285 | # endif 286 | //...................................................................... 287 | # if SEND_SONY 288 | void sendSony (unsigned long data, int nbits) ; 289 | # endif 290 | //...................................................................... 291 | # if SEND_PANASONIC 292 | void sendPanasonic (unsigned int address, unsigned long data) ; 293 | # endif 294 | //...................................................................... 295 | # if SEND_JVC 296 | // JVC does NOT repeat by sending a separate code (like NEC does). 297 | // The JVC protocol repeats by skipping the header. 298 | // To send a JVC repeat signal, send the original code value 299 | // and set 'repeat' to true 300 | void sendJVC (unsigned long data, int nbits, bool repeat) ; 301 | # endif 302 | //...................................................................... 303 | # if SEND_SAMSUNG 304 | void sendSAMSUNG (unsigned long data, int nbits) ; 305 | # endif 306 | //...................................................................... 307 | # if SEND_WHYNTER 308 | void sendWhynter (unsigned long data, int nbits) ; 309 | # endif 310 | //...................................................................... 311 | # if SEND_AIWA_RC_T501 312 | void sendAiwaRCT501 (int code) ; 313 | # endif 314 | //...................................................................... 315 | # if SEND_LG 316 | void sendLG (unsigned long data, int nbits) ; 317 | # endif 318 | //...................................................................... 319 | # if SEND_SANYO 320 | void sendSanyo ( ) ; // NOT WRITTEN 321 | # endif 322 | //...................................................................... 323 | # if SEND_MISUBISHI 324 | void sendMitsubishi ( ) ; // NOT WRITTEN 325 | # endif 326 | //...................................................................... 327 | # if SEND_DISH 328 | void sendDISH (unsigned long data, int nbits) ; 329 | # endif 330 | //...................................................................... 331 | # if SEND_SHARP 332 | void sendSharpRaw (unsigned long data, int nbits) ; 333 | void sendSharp (unsigned int address, unsigned int command) ; 334 | # endif 335 | //...................................................................... 336 | # if SEND_DENON 337 | void sendDenon (unsigned long data, int nbits) ; 338 | # endif 339 | //...................................................................... 340 | # if SEND_PRONTO 341 | void sendPronto (char* code, bool repeat, bool fallback) ; 342 | # endif 343 | //...................................................................... 344 | # if SEND_LEGO_PF 345 | void sendLegoPowerFunctions (uint16_t data, bool repeat = true) ; 346 | # endif 347 | } ; 348 | 349 | #endif 350 | -------------------------------------------------------------------------------- /IRremoteInt.h: -------------------------------------------------------------------------------- 1 | //****************************************************************************** 2 | // IRremote 3 | // Version 2.0.1 June, 2015 4 | // Copyright 2009 Ken Shirriff 5 | // For details, see http://arcfn.com/2009/08/multi-protocol-infrared-remote-library.html 6 | // 7 | // Modified by Paul Stoffregen to support other boards and timers 8 | // 9 | // Interrupt code based on NECIRrcv by Joe Knapp 10 | // http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1210243556 11 | // Also influenced by http://zovirl.com/2008/11/12/building-a-universal-remote-with-an-arduino/ 12 | // 13 | // JVC and Panasonic protocol added by Kristian Lauszus (Thanks to zenwheel and other people at the original blog post) 14 | // Whynter A/C ARC-110WD added by Francesco Meschia 15 | //****************************************************************************** 16 | 17 | #ifndef IRremoteint_h 18 | #define IRremoteint_h 19 | 20 | //------------------------------------------------------------------------------ 21 | // Include the right Arduino header 22 | // 23 | #if defined(ARDUINO) && (ARDUINO >= 100) 24 | # include 25 | #else 26 | # if !defined(IRPRONTO) 27 | # include 28 | # endif 29 | #endif 30 | 31 | //------------------------------------------------------------------------------ 32 | // This handles definition and access to global variables 33 | // 34 | #ifdef IR_GLOBAL 35 | # define EXTERN 36 | #else 37 | # define EXTERN extern 38 | #endif 39 | 40 | //------------------------------------------------------------------------------ 41 | // Information for the Interrupt Service Routine 42 | // 43 | #define RAWBUF 101 // Maximum length of raw duration buffer 44 | 45 | typedef 46 | struct { 47 | // The fields are ordered to reduce memory over caused by struct-padding 48 | uint8_t rcvstate; // State Machine state 49 | uint8_t recvpin; // Pin connected to IR data from detector 50 | uint8_t blinkpin; 51 | uint8_t blinkflag; // true -> enable blinking of pin on IR processing 52 | uint8_t rawlen; // counter of entries in rawbuf 53 | unsigned int timer; // State timer, counts 50uS ticks. 54 | unsigned int rawbuf[RAWBUF]; // raw data 55 | uint8_t overflow; // Raw buffer overflow occurred 56 | } 57 | irparams_t; 58 | 59 | // ISR State-Machine : Receiver States 60 | #define STATE_IDLE 2 61 | #define STATE_MARK 3 62 | #define STATE_SPACE 4 63 | #define STATE_STOP 5 64 | #define STATE_OVERFLOW 6 65 | 66 | // Allow all parts of the code access to the ISR data 67 | // NB. The data can be changed by the ISR at any time, even mid-function 68 | // Therefore we declare it as "volatile" to stop the compiler/CPU caching it 69 | EXTERN volatile irparams_t irparams; 70 | 71 | //------------------------------------------------------------------------------ 72 | // Defines for setting and clearing register bits 73 | // 74 | #ifndef cbi 75 | # define cbi(sfr, bit) (_SFR_BYTE(sfr) &= ~_BV(bit)) 76 | #endif 77 | 78 | #ifndef sbi 79 | # define sbi(sfr, bit) (_SFR_BYTE(sfr) |= _BV(bit)) 80 | #endif 81 | 82 | //------------------------------------------------------------------------------ 83 | // Pulse parms are ((X*50)-100) for the Mark and ((X*50)+100) for the Space. 84 | // First MARK is the one after the long gap 85 | // Pulse parameters in uSec 86 | // 87 | 88 | // Due to sensor lag, when received, Marks tend to be 100us too long and 89 | // Spaces tend to be 100us too short 90 | #define MARK_EXCESS 100 91 | 92 | // Upper and Lower percentage tolerances in measurements 93 | #define TOLERANCE 25 94 | #define LTOL (1.0 - (TOLERANCE/100.)) 95 | #define UTOL (1.0 + (TOLERANCE/100.)) 96 | 97 | // Minimum gap between IR transmissions 98 | #define _GAP 5000 99 | #define GAP_TICKS (_GAP/USECPERTICK) 100 | 101 | #define TICKS_LOW(us) ((int)(((us)*LTOL/USECPERTICK))) 102 | #define TICKS_HIGH(us) ((int)(((us)*UTOL/USECPERTICK + 1))) 103 | 104 | //------------------------------------------------------------------------------ 105 | // IR detector output is active low 106 | // 107 | #define MARK 0 108 | #define SPACE 1 109 | 110 | // All board specific stuff has been moved to its own file, included here. 111 | #include "boarddefs.h" 112 | 113 | #endif 114 | -------------------------------------------------------------------------------- /ISSUE_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | **Board:** ARDUINO UNO 2 | **Library Version:** 2.1.0 3 | **Protocol:** Sony (if any) 4 | 5 | **Code Block:** 6 | ```c 7 | 8 | #include 9 | 10 | ..... 11 | 12 | ``` 13 | 14 | Use [a gist](gist.github.com) if the code exceeds 30 lines 15 | 16 | **checklist:** 17 | - [] I have **read** the README.md file thoroughly 18 | - [] I have searched existing issues to see if there is anything I have missed. 19 | - [] The latest [release](https://github.com/z3t0/Arduino-IRremote/releases/latest) is used 20 | - [] Any code referenced is provided and if over 30 lines a gist is linked INSTEAD of it being pasted in here 21 | - [] The title of the issue is helpful and relevant 22 | 23 | ** We will start to close issues that do not follow these guidelines as it doesn't help the contributors who spend time trying to solve issues if the community ignores guidelines!** 24 | 25 | The above is a short template allowing you to make detailed issues! 26 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # IRremote Arduino Library 2 | 3 | [![Build Status](https://travis-ci.org/z3t0/Arduino-IRremote.svg?branch=master)](https://travis-ci.org/z3t0/Arduino-IRremote) 4 | 5 | [![Join the chat at https://gitter.im/z3t0/Arduino-IRremote](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/z3t0/Arduino-IRremote?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) 6 | 7 | This library enables you to send and receive using infra-red signals on an Arduino. 8 | 9 | Tutorials and more information will be made available on [the official homepage](http://z3t0.github.io/Arduino-IRremote/). 10 | 11 | ## Version - 2.2.3 12 | 13 | ## Installation 14 | 1. Navigate to the [Releases](https://github.com/z3t0/Arduino-IRremote/releases) page. 15 | 2. Download the latest release. 16 | 3. Extract the zip file 17 | 4. Move the "IRremote" folder that has been extracted to your libraries directory. 18 | 5. Make sure to delete Arduino_Root/libraries/RobotIRremote. Where Arduino_Root refers to the install directory of Arduino. The library RobotIRremote has similar definitions to IRremote and causes errors. 19 | 20 | 21 | ## FAQ 22 | - IR does not work right when I use Neopixels (aka WS2811/WS2812/WS2812B) 23 | Whether you use the Adafruit Neopixel lib, or FastLED, interrupts get disabled on many lower end CPUs like the basic arduinos. In turn, this stops the IR interrupt handler from running when it needs to. There are some solutions to this on some processors, [see this page from Marc MERLIN](http://marc.merlins.org/perso/arduino/post_2017-04-03_Arduino-328P-Uno-Teensy3_1-ESP8266-ESP32-IR-and-Neopixels.html) 24 | 25 | 26 | ## Supported Boards 27 | - Arduino Uno / Mega / Leonardo / Duemilanove / Diecimila / LilyPad / Mini / Fio / Nano etc. 28 | - Teensy 1.0 / 1.0++ / 2.0 / 2++ / 3.0 / 3.1 / Teensy-LC; Credits: @PaulStoffregen (Teensy Team) 29 | - Sanguino 30 | - ATmega8, 48, 88, 168, 328 31 | - ATmega8535, 16, 32, 164, 324, 644, 1284, 32 | - ATmega64, 128 33 | - ATtiny 84 / 85 34 | - ESP32 (receive only) 35 | - ESP8266 is supported in a fork based on an old codebase that isn't as recent, but it works reasonably well given that perfectly timed sub millisecond interrupts are different on that chip. See https://github.com/markszabo/IRremoteESP8266 36 | - Sparkfun Pro Micro 37 | 38 | We are open to suggestions for adding support to new boards, however we highly recommend you contact your supplier first and ask them to provide support from their side. 39 | 40 | ### Hardware specifications 41 | 42 | | Board/CPU | Send Pin | Timers | 43 | |--------------------------------------------------------------------------|---------------------|-------------------| 44 | | [ATtiny84](https://github.com/SpenceKonde/ATTinyCore) | **6** | **1** | 45 | | [ATtiny85](https://github.com/SpenceKonde/ATTinyCore) | **1** | **TINY0** | 46 | | [ATmega8](https://github.com/MCUdude/MiniCore) | **9** | **1** | 47 | | Atmega32u4 | 5, 9, **13** | 1, 3, **4** | 48 | | [ATmega48, ATmega88, ATmega168, ATmega328](https://github.com/MCUdude/MiniCore) | **3**, 9 | 1, **2** | 49 | | [ATmega1284](https://github.com/MCUdude/MightyCore) | 13, 14, 6 | 1, **2**, 3 | 50 | | [ATmega164, ATmega324, ATmega644](https://github.com/MCUdude/MightyCore) | 13, **14** | 1, **2** | 51 | | [ATmega8535 ATmega16, ATmega32](https://github.com/MCUdude/MightyCore) | **13** | **1** | 52 | | [ATmega64, ATmega128](https://github.com/MCUdude/MegaCore) | **13** | **1** | 53 | | ATmega1280, ATmega2560 | 5, 6, **9**, 11, 46 | 1, **2**, 3, 4, 5 | 54 | | [ESP32](http://esp32.net/) | N/A (not supported) | **1** | 55 | | [Sparkfun Pro Micro](https://www.sparkfun.com/products/12640) | 9, **5**, 5 | 1, **3**, 4_HS | 56 | | [Teensy 1.0](https://www.pjrc.com/teensy/) | **17** | **1** | 57 | | [Teensy 2.0](https://www.pjrc.com/teensy/) | 9, **10**, 14 | 1, 3, **4_HS** | 58 | | [Teensy++ 1.0 / 2.0](https://www.pjrc.com/teensy/) | **1**, 16, 25 | 1, **2**, 3 | 59 | | [Teensy 3.0 / 3.1](https://www.pjrc.com/teensy/) | **5** | **CMT** | 60 | | [Teensy-LC](https://www.pjrc.com/teensy/) | **16** | **TPM1** | 61 | 62 | 63 | ### Experimental patches 64 | The following are strictly community supported patches that have yet to make it into mainstream. If you have issues feel free to ask here. If it works well then let us know! 65 | 66 | [Arduino 101](https://github.com/z3t0/Arduino-IRremote/pull/481#issuecomment-311243146) 67 | 68 | The table above lists the currently supported timers and corresponding send pins, many of these can have additional pins opened up and we are open to requests if a need arises for other pins. 69 | 70 | ## Usage 71 | - TODO (Check examples for now) 72 | 73 | ## Contributing 74 | If you want to contribute to this project: 75 | - Report bugs and errors 76 | - Ask for enhancements 77 | - Create issues and pull requests 78 | - Tell other people about this library 79 | - Contribute new protocols 80 | 81 | Check [here](Contributing.md) for some guidelines. 82 | 83 | ## Contact 84 | Email: zetoslab@gmail.com 85 | Please only email me if it is more appropriate than creating an Issue / PR. I **will** not respond to requests for adding support for particular boards, unless of course you are the creator of the board and would like to cooperate on the project. I will also **ignore** any emails asking me to tell you how to implement your ideas. However, if you have a private inquiry that you would only apply to you and you would prefer it to be via email, by all means. 86 | 87 | ## Contributors 88 | Check [here](Contributors.md) 89 | 90 | ## Copyright 91 | Copyright 2009-2012 Ken Shirriff 92 | -------------------------------------------------------------------------------- /arduino-irremote.sublime-workspace: -------------------------------------------------------------------------------- 1 | { 2 | "auto_complete": 3 | { 4 | "selected_items": 5 | [ 6 | [ 7 | "vb", 8 | "vboMatrix" 9 | ] 10 | ] 11 | }, 12 | "buffers": 13 | [ 14 | ], 15 | "build_system": "", 16 | "build_system_choices": 17 | [ 18 | ], 19 | "build_varint": "", 20 | "command_palette": 21 | { 22 | "height": 275.0, 23 | "last_filter": "blame", 24 | "selected_items": 25 | [ 26 | [ 27 | "blame", 28 | "Git: Blame" 29 | ], 30 | [ 31 | "install", 32 | "Package Control: Install Package" 33 | ], 34 | [ 35 | "diff", 36 | "Git: Diff Current File" 37 | ], 38 | [ 39 | "js", 40 | "Set Syntax: JavaScript" 41 | ], 42 | [ 43 | "i", 44 | "Package Control: Install Package" 45 | ], 46 | [ 47 | "instal", 48 | "Package Control: Install Package" 49 | ] 50 | ], 51 | "width": 510.0 52 | }, 53 | "console": 54 | { 55 | "height": 126.0, 56 | "history": 57 | [ 58 | "import urllib.request,os,hashlib; h = '2915d1851351e5ee549c20394736b442' + '8bc59f460fa1548d1514676163dafc88'; pf = 'Package Control.sublime-package'; ipp = sublime.installed_packages_path(); urllib.request.install_opener( urllib.request.build_opener( urllib.request.ProxyHandler()) ); by = urllib.request.urlopen( 'http://packagecontrol.io/' + pf.replace(' ', '%20')).read(); dh = hashlib.sha256(by).hexdigest(); print('Error validating download (got %s instead of %s), please try manual install' % (dh, h)) if dh != h else open(os.path.join( ipp, pf), 'wb' ).write(by)" 59 | ] 60 | }, 61 | "distraction_free": 62 | { 63 | "menu_visible": true, 64 | "show_minimap": false, 65 | "show_open_files": false, 66 | "show_tabs": false, 67 | "side_bar_visible": false, 68 | "status_bar_visible": false 69 | }, 70 | "expanded_folders": 71 | [ 72 | "/C/Users/Rafi Khan/Documents/Arduino/libraries/Arduino-IRremote" 73 | ], 74 | "file_history": 75 | [ 76 | "/C/Users/Rafi Khan/Documents/Arduino/libraries/Arduino-IRremote/changelog.md", 77 | "/C/Users/Rafi Khan/Documents/Development/Arduino-IRremote/arduino-irremote.sublime-project", 78 | "/C/Users/Rafi Khan/Documents/Development/Arduino-IRremote/.gitignore", 79 | "/C/Users/Rafi Khan/Documents/Development/magic/README.md", 80 | "/C/Users/Rafi Khan/Documents/Development/magic/shader.frag", 81 | "/C/Users/Rafi Khan/Documents/Development/magic/package.json", 82 | "/C/Users/Rafi Khan/Documents/Development/magic/block.js", 83 | "/C/Users/Rafi Khan/Documents/Development/magic/chunker.js", 84 | "/C/Users/Rafi Khan/Documents/Development/magic/index.js", 85 | "/C/Users/Rafi Khan/Documents/Development/magic/blocks", 86 | "/C/Users/Rafi Khan/AppData/Roaming/Sublime Text 3/Packages/User/Preferences.sublime-settings", 87 | "/C/Users/Rafi Khan/Documents/Development/magic/shader.vert", 88 | "/C/Users/Rafi Khan/Documents/Development/magic/magic.sublime-project", 89 | "/C/Users/Rafi Khan/Documents/Development/magic/node_modules/browserify/node_modules/syntax-error/node_modules/acorn/.tern-project", 90 | "/C/Users/Rafi Khan/OneDrive/Documents/School-RafiKhan/Grade 11/CS30/Python/supermarket.py", 91 | "/C/Users/Rafi Khan/OneDrive/Documents/School-RafiKhan/Grade 11/CS30/Python/takingavacation.py", 92 | "/C/Users/Rafi Khan/OneDrive/Documents/School-RafiKhan/Grade 11/CS30/Python/TipCalculator.py", 93 | "/C/Users/Rafi Khan/OneDrive/Documents/School-RafiKhan/Grade 11/CS30/Python/battleship.py", 94 | "/C/Users/Rafi Khan/OneDrive/Documents/School-RafiKhan/Grade 11/CS30/Python/exam.py", 95 | "/C/Users/Rafi Khan/OneDrive/Documents/School-RafiKhan/Grade 11/CS30/Python/pyglatin.py", 96 | "/C/Users/Rafi Khan/OneDrive/Documents/School-RafiKhan/Grade 11/CS30/Python/student.py" 97 | ], 98 | "find": 99 | { 100 | "height": 28.0 101 | }, 102 | "find_in_files": 103 | { 104 | "height": 0.0, 105 | "where_history": 106 | [ 107 | ] 108 | }, 109 | "find_state": 110 | { 111 | "case_sensitive": false, 112 | "find_history": 113 | [ 114 | "i", 115 | "Direction", 116 | ";", 117 | ";\n", 118 | "north", 119 | "cubeMatrix", 120 | ")\n", 121 | "vec3.set", 122 | "f", 123 | ";", 124 | "();\n", 125 | "render", 126 | "this", 127 | "y" 128 | ], 129 | "highlight": true, 130 | "in_selection": false, 131 | "preserve_case": false, 132 | "regex": false, 133 | "replace_history": 134 | [ 135 | ], 136 | "reverse": false, 137 | "show_context": true, 138 | "use_buffer2": true, 139 | "whole_word": false, 140 | "wrap": true 141 | }, 142 | "groups": 143 | [ 144 | { 145 | "sheets": 146 | [ 147 | ] 148 | } 149 | ], 150 | "incremental_find": 151 | { 152 | "height": 28.0 153 | }, 154 | "input": 155 | { 156 | "height": 66.0 157 | }, 158 | "layout": 159 | { 160 | "cells": 161 | [ 162 | [ 163 | 0, 164 | 0, 165 | 1, 166 | 1 167 | ] 168 | ], 169 | "cols": 170 | [ 171 | 0.0, 172 | 1.0 173 | ], 174 | "rows": 175 | [ 176 | 0.0, 177 | 1.0 178 | ] 179 | }, 180 | "menu_visible": true, 181 | "output.find_results": 182 | { 183 | "height": 0.0 184 | }, 185 | "pinned_build_system": "", 186 | "project": "arduino-irremote.sublime-project", 187 | "replace": 188 | { 189 | "height": 52.0 190 | }, 191 | "save_all_on_build": true, 192 | "select_file": 193 | { 194 | "height": 0.0, 195 | "last_filter": "", 196 | "selected_items": 197 | [ 198 | [ 199 | "json", 200 | "package.json" 201 | ], 202 | [ 203 | "inde", 204 | "index.js" 205 | ] 206 | ], 207 | "width": 0.0 208 | }, 209 | "select_project": 210 | { 211 | "height": 0.0, 212 | "last_filter": "", 213 | "selected_items": 214 | [ 215 | ], 216 | "width": 0.0 217 | }, 218 | "select_symbol": 219 | { 220 | "height": 0.0, 221 | "last_filter": "", 222 | "selected_items": 223 | [ 224 | ], 225 | "width": 0.0 226 | }, 227 | "selected_group": 0, 228 | "settings": 229 | { 230 | }, 231 | "show_minimap": true, 232 | "show_open_files": false, 233 | "show_tabs": true, 234 | "side_bar_visible": true, 235 | "side_bar_width": 150.0, 236 | "status_bar_visible": true, 237 | "template_settings": 238 | { 239 | } 240 | } 241 | -------------------------------------------------------------------------------- /changelog.md: -------------------------------------------------------------------------------- 1 | ## 2.3.3 - 2017/03/31 2 | - Added ESP32 IR receive support [PR #427](https://github.com/z3t0/Arduino-IRremote/pull/425) 3 | 4 | ## 2.2.3 - 2017/03/27 5 | - Fix calculation of pause length in LEGO PF protocol [PR #427](https://github.com/z3t0/Arduino-IRremote/pull/427) 6 | 7 | ## 2.2.2 - 2017/01/20 8 | - Fixed naming bug [PR #398](https://github.com/z3t0/Arduino-IRremote/pull/398) 9 | 10 | ## 2.2.1 - 2016/07/27 11 | - Added tests for Lego Power Functions Protocol [PR #336](https://github.com/z3t0/Arduino-IRremote/pull/336) 12 | 13 | ## 2.2.0 - 2016/06/28 14 | - Added support for ATmega8535 15 | - Added support for ATmega16 16 | - Added support for ATmega32 17 | - Added support for ATmega164 18 | - Added support for ATmega324 19 | - Added support for ATmega644 20 | - Added support for ATmega1284 21 | - Added support for ATmega64 22 | - Added support for ATmega128 23 | 24 | [PR](https://github.com/z3t0/Arduino-IRremote/pull/324) 25 | 26 | ## 2.1.1 - 2016/05/04 27 | - Added Lego Power Functions Protocol [PR #309](https://github.com/z3t0/Arduino-IRremote/pull/309) 28 | 29 | ## 2.1.0 - 2016/02/20 30 | - Improved Debugging [PR #258](https://github.com/z3t0/Arduino-IRremote/pull/258) 31 | - Display TIME instead of TICKS [PR #258](https://github.com/z3t0/Arduino-IRremote/pull/258) 32 | 33 | ## 2.0.4 - 2016/02/20 34 | - Add Panasonic and JVC to IRrecord example [PR](https://github.com/z3t0/Arduino-IRremote/pull/54) 35 | 36 | ## 2.0.3 - 2016/02/20 37 | - Change IRSend Raw parameter to const [PR](https://github.com/z3t0/Arduino-IRremote/pull/227) 38 | 39 | ## 2.0.2 - 2015/12/02 40 | - Added IRremoteInfo Sketch - [PR](https://github.com/z3t0/Arduino-IRremote/pull/241) 41 | - Enforcing changelog.md 42 | 43 | ## 2.0.1 - 2015/07/26 - [Release](https://github.com/shirriff/Arduino-IRremote/releases/tag/BETA) 44 | ### Changes 45 | - Updated README 46 | - Updated Contributors 47 | - Fixed #110 Mess 48 | - Created Gitter Room 49 | - Added Gitter Badge 50 | - Standardised Code Base 51 | - Clean Debug Output 52 | - Optimized Send Loops 53 | - Modularized Design 54 | - Optimized and Updated Examples 55 | - Improved Documentation 56 | - Fixed and Improved many coding errors 57 | - Fixed Aiwa RC-T501 Decoding 58 | - Fixed Interrupt on ATmega8 59 | - Switched to Stable Release of @PlatformIO 60 | 61 | ### Additions 62 | - Added Aiwa RC-T501 Protocol 63 | - Added Denon Protocol 64 | - Added Pronto Support 65 | - Added Library Properties 66 | - Added Template For New Protocols 67 | - Added this changelog 68 | - Added Teensy LC Support 69 | - Added ATtiny84 Support 70 | - Added ATtiny85 Support 71 | - Added isIdle method 72 | 73 | ### Deletions 74 | - Removed (Fixed) #110 75 | - Broke Teensy 3 / 3.1 Support 76 | 77 | ### Not Working 78 | - Teensy 3 / 3.1 Support is in Development 79 | -------------------------------------------------------------------------------- /examples/AiwaRCT501SendDemo/AiwaRCT501SendDemo.ino: -------------------------------------------------------------------------------- 1 | /* 2 | * IRremote: IRsendDemo - demonstrates sending IR codes with IRsend 3 | * An IR LED must be connected to Arduino PWM pin 3. 4 | * Version 0.1 July, 2009 5 | * Copyright 2009 Ken Shirriff 6 | * http://arcfn.com 7 | */ 8 | 9 | #include "IRremote.h" 10 | 11 | #define POWER 0x7F80 12 | #define AIWA_RC_T501 13 | 14 | IRsend irsend; 15 | 16 | void setup() { 17 | Serial.begin(9600); 18 | Serial.println("Arduino Ready"); 19 | } 20 | 21 | void loop() { 22 | if (Serial.read() != -1) { 23 | irsend.sendAiwaRCT501(POWER); 24 | delay(60); // Optional 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /examples/IRrecord/IRrecord.ino: -------------------------------------------------------------------------------- 1 | /* 2 | * IRrecord: record and play back IR signals as a minimal 3 | * An IR detector/demodulator must be connected to the input RECV_PIN. 4 | * An IR LED must be connected to the output PWM pin 3. 5 | * A button must be connected to the input BUTTON_PIN; this is the 6 | * send button. 7 | * A visible LED can be connected to STATUS_PIN to provide status. 8 | * 9 | * The logic is: 10 | * If the button is pressed, send the IR code. 11 | * If an IR code is received, record it. 12 | * 13 | * Version 0.11 September, 2009 14 | * Copyright 2009 Ken Shirriff 15 | * http://arcfn.com 16 | */ 17 | 18 | #include 19 | 20 | int RECV_PIN = 11; 21 | int BUTTON_PIN = 12; 22 | int STATUS_PIN = 13; 23 | 24 | IRrecv irrecv(RECV_PIN); 25 | IRsend irsend; 26 | 27 | decode_results results; 28 | 29 | void setup() 30 | { 31 | Serial.begin(9600); 32 | irrecv.enableIRIn(); // Start the receiver 33 | pinMode(BUTTON_PIN, INPUT); 34 | pinMode(STATUS_PIN, OUTPUT); 35 | } 36 | 37 | // Storage for the recorded code 38 | int codeType = -1; // The type of code 39 | unsigned long codeValue; // The code value if not raw 40 | unsigned int rawCodes[RAWBUF]; // The durations if raw 41 | int codeLen; // The length of the code 42 | int toggle = 0; // The RC5/6 toggle state 43 | 44 | // Stores the code for later playback 45 | // Most of this code is just logging 46 | void storeCode(decode_results *results) { 47 | codeType = results->decode_type; 48 | //int count = results->rawlen; 49 | if (codeType == UNKNOWN) { 50 | Serial.println("Received unknown code, saving as raw"); 51 | codeLen = results->rawlen - 1; 52 | // To store raw codes: 53 | // Drop first value (gap) 54 | // Convert from ticks to microseconds 55 | // Tweak marks shorter, and spaces longer to cancel out IR receiver distortion 56 | for (int i = 1; i <= codeLen; i++) { 57 | if (i % 2) { 58 | // Mark 59 | rawCodes[i - 1] = results->rawbuf[i]*USECPERTICK - MARK_EXCESS; 60 | Serial.print(" m"); 61 | } 62 | else { 63 | // Space 64 | rawCodes[i - 1] = results->rawbuf[i]*USECPERTICK + MARK_EXCESS; 65 | Serial.print(" s"); 66 | } 67 | Serial.print(rawCodes[i - 1], DEC); 68 | } 69 | Serial.println(""); 70 | } 71 | else { 72 | if (codeType == NEC) { 73 | Serial.print("Received NEC: "); 74 | if (results->value == REPEAT) { 75 | // Don't record a NEC repeat value as that's useless. 76 | Serial.println("repeat; ignoring."); 77 | return; 78 | } 79 | } 80 | else if (codeType == SONY) { 81 | Serial.print("Received SONY: "); 82 | } 83 | else if (codeType == PANASONIC) { 84 | Serial.print("Received PANASONIC: "); 85 | } 86 | else if (codeType == JVC) { 87 | Serial.print("Received JVC: "); 88 | } 89 | else if (codeType == RC5) { 90 | Serial.print("Received RC5: "); 91 | } 92 | else if (codeType == RC6) { 93 | Serial.print("Received RC6: "); 94 | } 95 | else { 96 | Serial.print("Unexpected codeType "); 97 | Serial.print(codeType, DEC); 98 | Serial.println(""); 99 | } 100 | Serial.println(results->value, HEX); 101 | codeValue = results->value; 102 | codeLen = results->bits; 103 | } 104 | } 105 | 106 | void sendCode(int repeat) { 107 | if (codeType == NEC) { 108 | if (repeat) { 109 | irsend.sendNEC(REPEAT, codeLen); 110 | Serial.println("Sent NEC repeat"); 111 | } 112 | else { 113 | irsend.sendNEC(codeValue, codeLen); 114 | Serial.print("Sent NEC "); 115 | Serial.println(codeValue, HEX); 116 | } 117 | } 118 | else if (codeType == SONY) { 119 | irsend.sendSony(codeValue, codeLen); 120 | Serial.print("Sent Sony "); 121 | Serial.println(codeValue, HEX); 122 | } 123 | else if (codeType == PANASONIC) { 124 | irsend.sendPanasonic(codeValue, codeLen); 125 | Serial.print("Sent Panasonic"); 126 | Serial.println(codeValue, HEX); 127 | } 128 | else if (codeType == JVC) { 129 | irsend.sendJVC(codeValue, codeLen, false); 130 | Serial.print("Sent JVC"); 131 | Serial.println(codeValue, HEX); 132 | } 133 | else if (codeType == RC5 || codeType == RC6) { 134 | if (!repeat) { 135 | // Flip the toggle bit for a new button press 136 | toggle = 1 - toggle; 137 | } 138 | // Put the toggle bit into the code to send 139 | codeValue = codeValue & ~(1 << (codeLen - 1)); 140 | codeValue = codeValue | (toggle << (codeLen - 1)); 141 | if (codeType == RC5) { 142 | Serial.print("Sent RC5 "); 143 | Serial.println(codeValue, HEX); 144 | irsend.sendRC5(codeValue, codeLen); 145 | } 146 | else { 147 | irsend.sendRC6(codeValue, codeLen); 148 | Serial.print("Sent RC6 "); 149 | Serial.println(codeValue, HEX); 150 | } 151 | } 152 | else if (codeType == UNKNOWN /* i.e. raw */) { 153 | // Assume 38 KHz 154 | irsend.sendRaw(rawCodes, codeLen, 38); 155 | Serial.println("Sent raw"); 156 | } 157 | } 158 | 159 | int lastButtonState; 160 | 161 | void loop() { 162 | // If button pressed, send the code. 163 | int buttonState = digitalRead(BUTTON_PIN); 164 | if (lastButtonState == HIGH && buttonState == LOW) { 165 | Serial.println("Released"); 166 | irrecv.enableIRIn(); // Re-enable receiver 167 | } 168 | 169 | if (buttonState) { 170 | Serial.println("Pressed, sending"); 171 | digitalWrite(STATUS_PIN, HIGH); 172 | sendCode(lastButtonState == buttonState); 173 | digitalWrite(STATUS_PIN, LOW); 174 | delay(50); // Wait a bit between retransmissions 175 | } 176 | else if (irrecv.decode(&results)) { 177 | digitalWrite(STATUS_PIN, HIGH); 178 | storeCode(&results); 179 | irrecv.resume(); // resume receiver 180 | digitalWrite(STATUS_PIN, LOW); 181 | } 182 | lastButtonState = buttonState; 183 | } 184 | -------------------------------------------------------------------------------- /examples/IRrecvDemo/IRrecvDemo.ino: -------------------------------------------------------------------------------- 1 | /* 2 | * IRremote: IRrecvDemo - demonstrates receiving IR codes with IRrecv 3 | * An IR detector/demodulator must be connected to the input RECV_PIN. 4 | * Version 0.1 July, 2009 5 | * Copyright 2009 Ken Shirriff 6 | * http://arcfn.com 7 | */ 8 | 9 | #include 10 | 11 | int RECV_PIN = 11; 12 | 13 | IRrecv irrecv(RECV_PIN); 14 | 15 | decode_results results; 16 | 17 | void setup() 18 | { 19 | Serial.begin(9600); 20 | // In case the interrupt driver crashes on setup, give a clue 21 | // to the user what's going on. 22 | Serial.println("Enabling IRin"); 23 | irrecv.enableIRIn(); // Start the receiver 24 | Serial.println("Enabled IRin"); 25 | } 26 | 27 | void loop() { 28 | if (irrecv.decode(&results)) { 29 | Serial.println(results.value, HEX); 30 | irrecv.resume(); // Receive the next value 31 | } 32 | delay(100); 33 | } 34 | -------------------------------------------------------------------------------- /examples/IRrecvDump/IRrecvDump.ino: -------------------------------------------------------------------------------- 1 | /* 2 | * IRremote: IRrecvDump - dump details of IR codes with IRrecv 3 | * An IR detector/demodulator must be connected to the input RECV_PIN. 4 | * Version 0.1 July, 2009 5 | * Copyright 2009 Ken Shirriff 6 | * http://arcfn.com 7 | * JVC and Panasonic protocol added by Kristian Lauszus (Thanks to zenwheel and other people at the original blog post) 8 | * LG added by Darryl Smith (based on the JVC protocol) 9 | */ 10 | 11 | #include 12 | 13 | /* 14 | * Default is Arduino pin D11. 15 | * You can change this to another available Arduino Pin. 16 | * Your IR receiver should be connected to the pin defined here 17 | */ 18 | int RECV_PIN = 11; 19 | 20 | IRrecv irrecv(RECV_PIN); 21 | 22 | decode_results results; 23 | 24 | void setup() 25 | { 26 | Serial.begin(9600); 27 | irrecv.enableIRIn(); // Start the receiver 28 | } 29 | 30 | 31 | void dump(decode_results *results) { 32 | // Dumps out the decode_results structure. 33 | // Call this after IRrecv::decode() 34 | int count = results->rawlen; 35 | if (results->decode_type == UNKNOWN) { 36 | Serial.print("Unknown encoding: "); 37 | } 38 | else if (results->decode_type == NEC) { 39 | Serial.print("Decoded NEC: "); 40 | 41 | } 42 | else if (results->decode_type == SONY) { 43 | Serial.print("Decoded SONY: "); 44 | } 45 | else if (results->decode_type == RC5) { 46 | Serial.print("Decoded RC5: "); 47 | } 48 | else if (results->decode_type == RC6) { 49 | Serial.print("Decoded RC6: "); 50 | } 51 | else if (results->decode_type == PANASONIC) { 52 | Serial.print("Decoded PANASONIC - Address: "); 53 | Serial.print(results->address, HEX); 54 | Serial.print(" Value: "); 55 | } 56 | else if (results->decode_type == LG) { 57 | Serial.print("Decoded LG: "); 58 | } 59 | else if (results->decode_type == JVC) { 60 | Serial.print("Decoded JVC: "); 61 | } 62 | else if (results->decode_type == AIWA_RC_T501) { 63 | Serial.print("Decoded AIWA RC T501: "); 64 | } 65 | else if (results->decode_type == WHYNTER) { 66 | Serial.print("Decoded Whynter: "); 67 | } 68 | Serial.print(results->value, HEX); 69 | Serial.print(" ("); 70 | Serial.print(results->bits, DEC); 71 | Serial.println(" bits)"); 72 | Serial.print("Raw ("); 73 | Serial.print(count, DEC); 74 | Serial.print("): "); 75 | 76 | for (int i = 1; i < count; i++) { 77 | if (i & 1) { 78 | Serial.print(results->rawbuf[i]*USECPERTICK, DEC); 79 | } 80 | else { 81 | Serial.write('-'); 82 | Serial.print((unsigned long) results->rawbuf[i]*USECPERTICK, DEC); 83 | } 84 | Serial.print(" "); 85 | } 86 | Serial.println(); 87 | } 88 | 89 | void loop() { 90 | if (irrecv.decode(&results)) { 91 | Serial.println(results.value, HEX); 92 | dump(&results); 93 | irrecv.resume(); // Receive the next value 94 | } 95 | } 96 | -------------------------------------------------------------------------------- /examples/IRrecvDumpV2/IRrecvDumpV2.ino: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------ 2 | // Include the IRremote library header 3 | // 4 | #include 5 | 6 | //------------------------------------------------------------------------------ 7 | // Tell IRremote which Arduino pin is connected to the IR Receiver (TSOP4838) 8 | // 9 | int recvPin = 11; 10 | IRrecv irrecv(recvPin); 11 | 12 | //+============================================================================= 13 | // Configure the Arduino 14 | // 15 | void setup ( ) 16 | { 17 | Serial.begin(9600); // Status message will be sent to PC at 9600 baud 18 | irrecv.enableIRIn(); // Start the receiver 19 | } 20 | 21 | //+============================================================================= 22 | // Display IR code 23 | // 24 | void ircode (decode_results *results) 25 | { 26 | // Panasonic has an Address 27 | if (results->decode_type == PANASONIC) { 28 | Serial.print(results->address, HEX); 29 | Serial.print(":"); 30 | } 31 | 32 | // Print Code 33 | Serial.print(results->value, HEX); 34 | } 35 | 36 | //+============================================================================= 37 | // Display encoding type 38 | // 39 | void encoding (decode_results *results) 40 | { 41 | switch (results->decode_type) { 42 | default: 43 | case UNKNOWN: Serial.print("UNKNOWN"); break ; 44 | case NEC: Serial.print("NEC"); break ; 45 | case SONY: Serial.print("SONY"); break ; 46 | case RC5: Serial.print("RC5"); break ; 47 | case RC6: Serial.print("RC6"); break ; 48 | case DISH: Serial.print("DISH"); break ; 49 | case SHARP: Serial.print("SHARP"); break ; 50 | case JVC: Serial.print("JVC"); break ; 51 | case SANYO: Serial.print("SANYO"); break ; 52 | case MITSUBISHI: Serial.print("MITSUBISHI"); break ; 53 | case SAMSUNG: Serial.print("SAMSUNG"); break ; 54 | case LG: Serial.print("LG"); break ; 55 | case WHYNTER: Serial.print("WHYNTER"); break ; 56 | case AIWA_RC_T501: Serial.print("AIWA_RC_T501"); break ; 57 | case PANASONIC: Serial.print("PANASONIC"); break ; 58 | case DENON: Serial.print("Denon"); break ; 59 | } 60 | } 61 | 62 | //+============================================================================= 63 | // Dump out the decode_results structure. 64 | // 65 | void dumpInfo (decode_results *results) 66 | { 67 | // Check if the buffer overflowed 68 | if (results->overflow) { 69 | Serial.println("IR code too long. Edit IRremoteInt.h and increase RAWBUF"); 70 | return; 71 | } 72 | 73 | // Show Encoding standard 74 | Serial.print("Encoding : "); 75 | encoding(results); 76 | Serial.println(""); 77 | 78 | // Show Code & length 79 | Serial.print("Code : "); 80 | ircode(results); 81 | Serial.print(" ("); 82 | Serial.print(results->bits, DEC); 83 | Serial.println(" bits)"); 84 | } 85 | 86 | //+============================================================================= 87 | // Dump out the decode_results structure. 88 | // 89 | void dumpRaw (decode_results *results) 90 | { 91 | // Print Raw data 92 | Serial.print("Timing["); 93 | Serial.print(results->rawlen-1, DEC); 94 | Serial.println("]: "); 95 | 96 | for (int i = 1; i < results->rawlen; i++) { 97 | unsigned long x = results->rawbuf[i] * USECPERTICK; 98 | if (!(i & 1)) { // even 99 | Serial.print("-"); 100 | if (x < 1000) Serial.print(" ") ; 101 | if (x < 100) Serial.print(" ") ; 102 | Serial.print(x, DEC); 103 | } else { // odd 104 | Serial.print(" "); 105 | Serial.print("+"); 106 | if (x < 1000) Serial.print(" ") ; 107 | if (x < 100) Serial.print(" ") ; 108 | Serial.print(x, DEC); 109 | if (i < results->rawlen-1) Serial.print(", "); //',' not needed for last one 110 | } 111 | if (!(i % 8)) Serial.println(""); 112 | } 113 | Serial.println(""); // Newline 114 | } 115 | 116 | //+============================================================================= 117 | // Dump out the decode_results structure. 118 | // 119 | void dumpCode (decode_results *results) 120 | { 121 | // Start declaration 122 | Serial.print("unsigned int "); // variable type 123 | Serial.print("rawData["); // array name 124 | Serial.print(results->rawlen - 1, DEC); // array size 125 | Serial.print("] = {"); // Start declaration 126 | 127 | // Dump data 128 | for (int i = 1; i < results->rawlen; i++) { 129 | Serial.print(results->rawbuf[i] * USECPERTICK, DEC); 130 | if ( i < results->rawlen-1 ) Serial.print(","); // ',' not needed on last one 131 | if (!(i & 1)) Serial.print(" "); 132 | } 133 | 134 | // End declaration 135 | Serial.print("};"); // 136 | 137 | // Comment 138 | Serial.print(" // "); 139 | encoding(results); 140 | Serial.print(" "); 141 | ircode(results); 142 | 143 | // Newline 144 | Serial.println(""); 145 | 146 | // Now dump "known" codes 147 | if (results->decode_type != UNKNOWN) { 148 | 149 | // Some protocols have an address 150 | if (results->decode_type == PANASONIC) { 151 | Serial.print("unsigned int addr = 0x"); 152 | Serial.print(results->address, HEX); 153 | Serial.println(";"); 154 | } 155 | 156 | // All protocols have data 157 | Serial.print("unsigned int data = 0x"); 158 | Serial.print(results->value, HEX); 159 | Serial.println(";"); 160 | } 161 | } 162 | 163 | //+============================================================================= 164 | // The repeating section of the code 165 | // 166 | void loop ( ) 167 | { 168 | decode_results results; // Somewhere to store the results 169 | 170 | if (irrecv.decode(&results)) { // Grab an IR code 171 | dumpInfo(&results); // Output the results 172 | dumpRaw(&results); // Output the results in RAW format 173 | dumpCode(&results); // Output the results as source code 174 | Serial.println(""); // Blank line between entries 175 | irrecv.resume(); // Prepare for the next value 176 | } 177 | } 178 | -------------------------------------------------------------------------------- /examples/IRrelay/IRrelay.ino: -------------------------------------------------------------------------------- 1 | /* 2 | * IRremote: IRrecvDemo - demonstrates receiving IR codes with IRrecv 3 | * An IR detector/demodulator must be connected to the input RECV_PIN. 4 | * Version 0.1 July, 2009 5 | * Copyright 2009 Ken Shirriff 6 | * http://arcfn.com 7 | */ 8 | 9 | #include 10 | 11 | int RECV_PIN = 11; 12 | int RELAY_PIN = 4; 13 | 14 | IRrecv irrecv(RECV_PIN); 15 | decode_results results; 16 | 17 | // Dumps out the decode_results structure. 18 | // Call this after IRrecv::decode() 19 | // void * to work around compiler issue 20 | //void dump(void *v) { 21 | // decode_results *results = (decode_results *)v 22 | void dump(decode_results *results) { 23 | int count = results->rawlen; 24 | if (results->decode_type == UNKNOWN) { 25 | Serial.println("Could not decode message"); 26 | } 27 | else { 28 | if (results->decode_type == NEC) { 29 | Serial.print("Decoded NEC: "); 30 | } 31 | else if (results->decode_type == SONY) { 32 | Serial.print("Decoded SONY: "); 33 | } 34 | else if (results->decode_type == RC5) { 35 | Serial.print("Decoded RC5: "); 36 | } 37 | else if (results->decode_type == RC6) { 38 | Serial.print("Decoded RC6: "); 39 | } 40 | Serial.print(results->value, HEX); 41 | Serial.print(" ("); 42 | Serial.print(results->bits, DEC); 43 | Serial.println(" bits)"); 44 | } 45 | Serial.print("Raw ("); 46 | Serial.print(count, DEC); 47 | Serial.print("): "); 48 | 49 | for (int i = 0; i < count; i++) { 50 | if ((i % 2) == 1) { 51 | Serial.print(results->rawbuf[i]*USECPERTICK, DEC); 52 | } 53 | else { 54 | Serial.print(-(int)results->rawbuf[i]*USECPERTICK, DEC); 55 | } 56 | Serial.print(" "); 57 | } 58 | Serial.println(""); 59 | } 60 | 61 | void setup() 62 | { 63 | pinMode(RELAY_PIN, OUTPUT); 64 | pinMode(13, OUTPUT); 65 | Serial.begin(9600); 66 | irrecv.enableIRIn(); // Start the receiver 67 | } 68 | 69 | int on = 0; 70 | unsigned long last = millis(); 71 | 72 | void loop() { 73 | if (irrecv.decode(&results)) { 74 | // If it's been at least 1/4 second since the last 75 | // IR received, toggle the relay 76 | if (millis() - last > 250) { 77 | on = !on; 78 | digitalWrite(RELAY_PIN, on ? HIGH : LOW); 79 | digitalWrite(13, on ? HIGH : LOW); 80 | dump(&results); 81 | } 82 | last = millis(); 83 | irrecv.resume(); // Receive the next value 84 | } 85 | } 86 | -------------------------------------------------------------------------------- /examples/IRremoteInfo/IRremoteInfo.ino: -------------------------------------------------------------------------------- 1 | /* 2 | * IRremote: IRremoteInfo - prints relevant config info & settings for IRremote over serial 3 | * Intended to help identify & troubleshoot the various settings of IRremote 4 | * For example, sometimes users are unsure of which pin is used for Tx or the RAWBUF values 5 | * This example can be used to assist the user directly or with support. 6 | * Intended to help identify & troubleshoot the various settings of IRremote 7 | * Hopefully this utility will be a useful tool for support & troubleshooting for IRremote 8 | * Check out the blog post describing the sketch via http://www.analysir.com/blog/2015/11/28/helper-utility-for-troubleshooting-irremote/ 9 | * Version 1.0 November 2015 10 | * Original Author: AnalysIR - IR software & modules for Makers & Pros, visit http://www.AnalysIR.com 11 | */ 12 | 13 | 14 | #include 15 | 16 | void setup() 17 | { 18 | Serial.begin(115200); //You may alter the BAUD rate here as needed 19 | while (!Serial); //wait until Serial is established - required on some Platforms 20 | 21 | //Runs only once per restart of the Arduino. 22 | dumpHeader(); 23 | dumpRAWBUF(); 24 | dumpTIMER(); 25 | dumpTimerPin(); 26 | dumpClock(); 27 | dumpPlatform(); 28 | dumpPulseParams(); 29 | dumpSignalParams(); 30 | dumpArduinoIDE(); 31 | dumpDebugMode(); 32 | dumpProtocols(); 33 | dumpFooter(); 34 | } 35 | 36 | void loop() { 37 | //nothing to do! 38 | } 39 | 40 | void dumpRAWBUF() { 41 | Serial.print(F("RAWBUF: ")); 42 | Serial.println(RAWBUF); 43 | } 44 | 45 | void dumpTIMER() { 46 | boolean flag = false; 47 | #ifdef IR_USE_TIMER1 48 | Serial.print(F("Timer defined for use: ")); Serial.println(F("Timer1")); flag = true; 49 | #endif 50 | #ifdef IR_USE_TIMER2 51 | Serial.print(F("Timer defined for use: ")); Serial.println(F("Timer2")); flag = true; 52 | #endif 53 | #ifdef IR_USE_TIMER3 54 | Serial.print(F("Timer defined for use: ")); Serial.println(F("Timer3")); flag = true; 55 | #endif 56 | #ifdef IR_USE_TIMER4 57 | Serial.print(F("Timer defined for use: ")); Serial.println(F("Timer4")); flag = true; 58 | #endif 59 | #ifdef IR_USE_TIMER5 60 | Serial.print(F("Timer defined for use: ")); Serial.println(F("Timer5")); flag = true; 61 | #endif 62 | #ifdef IR_USE_TIMER4_HS 63 | Serial.print(F("Timer defined for use: ")); Serial.println(F("Timer4_HS")); flag = true; 64 | #endif 65 | #ifdef IR_USE_TIMER_CMT 66 | Serial.print(F("Timer defined for use: ")); Serial.println(F("Timer_CMT")); flag = true; 67 | #endif 68 | #ifdef IR_USE_TIMER_TPM1 69 | Serial.print(F("Timer defined for use: ")); Serial.println(F("Timer_TPM1")); flag = true; 70 | #endif 71 | #ifdef IR_USE_TIMER_TINY0 72 | Serial.print(F("Timer defined for use: ")); Serial.println(F("Timer_TINY0")); flag = true; 73 | #endif 74 | 75 | if (!flag) { 76 | Serial.print(F("Timer Error: ")); Serial.println(F("not defined")); 77 | } 78 | } 79 | 80 | void dumpTimerPin() { 81 | Serial.print(F("IR Tx Pin: ")); 82 | Serial.println(TIMER_PWM_PIN); 83 | } 84 | 85 | void dumpClock() { 86 | Serial.print(F("MCU Clock: ")); 87 | Serial.println(F_CPU); 88 | } 89 | 90 | void dumpPlatform() { 91 | Serial.print(F("MCU Platform: ")); 92 | 93 | #if defined(__AVR_ATmega1280__) 94 | Serial.println(F("Arduino Mega1280")); 95 | #elif defined(__AVR_ATmega2560__) 96 | Serial.println(F("Arduino Mega2560")); 97 | #elif defined(__AVR_AT90USB162__) 98 | Serial.println(F("Teensy 1.0 / AT90USB162")); 99 | // Teensy 2.0 100 | #elif defined(__AVR_ATmega32U4__) 101 | Serial.println(F("Arduino Leonardo / Yun / Teensy 1.0 / ATmega32U4")); 102 | #elif defined(__MK20DX128__) || defined(__MK20DX256__) 103 | Serial.println(F("Teensy 3.0 / Teensy 3.1 / MK20DX128 / MK20DX256")); 104 | #elif defined(__MKL26Z64__) 105 | Serial.println(F("Teensy-LC / MKL26Z64")); 106 | #elif defined(__AVR_AT90USB646__) 107 | Serial.println(F("Teensy++ 1.0 / AT90USB646")); 108 | #elif defined(__AVR_AT90USB1286__) 109 | Serial.println(F("Teensy++ 2.0 / AT90USB1286")); 110 | #elif defined(__AVR_ATmega1284__) || defined(__AVR_ATmega1284P__) 111 | Serial.println(F("ATmega1284")); 112 | #elif defined(__AVR_ATmega644__) || defined(__AVR_ATmega644P__) 113 | Serial.println(F("ATmega644")); 114 | #elif defined(__AVR_ATmega324P__) || defined(__AVR_ATmega324A__) || defined(__AVR_ATmega324PA__) 115 | Serial.println(F("ATmega324")); 116 | #elif defined(__AVR_ATmega164A__) || defined(__AVR_ATmega164P__) 117 | Serial.println(F("ATmega164")); 118 | #elif defined(__AVR_ATmega128__) 119 | Serial.println(F("ATmega128")); 120 | #elif defined(__AVR_ATmega88__) || defined(__AVR_ATmega88P__) 121 | Serial.println(F("ATmega88")); 122 | #elif defined(__AVR_ATmega64__) 123 | Serial.println(F("ATmega64")); 124 | #elif defined(__AVR_ATmega48__) || defined(__AVR_ATmega48P__) 125 | Serial.println(F("ATmega48")); 126 | #elif defined(__AVR_ATmega32__) 127 | Serial.println(F("ATmega32")); 128 | #elif defined(__AVR_ATmega16__) 129 | Serial.println(F("ATmega16")); 130 | #elif defined(__AVR_ATmega8535__) 131 | Serial.println(F("ATmega8535")); 132 | #elif defined(__AVR_ATmega8__) 133 | Serial.println(F("Atmega8")); 134 | #elif defined(__AVR_ATtiny84__) 135 | Serial.println(F("ATtiny84")); 136 | #elif defined(__AVR_ATtiny85__) 137 | Serial.println(F("ATtiny85")); 138 | #else 139 | Serial.println(F("ATmega328(P) / (Duemilanove, Diecimila, LilyPad, Mini, Micro, Fio, Nano, etc)")); 140 | #endif 141 | } 142 | 143 | void dumpPulseParams() { 144 | Serial.print(F("Mark Excess: ")); Serial.print(MARK_EXCESS);; Serial.println(F(" uSecs")); 145 | Serial.print(F("Microseconds per tick: ")); Serial.print(USECPERTICK);; Serial.println(F(" uSecs")); 146 | Serial.print(F("Measurement tolerance: ")); Serial.print(TOLERANCE); Serial.println(F("%")); 147 | } 148 | 149 | void dumpSignalParams() { 150 | Serial.print(F("Minimum Gap between IR Signals: ")); Serial.print(_GAP); Serial.println(F(" uSecs")); 151 | } 152 | 153 | void dumpDebugMode() { 154 | Serial.print(F("Debug Mode: ")); 155 | #if DEBUG 156 | Serial.println(F("ON")); 157 | #else 158 | Serial.println(F("OFF (Normal)")); 159 | #endif 160 | 161 | } 162 | 163 | void dumpArduinoIDE() { 164 | Serial.print(F("Arduino IDE version: ")); 165 | Serial.print(ARDUINO / 10000); 166 | Serial.write('.'); 167 | Serial.print((ARDUINO % 10000) / 100); 168 | Serial.write('.'); 169 | Serial.println(ARDUINO % 100); 170 | } 171 | 172 | void dumpProtocols() { 173 | 174 | Serial.println(); Serial.print(F("IR PROTOCOLS ")); Serial.print(F("SEND ")); Serial.println(F("DECODE")); 175 | Serial.print(F("============= ")); Serial.print(F("======== ")); Serial.println(F("========")); 176 | Serial.print(F("RC5: ")); printSendEnabled(SEND_RC5); printDecodeEnabled(DECODE_RC6); 177 | Serial.print(F("RC6: ")); printSendEnabled(SEND_RC6); printDecodeEnabled(DECODE_RC5); 178 | Serial.print(F("NEC: ")); printSendEnabled(SEND_NEC); printDecodeEnabled(DECODE_NEC); 179 | Serial.print(F("SONY: ")); printSendEnabled(SEND_SONY); printDecodeEnabled(DECODE_SONY); 180 | Serial.print(F("PANASONIC: ")); printSendEnabled(SEND_PANASONIC); printDecodeEnabled(DECODE_PANASONIC); 181 | Serial.print(F("JVC: ")); printSendEnabled(SEND_JVC); printDecodeEnabled(DECODE_JVC); 182 | Serial.print(F("SAMSUNG: ")); printSendEnabled(SEND_SAMSUNG); printDecodeEnabled(DECODE_SAMSUNG); 183 | Serial.print(F("WHYNTER: ")); printSendEnabled(SEND_WHYNTER); printDecodeEnabled(DECODE_WHYNTER); 184 | Serial.print(F("AIWA_RC_T501: ")); printSendEnabled(SEND_AIWA_RC_T501); printDecodeEnabled(DECODE_AIWA_RC_T501); 185 | Serial.print(F("LG: ")); printSendEnabled(SEND_LG); printDecodeEnabled(DECODE_LG); 186 | Serial.print(F("SANYO: ")); printSendEnabled(SEND_SANYO); printDecodeEnabled(DECODE_SANYO); 187 | Serial.print(F("MITSUBISHI: ")); printSendEnabled(SEND_MITSUBISHI); printDecodeEnabled(DECODE_MITSUBISHI); 188 | Serial.print(F("DISH: ")); printSendEnabled(SEND_DISH); printDecodeEnabled(DECODE_DISH); 189 | Serial.print(F("SHARP: ")); printSendEnabled(SEND_SHARP); printDecodeEnabled(DECODE_SHARP); 190 | Serial.print(F("DENON: ")); printSendEnabled(SEND_DENON); printDecodeEnabled(DECODE_DENON); 191 | Serial.print(F("PRONTO: ")); printSendEnabled(SEND_PRONTO); Serial.println(F("(Not Applicable)")); 192 | } 193 | 194 | void printSendEnabled(int flag) { 195 | if (flag) { 196 | Serial.print(F("Enabled ")); 197 | } 198 | else { 199 | Serial.print(F("Disabled ")); 200 | } 201 | } 202 | 203 | void printDecodeEnabled(int flag) { 204 | if (flag) { 205 | Serial.println(F("Enabled")); 206 | } 207 | else { 208 | Serial.println(F("Disabled")); 209 | } 210 | } 211 | 212 | void dumpHeader() { 213 | Serial.println(F("IRremoteInfo - by AnalysIR (http://www.AnalysIR.com/)")); 214 | Serial.println(F(" - A helper sketch to assist in troubleshooting issues with the library by reviewing the settings within the IRremote library")); 215 | Serial.println(F(" - Prints out the important settings within the library, which can be configured to suit the many supported platforms")); 216 | Serial.println(F(" - When seeking on-line support, please post or upload the output of this sketch, where appropriate")); 217 | Serial.println(); 218 | Serial.println(F("IRremote Library Settings")); 219 | Serial.println(F("=========================")); 220 | } 221 | 222 | void dumpFooter() { 223 | Serial.println(); 224 | Serial.println(F("Notes: ")); 225 | Serial.println(F(" - Most of the seetings above can be configured in the following files included as part of the library")); 226 | Serial.println(F(" - IRremteInt.h")); 227 | Serial.println(F(" - IRremote.h")); 228 | Serial.println(F(" - You can save SRAM by disabling the Decode or Send features for any protocol (Near the top of IRremoteInt.h)")); 229 | Serial.println(F(" - Some Timer conflicts, with other libraries, can be easily resolved by configuring a differnt Timer for your platform")); 230 | } 231 | -------------------------------------------------------------------------------- /examples/IRsendDemo/IRsendDemo.ino: -------------------------------------------------------------------------------- 1 | /* 2 | * IRremote: IRsendDemo - demonstrates sending IR codes with IRsend 3 | * An IR LED must be connected to Arduino PWM pin 3. 4 | * Version 0.1 July, 2009 5 | * Copyright 2009 Ken Shirriff 6 | * http://arcfn.com 7 | */ 8 | 9 | 10 | #include 11 | 12 | IRsend irsend; 13 | 14 | void setup() 15 | { 16 | } 17 | 18 | void loop() { 19 | for (int i = 0; i < 3; i++) { 20 | irsend.sendSony(0xa90, 12); 21 | delay(40); 22 | } 23 | delay(5000); //5 second delay between each signal burst 24 | } 25 | -------------------------------------------------------------------------------- /examples/IRsendRawDemo/IRsendRawDemo.ino: -------------------------------------------------------------------------------- 1 | /* 2 | * IRremote: IRsendRawDemo - demonstrates sending IR codes with sendRaw 3 | * An IR LED must be connected to Arduino PWM pin 3. 4 | * Version 0.1 July, 2009 5 | * Copyright 2009 Ken Shirriff 6 | * http://arcfn.com 7 | * 8 | * IRsendRawDemo - added by AnalysIR (via www.AnalysIR.com), 24 August 2015 9 | * 10 | * This example shows how to send a RAW signal using the IRremote library. 11 | * The example signal is actually a 32 bit NEC signal. 12 | * Remote Control button: LGTV Power On/Off. 13 | * Hex Value: 0x20DF10EF, 32 bits 14 | * 15 | * It is more efficient to use the sendNEC function to send NEC signals. 16 | * Use of sendRaw here, serves only as an example of using the function. 17 | * 18 | */ 19 | 20 | 21 | #include 22 | 23 | IRsend irsend; 24 | 25 | void setup() 26 | { 27 | 28 | } 29 | 30 | void loop() { 31 | int khz = 38; // 38kHz carrier frequency for the NEC protocol 32 | unsigned int irSignal[] = {9000, 4500, 560, 560, 560, 560, 560, 1690, 560, 560, 560, 560, 560, 560, 560, 560, 560, 560, 560, 1690, 560, 1690, 560, 560, 560, 1690, 560, 1690, 560, 1690, 560, 1690, 560, 1690, 560, 560, 560, 560, 560, 560, 560, 1690, 560, 560, 560, 560, 560, 560, 560, 560, 560, 1690, 560, 1690, 560, 1690, 560, 560, 560, 1690, 560, 1690, 560, 1690, 560, 1690, 560, 39416, 9000, 2210, 560}; //AnalysIR Batch Export (IRremote) - RAW 33 | 34 | irsend.sendRaw(irSignal, sizeof(irSignal) / sizeof(irSignal[0]), khz); //Note the approach used to automatically calculate the size of the array. 35 | 36 | delay(5000); //In this example, the signal will be repeated every 5 seconds, approximately. 37 | } 38 | -------------------------------------------------------------------------------- /examples/IRtest/IRtest.ino: -------------------------------------------------------------------------------- 1 | /* 2 | * IRremote: IRtest unittest 3 | * Version 0.1 July, 2009 4 | * Copyright 2009 Ken Shirriff 5 | * http://arcfn.com 6 | * 7 | * Note: to run these tests, edit IRremote/IRremote.h to add "#define TEST" 8 | * You must then recompile the library by removing IRremote.o and restarting 9 | * the arduino IDE. 10 | */ 11 | 12 | #include 13 | #include 14 | 15 | // Dumps out the decode_results structure. 16 | // Call this after IRrecv::decode() 17 | // void * to work around compiler issue 18 | //void dump(void *v) { 19 | // decode_results *results = (decode_results *)v 20 | void dump(decode_results *results) { 21 | int count = results->rawlen; 22 | if (results->decode_type == UNKNOWN) { 23 | Serial.println("Could not decode message"); 24 | } 25 | else { 26 | if (results->decode_type == NEC) { 27 | Serial.print("Decoded NEC: "); 28 | } 29 | else if (results->decode_type == SONY) { 30 | Serial.print("Decoded SONY: "); 31 | } 32 | else if (results->decode_type == RC5) { 33 | Serial.print("Decoded RC5: "); 34 | } 35 | else if (results->decode_type == RC6) { 36 | Serial.print("Decoded RC6: "); 37 | } 38 | Serial.print(results->value, HEX); 39 | Serial.print(" ("); 40 | Serial.print(results->bits, DEC); 41 | Serial.println(" bits)"); 42 | } 43 | Serial.print("Raw ("); 44 | Serial.print(count, DEC); 45 | Serial.print("): "); 46 | 47 | for (int i = 0; i < count; i++) { 48 | if ((i % 2) == 1) { 49 | Serial.print(results->rawbuf[i]*USECPERTICK, DEC); 50 | } 51 | else { 52 | Serial.print(-(int)results->rawbuf[i]*USECPERTICK, DEC); 53 | } 54 | Serial.print(" "); 55 | } 56 | Serial.println(""); 57 | } 58 | 59 | IRrecv irrecv(0); 60 | decode_results results; 61 | 62 | class IRsendDummy : 63 | public IRsend 64 | { 65 | public: 66 | // For testing, just log the marks/spaces 67 | #define SENDLOG_LEN 128 68 | int sendlog[SENDLOG_LEN]; 69 | int sendlogcnt; 70 | IRsendDummy() : 71 | IRsend() { 72 | } 73 | void reset() { 74 | sendlogcnt = 0; 75 | } 76 | void mark(int time) { 77 | sendlog[sendlogcnt] = time; 78 | if (sendlogcnt < SENDLOG_LEN) sendlogcnt++; 79 | } 80 | void space(int time) { 81 | sendlog[sendlogcnt] = -time; 82 | if (sendlogcnt < SENDLOG_LEN) sendlogcnt++; 83 | } 84 | // Copies the dummy buf into the interrupt buf 85 | void useDummyBuf() { 86 | int last = SPACE; 87 | irparams.rcvstate = STATE_STOP; 88 | irparams.rawlen = 1; // Skip the gap 89 | for (int i = 0 ; i < sendlogcnt; i++) { 90 | if (sendlog[i] < 0) { 91 | if (last == MARK) { 92 | // New space 93 | irparams.rawbuf[irparams.rawlen++] = (-sendlog[i] - MARK_EXCESS) / USECPERTICK; 94 | last = SPACE; 95 | } 96 | else { 97 | // More space 98 | irparams.rawbuf[irparams.rawlen - 1] += -sendlog[i] / USECPERTICK; 99 | } 100 | } 101 | else if (sendlog[i] > 0) { 102 | if (last == SPACE) { 103 | // New mark 104 | irparams.rawbuf[irparams.rawlen++] = (sendlog[i] + MARK_EXCESS) / USECPERTICK; 105 | last = MARK; 106 | } 107 | else { 108 | // More mark 109 | irparams.rawbuf[irparams.rawlen - 1] += sendlog[i] / USECPERTICK; 110 | } 111 | } 112 | } 113 | if (irparams.rawlen % 2) { 114 | irparams.rawlen--; // Remove trailing space 115 | } 116 | } 117 | }; 118 | 119 | IRsendDummy irsenddummy; 120 | 121 | void verify(unsigned long val, int bits, int type) { 122 | irsenddummy.useDummyBuf(); 123 | irrecv.decode(&results); 124 | Serial.print("Testing "); 125 | Serial.print(val, HEX); 126 | if (results.value == val && results.bits == bits && results.decode_type == type) { 127 | Serial.println(": OK"); 128 | } 129 | else { 130 | Serial.println(": Error"); 131 | dump(&results); 132 | } 133 | } 134 | 135 | void testNEC(unsigned long val, int bits) { 136 | irsenddummy.reset(); 137 | irsenddummy.sendNEC(val, bits); 138 | verify(val, bits, NEC); 139 | } 140 | void testSony(unsigned long val, int bits) { 141 | irsenddummy.reset(); 142 | irsenddummy.sendSony(val, bits); 143 | verify(val, bits, SONY); 144 | } 145 | void testRC5(unsigned long val, int bits) { 146 | irsenddummy.reset(); 147 | irsenddummy.sendRC5(val, bits); 148 | verify(val, bits, RC5); 149 | } 150 | void testRC6(unsigned long val, int bits) { 151 | irsenddummy.reset(); 152 | irsenddummy.sendRC6(val, bits); 153 | verify(val, bits, RC6); 154 | } 155 | 156 | void test() { 157 | Serial.println("NEC tests"); 158 | testNEC(0x00000000, 32); 159 | testNEC(0xffffffff, 32); 160 | testNEC(0xaaaaaaaa, 32); 161 | testNEC(0x55555555, 32); 162 | testNEC(0x12345678, 32); 163 | Serial.println("Sony tests"); 164 | testSony(0xfff, 12); 165 | testSony(0x000, 12); 166 | testSony(0xaaa, 12); 167 | testSony(0x555, 12); 168 | testSony(0x123, 12); 169 | Serial.println("RC5 tests"); 170 | testRC5(0xfff, 12); 171 | testRC5(0x000, 12); 172 | testRC5(0xaaa, 12); 173 | testRC5(0x555, 12); 174 | testRC5(0x123, 12); 175 | Serial.println("RC6 tests"); 176 | testRC6(0xfffff, 20); 177 | testRC6(0x00000, 20); 178 | testRC6(0xaaaaa, 20); 179 | testRC6(0x55555, 20); 180 | testRC6(0x12345, 20); 181 | } 182 | 183 | void setup() 184 | { 185 | Serial.begin(9600); 186 | test(); 187 | } 188 | 189 | void loop() { 190 | } 191 | -------------------------------------------------------------------------------- /examples/IRtest2/IRtest2.ino: -------------------------------------------------------------------------------- 1 | /* 2 | * Test send/receive functions of IRremote, using a pair of Arduinos. 3 | * 4 | * Arduino #1 should have an IR LED connected to the send pin (3). 5 | * Arduino #2 should have an IR detector/demodulator connected to the 6 | * receive pin (11) and a visible LED connected to pin 3. 7 | * 8 | * The cycle: 9 | * Arduino #1 will wait 2 seconds, then run through the tests. 10 | * It repeats this forever. 11 | * Arduino #2 will wait for at least one second of no signal 12 | * (to synchronize with #1). It will then wait for the same test 13 | * signals. It will log all the status to the serial port. It will 14 | * also indicate status through the LED, which will flash each time a test 15 | * is completed. If there is an error, it will light up for 5 seconds. 16 | * 17 | * The test passes if the LED flashes 19 times, pauses, and then repeats. 18 | * The test fails if the LED lights for 5 seconds. 19 | * 20 | * The test software automatically decides which board is the sender and which is 21 | * the receiver by looking for an input on the send pin, which will indicate 22 | * the sender. You should hook the serial port to the receiver for debugging. 23 | * 24 | * Copyright 2010 Ken Shirriff 25 | * http://arcfn.com 26 | */ 27 | 28 | #include 29 | 30 | int RECV_PIN = 11; 31 | int LED_PIN = 3; 32 | 33 | IRrecv irrecv(RECV_PIN); 34 | IRsend irsend; 35 | 36 | decode_results results; 37 | 38 | #define RECEIVER 1 39 | #define SENDER 2 40 | #define ERROR 3 41 | 42 | int mode; 43 | 44 | void setup() 45 | { 46 | Serial.begin(9600); 47 | // Check RECV_PIN to decide if we're RECEIVER or SENDER 48 | if (digitalRead(RECV_PIN) == HIGH) { 49 | mode = RECEIVER; 50 | irrecv.enableIRIn(); 51 | pinMode(LED_PIN, OUTPUT); 52 | digitalWrite(LED_PIN, LOW); 53 | Serial.println("Receiver mode"); 54 | } 55 | else { 56 | mode = SENDER; 57 | Serial.println("Sender mode"); 58 | } 59 | } 60 | 61 | // Wait for the gap between tests, to synchronize with 62 | // the sender. 63 | // Specifically, wait for a signal followed by a gap of at last gap ms. 64 | void waitForGap(unsigned long gap) { 65 | Serial.println("Waiting for gap"); 66 | while (1) { 67 | while (digitalRead(RECV_PIN) == LOW) { 68 | } 69 | unsigned long time = millis(); 70 | while (digitalRead(RECV_PIN) == HIGH) { 71 | if (millis() - time > gap) { 72 | return; 73 | } 74 | } 75 | } 76 | } 77 | 78 | // Dumps out the decode_results structure. 79 | // Call this after IRrecv::decode() 80 | void dump(decode_results *results) { 81 | int count = results->rawlen; 82 | if (results->decode_type == UNKNOWN) { 83 | Serial.println("Could not decode message"); 84 | } 85 | else { 86 | if (results->decode_type == NEC) { 87 | Serial.print("Decoded NEC: "); 88 | } 89 | else if (results->decode_type == SONY) { 90 | Serial.print("Decoded SONY: "); 91 | } 92 | else if (results->decode_type == RC5) { 93 | Serial.print("Decoded RC5: "); 94 | } 95 | else if (results->decode_type == RC6) { 96 | Serial.print("Decoded RC6: "); 97 | } 98 | Serial.print(results->value, HEX); 99 | Serial.print(" ("); 100 | Serial.print(results->bits, DEC); 101 | Serial.println(" bits)"); 102 | } 103 | Serial.print("Raw ("); 104 | Serial.print(count, DEC); 105 | Serial.print("): "); 106 | 107 | for (int i = 0; i < count; i++) { 108 | if ((i % 2) == 1) { 109 | Serial.print(results->rawbuf[i]*USECPERTICK, DEC); 110 | } 111 | else { 112 | Serial.print(-(int)results->rawbuf[i]*USECPERTICK, DEC); 113 | } 114 | Serial.print(" "); 115 | } 116 | Serial.println(""); 117 | } 118 | 119 | 120 | // Test send or receive. 121 | // If mode is SENDER, send a code of the specified type, value, and bits 122 | // If mode is RECEIVER, receive a code and verify that it is of the 123 | // specified type, value, and bits. For success, the LED is flashed; 124 | // for failure, the mode is set to ERROR. 125 | // The motivation behind this method is that the sender and the receiver 126 | // can do the same test calls, and the mode variable indicates whether 127 | // to send or receive. 128 | void test(const char *label, int type, unsigned long value, int bits) { 129 | if (mode == SENDER) { 130 | Serial.println(label); 131 | if (type == NEC) { 132 | irsend.sendNEC(value, bits); 133 | } 134 | else if (type == SONY) { 135 | irsend.sendSony(value, bits); 136 | } 137 | else if (type == RC5) { 138 | irsend.sendRC5(value, bits); 139 | } 140 | else if (type == RC6) { 141 | irsend.sendRC6(value, bits); 142 | } 143 | else { 144 | Serial.print(label); 145 | Serial.println("Bad type!"); 146 | } 147 | delay(200); 148 | } 149 | else if (mode == RECEIVER) { 150 | irrecv.resume(); // Receive the next value 151 | unsigned long max_time = millis() + 30000; 152 | Serial.print(label); 153 | 154 | // Wait for decode or timeout 155 | while (!irrecv.decode(&results)) { 156 | if (millis() > max_time) { 157 | Serial.println("Timeout receiving data"); 158 | mode = ERROR; 159 | return; 160 | } 161 | } 162 | if (type == results.decode_type && value == results.value && bits == results.bits) { 163 | Serial.println (": OK"); 164 | digitalWrite(LED_PIN, HIGH); 165 | delay(20); 166 | digitalWrite(LED_PIN, LOW); 167 | } 168 | else { 169 | Serial.println(": BAD"); 170 | dump(&results); 171 | mode = ERROR; 172 | } 173 | } 174 | } 175 | 176 | // Test raw send or receive. This is similar to the test method, 177 | // except it send/receives raw data. 178 | void testRaw(const char *label, unsigned int *rawbuf, int rawlen) { 179 | if (mode == SENDER) { 180 | Serial.println(label); 181 | irsend.sendRaw(rawbuf, rawlen, 38 /* kHz */); 182 | delay(200); 183 | } 184 | else if (mode == RECEIVER ) { 185 | irrecv.resume(); // Receive the next value 186 | unsigned long max_time = millis() + 30000; 187 | Serial.print(label); 188 | 189 | // Wait for decode or timeout 190 | while (!irrecv.decode(&results)) { 191 | if (millis() > max_time) { 192 | Serial.println("Timeout receiving data"); 193 | mode = ERROR; 194 | return; 195 | } 196 | } 197 | 198 | // Received length has extra first element for gap 199 | if (rawlen != results.rawlen - 1) { 200 | Serial.print("Bad raw length "); 201 | Serial.println(results.rawlen, DEC); 202 | mode = ERROR; 203 | return; 204 | } 205 | for (int i = 0; i < rawlen; i++) { 206 | long got = results.rawbuf[i+1] * USECPERTICK; 207 | // Adjust for extra duration of marks 208 | if (i % 2 == 0) { 209 | got -= MARK_EXCESS; 210 | } 211 | else { 212 | got += MARK_EXCESS; 213 | } 214 | // See if close enough, within 25% 215 | if (rawbuf[i] * 1.25 < got || got * 1.25 < rawbuf[i]) { 216 | Serial.println(": BAD"); 217 | dump(&results); 218 | mode = ERROR; 219 | return; 220 | } 221 | 222 | } 223 | Serial.println (": OK"); 224 | digitalWrite(LED_PIN, HIGH); 225 | delay(20); 226 | digitalWrite(LED_PIN, LOW); 227 | } 228 | } 229 | 230 | // This is the raw data corresponding to NEC 0x12345678 231 | unsigned int sendbuf[] = { /* NEC format */ 232 | 9000, 4500, 233 | 560, 560, 560, 560, 560, 560, 560, 1690, /* 1 */ 234 | 560, 560, 560, 560, 560, 1690, 560, 560, /* 2 */ 235 | 560, 560, 560, 560, 560, 1690, 560, 1690, /* 3 */ 236 | 560, 560, 560, 1690, 560, 560, 560, 560, /* 4 */ 237 | 560, 560, 560, 1690, 560, 560, 560, 1690, /* 5 */ 238 | 560, 560, 560, 1690, 560, 1690, 560, 560, /* 6 */ 239 | 560, 560, 560, 1690, 560, 1690, 560, 1690, /* 7 */ 240 | 560, 1690, 560, 560, 560, 560, 560, 560, /* 8 */ 241 | 560}; 242 | 243 | void loop() { 244 | if (mode == SENDER) { 245 | delay(2000); // Delay for more than gap to give receiver a better chance to sync. 246 | } 247 | else if (mode == RECEIVER) { 248 | waitForGap(1000); 249 | } 250 | else if (mode == ERROR) { 251 | // Light up for 5 seconds for error 252 | digitalWrite(LED_PIN, HIGH); 253 | delay(5000); 254 | digitalWrite(LED_PIN, LOW); 255 | mode = RECEIVER; // Try again 256 | return; 257 | } 258 | 259 | // The test suite. 260 | test("SONY1", SONY, 0x123, 12); 261 | test("SONY2", SONY, 0x000, 12); 262 | test("SONY3", SONY, 0xfff, 12); 263 | test("SONY4", SONY, 0x12345, 20); 264 | test("SONY5", SONY, 0x00000, 20); 265 | test("SONY6", SONY, 0xfffff, 20); 266 | test("NEC1", NEC, 0x12345678, 32); 267 | test("NEC2", NEC, 0x00000000, 32); 268 | test("NEC3", NEC, 0xffffffff, 32); 269 | test("NEC4", NEC, REPEAT, 32); 270 | test("RC51", RC5, 0x12345678, 32); 271 | test("RC52", RC5, 0x0, 32); 272 | test("RC53", RC5, 0xffffffff, 32); 273 | test("RC61", RC6, 0x12345678, 32); 274 | test("RC62", RC6, 0x0, 32); 275 | test("RC63", RC6, 0xffffffff, 32); 276 | 277 | // Tests of raw sending and receiving. 278 | // First test sending raw and receiving raw. 279 | // Then test sending raw and receiving decoded NEC 280 | // Then test sending NEC and receiving raw 281 | testRaw("RAW1", sendbuf, 67); 282 | if (mode == SENDER) { 283 | testRaw("RAW2", sendbuf, 67); 284 | test("RAW3", NEC, 0x12345678, 32); 285 | } 286 | else { 287 | test("RAW2", NEC, 0x12345678, 32); 288 | testRaw("RAW3", sendbuf, 67); 289 | } 290 | } 291 | -------------------------------------------------------------------------------- /examples/JVCPanasonicSendDemo/JVCPanasonicSendDemo.ino: -------------------------------------------------------------------------------- 1 | /* 2 | * IRremote: IRsendDemo - demonstrates sending IR codes with IRsend 3 | * An IR LED must be connected to Arduino PWM pin 3. 4 | * Version 0.1 July, 2009 5 | * Copyright 2009 Ken Shirriff 6 | * http://arcfn.com 7 | * JVC and Panasonic protocol added by Kristian Lauszus (Thanks to zenwheel and other people at the original blog post) 8 | */ 9 | #include 10 | 11 | #define PanasonicAddress 0x4004 // Panasonic address (Pre data) 12 | #define PanasonicPower 0x100BCBD // Panasonic Power button 13 | 14 | #define JVCPower 0xC5E8 15 | 16 | IRsend irsend; 17 | 18 | void setup() 19 | { 20 | } 21 | 22 | void loop() { 23 | irsend.sendPanasonic(PanasonicAddress,PanasonicPower); // This should turn your TV on and off 24 | 25 | irsend.sendJVC(JVCPower, 16,0); // hex value, 16 bits, no repeat 26 | delayMicroseconds(50); // see http://www.sbprojects.com/knowledge/ir/jvc.php for information 27 | irsend.sendJVC(JVCPower, 16,1); // hex value, 16 bits, repeat 28 | delayMicroseconds(50); 29 | } 30 | -------------------------------------------------------------------------------- /examples/LGACSendDemo/LGACSendDemo.ino: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | 5 | IRsend irsend; 6 | // not used 7 | int RECV_PIN = 11; 8 | IRrecv irrecv (RECV_PIN); 9 | 10 | const int AC_TYPE = 0; 11 | // 0 : TOWER 12 | // 1 : WALL 13 | // 14 | 15 | int AC_HEAT = 0; 16 | // 0 : cooling 17 | // 1 : heating 18 | 19 | int AC_POWER_ON = 0; 20 | // 0 : off 21 | // 1 : on 22 | 23 | int AC_AIR_ACLEAN = 0; 24 | // 0 : off 25 | // 1 : on --> power on 26 | 27 | int AC_TEMPERATURE = 27; 28 | // temperature : 18 ~ 30 29 | 30 | int AC_FLOW = 1; 31 | // 0 : low 32 | // 1 : mid 33 | // 2 : high 34 | // if AC_TYPE =1, 3 : change 35 | // 36 | 37 | 38 | const int AC_FLOW_TOWER[3] = {0, 4, 6}; 39 | const int AC_FLOW_WALL[4] = {0, 2, 4, 5}; 40 | 41 | unsigned long AC_CODE_TO_SEND; 42 | 43 | int r = LOW; 44 | int o_r = LOW; 45 | 46 | byte a, b; 47 | 48 | void ac_send_code(unsigned long code) 49 | { 50 | Serial.print("code to send : "); 51 | Serial.print(code, BIN); 52 | Serial.print(" : "); 53 | Serial.println(code, HEX); 54 | 55 | irsend.sendLG(code, 28); 56 | } 57 | 58 | void ac_activate(int temperature, int air_flow) 59 | { 60 | 61 | int AC_MSBITS1 = 8; 62 | int AC_MSBITS2 = 8; 63 | int AC_MSBITS3 = 0; 64 | int AC_MSBITS4 ; 65 | if ( AC_HEAT == 1 ) { 66 | // heating 67 | AC_MSBITS4 = 4; 68 | } else { 69 | // cooling 70 | AC_MSBITS4 = 0; 71 | } 72 | int AC_MSBITS5 = temperature - 15; 73 | int AC_MSBITS6 ; 74 | 75 | if ( AC_TYPE == 0) { 76 | AC_MSBITS6 = AC_FLOW_TOWER[air_flow]; 77 | } else { 78 | AC_MSBITS6 = AC_FLOW_WALL[air_flow]; 79 | } 80 | 81 | int AC_MSBITS7 = (AC_MSBITS3 + AC_MSBITS4 + AC_MSBITS5 + AC_MSBITS6) & B00001111; 82 | 83 | AC_CODE_TO_SEND = AC_MSBITS1 << 4 ; 84 | AC_CODE_TO_SEND = (AC_CODE_TO_SEND + AC_MSBITS2) << 4; 85 | AC_CODE_TO_SEND = (AC_CODE_TO_SEND + AC_MSBITS3) << 4; 86 | AC_CODE_TO_SEND = (AC_CODE_TO_SEND + AC_MSBITS4) << 4; 87 | AC_CODE_TO_SEND = (AC_CODE_TO_SEND + AC_MSBITS5) << 4; 88 | AC_CODE_TO_SEND = (AC_CODE_TO_SEND + AC_MSBITS6) << 4; 89 | AC_CODE_TO_SEND = (AC_CODE_TO_SEND + AC_MSBITS7); 90 | 91 | ac_send_code(AC_CODE_TO_SEND); 92 | 93 | AC_POWER_ON = 1; 94 | AC_TEMPERATURE = temperature; 95 | AC_FLOW = air_flow; 96 | } 97 | 98 | void ac_change_air_swing(int air_swing) 99 | { 100 | if ( AC_TYPE == 0) { 101 | if ( air_swing == 1) { 102 | AC_CODE_TO_SEND = 0x881316B; 103 | } else { 104 | AC_CODE_TO_SEND = 0x881317C; 105 | } 106 | } else { 107 | if ( air_swing == 1) { 108 | AC_CODE_TO_SEND = 0x8813149; 109 | } else { 110 | AC_CODE_TO_SEND = 0x881315A; 111 | } 112 | } 113 | 114 | ac_send_code(AC_CODE_TO_SEND); 115 | } 116 | 117 | void ac_power_down() 118 | { 119 | AC_CODE_TO_SEND = 0x88C0051; 120 | 121 | ac_send_code(AC_CODE_TO_SEND); 122 | 123 | AC_POWER_ON = 0; 124 | } 125 | 126 | void ac_air_clean(int air_clean) 127 | { 128 | if ( air_clean == 1) { 129 | AC_CODE_TO_SEND = 0x88C000C; 130 | } else { 131 | AC_CODE_TO_SEND = 0x88C0084; 132 | } 133 | 134 | ac_send_code(AC_CODE_TO_SEND); 135 | 136 | AC_AIR_ACLEAN = air_clean; 137 | } 138 | 139 | void setup() 140 | { 141 | Serial.begin(38400); 142 | delay(1000); 143 | Wire.begin(7); 144 | Wire.onReceive(receiveEvent); 145 | 146 | Serial.println(" - - - T E S T - - - "); 147 | 148 | /* test 149 | ac_activate(25, 1); 150 | delay(5000); 151 | ac_activate(27, 2); 152 | delay(5000); 153 | 154 | */ 155 | } 156 | 157 | void loop() 158 | { 159 | 160 | 161 | ac_activate(25, 1); 162 | delay(5000); 163 | ac_activate(27, 0); 164 | delay(5000); 165 | 166 | 167 | if ( r != o_r) { 168 | 169 | /* 170 | # a : mode or temp b : air_flow, temp, swing, clean, cooling/heating 171 | # 18 ~ 30 : temp 0 ~ 2 : flow // on 172 | # 0 : off 0 173 | # 1 : on 0 174 | # 2 : air_swing 0 or 1 175 | # 3 : air_clean 0 or 1 176 | # 4 : air_flow 0 ~ 2 : flow 177 | # 5 : temp 18 ~ 30 178 | # + : temp + 1 179 | # - : temp - 1 180 | # m : change cooling to air clean, air clean to cooling 181 | */ 182 | Serial.print("a : "); 183 | Serial.print(a); 184 | Serial.print(" b : "); 185 | Serial.println(b); 186 | 187 | switch (a) { 188 | case 0: // off 189 | ac_power_down(); 190 | break; 191 | case 1: // on 192 | ac_activate(AC_TEMPERATURE, AC_FLOW); 193 | break; 194 | case 2: 195 | if ( b == 0 || b == 1 ) { 196 | ac_change_air_swing(b); 197 | } 198 | break; 199 | case 3: // 1 : clean on, power on 200 | if ( b == 0 || b == 1 ) { 201 | ac_air_clean(b); 202 | } 203 | break; 204 | case 4: 205 | if ( 0 <= b && b <= 2 ) { 206 | ac_activate(AC_TEMPERATURE, b); 207 | } 208 | break; 209 | case 5: 210 | if (18 <= b && b <= 30 ) { 211 | ac_activate(b, AC_FLOW); 212 | } 213 | break; 214 | case '+': 215 | if ( 18 <= AC_TEMPERATURE && AC_TEMPERATURE <= 29 ) { 216 | ac_activate((AC_TEMPERATURE + 1), AC_FLOW); 217 | } 218 | break; 219 | case '-': 220 | if ( 19 <= AC_TEMPERATURE && AC_TEMPERATURE <= 30 ) { 221 | ac_activate((AC_TEMPERATURE - 1), AC_FLOW); 222 | } 223 | break; 224 | case 'm': 225 | /* 226 | if ac is on, 1) turn off, 2) turn on ac_air_clean(1) 227 | if ac is off, 1) turn on, 2) turn off ac_air_clean(0) 228 | */ 229 | if ( AC_POWER_ON == 1 ) { 230 | ac_power_down(); 231 | delay(100); 232 | ac_air_clean(1); 233 | } else { 234 | if ( AC_AIR_ACLEAN == 1) { 235 | ac_air_clean(0); 236 | delay(100); 237 | } 238 | ac_activate(AC_TEMPERATURE, AC_FLOW); 239 | } 240 | break; 241 | default: 242 | if ( 18 <= a && a <= 30 ) { 243 | if ( 0 <= b && b <= 2 ) { 244 | ac_activate(a, b); 245 | } 246 | } 247 | } 248 | 249 | o_r = r ; 250 | } 251 | delay(100); 252 | } 253 | 254 | 255 | 256 | void receiveEvent(int howMany) 257 | { 258 | a = Wire.read(); 259 | b = Wire.read(); 260 | r = !r ; 261 | } 262 | 263 | 264 | -------------------------------------------------------------------------------- /examples/LGACSendDemo/LGACSendDemo.md: -------------------------------------------------------------------------------- 1 | === decoding for LG A/C ==== 2 | - 1) remote of LG AC has two type of HDR mark/space, 8000/4000 and 3100/10000 3 | - 2) HDR 8000/4000 is decoded using decodeLG(IRrecvDumpV2) without problem 4 | - 3) for HDR 3100/10000, use AnalysIR's code : http://www.analysir.com/blog/2014/03/19/air-conditioners-problems-recording-long-infrared-remote-control-signals-arduino/ 5 | - 4) for bin output based on AnalysIR's code : https://gist.github.com/chaeplin/a3a4b4b6b887c663bfe8 6 | - 5) remove first two byte(11) 7 | - 6) sample rawcode with bin output : https://gist.github.com/chaeplin/134d232e0b8cfb898860 8 | 9 | 10 | === *** === 11 | - 1) Sample raw code : https://gist.github.com/chaeplin/ab2a7ad1533c41260f0d 12 | - 2) send raw code : https://gist.github.com/chaeplin/7c800d3166463bb51be4 13 | 14 | 15 | === *** === 16 | - (0) : Cooling or Heating 17 | - (1) : fixed 18 | - (2) : fixed 19 | - (3) : special(power, swing, air clean) 20 | - (4) : change air flow, temperature, cooling(0)/heating(4) 21 | - (5) : temperature ( 15 + (5) = ) 22 | - (6) : air flow 23 | - (7) : crc ( 3 + 4 + 5 + 6 ) & B00001111 24 | 25 | 26 | °F = °C × 1.8 + 32 27 | °C = (°F − 32) / 1.8 28 | 29 | 30 | === *** === 31 | * remote / Korea / without heating 32 | 33 | | status |(0)| (1)| (2)| (3)| (4)| (5)| (6)| (7) 34 | |----------------|---|----|----|----|----|----|----|---- 35 | | on / 25 / mid | C |1000|1000|0000|0000|1010|0010|1100 36 | | on / 26 / mid | C |1000|1000|0000|0000|1011|0010|1101 37 | | on / 27 / mid | C |1000|1000|0000|0000|1100|0010|1110 38 | | on / 28 / mid | C |1000|1000|0000|0000|1101|0010|1111 39 | | on / 25 / high | C |1000|1000|0000|0000|1010|0100|1110 40 | | on / 26 / high | C |1000|1000|0000|0000|1011|0100|1111 41 | | on / 27 / high | C |1000|1000|0000|0000|1100|0100|0000 42 | | on / 28 / high | C |1000|1000|0000|0000|1101|0100|0001 43 | |----------------|---|----|----|----|----|----|----|---- 44 | | 1 up | C |1000|1000|0000|1000|1101|0100|1001 45 | |----------------|---|----|----|----|----|----|----|---- 46 | | Cool power | C |1000|1000|0001|0000|0000|1100|1101 47 | | energy saving | C |1000|1000|0001|0000|0000|0100|0101 48 | | power | C |1000|1000|0001|0000|0000|1000|1001 49 | | flow/up/down | C |1000|1000|0001|0011|0001|0100|1001 50 | | up/down off | C |1000|1000|0001|0011|0001|0101|1010 51 | | flow/left/right| C |1000|1000|0001|0011|0001|0110|1011 52 | | left/right off | C |1000|1000|0001|0011|0001|0111|1100 53 | |----------------|---|----|----|----|----|----|----|---- 54 | | Air clean | C |1000|1000|1100|0000|0000|0000|1100 55 | |----------------|---|----|----|----|----|----|----|---- 56 | | off | C |1000|1000|1100|0000|0000|0101|0001 57 | 58 | 59 | 60 | * remote / with heating 61 | * converted using raw code at https://github.com/chaeplin/RaspAC/blob/master/lircd.conf 62 | 63 | | status |(0)| (1)| (2)| (3)| (4)| (5)| (6)| (7) 64 | |----------------|---|----|----|----|----|----|----|---- 65 | | on | C |1000|1000|0000|0000|1011|0010|1101 66 | |----------------|---|----|----|----|----|----|----|---- 67 | | off | C |1000|1000|1100|0000|0000|0101|0001 68 | |----------------|---|----|----|----|----|----|----|---- 69 | | 64 / 18 | C |1000|1000|0000|0000|0011|0100|0111 70 | | 66 / 19 | C |1000|1000|0000|0000|0100|0100|1000 71 | | 68 / 20 | C |1000|1000|0000|0000|0101|0100|1001 72 | | 70 / 21 | C |1000|1000|0000|0000|0110|0100|1010 73 | | 72 / 22 | C |1000|1000|0000|0000|0111|0100|1011 74 | | 74 / 23 | C |1000|1000|0000|0000|1000|0100|1100 75 | | 76 / 25 | C |1000|1000|0000|0000|1010|0100|1110 76 | | 78 / 26 | C |1000|1000|0000|0000|1011|0100|1111 77 | | 80 / 27 | C |1000|1000|0000|0000|1100|0100|0000 78 | | 82 / 28 | C |1000|1000|0000|0000|1101|0100|0001 79 | | 84 / 29 | C |1000|1000|0000|0000|1110|0100|0010 80 | | 86 / 30 | C |1000|1000|0000|0000|1111|0100|0011 81 | |----------------|---|----|----|----|----|----|----|---- 82 | | heat64 | H |1000|1000|0000|0100|0011|0100|1011 83 | | heat66 | H |1000|1000|0000|0100|0100|0100|1100 84 | | heat68 | H |1000|1000|0000|0100|0101|0100|1101 85 | | heat70 | H |1000|1000|0000|0100|0110|0100|1110 86 | | heat72 | H |1000|1000|0000|0100|0111|0100|1111 87 | | heat74 | H |1000|1000|0000|0100|1000|0100|0000 88 | | heat76 | H |1000|1000|0000|0100|1001|0100|0001 89 | | heat78 | H |1000|1000|0000|0100|1011|0100|0011 90 | | heat80 | H |1000|1000|0000|0100|1100|0100|0100 91 | | heat82 | H |1000|1000|0000|0100|1101|0100|0101 92 | | heat84 | H |1000|1000|0000|0100|1110|0100|0110 93 | | heat86 | H |1000|1000|0000|0100|1111|0100|0111 94 | -------------------------------------------------------------------------------- /examples/LegoPowerFunctionsSendDemo/LegoPowerFunctionsSendDemo.ino: -------------------------------------------------------------------------------- 1 | /* 2 | * LegoPowerFunctionsSendDemo: LEGO Power Functions 3 | * Copyright (c) 2016 Philipp Henkel 4 | */ 5 | 6 | #include 7 | #include 8 | 9 | IRsend irsend; 10 | 11 | void setup() { 12 | } 13 | 14 | void loop() { 15 | // Send repeated command "channel 1, blue forward, red backward" 16 | irsend.sendLegoPowerFunctions(0x197); 17 | delay(2000); 18 | 19 | // Send single command "channel 1, blue forward, red backward" 20 | irsend.sendLegoPowerFunctions(0x197, false); 21 | delay(2000); 22 | } 23 | -------------------------------------------------------------------------------- /examples/LegoPowerFunctionsTests/LegoPowerFunctionsTests.ino: -------------------------------------------------------------------------------- 1 | /* 2 | * LegoPowerFunctionsTest: LEGO Power Functions Tests 3 | * Copyright (c) 2016, 2017 Philipp Henkel 4 | */ 5 | 6 | #include 7 | 8 | void setup() { 9 | Serial.begin(9600); 10 | delay(1000); // wait for reset triggered by serial connection 11 | runBitStreamEncoderTests(); 12 | } 13 | 14 | void loop() { 15 | } 16 | 17 | void runBitStreamEncoderTests() { 18 | Serial.println(); 19 | Serial.println("BitStreamEncoder Tests"); 20 | static LegoPfBitStreamEncoder bitStreamEncoder; 21 | testStartBit(bitStreamEncoder); 22 | testLowBit(bitStreamEncoder); 23 | testHighBit(bitStreamEncoder); 24 | testMessageBitCount(bitStreamEncoder); 25 | testMessageBitCountRepeat(bitStreamEncoder); 26 | testMessage407(bitStreamEncoder); 27 | testMessage407Repeated(bitStreamEncoder); 28 | testGetChannelId1(bitStreamEncoder); 29 | testGetChannelId2(bitStreamEncoder); 30 | testGetChannelId3(bitStreamEncoder); 31 | testGetChannelId4(bitStreamEncoder); 32 | testGetMessageLengthAllHigh(bitStreamEncoder); 33 | testGetMessageLengthAllLow(bitStreamEncoder); 34 | } 35 | 36 | void logTestResult(bool testPassed) { 37 | if (testPassed) { 38 | Serial.println("OK"); 39 | } 40 | else { 41 | Serial.println("FAIL ############"); 42 | } 43 | } 44 | 45 | void testStartBit(LegoPfBitStreamEncoder& bitStreamEncoder) { 46 | Serial.print(" testStartBit "); 47 | bitStreamEncoder.reset(0, false); 48 | int startMark = bitStreamEncoder.getMarkDuration(); 49 | int startPause = bitStreamEncoder.getPauseDuration(); 50 | logTestResult(startMark == 158 && startPause == 1184-158); 51 | } 52 | 53 | void testLowBit(LegoPfBitStreamEncoder& bitStreamEncoder) { 54 | Serial.print(" testLowBit "); 55 | bitStreamEncoder.reset(0, false); 56 | bitStreamEncoder.next(); 57 | int lowMark = bitStreamEncoder.getMarkDuration(); 58 | int lowPause = bitStreamEncoder.getPauseDuration(); 59 | logTestResult(lowMark == 158 && lowPause == 421-158); 60 | } 61 | 62 | void testHighBit(LegoPfBitStreamEncoder& bitStreamEncoder) { 63 | Serial.print(" testHighBit "); 64 | bitStreamEncoder.reset(0xFFFF, false); 65 | bitStreamEncoder.next(); 66 | int highMark = bitStreamEncoder.getMarkDuration(); 67 | int highPause = bitStreamEncoder.getPauseDuration(); 68 | logTestResult(highMark == 158 && highPause == 711-158); 69 | } 70 | 71 | void testMessageBitCount(LegoPfBitStreamEncoder& bitStreamEncoder) { 72 | Serial.print(" testMessageBitCount "); 73 | bitStreamEncoder.reset(0xFFFF, false); 74 | int bitCount = 1; 75 | while (bitStreamEncoder.next()) { 76 | bitCount++; 77 | } 78 | logTestResult(bitCount == 18); 79 | } 80 | 81 | boolean check(LegoPfBitStreamEncoder& bitStreamEncoder, unsigned long markDuration, unsigned long pauseDuration) { 82 | bool result = true; 83 | result = result && bitStreamEncoder.getMarkDuration() == markDuration; 84 | result = result && bitStreamEncoder.getPauseDuration() == pauseDuration; 85 | return result; 86 | } 87 | 88 | boolean checkNext(LegoPfBitStreamEncoder& bitStreamEncoder, unsigned long markDuration, unsigned long pauseDuration) { 89 | bool result = bitStreamEncoder.next(); 90 | result = result && check(bitStreamEncoder, markDuration, pauseDuration); 91 | return result; 92 | } 93 | 94 | boolean checkDataBitsOfMessage407(LegoPfBitStreamEncoder& bitStreamEncoder) { 95 | bool result = true; 96 | result = result && checkNext(bitStreamEncoder, 158, 263); 97 | result = result && checkNext(bitStreamEncoder, 158, 263); 98 | result = result && checkNext(bitStreamEncoder, 158, 263); 99 | result = result && checkNext(bitStreamEncoder, 158, 263); 100 | result = result && checkNext(bitStreamEncoder, 158, 263); 101 | result = result && checkNext(bitStreamEncoder, 158, 263); 102 | result = result && checkNext(bitStreamEncoder, 158, 263); 103 | result = result && checkNext(bitStreamEncoder, 158, 553); 104 | result = result && checkNext(bitStreamEncoder, 158, 553); 105 | result = result && checkNext(bitStreamEncoder, 158, 263); 106 | result = result && checkNext(bitStreamEncoder, 158, 263); 107 | result = result && checkNext(bitStreamEncoder, 158, 553); 108 | result = result && checkNext(bitStreamEncoder, 158, 263); 109 | result = result && checkNext(bitStreamEncoder, 158, 553); 110 | result = result && checkNext(bitStreamEncoder, 158, 553); 111 | result = result && checkNext(bitStreamEncoder, 158, 553); 112 | return result; 113 | } 114 | 115 | void testMessage407(LegoPfBitStreamEncoder& bitStreamEncoder) { 116 | Serial.print(" testMessage407 "); 117 | bitStreamEncoder.reset(407, false); 118 | bool result = true; 119 | result = result && check(bitStreamEncoder, 158, 1026); 120 | result = result && checkDataBitsOfMessage407(bitStreamEncoder); 121 | result = result && checkNext(bitStreamEncoder, 158, 1026); 122 | result = result && !bitStreamEncoder.next(); 123 | logTestResult(result); 124 | } 125 | 126 | void testMessage407Repeated(LegoPfBitStreamEncoder& bitStreamEncoder) { 127 | Serial.print(" testMessage407Repeated "); 128 | bitStreamEncoder.reset(407, true); 129 | bool result = true; 130 | result = result && check(bitStreamEncoder, 158, 1026); 131 | result = result && checkDataBitsOfMessage407(bitStreamEncoder); 132 | result = result && checkNext(bitStreamEncoder, 158, 1026L + 5L * 16000L - 10844L); 133 | result = result && checkNext(bitStreamEncoder, 158, 1026); 134 | result = result && checkDataBitsOfMessage407(bitStreamEncoder); 135 | result = result && checkNext(bitStreamEncoder, 158, 1026L + 5L * 16000L - 10844L); 136 | result = result && checkNext(bitStreamEncoder, 158, 1026); 137 | result = result && checkDataBitsOfMessage407(bitStreamEncoder); 138 | result = result && checkNext(bitStreamEncoder, 158, 1026L + 8L * 16000L - 10844L); 139 | result = result && checkNext(bitStreamEncoder, 158, 1026); 140 | result = result && checkDataBitsOfMessage407(bitStreamEncoder); 141 | result = result && checkNext(bitStreamEncoder, 158, 1026L + 8L * 16000L - 10844L); 142 | result = result && checkNext(bitStreamEncoder, 158, 1026); 143 | result = result && checkDataBitsOfMessage407(bitStreamEncoder); 144 | result = result && checkNext(bitStreamEncoder, 158, 1026); 145 | result = result && !bitStreamEncoder.next(); 146 | logTestResult(result); 147 | } 148 | 149 | void testMessageBitCountRepeat(LegoPfBitStreamEncoder& bitStreamEncoder) { 150 | Serial.print(" testMessageBitCountRepeat "); 151 | bitStreamEncoder.reset(0xFFFF, true); 152 | int bitCount = 1; 153 | while (bitStreamEncoder.next()) { 154 | bitCount++; 155 | } 156 | logTestResult(bitCount == 5*18); 157 | } 158 | 159 | void testGetChannelId1(LegoPfBitStreamEncoder& bitStreamEncoder) { 160 | Serial.print(" testGetChannelId1 "); 161 | bitStreamEncoder.reset(407, false); 162 | logTestResult(bitStreamEncoder.getChannelId() == 1); 163 | } 164 | 165 | void testGetChannelId2(LegoPfBitStreamEncoder& bitStreamEncoder) { 166 | Serial.print(" testGetChannelId2 "); 167 | bitStreamEncoder.reset(4502, false); 168 | logTestResult(bitStreamEncoder.getChannelId() == 2); 169 | } 170 | 171 | void testGetChannelId3(LegoPfBitStreamEncoder& bitStreamEncoder) { 172 | Serial.print(" testGetChannelId3 "); 173 | bitStreamEncoder.reset(8597, false); 174 | logTestResult(bitStreamEncoder.getChannelId() == 3); 175 | } 176 | 177 | void testGetChannelId4(LegoPfBitStreamEncoder& bitStreamEncoder) { 178 | Serial.print(" testGetChannelId4 "); 179 | bitStreamEncoder.reset(12692, false); 180 | logTestResult(bitStreamEncoder.getChannelId() == 4); 181 | } 182 | 183 | void testGetMessageLengthAllHigh(LegoPfBitStreamEncoder& bitStreamEncoder) { 184 | Serial.print(" testGetMessageLengthAllHigh "); 185 | bitStreamEncoder.reset(0xFFFF, false); 186 | logTestResult(bitStreamEncoder.getMessageLength() == 13744); 187 | } 188 | 189 | void testGetMessageLengthAllLow(LegoPfBitStreamEncoder& bitStreamEncoder) { 190 | Serial.print(" testGetMessageLengthAllLow "); 191 | bitStreamEncoder.reset(0x0, false); 192 | logTestResult(bitStreamEncoder.getMessageLength() == 9104); 193 | } 194 | -------------------------------------------------------------------------------- /irPronto.cpp: -------------------------------------------------------------------------------- 1 | #define TEST 0 2 | 3 | #if TEST 4 | # define SEND_PRONTO 1 5 | # define PRONTO_ONCE false 6 | # define PRONTO_REPEAT true 7 | # define PRONTO_FALLBACK true 8 | # define PRONTO_NOFALLBACK false 9 | #endif 10 | 11 | #if SEND_PRONTO 12 | 13 | //****************************************************************************** 14 | #if TEST 15 | # include 16 | void enableIROut (int freq) { printf("\nFreq = %d KHz\n", freq); } 17 | void mark (int t) { printf("+%d," , t); } 18 | void space (int t) { printf("-%d, ", t); } 19 | #else 20 | # include "IRremote.h" 21 | #endif // TEST 22 | 23 | //+============================================================================= 24 | // Check for a valid hex digit 25 | // 26 | bool ishex (char ch) 27 | { 28 | return ( ((ch >= '0') && (ch <= '9')) || 29 | ((ch >= 'A') && (ch <= 'F')) || 30 | ((ch >= 'a') && (ch <= 'f')) ) ? true : false ; 31 | } 32 | 33 | //+============================================================================= 34 | // Check for a valid "blank" ... '\0' is a valid "blank" 35 | // 36 | bool isblank (char ch) 37 | { 38 | return ((ch == ' ') || (ch == '\t') || (ch == '\0')) ? true : false ; 39 | } 40 | 41 | //+============================================================================= 42 | // Bypass spaces 43 | // 44 | bool byp (char** pcp) 45 | { 46 | while (isblank(**pcp)) (*pcp)++ ; 47 | } 48 | 49 | //+============================================================================= 50 | // Hex-to-Byte : Decode a hex digit 51 | // We assume the character has already been validated 52 | // 53 | uint8_t htob (char ch) 54 | { 55 | if ((ch >= '0') && (ch <= '9')) return ch - '0' ; 56 | if ((ch >= 'A') && (ch <= 'F')) return ch - 'A' + 10 ; 57 | if ((ch >= 'a') && (ch <= 'f')) return ch - 'a' + 10 ; 58 | } 59 | 60 | //+============================================================================= 61 | // Hex-to-Word : Decode a block of 4 hex digits 62 | // We assume the string has already been validated 63 | // and the pointer being passed points at the start of a block of 4 hex digits 64 | // 65 | uint16_t htow (char* cp) 66 | { 67 | return ( (htob(cp[0]) << 12) | (htob(cp[1]) << 8) | 68 | (htob(cp[2]) << 4) | (htob(cp[3]) ) ) ; 69 | } 70 | 71 | //+============================================================================= 72 | // 73 | bool sendPronto (char* s, bool repeat, bool fallback) 74 | { 75 | int i; 76 | int len; 77 | int skip; 78 | char* cp; 79 | uint16_t freq; // Frequency in KHz 80 | uint8_t usec; // pronto uSec/tick 81 | uint8_t once; 82 | uint8_t rpt; 83 | 84 | // Validate the string 85 | for (cp = s; *cp; cp += 4) { 86 | byp(&cp); 87 | if ( !ishex(cp[0]) || !ishex(cp[1]) || 88 | !ishex(cp[2]) || !ishex(cp[3]) || !isblank(cp[4]) ) return false ; 89 | } 90 | 91 | // We will use cp to traverse the string 92 | cp = s; 93 | 94 | // Check mode = Oscillated/Learned 95 | byp(&cp); 96 | if (htow(cp) != 0000) return false; 97 | cp += 4; 98 | 99 | // Extract & set frequency 100 | byp(&cp); 101 | freq = (int)(1000000 / (htow(cp) * 0.241246)); // Rounding errors will occur, tolerance is +/- 10% 102 | usec = (int)(((1.0 / freq) * 1000000) + 0.5); // Another rounding error, thank Cod for analogue electronics 103 | freq /= 1000; // This will introduce a(nother) rounding error which we do not want in the usec calcualtion 104 | cp += 4; 105 | 106 | // Get length of "once" code 107 | byp(&cp); 108 | once = htow(cp); 109 | cp += 4; 110 | 111 | // Get length of "repeat" code 112 | byp(&cp); 113 | rpt = htow(cp); 114 | cp += 4; 115 | 116 | // Which code are we sending? 117 | if (fallback) { // fallback on the "other" code if "this" code is not present 118 | if (!repeat) { // requested 'once' 119 | if (once) len = once * 2, skip = 0 ; // if once exists send it 120 | else len = rpt * 2, skip = 0 ; // else send repeat code 121 | } else { // requested 'repeat' 122 | if (rpt) len = rpt * 2, skip = 0 ; // if rpt exists send it 123 | else len = once * 2, skip = 0 ; // else send once code 124 | } 125 | } else { // Send what we asked for, do not fallback if the code is empty! 126 | if (!repeat) len = once * 2, skip = 0 ; // 'once' starts at 0 127 | else len = rpt * 2, skip = once ; // 'repeat' starts where 'once' ends 128 | } 129 | 130 | // Skip to start of code 131 | for (i = 0; i < skip; i++, cp += 4) byp(&cp) ; 132 | 133 | // Send code 134 | enableIROut(freq); 135 | for (i = 0; i < len; i++) { 136 | byp(&cp); 137 | if (i & 1) space(htow(cp) * usec); 138 | else mark (htow(cp) * usec); 139 | cp += 4; 140 | } 141 | } 142 | 143 | //+============================================================================= 144 | #if TEST 145 | 146 | int main ( ) 147 | { 148 | char prontoTest[] = 149 | "0000 0070 0000 0032 0080 0040 0010 0010 0010 0030 " // 10 150 | "0010 0010 0010 0010 0010 0010 0010 0010 0010 0010 " // 20 151 | "0010 0010 0010 0010 0010 0010 0010 0010 0010 0010 " // 30 152 | "0010 0010 0010 0030 0010 0010 0010 0010 0010 0010 " // 40 153 | "0010 0010 0010 0010 0010 0010 0010 0010 0010 0010 " // 50 154 | "0010 0010 0010 0030 0010 0010 0010 0010 0010 0010 " // 60 155 | "0010 0010 0010 0010 0010 0010 0010 0010 0010 0010 " // 70 156 | "0010 0010 0010 0030 0010 0010 0010 0030 0010 0010 " // 80 157 | "0010 0010 0010 0030 0010 0010 0010 0010 0010 0030 " // 90 158 | "0010 0010 0010 0030 0010 0010 0010 0010 0010 0030 " // 100 159 | "0010 0030 0010 0aa6"; // 104 160 | 161 | sendPronto(prontoTest, PRONTO_ONCE, PRONTO_FALLBACK); // once code 162 | sendPronto(prontoTest, PRONTO_REPEAT, PRONTO_FALLBACK); // repeat code 163 | sendPronto(prontoTest, PRONTO_ONCE, PRONTO_NOFALLBACK); // once code 164 | sendPronto(prontoTest, PRONTO_REPEAT, PRONTO_NOFALLBACK); // repeat code 165 | 166 | return 0; 167 | } 168 | 169 | #endif // TEST 170 | 171 | #endif // SEND_PRONTO 172 | 173 | 174 | 175 | 176 | 177 | 178 | 179 | 180 | 181 | 182 | 183 | 184 | 185 | 186 | 187 | 188 | 189 | 190 | 191 | 192 | 193 | 194 | 195 | 196 | 197 | 198 | 199 | 200 | 201 | 202 | 203 | 204 | 205 | 206 | 207 | 208 | 209 | 210 | 211 | 212 | 213 | 214 | 215 | 216 | 217 | 218 | 219 | 220 | 221 | 222 | 223 | 224 | 225 | 226 | 227 | 228 | 229 | 230 | #if 0 231 | //****************************************************************************** 232 | // Sources: 233 | // http://www.remotecentral.com/features/irdisp2.htm 234 | // http://www.hifi-remote.com/wiki/index.php?title=Working_With_Pronto_Hex 235 | //****************************************************************************** 236 | 237 | #include 238 | #include 239 | 240 | #define IRPRONTO 241 | #include "IRremoteInt.h" // The Arduino IRremote library defines USECPERTICK 242 | 243 | //------------------------------------------------------------------------------ 244 | // Source: https://www.google.co.uk/search?q=DENON+MASTER+IR+Hex+Command+Sheet 245 | // -> http://assets.denon.com/documentmaster/us/denon%20master%20ir%20hex.xls 246 | // 247 | char prontoTest[] = 248 | "0000 0070 0000 0032 0080 0040 0010 0010 0010 0030 " // 10 249 | "0010 0010 0010 0010 0010 0010 0010 0010 0010 0010 " // 20 250 | "0010 0010 0010 0010 0010 0010 0010 0010 0010 0010 " // 30 251 | "0010 0010 0010 0030 0010 0010 0010 0010 0010 0010 " // 40 252 | "0010 0010 0010 0010 0010 0010 0010 0010 0010 0010 " // 50 253 | "0010 0010 0010 0030 0010 0010 0010 0010 0010 0010 " // 60 254 | "0010 0010 0010 0010 0010 0010 0010 0010 0010 0010 " // 70 255 | "0010 0010 0010 0030 0010 0010 0010 0030 0010 0010 " // 80 256 | "0010 0010 0010 0030 0010 0010 0010 0010 0010 0030 " // 90 257 | "0010 0010 0010 0030 0010 0010 0010 0010 0010 0030 " // 100 258 | "0010 0030 0010 0aa6"; // 104 259 | 260 | //------------------------------------------------------------------------------ 261 | // This is the longest code we can support 262 | #define CODEMAX 200 263 | 264 | //------------------------------------------------------------------------------ 265 | // This is the data we pull out of the pronto code 266 | typedef 267 | struct { 268 | int freq; // Carrier frequency (in Hz) 269 | int usec; // uSec per tick (based on freq) 270 | 271 | int codeLen; // Length of code 272 | uint16_t code[CODEMAX]; // Code in hex 273 | 274 | int onceLen; // Length of "once" transmit 275 | uint16_t* once; // Pointer to start within 'code' 276 | 277 | int rptLen; // Length of "repeat" transmit 278 | uint16_t* rpt; // Pointer to start within 'code' 279 | } 280 | pronto_t; 281 | 282 | //------------------------------------------------------------------------------ 283 | // From what I have seen, the only time we go over 8-bits is the 'space' 284 | // on the end which creates the lead-out/inter-code gap. Assuming I'm right, 285 | // we can code this up as a special case and otherwise halve the size of our 286 | // data! 287 | // Ignoring the first four values (the config data) and the last value 288 | // (the lead-out), if you find a protocol that uses values greater than 00fe 289 | // we are going to have to revisit this code! 290 | // 291 | // 292 | // So, the 0th byte will be the carrier frequency in Khz (NOT Hz) 293 | // " 1st " " " " length of the "once" code 294 | // " 2nd " " " " length of the "repeat" code 295 | // 296 | // Thereafter, odd bytes will be Mark lengths as a multiple of USECPERTICK uS 297 | // even " " " Space " " " " " " " 298 | // 299 | // Any occurence of "FF" in either a Mark or a Space will indicate 300 | // "Use the 16-bit FF value" which will also be a multiple of USECPERTICK uS 301 | // 302 | // 303 | // As a point of comparison, the test code (prontoTest[]) is 520 bytes 304 | // (yes, more than 0.5KB of our Arduino's precious 32KB) ... after conversion 305 | // to pronto hex that goes down to ((520/5)*2) = 208 bytes ... once converted to 306 | // our format we are down to ((208/2) -1 -1 +2) = 104 bytes 307 | // 308 | // In fariness this is still very memory-hungry 309 | // ...As a rough guide: 310 | // 10 codes cost 1K of memory (this will vary depending on the protocol). 311 | // 312 | // So if you're building a complex remote control, you will probably need to 313 | // keep the codes on an external memory device (not in the Arduino sketch) and 314 | // load them as you need them. Hmmm. 315 | // 316 | // This dictates that "Oscillated Pronto Codes" are probably NOT the way forward 317 | // 318 | // For example, prontoTest[] happens to be: A 48-bit IR code in Denon format 319 | // So we know it starts with 80/40 (Denon header) 320 | // and ends with 10/aa6 (Denon leadout) 321 | // and all (48) bits in between are either 10/10 (Denon 0) 322 | // or 10/30 (Denon 1) 323 | // So we could easily store this data in 1-byte ("Denon") 324 | // + 1-byte (Length=48) 325 | // + 6-bytes (IR code) 326 | // At 8-bytes per code, we can store 128 codes in 1KB or memory - that's a lot 327 | // better than the 2 (two) we started off with! 328 | // 329 | // And serendipitously, by reducing the amount of data, our program will run 330 | // a LOT faster! 331 | // 332 | // Again, I repeat, even after you have spent time converting the "Oscillated 333 | // Pronto Codes" in to IRremote format, it will be a LOT more memory-hungry 334 | // than using sendDenon() (or whichever) ...BUT these codes are easily 335 | // available on the internet, so we'll support them! 336 | // 337 | typedef 338 | struct { 339 | uint16_t FF; 340 | uint8_t code[CODEMAX]; 341 | } 342 | irCode_t; 343 | 344 | //------------------------------------------------------------------------------ 345 | #define DEBUGF(...) printf(__VA_ARGS__) 346 | 347 | //+============================================================================= 348 | // String must be block of 4 hex digits separated with blanks 349 | // 350 | bool validate (char* cp, int* len) 351 | { 352 | for (*len = 0; *cp; (*len)++, cp += 4) { 353 | byp(&cp); 354 | if ( !ishex(cp[0]) || !ishex(cp[1]) || 355 | !ishex(cp[2]) || !ishex(cp[3]) || !isblank(cp[4]) ) return false ; 356 | } 357 | 358 | return true; 359 | } 360 | 361 | //+============================================================================= 362 | // Hex-to-Byte : Decode a hex digit 363 | // We assume the character has already been validated 364 | // 365 | uint8_t htob (char ch) 366 | { 367 | if ((ch >= '0') && (ch <= '9')) return ch - '0' ; 368 | if ((ch >= 'A') && (ch <= 'F')) return ch - 'A' + 10 ; 369 | if ((ch >= 'a') && (ch <= 'f')) return ch - 'a' + 10 ; 370 | } 371 | 372 | //+============================================================================= 373 | // Hex-to-Word : Decode a block of 4 hex digits 374 | // We assume the string has already been validated 375 | // and the pointer being passed points at the start of a block of 4 hex digits 376 | // 377 | uint16_t htow (char* cp) 378 | { 379 | return ( (htob(cp[0]) << 12) | (htob(cp[1]) << 8) | 380 | (htob(cp[2]) << 4) | (htob(cp[3]) ) ) ; 381 | } 382 | 383 | //+============================================================================= 384 | // Convert the pronto string in to data 385 | // 386 | bool decode (char* s, pronto_t* p, irCode_t* ir) 387 | { 388 | int i, len; 389 | char* cp; 390 | 391 | // Validate the Pronto string 392 | if (!validate(s, &p->codeLen)) { 393 | DEBUGF("Invalid pronto string\n"); 394 | return false ; 395 | } 396 | DEBUGF("Found %d hex codes\n", p->codeLen); 397 | 398 | // Allocate memory to store the decoded string 399 | //if (!(p->code = malloc(p->len))) { 400 | // DEBUGF("Memory allocation failed\n"); 401 | // return false ; 402 | //} 403 | 404 | // Check in case our code is too long 405 | if (p->codeLen > CODEMAX) { 406 | DEBUGF("Code too long, edit CODEMAX and recompile\n"); 407 | return false ; 408 | } 409 | 410 | // Decode the string 411 | cp = s; 412 | for (i = 0; i < p->codeLen; i++, cp += 4) { 413 | byp(&cp); 414 | p->code[i] = htow(cp); 415 | } 416 | 417 | // Announce our findings 418 | DEBUGF("Input: |%s|\n", s); 419 | DEBUGF("Found: |"); 420 | for (i = 0; i < p->codeLen; i++) DEBUGF("%04x ", p->code[i]) ; 421 | DEBUGF("|\n"); 422 | 423 | DEBUGF("Form [%04X] : ", p->code[0]); 424 | if (p->code[0] == 0x0000) DEBUGF("Oscillated (Learned)\n"); 425 | else if (p->code[0] == 0x0100) DEBUGF("Unmodulated\n"); 426 | else DEBUGF("Unknown\n"); 427 | if (p->code[0] != 0x0000) return false ; // Can only handle Oscillated 428 | 429 | // Calculate the carrier frequency (+/- 10%) & uSecs per pulse 430 | // Pronto uses a crystal which generates a timeabse of 0.241246 431 | p->freq = (int)(1000000 / (p->code[1] * 0.241246)); 432 | p->usec = (int)(((1.0 / p->freq) * 1000000) + 0.5); 433 | ir->code[0] = p->freq / 1000; 434 | DEBUGF("Freq [%04X] : %d Hz (%d uS/pluse) -> %d KHz\n", 435 | p->code[1], p->freq, p->usec, ir->code[0]); 436 | 437 | // Set the length & start pointer for the "once" code 438 | p->onceLen = p->code[2]; 439 | p->once = &p->code[4]; 440 | ir->code[1] = p->onceLen; 441 | DEBUGF("Once [%04X] : %d\n", p->code[2], p->onceLen); 442 | 443 | // Set the length & start pointer for the "repeat" code 444 | p->rptLen = p->code[3]; 445 | p->rpt = &p->code[4 + p->onceLen]; 446 | ir->code[2] = p->rptLen; 447 | DEBUGF("Rpt [%04X] : %d\n", p->code[3], p->rptLen); 448 | 449 | // Check everything tallies 450 | if (1 + 1 + 1 + 1 + (p->onceLen * 2) + (p->rptLen * 2) != p->codeLen) { 451 | DEBUGF("Bad code length\n"); 452 | return false; 453 | } 454 | 455 | // Convert the IR data to our new format 456 | ir->FF = p->code[p->codeLen - 1]; 457 | 458 | len = (p->onceLen * 2) + (p->rptLen * 2); 459 | DEBUGF("Encoded: |"); 460 | for (i = 0; i < len; i++) { 461 | if (p->code[i+4] == ir->FF) { 462 | ir->code[i+3] = 0xFF; 463 | } else if (p->code[i+4] > 0xFE) { 464 | DEBUGF("\n%04X : Mark/Space overflow\n", p->code[i+4]); 465 | return false; 466 | } else { 467 | ir->code[i+3] = (p->code[i+4] * p->usec) / USECPERTICK; 468 | } 469 | DEBUGF("%s%d", !i ? "" : (i&1 ? "," : ", "), ir->code[i+3]); 470 | } 471 | DEBUGF("|\n"); 472 | 473 | ir->FF = (ir->FF * p->usec) / USECPERTICK; 474 | DEBUGF("FF -> %d\n", ir->FF); 475 | 476 | return true; 477 | } 478 | 479 | //+============================================================================= 480 | // 481 | void irDump (irCode_t* ir) 482 | { 483 | int i, len; 484 | 485 | printf("uint8_t buttonName[%d] = {", len); 486 | 487 | printf("%d,%d, ", (ir->FF >> 8), ir->FF & 0xFF); 488 | printf("%d,%d,%d, ", ir->code[0], ir->code[1], ir->code[2]); 489 | 490 | len = (ir->code[1] * 2) + (ir->code[2] * 2); 491 | for (i = 0; i < len; i++) { 492 | printf("%s%d", !i ? "" : (i&1 ? "," : ", "), ir->code[i+3]); 493 | } 494 | 495 | printf("};\n"); 496 | 497 | } 498 | 499 | //+============================================================================= 500 | // 501 | int main ( ) 502 | { 503 | pronto_t pCode; 504 | irCode_t irCode; 505 | 506 | decode(prontoTest, &pCode, &irCode); 507 | 508 | irDump(&irCode); 509 | 510 | return 0; 511 | } 512 | 513 | #endif //0 514 | -------------------------------------------------------------------------------- /irRecv.cpp: -------------------------------------------------------------------------------- 1 | #include "IRremote.h" 2 | #include "IRremoteInt.h" 3 | 4 | #ifdef IR_TIMER_USE_ESP32 5 | hw_timer_t *timer; 6 | void IRTimer(); // defined in IRremote.cpp 7 | #endif 8 | 9 | //+============================================================================= 10 | // Decodes the received IR message 11 | // Returns 0 if no data ready, 1 if data ready. 12 | // Results of decoding are stored in results 13 | // 14 | int IRrecv::decode (decode_results *results) 15 | { 16 | results->rawbuf = irparams.rawbuf; 17 | results->rawlen = irparams.rawlen; 18 | 19 | results->overflow = irparams.overflow; 20 | 21 | if (irparams.rcvstate != STATE_STOP) return false ; 22 | 23 | #if DECODE_NEC 24 | DBG_PRINTLN("Attempting NEC decode"); 25 | if (decodeNEC(results)) return true ; 26 | #endif 27 | 28 | #if DECODE_SONY 29 | DBG_PRINTLN("Attempting Sony decode"); 30 | if (decodeSony(results)) return true ; 31 | #endif 32 | 33 | #if DECODE_SANYO 34 | DBG_PRINTLN("Attempting Sanyo decode"); 35 | if (decodeSanyo(results)) return true ; 36 | #endif 37 | 38 | #if DECODE_MITSUBISHI 39 | DBG_PRINTLN("Attempting Mitsubishi decode"); 40 | if (decodeMitsubishi(results)) return true ; 41 | #endif 42 | 43 | #if DECODE_RC5 44 | DBG_PRINTLN("Attempting RC5 decode"); 45 | if (decodeRC5(results)) return true ; 46 | #endif 47 | 48 | #if DECODE_RC6 49 | DBG_PRINTLN("Attempting RC6 decode"); 50 | if (decodeRC6(results)) return true ; 51 | #endif 52 | 53 | #if DECODE_PANASONIC 54 | DBG_PRINTLN("Attempting Panasonic decode"); 55 | if (decodePanasonic(results)) return true ; 56 | #endif 57 | 58 | #if DECODE_LG 59 | DBG_PRINTLN("Attempting LG decode"); 60 | if (decodeLG(results)) return true ; 61 | #endif 62 | 63 | #if DECODE_JVC 64 | DBG_PRINTLN("Attempting JVC decode"); 65 | if (decodeJVC(results)) return true ; 66 | #endif 67 | 68 | #if DECODE_SAMSUNG 69 | DBG_PRINTLN("Attempting SAMSUNG decode"); 70 | if (decodeSAMSUNG(results)) return true ; 71 | #endif 72 | 73 | #if DECODE_WHYNTER 74 | DBG_PRINTLN("Attempting Whynter decode"); 75 | if (decodeWhynter(results)) return true ; 76 | #endif 77 | 78 | #if DECODE_AIWA_RC_T501 79 | DBG_PRINTLN("Attempting Aiwa RC-T501 decode"); 80 | if (decodeAiwaRCT501(results)) return true ; 81 | #endif 82 | 83 | #if DECODE_DENON 84 | DBG_PRINTLN("Attempting Denon decode"); 85 | if (decodeDenon(results)) return true ; 86 | #endif 87 | 88 | #if DECODE_LEGO_PF 89 | DBG_PRINTLN("Attempting Lego Power Functions"); 90 | if (decodeLegoPowerFunctions(results)) return true ; 91 | #endif 92 | 93 | // decodeHash returns a hash on any input. 94 | // Thus, it needs to be last in the list. 95 | // If you add any decodes, add them before this. 96 | if (decodeHash(results)) return true ; 97 | 98 | // Throw away and start over 99 | resume(); 100 | return false; 101 | } 102 | 103 | //+============================================================================= 104 | IRrecv::IRrecv (int recvpin) 105 | { 106 | irparams.recvpin = recvpin; 107 | irparams.blinkflag = 0; 108 | } 109 | 110 | IRrecv::IRrecv (int recvpin, int blinkpin) 111 | { 112 | irparams.recvpin = recvpin; 113 | irparams.blinkpin = blinkpin; 114 | pinMode(blinkpin, OUTPUT); 115 | irparams.blinkflag = 0; 116 | } 117 | 118 | 119 | 120 | //+============================================================================= 121 | // initialization 122 | // 123 | void IRrecv::enableIRIn ( ) 124 | { 125 | // Interrupt Service Routine - Fires every 50uS 126 | #ifdef ESP32 127 | // ESP32 has a proper API to setup timers, no weird chip macros needed 128 | // simply call the readable API versions :) 129 | // 3 timers, choose #1, 80 divider nanosecond precision, 1 to count up 130 | timer = timerBegin(1, 80, 1); 131 | timerAttachInterrupt(timer, &IRTimer, 1); 132 | // every 50ns, autoreload = true 133 | timerAlarmWrite(timer, 50, true); 134 | timerAlarmEnable(timer); 135 | #else 136 | cli(); 137 | // Setup pulse clock timer interrupt 138 | // Prescale /8 (16M/8 = 0.5 microseconds per tick) 139 | // Therefore, the timer interval can range from 0.5 to 128 microseconds 140 | // Depending on the reset value (255 to 0) 141 | TIMER_CONFIG_NORMAL(); 142 | 143 | // Timer2 Overflow Interrupt Enable 144 | TIMER_ENABLE_INTR; 145 | 146 | TIMER_RESET; 147 | 148 | sei(); // enable interrupts 149 | #endif 150 | 151 | // Initialize state machine variables 152 | irparams.rcvstate = STATE_IDLE; 153 | irparams.rawlen = 0; 154 | 155 | // Set pin modes 156 | pinMode(irparams.recvpin, INPUT); 157 | } 158 | 159 | //+============================================================================= 160 | // Enable/disable blinking of pin 13 on IR processing 161 | // 162 | void IRrecv::blink13 (int blinkflag) 163 | { 164 | irparams.blinkflag = blinkflag; 165 | if (blinkflag) pinMode(BLINKLED, OUTPUT) ; 166 | } 167 | 168 | //+============================================================================= 169 | // Return if receiving new IR signals 170 | // 171 | bool IRrecv::isIdle ( ) 172 | { 173 | return (irparams.rcvstate == STATE_IDLE || irparams.rcvstate == STATE_STOP) ? true : false; 174 | } 175 | //+============================================================================= 176 | // Restart the ISR state machine 177 | // 178 | void IRrecv::resume ( ) 179 | { 180 | irparams.rcvstate = STATE_IDLE; 181 | irparams.rawlen = 0; 182 | } 183 | 184 | //+============================================================================= 185 | // hashdecode - decode an arbitrary IR code. 186 | // Instead of decoding using a standard encoding scheme 187 | // (e.g. Sony, NEC, RC5), the code is hashed to a 32-bit value. 188 | // 189 | // The algorithm: look at the sequence of MARK signals, and see if each one 190 | // is shorter (0), the same length (1), or longer (2) than the previous. 191 | // Do the same with the SPACE signals. Hash the resulting sequence of 0's, 192 | // 1's, and 2's to a 32-bit value. This will give a unique value for each 193 | // different code (probably), for most code systems. 194 | // 195 | // http://arcfn.com/2010/01/using-arbitrary-remotes-with-arduino.html 196 | // 197 | // Compare two tick values, returning 0 if newval is shorter, 198 | // 1 if newval is equal, and 2 if newval is longer 199 | // Use a tolerance of 20% 200 | // 201 | int IRrecv::compare (unsigned int oldval, unsigned int newval) 202 | { 203 | if (newval < oldval * .8) return 0 ; 204 | else if (oldval < newval * .8) return 2 ; 205 | else return 1 ; 206 | } 207 | 208 | //+============================================================================= 209 | // Use FNV hash algorithm: http://isthe.com/chongo/tech/comp/fnv/#FNV-param 210 | // Converts the raw code values into a 32-bit hash code. 211 | // Hopefully this code is unique for each button. 212 | // This isn't a "real" decoding, just an arbitrary value. 213 | // 214 | #define FNV_PRIME_32 16777619 215 | #define FNV_BASIS_32 2166136261 216 | 217 | long IRrecv::decodeHash (decode_results *results) 218 | { 219 | long hash = FNV_BASIS_32; 220 | 221 | // Require at least 6 samples to prevent triggering on noise 222 | if (results->rawlen < 6) return false ; 223 | 224 | for (int i = 1; (i + 2) < results->rawlen; i++) { 225 | int value = compare(results->rawbuf[i], results->rawbuf[i+2]); 226 | // Add value into the hash 227 | hash = (hash * FNV_PRIME_32) ^ value; 228 | } 229 | 230 | results->value = hash; 231 | results->bits = 32; 232 | results->decode_type = UNKNOWN; 233 | 234 | return true; 235 | } 236 | -------------------------------------------------------------------------------- /irSend.cpp: -------------------------------------------------------------------------------- 1 | #include "IRremote.h" 2 | #include "IRremoteInt.h" 3 | 4 | //+============================================================================= 5 | void IRsend::sendRaw (const unsigned int buf[], unsigned int len, unsigned int hz) 6 | { 7 | // Set IR carrier frequency 8 | enableIROut(hz); 9 | 10 | for (unsigned int i = 0; i < len; i++) { 11 | if (i & 1) space(buf[i]) ; 12 | else mark (buf[i]) ; 13 | } 14 | 15 | space(0); // Always end with the LED off 16 | } 17 | 18 | //+============================================================================= 19 | // Sends an IR mark for the specified number of microseconds. 20 | // The mark output is modulated at the PWM frequency. 21 | // 22 | void IRsend::mark (unsigned int time) 23 | { 24 | #ifdef ESP32 25 | ledcWrite(LEDCHANNEL, 83); 26 | #else 27 | TIMER_ENABLE_PWM; // Enable pin 3 PWM output 28 | #endif 29 | if (time > 0) custom_delay_usec(time); 30 | } 31 | 32 | //+============================================================================= 33 | // Leave pin off for time (given in microseconds) 34 | // Sends an IR space for the specified number of microseconds. 35 | // A space is no output, so the PWM output is disabled. 36 | // 37 | void IRsend::space (unsigned int time) 38 | { 39 | #ifdef ESP32 40 | ledcWrite(LEDCHANNEL, 0); 41 | #else 42 | TIMER_DISABLE_PWM; // Disable pin 3 PWM output 43 | #endif 44 | if (time > 0) IRsend::custom_delay_usec(time); 45 | 46 | } 47 | 48 | 49 | 50 | 51 | 52 | //+============================================================================= 53 | // Enables IR output. The khz value controls the modulation frequency in kilohertz. 54 | // The IR output will be on pin 3 (OC2B). 55 | // This routine is designed for 36-40KHz; if you use it for other values, it's up to you 56 | // to make sure it gives reasonable results. (Watch out for overflow / underflow / rounding.) 57 | // TIMER2 is used in phase-correct PWM mode, with OCR2A controlling the frequency and OCR2B 58 | // controlling the duty cycle. 59 | // There is no prescaling, so the output frequency is 16MHz / (2 * OCR2A) 60 | // To turn the output on and off, we leave the PWM running, but connect and disconnect the output pin. 61 | // A few hours staring at the ATmega documentation and this will all make sense. 62 | // See my Secrets of Arduino PWM at http://arcfn.com/2009/07/secrets-of-arduino-pwm.html for details. 63 | // 64 | void IRsend::enableIROut (int khz) 65 | { 66 | // FIXME: implement ESP32 support, see IR_TIMER_USE_ESP32 in boarddefs.h 67 | #ifndef ESP32 68 | // Disable the Timer2 Interrupt (which is used for receiving IR) 69 | TIMER_DISABLE_INTR; //Timer2 Overflow Interrupt 70 | 71 | pinMode(TIMER_PWM_PIN, OUTPUT); 72 | digitalWrite(TIMER_PWM_PIN, LOW); // When not sending PWM, we want it low 73 | 74 | // COM2A = 00: disconnect OC2A 75 | // COM2B = 00: disconnect OC2B; to send signal set to 10: OC2B non-inverted 76 | // WGM2 = 101: phase-correct PWM with OCRA as top 77 | // CS2 = 000: no prescaling 78 | // The top value for the timer. The modulation frequency will be SYSCLOCK / 2 / OCR2A. 79 | TIMER_CONFIG_KHZ(khz); 80 | #else 81 | ledcSetup(LEDCHANNEL, khz*1000, 8); 82 | ledcAttachPin(timerPwmPin, LEDCHANNEL); 83 | #endif 84 | } 85 | 86 | //+============================================================================= 87 | // Custom delay function that circumvents Arduino's delayMicroseconds limit 88 | 89 | void IRsend::custom_delay_usec(unsigned long uSecs) { 90 | if (uSecs > 4) { 91 | unsigned long start = micros(); 92 | unsigned long endMicros = start + uSecs - 4; 93 | if (endMicros < start) { // Check if overflow 94 | while ( micros() > start ) {} // wait until overflow 95 | } 96 | while ( micros() < endMicros ) {} // normal wait 97 | } 98 | //else { 99 | // __asm__("nop\n\t"); // must have or compiler optimizes out 100 | //} 101 | } 102 | 103 | -------------------------------------------------------------------------------- /ir_Aiwa.cpp: -------------------------------------------------------------------------------- 1 | #include "IRremote.h" 2 | #include "IRremoteInt.h" 3 | 4 | //============================================================================== 5 | // AAA IIIII W W AAA 6 | // A A I W W A A 7 | // AAAAA I W W W AAAAA 8 | // A A I W W W A A 9 | // A A IIIII WWW A A 10 | //============================================================================== 11 | 12 | // Based off the RC-T501 RCU 13 | // Lirc file http://lirc.sourceforge.net/remotes/aiwa/RC-T501 14 | 15 | #define AIWA_RC_T501_HZ 38 16 | #define AIWA_RC_T501_BITS 15 17 | #define AIWA_RC_T501_PRE_BITS 26 18 | #define AIWA_RC_T501_POST_BITS 1 19 | #define AIWA_RC_T501_SUM_BITS (AIWA_RC_T501_PRE_BITS + AIWA_RC_T501_BITS + AIWA_RC_T501_POST_BITS) 20 | #define AIWA_RC_T501_HDR_MARK 8800 21 | #define AIWA_RC_T501_HDR_SPACE 4500 22 | #define AIWA_RC_T501_BIT_MARK 500 23 | #define AIWA_RC_T501_ONE_SPACE 600 24 | #define AIWA_RC_T501_ZERO_SPACE 1700 25 | 26 | //+============================================================================= 27 | #if SEND_AIWA_RC_T501 28 | void IRsend::sendAiwaRCT501 (int code) 29 | { 30 | unsigned long pre = 0x0227EEC0; // 26-bits 31 | 32 | // Set IR carrier frequency 33 | enableIROut(AIWA_RC_T501_HZ); 34 | 35 | // Header 36 | mark(AIWA_RC_T501_HDR_MARK); 37 | space(AIWA_RC_T501_HDR_SPACE); 38 | 39 | // Send "pre" data 40 | for (unsigned long mask = 1UL << (26 - 1); mask; mask >>= 1) { 41 | mark(AIWA_RC_T501_BIT_MARK); 42 | if (pre & mask) space(AIWA_RC_T501_ONE_SPACE) ; 43 | else space(AIWA_RC_T501_ZERO_SPACE) ; 44 | } 45 | 46 | //-v- THIS CODE LOOKS LIKE IT MIGHT BE WRONG - CHECK! 47 | // it only send 15bits and ignores the top bit 48 | // then uses TOPBIT which is 0x80000000 to check the bit code 49 | // I suspect TOPBIT should be changed to 0x00008000 50 | 51 | // Skip first code bit 52 | code <<= 1; 53 | // Send code 54 | for (int i = 0; i < 15; i++) { 55 | mark(AIWA_RC_T501_BIT_MARK); 56 | if (code & 0x80000000) space(AIWA_RC_T501_ONE_SPACE) ; 57 | else space(AIWA_RC_T501_ZERO_SPACE) ; 58 | code <<= 1; 59 | } 60 | 61 | //-^- THIS CODE LOOKS LIKE IT MIGHT BE WRONG - CHECK! 62 | 63 | // POST-DATA, 1 bit, 0x0 64 | mark(AIWA_RC_T501_BIT_MARK); 65 | space(AIWA_RC_T501_ZERO_SPACE); 66 | 67 | mark(AIWA_RC_T501_BIT_MARK); 68 | space(0); 69 | } 70 | #endif 71 | 72 | //+============================================================================= 73 | #if DECODE_AIWA_RC_T501 74 | bool IRrecv::decodeAiwaRCT501 (decode_results *results) 75 | { 76 | int data = 0; 77 | int offset = 1; 78 | 79 | // Check SIZE 80 | if (irparams.rawlen < 2 * (AIWA_RC_T501_SUM_BITS) + 4) return false ; 81 | 82 | // Check HDR Mark/Space 83 | if (!MATCH_MARK (results->rawbuf[offset++], AIWA_RC_T501_HDR_MARK )) return false ; 84 | if (!MATCH_SPACE(results->rawbuf[offset++], AIWA_RC_T501_HDR_SPACE)) return false ; 85 | 86 | offset += 26; // skip pre-data - optional 87 | while(offset < irparams.rawlen - 4) { 88 | if (MATCH_MARK(results->rawbuf[offset], AIWA_RC_T501_BIT_MARK)) offset++ ; 89 | else return false ; 90 | 91 | // ONE & ZERO 92 | if (MATCH_SPACE(results->rawbuf[offset], AIWA_RC_T501_ONE_SPACE)) data = (data << 1) | 1 ; 93 | else if (MATCH_SPACE(results->rawbuf[offset], AIWA_RC_T501_ZERO_SPACE)) data = (data << 1) | 0 ; 94 | else break ; // End of one & zero detected 95 | offset++; 96 | } 97 | 98 | results->bits = (offset - 1) / 2; 99 | if (results->bits < 42) return false ; 100 | 101 | results->value = data; 102 | results->decode_type = AIWA_RC_T501; 103 | return true; 104 | } 105 | #endif 106 | -------------------------------------------------------------------------------- /ir_Denon.cpp: -------------------------------------------------------------------------------- 1 | #include "IRremote.h" 2 | #include "IRremoteInt.h" 3 | 4 | // Reverse Engineered by looking at RAW dumps generated by IRremote 5 | 6 | // I have since discovered that Denon publish all their IR codes: 7 | // https://www.google.co.uk/search?q=DENON+MASTER+IR+Hex+Command+Sheet 8 | // -> http://assets.denon.com/documentmaster/us/denon%20master%20ir%20hex.xls 9 | 10 | // Having looked at the official Denon Pronto sheet and reverse engineered 11 | // the timing values from it, it is obvious that Denon have a range of 12 | // different timings and protocols ...the values here work for my AVR-3801 Amp! 13 | 14 | //============================================================================== 15 | // DDDD EEEEE N N OOO N N 16 | // D D E NN N O O NN N 17 | // D D EEE N N N O O N N N 18 | // D D E N NN O O N NN 19 | // DDDD EEEEE N N OOO N N 20 | //============================================================================== 21 | 22 | #define BITS 14 // The number of bits in the command 23 | 24 | #define HDR_MARK 300 // The length of the Header:Mark 25 | #define HDR_SPACE 750 // The lenght of the Header:Space 26 | 27 | #define BIT_MARK 300 // The length of a Bit:Mark 28 | #define ONE_SPACE 1800 // The length of a Bit:Space for 1's 29 | #define ZERO_SPACE 750 // The length of a Bit:Space for 0's 30 | 31 | //+============================================================================= 32 | // 33 | #if SEND_DENON 34 | void IRsend::sendDenon (unsigned long data, int nbits) 35 | { 36 | // Set IR carrier frequency 37 | enableIROut(38); 38 | 39 | // Header 40 | mark (HDR_MARK); 41 | space(HDR_SPACE); 42 | 43 | // Data 44 | for (unsigned long mask = 1UL << (nbits - 1); mask; mask >>= 1) { 45 | if (data & mask) { 46 | mark (BIT_MARK); 47 | space(ONE_SPACE); 48 | } else { 49 | mark (BIT_MARK); 50 | space(ZERO_SPACE); 51 | } 52 | } 53 | 54 | // Footer 55 | mark(BIT_MARK); 56 | space(0); // Always end with the LED off 57 | } 58 | #endif 59 | 60 | //+============================================================================= 61 | // 62 | #if DECODE_DENON 63 | bool IRrecv::decodeDenon (decode_results *results) 64 | { 65 | unsigned long data = 0; // Somewhere to build our code 66 | int offset = 1; // Skip the Gap reading 67 | 68 | // Check we have the right amount of data 69 | if (irparams.rawlen != 1 + 2 + (2 * BITS) + 1) return false ; 70 | 71 | // Check initial Mark+Space match 72 | if (!MATCH_MARK (results->rawbuf[offset++], HDR_MARK )) return false ; 73 | if (!MATCH_SPACE(results->rawbuf[offset++], HDR_SPACE)) return false ; 74 | 75 | // Read the bits in 76 | for (int i = 0; i < BITS; i++) { 77 | // Each bit looks like: MARK + SPACE_1 -> 1 78 | // or : MARK + SPACE_0 -> 0 79 | if (!MATCH_MARK(results->rawbuf[offset++], BIT_MARK)) return false ; 80 | 81 | // IR data is big-endian, so we shuffle it in from the right: 82 | if (MATCH_SPACE(results->rawbuf[offset], ONE_SPACE)) data = (data << 1) | 1 ; 83 | else if (MATCH_SPACE(results->rawbuf[offset], ZERO_SPACE)) data = (data << 1) | 0 ; 84 | else return false ; 85 | offset++; 86 | } 87 | 88 | // Success 89 | results->bits = BITS; 90 | results->value = data; 91 | results->decode_type = DENON; 92 | return true; 93 | } 94 | #endif 95 | -------------------------------------------------------------------------------- /ir_Dish.cpp: -------------------------------------------------------------------------------- 1 | #include "IRremote.h" 2 | #include "IRremoteInt.h" 3 | 4 | //============================================================================== 5 | // DDDD IIIII SSSS H H 6 | // D D I S H H 7 | // D D I SSS HHHHH 8 | // D D I S H H 9 | // DDDD IIIII SSSS H H 10 | //============================================================================== 11 | 12 | // Sharp and DISH support by Todd Treece ( http://unionbridge.org/design/ircommand ) 13 | // 14 | // The sned function needs to be repeated 4 times 15 | // 16 | // Only send the last for characters of the hex. 17 | // I.E. Use 0x1C10 instead of 0x0000000000001C10 as listed in the LIRC file. 18 | // 19 | // Here is the LIRC file I found that seems to match the remote codes from the 20 | // oscilloscope: 21 | // DISH NETWORK (echostar 301): 22 | // http://lirc.sourceforge.net/remotes/echostar/301_501_3100_5100_58xx_59xx 23 | 24 | #define DISH_BITS 16 25 | #define DISH_HDR_MARK 400 26 | #define DISH_HDR_SPACE 6100 27 | #define DISH_BIT_MARK 400 28 | #define DISH_ONE_SPACE 1700 29 | #define DISH_ZERO_SPACE 2800 30 | #define DISH_RPT_SPACE 6200 31 | 32 | //+============================================================================= 33 | #if SEND_DISH 34 | void IRsend::sendDISH (unsigned long data, int nbits) 35 | { 36 | // Set IR carrier frequency 37 | enableIROut(56); 38 | 39 | mark(DISH_HDR_MARK); 40 | space(DISH_HDR_SPACE); 41 | 42 | for (unsigned long mask = 1UL << (nbits - 1); mask; mask >>= 1) { 43 | if (data & mask) { 44 | mark(DISH_BIT_MARK); 45 | space(DISH_ONE_SPACE); 46 | } else { 47 | mark(DISH_BIT_MARK); 48 | space(DISH_ZERO_SPACE); 49 | } 50 | } 51 | mark(DISH_HDR_MARK); //added 26th March 2016, by AnalysIR ( https://www.AnalysIR.com ) 52 | } 53 | #endif 54 | 55 | -------------------------------------------------------------------------------- /ir_JVC.cpp: -------------------------------------------------------------------------------- 1 | #include "IRremote.h" 2 | #include "IRremoteInt.h" 3 | 4 | //============================================================================== 5 | // JJJJJ V V CCCC 6 | // J V V C 7 | // J V V C 8 | // J J V V C 9 | // J V CCCC 10 | //============================================================================== 11 | 12 | #define JVC_BITS 16 13 | #define JVC_HDR_MARK 8000 14 | #define JVC_HDR_SPACE 4000 15 | #define JVC_BIT_MARK 600 16 | #define JVC_ONE_SPACE 1600 17 | #define JVC_ZERO_SPACE 550 18 | #define JVC_RPT_LENGTH 60000 19 | 20 | //+============================================================================= 21 | // JVC does NOT repeat by sending a separate code (like NEC does). 22 | // The JVC protocol repeats by skipping the header. 23 | // To send a JVC repeat signal, send the original code value 24 | // and set 'repeat' to true 25 | // 26 | #if SEND_JVC 27 | void IRsend::sendJVC (unsigned long data, int nbits, bool repeat) 28 | { 29 | // Set IR carrier frequency 30 | enableIROut(38); 31 | 32 | // Only send the Header if this is NOT a repeat command 33 | if (!repeat){ 34 | mark(JVC_HDR_MARK); 35 | space(JVC_HDR_SPACE); 36 | } 37 | 38 | // Data 39 | for (unsigned long mask = 1UL << (nbits - 1); mask; mask >>= 1) { 40 | if (data & mask) { 41 | mark(JVC_BIT_MARK); 42 | space(JVC_ONE_SPACE); 43 | } else { 44 | mark(JVC_BIT_MARK); 45 | space(JVC_ZERO_SPACE); 46 | } 47 | } 48 | 49 | // Footer 50 | mark(JVC_BIT_MARK); 51 | space(0); // Always end with the LED off 52 | } 53 | #endif 54 | 55 | //+============================================================================= 56 | #if DECODE_JVC 57 | bool IRrecv::decodeJVC (decode_results *results) 58 | { 59 | long data = 0; 60 | int offset = 1; // Skip first space 61 | 62 | // Check for repeat 63 | if ( (irparams.rawlen - 1 == 33) 64 | && MATCH_MARK(results->rawbuf[offset], JVC_BIT_MARK) 65 | && MATCH_MARK(results->rawbuf[irparams.rawlen-1], JVC_BIT_MARK) 66 | ) { 67 | results->bits = 0; 68 | results->value = REPEAT; 69 | results->decode_type = JVC; 70 | return true; 71 | } 72 | 73 | // Initial mark 74 | if (!MATCH_MARK(results->rawbuf[offset++], JVC_HDR_MARK)) return false ; 75 | 76 | if (irparams.rawlen < (2 * JVC_BITS) + 1 ) return false ; 77 | 78 | // Initial space 79 | if (!MATCH_SPACE(results->rawbuf[offset++], JVC_HDR_SPACE)) return false ; 80 | 81 | for (int i = 0; i < JVC_BITS; i++) { 82 | if (!MATCH_MARK(results->rawbuf[offset++], JVC_BIT_MARK)) return false ; 83 | 84 | if (MATCH_SPACE(results->rawbuf[offset], JVC_ONE_SPACE)) data = (data << 1) | 1 ; 85 | else if (MATCH_SPACE(results->rawbuf[offset], JVC_ZERO_SPACE)) data = (data << 1) | 0 ; 86 | else return false ; 87 | offset++; 88 | } 89 | 90 | // Stop bit 91 | if (!MATCH_MARK(results->rawbuf[offset], JVC_BIT_MARK)) return false ; 92 | 93 | // Success 94 | results->bits = JVC_BITS; 95 | results->value = data; 96 | results->decode_type = JVC; 97 | 98 | return true; 99 | } 100 | #endif 101 | 102 | -------------------------------------------------------------------------------- /ir_LG.cpp: -------------------------------------------------------------------------------- 1 | #include "IRremote.h" 2 | #include "IRremoteInt.h" 3 | 4 | //============================================================================== 5 | // L GGGG 6 | // L G 7 | // L G GG 8 | // L G G 9 | // LLLLL GGG 10 | //============================================================================== 11 | 12 | #define LG_BITS 28 13 | 14 | #define LG_HDR_MARK 8000 15 | #define LG_HDR_SPACE 4000 16 | #define LG_BIT_MARK 600 17 | #define LG_ONE_SPACE 1600 18 | #define LG_ZERO_SPACE 550 19 | #define LG_RPT_LENGTH 60000 20 | 21 | //+============================================================================= 22 | #if DECODE_LG 23 | bool IRrecv::decodeLG (decode_results *results) 24 | { 25 | long data = 0; 26 | int offset = 1; // Skip first space 27 | 28 | // Check we have the right amount of data 29 | if (irparams.rawlen < (2 * LG_BITS) + 1 ) return false ; 30 | 31 | // Initial mark/space 32 | if (!MATCH_MARK(results->rawbuf[offset++], LG_HDR_MARK)) return false ; 33 | if (!MATCH_SPACE(results->rawbuf[offset++], LG_HDR_SPACE)) return false ; 34 | 35 | for (int i = 0; i < LG_BITS; i++) { 36 | if (!MATCH_MARK(results->rawbuf[offset++], LG_BIT_MARK)) return false ; 37 | 38 | if (MATCH_SPACE(results->rawbuf[offset], LG_ONE_SPACE)) data = (data << 1) | 1 ; 39 | else if (MATCH_SPACE(results->rawbuf[offset], LG_ZERO_SPACE)) data = (data << 1) | 0 ; 40 | else return false ; 41 | offset++; 42 | } 43 | 44 | // Stop bit 45 | if (!MATCH_MARK(results->rawbuf[offset], LG_BIT_MARK)) return false ; 46 | 47 | // Success 48 | results->bits = LG_BITS; 49 | results->value = data; 50 | results->decode_type = LG; 51 | return true; 52 | } 53 | #endif 54 | 55 | //+============================================================================= 56 | #if SEND_LG 57 | void IRsend::sendLG (unsigned long data, int nbits) 58 | { 59 | // Set IR carrier frequency 60 | enableIROut(38); 61 | 62 | // Header 63 | mark(LG_HDR_MARK); 64 | space(LG_HDR_SPACE); 65 | mark(LG_BIT_MARK); 66 | 67 | // Data 68 | for (unsigned long mask = 1UL << (nbits - 1); mask; mask >>= 1) { 69 | if (data & mask) { 70 | space(LG_ONE_SPACE); 71 | mark(LG_BIT_MARK); 72 | } else { 73 | space(LG_ZERO_SPACE); 74 | mark(LG_BIT_MARK); 75 | } 76 | } 77 | space(0); // Always end with the LED off 78 | } 79 | #endif 80 | 81 | -------------------------------------------------------------------------------- /ir_Lego_PF.cpp: -------------------------------------------------------------------------------- 1 | #include "IRremote.h" 2 | #include "IRremoteInt.h" 3 | #include "ir_Lego_PF_BitStreamEncoder.h" 4 | 5 | //============================================================================== 6 | // L EEEEEE EEEE OOOO 7 | // L E E O O 8 | // L EEEE E EEE O O 9 | // L E E E O O LEGO Power Functions 10 | // LLLLLL EEEEEE EEEE OOOO Copyright (c) 2016 Philipp Henkel 11 | //============================================================================== 12 | 13 | // Supported Devices 14 | // LEGO® Power Functions IR Receiver 8884 15 | 16 | //+============================================================================= 17 | // 18 | #if SEND_LEGO_PF 19 | 20 | #if DEBUG 21 | namespace { 22 | void logFunctionParameters(uint16_t data, bool repeat) { 23 | DBG_PRINT("sendLegoPowerFunctions(data="); 24 | DBG_PRINT(data); 25 | DBG_PRINT(", repeat="); 26 | DBG_PRINTLN(repeat?"true)" : "false)"); 27 | } 28 | } // anonymous namespace 29 | #endif // DEBUG 30 | 31 | void IRsend::sendLegoPowerFunctions(uint16_t data, bool repeat) 32 | { 33 | #if DEBUG 34 | ::logFunctionParameters(data, repeat); 35 | #endif // DEBUG 36 | 37 | enableIROut(38); 38 | static LegoPfBitStreamEncoder bitStreamEncoder; 39 | bitStreamEncoder.reset(data, repeat); 40 | do { 41 | mark(bitStreamEncoder.getMarkDuration()); 42 | space(bitStreamEncoder.getPauseDuration()); 43 | } while (bitStreamEncoder.next()); 44 | } 45 | 46 | #endif // SEND_LEGO_PF 47 | -------------------------------------------------------------------------------- /ir_Lego_PF_BitStreamEncoder.h: -------------------------------------------------------------------------------- 1 | 2 | //============================================================================== 3 | // L EEEEEE EEEE OOOO 4 | // L E E O O 5 | // L EEEE E EEE O O 6 | // L E E E O O LEGO Power Functions 7 | // LLLLLL EEEEEE EEEE OOOO Copyright (c) 2016, 2017 Philipp Henkel 8 | //============================================================================== 9 | 10 | //+============================================================================= 11 | // 12 | 13 | class LegoPfBitStreamEncoder { 14 | private: 15 | uint16_t data; 16 | bool repeatMessage; 17 | uint8_t messageBitIdx; 18 | uint8_t repeatCount; 19 | uint16_t messageLength; 20 | 21 | public: 22 | // HIGH data bit = IR mark + high pause 23 | // LOW data bit = IR mark + low pause 24 | static const uint16_t LOW_BIT_DURATION = 421; 25 | static const uint16_t HIGH_BIT_DURATION = 711; 26 | static const uint16_t START_BIT_DURATION = 1184; 27 | static const uint16_t STOP_BIT_DURATION = 1184; 28 | static const uint8_t IR_MARK_DURATION = 158; 29 | static const uint16_t HIGH_PAUSE_DURATION = HIGH_BIT_DURATION - IR_MARK_DURATION; 30 | static const uint16_t LOW_PAUSE_DURATION = LOW_BIT_DURATION - IR_MARK_DURATION; 31 | static const uint16_t START_PAUSE_DURATION = START_BIT_DURATION - IR_MARK_DURATION; 32 | static const uint16_t STOP_PAUSE_DURATION = STOP_BIT_DURATION - IR_MARK_DURATION; 33 | static const uint8_t MESSAGE_BITS = 18; 34 | static const uint16_t MAX_MESSAGE_LENGTH = 16000; 35 | 36 | void reset(uint16_t data, bool repeatMessage) { 37 | this->data = data; 38 | this->repeatMessage = repeatMessage; 39 | messageBitIdx = 0; 40 | repeatCount = 0; 41 | messageLength = getMessageLength(); 42 | } 43 | 44 | int getChannelId() const { return 1 + ((data >> 12) & 0x3); } 45 | 46 | uint16_t getMessageLength() const { 47 | // Sum up all marks 48 | uint16_t length = MESSAGE_BITS * IR_MARK_DURATION; 49 | 50 | // Sum up all pauses 51 | length += START_PAUSE_DURATION; 52 | for (unsigned long mask = 1UL << 15; mask; mask >>= 1) { 53 | if (data & mask) { 54 | length += HIGH_PAUSE_DURATION; 55 | } else { 56 | length += LOW_PAUSE_DURATION; 57 | } 58 | } 59 | length += STOP_PAUSE_DURATION; 60 | return length; 61 | } 62 | 63 | boolean next() { 64 | messageBitIdx++; 65 | if (messageBitIdx >= MESSAGE_BITS) { 66 | repeatCount++; 67 | messageBitIdx = 0; 68 | } 69 | if (repeatCount >= 1 && !repeatMessage) { 70 | return false; 71 | } else if (repeatCount >= 5) { 72 | return false; 73 | } else { 74 | return true; 75 | } 76 | } 77 | 78 | uint8_t getMarkDuration() const { return IR_MARK_DURATION; } 79 | 80 | uint32_t getPauseDuration() const { 81 | if (messageBitIdx == 0) 82 | return START_PAUSE_DURATION; 83 | else if (messageBitIdx < MESSAGE_BITS - 1) { 84 | return getDataBitPause(); 85 | } else { 86 | return getStopPause(); 87 | } 88 | } 89 | 90 | private: 91 | uint16_t getDataBitPause() const { 92 | const int pos = MESSAGE_BITS - 2 - messageBitIdx; 93 | const bool isHigh = data & (1 << pos); 94 | return isHigh ? HIGH_PAUSE_DURATION : LOW_PAUSE_DURATION; 95 | } 96 | 97 | uint32_t getStopPause() const { 98 | if (repeatMessage) { 99 | return getRepeatStopPause(); 100 | } else { 101 | return STOP_PAUSE_DURATION; 102 | } 103 | } 104 | 105 | uint32_t getRepeatStopPause() const { 106 | if (repeatCount == 0 || repeatCount == 1) { 107 | return STOP_PAUSE_DURATION + (uint32_t)5 * MAX_MESSAGE_LENGTH - messageLength; 108 | } else if (repeatCount == 2 || repeatCount == 3) { 109 | return STOP_PAUSE_DURATION 110 | + (uint32_t)(6 + 2 * getChannelId()) * MAX_MESSAGE_LENGTH - messageLength; 111 | } else { 112 | return STOP_PAUSE_DURATION; 113 | } 114 | } 115 | }; 116 | -------------------------------------------------------------------------------- /ir_Mitsubishi.cpp: -------------------------------------------------------------------------------- 1 | #include "IRremote.h" 2 | #include "IRremoteInt.h" 3 | 4 | //============================================================================== 5 | // MMMMM IIIII TTTTT SSSS U U BBBB IIIII SSSS H H IIIII 6 | // M M M I T S U U B B I S H H I 7 | // M M M I T SSS U U BBBB I SSS HHHHH I 8 | // M M I T S U U B B I S H H I 9 | // M M IIIII T SSSS UUU BBBBB IIIII SSSS H H IIIII 10 | //============================================================================== 11 | 12 | // Looks like Sony except for timings, 48 chars of data and time/space different 13 | 14 | #define MITSUBISHI_BITS 16 15 | 16 | // Mitsubishi RM 75501 17 | // 14200 7 41 7 42 7 42 7 17 7 17 7 18 7 41 7 18 7 17 7 17 7 18 7 41 8 17 7 17 7 18 7 17 7 18 | // #define MITSUBISHI_HDR_MARK 250 // seen range 3500 19 | #define MITSUBISHI_HDR_SPACE 350 // 7*50+100 20 | #define MITSUBISHI_ONE_MARK 1950 // 41*50-100 21 | #define MITSUBISHI_ZERO_MARK 750 // 17*50-100 22 | // #define MITSUBISHI_DOUBLE_SPACE_USECS 800 // usually ssee 713 - not using ticks as get number wrapround 23 | // #define MITSUBISHI_RPT_LENGTH 45000 24 | 25 | //+============================================================================= 26 | #if DECODE_MITSUBISHI 27 | bool IRrecv::decodeMitsubishi (decode_results *results) 28 | { 29 | // Serial.print("?!? decoding Mitsubishi:");Serial.print(irparams.rawlen); Serial.print(" want "); Serial.println( 2 * MITSUBISHI_BITS + 2); 30 | long data = 0; 31 | if (irparams.rawlen < 2 * MITSUBISHI_BITS + 2) return false ; 32 | int offset = 0; // Skip first space 33 | // Initial space 34 | 35 | #if 0 36 | // Put this back in for debugging - note can't use #DEBUG as if Debug on we don't see the repeat cos of the delay 37 | Serial.print("IR Gap: "); 38 | Serial.println( results->rawbuf[offset]); 39 | Serial.println( "test against:"); 40 | Serial.println(results->rawbuf[offset]); 41 | #endif 42 | 43 | #if 0 44 | // Not seeing double keys from Mitsubishi 45 | if (results->rawbuf[offset] < MITSUBISHI_DOUBLE_SPACE_USECS) { 46 | // Serial.print("IR Gap found: "); 47 | results->bits = 0; 48 | results->value = REPEAT; 49 | results->decode_type = MITSUBISHI; 50 | return true; 51 | } 52 | #endif 53 | 54 | offset++; 55 | 56 | // Typical 57 | // 14200 7 41 7 42 7 42 7 17 7 17 7 18 7 41 7 18 7 17 7 17 7 18 7 41 8 17 7 17 7 18 7 17 7 58 | 59 | // Initial Space 60 | if (!MATCH_MARK(results->rawbuf[offset], MITSUBISHI_HDR_SPACE)) return false ; 61 | offset++; 62 | 63 | while (offset + 1 < irparams.rawlen) { 64 | if (MATCH_MARK(results->rawbuf[offset], MITSUBISHI_ONE_MARK)) data = (data << 1) | 1 ; 65 | else if (MATCH_MARK(results->rawbuf[offset], MITSUBISHI_ZERO_MARK)) data <<= 1 ; 66 | else return false ; 67 | offset++; 68 | 69 | if (!MATCH_SPACE(results->rawbuf[offset], MITSUBISHI_HDR_SPACE)) break ; 70 | offset++; 71 | } 72 | 73 | // Success 74 | results->bits = (offset - 1) / 2; 75 | if (results->bits < MITSUBISHI_BITS) { 76 | results->bits = 0; 77 | return false; 78 | } 79 | 80 | results->value = data; 81 | results->decode_type = MITSUBISHI; 82 | return true; 83 | } 84 | #endif 85 | 86 | -------------------------------------------------------------------------------- /ir_NEC.cpp: -------------------------------------------------------------------------------- 1 | #include "IRremote.h" 2 | #include "IRremoteInt.h" 3 | 4 | //============================================================================== 5 | // N N EEEEE CCCC 6 | // NN N E C 7 | // N N N EEE C 8 | // N NN E C 9 | // N N EEEEE CCCC 10 | //============================================================================== 11 | 12 | #define NEC_BITS 32 13 | #define NEC_HDR_MARK 9000 14 | #define NEC_HDR_SPACE 4500 15 | #define NEC_BIT_MARK 560 16 | #define NEC_ONE_SPACE 1690 17 | #define NEC_ZERO_SPACE 560 18 | #define NEC_RPT_SPACE 2250 19 | 20 | //+============================================================================= 21 | #if SEND_NEC 22 | void IRsend::sendNEC (unsigned long data, int nbits) 23 | { 24 | // Set IR carrier frequency 25 | enableIROut(38); 26 | 27 | // Header 28 | mark(NEC_HDR_MARK); 29 | space(NEC_HDR_SPACE); 30 | 31 | // Data 32 | for (unsigned long mask = 1UL << (nbits - 1); mask; mask >>= 1) { 33 | if (data & mask) { 34 | mark(NEC_BIT_MARK); 35 | space(NEC_ONE_SPACE); 36 | } else { 37 | mark(NEC_BIT_MARK); 38 | space(NEC_ZERO_SPACE); 39 | } 40 | } 41 | 42 | // Footer 43 | mark(NEC_BIT_MARK); 44 | space(0); // Always end with the LED off 45 | } 46 | #endif 47 | 48 | //+============================================================================= 49 | // NECs have a repeat only 4 items long 50 | // 51 | #if DECODE_NEC 52 | bool IRrecv::decodeNEC (decode_results *results) 53 | { 54 | long data = 0; // We decode in to here; Start with nothing 55 | int offset = 1; // Index in to results; Skip first entry!? 56 | 57 | // Check header "mark" 58 | if (!MATCH_MARK(results->rawbuf[offset], NEC_HDR_MARK)) return false ; 59 | offset++; 60 | 61 | // Check for repeat 62 | if ( (irparams.rawlen == 4) 63 | && MATCH_SPACE(results->rawbuf[offset ], NEC_RPT_SPACE) 64 | && MATCH_MARK (results->rawbuf[offset+1], NEC_BIT_MARK ) 65 | ) { 66 | results->bits = 0; 67 | results->value = REPEAT; 68 | results->decode_type = NEC; 69 | return true; 70 | } 71 | 72 | // Check we have enough data 73 | if (irparams.rawlen < (2 * NEC_BITS) + 4) return false ; 74 | 75 | // Check header "space" 76 | if (!MATCH_SPACE(results->rawbuf[offset], NEC_HDR_SPACE)) return false ; 77 | offset++; 78 | 79 | // Build the data 80 | for (int i = 0; i < NEC_BITS; i++) { 81 | // Check data "mark" 82 | if (!MATCH_MARK(results->rawbuf[offset], NEC_BIT_MARK)) return false ; 83 | offset++; 84 | // Suppend this bit 85 | if (MATCH_SPACE(results->rawbuf[offset], NEC_ONE_SPACE )) data = (data << 1) | 1 ; 86 | else if (MATCH_SPACE(results->rawbuf[offset], NEC_ZERO_SPACE)) data = (data << 1) | 0 ; 87 | else return false ; 88 | offset++; 89 | } 90 | 91 | // Success 92 | results->bits = NEC_BITS; 93 | results->value = data; 94 | results->decode_type = NEC; 95 | 96 | return true; 97 | } 98 | #endif 99 | -------------------------------------------------------------------------------- /ir_Panasonic.cpp: -------------------------------------------------------------------------------- 1 | #include "IRremote.h" 2 | #include "IRremoteInt.h" 3 | 4 | //============================================================================== 5 | // PPPP AAA N N AAA SSSS OOO N N IIIII CCCC 6 | // P P A A NN N A A S O O NN N I C 7 | // PPPP AAAAA N N N AAAAA SSS O O N N N I C 8 | // P A A N NN A A S O O N NN I C 9 | // P A A N N A A SSSS OOO N N IIIII CCCC 10 | //============================================================================== 11 | 12 | #define PANASONIC_BITS 48 13 | #define PANASONIC_HDR_MARK 3502 14 | #define PANASONIC_HDR_SPACE 1750 15 | #define PANASONIC_BIT_MARK 502 16 | #define PANASONIC_ONE_SPACE 1244 17 | #define PANASONIC_ZERO_SPACE 400 18 | 19 | //+============================================================================= 20 | #if SEND_PANASONIC 21 | void IRsend::sendPanasonic (unsigned int address, unsigned long data) 22 | { 23 | // Set IR carrier frequency 24 | enableIROut(35); 25 | 26 | // Header 27 | mark(PANASONIC_HDR_MARK); 28 | space(PANASONIC_HDR_SPACE); 29 | 30 | // Address 31 | for (unsigned long mask = 1UL << (16 - 1); mask; mask >>= 1) { 32 | mark(PANASONIC_BIT_MARK); 33 | if (address & mask) space(PANASONIC_ONE_SPACE) ; 34 | else space(PANASONIC_ZERO_SPACE) ; 35 | } 36 | 37 | // Data 38 | for (unsigned long mask = 1UL << (32 - 1); mask; mask >>= 1) { 39 | mark(PANASONIC_BIT_MARK); 40 | if (data & mask) space(PANASONIC_ONE_SPACE) ; 41 | else space(PANASONIC_ZERO_SPACE) ; 42 | } 43 | 44 | // Footer 45 | mark(PANASONIC_BIT_MARK); 46 | space(0); // Always end with the LED off 47 | } 48 | #endif 49 | 50 | //+============================================================================= 51 | #if DECODE_PANASONIC 52 | bool IRrecv::decodePanasonic (decode_results *results) 53 | { 54 | unsigned long long data = 0; 55 | int offset = 1; 56 | 57 | if (!MATCH_MARK(results->rawbuf[offset++], PANASONIC_HDR_MARK )) return false ; 58 | if (!MATCH_MARK(results->rawbuf[offset++], PANASONIC_HDR_SPACE)) return false ; 59 | 60 | // decode address 61 | for (int i = 0; i < PANASONIC_BITS; i++) { 62 | if (!MATCH_MARK(results->rawbuf[offset++], PANASONIC_BIT_MARK)) return false ; 63 | 64 | if (MATCH_SPACE(results->rawbuf[offset],PANASONIC_ONE_SPACE )) data = (data << 1) | 1 ; 65 | else if (MATCH_SPACE(results->rawbuf[offset],PANASONIC_ZERO_SPACE)) data = (data << 1) | 0 ; 66 | else return false ; 67 | offset++; 68 | } 69 | 70 | results->value = (unsigned long)data; 71 | results->address = (unsigned int)(data >> 32); 72 | results->decode_type = PANASONIC; 73 | results->bits = PANASONIC_BITS; 74 | 75 | return true; 76 | } 77 | #endif 78 | 79 | -------------------------------------------------------------------------------- /ir_RC5_RC6.cpp: -------------------------------------------------------------------------------- 1 | #include "IRremote.h" 2 | #include "IRremoteInt.h" 3 | 4 | //+============================================================================= 5 | // Gets one undecoded level at a time from the raw buffer. 6 | // The RC5/6 decoding is easier if the data is broken into time intervals. 7 | // E.g. if the buffer has MARK for 2 time intervals and SPACE for 1, 8 | // successive calls to getRClevel will return MARK, MARK, SPACE. 9 | // offset and used are updated to keep track of the current position. 10 | // t1 is the time interval for a single bit in microseconds. 11 | // Returns -1 for error (measured time interval is not a multiple of t1). 12 | // 13 | #if (DECODE_RC5 || DECODE_RC6) 14 | int IRrecv::getRClevel (decode_results *results, int *offset, int *used, int t1) 15 | { 16 | int width; 17 | int val; 18 | int correction; 19 | int avail; 20 | 21 | if (*offset >= results->rawlen) return SPACE ; // After end of recorded buffer, assume SPACE. 22 | width = results->rawbuf[*offset]; 23 | val = ((*offset) % 2) ? MARK : SPACE; 24 | correction = (val == MARK) ? MARK_EXCESS : - MARK_EXCESS; 25 | 26 | if (MATCH(width, ( t1) + correction)) avail = 1 ; 27 | else if (MATCH(width, (2*t1) + correction)) avail = 2 ; 28 | else if (MATCH(width, (3*t1) + correction)) avail = 3 ; 29 | else return -1 ; 30 | 31 | (*used)++; 32 | if (*used >= avail) { 33 | *used = 0; 34 | (*offset)++; 35 | } 36 | 37 | DBG_PRINTLN( (val == MARK) ? "MARK" : "SPACE" ); 38 | 39 | return val; 40 | } 41 | #endif 42 | 43 | //============================================================================== 44 | // RRRR CCCC 55555 45 | // R R C 5 46 | // RRRR C 5555 47 | // R R C 5 48 | // R R CCCC 5555 49 | // 50 | // NB: First bit must be a one (start bit) 51 | // 52 | #define MIN_RC5_SAMPLES 11 53 | #define RC5_T1 889 54 | #define RC5_RPT_LENGTH 46000 55 | 56 | //+============================================================================= 57 | #if SEND_RC5 58 | void IRsend::sendRC5 (unsigned long data, int nbits) 59 | { 60 | // Set IR carrier frequency 61 | enableIROut(36); 62 | 63 | // Start 64 | mark(RC5_T1); 65 | space(RC5_T1); 66 | mark(RC5_T1); 67 | 68 | // Data 69 | for (unsigned long mask = 1UL << (nbits - 1); mask; mask >>= 1) { 70 | if (data & mask) { 71 | space(RC5_T1); // 1 is space, then mark 72 | mark(RC5_T1); 73 | } else { 74 | mark(RC5_T1); 75 | space(RC5_T1); 76 | } 77 | } 78 | 79 | space(0); // Always end with the LED off 80 | } 81 | #endif 82 | 83 | //+============================================================================= 84 | #if DECODE_RC5 85 | bool IRrecv::decodeRC5 (decode_results *results) 86 | { 87 | int nbits; 88 | long data = 0; 89 | int used = 0; 90 | int offset = 1; // Skip gap space 91 | 92 | if (irparams.rawlen < MIN_RC5_SAMPLES + 2) return false ; 93 | 94 | // Get start bits 95 | if (getRClevel(results, &offset, &used, RC5_T1) != MARK) return false ; 96 | if (getRClevel(results, &offset, &used, RC5_T1) != SPACE) return false ; 97 | if (getRClevel(results, &offset, &used, RC5_T1) != MARK) return false ; 98 | 99 | for (nbits = 0; offset < irparams.rawlen; nbits++) { 100 | int levelA = getRClevel(results, &offset, &used, RC5_T1); 101 | int levelB = getRClevel(results, &offset, &used, RC5_T1); 102 | 103 | if ((levelA == SPACE) && (levelB == MARK )) data = (data << 1) | 1 ; 104 | else if ((levelA == MARK ) && (levelB == SPACE)) data = (data << 1) | 0 ; 105 | else return false ; 106 | } 107 | 108 | // Success 109 | results->bits = nbits; 110 | results->value = data; 111 | results->decode_type = RC5; 112 | return true; 113 | } 114 | #endif 115 | 116 | //+============================================================================= 117 | // RRRR CCCC 6666 118 | // R R C 6 119 | // RRRR C 6666 120 | // R R C 6 6 121 | // R R CCCC 666 122 | // 123 | // NB : Caller needs to take care of flipping the toggle bit 124 | // 125 | #define MIN_RC6_SAMPLES 1 126 | #define RC6_HDR_MARK 2666 127 | #define RC6_HDR_SPACE 889 128 | #define RC6_T1 444 129 | #define RC6_RPT_LENGTH 46000 130 | 131 | #if SEND_RC6 132 | void IRsend::sendRC6 (unsigned long data, int nbits) 133 | { 134 | // Set IR carrier frequency 135 | enableIROut(36); 136 | 137 | // Header 138 | mark(RC6_HDR_MARK); 139 | space(RC6_HDR_SPACE); 140 | 141 | // Start bit 142 | mark(RC6_T1); 143 | space(RC6_T1); 144 | 145 | // Data 146 | for (unsigned long i = 1, mask = 1UL << (nbits - 1); mask; i++, mask >>= 1) { 147 | // The fourth bit we send is a "double width trailer bit" 148 | int t = (i == 4) ? (RC6_T1 * 2) : (RC6_T1) ; 149 | if (data & mask) { 150 | mark(t); 151 | space(t); 152 | } else { 153 | space(t); 154 | mark(t); 155 | } 156 | } 157 | 158 | space(0); // Always end with the LED off 159 | } 160 | #endif 161 | 162 | //+============================================================================= 163 | #if DECODE_RC6 164 | bool IRrecv::decodeRC6 (decode_results *results) 165 | { 166 | int nbits; 167 | long data = 0; 168 | int used = 0; 169 | int offset = 1; // Skip first space 170 | 171 | if (results->rawlen < MIN_RC6_SAMPLES) return false ; 172 | 173 | // Initial mark 174 | if (!MATCH_MARK(results->rawbuf[offset++], RC6_HDR_MARK)) return false ; 175 | if (!MATCH_SPACE(results->rawbuf[offset++], RC6_HDR_SPACE)) return false ; 176 | 177 | // Get start bit (1) 178 | if (getRClevel(results, &offset, &used, RC6_T1) != MARK) return false ; 179 | if (getRClevel(results, &offset, &used, RC6_T1) != SPACE) return false ; 180 | 181 | for (nbits = 0; offset < results->rawlen; nbits++) { 182 | int levelA, levelB; // Next two levels 183 | 184 | levelA = getRClevel(results, &offset, &used, RC6_T1); 185 | if (nbits == 3) { 186 | // T bit is double wide; make sure second half matches 187 | if (levelA != getRClevel(results, &offset, &used, RC6_T1)) return false; 188 | } 189 | 190 | levelB = getRClevel(results, &offset, &used, RC6_T1); 191 | if (nbits == 3) { 192 | // T bit is double wide; make sure second half matches 193 | if (levelB != getRClevel(results, &offset, &used, RC6_T1)) return false; 194 | } 195 | 196 | if ((levelA == MARK ) && (levelB == SPACE)) data = (data << 1) | 1 ; // inverted compared to RC5 197 | else if ((levelA == SPACE) && (levelB == MARK )) data = (data << 1) | 0 ; // ... 198 | else return false ; // Error 199 | } 200 | 201 | // Success 202 | results->bits = nbits; 203 | results->value = data; 204 | results->decode_type = RC6; 205 | return true; 206 | } 207 | #endif 208 | -------------------------------------------------------------------------------- /ir_Samsung.cpp: -------------------------------------------------------------------------------- 1 | #include "IRremote.h" 2 | #include "IRremoteInt.h" 3 | 4 | //============================================================================== 5 | // SSSS AAA MMM SSSS U U N N GGGG 6 | // S A A M M M S U U NN N G 7 | // SSS AAAAA M M M SSS U U N N N G GG 8 | // S A A M M S U U N NN G G 9 | // SSSS A A M M SSSS UUU N N GGG 10 | //============================================================================== 11 | 12 | #define SAMSUNG_BITS 32 13 | #define SAMSUNG_HDR_MARK 5000 14 | #define SAMSUNG_HDR_SPACE 5000 15 | #define SAMSUNG_BIT_MARK 560 16 | #define SAMSUNG_ONE_SPACE 1600 17 | #define SAMSUNG_ZERO_SPACE 560 18 | #define SAMSUNG_RPT_SPACE 2250 19 | 20 | //+============================================================================= 21 | #if SEND_SAMSUNG 22 | void IRsend::sendSAMSUNG (unsigned long data, int nbits) 23 | { 24 | // Set IR carrier frequency 25 | enableIROut(38); 26 | 27 | // Header 28 | mark(SAMSUNG_HDR_MARK); 29 | space(SAMSUNG_HDR_SPACE); 30 | 31 | // Data 32 | for (unsigned long mask = 1UL << (nbits - 1); mask; mask >>= 1) { 33 | if (data & mask) { 34 | mark(SAMSUNG_BIT_MARK); 35 | space(SAMSUNG_ONE_SPACE); 36 | } else { 37 | mark(SAMSUNG_BIT_MARK); 38 | space(SAMSUNG_ZERO_SPACE); 39 | } 40 | } 41 | 42 | // Footer 43 | mark(SAMSUNG_BIT_MARK); 44 | space(0); // Always end with the LED off 45 | } 46 | #endif 47 | 48 | //+============================================================================= 49 | // SAMSUNGs have a repeat only 4 items long 50 | // 51 | #if DECODE_SAMSUNG 52 | bool IRrecv::decodeSAMSUNG (decode_results *results) 53 | { 54 | long data = 0; 55 | int offset = 1; // Skip first space 56 | 57 | // Initial mark 58 | if (!MATCH_MARK(results->rawbuf[offset], SAMSUNG_HDR_MARK)) return false ; 59 | offset++; 60 | 61 | // Check for repeat 62 | if ( (irparams.rawlen == 4) 63 | && MATCH_SPACE(results->rawbuf[offset], SAMSUNG_RPT_SPACE) 64 | && MATCH_MARK(results->rawbuf[offset+1], SAMSUNG_BIT_MARK) 65 | ) { 66 | results->bits = 0; 67 | results->value = REPEAT; 68 | results->decode_type = SAMSUNG; 69 | return true; 70 | } 71 | if (irparams.rawlen < (2 * SAMSUNG_BITS) + 4) return false ; 72 | 73 | // Initial space 74 | if (!MATCH_SPACE(results->rawbuf[offset++], SAMSUNG_HDR_SPACE)) return false ; 75 | 76 | for (int i = 0; i < SAMSUNG_BITS; i++) { 77 | if (!MATCH_MARK(results->rawbuf[offset++], SAMSUNG_BIT_MARK)) return false ; 78 | 79 | if (MATCH_SPACE(results->rawbuf[offset], SAMSUNG_ONE_SPACE)) data = (data << 1) | 1 ; 80 | else if (MATCH_SPACE(results->rawbuf[offset], SAMSUNG_ZERO_SPACE)) data = (data << 1) | 0 ; 81 | else return false ; 82 | offset++; 83 | } 84 | 85 | // Success 86 | results->bits = SAMSUNG_BITS; 87 | results->value = data; 88 | results->decode_type = SAMSUNG; 89 | return true; 90 | } 91 | #endif 92 | 93 | -------------------------------------------------------------------------------- /ir_Sanyo.cpp: -------------------------------------------------------------------------------- 1 | #include "IRremote.h" 2 | #include "IRremoteInt.h" 3 | 4 | //============================================================================== 5 | // SSSS AAA N N Y Y OOO 6 | // S A A NN N Y Y O O 7 | // SSS AAAAA N N N Y O O 8 | // S A A N NN Y O O 9 | // SSSS A A N N Y OOO 10 | //============================================================================== 11 | 12 | // I think this is a Sanyo decoder: Serial = SA 8650B 13 | // Looks like Sony except for timings, 48 chars of data and time/space different 14 | 15 | #define SANYO_BITS 12 16 | #define SANYO_HDR_MARK 3500 // seen range 3500 17 | #define SANYO_HDR_SPACE 950 // seen 950 18 | #define SANYO_ONE_MARK 2400 // seen 2400 19 | #define SANYO_ZERO_MARK 700 // seen 700 20 | #define SANYO_DOUBLE_SPACE_USECS 800 // usually ssee 713 - not using ticks as get number wrapround 21 | #define SANYO_RPT_LENGTH 45000 22 | 23 | //+============================================================================= 24 | #if DECODE_SANYO 25 | bool IRrecv::decodeSanyo (decode_results *results) 26 | { 27 | long data = 0; 28 | int offset = 0; // Skip first space <-- CHECK THIS! 29 | 30 | if (irparams.rawlen < (2 * SANYO_BITS) + 2) return false ; 31 | 32 | #if 0 33 | // Put this back in for debugging - note can't use #DEBUG as if Debug on we don't see the repeat cos of the delay 34 | Serial.print("IR Gap: "); 35 | Serial.println( results->rawbuf[offset]); 36 | Serial.println( "test against:"); 37 | Serial.println(results->rawbuf[offset]); 38 | #endif 39 | 40 | // Initial space 41 | if (results->rawbuf[offset] < SANYO_DOUBLE_SPACE_USECS) { 42 | //Serial.print("IR Gap found: "); 43 | results->bits = 0; 44 | results->value = REPEAT; 45 | results->decode_type = SANYO; 46 | return true; 47 | } 48 | offset++; 49 | 50 | // Initial mark 51 | if (!MATCH_MARK(results->rawbuf[offset++], SANYO_HDR_MARK)) return false ; 52 | 53 | // Skip Second Mark 54 | if (!MATCH_MARK(results->rawbuf[offset++], SANYO_HDR_MARK)) return false ; 55 | 56 | while (offset + 1 < irparams.rawlen) { 57 | if (!MATCH_SPACE(results->rawbuf[offset++], SANYO_HDR_SPACE)) break ; 58 | 59 | if (MATCH_MARK(results->rawbuf[offset], SANYO_ONE_MARK)) data = (data << 1) | 1 ; 60 | else if (MATCH_MARK(results->rawbuf[offset], SANYO_ZERO_MARK)) data = (data << 1) | 0 ; 61 | else return false ; 62 | offset++; 63 | } 64 | 65 | // Success 66 | results->bits = (offset - 1) / 2; 67 | if (results->bits < 12) { 68 | results->bits = 0; 69 | return false; 70 | } 71 | 72 | results->value = data; 73 | results->decode_type = SANYO; 74 | return true; 75 | } 76 | #endif 77 | -------------------------------------------------------------------------------- /ir_Sharp.cpp: -------------------------------------------------------------------------------- 1 | #include "IRremote.h" 2 | #include "IRremoteInt.h" 3 | 4 | //============================================================================== 5 | // SSSS H H AAA RRRR PPPP 6 | // S H H A A R R P P 7 | // SSS HHHHH AAAAA RRRR PPPP 8 | // S H H A A R R P 9 | // SSSS H H A A R R P 10 | //============================================================================== 11 | 12 | // Sharp and DISH support by Todd Treece: http://unionbridge.org/design/ircommand 13 | // 14 | // The send function has the necessary repeat built in because of the need to 15 | // invert the signal. 16 | // 17 | // Sharp protocol documentation: 18 | // http://www.sbprojects.com/knowledge/ir/sharp.htm 19 | // 20 | // Here is the LIRC file I found that seems to match the remote codes from the 21 | // oscilloscope: 22 | // Sharp LCD TV: 23 | // http://lirc.sourceforge.net/remotes/sharp/GA538WJSA 24 | 25 | #define SHARP_BITS 15 26 | #define SHARP_BIT_MARK 245 27 | #define SHARP_ONE_SPACE 1805 28 | #define SHARP_ZERO_SPACE 795 29 | #define SHARP_GAP 600000 30 | #define SHARP_RPT_SPACE 3000 31 | 32 | #define SHARP_TOGGLE_MASK 0x3FF 33 | 34 | //+============================================================================= 35 | #if SEND_SHARP 36 | void IRsend::sendSharpRaw (unsigned long data, int nbits) 37 | { 38 | enableIROut(38); 39 | 40 | // Sending codes in bursts of 3 (normal, inverted, normal) makes transmission 41 | // much more reliable. That's the exact behaviour of CD-S6470 remote control. 42 | for (int n = 0; n < 3; n++) { 43 | for (unsigned long mask = 1UL << (nbits - 1); mask; mask >>= 1) { 44 | if (data & mask) { 45 | mark(SHARP_BIT_MARK); 46 | space(SHARP_ONE_SPACE); 47 | } else { 48 | mark(SHARP_BIT_MARK); 49 | space(SHARP_ZERO_SPACE); 50 | } 51 | } 52 | 53 | mark(SHARP_BIT_MARK); 54 | space(SHARP_ZERO_SPACE); 55 | delay(40); 56 | 57 | data = data ^ SHARP_TOGGLE_MASK; 58 | } 59 | } 60 | #endif 61 | 62 | //+============================================================================= 63 | // Sharp send compatible with data obtained through decodeSharp() 64 | // ^^^^^^^^^^^^^ FUNCTION MISSING! 65 | // 66 | #if SEND_SHARP 67 | void IRsend::sendSharp (unsigned int address, unsigned int command) 68 | { 69 | sendSharpRaw((address << 10) | (command << 2) | 2, SHARP_BITS); 70 | } 71 | #endif 72 | -------------------------------------------------------------------------------- /ir_Sony.cpp: -------------------------------------------------------------------------------- 1 | #include "IRremote.h" 2 | #include "IRremoteInt.h" 3 | 4 | //============================================================================== 5 | // SSSS OOO N N Y Y 6 | // S O O NN N Y Y 7 | // SSS O O N N N Y 8 | // S O O N NN Y 9 | // SSSS OOO N N Y 10 | //============================================================================== 11 | 12 | #define SONY_BITS 12 13 | #define SONY_HDR_MARK 2400 14 | #define SONY_HDR_SPACE 600 15 | #define SONY_ONE_MARK 1200 16 | #define SONY_ZERO_MARK 600 17 | #define SONY_RPT_LENGTH 45000 18 | #define SONY_DOUBLE_SPACE_USECS 500 // usually ssee 713 - not using ticks as get number wrapround 19 | 20 | //+============================================================================= 21 | #if SEND_SONY 22 | void IRsend::sendSony (unsigned long data, int nbits) 23 | { 24 | // Set IR carrier frequency 25 | enableIROut(40); 26 | 27 | // Header 28 | mark(SONY_HDR_MARK); 29 | space(SONY_HDR_SPACE); 30 | 31 | // Data 32 | for (unsigned long mask = 1UL << (nbits - 1); mask; mask >>= 1) { 33 | if (data & mask) { 34 | mark(SONY_ONE_MARK); 35 | space(SONY_HDR_SPACE); 36 | } else { 37 | mark(SONY_ZERO_MARK); 38 | space(SONY_HDR_SPACE); 39 | } 40 | } 41 | 42 | // We will have ended with LED off 43 | } 44 | #endif 45 | 46 | //+============================================================================= 47 | #if DECODE_SONY 48 | bool IRrecv::decodeSony (decode_results *results) 49 | { 50 | long data = 0; 51 | int offset = 0; // Dont skip first space, check its size 52 | 53 | if (irparams.rawlen < (2 * SONY_BITS) + 2) return false ; 54 | 55 | // Some Sony's deliver repeats fast after first 56 | // unfortunately can't spot difference from of repeat from two fast clicks 57 | if (results->rawbuf[offset] < SONY_DOUBLE_SPACE_USECS) { 58 | // Serial.print("IR Gap found: "); 59 | results->bits = 0; 60 | results->value = REPEAT; 61 | 62 | # ifdef DECODE_SANYO 63 | results->decode_type = SANYO; 64 | # else 65 | results->decode_type = UNKNOWN; 66 | # endif 67 | 68 | return true; 69 | } 70 | offset++; 71 | 72 | // Initial mark 73 | if (!MATCH_MARK(results->rawbuf[offset++], SONY_HDR_MARK)) return false ; 74 | 75 | while (offset + 1 < irparams.rawlen) { 76 | if (!MATCH_SPACE(results->rawbuf[offset++], SONY_HDR_SPACE)) break ; 77 | 78 | if (MATCH_MARK(results->rawbuf[offset], SONY_ONE_MARK)) data = (data << 1) | 1 ; 79 | else if (MATCH_MARK(results->rawbuf[offset], SONY_ZERO_MARK)) data = (data << 1) | 0 ; 80 | else return false ; 81 | offset++; 82 | } 83 | 84 | // Success 85 | results->bits = (offset - 1) / 2; 86 | if (results->bits < 12) { 87 | results->bits = 0; 88 | return false; 89 | } 90 | results->value = data; 91 | results->decode_type = SONY; 92 | return true; 93 | } 94 | #endif 95 | 96 | -------------------------------------------------------------------------------- /ir_Template.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Assuming the protocol we are adding is for the (imaginary) manufacturer: Shuzu 3 | 4 | Our fantasy protocol is a standard protocol, so we can use this standard 5 | template without too much work. Some protocols are quite unique and will require 6 | considerably more work in this file! It is way beyond the scope of this text to 7 | explain how to reverse engineer "unusual" IR protocols. But, unless you own an 8 | oscilloscope, the starting point is probably to use the rawDump.ino sketch and 9 | try to spot the pattern! 10 | 11 | Before you start, make sure the IR library is working OK: 12 | # Open up the Arduino IDE 13 | # Load up the rawDump.ino example sketch 14 | # Run it 15 | 16 | Now we can start to add our new protocol... 17 | 18 | 1. Copy this file to : ir_Shuzu.cpp 19 | 20 | 2. Replace all occurrences of "Shuzu" with the name of your protocol. 21 | 22 | 3. Tweak the #defines to suit your protocol. 23 | 24 | 4. If you're lucky, tweaking the #defines will make the default send() function 25 | work. 26 | 27 | 5. Again, if you're lucky, tweaking the #defines will have made the default 28 | decode() function work. 29 | 30 | You have written the code to support your new protocol! 31 | 32 | Now you must do a few things to add it to the IRremote system: 33 | 34 | 1. Open IRremote.h and make the following changes: 35 | REMEMEBER to change occurences of "SHUZU" with the name of your protocol 36 | 37 | A. At the top, in the section "Supported Protocols", add: 38 | #define DECODE_SHUZU 1 39 | #define SEND_SHUZU 1 40 | 41 | B. In the section "enumerated list of all supported formats", add: 42 | SHUZU, 43 | to the end of the list (notice there is a comma after the protocol name) 44 | 45 | C. Further down in "Main class for receiving IR", add: 46 | //...................................................................... 47 | #if DECODE_SHUZU 48 | bool decodeShuzu (decode_results *results) ; 49 | #endif 50 | 51 | D. Further down in "Main class for sending IR", add: 52 | //...................................................................... 53 | #if SEND_SHUZU 54 | void sendShuzu (unsigned long data, int nbits) ; 55 | #endif 56 | 57 | E. Save your changes and close the file 58 | 59 | 2. Now open irRecv.cpp and make the following change: 60 | 61 | A. In the function IRrecv::decode(), add: 62 | #ifdef DECODE_NEC 63 | DBG_PRINTLN("Attempting Shuzu decode"); 64 | if (decodeShuzu(results)) return true ; 65 | #endif 66 | 67 | B. Save your changes and close the file 68 | 69 | You will probably want to add your new protocol to the example sketch 70 | 71 | 3. Open MyDocuments\Arduino\libraries\IRremote\examples\IRrecvDumpV2.ino 72 | 73 | A. In the encoding() function, add: 74 | case SHUZU: Serial.print("SHUZU"); break ; 75 | 76 | Now open the Arduino IDE, load up the rawDump.ino sketch, and run it. 77 | Hopefully it will compile and upload. 78 | If it doesn't, you've done something wrong. Check your work. 79 | If you can't get it to work - seek help from somewhere. 80 | 81 | If you get this far, I will assume you have successfully added your new protocol 82 | There is one last thing to do. 83 | 84 | 1. Delete this giant instructional comment. 85 | 86 | 2. Send a copy of your work to us so we can include it in the library and 87 | others may benefit from your hard work and maybe even write a song about how 88 | great you are for helping them! :) 89 | 90 | Regards, 91 | BlueChip 92 | */ 93 | 94 | #include "IRremote.h" 95 | #include "IRremoteInt.h" 96 | 97 | //============================================================================== 98 | // 99 | // 100 | // S H U Z U 101 | // 102 | // 103 | //============================================================================== 104 | 105 | #define BITS 32 // The number of bits in the command 106 | 107 | #define HDR_MARK 1000 // The length of the Header:Mark 108 | #define HDR_SPACE 2000 // The lenght of the Header:Space 109 | 110 | #define BIT_MARK 3000 // The length of a Bit:Mark 111 | #define ONE_SPACE 4000 // The length of a Bit:Space for 1's 112 | #define ZERO_SPACE 5000 // The length of a Bit:Space for 0's 113 | 114 | #define OTHER 1234 // Other things you may need to define 115 | 116 | //+============================================================================= 117 | // 118 | #if SEND_SHUZU 119 | void IRsend::sendShuzu (unsigned long data, int nbits) 120 | { 121 | // Set IR carrier frequency 122 | enableIROut(38); 123 | 124 | // Header 125 | mark (HDR_MARK); 126 | space(HDR_SPACE); 127 | 128 | // Data 129 | for (unsigned long mask = 1UL << (nbits - 1); mask; mask >>= 1) { 130 | if (data & mask) { 131 | mark (BIT_MARK); 132 | space(ONE_SPACE); 133 | } else { 134 | mark (BIT_MARK); 135 | space(ZERO_SPACE); 136 | } 137 | } 138 | 139 | // Footer 140 | mark(BIT_MARK); 141 | space(0); // Always end with the LED off 142 | } 143 | #endif 144 | 145 | //+============================================================================= 146 | // 147 | #if DECODE_SHUZU 148 | bool IRrecv::decodeShuzu (decode_results *results) 149 | { 150 | unsigned long data = 0; // Somewhere to build our code 151 | int offset = 1; // Skip the Gap reading 152 | 153 | // Check we have the right amount of data 154 | if (irparams.rawlen != 1 + 2 + (2 * BITS) + 1) return false ; 155 | 156 | // Check initial Mark+Space match 157 | if (!MATCH_MARK (results->rawbuf[offset++], HDR_MARK )) return false ; 158 | if (!MATCH_SPACE(results->rawbuf[offset++], HDR_SPACE)) return false ; 159 | 160 | // Read the bits in 161 | for (int i = 0; i < SHUZU_BITS; i++) { 162 | // Each bit looks like: MARK + SPACE_1 -> 1 163 | // or : MARK + SPACE_0 -> 0 164 | if (!MATCH_MARK(results->rawbuf[offset++], BIT_MARK)) return false ; 165 | 166 | // IR data is big-endian, so we shuffle it in from the right: 167 | if (MATCH_SPACE(results->rawbuf[offset], ONE_SPACE)) data = (data << 1) | 1 ; 168 | else if (MATCH_SPACE(results->rawbuf[offset], ZERO_SPACE)) data = (data << 1) | 0 ; 169 | else return false ; 170 | offset++; 171 | } 172 | 173 | // Success 174 | results->bits = BITS; 175 | results->value = data; 176 | results->decode_type = SHUZU; 177 | return true; 178 | } 179 | #endif 180 | -------------------------------------------------------------------------------- /ir_Whynter.cpp: -------------------------------------------------------------------------------- 1 | #include "IRremote.h" 2 | #include "IRremoteInt.h" 3 | 4 | //============================================================================== 5 | // W W H H Y Y N N TTTTT EEEEE RRRRR 6 | // W W H H Y Y NN N T E R R 7 | // W W W HHHHH Y N N N T EEE RRRR 8 | // W W W H H Y N NN T E R R 9 | // WWW H H Y N N T EEEEE R R 10 | //============================================================================== 11 | 12 | #define WHYNTER_BITS 32 13 | #define WHYNTER_HDR_MARK 2850 14 | #define WHYNTER_HDR_SPACE 2850 15 | #define WHYNTER_BIT_MARK 750 16 | #define WHYNTER_ONE_MARK 750 17 | #define WHYNTER_ONE_SPACE 2150 18 | #define WHYNTER_ZERO_MARK 750 19 | #define WHYNTER_ZERO_SPACE 750 20 | 21 | //+============================================================================= 22 | #if SEND_WHYNTER 23 | void IRsend::sendWhynter (unsigned long data, int nbits) 24 | { 25 | // Set IR carrier frequency 26 | enableIROut(38); 27 | 28 | // Start 29 | mark(WHYNTER_ZERO_MARK); 30 | space(WHYNTER_ZERO_SPACE); 31 | 32 | // Header 33 | mark(WHYNTER_HDR_MARK); 34 | space(WHYNTER_HDR_SPACE); 35 | 36 | // Data 37 | for (unsigned long mask = 1UL << (nbits - 1); mask; mask >>= 1) { 38 | if (data & mask) { 39 | mark(WHYNTER_ONE_MARK); 40 | space(WHYNTER_ONE_SPACE); 41 | } else { 42 | mark(WHYNTER_ZERO_MARK); 43 | space(WHYNTER_ZERO_SPACE); 44 | } 45 | } 46 | 47 | // Footer 48 | mark(WHYNTER_ZERO_MARK); 49 | space(WHYNTER_ZERO_SPACE); // Always end with the LED off 50 | } 51 | #endif 52 | 53 | //+============================================================================= 54 | #if DECODE_WHYNTER 55 | bool IRrecv::decodeWhynter (decode_results *results) 56 | { 57 | long data = 0; 58 | int offset = 1; // skip initial space 59 | 60 | // Check we have the right amount of data 61 | if (irparams.rawlen < (2 * WHYNTER_BITS) + 6) return false ; 62 | 63 | // Sequence begins with a bit mark and a zero space 64 | if (!MATCH_MARK (results->rawbuf[offset++], WHYNTER_BIT_MARK )) return false ; 65 | if (!MATCH_SPACE(results->rawbuf[offset++], WHYNTER_ZERO_SPACE)) return false ; 66 | 67 | // header mark and space 68 | if (!MATCH_MARK (results->rawbuf[offset++], WHYNTER_HDR_MARK )) return false ; 69 | if (!MATCH_SPACE(results->rawbuf[offset++], WHYNTER_HDR_SPACE)) return false ; 70 | 71 | // data bits 72 | for (int i = 0; i < WHYNTER_BITS; i++) { 73 | if (!MATCH_MARK(results->rawbuf[offset++], WHYNTER_BIT_MARK)) return false ; 74 | 75 | if (MATCH_SPACE(results->rawbuf[offset], WHYNTER_ONE_SPACE )) data = (data << 1) | 1 ; 76 | else if (MATCH_SPACE(results->rawbuf[offset], WHYNTER_ZERO_SPACE)) data = (data << 1) | 0 ; 77 | else return false ; 78 | offset++; 79 | } 80 | 81 | // trailing mark 82 | if (!MATCH_MARK(results->rawbuf[offset], WHYNTER_BIT_MARK)) return false ; 83 | 84 | // Success 85 | results->bits = WHYNTER_BITS; 86 | results->value = data; 87 | results->decode_type = WHYNTER; 88 | return true; 89 | } 90 | #endif 91 | 92 | -------------------------------------------------------------------------------- /keywords.txt: -------------------------------------------------------------------------------- 1 | ####################################### 2 | # Syntax Coloring Map For IRremote 3 | ####################################### 4 | 5 | ####################################### 6 | # Datatypes (KEYWORD1) 7 | ####################################### 8 | 9 | decode_results KEYWORD1 10 | IRrecv KEYWORD1 11 | IRsend KEYWORD1 12 | 13 | ####################################### 14 | # Methods and Functions (KEYWORD2) 15 | ####################################### 16 | 17 | blink13 KEYWORD2 18 | decode KEYWORD2 19 | enableIRIn KEYWORD2 20 | resume KEYWORD2 21 | enableIROut KEYWORD2 22 | sendNEC KEYWORD2 23 | sendSony KEYWORD2 24 | sendSanyo KEYWORD2 25 | sendMitsubishi KEYWORD2 26 | sendRaw KEYWORD2 27 | sendRC5 KEYWORD2 28 | sendRC6 KEYWORD2 29 | sendDISH KEYWORD2 30 | sendSharp KEYWORD2 31 | sendSharpRaw KEYWORD2 32 | sendPanasonic KEYWORD2 33 | sendJVC KEYWORD2 34 | sendLG KEYWORD2 35 | 36 | ####################################### 37 | # Constants (LITERAL1) 38 | ####################################### 39 | 40 | NEC LITERAL1 41 | SONY LITERAL1 42 | SANYO LITERAL1 43 | MITSUBISHI LITERAL1 44 | RC5 LITERAL1 45 | RC6 LITERAL1 46 | DISH LITERAL1 47 | SHARP LITERAL1 48 | PANASONIC LITERAL1 49 | JVC LITERAL1 50 | LG LITERAL1 51 | AIWA_RC_T501 LITERAL1 52 | UNKNOWN LITERAL1 53 | REPEAT LITERAL1 54 | -------------------------------------------------------------------------------- /library.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "IRremote", 3 | "keywords": "infrared, ir, remote", 4 | "description": "Send and receive infrared signals with multiple protocols", 5 | "repository": 6 | { 7 | "type": "git", 8 | "url": "https://github.com/z3t0/Arduino-IRremote.git" 9 | }, 10 | "version": "2.3.3", 11 | "frameworks": "arduino", 12 | "platforms": "atmelavr", 13 | "authors" : 14 | [ 15 | { 16 | "name":"Rafi Khan", 17 | "email":"zetoslab@gmail.com" 18 | }, 19 | { 20 | "name":"Ken Shirriff", 21 | "email":"ken.shirriff@gmail.com" 22 | } 23 | ] 24 | } 25 | -------------------------------------------------------------------------------- /library.properties: -------------------------------------------------------------------------------- 1 | name=IRremote 2 | version=2.2.3 3 | author=shirriff 4 | maintainer=shirriff 5 | sentence=Send and receive infrared signals with multiple protocols 6 | paragraph=Send and receive infrared signals with multiple protocols 7 | category=Signal Input/Output 8 | url=https://github.com/shirriff/Arduino-IRremote.git 9 | architectures=* 10 | -------------------------------------------------------------------------------- /readmdFrench.md: -------------------------------------------------------------------------------- 1 | ## IRremote Library 2 | 3 | 4 | Cette bibliothèque vous permet d'envoyer et de recevoir des signaux infrarouges sur un Arduino. 5 | Des tutoriels et plus d'informations seront disponibles sur la page d'accueil officielle. 6 | 7 | ## Version - 2.2.3 8 | 9 | ## Installation 10 | 1. Allez à la [Releases](https://github.com/z3t0/Arduino-IRremote/releases) page. 11 | 2. Téléchargez la dernière version. 12 | 3. Extraire le fichier zip 13 | 4. Déplacez le dossier "IRremote" vers vos bibliothèques. 14 | 5. Assurez-vous de supprimer Arduino_Root / libraries / RobotIRremote. Où Arduino_Root fait référence au répertoire d'installation d'Arduino. La bibliothèque RobotIRremote a des définitions similaires à IRremote et provoque des erreurs. 15 | 16 | 17 | ## FAQ 18 | Je ne travaille pas correctement en utilisant Neopixels (aka WS2811 / WS2812 / WS2812B) 19 | Que vous utilisiez la librairie Adafruit Neopixel ou FastLED, les interruptions sont désactivées sur de nombreux processeurs bas de gamme comme les arduinos de base. À son tour, cela empêche le gestionnaire IR de s'exécuter quand il le faut. Il y a quelques solutions à ce processus, voir cette page de Marc MERLIN 20 | [cette page de Marc MERLIN](http://marc.merlins.org/perso/arduino/post_2017-04-03_Arduino-328P-Uno-Teensy3_1-ESP8266-ESP32-IR-and-Neopixels.html) 21 | 22 | 23 | ## Conseils pris en charge 24 | 25 | - Teensy 1.0 / 1.0++ / 2.0 / 2++ / 3.0 / 3.1 / Teensy-LC; Crédits: @PaulStoffregen (Teensy Team) 26 | - Sanguino 27 | - ATmega8, 48, 88, 168, 328 28 | - ATmega8535, 16, 32, 164, 324, 644, 1284, 29 | - ATmega64, 128 30 | - ATtiny 84 / 85 31 | - ESP32 (recevoir seulement) 32 | - ESP8266 est basé sur un ancien code qui n'est pas très récent, mais cela fonctionne raisonnablement bien. Voir https://github.com/markszabo/IRremoteESP8266 33 | Sparkfun Pro Micro 34 | 35 | 36 | 37 | 38 | Nous sommes ouverts aux suggestions d'ajout de support pour les nouveaux tableaux, cependant, nous vous recommandons fortement de contacter votre fournisseur et de fournir un soutien de leur côté. 39 | 40 | 41 | ## Spécifications matérielles 42 | 43 | 44 | | Carte/CPU | Envoyer Pin | Compteurs | 45 | |--------------------------------------------------------------------------|---------------------|-------------------| 46 | | [ATtiny84](https://github.com/SpenceKonde/ATTinyCore) | **6** | **1** | 47 | | [ATtiny85](https://github.com/SpenceKonde/ATTinyCore) | **1** | **TINY0** | 48 | | [ATmega8](https://github.com/MCUdude/MiniCore) | **9** | **1** | 49 | | Atmega32u4 | 5, 9, **13** | 1, 3, **4** | 50 | | [ATmega48, ATmega88, ATmega168, ATmega328](https://github.com/MCUdude/MiniCore) | **3**, 9 | 1, **2** | 51 | | [ATmega1284](https://github.com/MCUdude/MightyCore) | 13, 14, 6 | 1, **2**, 3 | 52 | | [ATmega164, ATmega324, ATmega644](https://github.com/MCUdude/MightyCore) | 13, **14** | 1, **2** | 53 | | [ATmega8535 ATmega16, ATmega32](https://github.com/MCUdude/MightyCore) | **13** | **1** | 54 | | [ATmega64, ATmega128](https://github.com/MCUdude/MegaCore) | **13** | **1** | 55 | | ATmega1280, ATmega2560 | 5, 6, **9**, 11, 46 | 1, **2**, 3, 4, 5 | 56 | | [ESP32](http://esp32.net/) | N/A (insupporté) | **1** | 57 | | [Sparkfun Pro Micro](https://www.sparkfun.com/products/12640) | 9, **5**, 5 | 1, **3**, 4_HS | 58 | | [Teensy 1.0](https://www.pjrc.com/teensy/) | **17** | **1** | 59 | | [Teensy 2.0](https://www.pjrc.com/teensy/) | 9, **10**, 14 | 1, 3, **4_HS** | 60 | | [Teensy++ 1.0 / 2.0](https://www.pjrc.com/teensy/) | **1**, 16, 25 | 1, **2**, 3 | 61 | | [Teensy 3.0 / 3.1](https://www.pjrc.com/teensy/) | **5** | **CMT** | 62 | | [Teensy-LC](https://www.pjrc.com/teensy/) | **16** | **TPM1** | 63 | 64 | 65 | ## Patchs expérimentaux 66 | 67 | Voici les correctifs strictement pris en charge qui n'ont pas encore été intégrés. Si vous avez des questions, n'hésitez pas à demander ici. Si cela fonctionne, faites le nous savoir! 68 | 69 | [Arduino 101](https://github.com/z3t0/Arduino-IRremote/pull/481#issuecomment-311243146) 70 | 71 | Le tableau ci-dessus répertorie les temporisations actuellement supportées et les broches d'envoi correspondantes, beaucoup de ces broches supplémentaires sont ouvertes. 72 | 73 | 74 | ## Utilisation 75 | - À faire TODO (Vérifier les exemples pour l'instant) 76 | 77 | 78 | ## Contribution 79 | Si vous voulez contribuer à ce projet: 80 | - Signaler les bogues et les erreurs 81 | - Demander des améliorations 82 | - Créer des problèmes et tirer des requêtes 83 | - Parlez de cette bibliothèque à d'autres personnes 84 | - Contribuer de nouveaux protocoles 85 | Vérifiez ici [ici](Contributing.md) pour quelques guidelines 86 | 87 | 88 | ## Contact 89 | Email: zetoslab@gmail.com 90 | Please only email me if it is more appropriate than creating an Issue / PR. I **will** not respond to requests for adding support for particular boards, unless of course you are the creator of the board and would like to cooperate on the project. I will also **ignore** any emails asking me to tell you how to implement your ideas. However, if you have a private inquiry that you would only apply to you and you would prefer it to be via email, by all means. 91 | 92 | ## Contributeurs 93 | Check [here](Contributors.md) 94 | @Lsuperman735 French translation 95 | 96 | ## Copyright 97 | Copyright 2009-2012 Ken Shirriff 98 | -------------------------------------------------------------------------------- /test/ir_atmega328p_4_base-carrier.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SensorsIot/Arduino-IRremote/41fb407cba2484e30ca64228799ad9663568bfab/test/ir_atmega328p_4_base-carrier.PNG -------------------------------------------------------------------------------- /test/ir_esp32_4_base-carrier.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SensorsIot/Arduino-IRremote/41fb407cba2484e30ca64228799ad9663568bfab/test/ir_esp32_4_base-carrier.PNG -------------------------------------------------------------------------------- /test/ir_esp32_4_base-carrier_afterFix.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SensorsIot/Arduino-IRremote/41fb407cba2484e30ca64228799ad9663568bfab/test/ir_esp32_4_base-carrier_afterFix.PNG --------------------------------------------------------------------------------