├── .github ├── issue_template.md └── workflows │ └── LibraryBuild.yml ├── .gitignore ├── Contributing.md ├── Contributors.md ├── Doxyfile ├── LICENSE.txt ├── README.md ├── changelog.md ├── examples ├── BoseWaveSendDemo │ └── BoseWaveSendDemo.ino ├── IR2Keyboard │ └── IR2Keyboard.ino ├── IRreceiveDemo │ └── IRreceiveDemo.ino ├── IRreceiveDump │ └── IRreceiveDump.ino ├── IRreceiveDumpV2 │ └── IRreceiveDumpV2.ino ├── IRrecord │ └── IRrecord.ino ├── IRrelay │ └── IRrelay.ino ├── IRremoteInfo │ └── IRremoteInfo.ino ├── IRsendDemo │ ├── ATtinySerialOut.cpp │ ├── ATtinySerialOut.h │ └── IRsendDemo.ino ├── IRsendNecStandardDemo │ └── IRsendNecStandardDemo.ino ├── IRsendProntoDemo │ └── IRsendProntoDemo.ino ├── IRsendRawDemo │ └── IRsendRawDemo.ino ├── IRtest │ └── IRtest.ino ├── IRtest2 │ └── IRtest2.ino ├── JVCPanasonicSendDemo │ └── JVCPanasonicSendDemo.ino ├── LGACSendDemo │ ├── LGACSendDemo.ino │ └── LGACSendDemo.md ├── LegoPowerFunctionsSendDemo │ └── LegoPowerFunctionsSendDemo.ino ├── LegoPowerFunctionsTests │ └── LegoPowerFunctionsTests.ino └── MicroGirs │ └── MicroGirs.ino ├── keywords.txt ├── library.json ├── library.properties ├── readmdFrench.md └── src ├── IRremote.cpp ├── IRremote.h ├── esp32.cpp ├── irPronto.cpp ├── irReceive.cpp ├── irSend.cpp ├── ir_BoseWave.cpp ├── ir_Denon.cpp ├── ir_Dish.cpp ├── ir_JVC.cpp ├── ir_LG.cpp ├── ir_Lego_PF.cpp ├── ir_Lego_PF_BitStreamEncoder.h ├── ir_MagiQuest.cpp ├── ir_NEC.cpp ├── ir_Panasonic.cpp ├── ir_RC5_RC6.cpp ├── ir_Samsung.cpp ├── ir_Sanyo.cpp ├── ir_Sharp.cpp ├── ir_Sharp_alt.cpp ├── ir_Sony.cpp ├── ir_Template.cpp ├── ir_Whynter.cpp ├── nRF5.cpp ├── private ├── IRremoteBoardDefs.h └── IRremoteInt.h └── sam.cpp /.github/issue_template.md: -------------------------------------------------------------------------------- 1 | ### Board 2 | * [ ] Arduino ATmega328* board (UNO, Nano) 3 | * [ ] Arduino ATmega2560 board (Mega) 4 | * [ ] Arduino ATmega32U4 board (Leonardo) 5 | * [ ] ATtiny85 board (ATTinyCore by Spence Conde) 6 | * [ ] Digispark board 7 | * [ ] Arduino SAM board (Due) 8 | * [ ] Arduino SAMD board (Zero, MKR*) 9 | * [ ] ESP32 board - first check https://github.com/crankyoldgit/IRremoteESP8266 10 | * [ ] Teensy board 11 | * [ ] Other - please specify 12 | 13 | ### Protocol 14 | * [ ] Unknown 15 | * [ ] BoseWave 16 | * [ ] Denon 17 | * [ ] Dish 18 | * [ ] JVC 19 | * [ ] Lego 20 | * [ ] LG 21 | * [ ] NEC 22 | * [ ] Panasonic 23 | * [ ] RC5, RC6 24 | * [ ] Samsung 25 | * [ ] Sanyo 26 | * [ ] Sharp 27 | * [ ] Sony 28 | * [ ] Whynter 29 | * [ ] Other - please specify 30 | 31 | 32 | **Code Block:** 33 | ``` 34 | 35 | #include 36 | 37 | ..... 38 | 39 | ``` 40 | 41 | Use [a gist](gist.github.com) if the code exceeds 30 lines 42 | 43 | **checklist:** 44 | - [] I have **read** the README.md file thoroughly 45 | - [] I have searched existing issues to see if there is anything I have missed. 46 | - [] The latest [release](https://github.com/z3t0/Arduino-IRremote/releases/latest) is used 47 | - [] Any code referenced is provided and if over 30 lines a gist is linked INSTEAD of it being pasted in here 48 | - [] The title of the issue is helpful and relevant 49 | 50 | ** 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!** 51 | 52 | The above is a short template allowing you to make detailed issues! 53 | -------------------------------------------------------------------------------- /.github/workflows/LibraryBuild.yml: -------------------------------------------------------------------------------- 1 | # LibraryBuild.yml 2 | # Github workflow script to test compile all examples of an Arduino library repository. 3 | # 4 | # Copyright (C) 2020 Armin Joachimsmeyer 5 | # https://github.com/ArminJo/Github-Actions 6 | # 7 | # Before being able to push to my .github\workflows directories, 8 | # I had to create a new personal token with workflow enabled at https://github.com/settings/tokens 9 | 10 | # This is the name of the workflow, visible on GitHub UI. 11 | name: LibraryBuild 12 | on: 13 | push: # see: https://help.github.com/en/actions/reference/events-that-trigger-workflows#pull-request-event-pull_request 14 | paths: 15 | - '**.ino' 16 | - '**.cpp' 17 | - '**.h' 18 | - '**LibraryBuild.yml' 19 | pull_request: 20 | paths: 21 | - '**.ino' 22 | - '**.cpp' 23 | - '**.h' 24 | - '**LibraryBuild.yml' 25 | 26 | jobs: 27 | build: 28 | name: ${{ matrix.arduino-boards-fqbn }} - test compiling examples 29 | 30 | runs-on: ubuntu-18.04 # I picked Ubuntu to use shell scripts. 31 | 32 | env: 33 | # Comma separated list without double quotes around the list. 34 | REQUIRED_LIBRARIES: Keyboard 35 | 36 | strategy: 37 | matrix: 38 | # The matrix will produce one job for each configuration parameter of type `arduino-boards-fqbn` 39 | # In the Arduino IDE, the fqbn is printed in the first line of the verbose output for compilation as parameter -fqbn=... for the "arduino-builder -dump-prefs" command 40 | # 41 | # Examples: arduino:avr:uno, arduino:avr:leonardo, arduino:avr:nano, arduino:avr:mega 42 | # arduino:sam:arduino_due_x, arduino:samd:arduino_zero_native" 43 | # ATTinyCore:avr:attinyx5:chip=85,clock=1internal, digistump:avr:digispark-tiny, digistump:avr:digispark-pro 44 | # STM32:stm32:GenF1:pnum=BLUEPILL_F103C8 45 | # esp8266:esp8266:huzzah:eesz=4M3M,xtal=80, esp32:esp32:featheresp32:FlashFreq=80 46 | # You may add a suffix behind the fqbn with "|" to specify one board for e.g. different compile options like arduino:avr:uno|trace 47 | ############################################################################################################# 48 | arduino-boards-fqbn: 49 | - arduino:avr:uno 50 | - arduino:avr:uno|USE_NEC_STANDARD 51 | - arduino:avr:uno|USE_NO_SEND_PWM 52 | - arduino:avr:leonardo 53 | - arduino:megaavr:nona4809:mode=off 54 | - digistump:avr:digispark-tiny:clock=clock1 55 | - ATTinyCore:avr:attinyx5:chip=85,clock=1internal 56 | - arduino:samd:arduino_zero_native 57 | - esp32:esp32:featheresp32:FlashFreq=80 58 | - SparkFun:avr:promicro 59 | - sandeepmistry:nRF5:BBCmicrobit 60 | 61 | # Specify parameters for each board. 62 | # With sketches-exclude you may exclude specific examples for a board. Use a comma separated list. 63 | ############################################################################################################# 64 | include: 65 | - arduino-boards-fqbn: arduino:avr:uno 66 | sketches-exclude: IR2Keyboard 67 | 68 | - arduino-boards-fqbn: arduino:avr:uno|USE_NEC_STANDARD 69 | sketches-exclude: IR2Keyboard 70 | build-properties: # the flags were put in compiler.cpp.extra_flags 71 | All: -DUSE_NEC_STANDARD 72 | 73 | - arduino-boards-fqbn: arduino:avr:uno|USE_NO_SEND_PWM 74 | sketches-exclude: IR2Keyboard 75 | build-properties: # the flags were put in compiler.cpp.extra_flags 76 | All: -DUSE_NO_SEND_PWM 77 | 78 | - arduino-boards-fqbn: arduino:megaavr:nona4809:mode=off 79 | sketches-exclude: IR2Keyboard 80 | 81 | - arduino-boards-fqbn: digistump:avr:digispark-tiny:clock=clock1 82 | platform-url: https://raw.githubusercontent.com/ArminJo/DigistumpArduino/master/package_digistump_index.json 83 | sketches-exclude: IR2Keyboard,IRtest,IRtest2,IRrelay,LegoPowerFunctionsTests,IRrecord,IRreceiveDumpV2,IRsendProntoDemo,MicroGirs # Does not fit in FLASH or RAM # Comma separated list of (unique substrings of) example names to exclude in build 84 | 85 | - arduino-boards-fqbn: ATTinyCore:avr:attinyx5:chip=85,clock=1internal 86 | platform-url: http://drazzy.com/package_drazzy.com_index.json 87 | sketches-exclude: IR2Keyboard,IRtestIRtest2,IRrelay,LegoPowerFunctionsTests,IRrecord,IRreceiveDumpV2,IRsendProntoDemo,MicroGirs,BoseWaveSendDemo # Does not fit in FLASH or RAM 88 | 89 | - arduino-boards-fqbn: esp32:esp32:featheresp32:FlashFreq=80 90 | platform-url: https://dl.espressif.com/dl/package_esp32_index.json 91 | sketches-exclude: IR2Keyboard,LGACSendDemo # undefined reference to `TwoWire::onReceive(void (*)(int))' 92 | 93 | - arduino-boards-fqbn: SparkFun:avr:promicro 94 | arduino-platform: arduino:avr,SparkFun:avr 95 | platform-url: https://raw.githubusercontent.com/sparkfun/Arduino_Boards/master/IDE_Board_Manager/package_sparkfun_index.json # Arduino URL is not required here 96 | 97 | - arduino-boards-fqbn: sandeepmistry:nRF5:BBCmicrobit 98 | platform-url: https://sandeepmistry.github.io/arduino-nRF5/package_nRF5_boards_index.json 99 | sketches-exclude: IR2Keyboard,BoseWaveSendDemo,IRrecord,IRsendDemo,IRsendProntoDemo,IRsendRawDemo,IRsendNecStandardDemo,IRtest,IRtest2,LegoPowerFunctionsSendDemo,JVCPanasonicSendDemo,LGACSendDemo,MicroGirs # no sending yet 100 | 101 | 102 | # Do not cancel all jobs / architectures if one job fails 103 | fail-fast: false 104 | 105 | steps: 106 | - name: Checkout 107 | uses: actions/checkout@master 108 | 109 | - name: Compile all examples using the arduino-test-compile action 110 | uses: ArminJo/arduino-test-compile@master 111 | with: 112 | arduino-board-fqbn: ${{ matrix.arduino-boards-fqbn }} 113 | arduino-platform: ${{ matrix.arduino-platform }} 114 | platform-url: ${{ matrix.platform-url }} 115 | required-libraries: ${{ env.REQUIRED_LIBRARIES }} 116 | sketches-exclude: ${{ matrix.sketches-exclude }} 117 | build-properties: ${{ toJson(matrix.build-properties) }} 118 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | nbproject 2 | api-doc 3 | *~ 4 | docs 5 | -------------------------------------------------------------------------------- /Contributing.md: -------------------------------------------------------------------------------- 1 | # Contribution Guidelines 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 | - Use the style; we use the original [C Style by Kerninghan / Ritchie](https://en.wikipedia.org/wiki/Indentation_style#K&R_style) in [variant: 1TBS (OTBS)](https://en.wikipedia.org/wiki/Indentation_style#Variant:_1TBS_(OTBS)). In short: 4 spaces indentation, no tabs, opening braces on the same line, braces are mandatory on all if/while/do, no hard line length limit. To beautify your code, you may use the online formatter [here](https://www.freecodeformat.com/c-format.php). 11 | - Choose the right Pull Request target; if you only have **minor changes or adding a new protocol**, choose **master** as target for your Pull Request. If have a change **addressing more general aspects** of this library or think, that the PR should be **discussed and reviewed**, choose the **dev** branch as target for your Pull Request like described [here](https://guides.github.com/introduction/flow/). 12 | 13 | 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) 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 | - [Informatic](https://github.com/Informatic) 8 | - [fmeschia](https://github.com/fmeschia) 9 | - [PaulStoffregen](https://github.com/paulstroffregen) 10 | - [crash7](https://github.com/crash7) 11 | - [Neco777](https://github.com/neco777) 12 | - [Lauszus](https://github.com/lauszus) 13 | - [csBlueChip](https://github.com/csbluechip) contributed major and vital changes to the code base. 14 | - [Sebazzz](https://github.com/sebazz) 15 | - [lumbric](https://github.com/lumbric) 16 | - [ElectricRCAircraftGuy](https://github.com/electricrcaircraftguy) 17 | - [philipphenkel](https://github.com/philipphenkel) 18 | - [MCUdude](https://github.com/MCUdude) 19 | - [adamlhumphreys](https://github.com/adamlhumphreys) (code space improvements) 20 | - [marcmerlin](https://github.com/marcmerlin) (ESP32 port) 21 | - [MrBryonMiller](https://github.com/MrBryonMiller) 22 | - [bengtmartensson](https://github.com/bengtmartensson) providing support 23 | - [AnalysIR](https:/github.com/AnalysIR) providing support 24 | - [ArminJo](https://github.com/ArminJo) Maintainer 25 | - [eshicks4](https://github.com/eshicks4) 26 | 27 | Note: Please let [z3t0](https://github.com/z3t0) know if you have been missed. 28 | -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- 1 | 2 | (c) Copyright 2009 Ken Shirriff http://www.righto.com 3 | (c) Copyright 2016 Rafi Khan 4 | (c) Copyright 2020 Armin Joachimsmeyer et al. 5 | 6 | Licensed under the MIT license: 7 | 8 | http://www.opensource.org/licenses/mit-license.php 9 | 10 | Permission is hereby granted, free of charge, to any person obtaining a copy 11 | of this software and associated documentation files (the "Software"), to deal 12 | in the Software without restriction, including without limitation the rights 13 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 14 | copies of the Software, and to permit persons to whom the Software is 15 | furnished to do so, subject to the following conditions: 16 | 17 | The above copyright notice and this permission notice shall be included in 18 | all copies or substantial portions of the Software. 19 | 20 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 21 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 22 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 23 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 24 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 25 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 26 | THE SOFTWARE. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iosifpeterfi/Arduino-IRremote/1988f15c1623790b66355bc9e84ccf10235988a7/README.md -------------------------------------------------------------------------------- /changelog.md: -------------------------------------------------------------------------------- 1 | ## 2.8.2 2020/11 2 | - Added SendRaw with byte data. 3 | 4 | ## 2.8.1 2020/10 5 | - Fixed bug in Sony decode introduced in 2.8.0. 6 | 7 | ## 2.8.0 2020/10 8 | - Changed License to MIT see https://github.com/z3t0/Arduino-IRremote/issues/397. 9 | - Added ATtiny timer 1 support. 10 | - Changed wrong return code signature of decodePulseDistanceData() and its handling. 11 | - Removed Mitsubishi protocol, since the implementation is in contradiction with all documentation I could found and therefore supposed to be wrong. 12 | - Removed AIWA implementation, since it is only for 1 device and at least sending implemented wrong. 13 | - Added Lego_PF decode. 14 | - Added new example IR2Keyboard. 15 | - Changed internal usage of custom_delay_usec. 16 | - Moved dump/print functions from example to irReceiver. 17 | - irPronto.cpp: Using Print instead of Stream saves 1020 bytes program memory. Changed from & to * parameter type to be more transparent and consistent with other code of IRremote. 18 | 19 | ## 2.7.0 2020/09 20 | - Added ATmega328PB support. 21 | - Renamed hardware specific macro and function names. 22 | - Renamed `USE_SOFT_CARRIER`, `USE_NO_CARRIER`, `DUTY_CYCLE` macros to `USE_SOFT_SEND_PWM`, `USE_NO_SEND_PWM`, `IR_SEND_DUTY_CYCLE`. 23 | - Removed blocking wait for ATmega32U4 Serial in examples. 24 | - Deactivated default debug output. 25 | - Optimized types in sendRC5ext and sendSharpAlt. 26 | - Added `DECODE_NEC_STANDARD` and `SEND_NEC_STANDARD`. 27 | - Renamed all IRrecv* examples to IRreceive*. 28 | - Added functions `printResultShort(&Serial)` and `getProtocolString(decode_type_t aDecodeType)`. 29 | - Added flag `results.isRepeat`. 30 | - Updated examples. 31 | 32 | ## 2.6.1 2020/08 33 | - Adjusted JVC and LG timing. 34 | - Fixed 4809 bug. 35 | 36 | ## 2.6.0 2020/08 37 | - Added support for MagiQuest IR wands. 38 | - Corrected Samsung timing. 39 | - NEC repeat implementation. 40 | - Formatting and changing `TIMER_CONFIG_KHZ` and `TIMER_CONFIG_NORMAL` macros to static functions. 41 | - Added `IRAM_ATTR` for ESP32 ISR. 42 | - Removed #define `HAS_AVR_INTERRUPT_H`. 43 | - Changed Receiver States. Now starting with 0. 44 | - Changed switch to if / else if in IRRemote.cpp because of ESP32 compiler bug. 45 | - Changed `DEBUG` handling since compiler warns about empty "IF" or "ELSE" statements in IRRemote.cpp. 46 | 47 | ## 2.5.0 2020/06 48 | - Corrected keywords.txt. 49 | - BoseWave protocol added PR #690. 50 | - Formatting comply to the new stylesheet. 51 | - Renamed "boarddefs.h" [ISSUE #375](https://github.com/z3t0/Arduino-IRremote/issues/375). 52 | - Renamed `SEND_PIN` to `IR_SEND_PIN`. 53 | - Renamed state macros. 54 | - Enabled `DUTY_CYCLE` for send signal. 55 | - Added sending for ESP32. 56 | - Changed rawlen from uint8_t to unsigned int allowing bigger receive buffer and renamed `RAWBUF` to `RAW_BUFFER_LENGTH`. 57 | - Introduced `USE_NO_CARRIER` for simulating an IR receiver. 58 | Changes from #283 by bengtmartensson 59 | - Added function sendRaw_P() for sending data from flash. 60 | Changes from #268 by adamlhumphreys 61 | - Optimized by reducing floating point operations as suggested by @madmalkav (#193). 62 | - Optimized with macros when using default `MICROS_PER_TICK` and `TOLERANCE`. 63 | - Made decodeHash as a settable protocol defined by `DECODE_HASH`. 64 | - Added Philips Extended RC-5 protocol support [PR #522] (https://github.com/z3t0/Arduino-IRremote/pull/522) 65 | 66 | ## 2.4.0 - 2017/08/10 67 | - Cleanup of hardware dependencies. Merge in SAM support [PR #437](https://github.com/z3t0/Arduino-IRremote/pull/437) 68 | 69 | ## 2.3.3 - 2017/03/31 70 | - Added ESP32 IR receive support [PR #427](https://github.com/z3t0/Arduino-IRremote/pull/425) 71 | 72 | ## 2.2.3 - 2017/03/27 73 | - Fix calculation of pause length in LEGO PF protocol [PR #427](https://github.com/z3t0/Arduino-IRremote/pull/427) 74 | 75 | ## 2.2.2 - 2017/01/20 76 | - Fixed naming bug [PR #398](https://github.com/z3t0/Arduino-IRremote/pull/398) 77 | 78 | ## 2.2.1 - 2016/07/27 79 | - Added tests for Lego Power Functions Protocol [PR #336](https://github.com/z3t0/Arduino-IRremote/pull/336) 80 | 81 | ## 2.2.0 - 2016/06/28 82 | - Added support for ATmega8535 83 | - Added support for ATmega16 84 | - Added support for ATmega32 85 | - Added support for ATmega164 86 | - Added support for ATmega324 87 | - Added support for ATmega644 88 | - Added support for ATmega1284 89 | - Added support for ATmega64 90 | - Added support for ATmega128 91 | 92 | [PR](https://github.com/z3t0/Arduino-IRremote/pull/324) 93 | 94 | ## 2.1.1 - 2016/05/04 95 | - Added Lego Power Functions Protocol [PR #309](https://github.com/z3t0/Arduino-IRremote/pull/309) 96 | 97 | ## 2.1.0 - 2016/02/20 98 | - Improved Debugging [PR #258](https://github.com/z3t0/Arduino-IRremote/pull/258) 99 | - Display TIME instead of TICKS [PR #258](https://github.com/z3t0/Arduino-IRremote/pull/258) 100 | 101 | ## 2.0.4 - 2016/02/20 102 | - Add Panasonic and JVC to IRrecord example [PR](https://github.com/z3t0/Arduino-IRremote/pull/54) 103 | 104 | ## 2.0.3 - 2016/02/20 105 | - Change IRSend Raw parameter to const [PR](https://github.com/z3t0/Arduino-IRremote/pull/227) 106 | 107 | ## 2.0.2 - 2015/12/02 108 | - Added IRremoteInfo Sketch - [PR](https://github.com/z3t0/Arduino-IRremote/pull/241) 109 | - Enforcing changelog.md 110 | 111 | ## 2.0.1 - 2015/07/26 - [Release](https://github.com/shirriff/Arduino-IRremote/releases/tag/BETA) 112 | ### Changes 113 | - Updated README 114 | - Updated Contributors 115 | - Fixed #110 Mess 116 | - Created Gitter Room 117 | - Added Gitter Badge 118 | - Standardised Code Base 119 | - Clean Debug Output 120 | - Optimized Send Loops 121 | - Modularized Design 122 | - Optimized and Updated Examples 123 | - Improved Documentation 124 | - Fixed and Improved many coding errors 125 | - Fixed Aiwa RC-T501 Decoding 126 | - Fixed Interrupt on ATmega8 127 | - Switched to Stable Release of @PlatformIO 128 | 129 | ### Additions 130 | - Added Aiwa RC-T501 Protocol 131 | - Added Denon Protocol 132 | - Added Pronto Support 133 | - Added Library Properties 134 | - Added Template For New Protocols 135 | - Added this changelog 136 | - Added Teensy LC Support 137 | - Added ATtiny84 Support 138 | - Added ATtiny85 Support 139 | - Added isIdle method 140 | 141 | ### Deletions 142 | - Removed (Fixed) #110 143 | - Broke Teensy 3 / 3.1 Support 144 | 145 | ### Not Working 146 | - Teensy 3 / 3.1 Support is in Development 147 | -------------------------------------------------------------------------------- /examples/BoseWaveSendDemo/BoseWaveSendDemo.ino: -------------------------------------------------------------------------------- 1 | /* 2 | * Based on IRremote: IRsendDemo by Ken Shirriff 3 | * 4 | * Prompt user for a code to send. Make sure your 940-950nm IR LED is 5 | * connected to the default digital output. Place your Bose Wave Radio 6 | * CD in the line of sight of your LED, and send commands! 7 | */ 8 | #include 9 | 10 | IRsend IrSender; 11 | 12 | // On the Zero and others we switch explicitly to SerialUSB 13 | #if defined(ARDUINO_ARCH_SAMD) 14 | #define Serial SerialUSB 15 | #endif 16 | 17 | bool prompt; 18 | void menu(); 19 | 20 | void setup() { 21 | pinMode(LED_BUILTIN, OUTPUT); 22 | 23 | Serial.begin(115200); 24 | #if defined(__AVR_ATmega32U4__) || defined(SERIAL_USB) || defined(SERIAL_PORT_USBVIRTUAL) 25 | delay(2000); // To be able to connect Serial monitor after reset and before first printout 26 | #endif 27 | // Just to know which program is running on my Arduino 28 | Serial.println(F("START " __FILE__ " from " __DATE__)); 29 | 30 | prompt = true; 31 | } 32 | 33 | void loop() { 34 | if (prompt) { 35 | menu(); 36 | } 37 | prompt = false; 38 | 39 | if (Serial.available()) { 40 | int answer = Serial.read(); 41 | if (answer == -1) { 42 | delay(300); 43 | } else if (answer == 48) { // 0 44 | IrSender.sendBoseWave(0xFF); // On/Off 45 | prompt = true; 46 | } else if (answer == 49) { // 1 47 | IrSender.sendBoseWave(0xFD); // Volume Up 48 | prompt = true; 49 | } else if (answer == 50) { // 2 50 | IrSender.sendBoseWave(0xFC); // Volume Down 51 | prompt = true; 52 | } else if (answer == 51) { // 3 53 | IrSender.sendBoseWave(0xF4); // Tune Up 54 | prompt = true; 55 | } else if (answer == 52) { // 4 56 | IrSender.sendBoseWave(0xF3); // Tune Down 57 | prompt = true; 58 | } else if (answer == 53) { // 5 59 | IrSender.sendBoseWave(0xF7); // AM 60 | prompt = true; 61 | } else if (answer == 54) { // 6 62 | IrSender.sendBoseWave(0xF9); // FM 63 | prompt = true; 64 | } else if (answer == 55) { // 7 65 | IrSender.sendBoseWave(0xF2); // Preset 1 66 | prompt = true; 67 | } else if (answer == 56) { // 8 68 | IrSender.sendBoseWave(0xF1); // Preset 2 69 | prompt = true; 70 | } else if (answer == 57) { // 9 71 | IrSender.sendBoseWave(0xF0); // Preset 3 72 | prompt = true; 73 | } else if (answer == 97) { // a 74 | IrSender.sendBoseWave(0xEF); // Preset 4 75 | prompt = true; 76 | } else if (answer == 98) { // b 77 | IrSender.sendBoseWave(0xEE); // Preset 5 78 | prompt = true; 79 | } else if (answer == 99) { // c 80 | IrSender.sendBoseWave(0xFB); // Preset 6 81 | prompt = true; 82 | } else if (answer == 100) { // d 83 | IrSender.sendBoseWave(0xFE); // Mute 84 | prompt = true; 85 | } else if (answer == 101) { // e 86 | IrSender.sendBoseWave(0xF6); // Pause 87 | prompt = true; 88 | } else if (answer == 102) { // f 89 | IrSender.sendBoseWave(0xF5); // Stop 90 | prompt = true; 91 | } else if (answer == 103) { // g 92 | IrSender.sendBoseWave(0xF8); // Aux 93 | prompt = true; 94 | } else if (answer == 104) { // h 95 | IrSender.sendBoseWave(0xFA); // Sleep 96 | prompt = true; 97 | } 98 | delay(300); 99 | } 100 | } 101 | 102 | void menu() { 103 | Serial.println("0: On / Off"); 104 | Serial.println("1: Volume Up"); 105 | Serial.println("2: Volume Down"); 106 | Serial.println("3: Tune Up"); 107 | Serial.println("4: Tune Down"); 108 | Serial.println("5: AM"); 109 | Serial.println("6: FM"); 110 | Serial.println("7: Preset 1"); 111 | Serial.println("8: Preset 2"); 112 | Serial.println("9: Preset 3"); 113 | Serial.println("a: Preset 4"); 114 | Serial.println("b: Preset 5"); 115 | Serial.println("c: Preset 6"); 116 | Serial.println("d: Mute"); 117 | Serial.println("e: Play/Pause"); 118 | Serial.println("f: Stop"); 119 | Serial.println("g: Aux"); 120 | Serial.println("h: Sleep"); 121 | } 122 | -------------------------------------------------------------------------------- /examples/IR2Keyboard/IR2Keyboard.ino: -------------------------------------------------------------------------------- 1 | /* 2 | this is just an example of creative (maybe useful) use of IR in a PC, as a media center or some other automatizations. 3 | the idea is fordward the IR commands (from any spare remote you may have) to keyboard pulses, combos, shortcuts, etc. 4 | Keyboard funtions only available on "leonardo" and "micro". for more keys read into https://www.arduino.cc/en/Reference/KeyboardModifiers 5 | for IR decoding im using the amazing lib from: http://www.righto.com/2009/08/multi-protocol-infrared-remote-library.html 6 | Remote class emulate media keys. need to be added manually to the arduino lib. http://stefanjones.ca/blog/arduino-leonardo-remote-multimedia-keys/ 7 | this is optional, you dont need Remote class to run the IR or Keyboard; its only for media keys 8 | */ 9 | 10 | /* 11 | Remote methods: 12 | http://stefanjones.ca/blog/arduino-leonardo-remote-multimedia-keys/ 13 | Volume 14 | Remote.increase(void); 15 | Remote.decrease(void); 16 | Remote.mute(void); 17 | Playback 18 | Remote.play(void); 19 | Remote.pause(void); 20 | Remote.stop(void); 21 | Track Controls 22 | Remote.next(void); 23 | Remote.previous(void); 24 | Remote.forward(void); 25 | Remote.rewind(void); 26 | Send an empty report to prevent repeated actions 27 | Keyboard.releaseAll(); 28 | */ 29 | 30 | #include 31 | #include 32 | #define T 15 33 | 34 | bool rotation = false; 35 | 36 | #if defined(ESP32) 37 | int IR_RECEIVE_PIN = 15; 38 | #elif defined(ARDUINO_AVR_PROMICRO) 39 | int IR_RECEIVE_PIN = 10; 40 | #else 41 | int IR_RECEIVE_PIN = 11; 42 | #endif 43 | IRrecv IrReceiver(IR_RECEIVE_PIN); 44 | 45 | // On the Zero and others we switch explicitly to SerialUSB 46 | #if defined(ARDUINO_ARCH_SAMD) 47 | #define Serial SerialUSB 48 | #endif 49 | 50 | void PanasonicRemote(); 51 | 52 | void setup() { 53 | pinMode(LED_BUILTIN, OUTPUT); 54 | 55 | Serial.begin(115200); 56 | #if defined(__AVR_ATmega32U4__) || defined(SERIAL_USB) || defined(SERIAL_PORT_USBVIRTUAL) 57 | delay(2000); // To be able to connect Serial monitor after reset and before first printout 58 | #endif 59 | // Just to know which program is running on my Arduino 60 | Serial.println(F("START " __FILE__ " from " __DATE__)); 61 | 62 | Keyboard.begin(); 63 | // In case the interrupt driver crashes on setup, give a clue 64 | // to the user what's going on. 65 | Serial.println("Enabling IRin"); 66 | IrReceiver.enableIRIn(); // Start the receiver 67 | IrReceiver.blink13(true); // Enable feedback LED 68 | 69 | Serial.print(F("Ready to receive IR signals at pin ")); 70 | Serial.println(IR_RECEIVE_PIN); 71 | } 72 | 73 | void loop() { 74 | if (IrReceiver.decode()) { 75 | //DellRemote(results.value); 76 | PanasonicRemote(); 77 | //mapping(); 78 | delay(300); 79 | IrReceiver.resume(); // Receive the next value 80 | } 81 | delay(100); 82 | } 83 | 84 | void mapping() { 85 | uint32_t tCode = IrReceiver.results.value; 86 | //use this function to map the codes of all your buttons. some buttons send different codes if they are hold down 87 | if ((tCode == 0x801C2B2E) or (tCode == 0xB4AFB411) or (tCode == 0xD17D8037)) { 88 | Serial.println("forward button"); 89 | } else if ((tCode == 0xB7AFB8C8) or (tCode == 0xD07D7EA2) or (tCode == 0x801CAB2F)) { 90 | Serial.println("previous button"); 91 | } else { 92 | Serial.print(IrReceiver.results.value, HEX); 93 | Serial.println("unknown code!"); 94 | } 95 | } 96 | 97 | void PanasonicRemote() { 98 | uint32_t code = IrReceiver.results.value; 99 | 100 | //here i have mapped some buttons of my blue ray remote. 101 | if (code == 0xD00A0AD) {/*forward*/ 102 | Keyboard.releaseAll(); 103 | delay(T); 104 | Keyboard.press(KEY_LEFT_ALT); 105 | Keyboard.press(KEY_RIGHT_ARROW); 106 | delay(T); 107 | Keyboard.releaseAll(); /*Remote.forward(); Keyboard.releaseAll(); */ 108 | } //Ctrl + -> forward 10 seconds VLC 109 | else if (code == 0xD00202D) {/*atras*/ 110 | Keyboard.releaseAll(); 111 | delay(T); 112 | Keyboard.press(KEY_LEFT_ALT); 113 | Keyboard.press(KEY_LEFT_ARROW); 114 | delay(T); 115 | Keyboard.releaseAll(); /*Remote.rewind(); Keyboard.releaseAll(); */ 116 | } //Ctrl + <- rewind 10 seconds VLC 117 | else if (code == 0xD00525F) {/*next*/ 118 | Keyboard.releaseAll(); 119 | delay(T); 120 | // Remote.next(); 121 | Keyboard.releaseAll(); 122 | } else if (code == 0xD00929F) {/*prev*/ 123 | Keyboard.releaseAll(); 124 | delay(T); 125 | // Remote.previous(); 126 | Keyboard.releaseAll(); 127 | } 128 | //else if (code == 0xD00000D){/*stop*/ Keyboard.releaseAll();delay(T); Remote.stop(); Keyboard.releaseAll(); } 129 | else if (code == 0x1000405) {/*vol +*/ 130 | Keyboard.releaseAll(); 131 | delay(T); 132 | // Remote.increase(); 133 | Keyboard.releaseAll(); 134 | } else if (code == 0x1008485) {/*vol -*/ 135 | Keyboard.releaseAll(); 136 | delay(T); 137 | // Remote.decrease(); 138 | Keyboard.releaseAll(); 139 | } else if (code == 0xD00BCB1) {/*POWER*/ 140 | Keyboard.releaseAll(); 141 | delay(T); 142 | // Remote.mute(); 143 | Keyboard.releaseAll(); 144 | } else if ((code == 0xD00606D) or (code == 0xD00505D)) {/*play/pause*/ 145 | Keyboard.releaseAll(); 146 | delay(T); 147 | // Remote.play(); 148 | Keyboard.releaseAll(); 149 | } else if (code == 0xD00818C) {/*return*/ 150 | Keyboard.releaseAll(); 151 | delay(T); 152 | Keyboard.write(KEY_ESC); 153 | } else if (code == 0xD00414C) {/*OK*/ 154 | Keyboard.releaseAll(); 155 | delay(T); 156 | Keyboard.print(" "); /*evitar doble pulsaciondelay(300);*/ 157 | } else if (code == 0x100BCBD) {/*tvPower*/ 158 | Keyboard.releaseAll(); 159 | delay(T); 160 | Keyboard.press(KEY_LEFT_CTRL); 161 | Keyboard.press(KEY_UP_ARROW); 162 | delay(T); 163 | Keyboard.releaseAll(); 164 | } //volumen en VLC 165 | else if (code == 0x100A0A1) {/*input AV*/ 166 | Keyboard.releaseAll(); 167 | delay(T); 168 | Keyboard.press(KEY_LEFT_CTRL); 169 | Keyboard.press(KEY_DOWN_ARROW); 170 | delay(T); 171 | Keyboard.releaseAll(); 172 | } //volumen en VLC 173 | else if (code == 0xD00808D) {/*open/close*/ 174 | Keyboard.releaseAll(); 175 | delay(T); 176 | Keyboard.press(KEY_LEFT_CTRL); 177 | Keyboard.press(KEY_PAGE_UP); 178 | delay(T); 179 | Keyboard.releaseAll(); 180 | } //cambiar canal HEXCHAT 181 | else if (code == 0xD004944) {/*display*/ 182 | Keyboard.releaseAll(); 183 | delay(T); 184 | Keyboard.press(KEY_LEFT_CTRL); 185 | Keyboard.press(KEY_PAGE_DOWN); 186 | delay(T); 187 | Keyboard.releaseAll(); 188 | } //cambiar canal HEXCHAT 189 | else if (code == 0xD803AB7) {/*DLNA*/ 190 | if (rotation) { 191 | Keyboard.releaseAll(); 192 | rotation = false; 193 | delay(T); 194 | } else { 195 | Keyboard.releaseAll(); 196 | delay(T); 197 | Keyboard.press(KEY_LEFT_GUI); 198 | delay(T); 199 | Keyboard.write(KEY_TAB); 200 | rotation = true; 201 | } 202 | } 203 | //rotation mode //iniciar animacion de rotation de ventanas //start window rotation with compiz 204 | else if (code == 0xD00A1AC) {/*arrow up*/ 205 | Keyboard.write(KEY_UP_ARROW); 206 | } else if (code == 0xD00616C) {/*arrow down*/ 207 | Keyboard.releaseAll(); 208 | delay(T); 209 | Keyboard.write(KEY_DOWN_ARROW); 210 | } else if (code == 0xD00E1EC) {/*arrow right*/ 211 | Keyboard.write(KEY_LEFT_ARROW); 212 | } else if (code == 0xD00111C) {/*arrow left*/ 213 | Keyboard.write(KEY_RIGHT_ARROW); 214 | } else if (code == 0xD00D9D4) {/*TOP MENU*/ 215 | Keyboard.print("f"); 216 | } //f pone a pantalla completa en VLC fullscreen 217 | else if (code == 0xD00010C) {/*S sub menu*/ 218 | Keyboard.print("v"); 219 | } //v cambia subs en VLC change subs 220 | else if (code == 0xD00CCC1) {/*AUDIO*/ 221 | Keyboard.print("b"); 222 | } //b cambia audio en VLC change audio track 223 | else if (code == 0xD002825) {/*#5*/ 224 | Keyboard.write(KEY_RETURN); 225 | } //useful to press enter on the file you want to play. 226 | else { 227 | Serial.print(IrReceiver.results.value, HEX); 228 | Serial.println(" Unknown!"); 229 | } 230 | } 231 | -------------------------------------------------------------------------------- /examples/IRreceiveDemo/IRreceiveDemo.ino: -------------------------------------------------------------------------------- 1 | /* 2 | * IRremote: IRreceiveDemo - demonstrates receiving IR codes with IRrecv 3 | * An IR detector/demodulator must be connected to the input RECV_PIN. 4 | * Initially coded 2009 Ken Shirriff http://www.righto.com/ 5 | */ 6 | 7 | #include 8 | 9 | #if defined(ESP32) 10 | int IR_RECEIVE_PIN = 15; 11 | #elif defined(ARDUINO_AVR_PROMICRO) 12 | int IR_RECEIVE_PIN = 10; 13 | #else 14 | int IR_RECEIVE_PIN = 11; 15 | #endif 16 | IRrecv IrReceiver(IR_RECEIVE_PIN); 17 | 18 | // On the Zero and others we switch explicitly to SerialUSB 19 | #if defined(ARDUINO_ARCH_SAMD) 20 | #define Serial SerialUSB 21 | #endif 22 | 23 | void setup() { 24 | pinMode(LED_BUILTIN, OUTPUT); 25 | 26 | Serial.begin(115200); 27 | #if defined(__AVR_ATmega32U4__) || defined(SERIAL_USB) || defined(SERIAL_PORT_USBVIRTUAL) 28 | delay(2000); // To be able to connect Serial monitor after reset and before first printout 29 | #endif 30 | // Just to know which program is running on my Arduino 31 | Serial.println(F("START " __FILE__ " from " __DATE__)); 32 | 33 | // In case the interrupt driver crashes on setup, give a clue 34 | // to the user what's going on. 35 | Serial.println("Enabling IRin"); 36 | IrReceiver.enableIRIn(); // Start the receiver 37 | IrReceiver.blink13(true); // Enable feedback LED 38 | 39 | Serial.print(F("Ready to receive IR signals at pin ")); 40 | Serial.println(IR_RECEIVE_PIN); 41 | } 42 | 43 | void loop() { 44 | if (IrReceiver.decode()) { 45 | IrReceiver.printResultShort(&Serial); 46 | Serial.println(); 47 | 48 | IrReceiver.resume(); // Receive the next value 49 | } 50 | delay(100); 51 | } 52 | -------------------------------------------------------------------------------- /examples/IRreceiveDump/IRreceiveDump.ino: -------------------------------------------------------------------------------- 1 | /* 2 | * IRremote: IRreceiveDump - dump details of IR codes with IRrecv 3 | * An IR detector/demodulator must be connected to the input RECV_PIN. 4 | * Initially coded 2009 Ken Shirriff http://www.righto.com 5 | * JVC and Panasonic protocol added by Kristian Lauszus (Thanks to zenwheel and other people at the original blog post) 6 | * LG added by Darryl Smith (based on the JVC protocol) 7 | */ 8 | 9 | #include 10 | 11 | /* 12 | * Default is Arduino pin D11. 13 | * You can change this to another available Arduino Pin. 14 | * Your IR receiver should be connected to the pin defined here 15 | */ 16 | #if defined(ESP32) 17 | int IR_RECEIVE_PIN = 15; 18 | #else 19 | int IR_RECEIVE_PIN = 11; 20 | #endif 21 | 22 | IRrecv IrReceiver(IR_RECEIVE_PIN); 23 | 24 | // On the Zero and others we switch explicitly to SerialUSB 25 | #if defined(ARDUINO_ARCH_SAMD) 26 | #define Serial SerialUSB 27 | #endif 28 | 29 | void setup() { 30 | pinMode(LED_BUILTIN, OUTPUT); 31 | 32 | Serial.begin(115200); 33 | #if defined(__AVR_ATmega32U4__) || defined(SERIAL_USB) || defined(SERIAL_PORT_USBVIRTUAL) 34 | delay(2000); // To be able to connect Serial monitor after reset and before first printout 35 | #endif 36 | // Just to know which program is running on my Arduino 37 | Serial.println(F("START " __FILE__ " from " __DATE__)); 38 | IrReceiver.enableIRIn(); // Start the receiver 39 | IrReceiver.blink13(true); // Enable feedback LED 40 | 41 | Serial.print(F("Ready to receive IR signals at pin ")); 42 | Serial.println(IR_RECEIVE_PIN); 43 | } 44 | 45 | void loop() { 46 | if (IrReceiver.decode()) { 47 | Serial.println(); 48 | Serial.println(); 49 | IrReceiver.printResultShort(&Serial); 50 | Serial.println(); 51 | Serial.println(F("Result in internal ticks (50 us):")); 52 | IrReceiver.printIRResultRaw(&Serial, false); 53 | 54 | Serial.println(); 55 | Serial.println(F("Result in microseconds:")); 56 | IrReceiver.printIRResultRaw(&Serial, true); 57 | 58 | IrReceiver.resume(); // Receive the next value 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /examples/IRreceiveDumpV2/IRreceiveDumpV2.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 | #if defined(ESP32) 10 | int IR_RECEIVE_PIN = 15; 11 | #else 12 | int IR_RECEIVE_PIN = 11; 13 | #endif 14 | IRrecv IrReceiver(IR_RECEIVE_PIN); 15 | 16 | //+============================================================================= 17 | // Configure the Arduino 18 | // 19 | void setup() { 20 | pinMode(LED_BUILTIN, OUTPUT); 21 | 22 | Serial.begin(115200); // Status message will be sent to PC at 9600 baud 23 | #if defined(__AVR_ATmega32U4__) || defined(SERIAL_USB) || defined(SERIAL_PORT_USBVIRTUAL) 24 | delay(2000); // To be able to connect Serial monitor after reset and before first printout 25 | #endif 26 | // Just to know which program is running on my Arduino 27 | Serial.println(F("START " __FILE__ " from " __DATE__)); 28 | 29 | IrReceiver.enableIRIn(); // Start the receiver 30 | IrReceiver.blink13(true); // Enable feedback LED 31 | 32 | Serial.print(F("Ready to receive IR signals at pin ")); 33 | Serial.println(IR_RECEIVE_PIN); 34 | } 35 | 36 | //+============================================================================= 37 | // The repeating section of the code 38 | // 39 | void loop() { 40 | if (IrReceiver.decode()) { // Grab an IR code 41 | // Check if the buffer overflowed 42 | if (IrReceiver.results.overflow) { 43 | Serial.println("IR code too long. Edit IRremoteInt.h and increase RAW_BUFFER_LENGTH"); 44 | return; 45 | } 46 | Serial.println(); // 2 blank lines between entries 47 | Serial.println(); 48 | IrReceiver.printResultShort(&Serial); 49 | 50 | Serial.println(F("Result in internal ticks (50 us)")); 51 | IrReceiver.printIRResultRawFormatted(&Serial, false); // Output the results in RAW format 52 | Serial.println(F("Result in microseconds")); 53 | IrReceiver.printIRResultRawFormatted(&Serial, true); // Output the results in RAW format 54 | Serial.println(); // blank line between entries 55 | Serial.println(F("Result as internal ticks (50 us) array")); 56 | IrReceiver.printIRResultAsCArray(&Serial, false); // Output the results as uint8_t source code array of ticks 57 | Serial.println(F("Result as microseconds array")); 58 | IrReceiver.printIRResultAsCArray(&Serial, true); // Output the results as uint16_t source code array of micros 59 | IrReceiver.printIRResultAsCVariables(&Serial); // Output address and data as source code variables 60 | IrReceiver.printIRResultAsPronto(&Serial); 61 | 62 | IrReceiver.resume(); // Prepare for the next value 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /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 between the input SEND_BUTTON_PIN and ground. 6 | * A visible LED can be connected to STATUS_PIN to provide status. 7 | * 8 | * The logic is: 9 | * If the button is pressed, send the IR code. 10 | * If an IR code is received, record it. 11 | * 12 | * Initially coded 2009 Ken Shirriff http://www.righto.com 13 | */ 14 | 15 | #include 16 | 17 | #if defined(ESP32) 18 | int IR_RECEIVE_PIN = 15; 19 | int SEND_BUTTON_PIN = 16; // RX2 pin 20 | #else 21 | int IR_RECEIVE_PIN = 11; 22 | int SEND_BUTTON_PIN = 12; 23 | #endif 24 | int STATUS_PIN = LED_BUILTIN; 25 | 26 | int DELAY_BETWEEN_REPEAT = 50; 27 | 28 | IRrecv IrReceiver(IR_RECEIVE_PIN); 29 | IRsend IrSender; 30 | 31 | // On the Zero and others we switch explicitly to SerialUSB 32 | #if defined(ARDUINO_ARCH_SAMD) 33 | #define Serial SerialUSB 34 | #endif 35 | 36 | void setup() { 37 | Serial.begin(115200); 38 | #if defined(__AVR_ATmega32U4__) || defined(SERIAL_USB) || defined(SERIAL_PORT_USBVIRTUAL) 39 | delay(2000); // To be able to connect Serial monitor after reset and before first printout 40 | #endif 41 | // Just to know which program is running on my Arduino 42 | Serial.println(F("START " __FILE__ " from " __DATE__)); 43 | 44 | IrReceiver.enableIRIn(); // Start the receiver 45 | IrReceiver.blink13(true); // Enable feedback LED 46 | 47 | pinMode(SEND_BUTTON_PIN, INPUT_PULLUP); 48 | pinMode(STATUS_PIN, OUTPUT); 49 | 50 | Serial.print(F("Ready to receive IR signals at pin ")); 51 | Serial.println(IR_RECEIVE_PIN); 52 | 53 | #if defined(SENDING_SUPPORTED) 54 | Serial.print(F("Ready to send IR signals at pin ")); 55 | Serial.print(IR_SEND_PIN); 56 | Serial.print(F(" on press of button at pin ")); 57 | Serial.println(SEND_BUTTON_PIN); 58 | 59 | #else 60 | Serial.println(F("Sending not supported for this board!")); 61 | #endif 62 | } 63 | 64 | // Storage for the recorded code 65 | int codeType = -1; // The type of code 66 | uint32_t codeValue; // The code value if not raw 67 | uint16_t address; // The address value if not raw 68 | uint16_t rawCodes[RAW_BUFFER_LENGTH]; // The durations if raw 69 | uint8_t codeLen; // The length of the code 70 | int toggle = 0; // The RC5/6 toggle state 71 | 72 | // Stores the code for later playback 73 | // Most of this code is just logging 74 | void storeCode() { 75 | if (IrReceiver.results.isRepeat) { 76 | Serial.println("Ignore repeat"); 77 | return; 78 | } 79 | codeType = IrReceiver.results.decode_type; 80 | address = IrReceiver.results.address; 81 | 82 | // int count = IrReceiver.results.rawlen; 83 | if (codeType == UNKNOWN) { 84 | Serial.println("Received unknown code, saving as raw"); 85 | codeLen = IrReceiver.results.rawlen - 1; 86 | // To store raw codes: 87 | // Drop first value (gap) 88 | // Convert from ticks to microseconds 89 | // Tweak marks shorter, and spaces longer to cancel out IR receiver distortion 90 | for (int i = 1; i <= codeLen; i++) { 91 | if (i % 2) { 92 | // Mark 93 | rawCodes[i - 1] = IrReceiver.results.rawbuf[i] * MICROS_PER_TICK - MARK_EXCESS_MICROS; 94 | Serial.print(" m"); 95 | } else { 96 | // Space 97 | rawCodes[i - 1] = IrReceiver.results.rawbuf[i] * MICROS_PER_TICK + MARK_EXCESS_MICROS; 98 | Serial.print(" s"); 99 | } 100 | Serial.print(rawCodes[i - 1], DEC); 101 | } 102 | Serial.println(); 103 | } else { 104 | IrReceiver.printResultShort(&Serial); 105 | Serial.println(); 106 | 107 | codeValue = IrReceiver.results.value; 108 | codeLen = IrReceiver.results.bits; 109 | } 110 | } 111 | 112 | void sendCode(bool aSendRepeat) { 113 | if (codeType == NEC) { 114 | if (aSendRepeat) { 115 | IrSender.sendNEC(REPEAT, codeLen); 116 | Serial.println("Sent NEC repeat"); 117 | } else { 118 | IrSender.sendNEC(codeValue, codeLen); 119 | Serial.print("Sent NEC "); 120 | Serial.println(codeValue, HEX); 121 | } 122 | } else if (codeType == NEC_STANDARD) { 123 | if (aSendRepeat) { 124 | IrSender.sendNECRepeat(); 125 | Serial.println("Sent NEC repeat"); 126 | } else { 127 | IrSender.sendNECStandard(address, codeValue); 128 | Serial.print("Sent NEC_STANDARD address=0x"); 129 | Serial.print(address, HEX); 130 | Serial.print(", command=0x"); 131 | Serial.println(codeValue, HEX); 132 | } 133 | } else if (codeType == SONY) { 134 | IrSender.sendSony(codeValue, codeLen); 135 | Serial.print("Sent Sony "); 136 | Serial.println(codeValue, HEX); 137 | } else if (codeType == PANASONIC) { 138 | IrSender.sendPanasonic(codeValue, codeLen); 139 | Serial.print("Sent Panasonic"); 140 | Serial.println(codeValue, HEX); 141 | } else if (codeType == JVC) { 142 | IrSender.sendJVC(codeValue, codeLen, false); 143 | Serial.print("Sent JVC"); 144 | Serial.println(codeValue, HEX); 145 | } else if (codeType == RC5 || codeType == RC6) { 146 | if (!aSendRepeat) { 147 | // Flip the toggle bit for a new button press 148 | toggle = 1 - toggle; 149 | } 150 | // Put the toggle bit into the code to send 151 | codeValue = codeValue & ~(1 << (codeLen - 1)); 152 | codeValue = codeValue | (toggle << (codeLen - 1)); 153 | if (codeType == RC5) { 154 | Serial.print("Sent RC5 "); 155 | Serial.println(codeValue, HEX); 156 | IrSender.sendRC5(codeValue, codeLen); 157 | } else { 158 | IrSender.sendRC6(codeValue, codeLen); 159 | Serial.print("Sent RC6 "); 160 | Serial.println(codeValue, HEX); 161 | } 162 | } else if (codeType == UNKNOWN /* i.e. raw */) { 163 | // Assume 38 KHz 164 | IrSender.sendRaw(rawCodes, codeLen, 38); 165 | Serial.println("Sent raw"); 166 | } 167 | } 168 | 169 | int lastButtonState; 170 | 171 | void loop() { 172 | // If button pressed, send the code. 173 | int buttonState = digitalRead(SEND_BUTTON_PIN); // Button pin is active LOW 174 | if (lastButtonState == LOW && buttonState == HIGH) { 175 | Serial.println("Button released"); 176 | IrReceiver.enableIRIn(); // Re-enable receiver 177 | } 178 | 179 | if (buttonState == LOW) { 180 | Serial.println("Button pressed, now sending"); 181 | digitalWrite(STATUS_PIN, HIGH); 182 | sendCode(lastButtonState == buttonState); 183 | digitalWrite(STATUS_PIN, LOW); 184 | delay(DELAY_BETWEEN_REPEAT); // Wait a bit between retransmissions 185 | } else if (IrReceiver.decode()) { 186 | storeCode(); 187 | IrReceiver.resume(); // resume receiver 188 | } 189 | lastButtonState = buttonState; 190 | } 191 | -------------------------------------------------------------------------------- /examples/IRrelay/IRrelay.ino: -------------------------------------------------------------------------------- 1 | /* 2 | * IRremote: IRrelay - demonstrates receiving IR codes with IRrecv 3 | * Toggles an output pin at each command received 4 | * An IR detector/demodulator must be connected to the input RECV_PIN. 5 | * Initially coded 2009 Ken Shirriff http://www.righto.com 6 | */ 7 | 8 | #include 9 | 10 | #if defined(ESP32) 11 | int IR_RECEIVE_PIN = 15; 12 | #else 13 | int IR_RECEIVE_PIN = 11; 14 | #endif 15 | int RELAY_PIN = 4; // is labeled D2 on the Chinese SAMD21 M0-Mini clone 16 | 17 | IRrecv IrReceiver(IR_RECEIVE_PIN); 18 | decode_results results; 19 | 20 | // On the Zero and others we switch explicitly to SerialUSB 21 | #if defined(ARDUINO_ARCH_SAMD) 22 | #define Serial SerialUSB 23 | // The Chinese SAMD21 M0-Mini clone has no led connected, if you connect it, it is on pin 24 like on the original board. 24 | // Attention! D2 and D4 are reversed on these boards 25 | //#undef LED_BUILTIN 26 | //#define LED_BUILTIN 25 // Or choose pin 25, it is the RX pin, but active low. 27 | #endif 28 | 29 | void dump(); 30 | 31 | void setup() { 32 | pinMode(LED_BUILTIN, OUTPUT); 33 | pinMode(RELAY_PIN, OUTPUT); 34 | 35 | Serial.begin(115200); 36 | #if defined(__AVR_ATmega32U4__) || defined(SERIAL_USB) || defined(SERIAL_PORT_USBVIRTUAL) 37 | delay(2000); // To be able to connect Serial monitor after reset and before first printout 38 | #endif 39 | // Just to know which program is running on my Arduino 40 | Serial.println(F("START " __FILE__ " from " __DATE__)); 41 | 42 | IrReceiver.enableIRIn(); // Start the receiver 43 | IrReceiver.blink13(true); // Enable feedback LED 44 | 45 | Serial.print(F("Ready to receive IR signals at pin ")); 46 | Serial.println(IR_RECEIVE_PIN); 47 | } 48 | 49 | int on = 0; 50 | unsigned long last = millis(); 51 | 52 | void loop() { 53 | if (IrReceiver.decode()) { 54 | // If it's been at least 1/4 second since the last 55 | // IR received, toggle the relay 56 | if (millis() - last > 250) { 57 | on = !on; 58 | Serial.print(F("Switch relay ")); 59 | if (on) { 60 | digitalWrite(RELAY_PIN, HIGH); 61 | digitalWrite(LED_BUILTIN, HIGH); 62 | Serial.println(F("on")); 63 | } else { 64 | digitalWrite(RELAY_PIN, LOW); 65 | digitalWrite(LED_BUILTIN, LOW); 66 | Serial.println(F("off")); 67 | } 68 | dump(); 69 | } 70 | last = millis(); 71 | IrReceiver.resume(); // Receive the next value 72 | } 73 | } 74 | 75 | 76 | // Dumps out the decode_results structure. 77 | // Call this after IRrecv::decode() 78 | void dump() { 79 | int count = IrReceiver.results.rawlen; 80 | if (IrReceiver.results.decode_type == UNKNOWN) { 81 | Serial.println("Could not decode message"); 82 | } else { 83 | IrReceiver.printResultShort(&Serial); 84 | 85 | Serial.print(" ("); 86 | Serial.print(IrReceiver.results.bits, DEC); 87 | Serial.println(" bits)"); 88 | } 89 | Serial.print("Raw ("); 90 | Serial.print(count, DEC); 91 | Serial.print("): "); 92 | 93 | for (int i = 0; i < count; i++) { 94 | if ((i % 2) == 1) { 95 | Serial.print(IrReceiver.results.rawbuf[i] * MICROS_PER_TICK, DEC); 96 | } else { 97 | Serial.print(-(int) IrReceiver.results.rawbuf[i] * MICROS_PER_TICK, DEC); 98 | } 99 | Serial.print(" "); 100 | } 101 | Serial.println(""); 102 | } 103 | -------------------------------------------------------------------------------- /examples/IRsendDemo/ATtinySerialOut.h: -------------------------------------------------------------------------------- 1 | /* 2 | * ATtinySerialOut.h 3 | * 4 | * Copyright (C) 2015-2020 Armin Joachimsmeyer 5 | * Email: armin.joachimsmeyer@gmail.com 6 | * 7 | * This file is part of TinySerialOut https://github.com/ArminJo/ATtinySerialOut. 8 | * 9 | * TinySerialOut is free software: you can redistribute it and/or modify 10 | * it under the terms of the GNU General Public License as published by 11 | * the Free Software Foundation, either version 3 of the License, or 12 | * (at your option) any later version. 13 | * 14 | * This program is distributed in the hope that it will be useful, 15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 | * GNU General Public License for more details. 18 | * 19 | * You should have received a copy of the GNU General Public License 20 | * along with this program. If not, see . 21 | * 22 | */ 23 | 24 | // 25 | // ATMEL ATTINY85 26 | // 27 | // +-\/-+ 28 | // PCINT5/!RESET/ADC0/dW (5) PB5 1| |8 VCC 29 | // USB+ PCINT3/XTAL1/CLKI/!OC1B/ADC3 (3) PB3 2| |7 PB2 (2) SCK/USCK/SCL/ADC1/T0/INT0/PCINT2 / TX Debug output 30 | // USB- PCINT4/XTAL2/CLKO/ OC1B/ADC2 (4) PB4 3| |6 PB1 (1) MISO/DO/AIN1/OC0B/ OC1A/PCINT1 - (Digispark) LED 31 | // GND 4| |5 PB0 (0) MOSI/DI/AIN0/OC0A/!OC1A/SDA/AREF/PCINT0 32 | // +----+ 33 | 34 | // ATMEL ATTINY167 35 | // Pin numbers are for Digispark core 36 | // Pin numbers in Parenthesis are for ATTinyCore 37 | // 38 | // +-\/-+ 39 | // RX 6 (0) PA0 1| |20 PB0 (D8) 0 OC1AU TONE Timer 1 Channel A 40 | // TX 7 (1) PA1 2| |19 PB1 (9) 1 OC1BU Internal LED 41 | // 8 (2) PA2 3| |18 PB2 (10) 2 OC1AV Timer 1 Channel B 42 | // INT1 9 (3) PA3 4| |17 PB3 (11) 4 OC1BV connected with 51 Ohm to D- and 3.3 volt Zener. 43 | // AVCC 5| |16 GND 44 | // AGND 6| |15 VCC 45 | // 10 (4) PA4 7| |14 PB4 (12) XTAL1 46 | // 11 (5) PA5 8| |13 PB5 (13) XTAL2 47 | // 12 (6) PA6 9| |12 PB6 (14) 3 INT0 connected with 68 Ohm to D+ (and disconnected 3.3 volt Zener). Is terminated with ~20 kOhm if USB attached :-( 48 | // 5 (7) PA7 10| |11 PB7 (15) RESET 49 | // +----+ 50 | // 51 | 52 | #ifndef ATTINY_SERIAL_OUT_H_ 53 | #define ATTINY_SERIAL_OUT_H_ 54 | 55 | #if defined(__AVR_ATtiny25__) || defined(__AVR_ATtiny45__) || defined(__AVR_ATtiny85__) \ 56 | || defined(__AVR_ATtiny24__) || defined(__AVR_ATtiny44__) || defined(__AVR_ATtiny84__) \ 57 | || defined(__AVR_ATtiny87__) || defined(__AVR_ATtiny167__) 58 | #include 59 | 60 | #define VERSION_ATTINY_SERIAL_OUT "1.2.1" 61 | #define VERSION_ATTINY_SERIAL_OUT_MAJOR 1 62 | #define VERSION_ATTINY_SERIAL_OUT_MINOR 2 63 | 64 | #if (F_CPU != 1000000) && (F_CPU != 8000000) && (F_CPU != 16000000) 65 | #error F_CPU value must be 1000000, 8000000 or 16000000. 66 | #endif 67 | 68 | #if defined(__AVR_ATtiny87__) || defined(__AVR_ATtiny167__) 69 | # ifndef TX_PIN 70 | #define TX_PIN PA1 // (package pin 2 / TXD on Tiny167) - can use one of PA0 to PA7 here 71 | # endif 72 | #else // defined(__AVR_ATtiny87__) || defined(__AVR_ATtiny167__) 73 | # ifndef TX_PIN 74 | #define TX_PIN PB2 // (package pin 7 on Tiny85) - can use one of PB0 to PB4 (+PB5) here 75 | # endif 76 | #endif 77 | 78 | /* 79 | * Define or comment this out, if you want to save 10 bytes code size and if you can live 80 | * with 87 micro seconds intervals of disabled interrupts for each sent byte @115200 baud. 81 | */ 82 | //#define USE_ALWAYS_CLI_SEI_GUARD_FOR_OUTPUT 83 | 84 | /* 85 | * @1 MHz use bigger (+120 bytes for unrolled loop) but faster code. Otherwise only 38400 baud is possible. 86 | * @8/16 MHz use 115200 baud instead of 230400 baud. 87 | */ 88 | //#define TINY_SERIAL_DO_NOT_USE_115200BAUD 89 | #ifndef TINY_SERIAL_DO_NOT_USE_115200BAUD // define this to force using other baud rates 90 | #define USE_115200BAUD 91 | #endif 92 | 93 | // The same class definition as for plain arduino 94 | #if not defined(F) 95 | class __FlashStringHelper; 96 | #define F(string_literal) (reinterpret_cast(PSTR(string_literal))) 97 | #endif 98 | 99 | extern bool sUseCliSeiForWrite; // default is true 100 | void useCliSeiForStrings(bool aUseCliSeiForWrite); // might be useful to set to false if output is done from ISR, to avoid to call unwanted sei(). 101 | 102 | void initTXPin(); 103 | void write1Start8Data1StopNoParity(uint8_t aValue); 104 | void write1Start8Data1StopNoParityWithCliSei(uint8_t aValue); 105 | void writeValue(uint8_t aValue); 106 | 107 | void writeString(const char *aStringPtr); 108 | void writeString(const __FlashStringHelper *aStringPtr); 109 | void writeString_P(const char *aStringPtr); 110 | void writeString_E(const char *aStringPtr); 111 | void writeStringWithCliSei(const char *aStringPtr); 112 | void writeStringWithoutCliSei(const char *aStringPtr); 113 | void writeStringSkipLeadingSpaces(const char *aStringPtr); 114 | 115 | void writeBinary(uint8_t aByte); // write direct without decoding 116 | void writeChar(uint8_t aChar); // Synonym for writeBinary 117 | void writeCRLF(); 118 | void writeByte(int8_t aByte); 119 | void writeUnsignedByte(uint8_t aByte); 120 | void writeUnsignedByteHex(uint8_t aByte); 121 | void writeUnsignedByteHexWithPrefix(uint8_t aByte); 122 | void writeInt(int16_t aInteger); 123 | void writeUnsignedInt(uint16_t aInteger); 124 | void writeLong(int32_t aLong); 125 | void writeUnsignedLong(uint32_t aLong); 126 | void writeFloat(double aFloat); 127 | void writeFloat(double aFloat, uint8_t aDigits); 128 | 129 | char nibbleToHex(uint8_t aByte); 130 | 131 | class TinySerialOut 132 | { 133 | public: 134 | 135 | void begin(long); 136 | void end(); 137 | void flush(void); 138 | 139 | void printHex(uint8_t aByte); // with 0x prefix 140 | void printHex(uint16_t aWord); // with 0x prefix 141 | void printlnHex(uint8_t aByte); // with 0x prefix 142 | void printlnHex(uint16_t aWord); // with 0x prefix 143 | 144 | // virtual functions of Print class 145 | size_t write(uint8_t aByte); 146 | operator bool(); // To support "while (!Serial); // wait for serial port to connect. Needed for Leonardo only 147 | 148 | void print(const __FlashStringHelper *aStringPtr); 149 | void print(const char *aStringPtr); 150 | void print(char aChar); 151 | void print(uint8_t aByte, uint8_t aBase = 10); 152 | void print(int16_t aInteger, uint8_t aBase = 10); 153 | void print(uint16_t aInteger, uint8_t aBase = 10); 154 | void print(int32_t aLong, uint8_t aBase = 10); 155 | void print(uint32_t aLong, uint8_t aBase = 10); 156 | void print(double aFloat, uint8_t aDigits = 2); 157 | 158 | void println(const char *aStringPtr); 159 | void println(const __FlashStringHelper *aStringPtr); 160 | void println(char aChar); 161 | void println(uint8_t aByte, uint8_t aBase = 10); 162 | void println(int16_t aInteger, uint8_t aBase = 10); 163 | void println(uint16_t aInteger, uint8_t aBase = 10); 164 | void println(int32_t aLong, uint8_t aBase = 10); 165 | void println(uint32_t aLong, uint8_t aBase = 10); 166 | void println(double aFloat, uint8_t aDigits = 2); 167 | 168 | void println(void); 169 | 170 | }; 171 | 172 | // #if ... to be compatible with ATTinyCores and AttinyDigisparkCores 173 | #if (!defined(UBRRH) && !defined(UBRR0H)) /*AttinyDigisparkCore and AttinyDigisparkCore condition*/ \ 174 | || USE_SOFTWARE_SERIAL /*AttinyDigisparkCore condition*/\ 175 | || ((defined(UBRRH) || defined(UBRR0H) || defined(UBRR1H) || defined(LINBRRH)) && !USE_SOFTWARE_SERIAL)/*AttinyDigisparkCore condition for HardwareSerial*/ 176 | // Switch to SerialOut since Serial is already defined 177 | // or comment out line 745 in TinyDebugSerial.h included in AttinyDigisparkCores/src/tiny/WProgram.h at line 24 for AttinyDigisparkCores 178 | extern TinySerialOut SerialOut; 179 | #define Serial SerialOut 180 | #else 181 | extern TinySerialOut Serial; 182 | #endif 183 | #define Print TinySerialOut 184 | 185 | #endif // defined(__AVR_ATtiny25__) || defined(__AVR_ATtiny45__) || defined(__AVR_ATtiny85__) || defined(__AVR_ATtiny87__) || defined(__AVR_ATtiny167__) 186 | 187 | #endif /* ATTINY_SERIAL_OUT_H_ */ 188 | 189 | #pragma once 190 | -------------------------------------------------------------------------------- /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 | * Initially coded 2009 Ken Shirriff http://www.righto.com 5 | */ 6 | 7 | #include 8 | #if defined(__AVR_ATtiny25__) || defined(__AVR_ATtiny45__) || defined(__AVR_ATtiny85__) || defined(__AVR_ATtiny87__) || defined(__AVR_ATtiny167__) 9 | #include "ATtinySerialOut.h" 10 | #endif 11 | 12 | IRsend IrSender; 13 | 14 | // On the Zero and others we switch explicitly to SerialUSB 15 | #if defined(ARDUINO_ARCH_SAMD) 16 | #define Serial SerialUSB 17 | #endif 18 | 19 | void setup() { 20 | pinMode(LED_BUILTIN, OUTPUT); 21 | 22 | Serial.begin(115200); 23 | #if defined(__AVR_ATmega32U4__) || defined(SERIAL_USB) || defined(SERIAL_PORT_USBVIRTUAL) 24 | delay(2000); // To be able to connect Serial monitor after reset and before first printout 25 | #endif 26 | // Just to know which program is running on my Arduino 27 | Serial.println(F("START " __FILE__ " from " __DATE__)); 28 | Serial.print(F("Ready to send IR signals at pin ")); 29 | Serial.println(IR_SEND_PIN); 30 | } 31 | 32 | void loop() { 33 | #ifdef SEND_NEC_STANDARD 34 | static uint8_t sCommand = 9; 35 | IrSender.sendNECStandard(0xFF00, sCommand, 2); 36 | Serial.println(F("sendNECStandard(0xFF00, sCommand,2)")); 37 | sCommand++; 38 | #else 39 | unsigned long tData = 0xa90; 40 | // loop for repeats 41 | for (int i = 0; i < 3; i++) { 42 | IrSender.sendSony(tData, 12); 43 | Serial.print(F("sendSony(0x")); 44 | Serial.print(tData,HEX); 45 | Serial.println(F(", 12)")); 46 | // IrSender.sendJVC(0xC5B8, 16,0); // hex value, 16 bits, no repeat 47 | // delayMicroseconds(50); // see http://www.sbprojects.com/knowledge/ir/jvc.php for information 48 | // IrSender.sendJVC(0xC5B8, 16,1); // hex value, 16 bits, repeat 49 | // Serial.println(F("sendJVC(9xC5B8, 16)")); 50 | 51 | delay(40); 52 | } 53 | tData++; 54 | #endif 55 | delay(5000); //5 second delay between each signal burst 56 | } 57 | -------------------------------------------------------------------------------- /examples/IRsendNecStandardDemo/IRsendNecStandardDemo.ino: -------------------------------------------------------------------------------- 1 | /* 2 | * IRremote: IRsendNecStandardDemo 3 | * 4 | * Demonstrates sending NEC IR codes in standard format with 16 bit Address 8bit Data 5 | * An IR LED must be connected to Arduino PWM pin 3 (IR_SEND_PIN). 6 | * To receive IR signals in compatible format, you must comment out the line 7 | * #define USE_NEC_STANDARD in IRremote.h. 8 | * 9 | * This file is part of Arduino-IRremote https://github.com/z3t0/Arduino-IRremote. 10 | */ 11 | 12 | #include 13 | 14 | IRsend IrSender; 15 | 16 | // On the Zero and others we switch explicitly to SerialUSB 17 | #if defined(ARDUINO_ARCH_SAMD) 18 | #define Serial SerialUSB 19 | #endif 20 | 21 | void setup() { 22 | pinMode(LED_BUILTIN, OUTPUT); 23 | 24 | Serial.begin(115200); 25 | #if defined(__AVR_ATmega32U4__) || defined(SERIAL_USB) || defined(SERIAL_PORT_USBVIRTUAL) 26 | delay(2000); // To be able to connect Serial monitor after reset and before first printout 27 | #endif 28 | // Just to know which program is running on my Arduino 29 | Serial.println(F("START " __FILE__ " from " __DATE__)); 30 | Serial.print(F("Ready to send IR signals at pin ")); 31 | Serial.println(IR_SEND_PIN); 32 | } 33 | 34 | uint16_t sAddress = 0xa90; 35 | uint8_t sCommand = 0x34; 36 | uint8_t sRepeats = 0; 37 | 38 | void loop() { 39 | 40 | IrSender.sendNECStandard(sAddress, sCommand, sRepeats); 41 | /* 42 | * Print values 43 | */ 44 | Serial.print(F("Send NEC standard: address=0x")); 45 | Serial.print(sAddress, HEX); 46 | Serial.print(F(" command=0x")); 47 | Serial.print(sCommand, HEX); 48 | Serial.print(F(" repeats=")); 49 | Serial.print(sRepeats); 50 | Serial.println(); 51 | /* 52 | * Increment values 53 | */ 54 | sAddress++; 55 | sCommand++; 56 | sRepeats++; 57 | if (sRepeats > 5) { 58 | sRepeats = 5; 59 | } 60 | 61 | delay(2000); // 2 second delay between each signal 62 | } 63 | -------------------------------------------------------------------------------- /examples/IRsendProntoDemo/IRsendProntoDemo.ino: -------------------------------------------------------------------------------- 1 | // Define exactly one of these 2 | //#define VAR_IN_PROGMEM 3 | #define VAR_IN_MEM 4 | //#define USE_F_FORM 5 | 6 | #define TIMES_TO_SEND 10U 7 | 8 | #include 9 | 10 | const char yamahaVolDown[] 11 | #ifdef VAR_IN_PROGMEM 12 | PROGMEM 13 | #endif 14 | = "0000 006C 0022 0002 " 15 | "015B 00AD 0016 0016 0016 0041 0016 0016 0016 0041 0016 0041 0016 0041 0016 0041 0016 0016 0016 0041 0016 0016 0016 0041 " 16 | "0016 0016 0016 0016 0016 0016 0016 0016 0016 0041 0016 0041 0016 0041 0016 0016 0016 0041 0016 0041 0016 0016 0016 0016 " 17 | "0016 0016 0016 0016 0016 0016 0016 0041 0016 0016 0016 0016 0016 0041 0016 0041 0016 0041 0016 05F7 015B 0057 0016 0E6C"; 18 | 19 | IRsend irsend; 20 | 21 | void setup() { 22 | Serial.begin(115200); 23 | while (!Serial) 24 | ; 25 | 26 | // Just to know which program is running on my Arduino 27 | Serial.println(F("START " __FILE__ " from " __DATE__)); 28 | 29 | Serial.print(F("Will send IR signals at pin ")); 30 | Serial.println(IR_SEND_PIN); 31 | } 32 | 33 | void loop() { 34 | 35 | 36 | #ifdef VAR_IN_PROGMEM 37 | Serial.println(F("Sending from PROGMEM")); 38 | irsend.sendPronto_PF(yamahaVolDown, TIMES_TO_SEND); 39 | #elif defined(VAR_IN_MEM) 40 | Serial.println(F("Sending from normal memory")); 41 | irsend.sendPronto(yamahaVolDown, TIMES_TO_SEND); 42 | #else 43 | Serial.println(F("Sending using the F()-form")); 44 | irsend.sendPronto(F("0000 006C 0022 0002 " 45 | "015B 00AD 0016 0016 0016 0041 0016 0016 0016 0041 0016 0041 0016 0041 0016 0041 0016 0016 0016 0041 0016 0016 0016 0041 " 46 | "0016 0016 0016 0016 0016 0016 0016 0016 0016 0041 0016 0041 0016 0041 0016 0016 0016 0041 0016 0041 0016 0016 0016 0016 " 47 | "0016 0016 0016 0016 0016 0016 0016 0041 0016 0016 0016 0016 0016 0041 0016 0041 0016 0041 0016 05F7 015B 0057 0016 0E6C"), TIMES_TO_SEND); 48 | #endif 49 | 50 | delay(5000); 51 | } 52 | -------------------------------------------------------------------------------- /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 | * Initially coded 2009 Ken Shirriff http://www.righto.com 5 | * 6 | * IRsendRawDemo - added by AnalysIR (via www.AnalysIR.com), 24 August 2015 7 | * 8 | * This example shows how to send a RAW signal using the IRremote library. 9 | * The example signal is actually a 32 bit NEC signal. 10 | * Remote Control button: LGTV Power On/Off. 11 | * Hex Value: 0x20DF10EF, 32 bits 12 | * 13 | * It is more efficient to use the sendNEC function to send NEC signals. 14 | * Use of sendRaw here, serves only as an example of using the function. 15 | * 16 | */ 17 | 18 | #include 19 | 20 | IRsend IrSender; 21 | 22 | // On the Zero and others we switch explicitly to SerialUSB 23 | #if defined(ARDUINO_ARCH_SAMD) 24 | #define Serial SerialUSB 25 | #endif 26 | 27 | void setup() { 28 | pinMode(LED_BUILTIN, OUTPUT); 29 | 30 | Serial.begin(115200); 31 | #if defined(__AVR_ATmega32U4__) || defined(SERIAL_USB) || defined(SERIAL_PORT_USBVIRTUAL) 32 | delay(2000); // To be able to connect Serial monitor after reset and before first printout 33 | #endif 34 | // Just to know which program is running on my Arduino 35 | Serial.println(F("START " __FILE__ " from " __DATE__)); 36 | Serial.print(F("Ready to send IR signals at pin ")); 37 | Serial.println(IR_SEND_PIN); 38 | } 39 | 40 | /* 41 | * NEC address=0xFB0C, command=0x18 42 | * 43 | * This is data in byte format. 44 | * The uint8_t/byte elements contain the number of ticks in 50 us 45 | * The integer format contains the (number of ticks * 50) if generated by IRremote, 46 | * so the integer format has the same resolution but requires double space. 47 | */ 48 | const uint8_t irSignalP[] PROGMEM 49 | = { 180, 90 /*Start bit*/, 11, 11, 11, 11, 11, 34, 11, 34/*0011 0xC of address LSB first*/, 11, 11, 11, 11, 11, 11, 11, 11/*0000*/, 50 | 11, 34, 11, 34, 11, 11, 11, 34/*1101 0xB*/, 11, 34, 11, 34, 11, 34, 11, 34/*1111*/, 11, 11, 11, 11, 11, 11, 11, 51 | 34/*0001 0x08 of command LSB first*/, 11, 34, 11, 11, 11, 11, 11, 11/*1000 0x01*/, 11, 34, 11, 34, 11, 34, 11, 52 | 11/*1110 Inverted 8 of command*/, 11, 11, 11, 34, 11, 34, 11, 34/*0111 inverted 1 of command*/, 11 /*stop bit*/}; 53 | 54 | void loop() { 55 | int khz = 38; // 38kHz carrier frequency for the NEC protocol 56 | /* 57 | * Send hand crafted data from RAM 58 | * The values are NOT multiple of 50, but are taken from the NEC timing definitions 59 | */ 60 | Serial.println(F("Send NEC 0xFB04, 0x08 with exact timing (integer format)")); 61 | const uint16_t irSignal[] = { 9000, 4500, 560, 560, 560, 560, 560, 1690, 560, 560, 560, 560, 560, 560, 560, 560, 560, 560, 62 | 560, 1690, 560, 1690, 560, 560, 560, 1690, 560, 1690, 560, 1690, 560, 1690, 560, 1690, 560, 560, 560, 560, 560, 560, 63 | 560, 1690, 560, 560, 560, 560, 560, 560, 560, 560, 560, 1690, 560, 1690, 560, 1690, 560, 560, 560, 1690, 560, 1690, 560, 64 | 1690, 560, 1690, 560 }; // Using exact NEC timing 65 | IrSender.sendRaw(irSignal, sizeof(irSignal) / sizeof(irSignal[0]), khz); // Note the approach used to automatically calculate the size of the array. 66 | 67 | delay(2000); 68 | 69 | /* 70 | * Send byte data direct from FLASH 71 | * Note the approach used to automatically calculate the size of the array. 72 | */ 73 | Serial.println(F("Send NEC 0xFB0C, 0x18 with tick resolution timing (byte format) ")); 74 | IrSender.sendRaw_P(irSignalP, sizeof(irSignalP) / sizeof(irSignalP[0]), khz); 75 | 76 | delay(2000); 77 | 78 | Serial.println(F("Send NEC 0xFF00, 0x17 generated")); 79 | IrSender.sendNECStandard(0xFF00, 0x17, 0); 80 | 81 | delay(3000); 82 | } 83 | -------------------------------------------------------------------------------- /examples/IRtest/IRtest.ino: -------------------------------------------------------------------------------- 1 | /* 2 | * IRremote: IRtest unittest 3 | * Initially coded 2009 Ken Shirriff http://www.righto.com 4 | * 5 | * Note: to run these tests, edit IRremote/IRremote.h to add "#define TEST" 6 | * You must then recompile the library by removing IRremote.o and restarting 7 | * the arduino IDE. 8 | */ 9 | 10 | #include 11 | 12 | IRrecv IrReceiver(0); 13 | 14 | // Dumps out the decode_results structure. 15 | // Call this after IRrecv::decode() 16 | // void * to work around compiler issue 17 | //void dump(void *v) { 18 | // decode_results *results = (decode_results *)v 19 | void dump() { 20 | int count = IrReceiver.results.rawlen; 21 | 22 | if (IrReceiver.results.decode_type == UNKNOWN) { 23 | Serial.println("Could not decode message"); 24 | } else { 25 | IrReceiver.printResultShort(&Serial); 26 | 27 | Serial.print(" ("); 28 | Serial.print(IrReceiver.results.bits, DEC); 29 | Serial.println(" bits)"); 30 | } 31 | Serial.print("Raw ("); 32 | Serial.print(count, DEC); 33 | Serial.print("): "); 34 | 35 | for (int i = 0; i < count; i++) { 36 | if ((i % 2) == 1) { 37 | Serial.print(IrReceiver.results.rawbuf[i] * MICROS_PER_TICK, DEC); 38 | } else { 39 | Serial.print(-(int) IrReceiver.results.rawbuf[i] * MICROS_PER_TICK, DEC); 40 | } 41 | Serial.print(" "); 42 | } 43 | Serial.println(""); 44 | } 45 | 46 | class IRsendDummy: public IRsend { 47 | public: 48 | // For testing, just log the marks/spaces 49 | #define SENDLOG_LEN 128 50 | int sendlog[SENDLOG_LEN]; 51 | int sendlogcnt = 0; 52 | IRsendDummy() : 53 | IRsend() { 54 | } 55 | void reset() { 56 | sendlogcnt = 0; 57 | } 58 | void mark(int time) { 59 | sendlog[sendlogcnt] = time; 60 | if (sendlogcnt < SENDLOG_LEN) 61 | sendlogcnt++; 62 | } 63 | void space(int time) { 64 | sendlog[sendlogcnt] = -time; 65 | if (sendlogcnt < SENDLOG_LEN) 66 | sendlogcnt++; 67 | } 68 | // Copies the dummy buf into the interrupt buf 69 | void useDummyBuf() { 70 | int last = SPACE; 71 | irparams.rcvstate = IR_REC_STATE_STOP; 72 | irparams.rawlen = 1; // Skip the gap 73 | for (int i = 0; i < sendlogcnt; i++) { 74 | if (sendlog[i] < 0) { 75 | if (last == MARK) { 76 | // New space 77 | irparams.rawbuf[irparams.rawlen++] = (-sendlog[i] - MARK_EXCESS_MICROS) / MICROS_PER_TICK; 78 | last = SPACE; 79 | } else { 80 | // More space 81 | irparams.rawbuf[irparams.rawlen - 1] += -sendlog[i] / MICROS_PER_TICK; 82 | } 83 | } else if (sendlog[i] > 0) { 84 | if (last == SPACE) { 85 | // New mark 86 | irparams.rawbuf[irparams.rawlen++] = (sendlog[i] + MARK_EXCESS_MICROS) / MICROS_PER_TICK; 87 | last = MARK; 88 | } else { 89 | // More mark 90 | irparams.rawbuf[irparams.rawlen - 1] += sendlog[i] / MICROS_PER_TICK; 91 | } 92 | } 93 | } 94 | if (irparams.rawlen % 2) { 95 | irparams.rawlen--; // Remove trailing space 96 | } 97 | } 98 | }; 99 | 100 | IRsendDummy irsenddummy; 101 | 102 | void verify(unsigned long val, unsigned int bits, unsigned int type) { 103 | irsenddummy.useDummyBuf(); 104 | IrReceiver.decode(); 105 | Serial.print("Testing "); 106 | Serial.print(val, HEX); 107 | if (IrReceiver.results.value == val && IrReceiver.results.bits == bits && IrReceiver.results.decode_type == type) { 108 | Serial.println(": OK"); 109 | } else { 110 | Serial.println(": Error"); 111 | dump(); 112 | } 113 | } 114 | 115 | void testNEC(uint32_t val, int bits) { 116 | irsenddummy.reset(); 117 | irsenddummy.sendNEC(val, bits); 118 | verify(val, bits, NEC); 119 | } 120 | void testSony(unsigned long val, int bits) { 121 | irsenddummy.reset(); 122 | irsenddummy.sendSony(val, bits); 123 | verify(val, bits, SONY); 124 | } 125 | void testRC5(uint32_t val, int bits) { 126 | irsenddummy.reset(); 127 | irsenddummy.sendRC5(val, bits); 128 | verify(val, bits, RC5); 129 | } 130 | void testRC6(uint32_t val, int bits) { 131 | irsenddummy.reset(); 132 | irsenddummy.sendRC6(val, bits); 133 | verify(val, bits, RC6); 134 | } 135 | 136 | void test() { 137 | Serial.println("NEC tests"); 138 | testNEC(0x00000000, 32); 139 | testNEC(0xffffffff, 32); 140 | testNEC(0xaaaaaaaa, 32); 141 | testNEC(0x55555555, 32); 142 | testNEC(0x12345678, 32); 143 | Serial.println("Sony tests"); 144 | testSony(0xfff, 12); 145 | testSony(0x000, 12); 146 | testSony(0xaaa, 12); 147 | testSony(0x555, 12); 148 | testSony(0x123, 12); 149 | Serial.println("RC5 tests"); 150 | testRC5(0xfff, 12); 151 | testRC5(0x000, 12); 152 | testRC5(0xaaa, 12); 153 | testRC5(0x555, 12); 154 | testRC5(0x123, 12); 155 | Serial.println("RC6 tests"); 156 | testRC6(0xfffff, 20); 157 | testRC6(0x00000, 20); 158 | testRC6(0xaaaaa, 20); 159 | testRC6(0x55555, 20); 160 | testRC6(0x12345, 20); 161 | } 162 | 163 | void setup() { 164 | Serial.begin(115200); 165 | test(); 166 | } 167 | 168 | void loop() { 169 | } 170 | -------------------------------------------------------------------------------- /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 | // JVC commands sometimes need to be sent two or three times with 40 to 60 ms pause in between. 26 | irsend.sendJVC(JVCPower, 16,0); // hex value, 16 bits, no repeat 27 | delayMicroseconds(50); // see http://www.sbprojects.net/knowledge/ir/jvc.php for information 28 | irsend.sendJVC(JVCPower, 16,1); // hex value, 16 bits, repeat 29 | delayMicroseconds(50); 30 | } 31 | -------------------------------------------------------------------------------- /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(115200); 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 | 8 | IRsend irsend; 9 | 10 | void setup() { 11 | } 12 | 13 | void loop() { 14 | // Send repeated command "channel 1, blue forward, red backward" 15 | irsend.sendLegoPowerFunctions(0x197); 16 | delay(2000); 17 | 18 | // Send single command "channel 1, blue forward, red backward" 19 | irsend.sendLegoPowerFunctions(0x197, false); 20 | delay(2000); 21 | } 22 | -------------------------------------------------------------------------------- /examples/LegoPowerFunctionsTests/LegoPowerFunctionsTests.ino: -------------------------------------------------------------------------------- 1 | /* 2 | * LegoPowerFunctionsTest: LEGO Power Functions Tests 3 | * Copyright (c) 2016, 2017 Philipp Henkel 4 | */ 5 | 6 | #include 7 | #include "ir_Lego_PF_BitStreamEncoder.h" 8 | 9 | void runBitStreamEncoderTests(); 10 | 11 | void setup() { 12 | pinMode(LED_BUILTIN, OUTPUT); 13 | 14 | Serial.begin(115200); 15 | #if defined(__AVR_ATmega32U4__) 16 | while (!Serial) 17 | ; //delay for Leonardo, but this loops forever for Maple Serial 18 | #endif 19 | #if defined(SERIAL_USB) || defined(SERIAL_PORT_USBVIRTUAL) 20 | delay(2000); // To be able to connect Serial monitor after reset and before first printout 21 | #endif 22 | // Just to know which program is running on my Arduino 23 | Serial.println(F("START " __FILE__ " from " __DATE__)); 24 | delay(1000); // wait for reset triggered by serial connection 25 | runBitStreamEncoderTests(); 26 | } 27 | 28 | void loop() { 29 | } 30 | 31 | void runBitStreamEncoderTests() { 32 | Serial.println(); 33 | Serial.println("BitStreamEncoder Tests"); 34 | static LegoPfBitStreamEncoder bitStreamEncoder; 35 | testStartBit(bitStreamEncoder); 36 | testLowBit(bitStreamEncoder); 37 | testHighBit(bitStreamEncoder); 38 | testMessageBitCount(bitStreamEncoder); 39 | testMessageBitCountRepeat(bitStreamEncoder); 40 | testMessage407(bitStreamEncoder); 41 | testMessage407Repeated(bitStreamEncoder); 42 | testGetChannelId1(bitStreamEncoder); 43 | testGetChannelId2(bitStreamEncoder); 44 | testGetChannelId3(bitStreamEncoder); 45 | testGetChannelId4(bitStreamEncoder); 46 | testGetMessageLengthAllHigh(bitStreamEncoder); 47 | testGetMessageLengthAllLow(bitStreamEncoder); 48 | } 49 | 50 | void logTestResult(bool testPassed) { 51 | if (testPassed) { 52 | Serial.println("OK"); 53 | } else { 54 | Serial.println("FAIL ############"); 55 | } 56 | } 57 | 58 | void testStartBit(LegoPfBitStreamEncoder& bitStreamEncoder) { 59 | Serial.print(" testStartBit "); 60 | bitStreamEncoder.reset(0, false); 61 | int startMark = bitStreamEncoder.getMarkDuration(); 62 | int startPause = bitStreamEncoder.getPauseDuration(); 63 | logTestResult(startMark == 158 && startPause == 1184 - 158); 64 | } 65 | 66 | void testLowBit(LegoPfBitStreamEncoder& bitStreamEncoder) { 67 | Serial.print(" testLowBit "); 68 | bitStreamEncoder.reset(0, false); 69 | bitStreamEncoder.next(); 70 | int lowMark = bitStreamEncoder.getMarkDuration(); 71 | int lowPause = bitStreamEncoder.getPauseDuration(); 72 | logTestResult(lowMark == 158 && lowPause == 421 - 158); 73 | } 74 | 75 | void testHighBit(LegoPfBitStreamEncoder& bitStreamEncoder) { 76 | Serial.print(" testHighBit "); 77 | bitStreamEncoder.reset(0xFFFF, false); 78 | bitStreamEncoder.next(); 79 | int highMark = bitStreamEncoder.getMarkDuration(); 80 | int highPause = bitStreamEncoder.getPauseDuration(); 81 | logTestResult(highMark == 158 && highPause == 711 - 158); 82 | } 83 | 84 | void testMessageBitCount(LegoPfBitStreamEncoder& bitStreamEncoder) { 85 | Serial.print(" testMessageBitCount "); 86 | bitStreamEncoder.reset(0xFFFF, false); 87 | int bitCount = 1; 88 | while (bitStreamEncoder.next()) { 89 | bitCount++; 90 | } 91 | logTestResult(bitCount == 18); 92 | } 93 | 94 | boolean check(LegoPfBitStreamEncoder& bitStreamEncoder, unsigned long markDuration, unsigned long pauseDuration) { 95 | bool result = true; 96 | result = result && bitStreamEncoder.getMarkDuration() == markDuration; 97 | result = result && bitStreamEncoder.getPauseDuration() == pauseDuration; 98 | return result; 99 | } 100 | 101 | boolean checkNext(LegoPfBitStreamEncoder& bitStreamEncoder, unsigned long markDuration, unsigned long pauseDuration) { 102 | bool result = bitStreamEncoder.next(); 103 | result = result && check(bitStreamEncoder, markDuration, pauseDuration); 104 | return result; 105 | } 106 | 107 | boolean checkDataBitsOfMessage407(LegoPfBitStreamEncoder& bitStreamEncoder) { 108 | bool result = true; 109 | result = result && checkNext(bitStreamEncoder, 158, 263); 110 | result = result && checkNext(bitStreamEncoder, 158, 263); 111 | result = result && checkNext(bitStreamEncoder, 158, 263); 112 | result = result && checkNext(bitStreamEncoder, 158, 263); 113 | result = result && checkNext(bitStreamEncoder, 158, 263); 114 | result = result && checkNext(bitStreamEncoder, 158, 263); 115 | result = result && checkNext(bitStreamEncoder, 158, 263); 116 | result = result && checkNext(bitStreamEncoder, 158, 553); 117 | result = result && checkNext(bitStreamEncoder, 158, 553); 118 | result = result && checkNext(bitStreamEncoder, 158, 263); 119 | result = result && checkNext(bitStreamEncoder, 158, 263); 120 | result = result && checkNext(bitStreamEncoder, 158, 553); 121 | result = result && checkNext(bitStreamEncoder, 158, 263); 122 | result = result && checkNext(bitStreamEncoder, 158, 553); 123 | result = result && checkNext(bitStreamEncoder, 158, 553); 124 | result = result && checkNext(bitStreamEncoder, 158, 553); 125 | return result; 126 | } 127 | 128 | void testMessage407(LegoPfBitStreamEncoder& bitStreamEncoder) { 129 | Serial.print(" testMessage407 "); 130 | bitStreamEncoder.reset(407, false); 131 | bool result = true; 132 | result = result && check(bitStreamEncoder, 158, 1026); 133 | result = result && checkDataBitsOfMessage407(bitStreamEncoder); 134 | result = result && checkNext(bitStreamEncoder, 158, 1026); 135 | result = result && !bitStreamEncoder.next(); 136 | logTestResult(result); 137 | } 138 | 139 | void testMessage407Repeated(LegoPfBitStreamEncoder& bitStreamEncoder) { 140 | Serial.print(" testMessage407Repeated "); 141 | bitStreamEncoder.reset(407, true); 142 | bool result = true; 143 | result = result && check(bitStreamEncoder, 158, 1026); 144 | result = result && checkDataBitsOfMessage407(bitStreamEncoder); 145 | result = result && checkNext(bitStreamEncoder, 158, 1026L + 5L * 16000L - 10844L); 146 | result = result && checkNext(bitStreamEncoder, 158, 1026); 147 | result = result && checkDataBitsOfMessage407(bitStreamEncoder); 148 | result = result && checkNext(bitStreamEncoder, 158, 1026L + 5L * 16000L - 10844L); 149 | result = result && checkNext(bitStreamEncoder, 158, 1026); 150 | result = result && checkDataBitsOfMessage407(bitStreamEncoder); 151 | result = result && checkNext(bitStreamEncoder, 158, 1026L + 8L * 16000L - 10844L); 152 | result = result && checkNext(bitStreamEncoder, 158, 1026); 153 | result = result && checkDataBitsOfMessage407(bitStreamEncoder); 154 | result = result && checkNext(bitStreamEncoder, 158, 1026L + 8L * 16000L - 10844L); 155 | result = result && checkNext(bitStreamEncoder, 158, 1026); 156 | result = result && checkDataBitsOfMessage407(bitStreamEncoder); 157 | result = result && checkNext(bitStreamEncoder, 158, 1026); 158 | result = result && !bitStreamEncoder.next(); 159 | logTestResult(result); 160 | } 161 | 162 | void testMessageBitCountRepeat(LegoPfBitStreamEncoder& bitStreamEncoder) { 163 | Serial.print(" testMessageBitCountRepeat "); 164 | bitStreamEncoder.reset(0xFFFF, true); 165 | int bitCount = 1; 166 | while (bitStreamEncoder.next()) { 167 | bitCount++; 168 | } 169 | logTestResult(bitCount == 5 * 18); 170 | } 171 | 172 | void testGetChannelId1(LegoPfBitStreamEncoder& bitStreamEncoder) { 173 | Serial.print(" testGetChannelId1 "); 174 | bitStreamEncoder.reset(407, false); 175 | logTestResult(bitStreamEncoder.getChannelId() == 1); 176 | } 177 | 178 | void testGetChannelId2(LegoPfBitStreamEncoder& bitStreamEncoder) { 179 | Serial.print(" testGetChannelId2 "); 180 | bitStreamEncoder.reset(4502, false); 181 | logTestResult(bitStreamEncoder.getChannelId() == 2); 182 | } 183 | 184 | void testGetChannelId3(LegoPfBitStreamEncoder& bitStreamEncoder) { 185 | Serial.print(" testGetChannelId3 "); 186 | bitStreamEncoder.reset(8597, false); 187 | logTestResult(bitStreamEncoder.getChannelId() == 3); 188 | } 189 | 190 | void testGetChannelId4(LegoPfBitStreamEncoder& bitStreamEncoder) { 191 | Serial.print(" testGetChannelId4 "); 192 | bitStreamEncoder.reset(12692, false); 193 | logTestResult(bitStreamEncoder.getChannelId() == 4); 194 | } 195 | 196 | void testGetMessageLengthAllHigh(LegoPfBitStreamEncoder& bitStreamEncoder) { 197 | Serial.print(" testGetMessageLengthAllHigh "); 198 | bitStreamEncoder.reset(0xFFFF, false); 199 | logTestResult(bitStreamEncoder.getMessageLength() == 13744); 200 | } 201 | 202 | void testGetMessageLengthAllLow(LegoPfBitStreamEncoder& bitStreamEncoder) { 203 | Serial.print(" testGetMessageLengthAllLow "); 204 | bitStreamEncoder.reset(0x0, false); 205 | logTestResult(bitStreamEncoder.getMessageLength() == 9104); 206 | } 207 | -------------------------------------------------------------------------------- /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 | sendSAMSUNG KEYWORD2 31 | sendSharp KEYWORD2 32 | sendSharpRaw KEYWORD2 33 | sendSharpAlt KEYWORD2 34 | sendSharpAltRaw KEYWORD2 35 | sendPanasonic KEYWORD2 36 | sendJVC KEYWORD2 37 | sendLG KEYWORD2 38 | sendMagiQuest KEYWORD2 39 | 40 | ####################################### 41 | # Constants (LITERAL1) 42 | ####################################### 43 | 44 | NEC LITERAL1 45 | SONY LITERAL1 46 | SANYO LITERAL1 47 | MITSUBISHI LITERAL1 48 | RC5 LITERAL1 49 | RC6 LITERAL1 50 | DISH LITERAL1 51 | SAMSUNGL ITERAL1 52 | SHARP LITERAL1 53 | SHARP_ALT LITERAL1 54 | PANASONIC LITERAL1 55 | JVC LITERAL1 56 | LG LITERAL1 57 | AIWA_RC_T501 LITERAL1 58 | MAGIQUEST LITERAL1 59 | UNKNOWN LITERAL1 60 | REPEAT LITERAL1 61 | -------------------------------------------------------------------------------- /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.8.0", 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.8.0 3 | author=shirriff, z3t0 4 | maintainer=Armin Joachimsmeyer 5 | sentence=Send and receive infrared signals with multiple protocols 6 | paragraph=Currently included protocols: BoseWave, Denon, Dish, JVC, Lego, LG, MagiQuest, NEC, Panasonic, RC5, RC6, Samsung, Sanyo, Sharp, Sony, Whynter, (Pronto).

New: Changed License to MIT, ATtiny timer 1 support, Removed AIWA + Mitsubishi, example IR2Keyboard.
7 | category=Communication 8 | url=https://github.com/z3t0/Arduino-IRremote 9 | architectures=avr,megaavr,samd,esp32,mbed 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 | -------------------------------------------------------------------------------- /src/IRremote.cpp: -------------------------------------------------------------------------------- 1 | //****************************************************************************** 2 | // IRremote 3 | // Version 2.0.1 June, 2015 4 | // Initially coded 2009 Ken Shirriff http://www.righto.com 5 | // 6 | // Modified by Paul Stoffregen to support other boards and timers 7 | // Modified by Mitra Ardron 8 | // Added Sanyo and Mitsubishi controllers 9 | // Modified Sony to spot the repeat codes that some Sony's send 10 | // 11 | // Interrupt code based on NECIRrcv by Joe Knapp 12 | // http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1210243556 13 | // Also influenced by http://zovirl.com/2008/11/12/building-a-universal-remote-with-an-arduino/ 14 | // 15 | // JVC and Panasonic protocol added by Kristian Lauszus (Thanks to zenwheel and other people at the original blog post) 16 | // LG added by Darryl Smith (based on the JVC protocol) 17 | // Whynter A/C ARC-110WD added by Francesco Meschia 18 | //****************************************************************************** 19 | 20 | #include "IRremote.h" 21 | 22 | struct irparams_struct irparams; // the irparams instance 23 | 24 | //+============================================================================= 25 | // The match functions were (apparently) originally MACROs to improve code speed 26 | // (although this would have bloated the code) hence the names being CAPS 27 | // A later release implemented debug output and so they needed to be converted 28 | // to functions. 29 | // I tried to implement a dual-compile mode (DEBUG/non-DEBUG) but for some 30 | // reason, no matter what I did I could not get them to function as macros again. 31 | // I have found a *lot* of bugs in the Arduino compiler over the last few weeks, 32 | // and I am currently assuming that one of these bugs is my problem. 33 | // I may revisit this code at a later date and look at the assembler produced 34 | // in a hope of finding out what is going on, but for now they will remain as 35 | // functions even in non-DEBUG mode 36 | // 37 | int MATCH(unsigned int measured, unsigned int desired) { 38 | #if DEBUG 39 | Serial.print(F("Testing: ")); 40 | Serial.print(TICKS_LOW(desired), DEC); 41 | Serial.print(F(" <= ")); 42 | Serial.print(measured, DEC); 43 | Serial.print(F(" <= ")); 44 | Serial.print(TICKS_HIGH(desired), DEC); 45 | #endif 46 | bool passed = ((measured >= TICKS_LOW(desired)) && (measured <= TICKS_HIGH(desired))); 47 | #if DEBUG 48 | if (passed) { 49 | Serial.println(F("?; passed")); 50 | } else { 51 | Serial.println(F("?; FAILED")); 52 | } 53 | #endif 54 | return passed; 55 | } 56 | 57 | //+======================================================== 58 | // Due to sensor lag, when received, Marks tend to be 100us too long 59 | // 60 | int MATCH_MARK(uint16_t measured_ticks, unsigned int desired_us) { 61 | #if DEBUG 62 | Serial.print(F("Testing mark (actual vs desired): ")); 63 | Serial.print(measured_ticks * MICROS_PER_TICK, DEC); 64 | Serial.print(F("us vs ")); 65 | Serial.print(desired_us, DEC); 66 | Serial.print(F("us: ")); 67 | Serial.print(TICKS_LOW(desired_us + MARK_EXCESS_MICROS) * MICROS_PER_TICK, DEC); 68 | Serial.print(F(" <= ")); 69 | Serial.print(measured_ticks * MICROS_PER_TICK, DEC); 70 | Serial.print(F(" <= ")); 71 | Serial.print(TICKS_HIGH(desired_us + MARK_EXCESS_MICROS) * MICROS_PER_TICK, DEC); 72 | #endif 73 | // compensate for marks exceeded by demodulator hardware 74 | bool passed = ((measured_ticks >= TICKS_LOW(desired_us + MARK_EXCESS_MICROS)) 75 | && (measured_ticks <= TICKS_HIGH(desired_us + MARK_EXCESS_MICROS))); 76 | #if DEBUG 77 | if (passed) { 78 | Serial.println(F("?; passed")); 79 | } else { 80 | Serial.println(F("?; FAILED")); 81 | } 82 | #endif 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(uint16_t measured_ticks, unsigned int desired_us) { 90 | #if DEBUG 91 | Serial.print(F("Testing space (actual vs desired): ")); 92 | Serial.print(measured_ticks * MICROS_PER_TICK, DEC); 93 | Serial.print(F("us vs ")); 94 | Serial.print(desired_us, DEC); 95 | Serial.print(F("us: ")); 96 | Serial.print(TICKS_LOW(desired_us - MARK_EXCESS_MICROS) * MICROS_PER_TICK, DEC); 97 | Serial.print(F(" <= ")); 98 | Serial.print(measured_ticks * MICROS_PER_TICK, DEC); 99 | Serial.print(F(" <= ")); 100 | Serial.print(TICKS_HIGH(desired_us - MARK_EXCESS_MICROS) * MICROS_PER_TICK, DEC); 101 | #endif 102 | // compensate for marks exceeded and spaces shortened by demodulator hardware 103 | bool passed = ((measured_ticks >= TICKS_LOW(desired_us - MARK_EXCESS_MICROS)) 104 | && (measured_ticks <= TICKS_HIGH(desired_us - MARK_EXCESS_MICROS))); 105 | #if DEBUG 106 | if (passed) { 107 | Serial.println(F("?; passed")); 108 | } else { 109 | Serial.println(F("?; FAILED")); 110 | } 111 | #endif 112 | return passed; 113 | } 114 | 115 | //+============================================================================= 116 | // Interrupt Service Routine - Fires every 50uS 117 | // TIMER2 interrupt code to collect raw data. 118 | // Widths of alternating SPACE, MARK are recorded in rawbuf. 119 | // Recorded in ticks of 50uS [microseconds, 0.000050 seconds] 120 | // 'rawlen' counts the number of entries recorded so far. 121 | // First entry is the SPACE between transmissions. 122 | // As soon as a the first [SPACE] entry gets long: 123 | // Ready is set; State switches to IDLE; Timing of SPACE continues. 124 | // As soon as first MARK arrives: 125 | // Gap width is recorded; Ready is cleared; New logging starts 126 | // 127 | ISR (TIMER_INTR_NAME) { 128 | TIMER_RESET_INTR_PENDING; // reset timer interrupt flag if required (currently only for Teensy and ATmega4809) 129 | 130 | // Read if IR Receiver -> SPACE [xmt LED off] or a MARK [xmt LED on] 131 | // digitalRead() is very slow. Optimisation is possible, but makes the code unportable 132 | uint8_t irdata = (uint8_t) digitalRead(irparams.recvpin); 133 | 134 | irparams.timer++; // One more 50uS tick 135 | if (irparams.rawlen >= RAW_BUFFER_LENGTH) { 136 | // Flag up a read overflow; Stop the State Machine 137 | irparams.overflow = true; 138 | irparams.rcvstate = IR_REC_STATE_STOP; 139 | } 140 | 141 | /* 142 | * Due to a ESP32 compiler bug https://github.com/espressif/esp-idf/issues/1552 no switch statements are possible for ESP32 143 | * So we change the code to if / else if 144 | */ 145 | // switch (irparams.rcvstate) { 146 | //...................................................................... 147 | if (irparams.rcvstate == IR_REC_STATE_IDLE) { // In the middle of a gap 148 | if (irdata == MARK) { 149 | if (irparams.timer < GAP_TICKS) { // Not big enough to be a gap. 150 | irparams.timer = 0; 151 | } else { 152 | // Gap just ended; Record gap duration; Start recording transmission 153 | // Initialize all state machine variables 154 | irparams.overflow = false; 155 | irparams.rawlen = 0; 156 | irparams.rawbuf[irparams.rawlen++] = irparams.timer; 157 | irparams.timer = 0; 158 | irparams.rcvstate = IR_REC_STATE_MARK; 159 | } 160 | } 161 | } else if (irparams.rcvstate == IR_REC_STATE_MARK) { // Timing Mark 162 | if (irdata == SPACE) { // Mark ended; Record time 163 | irparams.rawbuf[irparams.rawlen++] = irparams.timer; 164 | irparams.timer = 0; 165 | irparams.rcvstate = IR_REC_STATE_SPACE; 166 | } 167 | } else if (irparams.rcvstate == IR_REC_STATE_SPACE) { // Timing Space 168 | if (irdata == MARK) { // Space just ended; Record time 169 | irparams.rawbuf[irparams.rawlen++] = irparams.timer; 170 | irparams.timer = 0; 171 | irparams.rcvstate = IR_REC_STATE_MARK; 172 | 173 | } else if (irparams.timer > GAP_TICKS) { // Space 174 | // A long Space, indicates gap between codes 175 | // Flag the current code as ready for processing 176 | // Switch to STOP 177 | // Don't reset timer; keep counting Space width 178 | irparams.rcvstate = IR_REC_STATE_STOP; 179 | } 180 | } else if (irparams.rcvstate == IR_REC_STATE_STOP) { // Waiting; Measuring Gap 181 | if (irdata == MARK) { 182 | irparams.timer = 0; // Reset gap timer 183 | } 184 | } 185 | 186 | #ifdef BLINKLED 187 | // If requested, flash LED while receiving IR data 188 | if (irparams.blinkflag) { 189 | if (irdata == MARK) { 190 | if (irparams.blinkpin) { 191 | digitalWrite(irparams.blinkpin, HIGH); // Turn user defined pin LED on 192 | } else { 193 | BLINKLED_ON(); // if no user defined LED pin, turn default LED pin for the hardware on 194 | } 195 | } else { 196 | if (irparams.blinkpin) { 197 | digitalWrite(irparams.blinkpin, LOW); // Turn user defined pin LED on 198 | } else { 199 | BLINKLED_OFF(); // if no user defined LED pin, turn default LED pin for the hardware on 200 | } 201 | } 202 | } 203 | #endif // BLINKLED 204 | } 205 | -------------------------------------------------------------------------------- /src/esp32.cpp: -------------------------------------------------------------------------------- 1 | #ifdef ESP32 2 | 3 | // This file contains functions specific to the ESP32. 4 | 5 | #include "IRremote.h" 6 | 7 | // "Idiot check" 8 | #ifdef USE_DEFAULT_ENABLE_IR_IN 9 | #error Must undef USE_DEFAULT_ENABLE_IR_IN 10 | #endif 11 | 12 | hw_timer_t *timer; 13 | IRAM_ATTR void IRTimer(); // defined in IRremote.cpp, masqueraded as ISR(TIMER_INTR_NAME) 14 | 15 | //+============================================================================= 16 | // initialization 17 | // 18 | void IRrecv::enableIRIn() { 19 | // Interrupt Service Routine - Fires every 50uS 20 | // ESP32 has a proper API to setup timers, no weird chip macros needed 21 | // simply call the readable API versions :) 22 | // 3 timers, choose #1, 80 divider nanosecond precision, 1 to count up 23 | timer = timerBegin(1, 80, 1); 24 | timerAttachInterrupt(timer, &IRTimer, 1); 25 | // every 50ns, autoreload = true 26 | timerAlarmWrite(timer, 50, true); 27 | timerAlarmEnable(timer); 28 | 29 | // Initialize state machine variables 30 | irparams.rcvstate = IR_REC_STATE_IDLE; 31 | irparams.rawlen = 0; 32 | 33 | // Set pin modes 34 | pinMode(irparams.recvpin, INPUT); 35 | } 36 | 37 | void IRrecv::disableIRIn() { 38 | timerEnd(timer); 39 | timerDetachInterrupt(timer); 40 | } 41 | 42 | void IRsend::enableIROut(int khz) { 43 | ledcSetup(LED_CHANNEL, khz * 1000, 8); // 8 bit PWM resolution 44 | ledcAttachPin(IR_SEND_PIN, LED_CHANNEL); // bind pin to channel 45 | } 46 | 47 | #endif // ESP32 48 | -------------------------------------------------------------------------------- /src/irPronto.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * @file irPronto.cpp 3 | * @brief In this file, the functions IRrecv::dumpPronto and 4 | * IRsend::sendPronto are defined. 5 | */ 6 | 7 | #include "IRremote.h" 8 | 9 | // DO NOT EXPORT from this file 10 | static const uint16_t MICROSECONDS_T_MAX = 0xFFFFU; 11 | static const uint16_t learnedToken = 0x0000U; 12 | static const uint16_t learnedNonModulatedToken = 0x0100U; 13 | static const unsigned int bitsInHexadecimal = 4U; 14 | static const unsigned int digitsInProntoNumber = 4U; 15 | static const unsigned int numbersInPreamble = 4U; 16 | static const unsigned int hexMask = 0xFU; 17 | static const uint32_t referenceFrequency = 4145146UL; 18 | static const uint16_t fallbackFrequency = 64767U; // To use with frequency = 0; 19 | static const uint32_t microsecondsInSeconds = 1000000UL; 20 | static const unsigned int RESULT_JUNK_COUNT = 1U; 21 | 22 | static unsigned int toFrequencyKHz(uint16_t code) { 23 | return ((referenceFrequency / code) + 500) / 1000; 24 | } 25 | 26 | void IRsend::sendPronto(const uint16_t *data, unsigned int size, unsigned int times) { 27 | unsigned int timebase = (microsecondsInSeconds * data[1] + referenceFrequency / 2) / referenceFrequency; 28 | unsigned int khz; 29 | switch (data[0]) { 30 | case learnedToken: // normal, "learned" 31 | khz = toFrequencyKHz(data[1]); 32 | break; 33 | case learnedNonModulatedToken: // non-demodulated, "learned" 34 | khz = 0U; 35 | break; 36 | default: 37 | return; // There are other types, but they are not handled yet. 38 | } 39 | unsigned int intros = 2 * data[2]; 40 | unsigned int repeats = 2 * data[3]; 41 | if (numbersInPreamble + intros + repeats != size) // inconsistent sizes 42 | return; 43 | 44 | uint16_t durations[intros + repeats]; 45 | for (unsigned int i = 0; i < intros + repeats; i++) { 46 | uint32_t duration = ((uint32_t) data[i + numbersInPreamble]) * timebase; 47 | durations[i] = (unsigned int) ((duration <= MICROSECONDS_T_MAX) ? duration : MICROSECONDS_T_MAX); 48 | } 49 | 50 | unsigned int numberRepeats = intros > 0 ? times - 1 : times; 51 | if (intros > 0) { 52 | sendRaw(durations, intros - 1, khz); 53 | } 54 | 55 | if (numberRepeats == 0) 56 | return; 57 | 58 | delay(durations[intros - 1] / 1000U); 59 | for (unsigned int i = 0; i < numberRepeats; i++) { 60 | sendRaw(durations, intros + repeats - 1, khz); 61 | if (i < numberRepeats - 1) { // skip last wait 62 | delay(durations[intros + repeats - 1] / 1000U); 63 | } 64 | } 65 | } 66 | 67 | void IRsend::sendPronto(const char *str, unsigned int times) { 68 | size_t len = strlen(str) / (digitsInProntoNumber + 1) + 1; 69 | uint16_t data[len]; 70 | const char *p = str; 71 | char *endptr[1]; 72 | for (unsigned int i = 0; i < len; i++) { 73 | long x = strtol(p, endptr, 16); 74 | if (x == 0 && i >= numbersInPreamble) { 75 | // Alignment error?, bail immediately (often right result). 76 | len = i; 77 | break; 78 | } 79 | data[i] = static_cast(x); // If input is conforming, there can be no overflow! 80 | p = *endptr; 81 | } 82 | sendPronto(data, len, times); 83 | } 84 | 85 | #if HAS_FLASH_READ 86 | void IRsend::sendPronto_PF(uint_farptr_t str, unsigned int times) { 87 | size_t len = strlen_PF(STRCPY_PF_CAST(str)); 88 | char work[len + 1]; 89 | strncpy_PF(work, STRCPY_PF_CAST(str), len); 90 | sendPronto(work, times); 91 | } 92 | 93 | void IRsend::sendPronto_PF(const char *str, unsigned int times) { 94 | sendPronto_PF(reinterpret_cast(str), times); // to avoid infinite recursion 95 | } 96 | ; 97 | 98 | void IRsend::sendPronto(const __FlashStringHelper *str, unsigned int times) { 99 | return sendPronto_PF(reinterpret_cast(str), times); 100 | } 101 | #endif 102 | 103 | static uint16_t effectiveFrequency(uint16_t frequency) { 104 | return frequency > 0 ? frequency : fallbackFrequency; 105 | } 106 | 107 | static uint16_t toTimebase(uint16_t frequency) { 108 | return microsecondsInSeconds / effectiveFrequency(frequency); 109 | } 110 | 111 | static uint16_t toFrequencyCode(uint16_t frequency) { 112 | return referenceFrequency / effectiveFrequency(frequency); 113 | } 114 | 115 | static char hexDigit(unsigned int x) { 116 | return (char) (x <= 9 ? ('0' + x) : ('A' + (x - 10))); 117 | } 118 | 119 | static void dumpDigit(Print *aSerial, unsigned int number) { 120 | aSerial->print(hexDigit(number)); 121 | } 122 | 123 | static void dumpDigit(char *&varChar, unsigned int number) { 124 | *varChar = hexDigit(number); 125 | varChar++; 126 | } 127 | 128 | static void dumpNumber(Print *aSerial, uint16_t number) { 129 | for (unsigned int i = 0; i < digitsInProntoNumber; i++) { 130 | unsigned int shifts = bitsInHexadecimal * (digitsInProntoNumber - 1 - i); 131 | dumpDigit(aSerial, (number >> shifts) & hexMask); 132 | } 133 | aSerial->print(' '); 134 | } 135 | 136 | static void dumpNumber(char *&varChar, uint16_t number) { 137 | for (unsigned int i = 0; i < digitsInProntoNumber; i++) { 138 | unsigned int shifts = bitsInHexadecimal * (digitsInProntoNumber - 1 - i); 139 | dumpDigit(varChar, (number >> shifts) & hexMask); 140 | } 141 | *varChar = ' '; 142 | varChar++; 143 | } 144 | 145 | static void dumpDuration(Print *aSerial, uint16_t duration, uint16_t timebase) { 146 | dumpNumber(aSerial, (duration * MICROS_PER_TICK + timebase / 2) / timebase); 147 | } 148 | 149 | static void dumpDuration(char *&varChar, uint16_t duration, uint16_t timebase) { 150 | dumpNumber(varChar, (duration * MICROS_PER_TICK + timebase / 2) / timebase); 151 | } 152 | 153 | static void dumpSequence(Print *aSerial, const volatile uint16_t *data, size_t length, uint16_t timebase) { 154 | for (unsigned int i = 0; i < length; i++) 155 | dumpDuration(aSerial, data[i], timebase); 156 | 157 | dumpDuration(aSerial, _GAP, timebase); 158 | } 159 | 160 | static void dumpSequence(char *&varChar, const volatile uint16_t *data, size_t length, uint16_t timebase) { 161 | for (unsigned int i = 0; i < length; i++) 162 | dumpDuration(varChar, data[i], timebase); 163 | 164 | dumpDuration(varChar, _GAP, timebase); 165 | 166 | *varChar = '\0'; 167 | } 168 | 169 | /* 170 | * Using Print instead of Stream saves 1020 bytes program memory 171 | * Changed from & to * parameter type to be more transparent and consistent with other code of IRremote 172 | */ 173 | void IRrecv::dumpPronto(Print *aSerial, unsigned int frequency) { 174 | dumpNumber(aSerial, frequency > 0 ? learnedToken : learnedNonModulatedToken); 175 | dumpNumber(aSerial, toFrequencyCode(frequency)); 176 | dumpNumber(aSerial, (results.rawlen + 1) / 2); 177 | dumpNumber(aSerial, 0); 178 | unsigned int timebase = toTimebase(frequency); 179 | dumpSequence(aSerial, results.rawbuf + RESULT_JUNK_COUNT, results.rawlen - RESULT_JUNK_COUNT, timebase); 180 | } 181 | 182 | void IRrecv::dumpPronto(char *&varStr, unsigned int frequency) { 183 | dumpNumber(varStr, frequency > 0 ? learnedToken : learnedNonModulatedToken); 184 | dumpNumber(varStr, toFrequencyCode(frequency)); 185 | dumpNumber(varStr, (results.rawlen + 1) / 2); 186 | dumpNumber(varStr, 0); 187 | unsigned int timebase = toTimebase(frequency); 188 | dumpSequence(varStr, results.rawbuf + RESULT_JUNK_COUNT, results.rawlen - RESULT_JUNK_COUNT, timebase); 189 | } 190 | 191 | //+============================================================================= 192 | // Dump out the raw data as Pronto Hex. 193 | // I know Stream * is locally inconsistent, but all global print functions use it 194 | // 195 | void IRrecv::printIRResultAsPronto(Print *aSerial, unsigned int frequency) { 196 | aSerial->print("Pronto Hex: "); 197 | dumpPronto(aSerial, frequency); 198 | aSerial->println(); 199 | } 200 | -------------------------------------------------------------------------------- /src/irSend.cpp: -------------------------------------------------------------------------------- 1 | #include "IRremote.h" 2 | 3 | #ifdef SENDING_SUPPORTED // from IRremoteBoardDefs.h 4 | //+============================================================================= 5 | void IRsend::sendRaw(const uint16_t aBufferWithMicroseconds[], uint8_t aLengthOfBuffer, uint8_t aIRFrequencyKilohertz) { 6 | // Set IR carrier frequency 7 | enableIROut(aIRFrequencyKilohertz); 8 | 9 | for (uint8_t i = 0; i < aLengthOfBuffer; i++) { 10 | if (i & 1) { 11 | space(aBufferWithMicroseconds[i]); 12 | } else { 13 | mark(aBufferWithMicroseconds[i]); 14 | } 15 | } 16 | 17 | space(0); // Always end with the LED off 18 | } 19 | 20 | void IRsend::sendRaw(const uint8_t aBufferWithTicks[], uint8_t aLengthOfBuffer, uint8_t aIRFrequencyKilohertz) { 21 | // Set IR carrier frequency 22 | enableIROut(aIRFrequencyKilohertz); 23 | 24 | for (uint8_t i = 0; i < aLengthOfBuffer; i++) { 25 | if (i & 1) { 26 | space(aBufferWithTicks[i] * MICROS_PER_TICK); 27 | } else { 28 | mark(aBufferWithTicks[i] * MICROS_PER_TICK); 29 | } 30 | } 31 | 32 | space(0); // Always end with the LED off 33 | } 34 | 35 | void IRsend::sendRaw_P(const uint16_t aBufferWithMicroseconds[], uint8_t aLengthOfBuffer, uint8_t aIRFrequencyKilohertz) { 36 | #if !defined(__AVR__) 37 | sendRaw(aBufferWithMicroseconds, aLengthOfBuffer, aIRFrequencyKilohertz); // Let the function work for non AVR platforms 38 | #else 39 | // Set IR carrier frequency 40 | enableIROut(aIRFrequencyKilohertz); 41 | 42 | for (uint8_t i = 0; i < aLengthOfBuffer; i++) { 43 | uint16_t duration = pgm_read_word(&aBufferWithMicroseconds[i]); 44 | if (i & 1) { 45 | space(duration); 46 | } else { 47 | mark(duration); 48 | } 49 | } 50 | space(0); // Always end with the LED off 51 | #endif 52 | } 53 | 54 | void IRsend::sendRaw_P(const uint8_t aBufferWithTicks[], uint8_t aLengthOfBuffer, uint8_t aIRFrequencyKilohertz) { 55 | #if !defined(__AVR__) 56 | sendRaw(aBufferWithTicks, aLengthOfBuffer, aIRFrequencyKilohertz); // Let the function work for non AVR platforms 57 | #else 58 | // Set IR carrier frequency 59 | enableIROut(aIRFrequencyKilohertz); 60 | 61 | for (uint8_t i = 0; i < aLengthOfBuffer; i++) { 62 | uint16_t duration = pgm_read_byte(&aBufferWithTicks[i]) * (uint16_t)MICROS_PER_TICK; 63 | if (i & 1) { 64 | space(duration); 65 | } else { 66 | mark(duration); 67 | } 68 | } 69 | space(0); // Always end with the LED off 70 | #endif 71 | } 72 | 73 | #ifdef USE_SOFT_SEND_PWM 74 | void inline IRsend::sleepMicros(unsigned long us) { 75 | #ifdef USE_SPIN_WAIT 76 | sleepUntilMicros(micros() + us); 77 | #else 78 | if (us > 0U) { // Is this necessary? (Official docu https://www.arduino.cc/en/Reference/DelayMicroseconds does not tell.) 79 | delayMicroseconds((unsigned int) us); 80 | } 81 | #endif 82 | } 83 | 84 | void inline IRsend::sleepUntilMicros(unsigned long targetTime) { 85 | #ifdef USE_SPIN_WAIT 86 | while (micros() < targetTime) 87 | ; 88 | #else 89 | unsigned long now = micros(); 90 | if (now < targetTime) { 91 | sleepMicros(targetTime - now); 92 | } 93 | #endif 94 | } 95 | #endif // USE_SOFT_SEND_PWM 96 | 97 | //+============================================================================= 98 | // Sends PulseDistance data from MSB to LSB 99 | // 100 | void IRsend::sendPulseDistanceWidthData(unsigned int aOneMarkMicros, unsigned int aOneSpaceMicros, unsigned int aZeroMarkMicros, 101 | unsigned int aZeroSpaceMicros, unsigned long aData, uint8_t aNumberOfBits, bool aMSBfirst) { 102 | 103 | if (aMSBfirst) { // Send the MSB first. 104 | // send data from MSB to LSB until mask bit is shifted out 105 | for (unsigned long mask = 1UL << (aNumberOfBits - 1); mask; mask >>= 1) { 106 | if (aData & mask) { 107 | DBG_PRINT("1"); 108 | mark(aOneMarkMicros); 109 | space(aOneSpaceMicros); 110 | } else { 111 | DBG_PRINT("0"); 112 | mark(aZeroMarkMicros); 113 | space(aZeroSpaceMicros); 114 | } 115 | } 116 | DBG_PRINTLN(""); 117 | } 118 | #if defined(LSB_FIRST_REQUIRED) 119 | else { // Send the Least Significant Bit (LSB) first / MSB last. 120 | for (uint16_t bit = 0; bit < aNumberOfBits; bit++, aData >>= 1) 121 | if (aData & 1) { // Send a 1 122 | DBG_PRINT("1"); 123 | mark(aOneMarkMicros); 124 | space(aOneSpaceMicros); 125 | } else { // Send a 0 126 | DBG_PRINT("0"); 127 | mark(aZeroMarkMicros); 128 | space(aZeroSpaceMicros); 129 | } 130 | DBG_PRINTLN(""); 131 | } 132 | #endif 133 | } 134 | 135 | //+============================================================================= 136 | // Sends an IR mark for the specified number of microseconds. 137 | // The mark output is modulated at the PWM frequency. 138 | // 139 | 140 | void IRsend::mark(uint16_t timeMicros) { 141 | #ifdef USE_SOFT_SEND_PWM 142 | unsigned long start = micros(); 143 | unsigned long stop = start + timeMicros; 144 | if (stop + periodTimeMicros < start) { 145 | // Counter wrap-around, happens very seldom, but CAN happen. 146 | // Just give up instead of possibly damaging the hardware. 147 | return; 148 | } 149 | unsigned long nextPeriodEnding = start; 150 | unsigned long now = micros(); 151 | while (now < stop) { 152 | SENDPIN_ON(sendPin); 153 | sleepMicros (periodOnTimeMicros); 154 | SENDPIN_OFF(sendPin); 155 | nextPeriodEnding += periodTimeMicros; 156 | sleepUntilMicros(nextPeriodEnding); 157 | now = micros(); 158 | } 159 | #elif defined(USE_NO_SEND_PWM) 160 | digitalWrite(sendPin, LOW); // Set output to active low. 161 | #else 162 | TIMER_ENABLE_SEND_PWM; // Enable pin 3 PWM output 163 | #endif 164 | delayMicroseconds(timeMicros); 165 | } 166 | 167 | void IRsend::mark_long(uint32_t timeMicros) { 168 | #if defined(USE_NO_SEND_PWM) 169 | digitalWrite(sendPin, LOW); // Set output to active low. 170 | #else 171 | TIMER_ENABLE_SEND_PWM; // Enable pin 3 PWM output 172 | #endif 173 | custom_delay_usec(timeMicros); 174 | } 175 | 176 | //+============================================================================= 177 | // Leave pin off for time (given in microseconds) 178 | // Sends an IR space for the specified number of microseconds. 179 | // A space is no output, so the PWM output is disabled. 180 | // 181 | void IRsend::space(uint16_t timeMicros) { 182 | #if defined(USE_NO_SEND_PWM) 183 | digitalWrite(sendPin, HIGH); // Set output to inactive high. 184 | #else 185 | TIMER_DISABLE_SEND_PWM; // Disable PWM output 186 | #endif 187 | delayMicroseconds(timeMicros); // overflow at 0x4000 / 16.384 188 | } 189 | 190 | /* 191 | * used e.g. by LEGO 192 | */ 193 | void IRsend::space_long(uint32_t timeMicros) { 194 | #if defined(USE_NO_SEND_PWM) 195 | digitalWrite(sendPin, HIGH); // Set output to inactive high. 196 | #else 197 | TIMER_DISABLE_SEND_PWM; // Disable PWM output 198 | #endif 199 | // custom delay does not work on an ATtiny85 with 1 MHz. It results in a delay of 760 us instead of the requested 560 us 200 | custom_delay_usec(timeMicros); 201 | } 202 | 203 | #ifdef USE_DEFAULT_ENABLE_IR_OUT 204 | //+============================================================================= 205 | // Enables IR output. The khz value controls the modulation frequency in kilohertz. 206 | // The IR output will be on pin 3 (OC2B). 207 | // This routine is designed for 36-40KHz; if you use it for other values, it's up to you 208 | // to make sure it gives reasonable results. (Watch out for overflow / underflow / rounding.) 209 | // TIMER2 is used in phase-correct PWM mode, with OCR2A controlling the frequency and OCR2B 210 | // controlling the duty cycle. 211 | // There is no prescaling, so the output frequency is 16MHz / (2 * OCR2A) 212 | // To turn the output on and off, we leave the PWM running, but connect and disconnect the output pin. 213 | // A few hours staring at the ATmega documentation and this will all make sense. 214 | // See my Secrets of Arduino PWM at http://arcfn.com/2009/07/secrets-of-arduino-pwm.html for details. 215 | // 216 | void IRsend::enableIROut(int khz) { 217 | #ifdef USE_SOFT_SEND_PWM 218 | periodTimeMicros = (1000U + khz / 2) / khz; // = 1000/khz + 1/2 = round(1000.0/khz) 219 | periodOnTimeMicros = periodTimeMicros * IR_SEND_DUTY_CYCLE / 100U - PULSE_CORRECTION_MICROS; 220 | #endif 221 | 222 | #if defined(USE_NO_SEND_PWM) 223 | pinMode(sendPin, OUTPUT); 224 | digitalWrite(sendPin, HIGH); // Set output to inactive high. 225 | #else 226 | // Disable the Timer2 Interrupt (which is used for receiving IR) 227 | TIMER_DISABLE_RECEIVE_INTR; //Timer2 Overflow Interrupt 228 | 229 | pinMode(sendPin, OUTPUT); 230 | 231 | SENDPIN_OFF(sendPin); // When not sending, we want it low 232 | 233 | timerConfigForSend(khz); 234 | #endif 235 | } 236 | #endif 237 | 238 | //+============================================================================= 239 | // Custom delay function that circumvents Arduino's delayMicroseconds 16 bit limit 240 | // It does not work on an ATtiny85 with 1 MHz. It results in a delay of 760 us instead of the requested 560 us 241 | 242 | void IRsend::custom_delay_usec(unsigned long uSecs) { 243 | if (uSecs > 4) { 244 | unsigned long start = micros(); 245 | unsigned long endMicros = start + uSecs - 4; 246 | if (endMicros < start) { // Check if overflow 247 | while (micros() > start) { 248 | } // wait until overflow 249 | } 250 | while (micros() < endMicros) { 251 | } // normal wait 252 | } 253 | } 254 | 255 | #endif // SENDING_SUPPORTED 256 | -------------------------------------------------------------------------------- /src/ir_BoseWave.cpp: -------------------------------------------------------------------------------- 1 | #include "IRremote.h" 2 | 3 | //============================================================================== 4 | // BBBB OOO SSSS EEEEE 5 | // B B O O S E 6 | // BB B O O SSS EEEE 7 | // B B O O S E 8 | // BBBB OOO SSSS EEEEE 9 | //============================================================================== 10 | // 11 | // Bose Wave Radio CD Remote Control 12 | // |-------------------------------------| 13 | // | On/Off Sleep VolUp | 14 | // | Play/Pause Stop VolDown | 15 | // | FM AM Aux | 16 | // | Tune Down Tune Up Mute | 17 | // | 1 2 3 | 18 | // | 4 5 6 | 19 | // |-------------------------------------| 20 | // 21 | // Support for Bose Wave Radio CD provided by https://github.com/uvotguy. 22 | // 23 | // This protocol was reverse engineered by capturing IR signals from a working 24 | // remote. Multiple signals were captured on my oscilloscope, and the timing 25 | // values were averaged. 26 | // 27 | // IR codes are 8 bits. Transmission starts with a header: a mark and a space. 28 | // The header is followed by an 8-bit command, where a bit is a mark and a short 29 | // space (1) or a long space (0). The command is followed by the complement of 30 | // the command (8 bits). A transmission ends with a short mark. 31 | // 32 | // As seen on my trusty oscilloscope, there is no repeat code. Instead, when I 33 | // press and hold a button on my remote, it sends a command, makes a 51.2ms space, 34 | // and resends the command, etc, etc. 35 | // 36 | // It may be worth noting that these values do NOT match those in the LIRC 37 | // remote database (http://lirc.sourceforge.net/remotes/bose/). 38 | 39 | #define CMD_ON_OFF 0xff 40 | #define CMD_MUTE 0xfe 41 | #define CMD_VOL_UP 0xfd 42 | #define CMD_VOL_DOWN 0xfc 43 | #define CMD_PRESET_6 0xfb 44 | #define CMD_SLEEP 0xfa 45 | #define CMD_FM 0xf9 46 | #define CMD_AUX 0xf8 47 | #define CMD_AM 0xf7 48 | #define CMD_PLAY_PAUSE 0xf6 49 | #define CMD_STOP 0xf5 50 | #define CMD_TUNE_UP 0xf4 51 | #define CMD_TUNE_DOWN 0xf3 52 | #define CMD_PRESET_1 0xf2 53 | #define CMD_PRESET_2 0xf1 54 | #define CMD_PRESET_3 0xf0 55 | #define CMD_PRESET_4 0xef 56 | #define CMD_PRESET_5 0xee 57 | 58 | #define BOSEWAVE_BITS 8 59 | #define BOSEWAVE_HEADER_MARK 1061 60 | #define BOSEWAVE_HEADER_SPACE 1456 61 | #define BOSEWAVE_BIT_MARK 534 62 | #define BOSEWAVE_ONE_SPACE 468 63 | #define BOSEWAVE_ZERO_SPACE 1447 64 | #define BOSEWAVE_END_MARK 614 65 | #define BOSEWAVE_REPEAT_SPACE 51200 // Not used. 66 | 67 | //+============================================================================= 68 | #if SEND_BOSEWAVE 69 | uint16_t rawSignal[35]; 70 | void IRsend::sendBoseWave(unsigned char code) { 71 | 72 | int index = 0; 73 | // Header 74 | rawSignal[index++] = BOSEWAVE_HEADER_MARK; 75 | rawSignal[index++] = BOSEWAVE_HEADER_SPACE; 76 | 77 | // 8 bit command 78 | for (unsigned char mask = 0x80; mask; mask >>= 1) { 79 | rawSignal[index++] = BOSEWAVE_BIT_MARK; 80 | if (code & mask) { 81 | rawSignal[index++] = BOSEWAVE_ONE_SPACE; 82 | } else { 83 | rawSignal[index++] = BOSEWAVE_ZERO_SPACE; 84 | } 85 | } 86 | 87 | // 8 bit command complement 88 | for (unsigned char mask = 0x80; mask; mask >>= 1) { 89 | rawSignal[index++] = BOSEWAVE_BIT_MARK; 90 | if (code & mask) { 91 | rawSignal[index++] = BOSEWAVE_ZERO_SPACE; 92 | } else { 93 | rawSignal[index++] = BOSEWAVE_ONE_SPACE; 94 | } 95 | } 96 | // End transmission 97 | rawSignal[index++] = BOSEWAVE_END_MARK; 98 | 99 | // Transmit 100 | this->sendRaw(rawSignal, 35, 38); 101 | } 102 | #endif 103 | 104 | //+============================================================================= 105 | #if DECODE_BOSEWAVE 106 | bool IRrecv::decodeBoseWave() { 107 | unsigned char command = 0; // Decoded command 108 | unsigned char complement = 0; // Decoded command complement 109 | 110 | int index = 0; // Index in to results array 111 | 112 | DBG_PRINTLN("Decoding Bose Wave ..."); 113 | 114 | // Check we have enough data 115 | if (irparams.rawlen < (2 * BOSEWAVE_BITS * 2) + 3) { 116 | DBG_PRINT("\tInvalid data length found: "); 117 | DBG_PRINTLN(results.rawlen); 118 | return false; 119 | } 120 | 121 | // Check header "mark" 122 | index = 1; 123 | if (!MATCH_MARK(results.rawbuf[index], BOSEWAVE_HEADER_MARK)) { 124 | DBG_PRINT("\tInvalid Header Mark. Expecting "); 125 | DBG_PRINT(BOSEWAVE_HEADER_MARK); 126 | DBG_PRINT(". Got "); 127 | DBG_PRINTLN(results.rawbuf[index] * MICROS_PER_TICK); 128 | return false; 129 | } 130 | index++; 131 | 132 | // Check header "space" 133 | if (!MATCH_SPACE(results.rawbuf[index], BOSEWAVE_HEADER_SPACE)) { 134 | DBG_PRINT("\tInvalid Header Space. Expecting "); 135 | DBG_PRINT(BOSEWAVE_HEADER_SPACE); 136 | DBG_PRINT(". Got "); 137 | DBG_PRINTLN(results.rawbuf[index] * MICROS_PER_TICK); 138 | return false; 139 | } 140 | index++; 141 | 142 | // Decode the data bits 143 | for (int ii = 7; ii >= 0; ii--) { 144 | // Check bit "mark". Mark is always the same length. 145 | if (!MATCH_MARK(results.rawbuf[index], BOSEWAVE_BIT_MARK)) { 146 | DBG_PRINT("\tInvalid command Mark. Expecting "); 147 | DBG_PRINT(BOSEWAVE_BIT_MARK); 148 | DBG_PRINT(". Got "); 149 | DBG_PRINTLN(results.rawbuf[index] * MICROS_PER_TICK); 150 | return false; 151 | } 152 | index++; 153 | 154 | // Check bit "space" 155 | if (MATCH_SPACE(results.rawbuf[index], BOSEWAVE_ONE_SPACE)) { 156 | command |= (0x01 << ii); 157 | } else if (MATCH_SPACE(results.rawbuf[index], BOSEWAVE_ZERO_SPACE)) { 158 | // Nothing to do for zeroes. 159 | } else { 160 | DBG_PRINT("\tInvalid command Space. Got "); 161 | DBG_PRINTLN(results.rawbuf[index] * MICROS_PER_TICK); 162 | return false; 163 | } 164 | index++; 165 | } 166 | 167 | // Decode the command complement bits. We decode it here as the complement 168 | // of the complement (0=1 and 1=0) so we can easily compare it to the command. 169 | for (int ii = 7; ii >= 0; ii--) { 170 | // Check bit "mark". Mark is always the same length. 171 | if (!MATCH_MARK(results.rawbuf[index], BOSEWAVE_BIT_MARK)) { 172 | DBG_PRINT("\tInvalid complement Mark. Expecting "); 173 | DBG_PRINT(BOSEWAVE_BIT_MARK); 174 | DBG_PRINT(". Got "); 175 | DBG_PRINTLN(results.rawbuf[index] * MICROS_PER_TICK); 176 | return false; 177 | } 178 | index++; 179 | 180 | // Check bit "space" 181 | if (MATCH_SPACE(results.rawbuf[index], BOSEWAVE_ONE_SPACE)) { 182 | // Nothing to do. 183 | } else if (MATCH_SPACE(results.rawbuf[index], BOSEWAVE_ZERO_SPACE)) { 184 | complement |= (0x01 << ii); 185 | } else { 186 | DBG_PRINT("\tInvalid complement Space. Got "); 187 | DBG_PRINTLN(results.rawbuf[index] * MICROS_PER_TICK); 188 | return false; 189 | } 190 | index++; 191 | } 192 | 193 | if (command != complement) { 194 | DBG_PRINT("\tComplement is not correct. Command=0x"); 195 | DBG_PRINT(command, HEX); 196 | DBG_PRINT(" Complement=0x"); 197 | DBG_PRINTLN(complement, HEX); 198 | return false; 199 | } else { 200 | DBG_PRINTLN("\tValid command"); 201 | } 202 | 203 | // Check end "mark" 204 | if (MATCH_MARK(results.rawbuf[index], BOSEWAVE_END_MARK) == 0) { 205 | DBG_PRINT("\tInvalid end Mark. Got "); 206 | DBG_PRINTLN(results.rawbuf[index] * MICROS_PER_TICK); 207 | return false; 208 | } 209 | 210 | // Success 211 | results.bits = BOSEWAVE_BITS; 212 | results.value = command; 213 | results.decode_type = BOSEWAVE; 214 | 215 | return true; 216 | } 217 | bool IRrecv::decodeBoseWave(decode_results *aResults) { 218 | bool aReturnValue = decodeBoseWave(); 219 | *aResults = results; 220 | return aReturnValue; 221 | } 222 | #endif 223 | -------------------------------------------------------------------------------- /src/ir_Denon.cpp: -------------------------------------------------------------------------------- 1 | #include "IRremote.h" 2 | 3 | // Reverse Engineered by looking at RAW dumps generated by IRremote 4 | 5 | // I have since discovered that Denon publish all their IR codes: 6 | // https://www.google.co.uk/search?q=DENON+MASTER+IR+Hex+Command+Sheet 7 | // -> http://assets.denon.com/documentmaster/us/denon%20master%20ir%20hex.xls 8 | 9 | // Having looked at the official Denon Pronto sheet and reverse engineered 10 | // the timing values from it, it is obvious that Denon have a range of 11 | // different timings and protocols ...the values here work for my AVR-3801 Amp! 12 | 13 | //============================================================================== 14 | // DDDD EEEEE N N OOO N N 15 | // D D E NN N O O NN N 16 | // D D EEE N N N O O N N N 17 | // D D E N NN O O N NN 18 | // DDDD EEEEE N N OOO N N 19 | //============================================================================== 20 | 21 | #define DENON_BITS 14 // The number of bits in the command 22 | 23 | #define DENON_HEADER_MARK 300 // The length of the Header:Mark 24 | #define DENON_HEADER_SPACE 750 // The lenght of the Header:Space 25 | 26 | #define DENON_BIT_MARK 300 // The length of a Bit:Mark 27 | #define DENON_ONE_SPACE 1800 // The length of a Bit:Space for 1's 28 | #define DENON_ZERO_SPACE 750 // The length of a Bit:Space for 0's 29 | 30 | //+============================================================================= 31 | // 32 | #if SEND_DENON 33 | void IRsend::sendDenon(unsigned long data, int nbits) { 34 | // Set IR carrier frequency 35 | enableIROut(38); 36 | 37 | // Header 38 | mark(DENON_HEADER_MARK); 39 | space(DENON_HEADER_SPACE); 40 | 41 | // Data 42 | sendPulseDistanceWidthData(DENON_BIT_MARK, DENON_ONE_SPACE, DENON_BIT_MARK, DENON_ZERO_SPACE, data, nbits); 43 | 44 | // Footer 45 | mark(DENON_BIT_MARK); 46 | space(0); // Always end with the LED off 47 | } 48 | #endif 49 | 50 | //+============================================================================= 51 | // 52 | #if DECODE_DENON 53 | bool IRrecv::decodeDenon() { 54 | int offset = 1; // Skip the gap reading 55 | 56 | // Check we have the right amount of data 57 | if (irparams.rawlen != 1 + 2 + (2 * DENON_BITS) + 1) { 58 | return false; 59 | } 60 | 61 | // Check initial Mark+Space match 62 | if (!MATCH_MARK(results.rawbuf[offset], DENON_HEADER_MARK)) { 63 | return false; 64 | } 65 | offset++; 66 | 67 | if (!MATCH_SPACE(results.rawbuf[offset], DENON_HEADER_SPACE)) { 68 | return false; 69 | } 70 | offset++; 71 | 72 | // Read the bits in 73 | if (!decodePulseDistanceData(DENON_BITS, offset, DENON_BIT_MARK, DENON_ONE_SPACE, DENON_ZERO_SPACE)) { 74 | return false; 75 | } 76 | 77 | // Success 78 | results.bits = DENON_BITS; 79 | results.decode_type = DENON; 80 | return true; 81 | } 82 | 83 | bool IRrecv::decodeDenon(decode_results *aResults) { 84 | bool aReturnValue = decodeDenon(); 85 | *aResults = results; 86 | return aReturnValue; 87 | } 88 | #endif 89 | -------------------------------------------------------------------------------- /src/ir_Dish.cpp: -------------------------------------------------------------------------------- 1 | #include "IRremote.h" 2 | 3 | //============================================================================== 4 | // DDDD IIIII SSSS H H 5 | // D D I S H H 6 | // D D I SSS HHHHH 7 | // D D I S H H 8 | // DDDD IIIII SSSS H H 9 | //============================================================================== 10 | 11 | // Sharp and DISH support by Todd Treece ( http://unionbridge.org/design/ircommand ) 12 | // 13 | // The send function needs to be repeated 4 times 14 | // 15 | // Only send the last for characters of the hex. 16 | // I.E. Use 0x1C10 instead of 0x0000000000001C10 as listed in the LIRC file. 17 | // 18 | // Here is the LIRC file I found that seems to match the remote codes from the 19 | // oscilloscope: 20 | // DISH NETWORK (echostar 301): 21 | // http://lirc.sourceforge.net/remotes/echostar/301_501_3100_5100_58xx_59xx 22 | 23 | #define DISH_BITS 16 24 | #define DISH_HEADER_MARK 400 25 | #define DISH_HEADER_SPACE 6100 26 | #define DISH_BIT_MARK 400 27 | #define DISH_ONE_SPACE 1700 28 | #define DISH_ZERO_SPACE 2800 29 | #define DISH_REPEAT_SPACE 6200 30 | 31 | //+============================================================================= 32 | #if SEND_DISH 33 | void IRsend::sendDISH(unsigned long data, int nbits) { 34 | // Set IR carrier frequency 35 | enableIROut(56); 36 | 37 | mark(DISH_HEADER_MARK); 38 | space(DISH_HEADER_SPACE); 39 | 40 | sendPulseDistanceWidthData(DISH_BIT_MARK, DISH_ONE_SPACE, DISH_BIT_MARK, DISH_ZERO_SPACE, data, nbits); 41 | // for (unsigned long mask = 1UL << (nbits - 1); mask; mask >>= 1) { 42 | // if (data & mask) { 43 | // mark(DISH_BIT_MARK); 44 | // space(DISH_ONE_SPACE); 45 | // } else { 46 | // mark(DISH_BIT_MARK); 47 | // space(DISH_ZERO_SPACE); 48 | // } 49 | // } 50 | 51 | mark(DISH_HEADER_MARK); //added 26th March 2016, by AnalysIR ( https://www.AnalysIR.com ) 52 | space(0); // Always end with the LED off 53 | } 54 | #endif 55 | 56 | -------------------------------------------------------------------------------- /src/ir_JVC.cpp: -------------------------------------------------------------------------------- 1 | #include "IRremote.h" 2 | 3 | //============================================================================== 4 | // JJJJJ V V CCCC 5 | // J V V C 6 | // J V V C 7 | // J J V V C 8 | // J V CCCC 9 | //============================================================================== 10 | 11 | // https://www.sbprojects.net/knowledge/ir/jvc.php 12 | // Here it is decoded MSB first!!! It is not corrected in order to be backwards compatible! 13 | 14 | #define JVC_BITS 16 15 | #define JVC_HEADER_MARK 8400 16 | #define JVC_HEADER_SPACE 4200 17 | #define JVC_BIT_MARK 600 18 | #define JVC_ONE_SPACE 1600 19 | #define JVC_ZERO_SPACE 550 20 | #define JVC_REPEAT_SPACE 50000 // Not used. 21 | 22 | //+============================================================================= 23 | // JVC does NOT repeat by sending a separate code (like NEC does). 24 | // The JVC protocol repeats by skipping the header. 25 | // To send a JVC repeat signal, send the original code value 26 | // and set 'repeat' to true 27 | // 28 | // JVC commands sometimes need to be sent two or three times with 40 to 60 ms pause in between. 29 | // 30 | #if SEND_JVC 31 | void IRsend::sendJVC(unsigned long data, int nbits, bool repeat) { 32 | // Set IR carrier frequency 33 | enableIROut(38); 34 | 35 | // Only send the Header if this is NOT a repeat command 36 | if (!repeat) { 37 | mark(JVC_HEADER_MARK); 38 | space(JVC_HEADER_SPACE); 39 | } 40 | 41 | // Data 42 | sendPulseDistanceWidthData(JVC_BIT_MARK, JVC_ONE_SPACE, JVC_BIT_MARK, JVC_ZERO_SPACE, data, nbits, true); 43 | 44 | // Footer 45 | mark(JVC_BIT_MARK); 46 | space(0); // Always end with the LED off 47 | } 48 | #endif 49 | 50 | //+============================================================================= 51 | #if DECODE_JVC 52 | bool IRrecv::decodeJVC() { 53 | int offset = 1; // Skip first space 54 | 55 | // Check for repeat 56 | if ((results.rawlen - 1 == 33) && MATCH_MARK(results.rawbuf[offset], JVC_BIT_MARK) 57 | && MATCH_MARK(results.rawbuf[results.rawlen - 1], JVC_BIT_MARK)) { 58 | results.bits = 0; 59 | results.value = REPEAT; 60 | results.isRepeat = true; 61 | results.decode_type = JVC; 62 | return true; 63 | } 64 | 65 | // Initial mark 66 | if (!MATCH_MARK(results.rawbuf[offset], JVC_HEADER_MARK)) { 67 | return false; 68 | } 69 | offset++; 70 | 71 | // Check we have enough data - +3 for start bit mark and space + stop bit mark 72 | if (results.rawlen <= (2 * JVC_BITS) + 3) { 73 | return false; 74 | } 75 | 76 | // Initial space 77 | if (!MATCH_SPACE(results.rawbuf[offset], JVC_HEADER_SPACE)) { 78 | return false; 79 | } 80 | offset++; 81 | 82 | if (!decodePulseDistanceData(JVC_BITS, offset, JVC_BIT_MARK, JVC_ONE_SPACE, JVC_ZERO_SPACE)) { 83 | return false; 84 | } 85 | 86 | // Stop bit 87 | if (!MATCH_MARK(results.rawbuf[offset + (2 * JVC_BITS)], JVC_BIT_MARK)) { 88 | DBG_PRINT("Stop bit verify failed"); 89 | return false; 90 | } 91 | 92 | // Success 93 | results.bits = JVC_BITS; 94 | results.decode_type = JVC; 95 | 96 | return true; 97 | } 98 | 99 | bool IRrecv::decodeJVC(decode_results *aResults) { 100 | bool aReturnValue = decodeJVC(); 101 | *aResults = results; 102 | return aReturnValue; 103 | } 104 | #endif 105 | 106 | -------------------------------------------------------------------------------- /src/ir_LG.cpp: -------------------------------------------------------------------------------- 1 | #include "IRremote.h" 2 | 3 | //============================================================================== 4 | // L GGGG 5 | // L G 6 | // L G GG 7 | // L G G 8 | // LLLLL GGG 9 | //============================================================================== 10 | 11 | #define LG_BITS 28 12 | 13 | #define LG_HEADER_MARK 8400 14 | #define LG_HEADER_SPACE 4200 15 | #define LG_BIT_MARK 600 16 | #define LG_ONE_SPACE 1600 17 | #define LG_ZERO_SPACE 550 18 | 19 | //+============================================================================= 20 | #if DECODE_LG 21 | bool IRrecv::decodeLG() { 22 | int offset = 1; // Skip first space 23 | 24 | // Check we have the right amount of data +3 for start bit mark and space + stop bit mark 25 | if (irparams.rawlen <= (2 * LG_BITS) + 3) 26 | return false; 27 | 28 | // Initial mark/space 29 | if (!MATCH_MARK(results.rawbuf[offset], LG_HEADER_MARK)) { 30 | return false; 31 | } 32 | offset++; 33 | 34 | if (!MATCH_SPACE(results.rawbuf[offset], LG_HEADER_SPACE)) { 35 | return false; 36 | } 37 | offset++; 38 | 39 | if (!decodePulseDistanceData(LG_BITS, offset, LG_BIT_MARK, LG_ONE_SPACE, LG_ZERO_SPACE)) { 40 | return false; 41 | } 42 | // Stop bit 43 | if (!MATCH_MARK(results.rawbuf[offset + (2 * LG_BITS)], LG_BIT_MARK)) { 44 | DBG_PRINT("Stop bit verify failed"); 45 | return false; 46 | } 47 | 48 | // Success 49 | results.bits = LG_BITS; 50 | results.decode_type = LG; 51 | return true; 52 | } 53 | 54 | bool IRrecv::decodeLG(decode_results *aResults) { 55 | bool aReturnValue = decodeLG(); 56 | *aResults = results; 57 | return aReturnValue; 58 | } 59 | #endif 60 | 61 | //+============================================================================= 62 | #if SEND_LG 63 | void IRsend::sendLG(unsigned long data, int nbits) { 64 | // Set IR carrier frequency 65 | enableIROut(38); 66 | 67 | // Header 68 | mark(LG_HEADER_MARK); 69 | space(LG_HEADER_SPACE); 70 | // mark(LG_BIT_MARK); 71 | 72 | // Data 73 | sendPulseDistanceWidthData(LG_BIT_MARK, LG_ONE_SPACE, LG_BIT_MARK, LG_ZERO_SPACE, data, nbits); 74 | 75 | mark(LG_BIT_MARK); 76 | space(0); // Always end with the LED off 77 | } 78 | #endif 79 | 80 | -------------------------------------------------------------------------------- /src/ir_Lego_PF.cpp: -------------------------------------------------------------------------------- 1 | #include "IRremote.h" 2 | #include "ir_Lego_PF_BitStreamEncoder.h" 3 | 4 | //============================================================================== 5 | // L EEEEEE EEEE OOOO 6 | // L E E O O 7 | // L EEEE E EEE O O 8 | // L E E E O O LEGO Power Functions 9 | // LLLLLL EEEEEE EEEE OOOO Copyright (c) 2016 Philipp Henkel 10 | //============================================================================== 11 | 12 | // Supported Devices 13 | // LEGO® Power Functions IR Receiver 8884 14 | /* 15 | * Lego Power Functions receive. 16 | * As per document 17 | * http://cache.lego.com/Media/Download/PowerfunctionsElementSpecsDownloads/otherfiles/download9FC026117C091015E81EC28101DACD4E/8884RemoteControlIRReceiver_Download.pdf 18 | 19 | * Receives the 16 bit protocol. It can be decoded with the Open Powerfunctions code 20 | * https://bitbucket.org/tinkerer_/openpowerfunctionsrx 21 | */ 22 | 23 | //+============================================================================= 24 | // 25 | #if SEND_LEGO_PF 26 | #if DEBUG 27 | namespace { 28 | void logFunctionParameters(uint16_t data, bool repeat) { 29 | DBG_PRINT("sendLegoPowerFunctions(data="); 30 | DBG_PRINT(data); 31 | DBG_PRINT(", repeat="); 32 | DBG_PRINTLN(repeat?"true)" : "false)"); 33 | } 34 | } // anonymous namespace 35 | #endif // DEBUG 36 | 37 | void IRsend::sendLegoPowerFunctions(uint16_t data, bool repeat) { 38 | #if DEBUG 39 | ::logFunctionParameters(data, repeat); 40 | #endif // DEBUG 41 | 42 | enableIROut(38); 43 | static LegoPfBitStreamEncoder bitStreamEncoder; 44 | bitStreamEncoder.reset(data, repeat); 45 | do { 46 | mark(bitStreamEncoder.getMarkDuration()); 47 | space_long(bitStreamEncoder.getPauseDuration()); 48 | } while (bitStreamEncoder.next()); 49 | } 50 | 51 | #endif // SEND_LEGO_PF 52 | 53 | #if DECODE_LEGO_PF 54 | /* 55 | * UNTESTED!!! 56 | */ 57 | #define LEGO_PF_STARTSTOP 1579 58 | #define LEGO_PF_LOWBIT 526 59 | #define LEGO_PF_HIBIT 947 60 | #define LEGO_PF_LOWER 315 61 | #define LEGO_PF_BITS 16 // The number of bits in the command 62 | 63 | bool IRrecv::decodeLegoPowerFunctions() { 64 | unsigned long data = 0; // Somewhere to build our code 65 | DBG_PRINTLN(results.rawlen, DEC); 66 | // Check we have the right amount of data 67 | if (irparams.rawlen != (2 * LEGO_PF_BITS) + 4) 68 | return false; 69 | 70 | DBG_PRINTLN("Attempting Lego Power Functions Decode"); 71 | 72 | uint16_t desired_us = (results.rawbuf[1] + results.rawbuf[2]) * MICROS_PER_TICK; 73 | DBG_PRINT("PF desired_us = "); 74 | DBG_PRINTLN(desired_us, DEC); 75 | 76 | if (desired_us > LEGO_PF_HIBIT && desired_us <= LEGO_PF_STARTSTOP) { 77 | DBG_PRINTLN("Found PF Start Bit"); 78 | int offset = 3; 79 | for (int i = 0; i < LEGO_PF_BITS; i++) { 80 | desired_us = (results.rawbuf[offset] + results.rawbuf[offset + 1]) * MICROS_PER_TICK; 81 | 82 | DBG_PRINT("PF desired_us = "); 83 | DBG_PRINTLN(desired_us, DEC); 84 | if (desired_us >= LEGO_PF_LOWER && desired_us <= LEGO_PF_LOWBIT) { 85 | DBG_PRINTLN("PF 0"); 86 | data = (data << 1) | 0; 87 | } else if (desired_us > LEGO_PF_LOWBIT && desired_us <= LEGO_PF_HIBIT) { 88 | DBG_PRINTLN("PF 1"); 89 | data = (data << 1) | 1; 90 | } else { 91 | DBG_PRINTLN("PF Failed"); 92 | return false; 93 | } 94 | offset += 2; 95 | } 96 | 97 | desired_us = (results.rawbuf[offset]) * MICROS_PER_TICK; 98 | 99 | DBG_PRINT("PF END desired_us = "); 100 | DBG_PRINTLN(desired_us, DEC); 101 | if (desired_us < LEGO_PF_LOWER) { 102 | DBG_PRINTLN("Found PF End Bit"); 103 | DBG_PRINTLN(data, BIN); 104 | 105 | // Success 106 | results.bits = LEGO_PF_BITS; 107 | results.value = data; 108 | results.decode_type = LEGO_PF; 109 | return true; 110 | } 111 | } 112 | return false; 113 | } 114 | #endif 115 | -------------------------------------------------------------------------------- /src/ir_Lego_PF_BitStreamEncoder.h: -------------------------------------------------------------------------------- 1 | //============================================================================== 2 | // L EEEEEE EEEE OOOO 3 | // L E E O O 4 | // L EEEE E EEE O O 5 | // L E E E O O LEGO Power Functions 6 | // LLLLLL EEEEEE EEEE OOOO Copyright (c) 2016, 2017 Philipp Henkel 7 | //============================================================================== 8 | 9 | //+============================================================================= 10 | // 11 | 12 | class LegoPfBitStreamEncoder { 13 | private: 14 | uint16_t data; 15 | bool repeatMessage; 16 | uint8_t messageBitIdx; 17 | uint8_t repeatCount; 18 | uint16_t messageLength; 19 | 20 | public: 21 | // HIGH data bit = IR mark + high pause 22 | // LOW data bit = IR mark + low pause 23 | static const uint16_t LOW_BIT_DURATION = 421; 24 | static const uint16_t HIGH_BIT_DURATION = 711; 25 | static const uint16_t START_BIT_DURATION = 1184; 26 | static const uint16_t STOP_BIT_DURATION = 1184; 27 | static const uint8_t IR_MARK_DURATION = 158; 28 | static const uint16_t HIGH_PAUSE_DURATION = HIGH_BIT_DURATION - IR_MARK_DURATION; 29 | static const uint16_t LOW_PAUSE_DURATION = LOW_BIT_DURATION - IR_MARK_DURATION; 30 | static const uint16_t START_PAUSE_DURATION = START_BIT_DURATION - IR_MARK_DURATION; 31 | static const uint16_t STOP_PAUSE_DURATION = STOP_BIT_DURATION - IR_MARK_DURATION; 32 | static const uint8_t MESSAGE_BITS = 18; 33 | static const uint16_t MAX_MESSAGE_LENGTH = 16000; 34 | 35 | void reset(uint16_t data, bool repeatMessage) { 36 | this->data = data; 37 | this->repeatMessage = repeatMessage; 38 | messageBitIdx = 0; 39 | repeatCount = 0; 40 | messageLength = getMessageLength(); 41 | } 42 | 43 | int getChannelId() const { 44 | return 1 + ((data >> 12) & 0x3); 45 | } 46 | 47 | uint16_t getMessageLength() const { 48 | // Sum up all marks 49 | uint16_t length = MESSAGE_BITS * IR_MARK_DURATION; 50 | 51 | // Sum up all pauses 52 | length += START_PAUSE_DURATION; 53 | for (unsigned long mask = 1UL << 15; mask; mask >>= 1) { 54 | if (data & mask) { 55 | length += HIGH_PAUSE_DURATION; 56 | } else { 57 | length += LOW_PAUSE_DURATION; 58 | } 59 | } 60 | length += STOP_PAUSE_DURATION; 61 | return length; 62 | } 63 | 64 | boolean next() { 65 | messageBitIdx++; 66 | if (messageBitIdx >= MESSAGE_BITS) { 67 | repeatCount++; 68 | messageBitIdx = 0; 69 | } 70 | if (repeatCount >= 1 && !repeatMessage) { 71 | return false; 72 | } else if (repeatCount >= 5) { 73 | return false; 74 | } else { 75 | return true; 76 | } 77 | } 78 | 79 | uint8_t getMarkDuration() const { 80 | return IR_MARK_DURATION; 81 | } 82 | 83 | uint32_t getPauseDuration() const { 84 | if (messageBitIdx == 0) 85 | return START_PAUSE_DURATION; 86 | else if (messageBitIdx < MESSAGE_BITS - 1) { 87 | return getDataBitPause(); 88 | } else { 89 | return getStopPause(); 90 | } 91 | } 92 | 93 | private: 94 | uint16_t getDataBitPause() const { 95 | const int pos = MESSAGE_BITS - 2 - messageBitIdx; 96 | const bool isHigh = data & (1 << pos); 97 | return isHigh ? HIGH_PAUSE_DURATION : LOW_PAUSE_DURATION; 98 | } 99 | 100 | uint32_t getStopPause() const { 101 | if (repeatMessage) { 102 | return getRepeatStopPause(); 103 | } else { 104 | return STOP_PAUSE_DURATION; 105 | } 106 | } 107 | 108 | uint32_t getRepeatStopPause() const { 109 | if (repeatCount == 0 || repeatCount == 1) { 110 | return STOP_PAUSE_DURATION + (uint32_t) 5 * MAX_MESSAGE_LENGTH - messageLength; 111 | } else if (repeatCount == 2 || repeatCount == 3) { 112 | return STOP_PAUSE_DURATION + (uint32_t) (6 + 2 * getChannelId()) * MAX_MESSAGE_LENGTH - messageLength; 113 | } else { 114 | return STOP_PAUSE_DURATION; 115 | } 116 | } 117 | }; 118 | -------------------------------------------------------------------------------- /src/ir_MagiQuest.cpp: -------------------------------------------------------------------------------- 1 | #include "IRremote.h" 2 | 3 | // Based off the Magiquest fork of Arduino-IRremote by mpflaga 4 | // https://github.com/mpflaga/Arduino-IRremote/ 5 | 6 | //============================================================================== 7 | // 8 | // 9 | // M A G I Q U E S T 10 | // 11 | // 12 | //============================================================================== 13 | 14 | // MagiQuest packet is both Wand ID and magnitude of swish and flick 15 | union magiquest_t { 16 | unsigned long long llword; 17 | struct { 18 | unsigned int magnitude; 19 | unsigned long wand_id; 20 | char padding; 21 | char scrap; // just to pad the struct out to 64 bits so we can union with llword 22 | } cmd; 23 | }; 24 | 25 | #define MAGIQUEST_BITS 50 // The number of bits in the command itself 26 | #define MAGIQUEST_PERIOD 1150 // Length of time a full MQ "bit" consumes (1100 - 1200 usec) 27 | /* 28 | * 0 = 25% mark & 75% space across 1 period 29 | * 1150 * 0.25 = 288 usec mark 30 | * 1150 - 288 = 862 usec space 31 | * 1 = 50% mark & 50% space across 1 period 32 | * 1150 * 0.5 = 575 usec mark 33 | * 1150 - 575 = 575 usec space 34 | */ 35 | #define MAGIQUEST_ONE_MARK 575 36 | #define MAGIQUEST_ONE_SPACE 575 37 | #define MAGIQUEST_ZERO_MARK 288 38 | #define MAGIQUEST_ZERO_SPACE 862 39 | 40 | #define MAGIQUEST_MASK (1ULL << (MAGIQUEST_BITS-1)) 41 | 42 | //+============================================================================= 43 | // 44 | #if SEND_MAGIQUEST 45 | void IRsend::sendMagiQuest(unsigned long wand_id, unsigned int magnitude) { 46 | magiquest_t data; 47 | 48 | data.llword = 0; 49 | data.cmd.wand_id = wand_id; 50 | data.cmd.magnitude = magnitude; 51 | 52 | // Set IR carrier frequency 53 | enableIROut(38); 54 | 55 | // Data 56 | for (unsigned long long mask = MAGIQUEST_MASK; mask > 0; mask >>= 1) { 57 | if (data.llword & mask) { 58 | DBG_PRINT("1"); 59 | mark(MAGIQUEST_ONE_MARK); 60 | space(MAGIQUEST_ONE_SPACE); 61 | } else { 62 | DBG_PRINT("0"); 63 | mark(MAGIQUEST_ZERO_MARK); 64 | space(MAGIQUEST_ZERO_SPACE); 65 | } 66 | } 67 | DBG_PRINTLN(""); 68 | 69 | // Footer 70 | mark(MAGIQUEST_ZERO_MARK); 71 | space(0); // Always end with the LED off 72 | } 73 | #endif 74 | 75 | //+============================================================================= 76 | // 77 | #if DECODE_MAGIQUEST 78 | bool IRrecv::decodeMagiQuest() { 79 | magiquest_t data; // Somewhere to build our code 80 | unsigned int offset = 1; // Skip the gap reading 81 | 82 | unsigned int mark_; 83 | unsigned int space_; 84 | unsigned int ratio_; 85 | 86 | #if DEBUG 87 | char bitstring[MAGIQUEST_BITS*2]; 88 | memset(bitstring, 0, sizeof(bitstring)); 89 | #endif 90 | 91 | // Check we have enough data 92 | if (results.rawlen < 2 * MAGIQUEST_BITS) { 93 | DBG_PRINT("Not enough bits to be a MagiQuest packet ("); 94 | DBG_PRINT(irparams.rawlen); 95 | DBG_PRINT(" < "); 96 | DBG_PRINT(MAGIQUEST_BITS*2); 97 | DBG_PRINTLN(")"); 98 | return false; 99 | } 100 | 101 | // Read the bits in 102 | data.llword = 0; 103 | while (offset + 1 < results.rawlen) { 104 | mark_ = results.rawbuf[offset++]; 105 | space_ = results.rawbuf[offset++]; 106 | ratio_ = space_ / mark_; 107 | 108 | DBG_PRINT("mark="); 109 | DBG_PRINT(mark_ * MICROS_PER_TICK); 110 | DBG_PRINT(" space="); 111 | DBG_PRINT(space_ * MICROS_PER_TICK); 112 | DBG_PRINT(" ratio="); 113 | DBG_PRINTLN(ratio_); 114 | 115 | if (MATCH_MARK(space_ + mark_, MAGIQUEST_PERIOD)) { 116 | if (ratio_ > 1) { 117 | // It's a 0 118 | data.llword <<= 1; 119 | #if DEBUG 120 | bitstring[(offset/2)-1] = '0'; 121 | #endif 122 | } else { 123 | // It's a 1 124 | data.llword = (data.llword << 1) | 1; 125 | #if DEBUG 126 | bitstring[(offset/2)-1] = '1'; 127 | #endif 128 | } 129 | } else { 130 | DBG_PRINTLN("MATCH_MARK failed"); 131 | return false; 132 | } 133 | } 134 | #if DEBUG 135 | DBG_PRINTLN(bitstring); 136 | #endif 137 | 138 | // Success 139 | results.decode_type = MAGIQUEST; 140 | results.bits = offset / 2; 141 | results.value = data.cmd.wand_id; 142 | results.magnitude = data.cmd.magnitude; 143 | 144 | DBG_PRINT("MQ: bits="); 145 | DBG_PRINT(results.bits); 146 | DBG_PRINT(" value="); 147 | DBG_PRINT(results.value); 148 | DBG_PRINT(" magnitude="); 149 | DBG_PRINTLN(results.magnitude); 150 | 151 | return true; 152 | } 153 | bool IRrecv::decodeMagiQuest(decode_results *aResults) { 154 | bool aReturnValue = decodeMagiQuest(); 155 | *aResults = results; 156 | return aReturnValue; 157 | } 158 | #endif 159 | -------------------------------------------------------------------------------- /src/ir_NEC.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * ir_NEC.cpp 3 | * 4 | * Contains functions for receiving and sending NEC IR Protocol in "raw" and standard format with 16 bit Address 8bit Data 5 | * 6 | * This file is part of Arduino-IRremote https://github.com/z3t0/Arduino-IRremote. 7 | * 8 | */ 9 | 10 | #include "IRremote.h" 11 | 12 | //============================================================================== 13 | // N N EEEEE CCCC 14 | // NN N E C 15 | // N N N EEE C 16 | // N NN E C 17 | // N N EEEEE CCCC 18 | //============================================================================== 19 | 20 | #define NEC_BITS 32 21 | #define NEC_HEADER_MARK 9000 22 | #define NEC_HEADER_SPACE 4500 23 | #define NEC_BIT_MARK 560 24 | #define NEC_ONE_SPACE 1690 25 | #define NEC_ZERO_SPACE 560 26 | #define NEC_REPEAT_SPACE 2250 27 | 28 | //+============================================================================= 29 | #if SEND_NEC || SEND_NEC_STANDARD 30 | /* 31 | * Send repeat 32 | * Repeat commands should be sent in a 110 ms raster. 33 | */ 34 | void IRsend::sendNECRepeat() { 35 | enableIROut(38); 36 | mark(NEC_HEADER_MARK); 37 | space(NEC_REPEAT_SPACE); 38 | mark(NEC_BIT_MARK); 39 | space(0); // Always end with the LED off 40 | } 41 | #endif 42 | 43 | //+============================================================================= 44 | #if SEND_NEC 45 | /* 46 | * Repeat commands should be sent in a 110 ms raster. 47 | * https://www.sbprojects.net/knowledge/ir/nec.php 48 | */ 49 | void IRsend::sendNEC(uint32_t data, uint8_t nbits, bool repeat) { 50 | // Set IR carrier frequency 51 | enableIROut(38); 52 | 53 | if (data == REPEAT || repeat) { 54 | sendNECRepeat(); 55 | return; 56 | } 57 | 58 | // Header 59 | mark(NEC_HEADER_MARK); 60 | space(NEC_HEADER_SPACE); 61 | // Data 62 | sendPulseDistanceWidthData(NEC_BIT_MARK, NEC_ONE_SPACE, NEC_BIT_MARK, NEC_ZERO_SPACE, data, nbits); 63 | 64 | // Stop bit 65 | mark(NEC_BIT_MARK); 66 | space(0); // Always end with the LED off 67 | } 68 | #endif 69 | 70 | //+============================================================================= 71 | #if SEND_NEC_STANDARD 72 | /* 73 | * Repeat commands should be sent in a 110 ms raster. 74 | * https://www.sbprojects.net/knowledge/ir/nec.php 75 | */ 76 | void IRsend::sendNECStandard(uint16_t aAddress, uint8_t aCommand, uint8_t aNumberOfRepeats) { 77 | // Set IR carrier frequency 78 | enableIROut(38); 79 | 80 | unsigned long tStartMillis = millis(); 81 | // Header 82 | mark(NEC_HEADER_MARK); 83 | space(NEC_HEADER_SPACE); 84 | // Address 16 bit LSB first 85 | sendPulseDistanceWidthData(NEC_BIT_MARK, NEC_ONE_SPACE, NEC_BIT_MARK, NEC_ZERO_SPACE, aAddress, 16, false); 86 | 87 | // send 8 command bits and then 8 inverted command bits LSB first 88 | uint16_t tCommand = ((~aCommand) << 8) | aCommand; 89 | // Command 16 bit LSB first 90 | sendPulseDistanceWidthData(NEC_BIT_MARK, NEC_ONE_SPACE, NEC_BIT_MARK, NEC_ZERO_SPACE, tCommand, 16, false); 91 | mark(NEC_BIT_MARK); // Stop bit 92 | space(0); // Always end with the LED off 93 | 94 | for (uint8_t i = 0; i < aNumberOfRepeats; ++i) { 95 | // send repeat in a 110 ms raster 96 | delay((tStartMillis + 110) - millis()); 97 | tStartMillis = millis(); 98 | // send repeat 99 | sendNECRepeat(); 100 | } 101 | } 102 | #endif 103 | //+============================================================================= 104 | // NECs have a repeat only 4 items long 105 | // 106 | #if DECODE_NEC 107 | bool IRrecv::decodeNEC() { 108 | int offset = 1; // Index in to results; Skip first space. 109 | 110 | // Check header "mark" 111 | if (!MATCH_MARK(results.rawbuf[offset], NEC_HEADER_MARK)) { 112 | return false; 113 | } 114 | offset++; 115 | 116 | // Check for repeat 117 | if ((results.rawlen == 4) && MATCH_SPACE(results.rawbuf[offset], NEC_REPEAT_SPACE) 118 | && MATCH_MARK(results.rawbuf[offset + 1], NEC_BIT_MARK)) { 119 | results.bits = 0; 120 | results.value = REPEAT; 121 | results.isRepeat = true; 122 | results.decode_type = NEC; 123 | return true; 124 | } 125 | 126 | // Check we have enough data - +3 for start bit mark and space + stop bit mark 127 | if (results.rawlen <= (2 * NEC_BITS) + 3) { 128 | return false; 129 | } 130 | 131 | // Check header "space" 132 | if (!MATCH_SPACE(results.rawbuf[offset], NEC_HEADER_SPACE)) { 133 | return false; 134 | } 135 | offset++; 136 | 137 | if (!decodePulseDistanceData(NEC_BITS, offset, NEC_BIT_MARK, NEC_ONE_SPACE, NEC_ZERO_SPACE)) { 138 | return false; 139 | } 140 | 141 | // Stop bit 142 | if (!MATCH_MARK(results.rawbuf[offset + (2 * NEC_BITS)], NEC_BIT_MARK)) { 143 | DBG_PRINT("Stop bit verify failed"); 144 | return false; 145 | } 146 | 147 | // Success 148 | results.bits = NEC_BITS; 149 | results.decode_type = NEC; 150 | 151 | return true; 152 | } 153 | 154 | bool IRrecv::decodeNEC(decode_results *aResults) { 155 | bool aReturnValue = decodeNEC(); 156 | *aResults = results; 157 | return aReturnValue; 158 | } 159 | #endif 160 | 161 | //+============================================================================= 162 | // NECs have a repeat only 4 items long 163 | // 164 | #if DECODE_NEC_STANDARD 165 | bool IRrecv::decodeNECStandard() { 166 | long data = 0; // We decode in to here; Start with nothing 167 | int offset = 1; // Index in to results; Skip first space. 168 | 169 | // Check header "mark" 170 | if (!MATCH_MARK(results.rawbuf[offset], NEC_HEADER_MARK)) { 171 | return false; 172 | } 173 | offset++; 174 | 175 | // Check for repeat 176 | if ((results.rawlen == 4) && MATCH_SPACE(results.rawbuf[offset], NEC_REPEAT_SPACE) 177 | && MATCH_MARK(results.rawbuf[offset + 1], NEC_BIT_MARK)) { 178 | results.isRepeat = true; 179 | results.bits = 0; 180 | return true; 181 | } 182 | 183 | // Check we have enough data - +3 for start bit mark and space + stop bit mark 184 | if (results.rawlen <= (2 * NEC_BITS) + 3) { 185 | return false; 186 | } 187 | // Check header "space" 188 | if (!MATCH_SPACE(results.rawbuf[offset], NEC_HEADER_SPACE)) { 189 | return false; 190 | } 191 | offset++; 192 | 193 | data = decodePulseDistanceData(NEC_BITS, offset, NEC_BIT_MARK, NEC_ONE_SPACE, NEC_ZERO_SPACE, false); 194 | 195 | // Stop bit 196 | if (!MATCH_MARK(results.rawbuf[offset + (2 * NEC_BITS)], NEC_BIT_MARK)) { 197 | DBG_PRINT("Stop bit verify failed"); 198 | return false; 199 | } 200 | 201 | // Success 202 | uint16_t tCommand = data >> 16; 203 | uint8_t tCommandNotInverted = tCommand & 0xFF; 204 | uint8_t tCommandInverted = tCommand >> 8; 205 | // plausi check for command 206 | if ((tCommandNotInverted ^ tCommandInverted) != 0xFF) { 207 | return false; 208 | } 209 | 210 | results.isRepeat = false; 211 | results.value = tCommandNotInverted; 212 | results.bits = NEC_BITS; 213 | results.address = data & 0xFFFF; // first 16 bit 214 | results.decode_type = NEC_STANDARD; 215 | 216 | return true; 217 | } 218 | #endif 219 | 220 | -------------------------------------------------------------------------------- /src/ir_Panasonic.cpp: -------------------------------------------------------------------------------- 1 | #include "IRremote.h" 2 | 3 | //============================================================================== 4 | // PPPP AAA N N AAA SSSS OOO N N IIIII CCCC 5 | // P P A A NN N A A S O O NN N I C 6 | // PPPP AAAAA N N N AAAAA SSS O O N N N I C 7 | // P A A N NN A A S O O N NN I C 8 | // P A A N N A A SSSS OOO N N IIIII CCCC 9 | //============================================================================== 10 | 11 | #define PANASONIC_ADDRESS_BITS 16 12 | #define PANASONIC_DATA_BITS 32 13 | #define PANASONIC_BITS (PANASONIC_ADDRESS_BITS + PANASONIC_DATA_BITS) 14 | #define PANASONIC_HEADER_MARK 3502 15 | #define PANASONIC_HEADER_SPACE 1750 16 | #define PANASONIC_BIT_MARK 502 17 | #define PANASONIC_ONE_SPACE 1244 18 | #define PANASONIC_ZERO_SPACE 400 19 | 20 | //+============================================================================= 21 | #if SEND_PANASONIC 22 | void IRsend::sendPanasonic(unsigned int address, unsigned long data) { 23 | // Set IR carrier frequency 24 | enableIROut(37); // 36.7kHz is the correct frequency 25 | 26 | // Header 27 | mark(PANASONIC_HEADER_MARK); 28 | space(PANASONIC_HEADER_SPACE); 29 | 30 | // Address 31 | sendPulseDistanceWidthData(PANASONIC_BIT_MARK, PANASONIC_ONE_SPACE, PANASONIC_BIT_MARK, PANASONIC_ZERO_SPACE, address, 32 | PANASONIC_ADDRESS_BITS); 33 | 34 | // Data 35 | sendPulseDistanceWidthData(PANASONIC_BIT_MARK, PANASONIC_ONE_SPACE, PANASONIC_BIT_MARK, 36 | PANASONIC_ZERO_SPACE, data, PANASONIC_DATA_BITS); 37 | 38 | // Footer 39 | mark(PANASONIC_BIT_MARK); 40 | space(0); // Always end with the LED off 41 | } 42 | #endif 43 | 44 | //+============================================================================= 45 | #if DECODE_PANASONIC 46 | bool IRrecv::decodePanasonic() { 47 | int offset = 1; 48 | 49 | if (results.rawlen < (2 * PANASONIC_BITS) + 2) { 50 | return false; 51 | } 52 | 53 | if (!MATCH_MARK(results.rawbuf[offset], PANASONIC_HEADER_MARK)) { 54 | return false; 55 | } 56 | offset++; 57 | if (!MATCH_MARK(results.rawbuf[offset], PANASONIC_HEADER_SPACE)) { 58 | return false; 59 | } 60 | offset++; 61 | 62 | // decode address 63 | if (!decodePulseDistanceData(PANASONIC_ADDRESS_BITS, offset, PANASONIC_BIT_MARK, PANASONIC_ONE_SPACE, 64 | PANASONIC_ZERO_SPACE)) { 65 | return false; 66 | } 67 | results.address = results.value; 68 | 69 | if (!decodePulseDistanceData(PANASONIC_DATA_BITS, offset + PANASONIC_ADDRESS_BITS, PANASONIC_BIT_MARK, 70 | PANASONIC_ONE_SPACE, PANASONIC_ZERO_SPACE)) { 71 | return false; 72 | } 73 | 74 | results.decode_type = PANASONIC; 75 | results.bits = PANASONIC_BITS; 76 | 77 | return true; 78 | } 79 | 80 | bool IRrecv::decodePanasonic(decode_results *aResults) { 81 | bool aReturnValue = decodePanasonic(); 82 | *aResults = results; 83 | return aReturnValue; 84 | } 85 | #endif 86 | 87 | -------------------------------------------------------------------------------- /src/ir_Samsung.cpp: -------------------------------------------------------------------------------- 1 | #include "IRremote.h" 2 | 3 | //============================================================================== 4 | // SSSS AAA MMM SSSS U U N N GGGG 5 | // S A A M M M S U U NN N G 6 | // SSS AAAAA M M M SSS U U N N N G GG 7 | // S A A M M S U U N NN G G 8 | // SSSS A A M M SSSS UUU N N GGG 9 | //============================================================================== 10 | 11 | #define SAMSUNG_BITS 32 12 | #define SAMSUNG_HEADER_MARK 4500 13 | #define SAMSUNG_HEADER_SPACE 4500 14 | #define SAMSUNG_BIT_MARK 560 15 | #define SAMSUNG_ONE_SPACE 1600 16 | #define SAMSUNG_ZERO_SPACE 560 17 | #define SAMSUNG_REPEAT_SPACE 2250 18 | 19 | //+============================================================================= 20 | #if SEND_SAMSUNG 21 | void IRsend::sendSAMSUNG(unsigned long data, int nbits) { 22 | // Set IR carrier frequency 23 | enableIROut(38); 24 | 25 | // Header 26 | mark(SAMSUNG_HEADER_MARK); 27 | space(SAMSUNG_HEADER_SPACE); 28 | 29 | // Data 30 | sendPulseDistanceWidthData(SAMSUNG_BIT_MARK, SAMSUNG_ONE_SPACE, SAMSUNG_BIT_MARK, SAMSUNG_ZERO_SPACE, data, nbits); 31 | 32 | // Footer 33 | mark(SAMSUNG_BIT_MARK); 34 | space(0); // Always end with the LED off 35 | } 36 | #endif 37 | 38 | //+============================================================================= 39 | // SAMSUNGs have a repeat only 4 items long 40 | // 41 | #if DECODE_SAMSUNG 42 | bool IRrecv::decodeSAMSUNG() { 43 | int offset = 1; // Skip first space 44 | 45 | // Initial mark 46 | if (!MATCH_MARK(results.rawbuf[offset], SAMSUNG_HEADER_MARK)) { 47 | return false; 48 | } 49 | offset++; 50 | 51 | // Check for repeat 52 | if ((irparams.rawlen == 4) && MATCH_SPACE(results.rawbuf[offset], SAMSUNG_REPEAT_SPACE) 53 | && MATCH_MARK(results.rawbuf[offset + 1], SAMSUNG_BIT_MARK)) { 54 | results.bits = 0; 55 | results.value = REPEAT; 56 | results.isRepeat = true; 57 | results.decode_type = SAMSUNG; 58 | return true; 59 | } 60 | if (irparams.rawlen < (2 * SAMSUNG_BITS) + 4) { 61 | return false; 62 | } 63 | 64 | // Initial space 65 | if (!MATCH_SPACE(results.rawbuf[offset], SAMSUNG_HEADER_SPACE)) { 66 | return false; 67 | } 68 | offset++; 69 | 70 | if (!decodePulseDistanceData(SAMSUNG_BITS, offset, SAMSUNG_BIT_MARK, SAMSUNG_ONE_SPACE, SAMSUNG_ZERO_SPACE)) { 71 | return false; 72 | } 73 | 74 | // Success 75 | results.bits = SAMSUNG_BITS; 76 | results.decode_type = SAMSUNG; 77 | return true; 78 | } 79 | 80 | bool IRrecv::decodeSAMSUNG(decode_results *aResults) { 81 | bool aReturnValue = decodeSAMSUNG(); 82 | *aResults = results; 83 | return aReturnValue; 84 | } 85 | #endif 86 | 87 | -------------------------------------------------------------------------------- /src/ir_Sanyo.cpp: -------------------------------------------------------------------------------- 1 | #include "IRremote.h" 2 | 3 | //============================================================================== 4 | // SSSS AAA N N Y Y OOO 5 | // S A A NN N Y Y O O 6 | // SSS AAAAA N N N Y O O 7 | // S A A N NN Y O O 8 | // SSSS A A N N Y OOO 9 | //============================================================================== 10 | 11 | // I think this is a Sanyo decoder: Serial = SA 8650B 12 | // Looks like Sony except for timings, 48 chars of data and time/space different 13 | 14 | #define SANYO_BITS 12 15 | #define SANYO_HEADER_MARK 3500 // seen range 3500 16 | #define SANYO_HEADER_SPACE 950 // seen 950 17 | #define SANYO_ONE_MARK 2400 // seen 2400 18 | #define SANYO_ZERO_MARK 700 // seen 700 19 | #define SANYO_RPT_LENGTH 45000 // Not used. Commands are repeated every 45ms(measured from start to start) for as long as the key on the remote control is held down. 20 | #define SANYO_DOUBLE_SPACE_USECS 800 // usually see 713 - not using ticks as get number wrap around 21 | 22 | //+============================================================================= 23 | #if DECODE_SANYO 24 | bool IRrecv::decodeSanyo() { 25 | long data = 0; 26 | unsigned int offset = 0; // Don't skip first space, check its size 27 | 28 | if (results.rawlen < (2 * SANYO_BITS) + 2) { 29 | return false; 30 | } 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] * MICROS_PER_TICK); 36 | Serial.println( "test against:"); 37 | Serial.println(SANYO_DOUBLE_SPACE_USECS); 38 | #endif 39 | 40 | // Initial space 41 | if (results.rawbuf[offset] < (SANYO_DOUBLE_SPACE_USECS / MICROS_PER_TICK)) { 42 | //Serial.print("IR Gap found: "); 43 | results.bits = 0; 44 | results.value = REPEAT; 45 | results.isRepeat = true; 46 | results.decode_type = SANYO; 47 | return true; 48 | } 49 | offset++; 50 | 51 | // Initial mark 52 | if (!MATCH_MARK(results.rawbuf[offset], SANYO_HEADER_MARK)) { 53 | return false; 54 | } 55 | offset++; 56 | 57 | // Skip Second Mark 58 | if (!MATCH_MARK(results.rawbuf[offset], SANYO_HEADER_MARK)) { 59 | return false; 60 | } 61 | offset++; 62 | 63 | while (offset + 1 < irparams.rawlen) { 64 | if (!MATCH_SPACE(results.rawbuf[offset], SANYO_HEADER_SPACE)) { 65 | break; 66 | } 67 | offset++; 68 | 69 | if (MATCH_MARK(results.rawbuf[offset], SANYO_ONE_MARK)) { 70 | data = (data << 1) | 1; 71 | } else if (MATCH_MARK(results.rawbuf[offset], SANYO_ZERO_MARK)) { 72 | data = (data << 1) | 0; 73 | } else { 74 | return false; 75 | } 76 | offset++; 77 | } 78 | 79 | // Success 80 | results.bits = (offset - 1) / 2; 81 | if (results.bits < 12) { 82 | results.bits = 0; 83 | return false; 84 | } 85 | 86 | results.value = data; 87 | results.decode_type = SANYO; 88 | return true; 89 | } 90 | bool IRrecv::decodeSanyo(decode_results *aResults) { 91 | bool aReturnValue = decodeSanyo(); 92 | *aResults = results; 93 | return aReturnValue; 94 | } 95 | #endif 96 | -------------------------------------------------------------------------------- /src/ir_Sharp.cpp: -------------------------------------------------------------------------------- 1 | #include "IRremote.h" 2 | 3 | //============================================================================== 4 | // SSSS H H AAA RRRR PPPP 5 | // S H H A A R R P P 6 | // SSS HHHHH AAAAA RRRR PPPP 7 | // S H H A A R R P 8 | // SSSS H H A A R R P 9 | //============================================================================== 10 | 11 | // Sharp and DISH support by Todd Treece: http://unionbridge.org/design/ircommand 12 | // 13 | // The send function has the necessary repeat built in because of the need to 14 | // invert the signal. 15 | // 16 | // Sharp protocol documentation: 17 | // http://www.sbprojects.com/knowledge/ir/sharp.htm 18 | // 19 | // Here is the LIRC file I found that seems to match the remote codes from the 20 | // oscilloscope: 21 | // Sharp LCD TV: 22 | // http://lirc.sourceforge.net/remotes/sharp/GA538WJSA 23 | 24 | #define SHARP_BITS 15 25 | #define SHARP_ONE_SPACE 1805 26 | //#define SHARP_ONE_SPACE 1850 27 | 28 | #define SHARP_ADDR_BITS 5 29 | #define SHARP_DATA_BITS 8 30 | #define SHARP_BIT_MARK_SEND 250 31 | #define SHARP_BIT_MARK_RECV 150 32 | 33 | #define SHARP_ZERO_SPACE 795 34 | #define SHARP_GAP 600000 // Not used. 35 | #define SHARP_REPEAT_SPACE 3000 36 | 37 | #define SHARP_TOGGLE_MASK 0x3FF 38 | 39 | //+============================================================================= 40 | #if SEND_SHARP 41 | void IRsend::sendSharpRaw(unsigned long data, int nbits) { 42 | enableIROut(38); 43 | 44 | // Sending codes in bursts of 3 (normal, inverted, normal) makes transmission 45 | // much more reliable. That's the exact behavior of CD-S6470 remote control. 46 | for (int n = 0; n < 3; n++) { 47 | sendPulseDistanceWidthData(SHARP_BIT_MARK_SEND, SHARP_ONE_SPACE, SHARP_BIT_MARK_SEND, SHARP_ZERO_SPACE, data, nbits); 48 | // for (unsigned long mask = 1UL << (nbits - 1); mask; mask >>= 1) { 49 | // if (data & mask) { 50 | // mark (SHARP_BIT_MARK_SEND); 51 | // space(SHARP_ONE_SPACE); 52 | // } else { 53 | // mark (SHARP_BIT_MARK_SEND); 54 | // space(SHARP_ZERO_SPACE); 55 | // } 56 | // } 57 | 58 | mark(SHARP_BIT_MARK_SEND); 59 | space(SHARP_ZERO_SPACE); 60 | delay(40); 61 | 62 | data = data ^ SHARP_TOGGLE_MASK; 63 | } 64 | 65 | space(0); // Always end with the LED off 66 | } 67 | #endif 68 | 69 | //+============================================================================= 70 | // Sharp send compatible with data obtained through decodeSharp() 71 | // ^^^^^^^^^^^^^ FUNCTION MISSING! 72 | // 73 | #if SEND_SHARP 74 | void IRsend::sendSharp(unsigned int address, unsigned int command) { 75 | sendSharpRaw((address << 10) | (command << 2) | 2, SHARP_BITS); 76 | /* 77 | * Use this code instead of the line above to be code compatible to the decoded values from decodeSharp 78 | */ 79 | // //Change address to big-endian (five bits swap place) 80 | // address = (address & 0x10) >> 4 | (address & 0x01) << 4 | (address & 0x08) >> 2 | (address & 0x02) << 2 | (address & 0x04) ; 81 | // //Change command to big-endian (eight bit swap place) 82 | // command = (command & 0xF0) >> 4 | (command & 0x0F) << 4; 83 | // command = (command & 0xCC) >> 2 | (command & 0x33) << 2; 84 | // command = (command & 0xAA) >> 1 | (command & 0x55) << 1; 85 | // sendSharpRaw((address << 10) | (command << 2) | 0, SHARP_BITS); 86 | } 87 | 88 | #endif // SEND_SHARP 89 | 90 | //+============================================================================= 91 | // Sharp decode function written based on Sharp protocol documentation: 92 | // http://www.sbprojects.com/knowledge/ir/sharp.htm 93 | // Tesded on a DENON AVR-1804 reciever 94 | 95 | #if DECODE_SHARP 96 | bool IRrecv::decodeSharp() { 97 | unsigned long lastData = 0; // to store last data 98 | int offset = 1; //skip long space 99 | int loops = 1; //number of bursts 100 | 101 | // Check we have the right amount of data 102 | // Either one burst or three where second is inverted 103 | // The setting #define _GAP 5000 in IRremoteInt.h will give one burst and possibly three calls to this function 104 | if (irparams.rawlen == (SHARP_BITS + 1) * 2) 105 | loops = 1; 106 | else if (irparams.rawlen == (SHARP_BITS + 1) * 2 * 3) 107 | loops = 3; 108 | else 109 | return false; 110 | 111 | // Check the first mark to see if it fits the SHARP_BIT_MARK_RECV length 112 | if (!MATCH_MARK(results.rawbuf[offset], SHARP_BIT_MARK_RECV)) 113 | return false; 114 | //check the first pause and see if it fits the SHARP_ONE_SPACE or SHARP_ZERO_SPACE length 115 | if (!(MATCH_SPACE(results.rawbuf[offset + 1], SHARP_ONE_SPACE) || MATCH_SPACE(results.rawbuf[offset + 1], SHARP_ZERO_SPACE))) 116 | return false; 117 | 118 | // Read the bits in 119 | for (int j = 0; j < loops; j++) { 120 | if (!decodePulseDistanceData(SHARP_ADDR_BITS, offset, SHARP_BIT_MARK_SEND, SHARP_ONE_SPACE, SHARP_ZERO_SPACE)) { 121 | return false; 122 | } 123 | results.address = results.value; 124 | 125 | if (!decodePulseDistanceData( SHARP_DATA_BITS, offset + SHARP_ADDR_BITS, SHARP_BIT_MARK_SEND, SHARP_ONE_SPACE, 126 | SHARP_ZERO_SPACE)) { 127 | return false; 128 | } 129 | 130 | //skip exp bit (mark+pause), chk bit (mark+pause), mark and long pause before next burst 131 | offset += 6; 132 | 133 | //Check if last burst data is equal to this burst (lastData already inverted) 134 | if (lastData != 0 && results.value != lastData) 135 | return false; 136 | //save current burst of data but invert (XOR) the last 10 bits (8 data bits + exp bit + chk bit) 137 | lastData = results.value ^ 0xFF; 138 | } 139 | 140 | // Success 141 | results.bits = SHARP_BITS; 142 | results.decode_type = SHARP; 143 | return true; 144 | } 145 | 146 | bool IRrecv::decodeSharp(decode_results *aResults) { 147 | bool aReturnValue = decodeSharp(); 148 | *aResults = results; 149 | return aReturnValue; 150 | } 151 | #endif 152 | -------------------------------------------------------------------------------- /src/ir_Sharp_alt.cpp: -------------------------------------------------------------------------------- 1 | //-*- mode: C; c-basic-offset: 8; tab-width: 8; indent-tabs-mode: t; -*- 2 | #include "IRremote.h" 3 | 4 | //============================================================================== 5 | // SSSS H H AAA RRRR PPPP AAA L TTTTT 6 | // S H H A A R R P P A A L T 7 | // SSS HHHHH AAAAA RRRR PPPP AAAAA L T 8 | // S H H A A R R P A A L T 9 | // SSSS H H A A R R P A A LLLLL T 10 | //============================================================================== 11 | 12 | // This is an alternative protocol to that in ir_Sharp.cpp. It was tested with 13 | // the original Sharp GA538WJSA remote control. LIRC file with codes for this 14 | // remote control: http://lirc.sourceforge.net/remotes/sharp/GA538WJSA 15 | // 16 | // Author: Sergiy Kolesnikov 17 | // 18 | 19 | #define SHARP_ALT_RAWLEN 32 20 | #define SHARP_ALT_ADDRESS_BITS 5 21 | #define SHARP_ALT_COMMAND_BITS 8 22 | #define SHARP_ALT_BIT_MARK 150 23 | #define SHARP_ALT_SEND_BIT_MARK 300 24 | #define SHARP_ALT_ONE_SPACE 1750 25 | #define SHARP_ALT_ZERO_SPACE 700 26 | #define SHARP_ALT_REPEAT_SPACE 50000 27 | #define SHARP_ALT_SEND_REPEAT_SPACE 44000 28 | #define SHARP_ALT_TOGGLE_MASK 0x3FF 29 | #define SHARP_ALT_SEND_INVERT_MASK 0x7FE0 30 | 31 | //+============================================================================= 32 | #if SEND_SHARP_ALT 33 | void IRsend::sendSharpAltRaw(unsigned int data, int nbits) { 34 | enableIROut(38); 35 | 36 | for (int n = 0; n < 3; n++) { 37 | // From LSB to MSB 38 | sendPulseDistanceWidthData(SHARP_ALT_SEND_BIT_MARK, SHARP_ALT_ONE_SPACE, SHARP_ALT_SEND_BIT_MARK, SHARP_ALT_ZERO_SPACE, 39 | data, nbits, false); 40 | // unsigned long mask = 1UL; 41 | // for (int i = 0; i < nbits; i++) { 42 | // if (data & mask) { 43 | // mark(SHARP_ALT_SEND_BIT_MARK); 44 | // space(SHARP_ALT_ONE_SPACE); 45 | // } else { 46 | // mark(SHARP_ALT_SEND_BIT_MARK); 47 | // space(SHARP_ALT_ZERO_SPACE); 48 | // } 49 | // mask <<= 1; 50 | // } 51 | mark(SHARP_ALT_BIT_MARK); 52 | space(SHARP_ALT_SEND_REPEAT_SPACE); 53 | data = data ^ SHARP_ALT_SEND_INVERT_MASK; 54 | } 55 | } 56 | 57 | void IRsend::sendSharpAlt(uint8_t address, uint8_t command) { 58 | // 1 = The expansion and the check bits (01). 59 | unsigned int data = (1 << SHARP_ALT_COMMAND_BITS) | command; 60 | data = (data << SHARP_ALT_ADDRESS_BITS) | address; 61 | 62 | // (+2) is for the expansion and the check bits 0b01. 63 | sendSharpAltRaw(data, SHARP_ALT_ADDRESS_BITS + SHARP_ALT_COMMAND_BITS + 2); 64 | } 65 | #endif 66 | 67 | //+============================================================================= 68 | #if DECODE_SHARP_ALT 69 | bool IRrecv::decodeSharpAlt() { 70 | static boolean is_first_repeat = true; 71 | 72 | // Check we have enough data. 73 | if (results.rawlen < (SHARP_ALT_RAWLEN)) 74 | return false; 75 | 76 | // Check stop mark. 77 | if (!MATCH_MARK(results.rawbuf[SHARP_ALT_RAWLEN - 1], SHARP_ALT_BIT_MARK)) 78 | return false; 79 | 80 | // Check the "check bit." If this bit is not 0 than it is an inverted 81 | // frame, which we ignore. 82 | if (!MATCH_SPACE(results.rawbuf[SHARP_ALT_RAWLEN - 2], SHARP_ALT_ZERO_SPACE)) 83 | return false; 84 | 85 | // Check for repeat. 86 | long initial_space = ((long) results.rawbuf[0]) * MICROS_PER_TICK; 87 | if (initial_space <= SHARP_ALT_REPEAT_SPACE) { 88 | if (!is_first_repeat) { 89 | results.bits = 0; 90 | results.value = REPEAT; 91 | results.isRepeat = true; 92 | results.decode_type = SHARP; 93 | return true; 94 | } else { 95 | // Ignore the first repeat that always comes after the 96 | // inverted frame (even if the button was pressed only once). 97 | is_first_repeat = false; 98 | return false; 99 | } 100 | } 101 | 102 | // Decode bits. SHARP_ALT_RAWLEN-6 because index starts with 0 (-1) and we 103 | // omit the timings for the stop mark (-1), the check bit (-2), and the 104 | // expansion bit (-2). 105 | uint16_t bits = 0; 106 | for (uint8_t i = SHARP_ALT_RAWLEN - 6; i > 1; i -= 2) { 107 | if (MATCH_SPACE(results.rawbuf[i], SHARP_ALT_ONE_SPACE)) { 108 | bits = (bits << 1) | 1; 109 | } else if (MATCH_SPACE(results.rawbuf[i], SHARP_ALT_ZERO_SPACE)) { 110 | bits = (bits << 1) | 0; 111 | } else { 112 | return false; 113 | } 114 | } 115 | 116 | results.bits = SHARP_ALT_ADDRESS_BITS + SHARP_ALT_COMMAND_BITS; 117 | results.address = (bits & (1 << (SHARP_ALT_ADDRESS_BITS))) - 1; 118 | results.value = bits >> SHARP_ALT_ADDRESS_BITS; // command 119 | results.decode_type = SHARP_ALT; 120 | is_first_repeat = true; 121 | return true; 122 | } 123 | bool IRrecv::decodeSharpAlt(decode_results *aResults) { 124 | bool aReturnValue = decodeSharpAlt(); 125 | *aResults = results; 126 | return aReturnValue; 127 | } 128 | #endif 129 | -------------------------------------------------------------------------------- /src/ir_Sony.cpp: -------------------------------------------------------------------------------- 1 | #include "IRremote.h" 2 | 3 | //============================================================================== 4 | // SSSS OOO N N Y Y 5 | // S O O NN N Y Y 6 | // SSS O O N N N Y 7 | // S O O N NN Y 8 | // SSSS OOO N N Y 9 | //============================================================================== 10 | 11 | // see https://www.sbprojects.net/knowledge/ir/sirc.php 12 | // pulse width protocol 13 | 14 | #define SONY_BITS 12 15 | #define SONY_HEADER_MARK 2400 16 | #define SONY_SPACE 600 17 | #define SONY_ONE_MARK 1200 18 | #define SONY_ZERO_MARK 600 19 | #define SONY_RPT_LENGTH 45000 // Not used. Commands are repeated every 45ms(measured from start to start) for as long as the key on the remote control is held down. 20 | #define SONY_DOUBLE_SPACE_USECS 500 // usually see 713 - not using ticks as get number wrap around 21 | 22 | //+============================================================================= 23 | #if SEND_SONY 24 | void IRsend::sendSony(unsigned long data, int nbits) { 25 | // Set IR carrier frequency 26 | enableIROut(40); 27 | 28 | // Header 29 | mark(SONY_HEADER_MARK); 30 | space(SONY_SPACE); 31 | 32 | sendPulseDistanceWidthData(SONY_ONE_MARK, SONY_SPACE, SONY_ZERO_MARK, SONY_SPACE, data, nbits); 33 | /* 34 | * Pulse width coding, the short version. 35 | * Use this if need to save program space and you only require this protocol. 36 | */ 37 | // for (unsigned long mask = 1UL << (nbits - 1); mask; mask >>= 1) { 38 | // if (data & mask) { 39 | // mark(SONY_ONE_MARK); 40 | // space(SONY_SPACE); 41 | // } else { 42 | // mark(SONY_ZERO_MARK); 43 | // space(SONY_SPACE); 44 | // } 45 | // } 46 | space(0); // Always end with the LED off 47 | } 48 | #endif 49 | 50 | //+============================================================================= 51 | #if DECODE_SONY 52 | bool IRrecv::decodeSony() { 53 | long data = 0; 54 | unsigned int offset = 0; // Dont skip first space, check its size 55 | 56 | if (results.rawlen < (2 * SONY_BITS) + 2) { 57 | return false; 58 | } 59 | 60 | // Some Sony's deliver repeats fast after first 61 | // unfortunately can't spot difference from of repeat from two fast clicks 62 | if (results.rawbuf[0] < (SONY_DOUBLE_SPACE_USECS / MICROS_PER_TICK)) { 63 | DBG_PRINTLN("IR Gap found"); 64 | results.bits = 0; 65 | results.value = REPEAT; 66 | results.isRepeat = true; 67 | results.decode_type = UNKNOWN; 68 | return true; 69 | } 70 | offset++; 71 | 72 | // Check header "mark" 73 | if (!MATCH_MARK(results.rawbuf[offset], SONY_HEADER_MARK)) { 74 | return false; 75 | } 76 | offset++; 77 | 78 | // MSB first - Not compatible to standard, which says LSB first :-( 79 | while (offset + 1 < results.rawlen) { 80 | 81 | // First check for the constant space length, we do not have a space at the end of raw data 82 | // we are lucky, since the start space is equal the data space. 83 | if (!MATCH_SPACE(results.rawbuf[offset], SONY_SPACE)) { 84 | return false; 85 | } 86 | offset++; 87 | 88 | // bit value is determined by length of the mark 89 | if (MATCH_MARK(results.rawbuf[offset], SONY_ONE_MARK)) { 90 | data = (data << 1) | 1; 91 | } else if (MATCH_MARK(results.rawbuf[offset], SONY_ZERO_MARK)) { 92 | data = (data << 1) | 0; 93 | } else { 94 | return false; 95 | } 96 | offset++; 97 | 98 | } 99 | 100 | results.bits = SONY_BITS; 101 | results.value = data; 102 | results.decode_type = SONY; 103 | return true; 104 | } 105 | 106 | bool IRrecv::decodeSony(decode_results *aResults) { 107 | bool aReturnValue = decodeSony(); 108 | *aResults = results; 109 | return aReturnValue; 110 | } 111 | #endif 112 | 113 | -------------------------------------------------------------------------------- /src/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 *aResults) ; 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 | 96 | //============================================================================== 97 | // 98 | // 99 | // S H U Z U 100 | // 101 | // 102 | //============================================================================== 103 | 104 | #define SHUZU_BITS 32 // The number of bits in the command 105 | 106 | #define SHUZU_HEADER_MARK 1000 // The length of the Header:Mark 107 | #define SHUZU_HEADER_SPACE 2000 // The lenght of the Header:Space 108 | 109 | #define SHUZU_BIT_MARK 3000 // The length of a Bit:Mark 110 | #define SHUZU_ONE_SPACE 4000 // The length of a Bit:Space for 1's 111 | #define SHUZU_ZERO_SPACE 5000 // The length of a Bit:Space for 0's 112 | 113 | #define SHUZU_OTHER 1234 // Other things you may need to define 114 | 115 | //+============================================================================= 116 | // 117 | #if SEND_SHUZU 118 | void IRsend::sendShuzu(unsigned long data, int nbits) { 119 | // Set IR carrier frequency 120 | enableIROut(38); 121 | 122 | // Header 123 | mark(SHUZU_HEADER_MARK); 124 | space(SHUZU_HEADER_SPACE); 125 | 126 | // Data 127 | sendPulseDistanceData(data, nbits, SHUZU_BIT_MARK, SHUZU_ONE_SPACE,SHUZU_BIT_MARK, SHUZU_ZERO_SPACE); 128 | // for (unsigned long mask = 1UL << (nbits - 1); mask; mask >>= 1) { 129 | // if (data & mask) { 130 | // mark(SHUZU_BIT_MARK); 131 | // space(SHUZU_ONE_SPACE); 132 | // } else { 133 | // mark(SHUZU_BIT_MARK); 134 | // space(SHUZU_ZERO_SPACE); 135 | // } 136 | // } 137 | 138 | // Footer 139 | mark(SHUZU_BIT_MARK); 140 | space(0); // Always end with the LED off 141 | } 142 | #endif 143 | 144 | //+============================================================================= 145 | // 146 | #if DECODE_SHUZU 147 | bool IRrecv::decodeShuzu() { 148 | unsigned long data = 0; // Somewhere to build our code 149 | int offset = 1; // Skip the gap reading 150 | 151 | // Check we have the right amount of data 152 | if (results.rawlen != 1 + 2 + (2 * SHUZU_BITS) + 1) { 153 | return false; 154 | } 155 | 156 | // Check initial Mark+Space match 157 | if (!MATCH_MARK(results.rawbuf[offset], SHUZU_HEADER_MARK)) { 158 | return false; 159 | } 160 | offset++; 161 | 162 | if (!MATCH_SPACE(results.rawbuf[offset], SHUZU_HEADER_SPACE)) { 163 | return false; 164 | } 165 | offset++; 166 | 167 | data = decodePulseDistanceData(results, SHUZU_BITS, offset, SHUZU_BIT_MARK, SHUZU_ONE_SPACE, SHUZU_ZERO_SPACE); 168 | // // Read the bits in 169 | // for (int i = 0; i < SHUZU_BITS; i++) { 170 | // // Each bit looks like: MARK + SPACE_1 -> 1 171 | // // or : MARK + SPACE_0 -> 0 172 | // if (!MATCH_MARK(results.rawbuf[offset], SHUZU_BIT_MARK)) { 173 | // return false; 174 | // } 175 | // offset++; 176 | // 177 | // // IR data is big-endian, so we shuffle it in from the right: 178 | // if (MATCH_SPACE(results.rawbuf[offset], SHUZU_ONE_SPACE)) { 179 | // data = (data << 1) | 1; 180 | // } else if (MATCH_SPACE(results.rawbuf[offset], SHUZU_ZERO_SPACE)) { 181 | // data = (data << 1) | 0; 182 | // } else { 183 | // return false; 184 | // } 185 | // offset++; 186 | // } 187 | 188 | // Success 189 | results.bits = SHUZU_BITS; 190 | results.value = data; 191 | results.decode_type = SHUZU; 192 | return true; 193 | } 194 | bool IRrecv::decodeShuzu(decode_results *aResults) { 195 | bool aReturnValue = decodeShuzu(); 196 | } 197 | #endif 198 | -------------------------------------------------------------------------------- /src/ir_Whynter.cpp: -------------------------------------------------------------------------------- 1 | #include "IRremote.h" 2 | 3 | //============================================================================== 4 | // W W H H Y Y N N TTTTT EEEEE RRRRR 5 | // W W H H Y Y NN N T E R R 6 | // W W W HHHHH Y N N N T EEE RRRR 7 | // W W W H H Y N NN T E R R 8 | // WWW H H Y N N T EEEEE R R 9 | //============================================================================== 10 | 11 | #define WHYNTER_BITS 32 12 | #define WHYNTER_HEADER_MARK 2850 13 | #define WHYNTER_HEADER_SPACE 2850 14 | #define WHYNTER_BIT_MARK 750 15 | #define WHYNTER_ONE_SPACE 2150 16 | #define WHYNTER_ZERO_SPACE 750 17 | 18 | //+============================================================================= 19 | #if SEND_WHYNTER 20 | void IRsend::sendWhynter(unsigned long data, int nbits) { 21 | // Set IR carrier frequency 22 | enableIROut(38); 23 | 24 | // Start 25 | mark(WHYNTER_BIT_MARK); 26 | space(WHYNTER_ZERO_SPACE); 27 | 28 | // Header 29 | mark(WHYNTER_HEADER_MARK); 30 | space(WHYNTER_HEADER_SPACE); 31 | 32 | // Data 33 | sendPulseDistanceWidthData(WHYNTER_BIT_MARK, WHYNTER_ONE_SPACE, WHYNTER_BIT_MARK, WHYNTER_ZERO_SPACE, data, nbits); 34 | // for (unsigned long mask = 1UL << (nbits - 1); mask; mask >>= 1) { 35 | // if (data & mask) { 36 | // mark(WHYNTER_ONE_MARK); 37 | // space(WHYNTER_ONE_SPACE); 38 | // } else { 39 | // mark(WHYNTER_ZERO_MARK); 40 | // space(WHYNTER_ZERO_SPACE); 41 | // } 42 | // } 43 | 44 | // Footer 45 | mark(WHYNTER_BIT_MARK); 46 | space(0); // Always end with the LED off 47 | } 48 | #endif 49 | 50 | //+============================================================================= 51 | #if DECODE_WHYNTER 52 | bool IRrecv::decodeWhynter() { 53 | int offset = 1; // skip initial space 54 | 55 | // Check we have the right amount of data +5 for (start bit + header) mark and space + stop bit mark 56 | if (results.rawlen <= (2 * WHYNTER_BITS) + 5) { 57 | return false; 58 | } 59 | 60 | // Sequence begins with a bit mark and a zero space 61 | if (!MATCH_MARK(results.rawbuf[offset], WHYNTER_BIT_MARK)) { 62 | return false; 63 | } 64 | offset++; 65 | 66 | if (!MATCH_SPACE(results.rawbuf[offset], WHYNTER_ZERO_SPACE)) { 67 | return false; 68 | } 69 | offset++; 70 | 71 | // header mark and space 72 | if (!MATCH_MARK(results.rawbuf[offset], WHYNTER_HEADER_MARK)) { 73 | return false; 74 | } 75 | offset++; 76 | 77 | if (!MATCH_SPACE(results.rawbuf[offset], WHYNTER_HEADER_SPACE)) { 78 | return false; 79 | } 80 | offset++; 81 | 82 | if (!decodePulseDistanceData(WHYNTER_BITS, offset, WHYNTER_BIT_MARK, WHYNTER_ONE_SPACE, WHYNTER_ZERO_SPACE)) { 83 | return false; 84 | } 85 | 86 | // trailing mark / stop bit 87 | if (!MATCH_MARK(results.rawbuf[offset + (2 * WHYNTER_BITS)], WHYNTER_BIT_MARK)) { 88 | DBG_PRINT("Stop bit verify failed"); 89 | return false; 90 | } 91 | 92 | // Success 93 | results.bits = WHYNTER_BITS; 94 | results.decode_type = WHYNTER; 95 | return true; 96 | } 97 | 98 | bool IRrecv::decodeWhynter(decode_results *aResults) { 99 | bool aReturnValue = decodeWhynter(); 100 | *aResults = results; 101 | return aReturnValue; 102 | } 103 | #endif 104 | 105 | -------------------------------------------------------------------------------- /src/nRF5.cpp: -------------------------------------------------------------------------------- 1 | #if defined(NRF5) || defined(ARDUINO_ARCH_NRF52840) 2 | 3 | // This file contains functions specific to the nRF5. 4 | // It uses Timer2 so you cannot use the Adafruit_Microbit display driver 5 | 6 | #include "IRremote.h" 7 | 8 | // "Idiot check" 9 | #ifdef USE_DEFAULT_ENABLE_IR_IN 10 | #error Must undef USE_DEFAULT_ENABLE_IR_IN 11 | #endif 12 | 13 | void IRTimer(); // defined in IRremote.cpp, masqueraded as ISR(TIMER_INTR_NAME) 14 | 15 | //+============================================================================= 16 | // initialization 17 | // 18 | void IRrecv::enableIRIn() { 19 | // Interrupt Service Routine - Fires every 50uS 20 | NRF_TIMER2->MODE = TIMER_MODE_MODE_Timer; // Set the timer in Timer Mode 21 | NRF_TIMER2->TASKS_CLEAR = 1; // clear the task first to be usable for later 22 | NRF_TIMER2->PRESCALER = 4; // f TIMER = 16 MHz / (2 ^ PRESCALER ) : 4 -> 1 MHz, 1 uS 23 | NRF_TIMER2->BITMODE = TIMER_BITMODE_BITMODE_16Bit; //Set counter to 16 bit resolution 24 | NRF_TIMER2->CC[0] = 50; //Set value for TIMER2 compare register 0, to trigger every 50 uS 25 | NRF_TIMER2->CC[1] = 0; //Set value for TIMER2 compare register 1 26 | 27 | // Enable interrupt on Timer 2, for CC[0] compare match events 28 | NRF_TIMER2->INTENSET = (TIMER_INTENSET_COMPARE0_Enabled << TIMER_INTENSET_COMPARE0_Pos); 29 | NVIC_EnableIRQ (TIMER2_IRQn); 30 | 31 | NRF_TIMER2->TASKS_START = 1; // Start TIMER2 32 | 33 | // timerAttachInterrupt(timer, &IRTimer, 1); 34 | 35 | // Initialize state machine variables 36 | irparams.rcvstate = IR_REC_STATE_IDLE; 37 | irparams.rawlen = 0; 38 | 39 | // Set pin modes 40 | pinMode(irparams.recvpin, INPUT); 41 | } 42 | 43 | void timer_pal(void) { 44 | if ((NRF_TIMER2->EVENTS_COMPARE[0] != 0) && ((NRF_TIMER2->INTENSET & TIMER_INTENSET_COMPARE0_Msk) != 0)) { 45 | NRF_TIMER2->EVENTS_COMPARE[0] = 0; //Clear compare register 0 event 46 | IRTimer(); // call the IR-receive function 47 | NRF_TIMER2->CC[0] += 50; 48 | } 49 | } 50 | 51 | /** TIMTER2 peripheral interrupt handler. This interrupt handler is called whenever there it a TIMER2 interrupt 52 | * Don't mess with this line. really. 53 | */ 54 | extern "C" { 55 | void TIMER2_IRQHandler(void) { 56 | timer_pal(); 57 | } 58 | } 59 | 60 | #endif // NRF5 61 | -------------------------------------------------------------------------------- /src/private/IRremoteInt.h: -------------------------------------------------------------------------------- 1 | //****************************************************************************** 2 | // IRremoteint.h 3 | // IRremote 4 | // Version 2.0.1 June, 2015 5 | // Initially coded 2009 Ken Shirriff http://www.righto.com 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 Arduino header 22 | // 23 | #include 24 | 25 | // All board specific stuff have been moved to its own file, included here. 26 | #include "IRremoteBoardDefs.h" 27 | 28 | //------------------------------------------------------------------------------ 29 | // Information for the Interrupt Service Routine 30 | // 31 | #if ! defined(RAW_BUFFER_LENGTH) 32 | #define RAW_BUFFER_LENGTH 101 ///< Maximum length of raw duration buffer. Must be odd. Supports 16 + 32 bit codings. 33 | #endif 34 | 35 | // ISR State-Machine : Receiver States 36 | #define IR_REC_STATE_IDLE 0 37 | #define IR_REC_STATE_MARK 1 38 | #define IR_REC_STATE_SPACE 2 39 | #define IR_REC_STATE_STOP 3 40 | 41 | /** 42 | * This struct is used for the ISR (interrupt service routine) 43 | * and is copied once only in state STATE_STOP, so only rcvstate needs to be volatile. 44 | */ 45 | struct irparams_struct { 46 | // The fields are ordered to reduce memory over caused by struct-padding 47 | volatile uint8_t rcvstate; ///< State Machine state 48 | uint8_t recvpin; ///< Pin connected to IR data from detector 49 | uint8_t blinkpin; 50 | uint8_t blinkflag; ///< true -> enable blinking of pin on IR processing 51 | uint16_t rawlen; ///< counter of entries in rawbuf 52 | uint16_t timer; ///< State timer, counts 50uS ticks. 53 | uint16_t rawbuf[RAW_BUFFER_LENGTH]; ///< raw data / tick counts per mark/space, first entry is the length of the gap between previous and current command 54 | uint8_t overflow; ///< Raw buffer overflow occurred 55 | }; 56 | 57 | extern struct irparams_struct irparams; 58 | 59 | //------------------------------------------------------------------------------ 60 | // Defines for setting and clearing register bits 61 | // 62 | #ifndef cbi 63 | #define cbi(sfr, bit) (_SFR_BYTE(sfr) &= ~_BV(bit)) 64 | #endif 65 | 66 | #ifndef sbi 67 | #define sbi(sfr, bit) (_SFR_BYTE(sfr) |= _BV(bit)) 68 | #endif 69 | 70 | //------------------------------------------------------------------------------ 71 | // Pulse parms are ((X*50)-100) for the Mark and ((X*50)+100) for the Space. 72 | // First MARK is the one after the long gap 73 | // Pulse parameters in uSec 74 | // 75 | 76 | /** 77 | * When received, marks tend to be too long and spaces tend to be too short. 78 | * To compensate for this, MARK_EXCESS_MICROS is subtracted from all marks, and added to all spaces. 79 | * If you set MARK_EXCESS to approx. 50us then the TSOP4838 works best. 80 | * At 100us it also worked, but not as well. 81 | * Set MARK_EXCESS to 100us and the VS1838 doesn't work at all. 82 | */ 83 | #define MARK_EXCESS_MICROS 100 84 | 85 | /** Relative tolerance (in percent) for some comparisons on measured data. */ 86 | #define TOLERANCE 25 87 | 88 | /** Lower tolerance for comparison of measured data */ 89 | //#define LTOL (1.0 - (TOLERANCE/100.)) 90 | #define LTOL (100 - TOLERANCE) 91 | /** Upper tolerance for comparison of measured data */ 92 | //#define UTOL (1.0 + (TOLERANCE/100.)) 93 | #define UTOL (100 + TOLERANCE) 94 | 95 | /** Minimum gap between IR transmissions, in microseconds */ 96 | #define _GAP 5000 97 | 98 | /** Minimum gap between IR transmissions, in MICROS_PER_TICK */ 99 | #define GAP_TICKS (_GAP/MICROS_PER_TICK) 100 | 101 | //#define TICKS_LOW(us) ((int)(((us)*LTOL/MICROS_PER_TICK))) 102 | //#define TICKS_HIGH(us) ((int)(((us)*UTOL/MICROS_PER_TICK + 1))) 103 | #if MICROS_PER_TICK == 50 && TOLERANCE == 25 // Defaults 104 | #define TICKS_LOW(us) ((us)/67 ) // (us) / ((MICROS_PER_TICK:50 / LTOL:75 ) * 100) 105 | #define TICKS_HIGH(us) ((us)/40 + 1) // (us) / ((MICROS_PER_TICK:50 / UTOL:125) * 100) + 1 106 | #else 107 | #define TICKS_LOW(us) ((uint16_t) ((long) (us) * LTOL / (MICROS_PER_TICK * 100) )) 108 | #define TICKS_HIGH(us) ((uint16_t) ((long) (us) * UTOL / (MICROS_PER_TICK * 100) + 1)) 109 | #endif 110 | 111 | //------------------------------------------------------------------------------ 112 | // IR detector output is active low 113 | // 114 | #define MARK 0 ///< Sensor output for a mark ("flash") 115 | #define SPACE 1 ///< Sensor output for a space ("gap") 116 | 117 | #endif 118 | -------------------------------------------------------------------------------- /src/sam.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iosifpeterfi/Arduino-IRremote/1988f15c1623790b66355bc9e84ccf10235988a7/src/sam.cpp --------------------------------------------------------------------------------