[
  {
    "path": ".github/FUNDING.yml",
    "content": "# These are supported funding model platforms\n\ngithub: nicohood # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2]\npatreon: nicohood # Replace with a single Patreon username\nopen_collective: # Replace with a single Open Collective username\nko_fi: # Replace with a single Ko-fi username\ntidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel\ncommunity_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry\nliberapay: # Replace with a single Liberapay username\nissuehunt: # Replace with a single IssueHunt username\notechie: # Replace with a single Otechie username\ncustom: https://www.buymeacoffee.com/nicohood # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2']\n"
  },
  {
    "path": "Readme.md",
    "content": "# IRLremote 2.0.2\r\n\r\n![Infrared Picture](header.jpg)\r\n\r\nNew lightweight IR library with different, smarter implementation.\r\n\r\nThis library is way more efficient than the \"standard\" IR library from Ken Shirriff.\r\n\r\n<a href=\"https://www.buymeacoffee.com/nicohood\" target=\"_blank\"><img src=\"https://www.buymeacoffee.com/assets/img/custom_images/orange_img.png\" alt=\"Buy Me A Coffee\" style=\"height: auto !important;width: auto !important;\" ></a>\r\n\r\n# Table of Contents\r\n1. [Overview](#overview)\r\n2. [Library Installation](#library-installation)\r\n3. [API Documentation](#api-documentation)\r\n  * [Receive Protocols](#receive-protocols)\r\n  * [Setup Receiving](#setup-receiving)\r\n  * [Read IRLremote](#read-irlremote)\r\n  * [Time Functions](#time-functions)\r\n  * [Sending](#sending)\r\n  * [Adding new protocols](#adding-new-protocols)\r\n4. [How it works](#how-it-works)\r\n5. [Links](#links)\r\n6. [Version History](#version-history)\r\n7. [License and Copyright](#license-and-copyright)\r\n\r\n## Overview\r\n**The main improvements are:**\r\n* Faster decoding (on the fly)\r\n* Huge Ram improvements (13 bytes ram to decode NEC)\r\n* Huge Flash improvements (less than 1kb flash to decode NEC)\r\n* Receiving and sending possible\r\n* Very accurate even when pointing in different directions\r\n* Easy to use/customizable\r\n* Maximum error correction\r\n* Uses PinInterrupt or PinChangeInterrupts/No timer needed\r\n* Usable on almost any pin\r\n* Perfect for Attinys\r\n* All mainstream protocols supported\r\n* Very accurate hash decoding for unknown protocols\r\n* IDE 1.6.x compatible (not 1.0.5 compatible)\r\n\r\n**Supported Protocols**\r\n* NEC\r\n* Panasonic\r\n* ~~Sony 12~~ (TODO)\r\n* Hash (For any unknown protocol)\r\n* ~~RawIR (For dumping the raw data)~~ (TODO)\r\n* Ask me for more\r\n\r\n**Planned features:**\r\n* Test sending functions (for Panasonic, Sony etc)\r\n* Add more protocols (RC06)\r\n* Improve bit banging PWM?\r\n* Add Raw dump sending option\r\n* Implement Sony 15, 20 properly\r\n\r\n## Library Installation\r\nInstall the library as you are used to.\r\nMore information can be found [here](http://arduino.cc/en/guide/libraries).\r\n\r\n## API Documentation\r\nFor a very fast library example see the\r\n[Receiving example](/examples/Receive/Receive.ino).\r\n\r\n### Receive Protocols\r\nYou can choice between multiple protocols. All protocols are optimized in a way\r\nthat the recognition of the selected protocol is set to a maximum. This means\r\nyou can only decode a single protocol at a time but with best recognition.\r\n\r\n##### Supported Protocols:\r\n* NEC\r\n* Panasonic\r\n* IRHash\r\n\r\n##### Examples:\r\n```cpp\r\n// Choose the IR protocol of your remote\r\nCNec IRLremote;\r\n//CPanasonic IRLremote;\r\n//CHashIR IRLremote;\r\n```\r\n\r\n### Setup Receiving\r\nTo use the receiving you have to choose a **[PinInterrupt](http://arduino.cc/en/pmwiki.php?n=Reference/AttachInterrupt)**\r\nor **[PinChangeInterrupt](https://github.com/NicoHood/PinChangeInterrupt)** pin.\r\nThey work a bit different under the hood but the result for IR is the same.\r\nIn order to use PinChangeInterrupts you also have to [install the library](https://github.com/NicoHood/PinChangeInterrupt).\r\n\r\nYou can also terminate the receiver. This sets pins to input again to safely\r\nremove connections. This is **normally not required**.\r\n\r\n##### Function Prototype:\r\n```cpp\r\nbool begin(uint8_t pin);\r\nbool end(uint8_t pin);\r\n```\r\n\r\n##### Examples:\r\n```cpp\r\n// Choose a valid PinInterrupt or PinChangeInterrupt pin of your Arduino board\r\n#define pinIR 2\r\n\r\n// Start reading the remote\r\n// PinInterrupt or PinChangeInterrupt will automatically be selected\r\n// False indicates a wrong selected interrupt pin\r\nif (!IRLremote.begin(pinIR))\r\n    Serial.println(F(\"You did not choose a valid pin.\"));\r\n\r\n// End reading the remote\r\nIRLremote.end(pinIR);\r\n```\r\n\r\n### Read IRLremote\r\nIf there is input available you can read the data of the remote. It will return\r\nthe received data and automatically continue reading afterwards. Check if the\r\nremote is available before, otherwise you will get an empty structure back.\r\n\r\nThe returned data type will differ with the selected protocol. Each protocol has\r\nan address and a command member, but their size may differ. See the protocol\r\nsection for more information.\r\n\r\n##### Function Prototype:\r\n```cpp\r\nbool available(void);\r\n\r\n// Valid datatypes depending on the selected protocol:\r\nNec_data_t read(void);\r\nPanasonic_data_t read(void);\r\nHashIR_data_t read(void);\r\n```\r\n\r\n##### Examples:\r\n```cpp\r\n// Check if new IR protocol data is available\r\nif (IRLremote.available())\r\n{\r\n    // Get the new data from the remote\r\n    auto data = IRLremote.read();\r\n\r\n    // Print the protocol data\r\n    Serial.print(F(\"Address: 0x\"));\r\n    Serial.println(data.address, HEX);\r\n    Serial.print(F(\"Command: 0x\"));\r\n    Serial.println(data.command, HEX);\r\n    Serial.println();\r\n}\r\n```\r\n\r\n### Time Functions\r\nThe API provides a few interfaces to check some timings between the last Event\r\nor if the remote is currently still receiving. This is especially useful when\r\nyou want to build higher level APIs around the remote or when you have other\r\ninterrupt sensitive code that disables interrupts which affects the IR reading\r\nquality.\r\n\r\n##### Function Prototype:\r\n```cpp\r\nbool receiving(void);\r\nuint32_t timeout(void);\r\nuint32_t lastEvent(void);\r\nuint32_t nextEvent(void);\r\n```\r\n\r\n##### Examples:\r\n```cpp\r\n// Check if we are currently receiving data\r\nif (!IRLremote.receiving()) {\r\n  FastLED.show();\r\n}\r\n\r\n// Return relativ time between last event time (in micros)\r\nif (IRLremote.timeout() > 1000000UL) {\r\n    // Reading timed out 1s, release button from debouncing\r\n    digitalWrite(BUILTIN_LED, LOW);\r\n}\r\n\r\n// Return absolute last event time (in micros)\r\nSerial.println(IRLremote.lastEvent, HEX);\r\nSerial.println(micros(), HEX);\r\n\r\n// Return when the next event can be expected.\r\n// Zero means at any time.\r\n// Attention! This value is a little bit too high in general.\r\n// Also for the first press it is even higher than it should.\r\nif (IRLremote.nextEvent() == 0) {\r\n    // We timed out, this is the last event in this series of reading\r\n    digitalWrite(BUILTIN_LED, LOW);\r\n}\r\n```\r\n\r\n### Sending\r\n\r\n**For sending see the SendSerial/Button examples.**\r\nSending is currently **beta**. The library focuses more on decoding, rather than sending.\r\nYou first have to read the codes of your remote with one of the receiving examples.\r\nChoose your protocol in the sending sketch and use your address and command if choice.\r\n\r\nSending for Panasonic and Sony12 is not confirmed to work, since I have no device here to test.\r\nLet me know if it works!\r\n\r\n### Adding new protocols\r\n\r\nYou can also ask me to implement any new protocol, just file an issue on Github or contact me directly.\r\nOr you can just choose the hash option which works very reliable for unknown protocols.\r\n\r\nMore projects + contact can be found here:\r\nhttp://www.NicoHood.de\r\n\r\nHow it works\r\n============\r\n\r\n**The idea is: minimal implementation with maximal recognition.\r\nYou can still decode more than one protocol at the same time.**\r\n\r\nThe trick is to only check the border between logical zero and logical one\r\nto terminate space/mark and rely on the lead/length/checksum as error correction.\r\nLets say a logical 0 is 500ms and 1 is 1000ms. Then the border would be 750ms\r\nto get maximum recognition instead of using just 10%.\r\n\r\nOther protocols use different timings, leads, length, checksums\r\nso it shouldn't interfere with other protocols even with this method.\r\n\r\nThis gives the library very small implementation with maximum recognition.\r\nYou can point into almost every possible direction in the room without wrong signals.\r\n\r\nIt saves a lot of ram because it decodes the signals \"on the fly\" when an interrupt occurs.\r\nThat's why you should not add too many protocols at once to exceed the time of the next signal.\r\nHowever its so fast, its shouldn't make any difference since we are talking about ms, not us.\r\n\r\n**In comparison to Ken's lib**, he records the signals (with timer interrupts) in a buffer which takes a lot of ram.\r\nThen you need to check in the main loop if the buffer has any valid signals.\r\nIt checks every signal, that's why its slow and takes a lot of flash.\r\nAnd it also checks about 10~20% from the original value. Lets say a pulse is 100ms. Then 80-120ms is valid.\r\nThat's why the recognition is worse. And he also doesn't check the protocol intern error correction.\r\nFor example NEC has an inverse in the command: the first byte is the inverse of the 2nd byte. Its easy to filter wrong signals then.\r\nSo every protocol has its built in checksums, which we will use. And I also check for timeouts and start new readings if the signal timed out.\r\nThe only positive thing is that with the timer the pin is more flexible. However i will try to implement a PCINT version later.\r\n\r\nFor sending I decided to use Bitbang. This works on every MCU and on any PIN. He used proper timers,\r\nbut only PIN 3 is usable for sending (an interrupt pin). Bitbang might have problems with other interrupts but should work relyable.\r\nYou can turn off interrupts before sending if you like to ensure a proper sending.\r\nNormal IR devices shouldn't complain about a bit intolerance in the PWM signal. Just try to keep interrupts short.\r\n\r\nThis text should not attack the library from Ken. It's a great library with a lot of work and the most used IR library yet.\r\nIt is just worth a comparison and might be still useful like the old SoftSerial against the new one.\r\n\r\nLinks\r\n=====\r\n\r\n* https://github.com/z3t0/Arduino-IRremote\r\n* http://www.mikrocontroller.net/articles/IRMP#Literatur\r\n* JCV/Panasonic/Japan/KASEIKYO\r\n * http://www.mikrocontroller.net/attachment/4246/IR-Protokolle_Diplomarbeit.pdf\r\n * http://www.roboternetz.de/phpBB2/files/entwicklung_und_realisierung_einer_universalinfrarotfernbedienung_mit_timerfunktionen.pdf\r\n* Sony\r\n * http://picprojects.org.uk/projects/sirc/sonysirc.pdf\r\n * http://www.benryves.com/products/sonyir/\r\n * http://www.righto.com/2010/03/understanding-sony-ir-remote-codes-lirc.html\r\n * http://mc.mikrocontroller.com/de/IR-Protokolle.php#SIRCS\r\n* NEC\r\n * http://techdocs.altium.com/display/FPGA/NEC+Infrared+Transmission+Protocol\r\n * http://www.sbprojects.com/knowledge/ir/nec.php\r\n\r\nVersion History\r\n===============\r\n```\r\n2.0.2 Release (08.04.2018)\r\n* Added ESP8266 #20\r\n\r\n2.0.1 Release (16.01.2018)\r\n* Fix makefile compilation\r\n\r\n2.0.0 Release (07.03.2017)\r\n* Focus on single protocol implementation\r\n* Added better keycode definitions #11\r\n* Updated keywords.txt\r\n* Tabs -> Spaces\r\n* Added receive and time interface templates\r\n\r\n1.9.0 Release (Never officially released)\r\n* Added API as class\r\n* Fixed NEC Timeout value\r\n* NEC repeat code now integrated\r\n* Fixed Sony12 address\r\n* Added debounce\r\n* More flexible selection of protocols\r\n* PinChangeInterrupt library dynamically used\r\n* Added F() makro for examples\r\n* Removed older examples\r\n* Removed the general decoding function to improve decoding functionality\r\n* New inputs are generated at runtime, saves flash and ram\r\n* Faster interrupt if valid signal was received\r\n* Improved NEC sending\r\n* Added to Arduino IDE 1.6.x library manager\r\n* Some other complex library structure changes\r\n* Made reading interrupt save\r\n* Improved RawIR\r\n* Added hash function for unknown protocols\r\n\r\n1.7.4 Release (19.04.2015)\r\n* Updated examples\r\n* Added PinChangeInterrupt example\r\n* Removed NoBlocking API and integrated this into the examples\r\n* Added IRL_VERSION definition\r\n* Added library.properties\r\n* Improved Raw Example\r\n\r\n1.7.3 Release (27.11.2014)\r\n* Fixed critical Typo in decoding function\r\n* Fixed weak function variable type\r\n* Updated Raw Example slightly\r\n\r\n1.7.2 Release (18.11.2014)\r\n* Added always inline macro\r\n* Changed duration to 16 bit\r\n* Added easier PCINT map definitions\r\n* Fixed ARM compilation for receiving (sending is still not working)\r\n\r\n1.7.1 Release (15.11.2014)\r\n* Added 16u2 HoodLoader2 example\r\n\r\n1.7 Release (15.11.2014)\r\n* Changed IR bit order from MSB to correct LSB\r\n * This improved the overall handling and also reduced flash usage\r\n* Improved, extended sending function\r\n* Added Receive Send Example\r\n* Added smaller Basic PCINT function\r\n\r\n1.6 Release (14.11.2014)\r\n* Reworked decoding template\r\n* Added Sony 12 protocol\r\n* Added PCINT example for advanced users\r\n\r\n1.5.1 Release (21.09.2014)\r\n* improved Bitbang PWM\r\n* fixed SendSerial example\r\n\r\n1.5.0 Release (20.09.2014)\r\n* huge Ram and Flash improvements\r\n* new library structure\r\n* compacter code/new structure\r\n* more examples\r\n* more than one protocol possible at the same time\r\n* customizable decoding functions\r\n\r\n1.4.7 Release (13.09.2014)\r\n* changed NEC to template\r\n\r\n1.4.6 Release (30.08.2014)\r\n* fixed writing address + command bug\r\n* added sending function for NEC\r\n* added Led example\r\n\r\n1.4.5 Release (30.08.2014)\r\n* fixed raw protocol\r\n\r\n1.4.4 Release (07.08.2014)\r\n* added raw protocol (broken)\r\n\r\n1.4.3 Release (06.08.2014)\r\n* changed and improved a lot of stuff\r\n* rearranged classes\r\n* removed older versions\r\n\r\n1.0 - 1.3 (17.03.2014 - 03.5.2014)\r\n* Release and minor fixes\r\n```\r\n\r\nLicense and Copyright\r\n=====================\r\nIf you use this library for any cool project let me know!\r\n\r\n```\r\nCopyright (c) 2014-2015 NicoHood\r\nSee the readme for credit to other people.\r\n\r\nPermission is hereby granted, free of charge, to any person obtaining a copy\r\nof this software and associated documentation files (the \"Software\"), to deal\r\nin the Software without restriction, including without limitation the rights\r\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\r\ncopies of the Software, and to permit persons to whom the Software is\r\nfurnished to do so, subject to the following conditions:\r\n\r\nThe above copyright notice and this permission notice shall be included in\r\nall copies or substantial portions of the Software.\r\n\r\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\r\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\r\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\r\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\r\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\r\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\r\nTHE SOFTWARE.\r\n```\r\n"
  },
  {
    "path": "dev/Interpreting Decoded IR Signals (v2.43).htm",
    "content": "<html><head>\r\n<meta http-equiv=\"content-type\" content=\"text/html; charset=windows-1252\">\r\n<title>Interpreting Decoded IR Signals (v2.43)</title>\r\n</head>\r\n<body alink=\"#996600\" background=\"Interpreting%20Decoded%20IR%20Signals%20(v2.43)-Dateien/bg.jpg\" bgcolor=\"#ffffff\" link=\"#3366cc\" text=\"#000000\" vlink=\"#666666\">\r\n\r\n<table width=\"750\"><tbody><tr><td><center>\r\n<script type=\"text/javascript\"><!--\r\ngoogle_ad_client = \"pub-2040680936936450\";\r\n/* 468x60, created 4/17/09 */\r\ngoogle_ad_slot = \"7283198346\";\r\ngoogle_ad_width = 468;\r\ngoogle_ad_height = 60;\r\n//-->\r\n</script>\r\n<script type=\"text/javascript\" src=\"Interpreting%20Decoded%20IR%20Signals%20%28v2.43%29-Dateien/show_ads.js\">\r\n</script>\r\n</center>\r\n</td></tr></tbody></table>\r\n<p>\r\n\r\n</p><blockquote>\r\n<a href=\"#Introduction\">Introduction</a><br><br>\r\n\r\n<table>\r\n<tbody><tr><td valign=\"top\" width=\"140\">\r\n<a href=\"#48-NEC\">48-NEC</a><br>\r\n<a href=\"#48-NEC1\">48-NEC1</a><br>\r\n<a href=\"#48-NEC2\">48-NEC2</a><br>\r\n<a href=\"#AdNotam\">AdNotam</a><br>\r\n<a href=\"#AirAsync\">AirAsync</a><br>\r\n<a href=\"#AirB?-????\">AirB?-????</a><br>\r\n<a href=\"#Aiwa\">Aiwa</a><br>\r\n<a href=\"#AK\">AK</a><br>\r\n<a href=\"#Akai\">Akai</a><br>\r\n<a href=\"#Amino\">Amino</a><br>\r\n<a href=\"#Anthem\">Anthem</a><br>\r\n<a href=\"#Apple\">Apple</a><br>\r\n<a href=\"#Archer\">Archer</a><br>\r\n<a href=\"#Async\">Async</a><br>\r\n<a href=\"#Blaupunkt\">Blaupunkt</a><br>\r\n<a href=\"#Bose\">Bose</a><br>\r\n<a href=\"#CanalSat\">CanalSat</a><br>\r\n<a href=\"#Denon\">Denon</a><br>\r\n<a href=\"#Denon\">Denon{1}</a><br>\r\n<a href=\"#Denon\">Denon{2}</a><br>\r\n<a href=\"#Denon-K\">Denon-K</a><br>\r\n<a href=\"#Dgtec\">Dgtec</a><br>\r\n<a href=\"#DirecTV\">DirecTV</a><br>\r\n<a href=\"#Dishplayer\">Dishplayer</a><br>\r\n<a href=\"#Dish_Network\">Dish_Network</a><br>\r\n<a href=\"#Emerson\">Emerson</a><br>\r\n<a href=\"#F12\">F12</a><br>\r\n</td>\r\n\r\n<td valign=\"top\" width=\"144\">\r\n<a href=\"#Fujitsu\">Fujitsu</a><br>\r\n<a href=\"#Fujitsu-56\">Fujitsu-56</a><br>\r\n<a href=\"#G.I.%20Cable\">G.I. Cable</a><br>\r\n<a href=\"#G.I.%20Cable\">G.I. Cable{1}</a><br>\r\n<a href=\"#G.I.4DTV\">G.I.4DTV</a><br>\r\n<a href=\"#Grundig16\">Grundig16</a><br>\r\n<a href=\"#Grundig16\">Grundig16-30</a><br>\r\n<a href=\"#GXB\">GXB</a><br>\r\n<a href=\"#IODATAn\">IODATA<i>n</i></a><br>\r\n<a href=\"#IODATAn\">IODATA<i>n</i>-<i>x</i>-<i>y</i></a><br>\r\n<a href=\"#Jerrold\">Jerrold</a><br>\r\n<a href=\"#JVC\">JVC</a><br>\r\n<a href=\"#JVC\">JVC{2}</a><br>\r\n<a href=\"#JVC-48\">JVC-48</a><br>\r\n<a href=\"#JVC-56\">JVC-56</a><br>\r\n<a href=\"#Kaseikyo\">Kaseikyo</a><br>\r\n<a href=\"#Kaseikyo-???-???\">Kaseikyo-???-???</a><br>\r\n<a href=\"#Kaseikyo56\">Kaseikyo56</a><br>\r\n<a href=\"#Kaseikyo56-???-???\">Kaseikyo56-???-???</a><br>\r\n<a href=\"#Kathrein\">Kathrein</a><br>\r\n<a href=\"#Konka\">Konka</a><br>\r\n<a href=\"#Lumagen\">Lumagen</a><br>\r\n<a href=\"#Lutron\">Lutron</a><br>\r\n<a href=\"#Matsui\">Matsui</a><br>\r\n<a href=\"#MCE\">MCE</a><br>\r\n<a href=\"#Metz19\">Metz19</a><br>\r\n</td>\r\n\r\n<td valign=\"top\" width=\"142\">\r\n<a href=\"#Mitsubishi\">Mitsubishi</a><br>\r\n<a href=\"#Mitsubishi-K\">Mitsubishi-K</a><br>\r\n<a href=\"#NEC\">NEC</a><br>\r\n<a href=\"#NEC1\">NEC1</a><br>\r\n<a href=\"#NEC2\">NEC2</a><br>\r\n<a href=\"#NECx\">NECx</a><br>\r\n<a href=\"#NECx1\">NECx1</a><br>\r\n<a href=\"#NECx2\">NECx2</a><br>\r\n<a href=\"#Nokia\">Nokia</a><br>\r\n<a href=\"#Nokia12\">Nokia12</a><br>\r\n<a href=\"#Nokia32\">Nokia32</a><br>\r\n<a href=\"#NRC16\">NRC16</a><br>\r\n<a href=\"#NRC17\">NRC17</a><br>\r\n<a href=\"#OrtekMCE\">OrtekMCE</a><br>\r\n<a href=\"#Pace%20MSS\">Pace MSS</a><br>\r\n<a href=\"#Panasonic\">Panasonic</a><br>\r\n<a href=\"#Panasonic2\">Panasonic2</a><br>\r\n<a href=\"#Panasonic_Old\">Panasonic_Old</a><br>\r\n<a href=\"#PCTV\">PCTV</a><br>\r\n<a href=\"#pid-0001\">pid-0001</a><br>\r\n<a href=\"#pid-0003\">pid-0003</a><br>\r\n<a href=\"#pid-0004\">pid-0004</a><br>\r\n<a href=\"#pid-002A\">pid-002A</a><br>\r\n<a href=\"#pid-0083\">pid-0083</a><br>\r\n<a href=\"#Pioneer\">Pioneer</a><br>\r\n<a href=\"#Proton\">Proton</a><br>\r\n</td>\r\n\r\n<td valign=\"top\" width=\"131\">\r\n<a href=\"#RC5\">RC5</a><br>\r\n<a href=\"#RC5-7F\">RC5-7F</a><br>\r\n<a href=\"#RC5-7F-57\">RC5-7F-57</a><br>\r\n<a href=\"#RC5x\">RC5x</a><br>\r\n<a href=\"#RC5-?-??\">RC5-?-??</a><br>\r\n<a href=\"#RC6\">RC6</a><br>\r\n<a href=\"#RC6-6-20\">RC6-6-20</a><br>\r\n<a href=\"#RC6-?-??\">RC6-?-??</a><br>\r\n<a href=\"#RCA\">RCA</a><br>\r\n<a href=\"#RCA\">RCA(Old)</a><br>\r\n<a href=\"#RCA-38\">RCA-38</a><br>\r\n<a href=\"#RCA-38\">RCA-38(Old)</a><br>\r\n<a href=\"#RECS80\">RECS80</a><br>\r\n<a href=\"#Replay\">Replay</a><br>\r\n<a href=\"#Samsung20\">Samsung20</a><br>\r\n<a href=\"#Samsung36\">Samsung36</a><br>\r\n<a href=\"#Sampo\">Sampo</a><br>\r\n<a href=\"#ScAtl-6\">ScAtl-6</a><br>\r\n<a href=\"#Sejin-M-38\">Sejin-<i>M</i>-38</a><br>\r\n<a href=\"#Sejin-M-38\">Sejin-<i>M</i>-56</a><br>\r\n<a href=\"#Sharp\">Sharp</a><br>\r\n<a href=\"#Sharp\">Sharp{1}</a><br>\r\n<a href=\"#Sharp\">Sharp{2}</a><br>\r\n<a href=\"#SharpDVD\">SharpDVD</a><br>\r\n<a href=\"#SIM2\">SIM2</a><br>\r\n<a href=\"#Solidtek16\">Solidtek16</a><br>\r\n</td>\r\n\r\n<td valign=\"top\" width=\"130\">\r\n<a href=\"#Solidtek20\">Solidtek20</a><br>\r\n<a href=\"#Somfy\">Somfy</a><br>\r\n<a href=\"#Sony8\">Sony8</a><br>\r\n<a href=\"#Sony12\">Sony12</a><br>\r\n<a href=\"#Sony15\">Sony15</a><br>\r\n<a href=\"#Sony20\">Sony20</a><br>\r\n<a href=\"#StreamZap\">StreamZap</a><br>\r\n<a href=\"#Sunfire\">Sunfire</a><br>\r\n<a href=\"#TDC-38\">TDC-38</a><br>\r\n<a href=\"#TDC-38\">TDC-56</a><br>\r\n<a href=\"#Teac-K\">Teac-K</a><br>\r\n<a href=\"#Thomson\">Thomson</a><br>\r\n<a href=\"#Thomson7\">Thomson7</a><br>\r\n<a href=\"#Tivo\">Tivo</a><br>\r\n<a href=\"#Velleman\">Velleman</a><br>\r\n<a href=\"#Velodyne\">Velodyne</a><br>\r\n<a href=\"#Viewstar\">Viewstar</a><br>\r\n<a href=\"#X10\">X10</a><br>\r\n<a href=\"#X10\">X10.<i>n</i></a><br>\r\n<a href=\"#XMP\">XMP</a><br>\r\n<a href=\"#XMP\">XMP-1</a><br>\r\n<a href=\"#XMP\">XMP-2</a><br>\r\n<a href=\"#XX\">XX</a><br>\r\n<a href=\"#Zaptor\">Zaptor</a><br>\r\n<a href=\"#Zenith\">Zenith</a><br>\r\n<a href=\"#?1-??-??-??\">?1-??-??-??</a><br>\r\n</td></tr></tbody></table>\r\n\r\n<h2><a name=\"Introduction\">Introduction</a></h2>\r\nThe primary purpose of this document is to explain any peculiarities of the decoding of each protocol.\r\nClick in the list above on each protocol name to get any information specific to decodes with that name.\r\n<p>If you don't understand the advanced information (IRP notation, etc.) at the start of each of those\r\nentries, don't worry about that and please don't let it stop you from reading the text below that.  In many\r\ncases there is important protocol-specific information you will need in order to use the data from\r\nthe decode.</p>\r\n<h3>Decode problems</h3>\r\nThe decoder only looks at one IR signal at a time.  Sometimes it gives contradictory\r\nresults for a signal.  The best way to determine which result is correct is to\r\ncompare with the decodes of other signals for the same device.\r\n<h3><a name=\"spurious\">Spurious decodes and non-robust protocols</a></h3>\r\nMost IR protocols have enough internal consistency checks that the decoder can reliably\r\ntell whether that protocol is present in a learned signal and can reliably decode the\r\ndevice, subdevice and OBC numbers.  If the signal is learned badly enough, the decoder\r\nmay fail to find that protocol in the signal.  But it is very unlikely to decode it\r\nwith the wrong numbers or to imagine that protocol is a bad learn of something else.\r\n  <p>Some protocols are not robust. A totally unrelated IR signal can accidentally \r\n    fit the pattern of such a protocol resulting in a spurious decode. When you \r\n    get a decode for a non-robust protocol you need to exercise some judgment \r\n    about whether to believe or ignore that decode. Usually you can decide based \r\n    on decodes of other signals of the same device.</p>\r\n<h3><a name=\"jp1\">EFC, JP1, KeyMoves, Upgrades, etc.</a></h3>\r\nMuch of this document assumes DecodeIr is being used with JP1 or at least with a JP1\r\ncapable remote.  But some people will be using DecodeIr with other types of remote.\r\n<p>If your remote is not OneForAll brand and is not one of the models of Radio Shack (or a few\r\nother brands) that uses the same design as OneForAll, then everything this document says\r\nabout JP1, KeyMoves, Upgrades, KM, RM (RemoteMaster), and EFC numbers has no meaning for\r\nyour use.  Just ignore those references and the rest of this doc should apply to your use.\r\nAlso ignore the EFC numbers in the actual output from DecodeIr.</p>\r\n<p>If you are using a OneForAll type remote but have neither a JP1 cable nor a remote model\r\nthat can be upgraded by .wav file, then nothing about Upgrades, KM, RM, and OBC numbers\r\napplies to your use.  If the decodes you get include EFC numbers and you know (or can\r\nask in a forum) which setup code is right (corresponds to the protocol, device and\r\nsubdevice of the decode) then you can use those EFC numbers in KeyMoves.  Note that\r\nthe decoding process cannot directly tell you which setup code is needed to\r\ngenerate the signal.  If you post a question in an appropriate forum with the protocol name,\r\ndevice number, subdevice number, and which model OneForAll type remote you have, someone\r\nwill probably identify the setup code for you.</p>\r\n<h3><a name=\"toggle\">Toggle bits</a></h3>\r\nSeveral different protocols include something called a toggle bit.  This means that each command\r\nhas two or more different forms.  Some protocols (e.g. RC5) alternate the toggle on each key press, while\r\nothers change the toggle to indicate a start or end frame.\r\n<p>An alternating toggle lets the device receiving the commands distinguish between a long press\r\nof a button and two short presses.  For example, if you press and hold the '1' button\r\nthe remote continuously sends repeats of a single form of the '1' command.  But if you\r\npress '1', release it and press it again the remote will switch to the other form of the\r\ncommand for the second press.</p>\r\n<p>When you learn such a command you are capturing just one form of the command and\r\nevery use will send that same form.  If you use that learned signal and press the same button twice\r\nin a row, the device receiving the signal will see that as one long press rather than two\r\nshort ones.  For keys, such as digits, where one long press has a different meaning than\r\ntwo short presses, that gets quite inconvenient.</p>\r\n<p>With OneForAll type remotes, using an upgrade or KeyMove will solve that problem.</p>\r\n<p>For some of these protocols, for some models of Pronto remote, there is a condensed\r\nencoding of the Pronto Hex that will solve the problem.</p>\r\n\r\n<h3><a name=\"repeat\">Repeat frames and dittos</a></h3>\r\n<p>DecodeIR v2.37 and later versions have a look-ahead facility that is not present in earlier ones.  \r\n    This distinguishes between two styles of data passed to them by the calling application.  The \r\n    remote control programming applications IR.exe and RMIR pass signals learned by a UEI remote \r\n    that has itself performed a partial analysis of the signal.  The data is passed in a structured \r\n    form, divided into Once, Repeat and Extra sections.  The data in each of these sections can be \r\n    viewed in IR.exe if the \"Force Learned Timings\" option on the Advanced menu is selected.  Because \r\n    of this analysis, DecodeIR does not see the original signal in full and cannot determine such \r\n    things as the number of repeats of the signal that were sent.  Other applications such as the \r\n    IRScope software for the IR Widget send the entire signal as unstructured data, which enables \r\n    IR.exe to identify the number of repeats.</p>\r\n<p>The look-ahead facility checks successive frames within a single signal to see if they are \r\n    repeats  either identical repeats or, in certain protocols, frames of a repeat sequence \r\n    that have a distinctive marker in either the start or end frame, or both, of the sequence.  If a \r\n    protocol has distinctive start or end frame markers and either or both of the start and end frames \r\n    are missing, this is reported in the Misc field of the decode (but at present this may not be \r\n    implemented for all protocols with such markers).  If the data has been passed in an unstructured \r\n    form then the number of repeats in the signal will also be reported in the Misc field in a form \r\n    like \"4 frames\", or in version 2.39 and later, \"+ 3 copies\".</p>\r\n<p>In the case of unstructured data, DecodeIR v2.38 extends the look-ahead to protocols in which repeat \r\n    action is signalled not by a full repeat of the frame but by a much shorter frame that does not carry \r\n    the signal data (or occasionally carries just part of this data).  These frames serve \r\n    as \"ditto marks\".  If present then the number of such frames is reported in the Misc field \r\n    in a form like \"3 dittos\", or in version 2.39 and later, \"+ 3 dittos\".  If there \r\n    are no repeat frames or ditto marks, then to avoid ambiguity this is reported as \"no repeat\".</p>\r\n\r\n<h3><a name=\"MiniComboExecutors\">Mini Combos</a></h3>\r\nSome UEI protocol executors are \"mini-combos\".  This means they support more than one\r\ndevice number within one setup code using single-byte hex commands.  There will be more\r\nthan one possible EFC number for each OBC number.  DecodeIr can't determine the correct\r\nEFC number by looking at the IR signal, because it isn't a characteristic of the signal.\r\nIt is a characteristic of the fixed data used in creation of the setup code.\r\n<p>DecodeIr will list two or three different EFC numbers for each OBC number.\r\nThe sequence of those two or three EFC numbers is consistent across all the decodes.\r\nSo once you find out which position in that list is correct for one OBC of a given device\r\nnumber and setup code, that position will be correct for the EFC list of any other OBC of\r\nthe same device and setup code (except that for RC-5 the decision of whether or not the OBC\r\nnumber is above 63 is treated as being part of the device number).</p>\r\n\r\n<h3><a name=\"ReadingIRP\">Brief and incomplete guide to reading IRP</a></h3>\r\n\r\n<b>General</b>: {carrier frequency, time unit, sequencing rule} \r\nMitsubishi:<b>{32.6k,300}</b>&lt;1,-3|1,-7&gt;(D:8,F:8,1,-80)+ <br>\r\n<i>Carrier Frequency</i>: Hz; e.g. 38.3k; default is 0k--no  modulation<br>\r\n<i>Time Unit</i>: Integer that can represent durations.  Suffix u (default) is microseconds, p denotes number of pulses of the carrier.<br>\r\n<i>Sequencing Rule</i>:  lsb|msb; lsb (default) means the least significant bit of a binary form is sent first. <br>\r\n<b>BitSpec</b>: Rule for the translating bit sequences to duration \r\nsequences.  &lt;ZeroPulseSeq|OnePulseSeq|TwoPulseSeq....&gt;.  Most IR \r\nprotocols use only &lt;ZeroPulseSeq|OnePulseSeq&gt;, and the sequence is\r\n simply OnDuration,OffDuration.    Example: NEC uses  &lt;1,-1|1,-3&gt;<br>\r\n\r\n<b>Bitfield</b>:  D:NumberOfBits:StartingBit.  E.g. if D=71= 01000111, D:2:5 means x<b>10</b>xxxxx.\r\n  D:2:5 = 10b = 2.   ~ is the bitwise complement operator.  ~D \r\n=10111000. Specifying the StartingBit is optional. D:6 is equivalent to \r\nD:6:0.<br>\r\n\r\n<b>IRStream</b>: The sequence of data. Enclosed in parentheses, items separated by commas. \r\nA trailing + means send one or more times.  A trailing 3 means send 3 times; 3+ means at least 3 times.   \r\nA trailing * means send zero or more times. NEC2: {38.4k,564}&lt;1,-1|1,-3&gt;<b>(16,-8,D:8,S:8,F:8,~F:8,1,-78)+</b> <br>\r\n\r\n<b>Durations</b>: no suffix means duration is expressed in Time Units, as defined above.  \r\nm is milliseconds, u microsec, p pulses.  No prefix means a flash, a preceeding - (minus) means a gap.<br>\r\n\r\n<b>Extent</b>: A gap which trails a signal.   The trailing gap is adjusted to make the total length of signal \r\nplus trailing gap equal to the extent. Notation is like a gap duration, except ^ replaces the minus sign. \r\nRC-5:(1:1,~F:1:6,T:1,D:5,F:6,<b>^114m</b>)+ <br>\r\n\r\n<b>Expressions</b>:   names, numbers and bitfields connected by standard symbols for arithmetic and logical \r\noperations.  Enclosed in parentheses. Panasonic: {37k,432}&lt;1,-1|1,-3&gt;(8,-4,2:8,32:8,D:8,S:8,F:8,<b>(D^S^F)</b>:8,1,-173)+ \r\n <br>  \r\n\r\n<b>Permitted operators in decreasing order of precedence:</b><br>\r\n<code>\r\n      unary    (negation)<br>\r\n      **  (exponentiation)<br>\r\n      * /, %  (multiplication, integer division, modulo) (* is also used in IRStreams)<br>\r\n      +,    (addition, subtraction  (+ is also used in IRStreams)<br>\r\n      &amp;       (bitwise AND)<br>\r\n      ^        (exclusive OR)  (also used in extents)<br>\r\n      |        (OR)<br>\r\n      ~     (complement) is permitted in Bitfields</code><br>\r\n\r\n<b>Definitions</b>:  expressions separated by commas, enclosed in curly brackets. \r\nGI Cable: {38.7k,490}&lt;1,-4.5|1,-9&gt;(18,-9,F:8,D:4,C:4,1,-84,(18,-4.5,1,-178)*) \r\n<b>{C = -(D + F:4 + F:4:4)}</b> <br>\r\n<b>Assignments</b>:  For example T=T+1, which can be used to describe the RC-5 toggle bit.<br>\r\n<b>Variations</b>:  Up to 3 expressions enclosed in square brackets.  The first variation is \r\nsent on the first transmission, second for middle transmissons, and the third for the final transmission. \r\nE.g. the Zaptor toggle bit is zero until the last frame: [T=0] [T=0] [T=1]<br>\r\n<a href=\"http://www.hifi-remote.com/wiki/index.php?title=IRP_Notation\"> The IRP specification by Graham Dixon</a><br>\r\n<a href=\"http://www.hifi-remote.com/forums/dload.php?action=file&amp;file_id=6996\"> Practical explanation of IR signals and IRP by Vicky Getz</a>\r\n\r\n    \r\n<h2><a name=\"48-NEC\">48-NEC</a></h2>\r\nIf you get a decode whose protocol name is\r\nsimply \"48-NEC\" that indicates the learned signal is not complete (usually caused by\r\nnot holding the original remote's button long enough during learning).  Enough of\r\nthe signal is present to accurately determining the device, subdevice and OBC numbers.\r\nBut not enough is present to determine whether the protocol is 48-NEC1 or 48-NEC2.\r\n\r\n<h2><a name=\"48-NEC1\">48-NEC1</a></h2>\r\nIRP notation: {564}&lt;1,-1|1,-3&gt;(16,-8,D:8,S:8,F:8,~F:8,E:8,~E:8,1,-??,(16,-4,1,-??)*) \r\n<br>\r\nEFC translation: LSB\r\n<p>This protocol signals repeats by the use of <a href=\"#repeat\">dittos</a>.</p> \r\n\r\n<h2><a name=\"48-NEC2\">48-NEC2</a></h2>\r\nIRP notation: {564}&lt;1,-1|1,-3&gt;(16,-8,D:8,S:8,F:8,~F:8,E:8,~E:8,1,-??)+ \r\n<br>\r\nEFC translation: LSB\r\n\r\n<h2><a name=\"AdNotam\">AdNotam</a></h2>\r\nIRP notation: {35.7Khz,895,msb}&lt;1,-1|1,-3&gt;(0:1,1:1,D:6,F:6,^114m)+ \r\n<br>\r\n<p>Very similar to RC5, except AdNotam uses two start bits, and no toggle bit.    \r\n\r\n\r\n</p><h2><a name=\"AirAsync\">AirAsync</a></h2>\r\nIRP notation: {37.7Khz,840}&lt;1|-1&gt;( 1,B:8,-2 ... )\r\n<p>This protocol uses asynchronous data transmission that sends an 8-bit byte with 1 start bit, \r\n8 data bits and 2 stop bits.  The minimum signal is one byte.  The protocol is reported as\r\nAirAsync<i>n</i>-xx.yy. ...\r\nwhere <i>n</i> is the number of bytes and xx, yy, ... are the byte values in hexadecimal notation.  \r\n</p>\r\n\r\n<h2><a name=\"AirB?-????\">AirB?-????</a></h2>\r\n<p>This is not a robust protocol, so <a href=\"#spurious\">spurious decodes</a> are likely.\r\nIf you see this decode from something other than an IR keyboard, you should probably ignore it.</p>\r\n\r\n<h2><a name=\"Aiwa\">Aiwa</a></h2>\r\nUEI protocol: 005E or 009E\r\n<br>\r\nIRP notation: {38k,550}&lt;1,-1|1,-3&gt;(16,-8,D:8,S:5,~D:8,~S:5,F:8,~F:8,1,-42,(16,-8,1,-165)*) \r\n<br>\r\nEFC translation: LSB\r\n<p>This protocol signals repeats by the use of <a href=\"#repeat\">dittos</a>.</p>\r\n<p>The EFC numbering varies among the KM and RM versions of Aiwa.  Using OBC numbers is less confusing.</p>\r\n<p>When using a non-combo version of Aiwa in KM, you must combine the device and subdevice numbers as\r\ndevice+256*subdevice to get the number KM calls \"Device Code\".  (Since subdevice is usually zero, that\r\ncombination is trivial).  In Aiwa combo in KM you use the subdevice as \"parameter\" (on the setup sheet)\r\nand put the device in the byte2 column on the functions sheet.  RM follows DecodeIr's naming of Device\r\nand Subdevice.</p>\r\n\r\n<h2><a name=\"AK\">AK</a></h2>\r\nDocumentation not written yet.\r\n\r\n<h2><a name=\"Akai\">Akai</a></h2>\r\nUEI protocol: 000D\r\n<br>\r\nIRP notation: {38k,289}&lt;1,-2.6|1,-6.3&gt;(D:3,F:7,1,^25.3m)+ <br>\r\nEFC translation: LSB comp prefixed with last device bit\r\n<p>This is not a robust protocol, so <a href=\"#spurious\">spurious decodes</a> are likely.</p>\r\n<p>As of version 8.31, KM does not translate device to fixed data, nor OBC to EFC according to\r\nthe same rules used by DecodeIr.  RM does translate consistently with DecodeIr, so you may find\r\nit easier to use RM.  If you use KM, you must change the device number as follows:</p>\r\n<ul>\r\n<li>Decoded device 0 or 4 --&gt; KM device 3</li>\r\n<li>Decoded device 1 or 5 --&gt; KM device 2</li>\r\n<li>Decoded device 2 or 6 --&gt; KM device 1</li>\r\n<li>Decoded device 3 or 7 --&gt; KM device 0</li>\r\n</ul>\r\n<p>Also (in KM) you should use the EFC number from the decode not the OBC number.  Akai protocol\r\nuses the same EFC numbering across all JP1 remotes, so use of EFC is safe.  KM uses different\r\nOBC numbering than RM and DecodeIr, so use of OBCs isn't safe.</p>\r\n\r\n<h2><a name=\"Amino\">Amino</a></h2>\r\nUEI protocol: 019C\r\n<br>\r\nIRP notation: {56.0k,268,msb}&lt;-1,1|1,-1&gt;[T=1] [T=0] (7,-6,3,D:4,1:1,T:1,1:2,0:8,F:8,15:4,C:4,-79m)+<br>\r\n-----Variant: {36.0k,268,msb}&lt;-1,1|1,-1&gt;[T=1] [T=0] (7,-6,3,D:4,1:1,T:1,1:2,0:8,F:8,15:4,C:4,-79m)+\r\n<br>{C =(D:4+4*T+9+F:4+F:4:4+15)&amp;15}  [the arithmetic sum of the first 7 nibbles mod 15]\r\n<br>T=1 for the first frame and T=0 for all repeat frames.  \r\n<br>DecodeIR v2.43 checks T and will report in the Misc field if the start or end frame is missing.\r\nAmino equipment use both 36 and 56KHz, but the duration of the half-bit is\r\nalways 268.  Zaptor is a closely related protocol which for which the half-bit duration is 330.\r\nIRDecode v2.43 distinguishes between Amino and Zaptor in order of priority by 1)the position of the toggle bit,\r\n2)the value of the next to last nibble, and 3)the measured duration of a half-bit.\r\n<br>\r\nEFC translation: MSB\r\n\r\n<h2><a name=\"Anthem\">Anthem</a></h2>\r\nUEI protocol: 0123 <br>\r\nIRP notation: {38.0k,605}&lt;1,-1|1,-3&gt;((8000u,-4000u,D:8,S:8,E:8,C:8,1,-25m)3, -75m)+ {E=(64*U:2+F:6), C=~(D+S+E+255):8}\r\n<br>Anthem framing is very similar to NEC, and also uses 32 bits of data.  However, the leadout is much shorter.\r\nThe signal is sent at least3 times.\r\n\r\n<h2><a name=\"Apple\">Apple</a></h2>\r\nUEI protocol: 01E0\r\n<br>\r\n\r\nIRP notation: {38.4k,564}&lt;1,-1|1,-3&gt;(16,-8,D:8,S:8,C:1,F:7,I:8,1,-78,(16,-4,1,-173)*)<br>\r\nC=1 if the number of 1 bits in the fields F and I is even.  I is the remote ID.\r\n<p> Apple uses the same framing as NEC1, with D=238 in normal use, 224 while pairing.  S=135 </p>\r\n\r\n<h2><a name=\"Archer\">Archer</a></h2>\r\nIRP notation: {0k,12}&lt;1,-3.3m|1,-4.7m&gt;(F:5,1,-9.7m)+ <br>\r\nEFC translation: 5-bit LSB\r\n<p>This is not a robust protocol, so <a href=\"#spurious\">spurious decodes</a> are likely.</p>\r\n\r\n<h2><a name=\"Async\">Async</a></h2>\r\n<p>This protocol uses asynchronous data transmission that sends an 8-bit byte with 1 start bit, \r\n8 data bits and 1 stop bit.  The minimum signal is four bytes.  The protocol is reported as\r\nAsync<i>n</i>:min-max:aa.bb...yy.zz\r\nwhere <i>n</i> is the number of bytes, min-max is the range of durations\r\n in microseconds that was taken as a single bit and aa.bb...yy.zz are \r\nthe first two and last two byte values in hexadecimal notation.  \r\n</p>\r\n\r\n<h2><a name=\"Blaupunkt\">Blaupunkt</a></h2>\r\nIRP notation: {30.3k,528}&lt;-1,1|1,-1&gt;(1,-5,1023:10,-39,1,-5,1:1,F:7,D:2,-230) \r\n\r\n<h2><a name=\"Bose\">Bose</a></h2>\r\nIRP notation: {500,msb}&lt;1,-1|1,-3&gt;(2,-3,F:8,~F:8,1,-???)+ <br>\r\nEFC translation: MSB\r\nThe decode is intended to be consistent with the posted KM file:\r\n<a href=\"http://www.hifi-remote.com/forums/dload.php?action=file&amp;file_id=974\">Bose-Wave-Radio-KM.txt</a>\r\nand PB file:\r\n<a href=\"http://www.hifi-remote.com/forums/dload.php?action=file&amp;file_id=1389\">Bose_Wave_Radio-PB.txt</a>\r\n\r\n<h2><a name=\"CanalSat\">CanalSat</a></h2>\r\nUEI protocol: 018C\r\n<br>\r\nIRP notation: {55.5k,250,msb}&lt;-1,1|1,-1&gt;(1:1,D:7,S:6,T:1,0:1,F:7,-89m)+ \r\n<br>\r\nEFC translation: 7-bit MSB.\r\n<p>The <a href=\"#repeat\">repeat frames</a> are not all identical.  T toggles within a single signal, with T=0\r\nfor the start frame and T=1 for all repeats.  DecodeIR v2.37 and later check T and will report in the Misc\r\nfield if the start frame is missing.</p>\r\n\r\n<h2><a name=\"Denon\">Denon, Denon{1} and Denon{2}</a></h2>\r\nIRP notation: {38k,264}&lt;1,-3|1,-7&gt;(D:5,F:8,0:2,1,-165,D:5,~F:8,3:2,1,-165)+ \r\n<br>\r\nEFC translation: LSB\r\n<p>A Denon signal has two halves, either one of which is enough to fully decode \r\nthe information. A significant fraction of Denon learned signals contain just \r\none half or have the halves separated so that DecodeIr can't process them \r\ntogether. When one half is seen separate from the other, DecodeIr will name \r\nthe protocol Denon{1} or Denon{2} depending on which half is decoded. Denon, \r\nDenon{1} and Denon{2} all represent the same protocol when they are correct. \r\nBut only Denon is robust. A Denon{1} or Denon{2} decode might be <a href=\"#spurious\">spurious</a>.</p>\r\n\r\n<h2><a name=\"Denon-K\">Denon-K</a></h2>\r\nUEI protocol: 00CD\r\n<br>\r\nIRP notation: {37k,432}&lt;1,-1,1,-3&gt;(8,-4,84:8,50:8,0:4,D:4,S:4,F:12,((D*16)^S^(F*16)^(F:8:4)):8,1,-173)+ \r\n<br>\r\nEFC translation: LSB comp\r\n<p>Denon-K is the member of the Kaseikyo family with OEM_code1=84 and OEM_code2=50.</p>\r\n<p>Denon-K uses the same check byte rules as Panasonic protocol, but uses the data bits differently.\r\nThe Panasonic Combo protocol in KM can be used with some difficulty to produce Denon-K signals.\r\nThe Denon-K choice in RM uses the same protocol executor as Panasonic combo, but computes the hex commands\r\nbased on Denon's use of the Kaseikyo data bits.</p>\r\n\r\n<h2><a name=\"Dgtec\">Dgtec</a></h2>\r\nUEI protocol: 016A\r\n<br>\r\nIRP notation: {38k,560}&lt;1,-1|1,-3&gt;(16,-8,D:8,F:8,~F:8,1,^108m,(16,-4,1,^108m)+) \r\n<br>\r\nEFC translation: LSB comp\r\n<p>This protocol signals repeats by the use of <a href=\"#repeat\">dittos</a>.</p>\r\n\r\n<h2><a name=\"DirecTV\">DirecTV</a></h2>\r\nIRP notation: {38k,600,msb}&lt;1,-1|1,-2|2,-1|2,-2&gt;(5,(5,-2,D:4,F:8,C:4,1,-50)+) \r\n{C=7*(F:2:6)+5*(F:2:4)+3*(F:2:2)+(F:2)} <br>\r\nEFC translation: MSB\r\n<p>There are six variants of the DirecTV protocol, distinguished in RemoteMaster by the parameter \"Parm\" on\r\nthe Setup page.  The Parm value is shown in the Misc field of DecodeIR.  The IRP notation above corresponds\r\nto the default Parm=3.  The various Parm values correspond to three different frequencies (the 38k in the above) \r\nand two different lead-out times (the -50 in the above).  The corresponding values are:</p>\r\n<ul>\r\n<li>Parm=0 : 40k, -15\r\n</li><li>Parm=1 : 40k, -50\r\n</li><li>Parm=2 : 38k, -15\r\n</li><li>Parm=3 : 38k, -50\r\n</li><li>Parm=4 : 57k, -15\r\n</li><li>Parm=5 : 57k, -50\r\n</li></ul> \r\n<p>Portions of a dirty learn of a Sony signal may look like a DirecTV signal.  So, if you get a DirecTV\r\ndecode together with a plausible Sony decode, believe the Sony decode and ignore the DirecTV.  If you get\r\na DirecTV decode without a Sony decode for some functions of a Sony device, try relearning them;  a DirecTV\r\ndecode for a signal meant for a Sony device is not likely to be correct.</p>\r\n<p>This protocol was called Russound in versions of DecodeIR earlier than 2.40.</p>\r\n\r\n<h2><a name=\"Dishplayer\">Dishplayer</a></h2>\r\nUEI protocol: 010F\r\n<br>\r\nIRP notation: {38.4k,535,msb}&lt;1,-5|1,-3&gt;(1,-11,(F:6,U:5,D:2,1,-11)+) <br>\r\nEFC translation: Not available in this version of DecodeIr\r\n<p>This is not a robust protocol, so <a href=\"#spurious\">spurious decodes</a> are likely.</p>\r\n\r\n<h2><a name=\"Dish_Network\">Dish_Network</a></h2>\r\nUEI protocol: 0002 <br>IRP notation: {57.6k,400}&lt;1,-7|1,-4&gt;(1,-15,(F:-6,U:5,D:5,1,-15)+)\r\n<br>\r\nEFC translation: MSB comp 6 function bits followed by LSB comp low 2 unit bits.\r\n<p>This is not a robust protocol, so <a href=\"#spurious\">spurious decodes</a> are likely.</p>\r\n<p>The unit number shows up in the Subdevice field of DecodeIr's output.  In KM, the \"unit code\" is\r\none greater than the unit number.  So you must take the Subdevice from the decode and add one to\r\nit and use that as the \"unit code\" in KM.</p>\r\n<p>There are two variants of the protocol executor for DishNetwork with different \r\nbut compatible EFC numbering. The decoded EFC should work for both. But the \r\nresults may be less confusing if you use OBC numbers in KM or RM.</p>\r\n\r\n<h2><a name=\"EchoStar\">EchoStar</a></h2>\r\nUEI protocol: 0182\r\n<br> As of 2.42 DecodeIR shows this as RC5-7F\r\n\r\n<h2><a name=\"Emerson\">Emerson</a></h2>\r\nUEI protocol: 0065\r\n<br>\r\nIRP notation: {36.7k,872}&lt;1,-1|1,-3&gt;(4,-4,D:6,F:6,~D:6,~F:6,1,-39)+ <br>\r\nEFC translation: 6-bit LSB comp with 2-bit mini-combo\r\n<p>Lists three different EFCs because this protocol is a <a href=\"#mini%20combo\">mini combo</a>.</p>\r\n\r\n<h2><a name=\"F12\">F12</a></h2>\r\nUEI protocol: 001A\r\n<br>\r\nIRP notation: (Toshiba specification) K=(D:3,H:1,A:1,B:2,F:6)\r\n{37.9k,422}&lt;1,-3|3,-1&gt;(K,-34,K) for A=1 or B=1 <br>\r\n{37.9k,422}&lt;1,-3|3,-1&gt;(K,-34,K,-88,K,-34,K)+ for H=1.\r\nExactly one of H, A, or B can have a value of 1.  If H=1 the signal can be sent repeatedly, and F can take any 6 bit value.\r\nIf A or B=1, the signal is sent once only per button press, and only a single bit of F can be non-zero. <p>\r\nIRP notation: (JP1) K=(D:3,H:1,F:8)\r\n{37.9k,422}&lt;1,-3|3,-1&gt;(K,-34,K) for H=0. <br>\r\n{37.9k,422}&lt;1,-3|3,-1&gt;(K,-34,K,-88,K,-34,K)+ for H=1. <br>\r\nA and B are subsumed into F, and the value of H is computed in the executor. H=A^B.\r\n<br>EFC translation: lsb, but not computed in DecodeIR.\r\n<br> DecodeIR reports H as the subdevice.  This is useful when making a Pronto Hex file,\r\nor other description based on durations.  Remotes with executors (e.g. UEI remotes) normally compute the value of\r\nH in the executor, and the \"subdevice\" is not needed as a parameter.\r\n\r\n</p><h2><a name=\"Fujitsu\">Fujitsu</a></h2>\r\nUEI protocol: 00F8\r\n<br>\r\nIRP notation: {37k,432}&lt;1,-1,1,-3&gt;(8,-4,20:8,99:8,X:4,E:4,D:8,S:8,F:8,1,-110)+ \r\n<br>\r\nEFC translation: LSB comp\r\n<p>Fujitsu is the member of the Kaseikyo family with OEM_code1=20 and OEM_code2=99.</p>\r\n<p>There is no check byte, so the risk of an incorrectly decoded OBC is much higher than in\r\nother Kaseikyo protocols.</p>\r\n  <p>00F8 requires 2-byte hex commands, so the decoded EFC number is generally not \r\n    useful. Use OBC number in upgrades or to compute Hex commands.</p>\r\n\r\n<h2><a name=\"Fujitsu-56\">Fujitsu-56</a></h2>\r\nIRP notation: {37k,432}&lt;1,-1,1,-3&gt;(8,-4,20:8,99:8,H:4,E:4,D:8,S:8,X:8,F:8,1,-110)+ \r\n\r\n<h2><a name=\"G.I. Cable\">G.I. Cable and G.I. Cable{1}</a></h2>\r\nUEI protocol: 00C4\r\n<br>\r\nIRP notation: {38.7k,490}&lt;1,-4.5|1,-9&gt;(18,-9,F:8,D:4,C:4,1,-84,(18,-4.5,1,-178)*) \r\n{C = -(D + F:4 + F:4:4)} <br>\r\nEFC translation: LSB\r\n<p>This protocol signals repeats by the use of <a href=\"#repeat\">dittos</a>.\r\nWhen the {1} is shown as part of the protocol name for G.I. Cable, it just means that the repeat\r\npart of the signal is not present.  That doesn't indicate any difference in the actual protocol nor\r\neven any unreliability in the decode.  It may indicate that use of the learned signal will be less\r\nreliable, so you have more than usual reason to replace it with a <a href=\"#jp1\">KeyMove, Upgrade</a> or cleaned\r\nup version.</p>\r\n\r\n<h2><a name=\"G.I.4DTV\">G.I.4DTV</a></h2>\r\nUEI protocol: 00A4\r\n<br>\r\nIRP notation: {37.3k,992}&lt;1,-1|1,-3&gt;(5,-2,F:6,D:2,C:4,1,-60)+ <br>\r\nEFC translation: NONE\r\n<p>This is a moderately robust protocol, but <a href=\"#spurious\">spurious decodes</a> are still possible.</p>\r\n<p>The official (UEI) protocol executor for G.I.4DTV does not support EFC numbers.  If you are creating an\r\nupgrade in KM or RM you should use OBC numbers, not EFC numbers.  If you need the Hex Cmd for a KeyMove,\r\nyou should use the functions sheet of KM or RM to compute it for you from the OBC and device number.</p>\r\n\r\n<h2><a name=\"Grundig16\">Grundig16 and Grundig16-30</a></h2>\r\nUEI protocol:  Grundig16 0112, Grundig16-30 00AB\r\n<br>IRP notation for Grundig16: {35.7k,578,msb}&lt;-4,2|-3,1,-1,1|-2,1,-2,1|-1,1,-3,1&gt;\r\n(806u,-2960u,1346u,T:1,F:8,D:7,-100)+\r\n<br>IRP notation for Grundig16-30: {30.3k,578,msb}&lt;-4,2|-3,1,-1,1|-2,1,-2,1|-1,1,-3,1&gt;\r\n(806u,-2960u,1346u,T:1,F:8,D:7,-100)+ \r\n <br>\r\nEFC translation:  MSB but with bit pairs translated data-&gt;hex by 00-&gt;00, 01-&gt;11, 10-&gt;01, 11-&gt;\r\n10 and off by one position.\r\n<p>These are two variants of the same protocol, differing only in frequency.  The IRP notation is corrected \r\n    from previous versions of this document, to bring it into line with what DecodeIR actually does.</p>\r\n\r\n<h2><a name=\"GXB\">GXB</a></h2>\r\nIRP notation: {38.3k,520,msb}&lt;1,-3|3,-1&gt;(1,-1,D:4,F:8,P:1,1,^???)+ \r\n<p>Decoder for a nonstandard Xbox remote.</p>\r\n\r\n<h2><a name=\"IODATAn\">IODATA</a><i>n</i> and IODATA<i>n</i>-<i>x</i>-<i>y</i></h2>\r\nUEI protocol: not known.\r\n<br>\r\nIRP notation: {38k,550}&lt;1,-1|1,-3&gt;(16,-8,x:7,D:7,S:7,y:7,F:8,C:4,1,^108m)+ \r\n{n = F:4 ^ F:4:4 ^ C:4} <br>\r\nEFC translation: LSB\r\n<p>This is potentially a class of protocols distinguished by values of <i>n</i>, <i>x</i> and <i>y</i> with \r\n    <i>n</i> = 0..15 and <i>x</i>, <i>y</i> = 0..127.  If <i>x</i> and <i>y</i> are both zero, they are omitted.  The only known example is IODATA1.</p>\r\n\r\n<h2><a name=\"Jerrold\">Jerrold</a></h2>\r\nUEI protocol: 0006\r\n<br>\r\nIRP notation: {0k,44}&lt;1,-7.5m|1,-11.5m&gt;(F:5,1,-23.5m)+ \r\n<p>This is not a robust protocol, so <a href=\"#spurious\">spurious decodes</a> are likely.</p>\r\n\r\n<h2><a name=\"JVC\">JVC and JVC{2}</a></h2>\r\nUEI protocol: 0034\r\n<br>\r\nIRP notation: {38k,525}&lt;1,-1|1,-3&gt;(16,-8,(D:8,F:8,1,-45)+) <br>\r\nEFC translation: LSB comp\r\n<p>JVC{2} indicates a JVC signal from which the lead-in is missing.  The JVC protocol has\r\nlead-in on only the first frame, so it is quite easy to have it missing from a learned\r\nsignal.  So when JVC{2} is correct, it means the same as JVC.  But JVC{2} is not robust,\r\nso <a href=\"#spurious\">spurious decodes</a> are likely.  It\r\nis also very similar in structure and timing to <a href=\"#Mitsubishi\">Mitsubishi</a> protocol, so that\r\nDecodeIr has difficulty distinguishing one from the other.  The device number, OBC and EFC\r\nare all encoded the same way between the two.  So if you have JVC{2}\r\ndecodes that you have reason to suspect should actually be Mitsubishi, you can try using\r\nthem as Mitsubishi without changing the numbers.  However, true Mitsubishi signals will not\r\nmisdecode as JVC, just as JVC{2}.  So if some of the signals for your device decode as JVC\r\nand others as JVC{2}, you should trust all those decodes and not try Mitsubishi.</p>\r\n\r\n<h2><a name=\"JVC-48\">JVC-48</a></h2>\r\nUEI protocol: 001F or 00C9 or 00CD\r\n<br>\r\nIRP notation: {37k,432}&lt;1,-1|1,-3&gt;(8,-4,3:8,1:8,D:8,S:8,F:8,(D^S^F):8,1,-173)+ \r\n<br>\r\nEFC translation: LSB comp\r\n<p>JVC-48 is the member of the Kaseikyo family with OEM_code1=3 and OEM_code2=31.</p>\r\n<p>Panasonic protocol uses the same check byte rules as JVC-48, so you might want use the (more flexible)\r\nPanasonic entries in KM or RM to produce a JVC-48 upgrade (by changing the OEM_code1 and OEM_code2 values).  For simple\r\nJVC-48 upgrades you get exactly the same results by directly selecting the \"JVC-48\" protocol.</p>\r\n\r\n<h2><a name=\"JVC-56\">JVC-56</a></h2>\r\nIRP notation: {37k,432}&lt;1,-1|1,-3&gt;(8,-4,3:8,1:8,D:8,S:8,X:8,F:8,(D^S^X^F):8,1,-173)+\r\n \r\n<h2><a name=\"Kaseikyo\">Kaseikyo</a></h2>\r\n<p>Kaseikyo is a family of protocols that includes Panasonic, Mitsubishi-K, Fujitsu, Sharp-DVD and Teac-K.  Each\r\nprotocol in the Kaseikyo family is identified by two numbers, known as OEM_code1 and OEM_code2.</p>\r\n<p>\r\n  Most members of the family have minor structural differences from the generic \r\n  form. In those cases DecodeIR checks for the specific details (based on the \r\n  OEM codes) and if they are correct reports the protocol by name (see Panasonic \r\n  and Teak-K below). </p>\r\n<p>In the few cases where the structure exactly fits my understanding of the Kaseikyo spec,\r\nDecodeIR reports it as Kaseikyo-???-??? replacing the first ??? by the OEM_code1 and the second\r\n??? by the OEM_code2.</p>\r\n\r\n<h2><a name=\"Kaseikyo-???-???\">Kaseikyo-???-???</a></h2>\r\nIRP notation: \r\n{37k,432}&lt;1,-1|1,-3&gt;(8,-4,M:8,N:8,X:4,D:4,S:8,F:8,E:4,C:4,1,-173)+\r\n {X=M:4:0^M:4:4^N:4:0^N:4:4,C=D^S:4:0^S:4:4^F:4:0^F:4:4^E}\r\n<br>\r\nEFC translation: LSB comp\r\n<p>This is the nominal form of the Kaseikyo.\r\nIt is most commonly seen with OEM codes 170.90, which\r\nindicates \"Sharp\".  I assume (haven't tested) that the SharpDVD protocol in KM generates these\r\nKaseikyo-170-90 signals.  \r\nWe have also seen this protocol with OEM codes 3.32.  I'm not sure what manufacturer that indicates.</p>\r\n<p>The Kaseikyo protocol in KM seems to be designed to produce this nominal form of Kaseikyo for any\r\nspecified OEM codes and any constant value of E.  That should be the way to reproduce any Kaseikyo-???-???\r\ndecode other than SharpDVD, and might be better than SharpDVD for the Kaseikyo-170-90 signals.</p>\r\n\r\n<h2><a name=\"Kaseikyo56\">Kaseikyo56</a></h2>\r\nKaseikyo56 is a lengthened version of the Kaseikyo family of protocols.  It has the same OEM codes indicating \r\nthe same manufacturers as Kaseikyo, and it has the same variation (by manufacturer) in check byte and other \r\ndetails as Kaseikyo.\r\n\r\n<h2><a name=\"Kaseikyo56-???-???\">Kaseikyo56-???-???</a></h2>\r\nIRP notation: {37k,432}&lt;1,-1|1,-3&gt;(8,-4,M:8,N:8,H:4,D:4,S:8,X:8,F:8,E:4,C:4,1,-173)+ \r\n\r\n<h2><a name=\"Kathrein\">Kathrein</a></h2>\r\nUEI protocol: 0066\r\n<br>IRP notation: {38k,540}&lt;1,-1|1,-3&gt;(16,-8,D:4,~D:4,F:8,~F:8,1,^105m,(16,-8,F:8,1,^105m)+)\r\n<br>EFC translation: LSB comp\r\n<p>This protocol signals repeats by the use of <a href=\"#repeat\">dittos</a>.  It is unusual in that the ditto \r\n    frame carries part of the signal data, specifically the function code (OBC) but not the device code.</p>\r\n\r\n<h2><a name=\"Konka\">Konka</a></h2>\r\nUEI protocol: 019B\r\n<br>\r\nIRP notation: {38k,500,msb}&lt;1,-3|1,-5&gt;(6,-6,D:8,F:8,1,-8,1,-46)+ <br>\r\nEFC translation: MSB\r\n\r\n<h2><a name=\"Lumagen\">Lumagen</a></h2>\r\nIRP notation: {38.4k,416,msb}&lt;1,-6|1,-12&gt;(D:4,C:1,F:7,1,-26)+ {C = odd parity \r\nfor F} <br>\r\nEFC translation: MSB prepended with C bit.\r\n<p>This is a moderately robust protocol, but <a href=\"#spurious\">spurious decodes</a> are still possible.</p>\r\n\r\n<h2><a name=\"Lutron\">Lutron</a></h2>\r\nIRP notation: {40k,2300,msb}&lt;-1|1&gt;(255:8,X:24,0:4)+ <br>\r\nEFC translation: MSB of decoded signal.\r\n<p>This is an unusual protocol in that an 8-bit device code and 8-bit OBC are encoded in a 24-bit \r\n    error-correcting code as the X of the IRP notation.  This is constructed as follows.  First two parity \r\n    bits are appended to the 16 data bits to give even parity for the two sets of 9 bits taken alternately.  \r\n    The resulting 18-bit sequence is then treated as 6 octal digits (0-7) expressed in 3-bit binary code.  \r\n    These are then re-coded in the 3-bit Gray code (also called, more descriptively, the reflected-binary code) \r\n    with a parity bit to give odd parity, so giving 6 4-bit groups treated as a single 24-bit sequence.  The \r\n    whole thing allows any single-bit error in transmission to be identified and corrected.</p>\r\n\r\n<h2><a name=\"Matsui\">Matsui</a></h2>\r\nIRP notation: {38K,525}&lt;1,-1|1,-3&gt;(D:3,F:7,1,^30.5m)+ <br>\r\nEFC translation: Not available in this version of DecodeIr\r\n<p>This is not a robust protocol, so <a href=\"#spurious\">spurious decodes</a> are likely.</p>\r\n\r\n<h2><a name=\"MCE\">MCE (RC6-6-32)</a></h2>\r\nIRP notation: {36k,444,msb}&lt;-1,1|1,-1&gt;(6,-2,1:1,6:3,-2,2,OEM1:8,OEM2:8,T:1,D:7,F:8,-???)+\r\n<p>MCE is a member of the RC6 family.  Technically it is RC6-6-32 with the standard toggle bit zero, with the \r\n    OEM1 field equal to 128, and with a nonstandard (for the RC6 family) toggle bit added. If all those \r\n    rules are met, DecodeIr will display the name as \"MCE\" and with the OEM2 field moved to the \r\n    subdevice position.  Otherwise it will display RC6-6-32.</p>\r\n<p>As of version 8.31, KM does not have built-in support for this protocol, but there are KM format upgrade \r\n    files available for Media Center (built by an expert who isn't limited to KM's built-in protocols).  Those \r\n    upgrades should be adaptable to any RC6-6-32 code set (by changing the fixed data), if the one you have \r\n    doesn't already match the upgrade.</p>\r\n<p>RM version 1.16 has support for RC6-6-32, which can be used for MCE upgrades.  Version 1.17 will also have \r\n    direct support for MCE</p>\r\n<h2><a name=\"Metz19\">Metz19</a></h2>\r\nIRP notation: (37.9K,106,msb)&lt;4,-9|4,-16&gt;(8,-22,T:1,D:3,~D:3,F:6,~F:6,4,-125m)+ <br>\r\nThe toggle bit T is inverted each time a new button press occurs.\r\n\r\n<h2><a name=\"Mitsubishi\">Mitsubishi</a></h2>\r\nUEI protocol: 0014\r\n<br>\r\nIRP notation: {32.6k,300}&lt;1,-3|1,-7&gt;(D:8,F:8,1,-80)+ <br>\r\nEFC translation: LSB comp\r\n<p>This is not a robust protocol, so <a href=\"#spurious\">spurious decodes</a> are likely.  It\r\nis also very similar in structure and timing to <a href=\"#JVC\">JVC{2}</a> protocol, so that\r\nDecodeIr has difficulty distinguishing one from the other.  The device number, OBC and EFC\r\nare all encoded the same way between the two.  So if you have Mitsubishi\r\ndecodes that you have reason to suspect should actually be JVC, you can try using\r\nthem as JVC without changing the numbers.</p>\r\n\r\n<h2><a name=\"Mitsubishi-K\">Mitsubishi-K</a></h2>\r\nIRP notation: {37k,432}&lt;1,-1|1,-3&gt;(8,-4,35:8,203:8,X:4,D:8,S:8,F:8,T:4,1,-100)+ \r\n<br>\r\nEFC translation: not available yet\r\n<p>Mitsubishi-K is the member of the Kaseikyo family with OEM_code1=35 and OEM_code2=203.</p>\r\n\r\n<h2><a name=\"NEC\">NEC</a></h2>\r\nNEC is a family of similar protocols including NEC1, NEC2, Tivo, Pioneer, Apple, NECx1 and NECx2.\r\nIf you get a decode whose protocol name is\r\nsimply \"NEC\" that indicates the learned signal is not complete (usually caused by\r\nnot holding the original remote's button long enough during learning).  Enough of\r\nthe signal is present to accurately determine the device, subdevice and OBC numbers.\r\nBut not enough is present to determine whether the protocol is NEC1 or NEC2.\r\n<h3><a name=\"NEC12difference\">Difference between NEC1 and NEC2</a></h3>\r\nThe difference between NEC1 and NEC2 only affects the signal sent by a long\r\nkeypress.  A short press sends the same signal in NEC1 and NEC2.\r\n\r\n<h3><a name=\"Variant IRstreams in NEC protocols\">Variant IRstreams in NEC protocols</a></h3>\r\nFor NEC1, NEC2, NECx1, and NECx2 protocols, the IRstream contains D:8,S:8,F:8,~F:8 <br>\r\nHowever, some manufacturers (especially Yamaha and Onkyo) are breaking the \"rule\" that the 4th byte should be ~F:8<br>\r\nVersion 2.42 decodes these variants by adding suffixes to the protocol name depending on the IRstream:<br>\r\n-y1: D:8,S:8,F:8,~F:7,F:1:7  (complement all of F except the MSB)<br>\r\n-y2: D:8,S:8,F:8,F:1,~F:7:1  (complement all of F except the LSB)<br>\r\n-y3: D:8,S:8,F:8,F:1,~F:6:1,F:1:7  (complement all of F except MSB and LSB)<br>\r\n-f16: D:8,S:8,F:8,E:8  (no relationship between the 3rd and 4th bytes)<br>\r\n\r\n<h2><a name=\"NEC1\">NEC1</a></h2>\r\nIRP notation: {38.4k,564}&lt;1,-1|1,-3&gt;(16,-8,D:8,S:8,F:8,~F:8,1,-78,(16,-4,1,-173)*) \r\n<br>\r\nEFC translation: LSB comp\r\n<p>A few devices use NEC1 protocol at 40Khz, rather than the typical frequency.\r\nWhen getting a decode of NEC1, if you notice that the frequency is closer to 40Khz than to 38Khz,\r\nexamine multiple learns from the same device to estimate whether the 40Khz frequency is a\r\nlearning error or a true characteristic of the device. If the 40Khz is correct, there are\r\nmethods in JP1, or MakeHex (whichever you are using) to reproduce NEC1 at 40Khz rather than the\r\nusual frequency.</p>\r\n\r\n<h2><a name=\"NEC2\">NEC2</a></h2>\r\nIRP notation: {38.4k,564}&lt;1,-1|1,-3&gt;(16,-8,D:8,S:8,F:8,~F:8,1,-78)+ <br>\r\nEFC translation: LSB comp\r\n<p>Pioneer is distinguished from NEC2 only by frequency.  So if your learning system does not\r\nlearn frequency accurately, it won't accurately distinguish Pioneer from NEC2.  All Pioneer signals\r\nshould have a device number in the range 160 to 175 and no subdevice.  No NEC2 signal should fit those\r\nrules.  So you usually can determine whether the decision (by frequency) was wrong by checking the device numbers.</p>\r\n\r\n<h2><a name=\"NECx\">NECx</a></h2>\r\nIf you get a decode whose protocol name is\r\nsimply \"NECx\" that indicates the learned signal is not complete (usually caused by\r\nnot holding the original remote's button long enough during learning).  Enough of\r\nthe signal is present to accurately determining the device, subdevice and OBC numbers.\r\nBut not enough is present to determine the exact protocol, which is probably NECx1 or NECx2.  This\r\nincomplete learn also makes it harder to distinguish NEC from NECx, so a decode of \"NECx\"\r\nmight be NEC1 or NEC2 or even Tivo or Pioneer.\r\n\r\n<h2><a name=\"NECx1\">NECx1</a></h2>\r\nIRP notation: {38.4k,564}&lt;1,-1|1,-3&gt;(8,-8,D:8,S:8,F:8,~F8,1,^108m,(8,-8,D:1,1,^108m)*) <br>\r\nEFC translation: LSB comp\r\n<br>  Most, but not all NECx1 signals have S=D\r\n\r\n<h2><a name=\"NECx2\">NECx2</a></h2>\r\nIRP notation: {38.4k,564}&lt;1,-1|1,-3&gt;(8,-8,D:8,S:8,F:8,~F8,1,^108m)+ <br>\r\nEFC translation: LSB comp\r\n<br>  Most, but not all  NECx2 signals have S=D\r\n\r\n<h2><a name=\"Nokia\">Nokia</a></h2>\r\nIRP notation: {36k,msb}&lt;164,-276|164,-445|164,-614|164,-783&gt;(412,-276,D:8,S:8,F:8,164,-???)+ \r\n<br>\r\nEFC translation: MSB\r\n\r\n<h2><a name=\"Nokia12\">Nokia12</a></h2>\r\nIRP notation: {36k,msb}&lt;164,-276|164,-445|164,-614|164,-783&gt;(412,-276,D:4,F:8,164,-???)+ \r\n<br>\r\nEFC translation: MSB\r\n\r\n<h2><a name=\"Nokia32\">Nokia32</a></h2>\r\nUEI protocol: 0173\r\n<br>\r\nIRP notation: {36k,msb}&lt;164,-276|164,-445|164,-614|164,-783&gt;(412,-276,D:8,S:8,X:8,F:8,164,^100m)+ \r\n<br>\r\nEFC translation: MSB\r\n\r\n<h2><a name=\"NRC16\">NRC16</a></h2>\r\nDocumentation not written yet.\r\n\r\n<h2><a name=\"NRC17\">NRC17</a></h2>\r\nUEI protocol: 00BD\r\n\r\n<h2><a name=\"OrtekMCE\">OrtekMCE</a></h2>\r\nUEI protocol: not known.\r\n<br>\r\nIRP notation: {38.6k,480}&lt;1,-1|-1,1&gt;(4,-1,D:5,P:2,F:6,C:4,-48m)+<br>\r\nEFC translation: 6-bit LSB comp\r\n<p>The <a href=\"#repeat\">repeat frames</a> are not all identical. P is a\r\n position code: 0 for the start frame of a repeat sequence, 2 for the \r\nend frame and 1 for all frames in between. C is a checksum, 3 more than \r\nthe number of 1 bits in D, P, F together.  DecodeIR v2.37\r\nand later check P and will report in the Misc field if either the start \r\nor end frame, or both, is/are missing.</p>\r\n\r\n<h2><a name=\"Pace MSS\">Pace MSS</a></h2>\r\nIRP notation: {38k,630,msb}&lt;1,-7|1,-11&gt;(1,-5,1,-5,T:1,D:1,F:8,1,^120m)+ \r\n<br>\r\nEFC translation: Not available in this version of DecodeIr\r\n<p>This is a moderately robust protocol, but <a href=\"#spurious\">spurious decodes</a> are still possible.</p>\r\n\r\n<h2><a name=\"Panasonic\">Panasonic</a></h2>\r\nUEI protocol: 001F or 00C9 or 00CD\r\n<br>\r\nIRP notation: {37k,432}&lt;1,-1|1,-3&gt;(8,-4,2:8,32:8,D:8,S:8,F:8,(D^S^F):8,1,-173)+ \r\n<br>\r\nEFC translation: LSB comp\r\n<p>Panasonic protocol is the most commonly seen member of the Kaseikyo family</p>\r\n  <p>OEM_code1 is 2 and OEM_code2 is 32 (or DecodeIr won't display the name as \"Panasonic\"). \r\n    So those values in KM or RM can be changed from the default 2 and 32 only \r\n    when using the Panasonic entry in KM or RM to produce some Kaseikyo variant \r\n    OTHER THAN Panasonic. When creating a Panasonic upgrade, don't change those \r\n    from the default values.</p>\r\n\r\n<h2><a name=\"Panasonic2\">Panasonic2</a></h2>\r\nIRP notation: {37k,432}&lt;1,-1|1,-3&gt;(8,-4,2:8,32:8,D:8,S:8,X:8,F:8,(D^S^X^F):8,1,-173)+ \r\n\r\n<h2><a name=\"Panasonic_Old\">Panasonic_Old</a></h2>\r\nUEI protocol: 0000\r\n<br>\r\nIRP notation: {57.6k,833}&lt;1,-1|1,-3&gt;(4,-4,D:5,F:6,~D:5,~F:6,1,-???)+ <br>\r\nEFC translation: 6-bit LSB comp with 2-bit mini-combo\r\n<p>Lists three different EFCs because this protocol is a <a href=\"#mini%20combo\">mini combo</a>.</p>\r\n\r\n<h2><a name=\"PCTV\">PCTV</a></h2>\r\nIRP notation: {38.4k,832}&lt;0,-1|1,-0&gt;(2,-8,1,D:8,F:8,2,-???) \r\n\r\n<h2><a name=\"pid-0001\">pid-0001</a></h2>\r\nUEI protocol: 0001\r\n<br>IRP notation:  {0k,msb}&lt;24,-9314|24,-13486&gt;(24,-21148,(F:5,1,-28m)+)\r\n<br>EFC translation: 5-bit MSB comp\r\n<p>As of version 8.31 KM has seriously wrong OBC translation for pid-0001, so use only EFC's with KM.</p>\r\n\r\n<h2><a name=\"pid-0003\">pid-0003</a></h2>\r\nUEI protocol: 0003\r\n<br>IRP notation:  {40.2k,389}&lt;2,-2|3,-1&gt;(F:8,~F:8,^102k)+\r\n<br>EFC translation: LSB\r\n\r\n<h2><a name=\"pid-0004\">pid-0004</a></h2>\r\nUEI protocol: 0004\r\n<br>IRP notation:  {0k,msb}&lt;12,-130|12,-372&gt;(F:6,12,-27k)+\r\n<br>EFC translation: 6-bit MSB comp\r\n\r\n<h2><a name=\"pid-002A\">pid-002A</a></h2>\r\nUEI protocol: 002A\r\n<br>IRP notation: {0k,10}&lt;1,-5|1,-15&gt;(1,-25, D:5,F:6, 1,-25,1,120m)+\r\n<br>EFC translation: 6-bit LSB comp\r\n<br> Used primarily in Barco remotes.\r\n<p>This is a moderately robust protocol, but <a href=\"#spurious\">spurious decodes</a> are still possible.</p>\r\n\r\n<h2><a name=\"pid-0083\">pid-0083</a></h2>\r\nUEI protocol: 0083\r\n<br>EFC translation: 5-bit MSB comp\r\n<br>IRP notation: {42.3K, 3000}&lt;1,-3,1,-7|1,-7,1,-3&gt;(F:5,1,-27)+\r\n<p>This protocol is a very limited design.  We have seen it used only in the UEI setup code TV/0159,\r\nwhich is for some TVs brand named Fisher, Sanyo and Sears.  It is not likely that any other code\r\nset uses this protocol.  So if you get a correct decode of pid-0083 you probably have a TV that\r\ncan be controlled by the TV/0159 setup code.</p>\r\n<p>As of version 8.31, KM does not translate OBC to EFC according to\r\nthe same rules used by DecodeIr.  RM does translate consistently with DecodeIr, so you may find\r\nit easier to use RM.  If you use KM, you should use the EFC number from the decode not the OBC number.\r\nPid-0083 protocol\r\nuses the same EFC numbering across all JP1 remotes, so use of EFC is safe.  KM uses different\r\nOBC numbering than RM and DecodeIr, so use of OBCs isn't safe.</p>\r\n\r\n<h2><a name=\"Pioneer\">Pioneer</a></h2>\r\nIRP notation: {40k,564}&lt;1,-1|1,-3&gt;(16,-8,D:8,S:8,F:8,~F:8,1,-78)+ <br>\r\nEFC translation: LSB comp\r\n<p>Pioneer is distinguished from NEC2 only by frequency.  So if your learning system does not\r\nlearn frequency accurately, it won't accurately distinguish Pioneer from NEC2.  All Pioneer signals\r\nshould have a device number in the range 160 to 175 and no subdevice.  No NEC2 signal should fit those\r\nrules.  So you usually can determine whether the decision (by frequency) was wrong by checking the device numbers.</p>\r\n  <p>Many Pioneer commands are sent as combinations of two different Pioneer signals. \r\n    This version of DecodeIr does not associate the two signals together into \r\n    one command. It decodes them separately. If you get more than one of the same \r\n    OBC from decoding a learned signal, that just means the learning system failed \r\n    to understand the repeat pattern. It does not mean a two part signal. But \r\n    if there are two different OBCs (with the same or different device numbers) \r\n    you have a two part Pioneer signal.</p>\r\n<p>Including a two part Pioneer signal in a KeyMove or upgrade is a complex process that requires a good\r\nunderstanding of Pioneer signals and of the Pioneer support in KM.  The signals don't vary much among related Pioneer models.\r\nSo the best way to get an upgrade or hex cmd including such signals is to look through existing Pioneer upgrades in\r\nthe JP1 group and find one that already includes the same (or nearly same) signal.</p>\r\n\r\n<h2><a name=\"Proton\">Proton</a></h2>\r\nUEI protocol: 005C\r\n<br>\r\nIRP notation: {38k,500}&lt;1,-1|1,-3&gt;(16,-8,D:8,1,-8,F:8,1,^63m)+ <br>\r\nEFC translation: LSB comp\r\n<p>This is not a robust protocol, so <a href=\"#spurious\">spurious decodes</a> are likely.</p>\r\n\r\n<h2><a name=\"RC5\">RC5</a></h2>\r\nUEI protocol: 00E8\r\n<br>\r\nIRP notation: {36k,msb,889}&lt;1,-1|-1,1&gt;(1:1,~F:1:6,T:1,D:5,F:6,^114m)+ <br>\r\nEFC translation: 6-bit MSB comp with 2-bit mini-combo\r\n<p>Lists three different EFCs because this protocol is a <a href=\"#mini%20combo\">mini combo</a>.</p>\r\n  <p>What we call \"device\" is really the \"System\" and what we \r\n    call \"OBC\" is really the \"Command\". If you are using ProntoEdit \r\n    to create the RC5 signals directly, that GUI uses that correct (System and \r\n    Command) Philips terminology.</p>\r\n\r\n\r\n<h2><a name=\"RC5-7F\">RC5-7F</a></h2>\r\nUEI protocol: 0182\r\n<br>\r\nIRP notation: {36k,msb,889}&lt;1,-1|-1,1&gt;(1:1, D:1:5,T:1,D:5,F:7,^114m)+ <br>\r\nEFC translation: 7-bit MSB comp\r\n\r\n<h2><a name=\"RC5-7F-57\">RC5-7F-57</a></h2>\r\nUEI protocol: 0182\r\n<br>\r\nIRP notation: {57k,msb,889}&lt;1,-1|-1,1&gt;(1:1, D:1:5,T:1,D:5,F:7,^114m)+ <br>\r\nEFC translation: 7-bit MSB comp\r\n\r\n<h2><a name=\"RC5x\">RC5x</a></h2>\r\nUEI protocol: 00F2\r\n<br>\r\nIRP notation: {36k,msb,889}&lt;1,-1|-1,1&gt;(1:1,~S:1:6,T:1,D:5,-4,S:6,F:6,^114m)+ \r\n<br>\r\nEFC translation: NONE\r\n<p>The official (UEI) protocol executor for RC5x does not support EFC numbers.  If you are creating an\r\nupgrade in KM or RM you should use OBC numbers, not EFC numbers.  If you need the Hex Cmd for a KeyMove,\r\nyou should use the functions sheet of KM or RM to compute it for you from the OBC and subdevice number.</p>\r\n<p>In the functions sheet in KM you must put the subdevice number in the byte2 column, which KM calls \r\n    \"unit code\".</p>\r\n  <p>What we call \"Device\" is really the \"System\". What we call \r\n    Subdevice is really the \"Command\". What we call \"OBC\" \r\n    is really the \"Data\". If you are using ProntoEdit to create the \r\n    RC5 signals directly, that GUI uses that correct (System, Command and Data) \r\n    Philips terminology.</p>\r\n\r\n<h2><a name=\"RC5-?-??\">RC5-?-??</a></h2>\r\nJust ignore this decode.  It is almost certainly <a href=\"#spurious\">spurious</a>.  In case there is a new \r\nprotocol I don't know about yet in the family with RC5 and StreamZap, it will decode in this form producing \r\ndata to help me understand that protocol.\r\n\r\n<h2><a name=\"RC6\">RC6</a></h2>\r\nUEI protocol: 0058\r\n<br>IRP notation: {36k,444,msb}&lt;-1,1|1,-1&gt;(6,-2,1:1,0:3,&lt;-2,2|2,-2&gt;(T:1),D:8,F:8,^107m)+\r\n<br>EFC translation: MSB\r\n<p>RC6 is the name used for the first member of the RC6 family of protocols.  Technically this is\r\nRC6-0-16, but DecodeIr will always display that as simply \"RC6\"</p>\r\n\r\n<h2><a name=\"RC6-6-20\">RC6-6-20</a></h2>\r\nIRP notation: {36k,444,msb}&lt;-1,1|1,-1&gt;(6,-2,1:1,6:3,&lt;-2,2|2,-2&gt;(T:1),D:8,S:4,F:8,-???)+\r\n<br>EFC translation: MSB\r\n<p>This protocol is commonly used in Sky and Sky+ remotes.  As of version 8.31, KM does not have built-in support\r\nfor this protocol, but there are KM format upgrade files available for Sky and Sky+ (built by an expert who isn't limited\r\nto KM's built-in protocols). RM has built-in support for RC6-M-20n protocol, which can be used to make Sky and Sky+\r\nupgrades (or any other RC6-6-20 upgrades as long as the T bit is the same for all learned signals, as it is with Sky).\r\nTo use RC6-M-20n for RC6-6-20, you must leave the M field in RM's setup sheet with its default value of 6, and you\r\nmust set or leave the T field (if present) to the value shown in all the decodes (which I assume will be 0).</p>\r\n\r\n<h2><a name=\"RC6-?-??\">RC6-?-??</a></h2>\r\nIRP notation: {36k,444,msb}&lt;-1,1|1,-1&gt;(6,-2,1:1,M:3,&lt;-2,2|2,-2&gt;(T:1),???:??)+\r\n  <p>This is the generic form for a decode of protocols in the RC6 family. DecodeIr \r\n    uses this form for all RC6 decodes, except RC6-0-16 which is displayed as \r\n    simply \"RC6\", RC6-6-24 which is displayed as \"Replay\" \r\n    and some RC6-6-32 which display as MCE.</p>\r\n<p>The first ? in the protocol name is the M value in the RC6 spec.  The ending ?? represents the number of data bits\r\nin the signal.</p>\r\n\r\n<h2><a name=\"RCA\">RCA and RCA(Old)</a></h2>\r\nUEI protocols: 00AF (RCA), 002D(RCA(Old)) and 0114 (RCA Combo)\r\n<br>IRP notation for RCA: {58k,460,msb}&lt;1,-2|1,-4&gt;(8,-8,D:4,F:8,~D:4,~F:8,1,-16)+\r\n<br>IRP notation for RCA(Old): {58k,460,msb}&lt;1,-2|1,-4&gt;(32,(8,-8,D:4,F:8,~D:4,~F:8,2,-16)+)\r\n<br>EFC translation: MSB\r\n<p>These are two very similar forms of RCA protocol which differ only in\r\n that RCA(Old) has an extended lead-in \r\nand a double-length ON pulse before the lead-out.  They are so similar \r\nthat most RCA devices will accept either.  \r\nBut some RCA devices only accept the one that really matches their own \r\nremote.\r\nIn versions of DecodeIR prior to v2.40, RCA(Old) was decoded as a frame \r\nof RCA{1} followed usually by a frame of RCA.  The second frame now no \r\nlonger appears, so the protocol has been renamed to correspond to that \r\nused in KM and RM.</p>\r\n\r\n<h2><a name=\"RCA-38\">RCA-38 and RCA-38(Old)</a></h2>\r\nUEI protocol: not known\r\n<br>IRP notation for RCA-38: {38.7k,460,msb}&lt;1,-2|1,-4&gt;(8,-8,D:4,F:8,~D:4,~F:8,1,-16)+\r\n<br>IRP notation for RCA-38(Old): {38.7k,460,msb}&lt;1,-2|1,-4&gt;(32,(8,-8,D:4,F:8,~D:4,~F:8,2,-16)+)\r\n<br>EFC translation: MSB\r\n<p>These are recently discovered variants of the RCA protocol.  They differ from RCA and RCA(Old) only in the \r\n    frequency, which is 38.7kHz instead of the standard 58kHz.</p>\r\n\r\n<h2><a name=\"RECS80\">RECS80</a></h2>\r\nUEI protocol: 0045, 0068, 0090 or ???\r\n<br>IRP notation for 0045: {38k,158,msb}&lt;1,-31|1,-47&gt;(1:1,T:1,D:3,F:6,1,-45m)+\r\n<br>IRP notation for 0068: {33.3k,180,msb}&lt;1,-31|1,-47&gt;(1:1,T:1,D:3,F:6,1,^138m)+\r\n<br>EFC translation: 6-bit MSB comp\r\n<p>RECS80 is a family of related protocols with the same structure, but different timing.  See also\r\nVelleman </p>\r\n<p>These are moderately non robust protocols, so <a href=\"#spurious\">spurious decodes</a> are possible.</p>\r\n<p>The timing differences are not definitive enough for DecodeIr to identify which RECS80\r\nversion is which.  Instead it displays the timing information in the \"Misc\" field of the\r\noutput.  That will be three numbers formatted as in this example: (157/5048/7572).</p>\r\n<p>Using those three numbers and the frequency, you should be able to determine whether\r\nthe signals fit the 0045 version, the 0068 version, the 0090 version or none of them.  You should look at all\r\nthe learned signals for your device together when doing that.  A single device won't mix\r\nversions of RECS80, so any differences in frequency or timing between learns is\r\ndue to the IR learning process, not due to any differences among the correct signals.  You\r\nshould find one RECS80 version that is a good enough fit for all signals of the device.</p>\r\n<p>For 0045,</p>\r\n<ul>\r\n<li>frequency should be between 37000 and 39000</li>\r\n<li>first timing number between 100 and 200</li>\r\n<li>second timing number between 4500 and 5500</li>\r\n<li>third timing number between 6800 and 8300</li>\r\n</ul>\r\n<p>For 0068,</p>\r\n<ul>\r\n<li>frequency should be between 32300 and 34300</li>\r\n<li>first timing number between 130 and 250</li>\r\n<li>second timing number between 5100 and 6300</li>\r\n<li>third timing number between 7700 and 9500</li>\r\n</ul>\r\n<p>For 0090,</p>\r\n<ul>\r\n<li>frequency should be 0</li>\r\n<li>first timing number between 0 and 40</li>\r\n<li>second timing number between 4500 and 5500</li>\r\n<li>third timing number between 6800 and 8300</li>\r\n</ul>\r\n<p>You may find decodes that don't quite fit either.  If it almost fits, it may\r\nbe worth testing to see if it works, but it's most unlikely to work if the\r\nsecond timing number is above the suggested max or the third timing number\r\nis below the suggested min.  For example, I found a decode with frequency\r\n41879 and timing numbers (132,5092,7652).  The three timing numbers are\r\nperfect for protocol 0045, but the frequency is quite wrong.  I have no\r\ndevice to test with, but my guess is that it would work anyway.  For\r\nprotocol 0068, the third number 7652 is below the minimum of 7700 making\r\nit quite unlikely to work.  I found a different device with frequency\r\n33333 and timing (450,5770,8656).  For 0068 all but the first number are\r\nperfect and I would be quite surprised if it didn't work.  For 0045 the second\r\nnumber 5770 is too high for the max of 5500, so it's unlikely to work.</p>\r\n<p>The decodes for RECS80 all report EFCs for protocol 0045.  These are not\r\ncorrect EFCs if you select a protocol other than 0045, so it is better to\r\nuse OBC numbers when creating a JP1 upgrade based on these decodes.</p>\r\n\r\n<h2><a name=\"Replay\">Replay</a></h2>\r\nUEI protocol: 0092\r\n<br>IRP notation: {36k,444,msb}&lt;-1,1|1,-1&gt;(6,-2,1:1,6:3,&lt;-2,2|2,-2&gt;(T:1),D:8,S:8,F:8,-???)+\r\n<br>EFC translation: MSB\r\n<p>Replay is a member of the RC6 family.  Technically it is RC6-6-24, but DecodeIr will always\r\ndisplay the name as \"Replay\".  ProntoEdit calls this protocol \"RC6 mode 6A\" and KM has it under the\r\nalternate name \"RC-6a\" as well as its primary name \"Replay\".  RM has it under the alternate name \"RC6-M-24n\" as\r\nwell as its primary name \"Replay\".</p>\r\n<p>DecodeIr's Subdevice field in  is called \"unit\" in KM</p>\r\n<p>In ProntoEdit, DecodeIr's \"Device\" is called \"Customer Code\"; DecodeIr's \"Subdevice\" is called \"System\";\r\nand DecodeIr's \"OBC\" is called \"Command\".</p>\r\n\r\n<h2><a name=\"Samsung20\">Samsung20</a></h2>\r\nIRP notation: {38.4k,564}&lt;1,-1|1,-3&gt;(8,-8,D:6,S:6,F:8,1,^???)+\r\n<br>EFC translation: LSB\r\n<p>This is a moderately robust protocol, but <a href=\"#spurious\">spurious decodes</a> are still possible.</p>\r\n\r\n\r\n<h2><a name=\"Samsung36\">Samsung36</a></h2>\r\nUEI protocol: 01B5\r\n<br>IRP notation: {38k,500}&lt;1,-1|1,-3&gt;(9,-9,D:8,S:8,1,-9,E:4,F:8,-68u,~F:8,1,-118)+\r\n<br>EFC translation: LSB\r\n\r\n<h2><a name=\"Sampo\">Sampo</a></h2>\r\nIRP notation: {38.4k, 833}&lt;1,-1|1,-3&gt;(4,-4,D:6,F:6,S:6,~F:6,1,-39)+\r\n<br>EFC translation: Not available in this version of DecodeIr\r\n<p>This is a moderately robust protocol, but <a href=\"#spurious\">spurious decodes</a> are still possible.</p>\r\n\r\n<h2><a name=\"ScAtl-6\">ScAtl-6</a></h2>\r\nUEI protocol: 0078\r\n<br>IRP notation: {57.6k,846}&lt;1,-1|1,-3&gt;(4,-4,D:6,F:6,~D:6,~F:6,1,-40)+\r\n<br>EFC translation: 6-bit LSB comp\r\n  <p>ScAtl-6 is distinguished from Emerson only by frequency. So if you are using \r\n    a learning system that doesn't record the frequency accurately, then DecodeIr \r\n    can't accurately select between Emerson and ScAtl-6.</p>\r\n<p>In KM, this protocol is named \"Scientific Atlanta\".  Most Scientific Atlanta cable tuners use Panasonic_Old\r\nprotocol, not this protocol.</p>\r\n\r\n<h2><a name=\"Sejin-M-38\">Sejin-<i>M</i>-38 and Sejin-<i>M</i>-56</a></h2>\r\nUEI protocol: 0161\r\n<br>\r\nIRP notation for Sejin-<i>M</i>-38: {38.8k,310,msb}&lt;-1|1&gt;(&lt;8:4|4:4|2:4|1:4&gt;(3,3:2,Dx:8,Fx:8,Fy:8,E:4,C:4,-L))+ \r\n<br>\r\nIRP notation for Sejin-<i>M</i>-56: {56.3k,310,msb}&lt;-1|1&gt;(&lt;8:4|4:4|2:4|1:4&gt;(3,3:2,Dx:8,Fx:8,Fy:8,E:4,C:4,-L))+ \r\n<br>\r\nIn both cases E is a checksum seed (0 in all known examples) and C is a checksum given by\r\n<br>C = Dx:4 + Dx:4:4 + Fx:4 + Fx:4:4 + Fy:4 + Fy:4:4 + E.\r\n<br>EFC translation: For Sejin-1, MSB.  For Sejin-2, EFC translation not available.\r\n<p>The parameter <i>M</i> is either 1 or 2. It distinguishes two styles \r\nof this protocol that have different purposes and very different \r\nlead-out times L.  The 8-bit parameter Dx is a signed integer.  If Dx \r\n&gt; 0 then the style is Sejin-1, used for normal buttons of a remote \r\ncontrol.  If Dx &lt; 0 then the style is Sejin-2, used for signals of an\r\n associated 2- or 3-button pointing device.  E is a checksum seed, E=0 \r\nin the only known examples.  The checksum formula reflects that in the \r\nUEI executor, so is\r\npresumed correct.</p>\r\n\r\n<p>The protocol parameters Dx, Fx, Fy translate into device parameters \r\nin different ways corresponding to the different uses of the protocol.  \r\nIn Sejin-1 the device parameters are a Device Code, a SubDevice code and\r\n an OBC as is common for many protocols.  Sejin-2 has two sub-styles. \r\nOne corresponds to the displacement of a cursor or other pointer with \r\ndevice parameters (X, Y) that\r\ngive the horizontal and vertical components of the displacement (and \r\nwhich can be positive or negative).  The other signals Button Up or \r\nButton Down for any of the three buttons of the pointing device.  The \r\nMisc field of the DecodeIR output displays these device parameters for \r\nthe Sejin-2 signals.  The relationship between these and the protocol \r\nparameters is beyond the\r\nscope of this document.  The Misc field also displays an RMOBC value for\r\n Sejin-2 signals, which is an artificial OBC value that can be used as \r\ninput to RemoteMaster to create the signal concerned.</p>\r\n\r\n<p>The protocol parameters for Sejin-1 include a bit that marks the end frame of a <a href=\"#repeat\">repeat \r\n   sequence</a>.  DecodeIR v2.37 and later check this and will report in the Misc field if the end frame is \r\n   missing.  This will normally be due to the key still being held when the learning process ends, so that \r\n   the end frame gets omitted from the learned signal.  For Sejin-2 signals that represent button operations \r\n   the signal does not repeat.  A single frame is sent on button down, a different frame is sent once on \r\n   button up.  Both frames can be detected and distinguished by DecodeIR v2.37 and later but the button up \r\n   frame will not normally be present in a learned signal.</p>\r\n\r\n<h2><a name=\"Sharp\">Sharp, Sharp{1} and Sharp{2}</a></h2>\r\nIRP notation: {38k,264}&lt;1,-3|1,-7&gt;(D:5,F:8,1:2,1,-165,D:5,~F:8,2:2,1,-165)+\r\n<br>EFC translation: LSB\r\n  <p>A Sharp signal has two halves, either one of which is enough to fully decode \r\n    the information. A significant fraction of Sharp learned signals contain just \r\n    one half or have the halves separated so that DecodeIr can't process them \r\n    together. When one half is seen separate from the other, DecodeIr will name \r\n    the protocol Sharp{1} or Sharp{2} depending on which half is decoded. Sharp, \r\n    Sharp{1} and Sharp{2} all represent the same protocol when they are correct. \r\n    But only Sharp is robust. A Sharp{1} or Sharp{2} decode might be <a href=\"#spurious\">spurious</a>.</p>\r\n\r\n\r\n<h2><a name=\"SharpDVD\">SharpDVD</a></h2>\r\nUEI protocol: 00F8\r\n<br>\r\nIRP notation: {38k,400}&lt;1,-1|1,-3&gt;(8,-4,170:8,90:8,15:4,D:4,S:8,F:8,E:4,C:4,1,-48)+ {E=1,C=D^S:4:0^S:4:4^F:4:0^F:4:4^E:4}\r\n<br> EFC translation: LSB comp\r\n<p>SharpDVD is the member of the Kaseikyo family with OEM_code1=170 and OEM_code2=90.</p>\r\n\r\n<h2><a name=\"SIM2\">SIM2</a></h2>\r\nIRP notation: {38.8k,400}&lt;3,-3|3,-7&gt;(6,-7,D:8,F:8,3,-60m)\r\n\r\n<h2><a name=\"Solidtek16\">Solidtek16</a></h2>\r\nIRP notation: {38k}&lt;-624,468|468-624&gt;(1820,-590,0:1,D:4,F:7,S:1,C:4,1:1,-???) \r\n<p>\r\nThis is a KeyBoard protocol.  The make/break bit is decoded into the subdevice field.</p>\r\n\r\n<h2><a name=\"Solidtek20\">Solidtek20</a></h2>\r\nIRP notation: {38k}&lt;-624,468|468-624&gt;(1820,-590,0:1,D:4,S:6,F:6,C:4,1:1,-???) \r\n<p>\r\nThis is a mouse protocol.  The button press info is included in the Device field.  The horizontal motion\r\nis in the Subdevice field, and the vertical motion is in the OBC field.</p>\r\n<p>The decode interface does not support returning negative Subdevice or OBC.  So negative motions are\r\nrepresented by adding 64 to them.  The numbers 1 to 31 represent positive motion.  The numbers 32 to 63\r\nare each 64 larger than the true negative motion, so 63 represents -1 and 32 represents -32.</p>\r\n\r\n<h2><a name=\"Somfy\">Somfy</a></h2>\r\nIRP notation: {35.7k}&lt;308,-881|669,-520&gt;(2072,-484,F:2,D:3,C:4,-2300)+\r\n<br>C is reported as SubDevice.  It is probably a check nibble {C = F*4 + D + 3}.\r\n<br>F = 1 for UP or 2 for DOWN.\r\n<br>D = 1, 2 or 3 for the three observed devices, or D = 0 to control all devices together.\r\n\r\n<h2><a name=\"Sony8\">Sony8</a></h2>\r\nIRP notation: {40k,600}&lt;1,-1|2,-1&gt;(4,-1,F:8,^22200)\r\n<br>EFC translation: LSB.\r\n\r\n<h2><a name=\"Sony12\">Sony12</a></h2>\r\nUEI protocol: 00CA\r\n<br>IRP notation: {40k,600}&lt;1,-1|2,-1&gt;(4,-1,F:7,D:5,^45m)+\r\n<br>EFC translation: LSB.\r\n\r\n<h2><a name=\"Sony15\">Sony15</a></h2>\r\nUEI protocol: 00CA\r\n<br>IRP notation: {40k,600}&lt;1,-1|2,-1&gt;(4,-1,F:7,D:8,^45m)+\r\n<br>EFC translation: LSB.\r\n\r\n<h2><a name=\"Sony20\">Sony20</a></h2>\r\nUEI protocol: 00DE\r\n<br>IRP notation: {40k,600}&lt;1,-1|2,-1&gt;(4,-1,F:7,D:5,S:8,^45m)+\r\n<br>EFC translation: LSB.\r\n\r\n<h2><a name=\"StreamZap\">StreamZap</a></h2>\r\nIRP notation: {36k,msb,889}&lt;1,-1|-1,1&gt;(1:1,~F:1:6,T:1,D:6,F:6,^114m)+\r\n<br>DecodeIR V2.43 decodes this as RC5-7F\r\n<br>EFC translation: 6-bit MSB comp\r\n\r\n<h2><a name=\"StreamZap-57\">StreamZap-57</a></h2>\r\nIRP notation: {57k,msb,889}&lt;1,-1|-1,1&gt;(1:1,~F:1:6,T:1,D:6,F:6,^114m)+\r\n<br>DecodeIR V2.43 decodes this as RC5-7F-57\r\n<br>EFC translation: 6-bit MSB comp\r\n\r\n\r\n<h2><a name=\"Sunfire\">Sunfire</a></h2>\r\nIRP notation: (38k,560,msb)&lt;1,-1|3,-1&gt;(16,-8, D:4,F:8,~D:4,~F:8 -32)+\r\n<br>EFC translation: Not available in this version of DecodeIr\r\n\r\n<h2><a name=\"TDC-38\">TDC-38 and TDC-56</a></h2>\r\nIRP notation for TDC-38: {38k,315,msb}&lt;-1,1|1,-1&gt;(1:1,D:5,S:5,F:7,-89m)+\r\n<br>IRP notation for TDC-56:  {56.3k,213,msb}&lt;-1,1|1,-1&gt;(1:1,D:5,S:5,F:7,-89m)+\r\n<br>EFC translation: 7-bit MSB.\r\n<p>There are two variants of this protocol, with different frequencies but with the same number of carrier \r\n    cycles in each burst, which makes the duration of a burst also differ.  TDC-38 has a 38kHz carrier and is \r\n    used by Danish TDC IPTV.  TDC-56 has a 56.3kHz carrier and is used by Italian ALICE Home TV box.  These \r\n    implementations effectively use a 6-bit OBC as bit 0 of F is always the complement of bit 1, but there \r\n    are other implementations which do not follow that pattern.</p>\r\n\r\n<h2><a name=\"Teac-K\">Teac-K</a></h2>\r\nUEI protocol: 00BB\r\n<br>\r\nIRP notation: {37k,432}&lt;1,-1|1,-3&gt;(8,-4,67:8,83:8,X:4,D:4,S:8,F:8,T:8,1,-100,(8,-8,1,-100)+\r\n{T=D+S:4:0+S:4:4+F:4:0+F:4:4} <br>\r\nEFC translation: LSB comp, two parts\r\n<p>Teac-K is the member of the Kaseikyo family with OEM_code1=67 and OEM_code2=83.</p>\r\n<p>Teac-K uses different repeat rules and a different check byte than other Kaseikyo protocols.</p>\r\n<p>00BB requires 2-byte hex commands.  DecodeIr returns both hex cmd bytes through the interface that usually\r\nmeans one or the other (for mini combos) but in this case it means both.</p>\r\n<p>This protocol signals repeats by the use of <a href=\"#repeat\">dittos</a>.</p>\r\n\r\n<h2><a name=\"Thomson\">Thomson</a></h2>\r\nUEI protocol: 004B\r\n<br>IRP notation: {33k,500}&lt;1,-4|1,-9&gt;(D:4,T:1,D:1:5,F:6,1,^80m)+\r\n<br>EFC translation: 6-bit LSB comp, or that prepended with extra device bit.\r\n<p>This is not a robust protocol, so <a href=\"#spurious\">spurious decodes</a> are likely.</p>\r\n<p>DecodeIR2.42 deprecates Thompson (5 bits of device, and 6 bits of function) and reports these\r\n    signals as Thompson7 (4 bits of device and 7 bits of function).</p>\r\n<p>Thomson includes a <a href=\"#toggle\">toggle bit</a> so using learned signals will have\r\noperational problems.  You should use <a href=\"#jp1\">KeyMoves or Upgrades</a> based on the decoded values,\r\nrather than continue to use the learned signals.</p>\r\n  <p>There are two different variants of UEI protocol 004B which have different \r\n    EFC numbering. The decode lists both possible EFCs so you could experiment \r\n    to discover which is right for your model. But, if you are creating an upgrade \r\n    (rather than just KeyMoves) it is better to use RM and use the OBC numbers \r\n    from the decode (which are stable across models of JP1 remote). As of version \r\n    8.31, KM does not have support for Thomson protocol, so if you must make an \r\n    upgrade in KM you need to use pid:004B. For the URC-8040 and 8060 the second \r\n    decoded EFC should be right and the OBC values in KM should be wrong. For \r\n    most (maybe all) other models, the first decoded EFC should be right and KM's \r\n    default EFC to OBC translation should also be right.</p>\r\n\r\n<h2><a name=\"Thomson7\">Thomson7</a></h2>\r\nUEI protocol: 004B\r\n<br>IRP notation: {33k,500}&lt;1,-4|1,-9&gt;(D:4,T:1,F:7,1,^80m)+\r\n<br>EFC translation: 7-bit LSB comp\r\n<p>DecodeIR2.42 deprecates Thompson (5 bits of device, and 6 bits of function) and reports these\r\n    signals as Thompson7 (4 bits of device and 7 bits of function).</p>\r\n\r\n<h2><a name=\"Tivo\">Tivo</a></h2>\r\nIRP notation: {38.4k,564}&lt;1,-1|1,-3&gt;(16,-8,133:8,48:8,F:8,U:4,~F:4:4,1,-78,(16,-4,1,-173)*) \r\n<br>\r\nEFC translation: LSB comp\r\n\r\n<h2><a name=\"Velleman\">Velleman</a></h2>\r\nIRP notation: {38k,msb}&lt;700,-5060|700,-7590&gt;(1:1,T:1,D:3,F:6,1,-55m)+\r\n<br>EFC translation: 6-bit MSB comp\r\n<p>Very similar to RECS80-0045, except on duration is longer</p>\r\n\r\n<h2><a name=\"Velodyne\">Velodyne</a></h2>\r\nIRP notation: \r\n{38k,136,msb}&lt;210,-760&gt;(&lt;0:1|0:1,-1|0:1,-2|0:1,-3|0:1,-4|0:1,-5|0:1,-6|0:1,-7|0:1,-8|0:1,-9|0:1,-10|0:1,-11|0:1,-12|0:1,-13|0:1,-14|0:1,-15&gt;(S:4:4,C1:4,S:4,15:4,D:4,0:4,F:8,210u,-79m,S:4:4,C2:4,S:4,15:4,D:4,8:4,F:8,210u,-79m)+){C1=-(8+S+S::4+15+D+0+F+F::4),C2=-(8+S+S::4+15+D+8+F+F::4))\r\n<br> Velodyne is a close relative of XMP.  \r\n\r\n<h2><a name=\"Viewstar\">Viewstar</a></h2>\r\nUEI protocol: 0021\r\n<br>IRP notation: {50.5k,337}&lt;1,-8|1,-5&gt;(F:5,1,-17)+\r\n<br>EFC translation: 5-bit LSB comp\r\n<p>This is not a robust protocol, so <a href=\"#spurious\">spurious decodes</a> are likely.</p>\r\n\r\n<h2><a name=\"X10\">X10 and X10.<i>n</i></a></h2>\r\nUEI protocol: 003F (X10.<i>n</i>), 01DF (X10)\r\n<br>IRP notation for X10: {40.8k,565}&lt;2,-12|7,-7&gt;(7,-7,F:5,~F:5,21,-7)+\r\n<br>IRP notation for X10.<i>n</i>: {40.8k,565}&lt;2,-12|7,-7&gt;(F:5,N:-4,21,-7,(7,-7,F:5,~F:5,21,-7)+)\r\n<br>EFC translation: LSB of 2*OBC+1\r\n<p>These are two variants of the same Home Automation protocol.  They differ in that X10.<i>n</i> has a \r\n    distinctive start frame that carries a sequence number, the <i>n</i> of the protocol name, in addition \r\n    to the OBC.  The repeat frames, and all frames of the X10 version, only carry the OBC.  The value \r\n    of <i>n</i> runs from 0 to 15 (or some lower value) and then restarts again at 0.  It is incremented on \r\n    each successive keypress.  A valid X10.<i>n</i> signal must have at least one repeat frame.  If this is \r\n    missing then the Misc column shows \"invalid signal\".</p>\r\n<p>RemoteMaster has a single protocol, named X10 with PID 003F, that sends X10.<i>n</i> signals.  This is \r\n    the same as the UEI protocol with that PID.  There is no control over the value of <i>n</i>, this is \r\n    handled automatically by the remote.  The newer UEI protocol, with PID 01DF, sends X10 signals.</p>\r\n\r\n<h2><a name=\"XMP\">XMP, XMP-1 and XMP-2</a></h2>\r\nUEI protocol: 016C\r\n<br>IRP notation (without final frame): \r\n{38k,136,msb}&lt;210,-760&gt;(&lt;0:1|0:1,-1|0:1,-2|0:1,-3|0:1,-4|0:1,-5|0:1,-6|0:1,-7|0:1,-8|0:1,-9|0:1,-10|0:1,-11|0:1,-12|0:1,-13|0:1,-14|0:1,-15&gt;(T=0,(S:4:4,C1:4,S:4,15:4,OEM:8,D:8,210u,-13.8m,S:4:4,C2:4,T:4,S:4,F:16,210u,-80.4m,T=8)+)){C1=-(15+S+S::4+15+OEM+OEM::4+D+D::4),C2=-(15+S+S:4+T+F+F::4+F::8+F::12)}\r\n<br>IRP notation (with final \r\nframe):{38k,136,msb}&lt;210,-760&gt;(&lt;0:1|0:1,-1|0:1,-2|0:1,-3|0:1,-4|0:1,-5|0:1,-6|0:1,-7|0:1,-8|0:1,-9|0:1,-10|0:1,-11|0:1,-12|0:1,-13|0:1,-14|0:1,-15&gt;(T=0,((S:4:4,C1:4,S:4,15:4,OEM:8,D:8,210u,-13.8m,S:4:4,C2:4,T:4,S:4,F:16,210u,[-80.4m][-80.4m][-13.8m],T=8)+,T=9)2)){C1=-(S+S::4+15+OEM+OEM::4+D+D::4),C2=-(S+S:4+T+F+F::4+F::8+F::12)}\r\n<br>XMP uses one burst pair to encode numbers 0 to 15, with an on \r\nduration of 210uS, and off duration of 760uS + n*136uS where n takes on \r\nvalues of 0 to 15.\r\nThe checksum nibble is the complement of 15 plus the sum of the other 7 \r\nnibbles, mod 16\r\n\r\n<br><br>The Device code is D, the SubDevice code is S and there are two OBC values.  OBC1 is the high byte \r\nof F, OBC2 is the low byte of F. The OEM code is normally 0x44 and is reported in the Misc field only if it \r\nhas a different value. The XMP-1 protocol is XMP with OBC2 = 0.  The OBC field in DecodeIR then shows OBC1. \r\nThe XMP-2 protocol is XMP with OBC1 = 0.  The OBC field in DecodeIR then shows OBC2.\r\n<br><p>This protocol has a 4-bit toggle T that is 0 for the first frame and normally 8 for all repeat frames.  \r\n    There is, however, a variant in which a further frame with T=9 is sent after the button is released, \r\n    separated from the preceding frame by the short leadout of 13.8m that is used between two half-frames \r\n    rather than the long lead-out of 80.4m used at the end of all other frames.  When this frame is detected \r\n    then the Misc field displays \"With Final Frame\".  For this to be shown in a learned signal, the \r\n    button must be released before the learning process times out, so a short button press is needed.</p>\r\n\r\n<p>These are problem decodes because JP1 remotes don't typically learn these signals accurately enough\r\nfor a correct decode.  NG Prontos also do a rotten job of learning these signals.  Older Prontos seem to do\r\nfairly well.  DecodeIR v2.40 includes algorithms that attempt to reconstruct a valid XMP signal from a corrupt\r\nlearn, but it is impossible to correct all learning errors and there can be no certainty that a reconstruction\r\nis actually correct.</p>\r\n<p>In a correctly learned or fully reconstructed signal there will be an\r\n \"XMP\", \"XMP-1\" or \"XMP-2\" decode with device, subdevice and OBC values \r\nthat can be used with RemoteMaster or any similar\r\nprogram to regenerate a clean signal.  The Misc field shows which \r\nalgorithms, if any, have been applied, as a list in brackets after any \r\ndecode data in this field.  There are notes below on the reliability of \r\nthe various algorithms.  When the protocol shows as (unqualified) XMP, \r\nboth OBC values are non-zero.  The OBC and Hex fields show OBC1.  The \r\ncorresponding values for OBC2 are shown in the Misc field.</p>\r\n<p>The learned signal itself will certainly not be valid if any reconstruction algorithms have been applied and\r\nit may not be so even if it has been decoded without reconstruction.  The possible algorithm indicators in the \r\nMisc field are as follows:</p>\r\n<ul>\r\n<li>End (= Endpoint):  The lead-out burst is missing and has been inserted.  This is almost certainly correct.\r\n</li><li>Rec (= Recovery):  Look-ahead has been used to recover a \r\nmissing burst from the following repeat frame.  This is very likely to \r\nbe correct.\r\n</li><li>Cor (= Correction): Two bursts have been coalesced in the \r\nlearning process, e.g. those for hex digits C and D, causing a C to \r\nappear as D or vice versa.\r\nThe error has been identified and corrected.  This is probably correct.\r\n</li><li>Cal (= Calculated): A missing digit has been calculated from a \r\nchecksum.  The digit is probably correct but it may be in the wrong \r\nplace.  The most likely error in the reconstruction is that the two \r\ndigits of the OBC are the wrong way round.\r\n</li><li>Cal2 (= Calculated 2)  Two consecutive missing zero digits have\r\n been identified, corresponding to a zero OBC.  When this happens, the \r\nsignal will always be shown as XMP-1.  The most likely error in the \r\nreconstruction is that it should actually be XMP-2.\r\n</li></ul>\r\n<p>If a learned signal is good enough to be recognised as XMP but not good enough to be fully reconstructed, the\r\nprotocol will display with a name of the form\r\n<br><br>XMP:136.218-0F0F441A0A800F00\r\n<br><br>\r\n  In IR.exe you'll need to widen the Protocol column to see the whole thing. This \r\n  represents intermediate data from an unsuccessful attempt to decode a XMP signal. \r\n\r\n  The number in the position where the 136 is in this example represents the time scale.  A number (like this\r\nexample) that is near 137 is reasonable.  A number much further from 137 indicates a more serious learning or decoding\r\nproblem.\r\nThe number in the position where the .218 is in this example (it is not part of the 136) represents the level\r\nof inconsistency in the individual hex digit decodes.  A value greater than .100 means the hex digits aren't very\r\nreliable.</p>\r\n<p>The hex string, where the 0F0F441A0A800F00 is, is the decoded data.  At least one digit is almost certainly wrong or\r\nthe whole decode wouldn't be displayed in this form.  With a JP1 learning remote, the most common errors are that a\r\ndigit is actually missing, in which case the string will have fewer than 16 hex digits, or that two\r\nor more digits which are decoded the same are actually different, so some of them are correct and some are one value\r\nhigher or lower.  Although the reconstruction algorithms attempt to correct these types of errors, it is not always\r\npossible.  In this example I happen to know the correct signal.  One of the three F's is really an E and one\r\nof the two A's is really a 9.  The correct string is 0E0F441A09800F00.</p>\r\n<p>Almost all examples we've seen start with \"0E0F441A0\" or \"060F44120\".  But we've also seen upgrades from UEI for\r\n\"0D1F441A0\" and \"0C2F441A0\" and \"0B3F441A0\".\r\nThe last 4 digits of the whole 16 digit string (if they are correct) represent the Hex command needed to reproduce\r\nthe signal in a JP1 upgrade or KeyMove.  DecodeIR shows them as two 8-bit OBC values, as described with the IRP\r\nnotation above.</p>\r\n\r\n<h2><a name=\"XX\">XX</a></h2>\r\nDocumentation not written yet.\r\n\r\n<h2><a name=\"Zaptor\">Zaptor</a></h2>\r\nUEI protocol: unknown\r\n<br>IRP notation: {36k,330,msb}&lt;-1,1|1,-1&gt;[T=0] [T=0] [T=1] (8,-6,2,D:8,T:1,S:7,F:8,E:4,C:4,-74m)+ \r\n    {C = (D:4+D:4:4+S:4+S:3:4+8*T+F:4+F:4:4+E)&amp;15}\r\n<br>where T=0 for all frames except the last, T=1 for last frame, E is a checksum seed.  There is a 56KHz variant.\r\n<br>EFC translation: MSB\r\n<p>A protocol so far seen only in the Motorola Zaptor.  See also Amino</p>\r\n\r\n<h2><a name=\"Zenith\">Zenith</a></h2>\r\nUEI protocol: 0022\r\nIRP notation: {40k,520,msb}&lt;1,-10|1,-1,1,-8&gt;(S:1,&lt;1:2|2:2&gt;(F:D),-90m)+\r\n<br>Before Version 2.43, this document has shown the IRP notation as \r\n{40k,520,msb}&lt;1,-1,1,-8|1,-10&gt;(S:1,&lt;1:2|2:2&gt;(F:D),-90m)+\r\n<br>EFC translation: MSB \r\n<p>An unusual protocol, in that the number of bits in the function code is variable.  It is represented in \r\n    DecodeIR as the device code.  There are also two lead-in styles, decoded as subdevice values 0 and 1.  \r\n    Style 1 aka \"double-start\" is usually used in TV's, other appliances use 0 aka \"single start\".  If the \r\n    device code is &gt;8 then the bytes given in the Misc field as E = ... follow the OBC in the function \r\n    code value.</p>\r\n\r\n<h2><a name=\"?1-??-??-??\">?1-??-??-??</a></h2>\r\nAn experimental decode I added based on the thread at\r\n<a href=\"http://www.hifi-remote.com/forums/viewtopic.php?p=19168#19168\">JP1-forum\"Unknown \r\n    Protocol\"</a>\r\n\r\n</blockquote>\r\n<p>&nbsp;</p>\r\n<table width=\"750\"><tbody><tr><td><center>\r\n<script type=\"text/javascript\"><!--\r\ngoogle_ad_client = \"pub-2040680936936450\";\r\n/* 468x60, created 4/17/09 */\r\ngoogle_ad_slot = \"7283198346\";\r\ngoogle_ad_width = 468;\r\ngoogle_ad_height = 60;\r\n//-->\r\n</script>\r\n<script type=\"text/javascript\" src=\"Interpreting%20Decoded%20IR%20Signals%20%28v2.43%29-Dateien/show_ads.js\">\r\n</script>\r\n</center>\r\n</td></tr></tbody></table>\r\n\r\n</body></html>"
  },
  {
    "path": "examples/Convert_Old_Nec/Convert_Old_Nec.ino",
    "content": "/*\n Copyright (c) 2014 NicoHood\n See the readme for credit to other people.\n\n IRL Convert Old Nec\n Converts Nec Signals from the old format that Ken used\n with his library to the new bit order. Add your codes\n to the array, upload and open the Serial monitor.\n*/\n\nvoid setup() {\n  // Serial setup\n  while (!Serial);\n  Serial.begin(115200);\n  Serial.println(F(\"Startup\"));\n\n  // add your old code here\n  uint32_t oldcode[] = {\n    0x20DF0FF0,\n    0x20DF9E61,\n    0x20DFD02F,\n    0x20DFA956,\n    // ...\n  };\n\n  // go thorugh all entries\n  for (int i = 0; i < (sizeof(oldcode) / sizeof(uint32_t)); i++) {\n    uint32_t newcode = 0;\n    uint16_t command = 0;\n    uint16_t address = 0;\n\n    // print old code\n    Serial.print(oldcode[i], HEX);\n    Serial.print(F(\" --> 0x\"));\n\n    // LSB to MSB\n    for (uint8_t j = 0; j < 32; j++) {\n      newcode <<= 1;\n      newcode |= (oldcode[i] & 0x00000001);\n      oldcode[i] >>= 1;\n    }\n\n    // new code (address + command)\n    address = newcode & 0xFFFF;\n    command = (newcode >> 16);\n\n    // print new code\n    //Serial.print(newcode, HEX);\n    Serial.print(address, HEX);\n    Serial.print(F(\", 0x\"));\n    Serial.println(command, HEX);\n  }\n}\n\nvoid loop() {\n  // empty\n}"
  },
  {
    "path": "examples/NecAPI/NecAPI.ino",
    "content": "/*\n  Copyright (c) 2014-2017 NicoHood\n  See the readme for credit to other people.\n\n  IRL NecAPI\n\n  Receives IR NEC signals and decodes them with the API for better processing.\n\n  The following pins are usable for PinInterrupt or PinChangeInterrupt*:\n  Arduino Uno/Nano/Mini: All pins are usable\n  Arduino Mega: 10, 11, 12, 13, 50, 51, 52, 53, A8 (62), A9 (63), A10 (64),\n              A11 (65), A12 (66), A13 (67), A14 (68), A15 (69)\n  Arduino Leonardo/Micro: 8, 9, 10, 11, 14 (MISO), 15 (SCK), 16 (MOSI)\n  HoodLoader2: All (broken out 1-7) pins are usable\n  Attiny 24/44/84: All pins are usable\n  Attiny 25/45/85: All pins are usable\n  Attiny 13: All pins are usable\n  Attiny 441/841: All pins are usable\n  ATmega644P/ATmega1284P: All pins are usable\n\n  PinChangeInterrupts* requires a special library which can be downloaded here:\n  https://github.com/NicoHood/PinChangeInterrupt\n*/\n\n// Use HID Project for more keys and options\n#include \"HID-Project.h\"\n\n#define USBKEYBOARD BootKeyboard\n#define USBMOUSE BootMouse\n\n// include PinChangeInterrupt library* BEFORE IRLremote to acces more pins if needed\n//#include \"PinChangeInterrupt.h\"\n\n#include \"IRLremote.h\"\n\n// Choose a valid PinInterrupt or PinChangeInterrupt* pin of your Arduino board\n#define pinIR 2\nusing namespace IRL_Protek_Remote;\n\n// Choose the IR protocol of your remote. See the other example for this.\nvoid NecEvent(void);\nCNecAPI<NecEvent, IRL_ADDRESS> IRLremote;\n\n#define pinLed LED_BUILTIN\n\nvoid setup()\n{\n  // Start serial debug output\n  while (!Serial);\n  Serial.begin(115200);\n  Serial.println(F(\"Startup\"));\n\n  // Set LED to output\n  pinMode(pinLed, OUTPUT);\n\n  // Start reading the remote. PinInterrupt or PinChangeInterrupt* will automatically be selected\n  if (!IRLremote.begin(pinIR))\n    Serial.println(F(\"You did not choose a valid pin.\"));\n\n  // Start HID devices\n  USBKEYBOARD.begin();\n  USBMOUSE.begin();\n}\n\nvoid loop()\n{\n  // Get the new data from the remote\n  // Always call this to check for timeouts\n  IRLremote.read();\n}\n\n\n\nvoid NecEvent(void)\n{\n  // Get the current button (re)press count\n  auto pressCount = IRLremote.pressCount();\n\n  // Tells how many times the button was pressed including the first time.\n  // Add a debounce if the button is held down, only accept every xth key.\n  // 1, 2, 4, 8, 16, 32, 64, 128 works best\n  auto holdDebounce = IRLremote.holdCount(4);\n  auto holdCount = IRLremote.holdCount(0);\n\n  // Button holding/pressing multiple times timed out.\n  // Use this to differentiate between 1,2,3,...,n button presses.\n  // or release holding keys.\n  auto pressTimeout = IRLremote.pressTimeout();\n  auto releaseButton = IRLremote.releaseButton();\n\n  // Get the actual command we are processing\n  auto command = IRLremote.command();\n\n\n  // Print data to the serial for debugging\n  //  Serial.println(F(\"----------\"));\n  //  Serial.print(F(\"Key: \"));\n  //  Serial.println(command);\n  //  Serial.print(F(\"Keypresses: \"));\n  //  Serial.println(pressCount);\n  //  Serial.print(F(\"holdDebounce: \"));\n  //  Serial.println(holdDebounce);\n  //  Serial.print(F(\"pressTimeout: \"));\n  //  Serial.println(pressTimeout);\n  //  Serial.println();\n\n\n  // Differenciate between 4 modes\n  enum IRModes : uint8_t\n  {\n    PC_Mode,\n    Mouse_Mode,\n    Led_Mode,\n    Kodi_Mode,\n  };\n  static IRModes IRMode = PC_Mode;\n\n  // Press HID keys with a protek remote\n  switch (command)\n  {\n    // Red mode\n    case IRL_KEYCODE_RED:\n      if (holdCount == 1) {\n        IRMode = PC_Mode;\n      }\n      break;\n\n    // Green mode\n    case IRL_KEYCODE_GREEN:\n      if (holdCount == 1) {\n        IRMode = Mouse_Mode;\n      }\n      break;\n\n    // Yellow mode\n    case IRL_KEYCODE_YELLOW:\n      if (holdCount == 1) {\n        // Not implemented\n        IRMode = Led_Mode;\n      }\n      break;\n\n    // Blue mode\n    case IRL_KEYCODE_BLUE:\n      if (holdCount == 1) {\n        // Kodi remote\n        // http://kodi.wiki/view/Keyboard_controls\n        // https://github.com/xbmc/xbmc/blob/master/system/keymaps/keyboard.xml\n        IRMode = Kodi_Mode;\n      }\n      break;\n\n\n    // Shutdown menu\n    case IRL_KEYCODE_POWER:\n      if (IRMode == Kodi_Mode) {\n        // Hold the button some time (around 3 sec) to trigger shutdown button\n        if (holdDebounce == 4) {\n          USBKEYBOARD.press('s');\n          USBKEYBOARD.releaseAll();\n        }\n      }\n      else {\n        // Hold the button some time (around 3 sec) to trigger shutdown button\n        if (pressCount == 1 && holdDebounce == 4) {\n          if (IRMode == PC_Mode) {\n            USBKEYBOARD.press(KEY_POWER);\n            USBKEYBOARD.releaseAll();\n          }\n          IRLremote.reset();\n        }\n        // For two short keypress just exit the current program\n        else if (pressCount == 2 && holdDebounce == 4)\n        {\n          IRLremote.reset();\n        }\n      }\n      break;\n\n    // Global system mute\n    case IRL_KEYCODE_MUTE:\n      if (holdDebounce == 1) {\n        if (IRMode == Kodi_Mode) {\n          USBKEYBOARD.press(KEY_F8);\n          USBKEYBOARD.releaseAll();\n        }\n        else if (IRMode == PC_Mode) {\n          USBKEYBOARD.press(KEY_VOLUME_MUTE);\n          USBKEYBOARD.releaseAll();\n        }\n      }\n      break;\n\n    // Fullscreen/Window mode\n    case IRL_KEYCODE_SCREEN:\n      if (holdDebounce == 1) {\n        if (IRMode == Kodi_Mode) {\n          USBKEYBOARD.press('\\\\');\n          USBKEYBOARD.releaseAll();\n        }\n        else if (IRMode == PC_Mode || IRMode == Led_Mode) {\n          // Turn off screens\n          // xset dpms force off\n          USBKEYBOARD.write(CONSUMER_SLEEP);\n          USBKEYBOARD.releaseAll();\n        }\n      }\n      break;\n\n    // Live TV channels window\n    case IRL_KEYCODE_SATELLITE:\n      if (holdDebounce == 1) {\n        if (IRMode == Kodi_Mode) {\n          USBKEYBOARD.press('h');\n          USBKEYBOARD.releaseAll();\n        }\n      }\n      break;\n\n    // Open videos\n    case IRL_KEYCODE_TV_RADIO:\n      if (holdDebounce == 1) {\n        if (IRMode == Kodi_Mode) {\n          USBKEYBOARD.press(KEY_LEFT_CTRL);\n          USBKEYBOARD.press('e');\n          USBKEYBOARD.releaseAll();\n        }\n      }\n      break;\n\n    // Open music\n    case IRL_KEYCODE_TV_MUSIC:\n      if (holdDebounce == 1) {\n        if (IRMode == Kodi_Mode) {\n          USBKEYBOARD.press(KEY_LEFT_CTRL);\n          USBKEYBOARD.press('m');\n          USBKEYBOARD.releaseAll();\n        }\n      }\n      break;\n\n    // 1\n    case IRL_KEYCODE_1:\n      if (holdDebounce == 1) {\n        USBKEYBOARD.press('1');\n        USBKEYBOARD.releaseAll();\n      }\n      break;\n\n    // Letters are used to qickly jump between movies in the library\n    // A, B, C, 2\n    case IRL_KEYCODE_2:\n      if (pressTimeout == 1) {\n        USBKEYBOARD.press('A');\n      }\n      else if (pressTimeout == 2) {\n        USBKEYBOARD.press('B');\n      }\n      else if (pressTimeout == 3) {\n        USBKEYBOARD.press('C');\n      }\n      else if (pressTimeout == 4) {\n        USBKEYBOARD.press('2');\n      }\n      USBKEYBOARD.releaseAll();\n      break;\n\n    // D, E, F, 3\n    case IRL_KEYCODE_3:\n      if (pressTimeout == 1) {\n        USBKEYBOARD.press('D');\n      }\n      else if (pressTimeout == 2) {\n        USBKEYBOARD.press('E');\n      }\n      else if (pressTimeout == 3) {\n        USBKEYBOARD.press('F');\n      }\n      else if (pressTimeout == 4) {\n        USBKEYBOARD.press('3');\n      }\n      USBKEYBOARD.releaseAll();\n      break;\n\n    // G, H, I, 4\n    case IRL_KEYCODE_4:\n      if (pressTimeout == 1) {\n        USBKEYBOARD.press('G');\n      }\n      else if (pressTimeout == 2) {\n        USBKEYBOARD.press('H');\n      }\n      else if (pressTimeout == 3) {\n        USBKEYBOARD.press('I');\n      }\n      else if (pressTimeout == 4) {\n        USBKEYBOARD.press('4');\n      }\n      USBKEYBOARD.releaseAll();\n      break;\n\n    // J, K, L, 5\n    case IRL_KEYCODE_5:\n      if (pressTimeout == 1) {\n        USBKEYBOARD.press('J');\n      }\n      else if (pressTimeout == 2) {\n        USBKEYBOARD.press('K');\n      }\n      else if (pressTimeout == 3) {\n        USBKEYBOARD.press('L');\n      }\n      else if (pressTimeout == 4) {\n        USBKEYBOARD.press('5');\n      }\n      USBKEYBOARD.releaseAll();\n      break;\n\n    // M, N, O, 6\n    case IRL_KEYCODE_6:\n      if (pressTimeout == 1) {\n        USBKEYBOARD.press('M');\n      }\n      else if (pressTimeout == 2) {\n        USBKEYBOARD.press('N');\n      }\n      else if (pressTimeout == 3) {\n        USBKEYBOARD.press('O');\n      }\n      else if (pressTimeout == 4) {\n        USBKEYBOARD.press('6');\n      }\n      USBKEYBOARD.releaseAll();\n      break;\n\n    // P, Q, R, S, 7\n    case IRL_KEYCODE_7:\n      if (pressTimeout == 1) {\n        USBKEYBOARD.press('P');\n      }\n      else if (pressTimeout == 2) {\n        USBKEYBOARD.press('Q');\n      }\n      else if (pressTimeout == 3) {\n        USBKEYBOARD.press('R');\n      }\n      else if (pressTimeout == 4) {\n        USBKEYBOARD.press('S');\n      }\n      else if (pressTimeout == 5) {\n        USBKEYBOARD.press('7');\n      }\n      USBKEYBOARD.releaseAll();\n      break;\n\n    // T, U, V, 8\n    case IRL_KEYCODE_8:\n      if (pressTimeout == 1) {\n        USBKEYBOARD.press('T');\n      }\n      else if (pressTimeout == 2) {\n        USBKEYBOARD.press('U');\n      }\n      else if (pressTimeout == 3) {\n        USBKEYBOARD.press('V');\n      }\n      else if (pressTimeout == 4) {\n        USBKEYBOARD.press('8');\n      }\n      USBKEYBOARD.releaseAll();\n      break;\n\n    // W, X, Y, Z, 9\n    case IRL_KEYCODE_9:\n      if (pressTimeout == 1) {\n        USBKEYBOARD.press('W');\n      }\n      else if (pressTimeout == 2) {\n        USBKEYBOARD.press('X');\n      }\n      else if (pressTimeout == 3) {\n        USBKEYBOARD.press('Y');\n      }\n      else if (pressTimeout == 4) {\n        USBKEYBOARD.press('Z');\n      }\n      else if (pressTimeout == 5) {\n        USBKEYBOARD.press('9');\n      }\n      USBKEYBOARD.releaseAll();\n      break;\n\n    // Space, 0\n    case IRL_KEYCODE_0:\n      if (pressTimeout == 1) {\n        USBKEYBOARD.press(' ');\n      }\n      else if (pressTimeout == 2) {\n        USBKEYBOARD.press('0');\n      }\n      USBKEYBOARD.releaseAll();\n      break;\n\n    case IRL_KEYCODE_BACK:\n      if (holdDebounce == 1) {\n        // Back\n        if (IRMode == Kodi_Mode) {\n          USBKEYBOARD.press(KEY_BACKSPACE);\n          USBKEYBOARD.releaseAll();\n        }\n        // Backspace\n        else if (IRMode == PC_Mode || IRMode == Mouse_Mode) {\n          USBKEYBOARD.press(KEY_BACKSPACE);\n          USBKEYBOARD.releaseAll();\n        }\n      }\n      break;\n\n    case IRL_KEYCODE_FAVORITE:\n      if (holdDebounce == 1) {\n        // Mark as watched/unwatched\n        if (IRMode == Kodi_Mode) {\n          USBKEYBOARD.press('w');\n          USBKEYBOARD.releaseAll();\n        }\n        // Delete\n        else if (IRMode == PC_Mode || IRMode == Mouse_Mode) {\n          USBKEYBOARD.press(KEY_DELETE);\n          USBKEYBOARD.releaseAll();\n        }\n      }\n      break;\n\n    // Volume up\n    case IRL_KEYCODE_VOL_UP:\n      if (holdDebounce) {\n        if (IRMode == Kodi_Mode) {\n          USBKEYBOARD.press('+'); // F10, =\n          USBKEYBOARD.releaseAll();\n        }\n        else if (IRMode == PC_Mode || IRMode == Mouse_Mode) {\n          USBKEYBOARD.press(KEY_VOLUME_UP);\n          USBKEYBOARD.releaseAll();\n        }\n      }\n      break;\n\n    // Volume down\n    case IRL_KEYCODE_VOL_DOWN:\n      if (holdDebounce) {\n        if (IRMode == Kodi_Mode) {\n          USBKEYBOARD.press('-'); // F9\n          USBKEYBOARD.releaseAll();\n        }\n        else if (IRMode == PC_Mode || IRMode == Mouse_Mode) {\n          USBKEYBOARD.press(KEY_VOLUME_DOWN);\n          USBKEYBOARD.releaseAll();\n        }\n      }\n      break;\n\n    // Live TV EPG/TV guide\n    case IRL_KEYCODE_EPG:\n      if (holdDebounce == 1) {\n        if (IRMode == Kodi_Mode) {\n          USBKEYBOARD.press('e');\n          USBKEYBOARD.releaseAll();\n        }\n        else if (IRMode == PC_Mode || IRMode == Mouse_Mode) {\n          USBKEYBOARD.press(KEY_TAB);\n          USBKEYBOARD.releaseAll();\n        }\n      }\n      break;\n\n    // Info\n    case IRL_KEYCODE_INFO:\n      if (holdDebounce == 1) {\n        if (IRMode == Kodi_Mode) {\n          USBKEYBOARD.press('i');\n          USBKEYBOARD.releaseAll();\n        }\n        else if (IRMode == PC_Mode || IRMode == Mouse_Mode) {\n          USBKEYBOARD.press(KEY_F1);\n          USBKEYBOARD.releaseAll();\n        }\n      }\n      break;\n\n    // Increase rating\n    case IRL_KEYCODE_CHANNEL_UP:\n      if (IRMode == Kodi_Mode || IRMode == PC_Mode) {\n        // Decrease rating\n        if (holdDebounce) {\n          USBKEYBOARD.press(KEY_PAGE_UP);\n          USBKEYBOARD.releaseAll();\n        }\n      }\n      else if (IRMode == Mouse_Mode) {\n        // Scroll\n        if (holdCount) {\n          USBMOUSE.move(0, 0, min(holdCount, 10));\n        }\n      }\n      break;\n\n    // Decrease rating\n    case IRL_KEYCODE_CHANNEL_DOWN:\n      if (IRMode == Kodi_Mode || IRMode == PC_Mode) {\n        if (holdDebounce) {\n          USBKEYBOARD.press(KEY_PAGE_DOWN);\n          USBKEYBOARD.releaseAll();\n        }\n      }\n      else if (IRMode == Mouse_Mode) {\n        // Scroll\n        if (holdCount) {\n          USBMOUSE.move(0, 0, -1 * min(holdCount, 10));\n        }\n      }\n      break;\n\n    // Navigation\n    case IRL_KEYCODE_RIGHT:\n      if (IRMode == Kodi_Mode || IRMode == PC_Mode) {\n        if (holdDebounce) {\n          USBKEYBOARD.press(KEY_RIGHT_ARROW);\n          USBKEYBOARD.releaseAll();\n        }\n      }\n      else if (IRMode == Mouse_Mode) {\n        if (holdCount) {\n          USBMOUSE.move(min(holdCount * holdCount, 127), 0);\n        }\n      }\n      break;\n    case IRL_KEYCODE_LEFT:\n      if (IRMode == Kodi_Mode || IRMode == PC_Mode) {\n        if (holdDebounce) {\n          USBKEYBOARD.press(KEY_LEFT_ARROW);\n          USBKEYBOARD.releaseAll();\n        }\n      }\n      else if (IRMode == Mouse_Mode) {\n        if (holdCount) {\n          USBMOUSE.move(-1 * min(holdCount * holdCount, 127), 0);\n        }\n      }\n      break;\n    case IRL_KEYCODE_UP:\n      if (IRMode == Kodi_Mode || IRMode == PC_Mode) {\n        if (holdDebounce) {\n          USBKEYBOARD.press(KEY_UP_ARROW);\n          USBKEYBOARD.releaseAll();\n        }\n      }\n      else if (IRMode == Mouse_Mode) {\n        if (holdCount) {\n          USBMOUSE.move(0, -1 * min(holdCount * holdCount, 127));\n        }\n      }\n      break;\n    case IRL_KEYCODE_DOWN:\n      if (IRMode == Kodi_Mode || IRMode == PC_Mode) {\n        if (holdDebounce) {\n          USBKEYBOARD.press(KEY_DOWN_ARROW);\n          USBKEYBOARD.releaseAll();\n        }\n      }\n      else if (IRMode == Mouse_Mode) {\n        if (holdCount) {\n          USBMOUSE.move(0, min(holdCount * holdCount, 127));\n        }\n      }\n      break;\n\n    // Enter menu, play/pause, general okay button\n    case IRL_KEYCODE_OK:\n      if (IRMode == Mouse_Mode) {\n        if (holdDebounce == 1) {\n          USBMOUSE.press();\n        }\n        else if (releaseButton) {\n          USBMOUSE.releaseAll();\n        }\n      }\n      else if (IRMode == Kodi_Mode || IRMode == PC_Mode) {\n        if (holdDebounce == 1) {\n          USBKEYBOARD.press(KEY_RETURN);\n          USBKEYBOARD.releaseAll();\n        }\n      }\n      break;\n\n    // Exit full screeen\n    case IRL_KEYCODE_EXIT:\n      if (holdDebounce == 1) {\n        if (IRMode == Kodi_Mode || IRMode == PC_Mode || IRMode == Mouse_Mode) {\n          USBKEYBOARD.press(KEY_ESC);\n          USBKEYBOARD.releaseAll();\n        }\n      }\n      break;\n\n    // Context menu/Playlist\n    case IRL_KEYCODE_MENU:\n      if (holdDebounce == 1) {\n        if (IRMode == Kodi_Mode) {\n          USBKEYBOARD.press('c');\n          USBKEYBOARD.releaseAll();\n        }\n        else if (IRMode == PC_Mode) {\n          USBKEYBOARD.press(KEY_MENU);\n          USBKEYBOARD.releaseAll();\n        }\n        else if (IRMode == Mouse_Mode) {\n          USBMOUSE.press(MOUSE_RIGHT);\n        }\n      }\n      else if (releaseButton) {\n        USBMOUSE.releaseAll();\n      }\n      break;\n\n    // Show debug information\n    case IRL_KEYCODE_I_II:\n      if (holdDebounce == 1) {\n        if (IRMode == Kodi_Mode) {\n          USBKEYBOARD.press(KEY_LEFT_CTRL);\n          USBKEYBOARD.press('D');\n          USBKEYBOARD.releaseAll();\n        }\n        else if (IRMode == PC_Mode) {\n          USBKEYBOARD.press(KEY_LEFT_GUI);\n          USBKEYBOARD.press('p');\n          USBKEYBOARD.releaseAll();\n        }\n      }\n      break;\n\n    // Teletext/Visualization settings\n    case IRL_KEYCODE_TELETEXT:\n      if (holdDebounce == 1) {\n        if (IRMode == Kodi_Mode) {\n          USBKEYBOARD.press('v');\n          USBKEYBOARD.releaseAll();\n        }\n        else if (IRMode == PC_Mode) {\n          // Linux is very picky here, 'e' needs to be released first.\n          USBKEYBOARD.press(KEY_LEFT_GUI);\n          USBKEYBOARD.write('e');\n          USBKEYBOARD.releaseAll();\n        }\n      }\n      break;\n\n    // Next subtitle\n    case IRL_KEYCODE_SUBTITLE:\n      if (holdDebounce == 1) {\n        if (IRMode == Kodi_Mode) {\n          USBKEYBOARD.press('l');\n          USBKEYBOARD.releaseAll();\n        }\n        // Open Switchboard\n        else if (IRMode == PC_Mode || IRMode == Mouse_Mode) {\n          USBKEYBOARD.press(KEY_LEFT_GUI);\n          USBKEYBOARD.press(KEY_SPACE);\n          USBKEYBOARD.releaseAll();\n        }\n      }\n      break;\n\n    // Fullscreen play\n    case IRL_KEYCODE_ADD:\n      if (IRMode == Kodi_Mode) {\n        if (holdDebounce == 1) {\n          USBKEYBOARD.press(KEY_TAB);\n          USBKEYBOARD.releaseAll();\n        }\n      }\n      // Switch application\n      else if (IRMode == PC_Mode || IRMode == Mouse_Mode) {\n        // Hold down to keep the overview, press again to switch application\n        if (holdDebounce == 1) {\n          USBKEYBOARD.press(KEY_LEFT_ALT);\n          USBKEYBOARD.write(KEY_TAB);\n        }\n        if (pressTimeout) {\n          USBKEYBOARD.releaseAll();\n        }\n      }\n\n      break;\n\n    // Play/Pause\n    case IRL_KEYCODE_PLAY:\n    case IRL_KEYCODE_PAUSE:\n      if (holdDebounce == 1) {\n        if (IRMode == Kodi_Mode) {\n          USBKEYBOARD.press(KEY_SPACE);\n          USBKEYBOARD.releaseAll();\n        }\n        else if (IRMode == PC_Mode || IRMode == Mouse_Mode) {\n          USBKEYBOARD.press(MEDIA_PLAY_PAUSE);\n          USBKEYBOARD.releaseAll();\n        }\n      }\n      break;\n\n    // Skip forward\n    case IRL_KEYCODE_NEXT:\n      if (holdDebounce == 1) {\n        if (IRMode == Kodi_Mode) {\n          USBKEYBOARD.press('.');\n          USBKEYBOARD.releaseAll();\n        }\n        else if (IRMode == PC_Mode || IRMode == Mouse_Mode) {\n          USBKEYBOARD.press(MEDIA_NEXT);\n          USBKEYBOARD.releaseAll();\n        }\n      }\n      break;\n\n    // Skip backward\n    case IRL_KEYCODE_PREV:\n      if (holdDebounce == 1) {\n        if (IRMode == Kodi_Mode) {\n          USBKEYBOARD.press(',');\n          USBKEYBOARD.releaseAll();\n        }\n        else if (IRMode == PC_Mode || IRMode == Mouse_Mode) {\n          USBKEYBOARD.press(MEDIA_PREVIOUS);\n          USBKEYBOARD.releaseAll();\n        }\n      }\n      break;\n\n    // Stop\n    case IRL_KEYCODE_STOP:\n      if (holdDebounce == 1) {\n        if (IRMode == Kodi_Mode) {\n          USBKEYBOARD.press('x');\n          USBKEYBOARD.releaseAll();\n        }\n        else if (IRMode == PC_Mode || IRMode == Mouse_Mode) {\n          USBKEYBOARD.press(MEDIA_STOP);\n          USBKEYBOARD.releaseAll();\n        }\n      }\n      break;\n\n    // Change keyboard layout\n    case IRL_KEYCODE_USB:\n      if (IRMode == PC_Mode || IRMode == Mouse_Mode || IRMode == Kodi_Mode) {\n        if (holdDebounce == 1) {\n          USBKEYBOARD.press(KEY_LEFT_SHIFT);\n          USBKEYBOARD.press(KEY_LEFT_ALT);\n          USBKEYBOARD.press(KEY_SPACE);\n          USBKEYBOARD.releaseAll();\n        }\n      }\n      break;\n\n    // Screenshot\n    case IRL_KEYCODE_REC:\n      if (holdDebounce == 1) {\n        if (IRMode == Kodi_Mode) {\n          USBKEYBOARD.press(KEY_LEFT_CTRL);\n          USBKEYBOARD.press('s');\n          USBKEYBOARD.releaseAll();\n        }\n        else if (IRMode == PC_Mode || IRMode == Mouse_Mode) {\n          USBKEYBOARD.press(KEY_PRINT);\n          USBKEYBOARD.releaseAll();\n        }\n      }\n      break;\n\n    // TODO\n    case IRL_KEYCODE_LIVE:\n\n      break;\n  }\n}\n\n"
  },
  {
    "path": "examples/Receive/Receive.ino",
    "content": "/*\n  Copyright (c) 2014-2015 NicoHood\n  See the readme for credit to other people.\n\n  IRL Receive\n\n  Receives IR signals from different protocols and prints them to the Serial monitor.\n  Choose your protocols that should be decoded. Remove the not used ones to save flash/ram/speed.\n  You can choose a custom debounce time to not trigger a button two times in a row too fast.\n\n  The following pins are usable for PinInterrupt or PinChangeInterrupt*:\n  Arduino Uno/Nano/Mini: All pins are usable\n  Arduino Mega: 10, 11, 12, 13, 50, 51, 52, 53, A8 (62), A9 (63), A10 (64),\n              A11 (65), A12 (66), A13 (67), A14 (68), A15 (69)\n  Arduino Leonardo/Micro: 8, 9, 10, 11, 14 (MISO), 15 (SCK), 16 (MOSI)\n  HoodLoader2: All (broken out 1-7) pins are usable\n  Attiny 24/44/84: All pins are usable\n  Attiny 25/45/85: All pins are usable\n  Attiny 13: All pins are usable\n  Attiny 441/841: All pins are usable\n  ATmega644P/ATmega1284P: All pins are usable\n\n  PinChangeInterrupts* requires a special library which can be downloaded here:\n  https://github.com/NicoHood/PinChangeInterrupt\n*/\n\n// include PinChangeInterrupt library* BEFORE IRLremote to acces more pins if needed\n//#include \"PinChangeInterrupt.h\"\n\n#include \"IRLremote.h\"\n\n// Choose a valid PinInterrupt or PinChangeInterrupt* pin of your Arduino board\n#define pinIR 2\n\n// Choose the IR protocol of your remote. See the other example for this.\nCNec IRLremote;\n//CPanasonic IRLremote;\n//CHashIR IRLremote;\n//#define IRLremote Sony12\n\n#define pinLed LED_BUILTIN\n\nvoid setup()\n{\n  // Start serial debug output\n  while (!Serial);\n  Serial.begin(115200);\n  Serial.println(F(\"Startup\"));\n\n  // Set LED to output\n  pinMode(pinLed, OUTPUT);\n\n  // Start reading the remote. PinInterrupt or PinChangeInterrupt* will automatically be selected\n  if (!IRLremote.begin(pinIR))\n    Serial.println(F(\"You did not choose a valid pin.\"));\n}\n\nvoid loop()\n{\n  // Check if we are currently receiving data\n  //if (!IRLremote.receiving()) {\n    // Run code that disables interrupts, such as some led strips\n  //}\n\n  // Check if new IR protocol data is available\n  if (IRLremote.available())\n  {\n    // Light Led\n    digitalWrite(pinLed, HIGH);\n\n    // Get the new data from the remote\n    auto data = IRLremote.read();\n\n    // Print the protocol data\n    Serial.print(F(\"Address: 0x\"));\n    Serial.println(data.address, HEX);\n    Serial.print(F(\"Command: 0x\"));\n    Serial.println(data.command, HEX);\n    Serial.println();\n\n    // Turn Led off after printing the data\n    digitalWrite(pinLed, LOW);\n  }\n}\n"
  },
  {
    "path": "examples/Receive_Raw/Receive_Raw.ino",
    "content": "/*\n  Copyright (c) 2014-2015 NicoHood\n  See the readme for credit to other people.\n\n  IRL Receive_Raw\n\n  Receives IR signals and prints raw values to the Serial.\n  Please read the notes below, this example is used for developing/debugging only.\n\n  The following pins are usable for PinInterrupt or PinChangeInterrupt*:\n  Arduino Uno/Nano/Mini: 2, 3, All pins* are usable\n  Arduino Mega: 2, 3, 18, 19, 20, 21,\n               10*, 11*, 12*, 13*, 50*, 51*, 52*, 53*, A8 (62)*, A9 (63)*, A10 (64)*,\n               A11 (65)*, A12 (66)*, A13 (67)*, A14 (68)*, A15 (69)*\n  Arduino Leonardo/Micro: 0, 1, 2, 3, 7, 8*, 9*, 10*, 11*, 14 (MISO)*, 15 (SCK)*, 16 (MOSI)*\n  HoodLoader2: All (broken out 1-7*) pins are usable\n  Attiny 24/44/84: 8, All pins* are usable\n  Attiny 25/45/85: 2, All pins* are usable\n  Attiny 13: All pins* are usable\n  ATmega644P/ATmega1284P: 10, 11, All pins* are usable\n\n  PinChangeInterrupts* requires a special library which can be downloaded here:\n  https://github.com/NicoHood/PinChangeInterrupt\n*/\n\n// include PinChangeInterrupt library* BEFORE IRLremote to acces more pins if needed\n//#include \"PinChangeInterrupt.h\"\n\n#include \"IRLremote.h\"\n// choose a valid PinInterrupt or PinChangeInterrupt* pin of your Arduino board\n#define pinIR 2\nCIRLremote<RawIR> IRLremote;\n\n#define pinLed LED_BUILTIN\n\nvoid setup() {\n  // Start serial debug output\n  while (!Serial);\n  Serial.begin(115200);\n  Serial.println(F(\"Startup\"));\n\n  // Set LED to output\n  pinMode(pinLed, OUTPUT);\n\n  // Start reading the remote. PinInterrupt or PinChangeInterrupt* will automatically be selected\n  if (!IRLremote.begin(pinIR))\n    Serial.println(F(\"You did not choose a valid pin.\"));\n}\n\nvoid loop() {\n  if (IRLremote.available()) {\n    // Light Led\n    digitalWrite(pinLed, HIGH);\n\n    // Important note:\n    // Printing the values might cause you to miss\n    // the first byte of the next sequence.\n    // You might want to increase the buffer size\n    // and the timeout as well in the settings.\n    // You could also copy the buffer, call read()\n    // and print afterwards if enough ram is available.\n    // Do not use RawIR as \"all day\" protocol.\n    // But you can use the HashIR protocol instead.\n    const bool printRaw = true;\n    if (printRaw) {\n\n      // Print a mark\n      Serial.println(F(\"==========\"));\n\n      // Go through the whole buffer and print values\n      for (typeof(RawIR::countRawIR) i = 0; i < RawIR::countRawIR; i++) {\n        Serial.print(i);\n        Serial.print(F(\": \"));\n        Serial.println(RawIR::dataRawIR[i], DEC);\n      }\n\n      // Each buffer should end with the timeout value\n      if (RawIR::countRawIR == RAWIR_BLOCKS) {\n        Serial.println(F(\"Buffer was full!\"));\n      }\n      Serial.println();\n    }\n\n    // Get the new data from the remote\n    IR_data_t data = IRLremote.read();\n\n    // Print the protocol data\n    // For RawIR this is just an approximate calculation.\n    // You should ignore addresses/length < 6 to avoid noise.\n    Serial.print(F(\"Buffer length: \"));\n    Serial.println(data.address, DEC);\n    Serial.print(F(\"Command: 0x\"));\n    Serial.println(data.command, HEX);\n    Serial.println();\n\n    // Turn Led off after printing the data\n    digitalWrite(pinLed, LOW);\n  }\n}\n"
  },
  {
    "path": "examples/Send_Button/Send_Button.ino",
    "content": "/*\r\n Copyright (c) 2014 NicoHood\r\n See the readme for credit to other people.\r\n\r\n IRL Send Button\r\n Sends IR signals on any pin. This uses Bitbanging.\r\n \r\n Press the button to send data.\r\n Turn interrupts off to get a better result if needed\r\n */\r\n\r\n#include \"IRLremote.h\"\r\n\r\n// choose any pin to send IR signals\r\nconst int pinSendIR = 3;\r\n\r\n// choose any pin to trigger IR sending\r\nconst int pinButton = 8;\r\n\r\nvoid setup() {\r\n  // setup for the button\r\n  pinMode(pinButton, INPUT_PULLUP);\r\n}\r\n\r\nvoid loop() {\r\n  if (!digitalRead(pinButton)) {\r\n    // send the data, no pin setting to OUTPUT needed\r\n    uint16_t address = 0x6361;\r\n    uint32_t command = 0xFE01;\r\n    IRLwrite<IR_NEC>(pinSendIR, address, command);\r\n\r\n    // simple debounce\r\n    delay(300);\r\n  }\r\n}\r\n"
  },
  {
    "path": "examples/Send_Serial/Send_Serial.ino",
    "content": "/*\r\n Copyright (c) 2014 NicoHood\r\n See the readme for credit to other people.\r\n\r\n IRL Send Serial\r\n Sends IR signals on any pin. This uses Bitbanging.\r\n \r\n Write anything to the Serial port and hit enter to send Data.\r\n Turn interrupts off to get a better result if needed\r\n */\r\n\r\n#include \"IRLremote.h\"\r\n\r\n// choose any pin to send IR signals\r\nconst int pinSendIR = 3;\r\n\r\nvoid setup() {\r\n  // start serial debug in/output\r\n  Serial.begin(115200);\r\n  Serial.println(\"Startup\");\r\n}\r\n\r\nvoid loop() {\r\n  if (Serial.available()) {\r\n    // discard all Serial bytes to avoid multiple sendings\r\n    delay(10);\r\n    while (Serial.available())\r\n      Serial.read();\r\n      \r\n    // send the data, no pin setting to OUTPUT needed\r\n    Serial.println(\"Sending...\");\r\n    uint16_t address = 0x6361;\r\n    uint32_t command = 0xFE01;\r\n\r\n    IRLwrite<IR_NEC>(pinSendIR, address, command);\r\n  }\r\n}"
  },
  {
    "path": "examples/Transceive/Transceive.ino",
    "content": "/*\n Copyright (c) 2014-2015 NicoHood\n See the readme for credit to other people.\n\n IRL Transceive\n\n Receives IR signals from different protocols and prints them to the Serial monitor.\n On receiving a specific IR input it will send another IR signal out.\n Choose your protocols that should be decoded. Remove the not used ones to save flash/ram/speed.\n You can choose a custom debounce time to not trigger a button two times in a row too fast.\n\n The following pins are usable for PinInterrupt or PinChangeInterrupt*:\n Arduino Uno/Nano/Mini: 2, 3, All pins* are usable\n Arduino Mega: 2, 3, 18, 19, 20, 21,\n               10*, 11*, 12*, 13*, 50*, 51*, 52*, 53*, A8 (62)*, A9 (63)*, A10 (64)*,\n               A11 (65)*, A12 (66)*, A13 (67)*, A14 (68)*, A15 (69)*\n Arduino Leonardo/Micro: 0, 1, 2, 3, 7, 8*, 9*, 10*, 11*, 14 (MISO)*, 15 (SCK)*, 16 (MOSI)*\n HoodLoader2: All (broken out 1-7*) pins are usable\n Attiny 24/44/84: 8, All pins* are usable\n Attiny 25/45/85: 2, All pins* are usable\n ATmega644P/ATmega1284P: 10, 11, All pins* are usable\n\n *: PinChangeInterrupts requires a special library which can be downloaded here:\n  https://github.com/NicoHood/PinChangeInterrupt\n*/\n\n// include PinChangeInterrupt library* BEFORE IRLremote to acces more pins if needed\n//#include \"PinChangeInterrupt.h\"\n\n#include \"IRLremote.h\"\n// choose a valid PinInterrupt or PinChangeInterrupt* pin of your Arduino board\n#define pinIR 2\n#define pinSendIR 3\n#define IRL_DEBOUCE 300\nCIRLremote<IRL_DEBOUCE, IR_NEC, IR_PANASONIC, IR_SONY12> IRLremote;\n\n#define pinLed LED_BUILTIN\n\nvoid setup() {\n  // start serial debug output\n  Serial.begin(115200);\n  Serial.println(F(\"Startup\"));\n\n  // set LED to output\n  pinMode(pinLed, OUTPUT);\n\n  // start reading the remote. PinInterrupt or PinChangeInterrupt* will automatically be selected\n  if (!IRLremote.begin(pinIR))\n    Serial.println(F(\"You did not choose a valid pin.\"));\n}\n\nvoid loop() {\n  if (IRLremote.available()) {\n    // light Led\n    digitalWrite(pinLed, HIGH);\n\n    // get the new data from the remote\n    IR_data_t data = IRLremote.read();\n\n    // print protocol number\n    Serial.println();\n    Serial.print(F(\"Protocol: \"));\n    Serial.print(data.protocol);\n\n    // see readme to terminate what number is for each protocol\n    switch (data.protocol) {\n      case IR_NEC:\n        Serial.println(F(\" NEC\"));\n        break;\n      case IR_PANASONIC:\n        Serial.println(F(\" Panasonic\"));\n        break;\n      case IR_SONY12:\n        Serial.println(F(\" Sony12\"));\n        break;\n      default:\n        Serial.println(F(\" Unknown\"));\n        break;\n    }\n\n    // print the protocol data\n    Serial.print(F(\"Address: 0x\"));\n    Serial.println(data.address, HEX);\n    Serial.print(F(\"Command: 0x\"));\n    Serial.println(data.command, HEX);\n\n\n    // check if the input was a specific signal and send another signal out\n    if (data.protocol == IR_PANASONIC && data.address == 0x2002 && data.command == 0x813D1CA0) {\n      // send the data, no pin setting to OUTPUT needed\n      Serial.println();\n      Serial.println(F(\"Sending...\"));\n      uint16_t address = 0x6361;\n      uint32_t command = 0xFE01;\n\n      IRLwrite<IR_NEC>(pinSendIR, address, command);\n    }\n\n    // turn Led off after printing the data\n    digitalWrite(pinLed, LOW);\n  }\n}\n\r\n"
  },
  {
    "path": "extra/old/IRL_Hash.hpp",
    "content": "/*\nCopyright (c) 2014-2015 NicoHood\nSee the readme for credit to other people.\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in\nall copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\nTHE SOFTWARE.\n*/\n\n// Include guard\n#pragma once\n\n//================================================================================\n// Protocol Definitions\n//================================================================================\n\n//HashIR\n#define HASHIR_BLOCKS 255\t\t\t\t// 0-65535 (maximum input length)\n#define HASHIR_TIMEOUT (0xFFFF/4)\t\t// 65535, max timeout\n#define HASHIR_TIME_THRESHOLD 10000UL\t// 0-32bit\n\n//================================================================================\n// Decoding Class\n//================================================================================\n\nclass HashIR : public CIRLData{\npublic:\n\tHashIR(void){\n\t\t// Empty\t\n\t}\n\t\n\t// Hide anything that is inside this class so the user dont accidently uses this class\n\ttemplate<typename protocol, typename ...protocols>\n\tfriend class CIRLremote;\n\t\nprivate:\n\tstatic inline uint8_t getSingleFlag(void) __attribute__((always_inline));\n\tstatic inline bool requiresCheckTimeout(void) __attribute__((always_inline));\n\tstatic inline void checkTimeout(void) __attribute__((always_inline));\n\tstatic inline bool available(void) __attribute__((always_inline));\n\tstatic inline void read(IR_data_t* data) __attribute__((always_inline));\n\tstatic inline bool requiresReset(void) __attribute__((always_inline));\n\tstatic inline void reset(void) __attribute__((always_inline));\n\t\n\t// Decode functions for a single protocol/multiprotocol for less/more accuration\n\tstatic inline void decodeSingle(const uint16_t &duration) __attribute__((always_inline));\n\tstatic inline void decode(const uint16_t &duration) __attribute__((always_inline));\n\nprotected:\n\t// Temporary buffer to hold bytes for decoding the protocols\n\t// not all of them are compiled, only the used ones\n\tstatic uint16_t durationHashIR;\n\tstatic uint16_t countHashIR;\n\tstatic uint32_t commandHashIR;\n};\n\n\nuint8_t HashIR::getSingleFlag(void){\n\treturn CHANGE;\n}\n\n\nbool HashIR::requiresCheckTimeout(void){\n\t// Used in this protocol\n\treturn true;\n}\n\n\nvoid HashIR::checkTimeout(void){\n\t// This function is executed with interrupts turned off\n\tif (countHashIR) {\n\t\t// Check if reading timed out and save value.\n\t\tif ((micros() - IRLLastTime) >= HASHIR_TIMEOUT) {\n\t\t\t// Flag a new input if reading timed out\n\t\t\tcountHashIR--;\n\t\t\t\n\t\t\tIRLProtocol = IR_HASH;\n\t\t\tIRLLastEvent = IRLLastTime;\n\t\t}\n\t}\n}\n\n\nbool HashIR::available(void)\n{\n\t// Only return a value if this protocol has new data\n\tif(IRLProtocol == IR_HASH)\n\t\treturn true;\n\telse\n\t\treturn false;\t\n}\n\n\nvoid HashIR::read(IR_data_t* data){\n\t// Only (over)write new data if this protocol received any data\n\tif(IRLProtocol == IR_HASH){\n\t\t// Save address as length.\n\t\t// You can check the address/length to prevent triggering on noise\n\t\tdata->address = countHashIR;\n\t\t\n\t\t// Save calculated hash\n\t\tdata->command = commandHashIR;\n\t}\n}\n\n\nbool HashIR::requiresReset(void){\n\t// Used in this protocol\n\treturn true;\n}\n\n\nvoid HashIR::reset(void){\n\t// Reset protocol for new reading\n\tcountHashIR = 0;\n\tcommandHashIR = FNV_BASIS_32;\n}\n\n\nvoid HashIR::decodeSingle(const uint16_t &duration){\n\t// Reading timed out\n\tif(duration >= HASHIR_TIMEOUT)\n\t{\n\t\t// Start a new reading sequence.\n\t\tif(countHashIR == 0){\n\t\t\tcountHashIR++;\n\t\t}\n\t\t// Ignore the very first timeout of each reading.\n\t\t// Otherwise flag a new input and stop reading.\n\t\telse if(countHashIR != 1){\n\t\t\tcountHashIR--;\n\t\t\tIRLProtocol = IR_HASH;\n\t\t}\n\t\treturn;\n\t}\n\t\n\t// Only save data if a sequence is running.\n\t// This is required to avoid corrupted data\n\t// when starting capturing at the middle of a sequence.\n\tif(countHashIR)\n\t{\n\t\t// Converts the raw code values into a 32-bit hash code.\n\t\t// Hopefully this code is unique for each button.\n\t\t// This isn't a \"real\" decoding, just an arbitrary value.\n\t\t// Code taken from https://github.com/z3t0/Arduino-IRremote\n\n\t\t// Use FNV hash algorithm: http://isthe.com/chongo/tech/comp/fnv/#FNV-param\n\t#define FNV_PRIME_32 16777619UL\n\t#define FNV_BASIS_32 2166136261UL\n\n\t\t// Only compare after the first value got received\n\t\tif(countHashIR > 1){\n\t\t\t// Get both values\n\t\t\tauto oldval = durationHashIR;\n\t\t\tauto newval = duration;\n\n\t\t\t// Compare two tick values, returning 0 if newval is shorter,\n\t\t\t// 1 if newval is equal, and 2 if newval is longer\n\t\t\t// Use a tolerance of 75%\n\t\t\tuint8_t value = 1;\n\t\t\tif (newval < (oldval * 3 / 4)) {\n\t\t\t\tvalue = 0;\n\t\t\t}\n\t\t\telse if (oldval < (newval * 3 / 4)) {\n\t\t\t\tvalue = 2;\n\t\t\t}\n\n\t\t\t// Add value into the hash\n\t\t\tcommandHashIR = (commandHashIR * FNV_PRIME_32) ^ value;\n\t\t}\n\t\t\n\t\t// Save last time and count up\n\t\tcountHashIR++;\n\t\tdurationHashIR = duration;\n\n\t\t// Flag a new input if buffer is full\n\t\tif((countHashIR > HASHIR_BLOCKS)){\n\t\t\tcountHashIR--;\n\t\t\tIRLProtocol = IR_HASH;\n\t\t}\n\t}\n}\n\n\nvoid HashIR::decode(const uint16_t &duration) {\n\t// Wait some time after the last protocol.\n\t// This way it can finish its (possibly ignored) stop bit.\n\tuint8_t lastProtocol = IRLProtocol | IR_NEW_PROTOCOL;\n\tif(lastProtocol != IR_HASH && lastProtocol != IR_NEW_PROTOCOL && (IRLLastTime - IRLLastEvent < HASHIR_TIME_THRESHOLD))\n\t\treturn;\n\n\tdecodeSingle(duration);\n}\n"
  },
  {
    "path": "extra/old/IRL_RawIR.hpp",
    "content": "/*\nCopyright (c) 2014-2015 NicoHood\nSee the readme for credit to other people.\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in\nall copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\nTHE SOFTWARE.\n*/\n\n// Include guard\n#pragma once\n\n//================================================================================\n// Protocol Definitions\n//================================================================================\n\n//RawIR\n#define RAWIR_BLOCKS 100\t\t\t\t// 0-65535\n#define RAWIR_TIMEOUT (0xFFFF/4)\t\t// 65535, max timeout\n#define RAWIR_TIME_THRESHOLD 10000UL\t// 0-32bit\n\n// Determine buffer length datatype\n#if (RAWIR_BLOCKS >= 255)\n#define RAWIR_DATA_T uint16_t\n#else\n#define RAWIR_DATA_T uint8_t\n#endif\n\n//================================================================================\n// Decoding Class\n//================================================================================\n\nclass RawIR : public CIRLData{\npublic:\n\tRawIR(void){\n\t\t// Empty\t\n\t}\n\t\n\t// Hide anything that is inside this class so the user dont accidently uses this class\n\ttemplate<typename protocol, typename ...protocols>\n\tfriend class CIRLremote;\n\t\nprivate:\n\tstatic inline uint8_t getSingleFlag(void) __attribute__((always_inline));\n\tstatic inline bool requiresCheckTimeout(void) __attribute__((always_inline));\n\tstatic inline void checkTimeout(void) __attribute__((always_inline));\n\tstatic inline bool available(void) __attribute__((always_inline));\n\tstatic inline void read(IR_data_t* data) __attribute__((always_inline));\n\tstatic inline bool requiresReset(void) __attribute__((always_inline));\n\tstatic inline void reset(void) __attribute__((always_inline));\n\t\n\t// Decode functions for a single protocol/multiprotocol for less/more accuration\n\tstatic inline void decodeSingle(const uint16_t &duration) __attribute__((always_inline));\n\tstatic inline void decode(const uint16_t &duration) __attribute__((always_inline));\n\npublic:\n\t// Temporary buffer to hold bytes for decoding the protocols\n\t// not all of them are compiled, only the used ones\n\tstatic volatile RAWIR_DATA_T countRawIR;\n\tstatic volatile uint16_t dataRawIR[RAWIR_BLOCKS];\n};\n\n\nuint8_t RawIR::getSingleFlag(void){\n\treturn CHANGE;\n}\n\n\nbool RawIR::requiresCheckTimeout(void){\n\t// Used in this protocol\n\treturn true;\n}\n\n\nvoid RawIR::checkTimeout(void){\n\t// This function is executed with interrupts turned off\n\tif(countRawIR)\n\t{\n\t\t// Check if reading timed out and save value.\n\t\tif ((micros() - IRLLastTime) >= RAWIR_TIMEOUT)\n\t\t{\n\t\t\t// Flag a new input if reading timed out\n\t\t\tcountRawIR--;\n\n\t\t\t// Ignore the very first timeout.\n\t\t\t// This should normally never happen, but in any case\n\t\t\t// try to avoid a timeout only flag with bufferlength 0.\n\t\t\tif(countRawIR){\n\t\t\t\tIRLProtocol = IR_RAW;\n\t\t\t\tIRLLastEvent = IRLLastTime;\n\t\t\t}\n\t\t}\n\t}\n}\n\n\nbool RawIR::available(void)\n{\n\t// Only return a value if this protocol has new data\n\tif(IRLProtocol == IR_RAW)\n\t\treturn true;\n\telse\n\t\treturn false;\t\n}\n\n\nvoid RawIR::read(IR_data_t* data){\n\t// Only (over)write new data if this protocol received any data\n\tif(IRLProtocol == IR_RAW){\n\t\t// Converts the raw code values into a 32-bit hash code.\n\t\t// Hopefully this code is unique for each button.\n\t\t// This isn't a \"real\" decoding, just an arbitrary value.\n\t\t// Code taken from https://github.com/z3t0/Arduino-IRremote\n\n\t\t// Use FNV hash algorithm: http://isthe.com/chongo/tech/comp/fnv/#FNV-param\n#define FNV_PRIME_32 16777619UL\n#define FNV_BASIS_32 2166136261UL\n\n\t\t// Save address as length.\n\t\t// You can check the address/length to prevent triggering on noise\n\t\tdata->address = countRawIR;\n\n\t\t// Iterate through all raw values and calculate a hash\n\t\tuint32_t hash = FNV_BASIS_32;\n\t\tfor (typeof(countRawIR) i = 1; i < countRawIR; i++) {\n\t\t\t// Get both values\n\t\t\tauto oldval = dataRawIR[i - 1];\n\t\t\tauto newval = dataRawIR[i];\n\n\t\t\t// Compare two tick values, returning 0 if newval is shorter,\n\t\t\t// 1 if newval is equal, and 2 if newval is longer\n\t\t\t// Use a tolerance of 75%\n\t\t\tuint8_t value = 1;\n\t\t\tif (newval < (oldval * 3 / 4)) {\n\t\t\t\tvalue = 0;\n\t\t\t}\n\t\t\telse if (oldval < (newval * 3 / 4)) {\n\t\t\t\tvalue = 2;\n\t\t\t}\n\n\t\t\t// Add value into the hash\n\t\t\thash = (hash * FNV_PRIME_32) ^ value;\n\t\t}\n\n\t\t// Save calculated hash\n\t\tdata->command = hash;\n\t}\n}\n\n\nbool RawIR::requiresReset(void){\n\t// Used in this protocol\n\treturn true;\n}\n\n\nvoid RawIR::reset(void){\n\t// Reset protocol for new reading\n\tcountRawIR = 0;\n}\n\n\nvoid RawIR::decodeSingle(const uint16_t &duration){\n\t// Reading timed out\n\tif(duration >= RAWIR_TIMEOUT){\n\t\t// Ignore the very first timeout of each reading.\n\t\tif(countRawIR == 1){\n\t\t\treturn;\n\t\t}\n\t\t// Otherwise flag a new input and stop reading.\n\t\telse if(countRawIR){\n\t\t\tcountRawIR--;\n\t\t\tIRLProtocol = IR_RAW;\n\t\t}\n\t\t// Start a new reading sequence.\n\t\telse{\n\t\t\tcountRawIR++;\n\t\t}\n\t\treturn;\n\t}\n\n\t// Only save data if a sequence is running.\n\t// This is required to avoid corrupted data\n\t// when starting capturing at the middle of a sequence.\n\tif(countRawIR){\n\t\t// Save value and increase count\n\t\tdataRawIR[countRawIR - 1] = duration;\n\t\tcountRawIR++;\n\n\t\t// Flag a new input if buffer is full\n\t\tif((countRawIR > RAWIR_BLOCKS)){\n\t\t\tcountRawIR--;\n\t\t\tIRLProtocol = IR_RAW;\n\t\t}\n\t}\n}\n\n\nvoid RawIR::decode(const uint16_t &duration) {\n\t// Wait some time after the last protocol.\n\t// This way it can finish its (possibly ignored) stop bit.\n\tuint8_t lastProtocol = IRLProtocol | IR_NEW_PROTOCOL;\n\tif(lastProtocol != IR_RAW && lastProtocol != IR_NEW_PROTOCOL && (IRLLastTime - IRLLastEvent < RAWIR_TIME_THRESHOLD)){\n\t\treturn;\n\t}\n\n\tdecodeSingle(duration);\n}\n"
  },
  {
    "path": "extra/old/IRL_Sony.hpp",
    "content": "/*\nCopyright (c) 2014-2015 NicoHood\nSee the readme for credit to other people.\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in\nall copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\nTHE SOFTWARE.\n*/\n\n// Include guard\n#pragma once\n\n//================================================================================\n// Protocol Definitions\n//================================================================================\n\n//SONY 8, 12, 15, 20\n//IRP notation: {40k,600}<1,-1|2,-1>(4,-1,F:8,^22200)\n//IRP notation: {40k,600}<1,-1|2,-1>(4,-1,F:7,D:5,^45m)+\n//IRP notation: {40k,600}<1,-1|2,-1>(4,-1,F:7,D:8,^45m)+\n//IRP notation: {40k,600}<1,-1|2,-1>(4,-1,F:7,D:5,S:8,^45m) +\n// Lead + Mark logic\n#define SONY_HZ\t\t\t\t\t40000\n#define SONY_PULSE\t\t\t\t600UL\n#define SONY_BLOCKS_8\t\t\t1\n#define SONY_BLOCKS_12\t\t\t2\n#define SONY_BLOCKS_15\t\t\t2\n#define SONY_BLOCKS_20\t\t\t3\n#define SONY_ADDRESS_LENGTH_8\t0\n#define SONY_ADDRESS_LENGTH_12\t5\n#define SONY_ADDRESS_LENGTH_15\t8\n#define SONY_ADDRESS_LENGTH_20\t13\n#define SONY_COMMAND_LENGTH_8\t8\n#define SONY_COMMAND_LENGTH_12\t7\n#define SONY_COMMAND_LENGTH_15\t7\n#define SONY_COMMAND_LENGTH_20\t7\n#define SONY_LENGTH_8\t\t\t(2 + (8-1) * 2) // 2 for lead + space, -1 for mark end, 8 bit\n#define SONY_LENGTH_12\t\t\t(2 + (7+5-1) * 2) // 2 for lead + space, -1 for mark end, 12 bit\n#define SONY_LENGTH_15\t\t\t(2 + (7+8-1) * 2) // 2 for lead + space, -1 for mark end, 15 bit\n#define SONY_LENGTH_20\t\t\t(2 + (7+5+8-1) * 2) // 2 for lead + space, -1 for mark end, 20 bit\n#define SONY_TIMEOUT_8\t\t\t22200\n#define SONY_TIMEOUT\t\t\t45000 // 12, 15, 20 have the same timeout\n#define SONY_MARK_LEAD\t\t\t(SONY_PULSE * 4)\n#define SONY_SPACE_LEAD\t\t\t(SONY_PULSE * 1)\n#define SONY_SPACE_HOLDING\t\t0 // no holding function in this protocol\n#define SONY_MARK_ZERO\t\t\t(SONY_PULSE * 1)\n#define SONY_MARK_ONE\t\t\t(SONY_PULSE * 2)\n#define SONY_SPACE_ZERO\t\t\t(SONY_PULSE * 1)\n#define SONY_SPACE_ONE\t\t\t(SONY_PULSE * 1)\n\n//================================================================================\n// Decoding Class\n//================================================================================\n\nclass Sony : public CIRLData{\npublic:\n\tSony(void){\n\t\t// Empty\t\n\t}\n\t\n\t// Hide anything that is inside this class so the user dont accidently uses this class\n\ttemplate<typename protocol, typename ...protocols>\n\tfriend class CIRLremote;\n\t\nprivate:\n\tstatic inline uint8_t getSingleFlag(void) __attribute__((always_inline));\n\tstatic inline bool requiresCheckTimeout(void) __attribute__((always_inline));\n\tstatic inline void checkTimeout(void) __attribute__((always_inline));\n\tstatic inline bool available(void) __attribute__((always_inline));\n\tstatic inline void read(IR_data_t* data) __attribute__((always_inline));\n\tstatic inline bool requiresReset(void) __attribute__((always_inline));\n\tstatic inline void reset(void) __attribute__((always_inline));\n\n\t// Decode functions for a single protocol/multiprotocol for less/more accuration\n\tstatic inline void decodeSingle(const uint16_t &duration) __attribute__((always_inline));\n\tstatic inline void decode(const uint16_t &duration) __attribute__((always_inline));\n\nprotected:\n\t// Temporary buffer to hold bytes for decoding the protocols\n\t// not all of them are compiled, only the used ones\n\tstatic uint8_t countSony;\n\tstatic uint8_t dataSony[SONY_BLOCKS_12];\n};\n\n\nuint8_t Sony::getSingleFlag(void){\n\treturn CHANGE; //TODO change to RISING and implement function\n}\n\n\nbool Sony::requiresCheckTimeout(void){\n\t// Used in this protocol\n\treturn true;\n}\n\n\nvoid Sony::checkTimeout(void){\n\t// Only check for timeout if the last protocol was Sony\n\tuint8_t lastProtocol = IRLProtocol | IR_NEW_PROTOCOL;\n\tif(lastProtocol == IR_SONY12)\n\t{\n\t\t// Reset if a keypress ended to ensure\n\t\t// the next reading does not trigger\n\t\t// the first and 3rd signal (instead of the 2nd).\n\t\tif ((micros() - IRLLastTime) >= SONY_TIMEOUT) {\n\t\t\treset();\n\t\t}\n\t}\n}\n\n\nbool Sony::available(void)\n{\n\t// Only return a value if this protocol has new data\n\tif(IRLProtocol == IR_SONY12) //TODO\n\t\treturn true;\n\telse\n\t\treturn false;\t\n}\n\n\nvoid Sony::read(IR_data_t* data){\n\t// Only (over)write new data if this protocol received any data\n\tif(IRLProtocol == IR_SONY12){\n\t\t//TODO\n\t\t// protocol has no checksum\n\t\tuint8_t upper4Bits = ((dataSony[1] >> 3) & 0x1E);\n\t\tif (dataSony[0] & 0x80)\n\t\t\tupper4Bits |= 0x01;\n\n\t\tdata->address = upper4Bits;\n\t\tdata->command = dataSony[0] & 0x7F;\n\t}\n}\n\n\nbool Sony::requiresReset(void){\n\t// Used in this protocol\n\treturn true;\n}\n\n\nvoid Sony::reset(void){\n\tcountSony = 0;\n\n\t// Remove last protocol flag\n\t// This prevents the remote from triggering again\n\t// When the very first of three signals is recived\n\t// and the last keypress was already sony.\n\t// This also ensures that then 3rd signal is\n\t// also ignored. After this every 2nd signal\n\t// is recognized correct.\n\tif((IRLProtocol | IR_NEW_PROTOCOL) == IR_SONY12){\n\t\tIRLProtocol = IR_NO_PROTOCOL;\n\t}\n}\n\n\nvoid Sony::decodeSingle(const uint16_t &duration){\n\t// not implemented TODO\n\tdecode(duration);\n}\n\n\nvoid Sony::decode(const uint16_t &duration) {\n\t// spaceTimeout gives some better accuracy, since we dont have a checksum here.\n\t// also set markTimeout if needed.\n\tconst uint8_t irLength = SONY_LENGTH_12;\n\tconst uint16_t timeoutThreshold = (SONY_TIMEOUT + SONY_MARK_LEAD) / 2;\n\tconst uint16_t markLeadThreshold = (SONY_MARK_LEAD + SONY_MARK_ONE) / 2;\n\tconst uint16_t markThreshold = (SONY_MARK_ONE + SONY_MARK_ZERO) / 2;\n\tconst uint16_t markTimeout = 0; // (SONY_MARK_LEAD + SONY_MARK_ONE) / 2\n\tconst uint16_t spaceTimeout = SONY_MARK_ONE;\n\n\t// if timeout always start next possible reading and abort any pending readings\n\t//TODO maybe use the sending 3 times to determine sony 12 vs 20\n\t// call the event from here after 2nd valid input if its still smaller than x\n\tif (duration >= timeoutThreshold)\n\t\tcountSony = 1;\n\n\t// on a reset (error in decoding) we are waiting for a timeout to start a new reading again\n\t// this is to not conflict with other protocols while they are sending 0/1 which might be similar to a lead in another protocol\n\telse if (countSony == 0)\n\t\treturn;\n\n\t// check pulses for mark/space and lead + logical 0/1 seperate\n\telse {\n\t\t// Mark pulses (odd numbers)\n\t\tif (countSony % 2 == 1) {\n\t\t\t// check Mark Lead (needs a timeout or a correct signal)\n\t\t\tif (countSony == 1) {\n\t\t\t\t// wrong lead\n\t\t\t\tif (duration < markLeadThreshold) {\n\t\t\t\t\tcountSony = 0;\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\telse {\n\t\t\t\t// check for timeout if needed (might be a different protocol)\n\t\t\t\tif (markTimeout && duration > markTimeout) {\n\t\t\t\t\tcountSony = 0;\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\t// check different logical space pulses\n\n\t\t\t\t// get number of the Mark Bits (starting from zero)\n\t\t\t\t// only save every 2nd value, substract the first two lead pulses\n\t\t\t\tuint8_t length = (countSony / 2) - 1;\n\n\t\t\t\t// move bits and write 1 or 0 depending on the duration\n\t\t\t\tbool LSB = dataSony[length / 8] & 0x01;\n\t\t\t\tdataSony[length / 8] >>= 1;\n\n\t\t\t\t// set bit if it's a logical 1. Setting zero not needed due to bitshifting.\n\t\t\t\tbool logicBit = duration >= markThreshold;\n\t\t\t\tif (logicBit){\n\t\t\t\t\tdataSony[length / 8] |= 0x80;\n\t\t\t\t}\n\n\t\t\t\t// Compare if new data is equal with last.\n\t\t\t\t// If not, remove the pressed flag and mark\n\t\t\t\t// the data as corrupted.\n\t\t\t\t// A new series is then required.\n\t\t\t\t// This is possible with Sony since it sends the\n\t\t\t\t// data always 3 times + X holding.\n\t\t\t\tif(LSB != logicBit){\n\t\t\t\t\tif((IRLProtocol | IR_NEW_PROTOCOL) == IR_SONY12){\n\t\t\t\t\t\tIRLProtocol = IR_NO_PROTOCOL;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t// check last input (always a mark)\n\t\t\t\tif (countSony > irLength) {\n\t\t\t\t\t// reset reading\n\t\t\t\t\tcountSony = 0;\n\n\t\t\t\t\tuint8_t lastProtocol = IRLProtocol | IR_NEW_PROTOCOL;\n\n\t\t\t\t\t// Sony has no checksum\n\t\t\t\t\tIRLProtocol = IR_SONY12;\n\n\t\t\t\t\t// Trigger only on 2nd press and onwards\n\t\t\t\t\t// Sony normally should trigger 3 times anyways.\n\t\t\t\t\t// Normally it is recommended to check the last received data\n\t\t\t\t\t// and compare them with the 2nd (and 3rd) press.\n\t\t\t\t\t// TODO compare this while decoding (writing)\n\t\t\t\t\t// and remove lastProtocol if its unequal\n\t\t\t\t\t// This is also required to differenciate between Sony 12 and 20.\n\t\t\t\t\t// TODO the reset should then not happen\n\t\t\t\t\tif(lastProtocol != IR_SONY12){\n\t\t\t\t\t\tIRLProtocol &= (~IR_NEW_PROTOCOL);\n\t\t\t\t\t}\n\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Space pulses (even numbers)\n\t\telse {\n\t\t\t// check for timeout if needed (might be a different protocol)\n\t\t\t// we could only check the lead or all data,\n\t\t\t// since the pulse should be always the same for lead and data\n\t\t\t// all data gives better errorcorrection and takes less flash\n\t\t\tif (spaceTimeout && duration > spaceTimeout) {\n\t\t\t\tcountSony = 0;\n\t\t\t\treturn;\n\t\t\t}\n\t\t}\n\n\t\t// next reading, no errors\n\t\tcountSony++;\n\t}\n}\n\n\n/*\n\n\ntemplate <IRType ...irProtocol>\ninline void CIRLremote<debounce, irProtocol...>::\ndecodeSony20(const uint16_t duration) {\n\t//// pass the duration to the decoding function\n\t//bool newInput;\n\t//// 1st extra accuracy solution\n\t//if (sizeof...(irProtocol) != 1)\n\t//\tnewInput = IRLdecode <SONY_LENGTH_20, (SONY_TIMEOUT + SONY_MARK_LEAD) / 2, // irLength, timeoutThreshold\n\t//\t(SONY_MARK_LEAD + SONY_MARK_ONE) / 2, 0, // markLeadThreshold, spaceLeadThreshold\n\t//\t0, (SONY_MARK_ONE + SONY_MARK_ZERO) / 2, // spaceLeadHoldingThreshold, markThreshold\n\t//\t0, // spaceThreshold\n\t//\t(SONY_MARK_LEAD + SONY_MARK_ONE) / 2, SONY_MARK_ONE>// markTimeout, spaceTimeout\n\t//\t(duration, dataSony20, countSony20);\n\t//else\n\t//\tnewInput = IRLdecode <SONY_LENGTH_20, (SONY_TIMEOUT + SONY_MARK_LEAD) / 2, // irLength, timeoutThreshold\n\t//\t(SONY_MARK_LEAD + SONY_MARK_ONE) / 2, 0, // markLeadThreshold, spaceLeadThreshold\n\t//\t0, (SONY_MARK_ONE + SONY_MARK_ZERO) / 2, // spaceLeadHoldingThreshold, markThreshold\n\t//\t0, // spaceThreshold\n\t//\t0, 0>// markTimeout, spaceTimeout\n\t//\t(duration, dataSony20, countSony20);\n\n\t//if (newInput){\n\t//\t// protocol has no checksum\n\t//\tuint8_t upper5Bits = ((dataSony20[2] >> 2) & 0x3E);\n\t//\tuint8_t lsb = (dataSony20[0] >> 7) & 0x01;\n\t//\tuint16_t address = (upper5Bits << 8) | (dataSony20[1] << 1) | lsb;\n\t//\tuint32_t command = dataSony20[0] & 0x7F;\n\t//\t// 2nd extra accuracy solution\n\t//\t//if ((sizeof...(irProtocol) != 1) && (address || command))\n\t//\tIREvent(IR_SONY20, address, command);\n\n\t//\t// reset reading\n\t//\tcountSony20 = 0;\n\t//}\n}\n\n//\n//\n//template <IRType ...irProtocol>\n//template <uint8_t irLength, uint16_t timeoutThreshold, uint16_t markLeadThreshold, uint16_t spaceLeadThreshold,\n//\tuint16_t spaceLeadHoldingThreshold, uint16_t markThreshold, uint16_t spaceThreshold,\n//\tuint16_t markTimeout, uint16_t spaceTimeout>\n//\tinline bool CIRLremote<debounce, irProtocol...>::\n//\tIRLdecode(uint16_t duration, uint8_t data[], uint8_t &count){\n//\n//\t// if timeout always start next possible reading and abort any pending readings\n//\tif (duration >= timeoutThreshold)\n//\t\tcount = 1;\n//\n//\t// on a reset (error in decoding) we are waiting for a timeout to start a new reading again\n//\t// this is to not conflict with other protocols while they are sending 0/1 which might be similar to a lead in another protocol\n//\telse if (count == 0)\n//\t\treturn false;\n//\n//\t// check pulses for mark/space and lead + logical 0/1 seperate\n//\telse{\n//\t\t// Mark pulses (odd numbers)\n//\t\tif (count % 2 == 1){\n//\t\t\t// check Mark Lead (needs a timeout or a correct signal)\n//\t\t\tif (markLeadThreshold && count == 1){\n//\t\t\t\t// wrong lead\n//\t\t\t\tif (duration <= markLeadThreshold){\n//\t\t\t\t\tcount = 0;\n//\t\t\t\t\treturn false;\n//\t\t\t\t}\n//\t\t\t}\n//\n//\t\t\telse{\n//\t\t\t\t// check for timeout if needed (might be a different protocol)\n//\t\t\t\tif (markTimeout && duration > markTimeout){\n//\t\t\t\t\tcount = 0;\n//\t\t\t\t\treturn false;\n//\t\t\t\t}\n//\n//\t\t\t\t// only check values if the protocol has different logical space pulses\n//\t\t\t\telse if (markThreshold){\n//\n//\t\t\t\t\t// get number of the Mark Bits (starting from zero)\n//\t\t\t\t\tuint8_t length;\n//\t\t\t\t\t// only save every 2nd value, substract the first two lead pulses\n//\t\t\t\t\tif (!spaceThreshold)\n//\t\t\t\t\t\tlength = (count / 2) - 1;\n//\t\t\t\t\t// special case: spaces and marks both have data in the pulse\n//\t\t\t\t\telse length = count - 2;\n//\n//\t\t\t\t\t// move bits and write 1 or 0 depending on the duration\n//\t\t\t\t\t// 1.7: changed from MSB to LSB. somehow takes a bit more flash but is correct and easier to handle.\n//\t\t\t\t\tdata[length / 8] >>= 1;\n//\t\t\t\t\tif (duration > markThreshold)\n//\t\t\t\t\t\tdata[length / 8] |= 0x80;\n//\t\t\t\t\t//else // normally not needed through the bitshift\n//\t\t\t\t\t//\tdata[length / 8] &= ~0x80;\n//\t\t\t\t}\n//\n//\t\t\t\t// check last input (always a mark)\n//\t\t\t\tif (count > irLength){\n//\t\t\t\t\t// reset by decoding function\n//\t\t\t\t\t//count = 0;\n//\t\t\t\t\treturn true;\n//\t\t\t\t}\n//\t\t\t}\n//\t\t}\n//\n//\t\t// Space pulses (even numbers)\n//\t\telse{\n//\t\t\t//check Space Lead/Space Holding\n//\t\t\tif (spaceLeadThreshold && count == 2){\n//\t\t\t\t// normal Space, next reading\n//\t\t\t\tif (duration > spaceLeadThreshold);\n//\n//\t\t\t\t// Button holding (if supported by protocol)\n//\t\t\t\telse if (spaceLeadHoldingThreshold && duration > spaceLeadHoldingThreshold){\n//\t\t\t\t\t// call the holding function after\n//\t\t\t\t\t// count not resetted to read it afterwards\n//\t\t\t\t\t// next mark ignored due to detecting techniques\n//\t\t\t\t\t//count = 0;\n//\t\t\t\t\treturn true;\n//\t\t\t\t}\n//\t\t\t\t// wrong space\n//\t\t\t\telse {\n//\t\t\t\t\tcount = 0;\n//\t\t\t\t\treturn false;\n//\t\t\t\t}\n//\t\t\t}\n//\t\t\telse{\n//\t\t\t\t// check for timeout if needed (might be a different protocol)\n//\t\t\t\tif (spaceTimeout && duration > spaceTimeout){\n//\t\t\t\t\tcount = 0;\n//\t\t\t\t\treturn false;\n//\t\t\t\t}\n//\n//\t\t\t\t// only check values if the protocol has different logical space pulses\n//\t\t\t\telse if (spaceThreshold){\n//\n//\t\t\t\t\t// get number of the Space Bits (starting from zero)\n//\t\t\t\t\tuint8_t length;\n//\t\t\t\t\t// only save every 2nd value, substract the first two lead pulses\n//\t\t\t\t\tif (!markThreshold)\n//\t\t\t\t\t\tlength = (count / 2) - 2;\n//\t\t\t\t\t// special case: spaces and marks both have data in the pulse\n//\t\t\t\t\telse length = count - 2;\n//\n//\t\t\t\t\t// move bits and write 1 or 0 depending on the duration\n//\t\t\t\t\t// 1.7: changed from MSB to LSB. somehow takes a bit more flash but is correct and easier to handle.\n//\t\t\t\t\tdata[length / 8] >>= 1;\n//\t\t\t\t\tif (duration > spaceThreshold)\n//\t\t\t\t\t\tdata[length / 8] |= 0x80;\n//\t\t\t\t\t//else // normally not needed through the bitshift\n//\t\t\t\t\t//\tdata[length / 8] &= ~0x80;\n//\t\t\t\t}\n//\t\t\t}\n//\t\t}\n//\n//\t\t// next reading, no errors\n//\t\tcount++;\n//\t}\n//\n//\t// no valid input (yet)\n//\treturn false;\n//}\n\n*/\n"
  },
  {
    "path": "extra/old/IRLremote.cpp",
    "content": "/*\nCopyright (c) 2014-2015 NicoHood\nSee the readme for credit to other people.\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in\nall copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\nTHE SOFTWARE.\n*/\n\n#include \"IRLremote.h\"\n\n//================================================================================\n// Static Data\n//================================================================================\n\n// Protocol temporary data\nuint8_t Nec::countNec = 0;\nuint8_t Nec::dataNec[NEC_BLOCKS] = { 0 };\nvolatile uint8_t Nec::protocol = IR_NO_PROTOCOL;\nuint32_t Nec::lastTime = 0;\nvolatile uint32_t Nec::lastEvent = 0;\n\n\nuint8_t Panasonic::countPanasonic = 0;\nuint8_t Panasonic::dataPanasonic[PANASONIC_BLOCKS] = { 0 };\nuint8_t Sony::countSony = 0;\nuint8_t Sony::dataSony[SONY_BLOCKS_12] = { 0 };\nvolatile RAWIR_DATA_T RawIR::countRawIR = 0;\nvolatile uint16_t RawIR::dataRawIR[RAWIR_BLOCKS] = { 0 };\nuint16_t HashIR::durationHashIR = 0;\nuint16_t HashIR::countHashIR = 0;\nuint32_t HashIR::commandHashIR = FNV_BASIS_32;\n\n// Main/shared remote data\nvolatile uint8_t CIRLData::IRLProtocol = IR_NO_PROTOCOL;\nuint32_t CIRLData::IRLLastTime = 0;\nvolatile uint32_t CIRLData::IRLLastEvent = 0;\n"
  },
  {
    "path": "extra/old/IRLremoteReceive.hpp",
    "content": "/*\nCopyright (c) 2014-2015 NicoHood\nSee the readme for credit to other people.\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in\nall copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\nTHE SOFTWARE.\n*/\n\n// include guard\n#pragma once\n\n//================================================================================\n// User Functions\n//================================================================================\n\ntemplate<typename protocol, typename ...protocols>\nCIRLremote<protocol, protocols...>::\nCIRLremote(void) {\n\t// Empty\n}\n\n\ntemplate<typename protocol, typename ...protocols>\nbool CIRLremote<protocol, protocols...>::\nbegin(uint8_t pin)\n{\n\t// Get pin ready for reading.\n\t// This is normally not required with a static setup\n\t// But for dynamic plugging it is.\n\tpinMode(pin, INPUT_PULLUP);\n\n\t// For single protocols use a different flag\n\tuint8_t flag = CHANGE;\n\tif(sizeof...(protocols) == 0){\n\t\tflag = protocol::getSingleFlag();\n\t}\n\n\t// Try to attach PinInterrupt first\n\tif (digitalPinToInterrupt(pin) != NOT_AN_INTERRUPT){\n\t\tattachInterrupt(digitalPinToInterrupt(pin), interrupt, flag);\n\t\treturn true;\n\t}\n\n\t// If PinChangeInterrupt library is used, try to attach it\n#ifdef PCINT_VERSION\n\telse if (digitalPinToPCINT(pin) != NOT_AN_INTERRUPT){\n\t\tattachPCINT(digitalPinToPCINT(pin), interrupt, flag);\n\t\treturn true;\n\t}\n#endif\n\n\t// Return an error if none of them work (pin has no Pin(Change)Interrupt)\n\treturn false;\n}\n\n\ntemplate<typename protocol, typename ...protocols>\nbool CIRLremote<protocol, protocols...>::\nend(uint8_t pin)\n{\n\t// Disable pullup.\n\tpinMode(pin, INPUT);\n\n\t// Try to detach PinInterrupt first\n\tif (digitalPinToInterrupt(pin) != NOT_AN_INTERRUPT){\n\t\tdetachInterrupt(digitalPinToInterrupt(pin));\n\t\treturn true;\n\t}\n\n\t// If PinChangeInterrupt library is used, try to detach it\n#ifdef PCINT_VERSION\n\telse if (digitalPinToPCINT(pin) != NOT_AN_INTERRUPT){\n\t\tdetachPCINT(digitalPinToPCINT(pin));\n\t\treturn true;\n\t}\n#endif\n\n\t// Return an error if none of them work (pin has no Pin(Change)Interrupt)\n\treturn false;\n}\n\n\ntemplate<typename protocol, typename ...protocols>\nbool CIRLremote<protocol, protocols...>::\navailable(void)\n{\n\t// Only add this overhead if we have multiple protocols\n\t// Or the protocol requires a timeout check.\n\tif(sizeof...(protocols) != 0 || protocol::requiresCheckTimeout())\n\t{\n\t\t// Disable interrupts when checking for new input\n\t\tuint8_t oldSREG = SREG;\n\t\tcli();\n\n\t\t// Let each protocol check if their timeout expired. Not all protocols use this.\n\t\tif(!(IRLProtocol & IR_NEW_PROTOCOL)){\n\t\t\tprotocol::checkTimeout();\n\t\t\tnop((protocols::checkTimeout(), 0)...);\n\t\t}\n\t\tSREG = oldSREG;\n\t}\n\n\t// This if construct saves flash\n\tif(IRLProtocol & IR_NEW_PROTOCOL)\n\t\treturn true;\n\telse\n\t\treturn false;\n}\n\n\ntemplate<typename protocol, typename ...protocols>\nIR_data_t CIRLremote<protocol, protocols...>::\nread(void)\n{\n\t// If nothing was received return an empty struct\n\tIR_data_t data = IR_data_t();\n\n\t// Only the received protocol will write data into the struct\n\tuint8_t oldSREG = SREG;\n\tcli();\n\n\t// Get new data, if any\n\tif(IRLProtocol & IR_NEW_PROTOCOL)\n\t{\n\t\t// Check if we actually have new data and save the protocol as well\n\t\tdata.address = ((uint16_t)dataNec[1] << 8) | ((uint16_t)dataNec[0]);\n\t\tdata.command = ((uint16_t)dataNec[3] << 8) | ((uint16_t)dataNec[2]);\n\t\tdata.protocol = IRLProtocol;\n\n\t\t// Remove new protocol flag\n\t\tIRLProtocol &= ~IR_NEW_PROTOCOL;\n\n\t\t// Set last ISR to current time.\n\t\t// This is required to not trigger a timeout afterwards\n\t\t// and read corrupted data. This might happen\n\t\t// if the reading loop is too slow.\n\t\tIRLLastTime = micros();\n\t}\n\tSREG = oldSREG;\n\n\t// Process API TODO\n\n\t// Return the new protocol information to the user\n\treturn data;\n}\n\n\ntemplate<typename protocol, typename ...protocols>\nvoid CIRLremote<protocol, protocols...>::\nreset(void)\n{\n\t// Call all protocol reset functions\n\tprotocol::reset();\n\tnop((protocols::reset(), 0)...);\n}\n\n\n//================================================================================\n// Interrupt Function\n//================================================================================\n\ntemplate<typename protocol, typename ...protocols>\nvoid CIRLremote<protocol, protocols...>::\ninterrupt(void)\n{\n\t// Block if the protocol is already recognized\n\tif(IRLProtocol & IR_NEW_PROTOCOL)\n\t\treturn;\n\n\t// Save the duration between the last reading\n\tuint32_t time = micros();\n\tuint32_t duration_32 = time - IRLLastTime;\n\tIRLLastTime = time;\n\n\t// Calculate 16 bit duration. On overflow sets duration to a clear timeout\n\tuint16_t duration = 0xFFFF;\n\tif (duration_32 <= 0xFFFF)\n\t\tduration = duration_32;\n\n\t\t// For a single protocol use a simpler decode function\n\t\t// to get maximum speed + recognition and minimum flash size\n\t\tprotocol::decodeSingle(duration);\n\n\t// New valid signal, save new time\n\tif(IRLProtocol & IR_NEW_PROTOCOL) {\n\t\tIRLLastEvent = IRLLastTime;\n\t}\n}\n"
  },
  {
    "path": "extra/old/IRLremoteTransmit.hpp",
    "content": "/*\nCopyright (c) 2014-2015 NicoHood\nSee the readme for credit to other people.\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in\nall copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\nTHE SOFTWARE.\n*/\n\n// include guard\n#pragma once\n\n//================================================================================\n// Definitions\n//================================================================================\n\n// definition for sending to determine what should be send first\n#define IR_ADDRESS_FIRST true\n#define IR_COMMAND_FIRST false\n\n// definition to convert an uint8_t array to an uint16_t/uint32_t at any position (thx timeage!)\n#define UINT16_AT_OFFSET(p_to_8, offset)    ((uint16_t)*((const uint16_t *)((p_to_8)+(offset))))\n#define UINT32_AT_OFFSET(p_to_8, offset)    ((uint32_t)*((const uint32_t *)((p_to_8)+(offset))))\n\n// definition to get the higher value\n#define MAX(a,b) \\\n   ({ __typeof__ (a) _a = (a); \\\n       __typeof__ (b) _b = (b); \\\n     _a > _b ? _a : _b; })\n\n// definition to get the lower value\n#define MIN(a,b) \\\n   ({ __typeof__ (a) _a = (a); \\\n       __typeof__ (b) _b = (b); \\\n     _a < _b ? _a : _b; })\n\n\n//================================================================================\n// Inline Implementations (send)\n//================================================================================\n\ntemplate <IRType irType>\nvoid IRLwrite(const uint8_t pin, uint16_t address, uint32_t command)\n{\n\t// get the port mask and the pointers to the out/mode registers for faster access\n\tuint8_t bitMask = digitalPinToBitMask(pin);\n\tuint8_t port = digitalPinToPort(pin);\n\tvolatile uint8_t * outPort = portOutputRegister(port);\n\tvolatile uint8_t * modePort = portModeRegister(port);\n\n\t// set pin to OUTPUT and LOW\n\t*modePort |= bitMask;\n\t*outPort &= ~bitMask;\n\n\t// disable interrupts\n\tuint8_t oldSREG = SREG;\n\tcli();\n\n\tswitch (irType) {\n\n\tcase IR_NEC:\n\t\t// NEC only sends the data once\n\t\tif (command == 0xFFF)\n\t\t\t// send holding indicator\n\t\t\tIRLsend<0, 0, NEC_HZ, 0, NEC_MARK_LEAD, NEC_SPACE_HOLDING,\n\t\t\t        0, 0, 0, 0>\n\t\t\t        (outPort, bitMask, address, command);\n\t\telse\n\t\t\t// send data\n\t\t\tIRLsend<NEC_ADDRESS_LENGTH, NEC_COMMAND_LENGTH, NEC_HZ, IR_ADDRESS_FIRST, NEC_MARK_LEAD, NEC_SPACE_LEAD,\n\t\t\t        NEC_MARK_ZERO, NEC_MARK_ONE, NEC_SPACE_ZERO, NEC_SPACE_ONE>\n\t\t\t        (outPort, bitMask, address, command);\n\t\tbreak;\n\n\tcase IR_PANASONIC: //TODO test\n\t\t// send data\n\t\tIRLsend<PANASONIC_ADDRESS_LENGTH, PANASONIC_COMMAND_LENGTH, PANASONIC_HZ, IR_ADDRESS_FIRST, PANASONIC_MARK_LEAD, PANASONIC_SPACE_LEAD,\n\t\t        PANASONIC_MARK_ZERO, PANASONIC_MARK_ONE, PANASONIC_SPACE_ZERO, PANASONIC_SPACE_ONE>\n\t\t        (outPort, bitMask, address, command);\n\t\tbreak;\n\n\tcase IR_SONY12: //TODO test, address -1?\n\t\t// repeat 3 times\n\t\tfor (uint8_t i = 0; i < 3; i++)\n\t\t\t// send data\n\t\t\tIRLsend<SONY_ADDRESS_LENGTH_12, SONY_COMMAND_LENGTH_12, SONY_HZ, IR_COMMAND_FIRST, SONY_MARK_LEAD, SONY_SPACE_LEAD,\n\t\t\t        SONY_MARK_ZERO, SONY_MARK_ONE, SONY_SPACE_ZERO, SONY_SPACE_ONE>\n\t\t\t        (outPort, bitMask, address, command);\n\t\tbreak;\n\t}\n\n\t// enable interrupts\n\tSREG = oldSREG;\n\n\t// set pin to INPUT again to be save\n\t*modePort &= ~bitMask;\n}\n\n// multifunctional template for sending\ntemplate <uint8_t addressLength, uint8_t commandLength,\n          uint16_t Hz, bool addressFirst,\n          uint16_t markLead, uint16_t spaceLead,\n          uint16_t markZero, uint16_t markOne,\n          uint16_t spaceZero, uint16_t spaceOne>\nvoid IRLsend(volatile uint8_t * outPort, uint8_t bitmask, uint16_t address, uint32_t command) {\n\n\t// send lead mark\n\tif (markLead)\n\t\tIRLmark(Hz, outPort, bitmask, markLead);\n\n\t// send lead space\n\tif (spaceLead)\n\t\tIRLspace(outPort, bitmask, spaceLead);\n\n\t// abort if input values are both the same (sending a holding signal for example)\n\tif (markOne != markZero || spaceOne != spaceZero)\n\t{\n\t\t// go through all bits\n\t\tfor (uint8_t i = 0; i < (addressLength + commandLength); i++) {\n\t\t\t// determine if its a logical one or zero, starting with address or command\n\t\t\tbool bitToSend;\n\t\t\tif (addressFirst && i < addressLength || !addressFirst && i >= commandLength) {\n\t\t\t\tbitToSend = address & 0x01;\n\t\t\t\taddress >>= 1;\n\t\t\t}\n\t\t\telse {\n\t\t\t\tbitToSend = command & 0x01;\n\t\t\t\tcommand >>= 1;\n\t\t\t}\n\n\t\t\t// send logic mark bits if needed\n\t\t\tif (markOne != markZero) {\n\t\t\t\t// modulate if spaces dont have logic, else only every even number\n\t\t\t\tif (spaceOne == spaceZero || spaceOne != spaceZero && i % 2 == 0)\n\t\t\t\t{\n\t\t\t\t\tif (bitToSend)\n\t\t\t\t\t\tIRLmark(Hz, outPort, bitmask, markOne);\n\t\t\t\t\telse\n\t\t\t\t\t\tIRLmark(Hz, outPort, bitmask, markZero);\n\t\t\t\t}\n\t\t\t}\n\t\t\telse\n\t\t\t\tIRLmark(Hz, outPort, bitmask, markOne);\n\n\t\t\t// send logic space bits if needed\n\t\t\tif (spaceOne != spaceZero) {\n\t\t\t\t// modulate if marks dont have logic, else only every odd number\n\t\t\t\tif (markOne == markZero || markOne != markZero && i % 2 == 1) {\n\t\t\t\t\tif (bitToSend)\n\t\t\t\t\t\tIRLspace(outPort, bitmask, spaceOne);\n\t\t\t\t\telse\n\t\t\t\t\t\tIRLspace(outPort, bitmask, spaceZero);\n\t\t\t\t}\n\t\t\t}\n\t\t\telse\n\t\t\t\tIRLspace(outPort, bitmask, spaceOne);\n\t\t}\n\t}\n\n\t// finish mark\n\tIRLmark(Hz, outPort, bitmask, markZero); //TODO zero or one for sony?\n\tIRLspace(outPort, bitmask, 0);\n}\n\nvoid IRLmark(const uint16_t Hz, volatile uint8_t * outPort, uint8_t bitMask, uint16_t time) {\n\t/*\n\tBitbangs PWM in the given Hz number for the given time\n\t________________________________________________________________________________\n\tDelay calculation:\n\tF_CPU/1.000.000 to get number of cycles/uS\n\t/3 to get the number of loops needed for 1ms (1loop = 3 cycles)\n\n\tMultiply with the number of ms delay:\n\t1/kHz to get the seconds\n\t* 1.000.000 to get it in uS\n\t/2 to get half of a full pulse\n\n\tSubstract the while, portmanipulation, loop overhead /3 loop cycles\n\n\tF_CPU(16.000.000)            1 * 1.000.000(pulse in uS)   12(overhead)\n\t========================== * ========================== - ==============\n\t1.000.000 * 3(loop cycles)   Hz * 2(half of a pulse)      3(loop cycles)\n\n\t<==>\n\n\tF_CPU(16.000.000) - (12(overhead) * Hz * 2(half of a pulse))\n\t===========================================================\n\tHz * 2(half of a on/off pulse) * 3(loop cycles)\n\n\t________________________________________________________________________________\n\tIterations calculation:\n\tDevide time with cycles in while loop\n\tMultiply this with the cycles per uS\n\tcycles per while loop: 3(loop cycles) * delay + overhead\n\n\ttime * (F_CPU(16.000.000) / 1.000.000)\n\t======================================\n\tdelay*3(loop cycles) + overhead\n\t*/\n\n\tconst uint32_t loopCycles = 3;\n\tconst uint32_t overHead = 12; // just a guess from try + error\n\tuint8_t delay = (F_CPU - (overHead * Hz * 2UL)) / (Hz * 2UL * loopCycles);\n\tuint16_t iterations = (time * (F_CPU / 1000000UL)) / (delay * loopCycles + overHead);\n\n\t// modulate IR signal\n\twhile (iterations--) {\n\t\t// flip pin state and wait for the calculated time\n\t\t*outPort ^= bitMask;\n#ifdef ARDUINO_ARCH_AVR\n\t\t// loop\n\t\t_delay_loop_1(delay);\n#else\n\t\t// ARM TODO?\n#endif\n\t}\n\n\t// register uint8_t temp;\n\t// asm volatile (\n\t//     // flip pin state\n\t//     \".L%=_iteration_loop:\\n\"\n\t//     \"ld %[temp], %a[outPort]\\n\" // (2) read the pin (happens before the 2 cycles)\n\t//     \"eor %[temp], %[bitMask]\\n\" // (1) XOR value\n\t//     \"st %a[outPort],%[temp]\\n\"\t// (2) flip pin state TODO happens before or after the 2 cycles\n\n\t//     // wait some time to modulate the Hz\n\t//     \"mov %[temp],%[delay]\\n\"\t// (1) load delay value into temp\n\t//     \".L%=_delay_loop:\\n\"\n\t//     \"dec %[temp]\\n\"\t\t\t\t// (1) decrement 1 from delay counter\n\t//     \"brne .L%=_delay_loop\\n\"\t// (1/2) wait until delay is over\n\n\t//     // check if all pulses have been sent\n\n\t//     //TODO set pin low\n\t//     \"eor %[bitMask], %[bitMask]\\n\" // (1) XOR value\n\t//     \"ld %[temp], %a[outPort]\\n\" // (2) read the pin (happens before the 2 cycles)\n\t//     \"and %[temp], %[bitMask]\\n\" // (1) AND value\n\t//     \"st %a[outPort],%[temp]\\n\"\t// (2) set pin low TODO happens before or after the 2 cycles\n\n\t//     //MOVF    NumL, F; Test lo byte\n\t//     //BTFSC   STATUS, Z; Skip if not zero\n\t//     //DECF    NumH, F; Decrement hi byte\n\t//     //DECF    NumL, F; Decrement lo byte\n\n\t//     // decrement low byte\n\t//     // check if low byte is 255\n\t//     // if yes decrement high byte\n\t//     // check if high byte is zero, if yes and function\n\t//     // if no decrement\n\t//     // jump to loop above\n\t//     // end of loop\n\n\t//     // ----------\n\t//     // outputs:\n\t//     : [outPort] \"+e\" (outPort), // (read and write)\n\t//     [temp] \"=&r\" (temp), // (output only)\n\n\t//     // inputs:\n\t//     : [delay] \"r\" (delay),\n\t//     [bitMask] \"r\" (bitMask)\n\n\t//     // no clobbers\n\t// ); // end of asm volatile\n}\n//}\n//\n//\t// abort if input values are both the same (sending a holding signal for example)\n//\tif (markOne != markZero || spaceOne != spaceZero)\n//\t{\n//\t\t// go through all bits\n//\t\tfor (uint8_t i = 0; i < (addressLength + commandLength); i++){\n//     5f4:\t8c e2       \tldi\tr24, 0x2C\t; 44\n//     5f6:\t90 e0       \tldi\tr25, 0x00\t; 0\n//     5f8:\t01 97       \tsbiw\tr24, 0x01\t; 1\n//\tconst uint32_t overHead = 12; // just a guess from try + error\n//\tuint8_t delay = (F_CPU - (overHead * Hz * 2UL)) / (Hz * 2UL * loopCycles);\n//\tuint16_t iterations = (time*(F_CPU / 1000000UL)) / (delay * loopCycles + overHead);\n//\n//\t// modulate IR signal\n//\twhile (iterations--){\n//     5fa:\t39 f0       \tbreq\t.+14     \t; 0x60a <loop+0x204>\n//\t\t// flip pin state and wait for the calculated time\n//\t\t*outPort ^= bitMask;\n//\n//     //5fc:\t28 81       \tld\tr18, Y\n//     //5fe:\t27 25       \teor\tr18, r7\n//     //600:\t28 83       \tst\tY, r18\n//\n//     602:\t25 2d       \tmov\tr18, r5\n//     604:\t2a 95       \tdec\tr18\n//     606:\tf1 f7       \tbrne\t.-4      \t; 0x604 <loop+0x1fe>\n//     608:\tf7 cf       \trjmp\t.-18     \t; 0x5f8 <loop+0x1f2>\n//\n//\t const uint32_t loopCycles = 3;\n//\t const uint32_t overHead = 12; // just a guess from try + error\n//\t uint8_t delay = (F_CPU - (overHead * Hz * 2UL)) / (Hz * 2UL * loopCycles);\n//\t uint16_t iterations = (time*(F_CPU / 1000000UL)) / (delay * loopCycles + overHead);\n//\n//\t // modulate IR signal\n//\t while (iterations--){\n//\t\t // flip pin state and wait for the calculated time\n//\t\t *outPort ^= bitMask;\n//\t\t //5fc:\t28 81       \tld\tr18, Y\n//\t\t //5fe:\t27 25       \teor\tr18, r7\n//\t\t //600:\t28 83       \tst\tY, r18\n//\n//#ifdef ARDUINO_ARCH_AVR\n//\t\t // loop\n//\t\t _delay_loop_1(delay);\n//#else\n//\t\t // ARM TODO?\n//#endif\n//\t }\n//\t}\n\nvoid IRLspace(volatile uint8_t * outPort, uint8_t bitMask, uint16_t time) {\n\t// Sends an IRLspace for the specified number of microseconds.\n\t// A IRLspace is no output, so the PWM output is disabled.\n\t*outPort &= ~bitMask; // write pin LOW\n\tdelayMicroseconds(time);\n\t//_delay_loop_2(time*(F_CPU/1000000UL)/4UL);\n}\n\n//\n//template<const uint16_t Hz>\n//void IRLsend(volatile uint8_t* outPort, volatile uint8_t* inPort uint8_t bitMask, uint16_t timeMark, uint16_ timeSpace){\n//\n//\tuint16_t iterations = timeMark;\n//\n//\twhile (iterations){\n//\t\t*inPort |= bitMask;\n//\t}\n//}\n\n"
  },
  {
    "path": "keywords.txt",
    "content": "#######################################\r\n# Syntax Coloring Map For IRLremote\r\n#######################################\r\n\r\n#######################################\r\n# Datatypes (KEYWORD1)\r\n#######################################\r\n\r\nIRLremote\tKEYWORD1\r\n\r\n#######################################\r\n# Methods and Functions (KEYWORD2)\r\n#######################################\r\n\r\nCNec\tKEYWORD2\r\nCNecAPI\tKEYWORD2\r\nCPanasonic\tKEYWORD2\r\nCHashIR\tKEYWORD2\r\nNec_data_t\tKEYWORD2\r\nPanasonic_data_t\tKEYWORD2\r\nHash_data_t\tKEYWORD2\r\n\r\nbegin\tKEYWORD2\r\nend\tKEYWORD2\r\navailable\tKEYWORD2\r\nreceiving\tKEYWORD2\r\nread\tKEYWORD2\r\ntimeout\tKEYWORD2\r\nlastEvent\tKEYWORD2\r\nnextEvent\tKEYWORD2\r\n\r\nread\tKEYWORD2\r\ncommand\tKEYWORD2\r\npressCount\tKEYWORD2\r\nholdCount\tKEYWORD2\r\ngetTimeout\tKEYWORD2\r\npressTimeout\tKEYWORD2\r\nnextTimeout\tKEYWORD2\r\nreleaseButton\tKEYWORD2\r\nreset\tKEYWORD2\r\n\r\nIRLwrite\tKEYWORD2\r\nIRLmark\tKEYWORD2\r\nIRLspace\tKEYWORD2\r\n\r\n#######################################\r\n# Constants (LITERAL1)\r\n#######################################\r\n\r\nIRL_KEYCODE_POWER\tLITERAL1\r\nIRL_KEYCODE_MUTE\tLITERAL1\r\n\r\nIRL_KEYCODE_SCREEN\tLITERAL1\r\nIRL_KEYCODE_SATELLITE\tLITERAL1\r\nIRL_KEYCODE_TV_RADIO\tLITERAL1\r\nIRL_KEYCODE_TV_MUSIC\tLITERAL1\r\n\r\nIRL_KEYCODE_1\tLITERAL1\r\nIRL_KEYCODE_2\tLITERAL1\r\nIRL_KEYCODE_3\tLITERAL1\r\nIRL_KEYCODE_4\tLITERAL1\r\nIRL_KEYCODE_5\tLITERAL1\r\nIRL_KEYCODE_6\tLITERAL1\r\nIRL_KEYCODE_7\tLITERAL1\r\nIRL_KEYCODE_8\tLITERAL1\r\nIRL_KEYCODE_9\tLITERAL1\r\nIRL_KEYCODE_BACK\tLITERAL1\r\nIRL_KEYCODE_0\tLITERAL1\r\nIRL_KEYCODE_FAVORITE\tLITERAL1\r\n\r\nIRL_KEYCODE_VOL_UP\tLITERAL1\r\nIRL_KEYCODE_VOL_DOWN\tLITERAL1\r\nIRL_KEYCODE_EPG\tLITERAL1\r\nIRL_KEYCODE_INFO\tLITERAL1\r\nIRL_KEYCODE_CHANNEL_UP\tLITERAL1\r\nIRL_KEYCODE_CHANNEL_DOWN\tLITERAL1\r\n\r\nIRL_KEYCODE_UP\tLITERAL1\r\nIRL_KEYCODE_DOWN\tLITERAL1\r\nIRL_KEYCODE_LEFT\tLITERAL1\r\nIRL_KEYCODE_RIGHT\tLITERAL1\r\nIRL_KEYCODE_OK\tLITERAL1\r\n\r\nIRL_KEYCODE_EXIT\tLITERAL1\r\nIRL_KEYCODE_MENU\tLITERAL1\r\n\r\nIRL_KEYCODE_I_II\tLITERAL1\r\nIRL_KEYCODE_TELETEXT\tLITERAL1\r\nIRL_KEYCODE_SUBTITLE\tLITERAL1\r\nIRL_KEYCODE_ADD\tLITERAL1\r\n\r\nIRL_KEYCODE_RED\tLITERAL1\r\nIRL_KEYCODE_GREEN\tLITERAL1\r\nIRL_KEYCODE_YELLOW\tLITERAL1\r\nIRL_KEYCODE_BLUE\tLITERAL1\r\n\r\nIRL_KEYCODE_PREV\tLITERAL1\r\nIRL_KEYCODE_PLAY\tLITERAL1\r\nIRL_KEYCODE_STOP\tLITERAL1\r\nIRL_KEYCODE_NEXT\tLITERAL1\r\nIRL_KEYCODE_USB\tLITERAL1\r\nIRL_KEYCODE_PAUSE\tLITERAL1\r\nIRL_KEYCODE_REC\tLITERAL1\r\nIRL_KEYCODE_LIVE\tLITERAL1\r\n"
  },
  {
    "path": "library.properties",
    "content": "name=IRLremote\r\nversion=2.0.2\r\nauthor=NicoHood\r\nmaintainer=NicoHood <blog@NicoHood.de>\r\nsentence=Lightweight Infrared library for Arduino\r\nparagraph=IRLremote implements a fast and compact way to analyze IR signals with PinInterrupts and PinChangeInterrupts.\r\ncategory=Signal Input/Output\r\nurl=https://github.com/NicoHood/IRLremote\r\narchitectures=avr,esp8266\r\n"
  },
  {
    "path": "src/IRL_Decode.h",
    "content": "/*\nCopyright (c) 2014-2018 NicoHood\nSee the readme for credit to other people.\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in\nall copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\nTHE SOFTWARE.\n*/\n\n// Include guard\n#pragma once\n\n#include \"IRL_Platform.h\"\n\n//==============================================================================\n// CIRL_DecodeSpaces Class\n//==============================================================================\n\ntemplate<class T, int blocks>\nclass CIRL_DecodeSpaces\n{\npublic:\n    // User API to access library data\n    inline bool available(void);\n    inline bool receiving(void);\n\nprotected:\n    // Temporary buffer to hold bytes for decoding the protocol\n    static volatile uint8_t count;\n    static uint8_t data[blocks];\n\n    // Interrupt function that is attached\n    inline void resetReading(void);\n    static void interrupt(void);\n    static constexpr uint8_t interruptMode = FALLING;\n\n    // Interface that is required to be implemented\n    //static inline bool checksum(void);\n    //static inline void holding(void);\n    //static constexpr uint32_t limitTimeout = VALUE;\n    //static constexpr uint32_t limitLead = VALUE;\n    //static constexpr uint32_t limitHolding = VALUE;\n    //static constexpr uint32_t limitLogic = VALUE;\n    //static constexpr uint32_t limitRepeat = VALUE;\n    //static constexpr uint8_t irLength = VALUE;\n};\n\n\n//==============================================================================\n// Static Data\n//==============================================================================\n\n// Protocol temporary data\ntemplate<class T, int blocks>\nvolatile uint8_t CIRL_DecodeSpaces<T, blocks>::count = 0;\ntemplate<class T, int blocks>\nuint8_t CIRL_DecodeSpaces<T, blocks>::data[blocks] = { 0 };\n\n\n//==============================================================================\n// CIRL_DecodeSpaces Implementation\n//==============================================================================\n\ntemplate<class T, int blocks>\nbool CIRL_DecodeSpaces<T, blocks>::available(void){\n    return count > (T::irLength / 2);\n}\n\n\ntemplate<class T, int blocks>\nvoid CIRL_DecodeSpaces<T, blocks>::resetReading(void){\n    // Reset reading\n    count = 0;\n}\n\n\ntemplate<class T, int blocks>\nvoid CIRL_DecodeSpaces<T, blocks>::interrupt(void)\n{\n    // Block if the protocol is already recognized\n    if (count > (T::irLength / 2)) {\n        return;\n    }\n\n    // Get time between previous call and decode\n    auto duration = T::nextTime();\n\n    // On a timeout abort pending readings and start next possible reading\n    if (duration >= T::limitTimeout) {\n        count = 0;\n    }\n\n    // On a reset (error in decoding) wait for a timeout to start a new reading\n    // This is to not conflict with other protocols while they are sending 0/1\n    // which might be similar to a lead in this protocol\n    else if (count == 0) {\n        return;\n    }\n\n    // Check Mark Lead (requires a timeout)\n    else if (count == 1)\n    {\n        // Wrong lead\n        if (duration < T::limitHolding)\n        {\n            count = 0;\n            return;\n        }\n        // Check for a \"button holding\" lead\n        else if (duration < T::limitLead)\n        {\n            // Abort if last valid button press is too long ago\n            if ((T::mlastTime - \\\n                T::mlastEvent) >= \\\n                T::limitRepeat)\n            {\n                count = 0;\n                return;\n            }\n\n            // Received a Nec Repeat signal\n            // Next mark (stop bit) ignored due to detecting techniques\n            T::holding();\n            count = (T::irLength / 2);\n            T::mlastEvent = T::mlastTime;\n        }\n        // Else normal lead, continue processing\n    }\n\n    // Check different logical space pulses (mark + space)\n    else\n    {\n        // Get number of the Bits (starting from zero)\n        // Substract the first lead pulse\n        uint8_t length = count - 2;\n\n        // Move bits (MSB is zero)\n        data[length / 8] >>= 1;\n\n        // Set MSB if it's a logical one\n        if (duration >= T::limitLogic) {\n            data[length / 8] |= 0x80;\n        }\n\n        // Last bit (stop bit following)\n        if (count >= (T::irLength / 2))\n        {\n            // Check if the protcol's command checksum is correct\n            if (T::checksum()) {\n                T::mlastEvent = T::mlastTime;\n            }\n            else {\n                count = 0;\n                return;\n            }\n        }\n    }\n\n    // Next reading, no errors\n    count++;\n}\n\n/*\n * Return true if we are currently receiving new data\n */\ntemplate<class T, int blocks>\nbool CIRL_DecodeSpaces<T, blocks>::receiving(void)\n{\n    bool ret = false;\n\n    // Provess with interrupts disabled to avoid any conflicts\n    ATOMIC_BLOCK(ATOMIC_RESTORESTATE)\n    {\n        // Check if we already recognized a timed out\n        if (count == 0) {\n            ret = false;\n        }\n        else\n        {\n            // Calculate difference between last interrupt and now\n            uint32_t timeout = T::mlastTime;\n            uint32_t time = micros();\n            timeout = time - timeout;\n\n            // Check for a new timeout\n            if (timeout >= T::limitTimeout) {\n                count = 0;\n                ret = false;\n            }\n            // We are currently receiving\n            else {\n                ret = true;\n            }\n        }\n    }\n\n    return ret;\n}\n"
  },
  {
    "path": "src/IRL_Hash.h",
    "content": "/*\nCopyright (c) 2014-2018 NicoHood\nSee the readme for credit to other people.\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in\nall copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\nTHE SOFTWARE.\n*/\n\n// Include guard\n#pragma once\n\n#ifdef ARDUINO\n#include <Arduino.h> // micros()\n#endif\n#include \"IRL_Receive.h\"\n#include \"IRL_Time.h\"\n#include \"IRL_Protocol.h\"\n#include \"IRL_Decode.h\"\n\n//==============================================================================\n// Protocol Definitions\n//==============================================================================\n\n//HashIR\n#define HASHIR_BLOCKS 255\t\t\t\t// 0-65535 (maximum input length)\n#define HASHIR_TIMEOUT (0xFFFF/4)\t\t// 65535, max timeout\n#define HashIR_TIMESPAN (HASHIR_TIMEOUT * 3)\n#define HASHIR_TIME_THRESHOLD 10000UL\t// 0-32bit\n\n// Use FNV hash algorithm: http://isthe.com/chongo/tech/comp/fnv/#FNV-param\n#define FNV_PRIME_32 16777619UL\n#define FNV_BASIS_32 2166136261UL\n\ntypedef uint8_t HashIR_address_t;\ntypedef uint32_t HashIR_command_t;\n\n// Struct that is returned by the read() function\nstruct HashIR_data_t\n{\n    HashIR_address_t address;\n    HashIR_command_t command;\n};\n\n//==============================================================================\n// Hash Decoding Class\n//==============================================================================\n\nclass CHashIR : public CIRL_Receive<CHashIR>,\n             public CIRL_Time<CHashIR>,\n             public CIRL_Protocol<CHashIR, HashIR_data_t>\n{\npublic:\n    // User API to access library data\n    inline bool available(void);\n    inline bool receiving(void);\n\nprotected:\n    static constexpr uint32_t timespanEvent = HashIR_TIMESPAN;\n\n    friend CIRL_Receive<CHashIR>;\n    friend CIRL_Protocol<CHashIR, HashIR_data_t>;\n\n    // Interrupt function that is attached\n    inline void resetReading(void);\n    static inline void interrupt(void);\n    static constexpr uint8_t interruptMode = CHANGE;\n\n    // Protocol interface functions\n    inline HashIR_data_t getData(void);\n    static inline bool checksum(void);\n    static inline void holding(void);\n\n    // Protocol variables\n    static volatile uint8_t count;\n    static uint32_t hash;\n    static volatile uint16_t lastDuration;\n};\n\n\n//==============================================================================\n// Hash Decoding Implementation\n//==============================================================================\n\nHashIR_data_t CHashIR::getData(void){\n    // Save address as length.\n    // You can check the address/length to prevent triggering on noise\n    HashIR_data_t retdata;\n    retdata.address = count;\n    retdata.command = hash;\n    return retdata;\n}\n\n\nbool CHashIR::available(void){\n    // First look for a timeout\n    receiving();\n    bool ret;\n    ATOMIC_BLOCK(ATOMIC_RESTORESTATE)\n    {\n        ret = lastDuration == 0;\n    }\n    return ret;\n}\n\n\nvoid CHashIR::resetReading(void){\n    // Reset reading\n    hash = FNV_BASIS_32;\n    lastDuration = 0xFFFF;\n    count = 0;\n}\n\n\nbool CHashIR::receiving(void)\n{\n    bool ret = false;\n\n    // Provess with interrupts disabled to avoid any conflicts\n    ATOMIC_BLOCK(ATOMIC_RESTORESTATE)\n    {\n        // Check if we already recognized a timed out\n        if (count == 0) {\n            ret = false;\n        }\n        else\n        {\n            // Calculate difference between last interrupt and now\n            uint32_t timeout = mlastTime;\n            uint32_t time = micros();\n            timeout = time - timeout;\n\n            // Check for a new timeout\n            if (timeout >= HASHIR_TIMEOUT)\n            {\n                // Flag new data if we previously received data\n                if(count > 1) {\n                    count--;\n                    lastDuration = 0;\n                    mlastEvent = mlastTime;\n                }\n                else {\n                    count = 0;\n                }\n                ret = false;\n            }\n            // We are currently receiving\n            else {\n                ret = true;\n            }\n        }\n    }\n\n    return ret;\n}\n\n\nvoid CHashIR::interrupt(void)\n{\n    // Block if the protocol is already recognized\n    if (lastDuration == 0) {\n        return;\n    }\n\n    // Get time between previous call and decode\n    auto duration = nextTime();\n\n    // Reading timed out\n    if(duration >= HASHIR_TIMEOUT)\n    {\n        // Start a new reading sequence.\n        if(count == 0) {\n            count++;\n        }\n        // Ignore the very first timeout of each reading.\n        // Otherwise flag a new input and stop reading.\n        else if(count != 1) {\n            count--;\n            lastDuration = 0;\n            mlastEvent = mlastTime;\n        }\n        return;\n    }\n\n    // Only save data if a sequence is running.\n    // This is required to avoid corrupted data\n    // when starting capturing at the middle of a sequence.\n    if(count)\n    {\n        // Converts the raw code values into a 32-bit hash code.\n        // Hopefully this code is unique for each button.\n        // This isn't a \"real\" decoding, just an arbitrary value.\n        // Code taken from https://github.com/z3t0/Arduino-IRremote\n\n        // Only compare after the first value got received\n        if(count > 1)\n        {\n            // Get both values\n            auto oldval = lastDuration;\n            auto newval = duration;\n\n            // Compare two tick values, returning 0 if newval is shorter,\n            // 1 if newval is equal, and 2 if newval is longer\n            // Use a tolerance of 75%\n            uint8_t value = 1;\n            if (newval < (oldval * 3 / 4)) {\n                value = 0;\n            }\n            else if (oldval < (newval * 3 / 4)) {\n                value = 2;\n            }\n\n            // Add value into the hash\n            hash = (hash * FNV_PRIME_32) ^ value;\n        }\n\n        // Save last time and count up\n        count++;\n\n        // Flag a new input if buffer is full\n        if(count >= HASHIR_BLOCKS){\n            lastDuration = 0;\n            mlastEvent = mlastTime;\n        }\n        else {\n            lastDuration = duration;\n        }\n    }\n}\n"
  },
  {
    "path": "src/IRL_Keycodes.h",
    "content": "/*\nCopyright (c) 2014-2018 NicoHood\nSee the readme for credit to other people.\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in\nall copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\nTHE SOFTWARE.\n*/\n\n// Include guard\n#pragma once\n\n#include \"IRLremote.h\"\n\n//==============================================================================\n// Protek 9700 Series\n//==============================================================================\n\nnamespace IRL_Protek_Remote{\n\n    // Protocol: (Extended) NEC\n    typedef Nec_address_t IRL_address_t;\n    typedef Nec_command_t IRL_command_t;\n    typedef Nec_data_t IRL_data_t;\n    static const uint16_t IRL_ADDRESS = 0x2222;\n\n    enum IRL_Keycode : uint8_t\n    {\n        IRL_KEYCODE_POWER           = 0x02,\n        IRL_KEYCODE_MUTE            = 0x16,\n\n        IRL_KEYCODE_SCREEN          = 0x2B,\n        IRL_KEYCODE_SATELLITE       = 0x2C,\n        IRL_KEYCODE_TV_RADIO        = 0x2D,\n        IRL_KEYCODE_TV_MUSIC        = 0x2E,\n\n        IRL_KEYCODE_1               = 0x13,\n        IRL_KEYCODE_2               = 0x14,\n        IRL_KEYCODE_3               = 0x15,\n        IRL_KEYCODE_4               = 0x17,\n        IRL_KEYCODE_5               = 0x18,\n        IRL_KEYCODE_6               = 0x19,\n        IRL_KEYCODE_7               = 0x1B,\n        IRL_KEYCODE_8               = 0x1C,\n        IRL_KEYCODE_9               = 0x1D,\n        IRL_KEYCODE_BACK            = 0x0E,\n        IRL_KEYCODE_0               = 0x0C,\n        IRL_KEYCODE_FAVORITE        = 0x04,\n\n        IRL_KEYCODE_VOL_UP          = 0x20,\n        IRL_KEYCODE_VOL_DOWN        = 0x21,\n        IRL_KEYCODE_EPG             = 0x08,\n        IRL_KEYCODE_INFO            = 0x12,\n        IRL_KEYCODE_CHANNEL_UP      = 0x22,\n        IRL_KEYCODE_CHANNEL_DOWN    = 0x23,\n\n        IRL_KEYCODE_UP              = 0x09,\n        IRL_KEYCODE_DOWN            = 0x07,\n        IRL_KEYCODE_LEFT            = 0x0A,\n        IRL_KEYCODE_RIGHT           = 0x06,\n        IRL_KEYCODE_OK              = 0x11,\n\n        IRL_KEYCODE_EXIT            = 0x10,\n        IRL_KEYCODE_MENU            = 0x0F,\n\n        IRL_KEYCODE_I_II            = 0x0D,\n        IRL_KEYCODE_TELETEXT        = 0x1F,\n        IRL_KEYCODE_SUBTITLE        = 0x01,\n        IRL_KEYCODE_ADD             = 0x2F,\n\n        IRL_KEYCODE_RED             = 0x27,\n        IRL_KEYCODE_GREEN           = 0x28,\n        IRL_KEYCODE_YELLOW          = 0x29,\n        IRL_KEYCODE_BLUE            = 0x2A,\n\n        IRL_KEYCODE_PREV            = 0x30,\n        IRL_KEYCODE_PLAY            = 0x31,\n        IRL_KEYCODE_STOP            = 0x32,\n        IRL_KEYCODE_NEXT            = 0x33,\n        IRL_KEYCODE_USB             = 0x34,\n        IRL_KEYCODE_PAUSE           = 0x35,\n        IRL_KEYCODE_REC             = 0x36,\n        IRL_KEYCODE_LIVE            = 0x37,\n    };\n}\n"
  },
  {
    "path": "src/IRL_Nec.h",
    "content": "/*\nCopyright (c) 2014-2018 NicoHood\nSee the readme for credit to other people.\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in\nall copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\nTHE SOFTWARE.\n*/\n\n// Include guard\n#pragma once\n\n#include \"IRL_Receive.h\"\n#include \"IRL_Time.h\"\n#include \"IRL_Protocol.h\"\n#include \"IRL_Decode.h\"\n\n//==============================================================================\n// Protocol Definitions\n//==============================================================================\n\n// NEC\n// IRP notation:\n// {38.4k,564}<1,-1|1,-3>(16,-8,D:8,S:8,F:8,~F:8,1,-78,(16,-4,1,-173)*)\n// Lead + Space logic\n#define NEC_HZ                38000UL\n#define NEC_PULSE             564UL\n#define NEC_ADDRESS_LENGTH    16\n#define NEC_COMMAND_LENGTH    16\n#define NEC_DATA_LENGTH       (NEC_ADDRESS_LENGTH + NEC_COMMAND_LENGTH)\n#define NEC_BLOCKS            (NEC_DATA_LENGTH / 8)\n// 2 for lead + space, each block has mark and space\n#define NEC_LENGTH            (2 + NEC_DATA_LENGTH * 2)\n#define NEC_TIMEOUT           (NEC_PULSE * 78UL)\n#define NEC_TIMEOUT_HOLDING   (NEC_PULSE * 173UL)\n#define NEC_TIMESPAN_HOLDING  (NEC_TIMEOUT_HOLDING + NEC_LOGICAL_HOLDING)\n#define NEC_MARK_LEAD         (NEC_PULSE * 16UL)\n#define NEC_MARK_HOLDING      (NEC_PULSE * 16UL)\n#define NEC_SPACE_LEAD        (NEC_PULSE * 8UL)\n#define NEC_SPACE_HOLDING     (NEC_PULSE * 4UL)\n#define NEC_LOGICAL_LEAD      (NEC_MARK_LEAD + NEC_SPACE_LEAD)\n#define NEC_LOGICAL_HOLDING   (NEC_MARK_LEAD + NEC_SPACE_HOLDING)\n#define NEC_MARK_ZERO         (NEC_PULSE * 1UL)\n#define NEC_MARK_ONE          (NEC_PULSE * 1UL)\n#define NEC_SPACE_ZERO        (NEC_PULSE * 1UL)\n#define NEC_SPACE_ONE         (NEC_PULSE * 3UL)\n#define NEC_LOGICAL_ZERO      (NEC_MARK_ZERO + NEC_SPACE_ZERO)\n#define NEC_LOGICAL_ONE       (NEC_MARK_ONE + NEC_SPACE_ONE)\n\n// Decoding limits\n#define NEC_LIMIT_LOGIC       ((NEC_LOGICAL_ONE + NEC_LOGICAL_ZERO) / 2)\n#define NEC_LIMIT_HOLDING     ((NEC_LOGICAL_HOLDING + NEC_LOGICAL_ONE) / 2)\n#define NEC_LIMIT_LEAD        ((NEC_LOGICAL_LEAD + NEC_LOGICAL_HOLDING) / 2)\n#define NEC_LIMIT_TIMEOUT     ((NEC_TIMEOUT + NEC_LOGICAL_LEAD) / 2)\n#define NEC_LIMIT_REPEAT      (NEC_TIMESPAN_HOLDING * 3 / 2)\n\n/*\n * Nec pulse demonstration:\n *\n *---|                |--------| |---| |-|   ... -| |----------/ ~ /----------|\n *   |                |        | |   | | |   ...  | |                         |\n *   |                |        | |   | | |   ...  | |                         |\n *   |----------------|        |-|   |-| |-  ...  |-|                         |\n *   |          Lead           |Log 1|Lg0|  Data  |E|         Timeout         |-\n\n *---|                |----| |---------------------/ ~ /----------------------|\n *   |                |    | |                                                |\n *   |                |    | |                                                |\n *   |----------------|    |-|                                                |\n *   |      Holding        |E|                Timeout Holding                 |-\n *   |                            Timespan Holding                            |\n *\n *  2 Pulses: |-+-| Logical 0\n *  3 Pulses: |----| limitLogic\n *  4 Pulses: |-+---| Logical 1\n * 12 Pulses: |-------------| limitHolding\n * 20 Pulses: |----------------+----| Holding\n * 22 Pulses: |-----------------------| limitLead\n * 24 Pulses: |----------------+--------| Lead\n * 51 Pulses: |-----------------/ ~ /-----------------| limitTimeout\n * 78 Pulses: |-------------------------/ ~ /-------------------------| Timeout\n */\n\ntypedef uint16_t Nec_address_t;\ntypedef uint8_t Nec_command_t;\n\n// Struct that is returned by the read() function\nstruct Nec_data_t\n{\n    Nec_address_t address;\n    Nec_command_t command;\n};\n\n//==============================================================================\n// Nec Decoding Class\n//==============================================================================\n\nclass CNec : public CIRL_Receive<CNec>,\n             public CIRL_Time<CNec>,\n             public CIRL_Protocol<CNec, Nec_data_t>,\n             public CIRL_DecodeSpaces<CNec, NEC_BLOCKS>\n{\nprotected:\n    static constexpr uint32_t timespanEvent = NEC_TIMESPAN_HOLDING;\n    static constexpr uint32_t limitTimeout = NEC_LIMIT_TIMEOUT;\n    static constexpr uint32_t limitLead = NEC_LIMIT_LEAD;\n    static constexpr uint32_t limitHolding = NEC_LIMIT_HOLDING;\n    static constexpr uint32_t limitLogic = NEC_LIMIT_LOGIC;\n    static constexpr uint32_t limitRepeat = NEC_LIMIT_REPEAT;\n    static constexpr uint8_t irLength = NEC_LENGTH;\n\n    friend CIRL_Receive<CNec>;\n    friend CIRL_Protocol<CNec, Nec_data_t>;\n    friend CIRL_DecodeSpaces<CNec, NEC_BLOCKS>;\n\n    // Protocol interface functions\n    inline Nec_data_t getData(void);\n    static inline bool checksum(void);\n    static inline void holding(void);\n};\n\n\n//==============================================================================\n// Nec Decoding Implementation\n//==============================================================================\n\nNec_data_t CNec::getData(void){\n    Nec_data_t retdata;\n    retdata.address = ((uint16_t)data[1] << 8) | ((uint16_t)data[0]);\n    retdata.command = data[2];\n    return retdata;\n}\n\n\nbool CNec::checksum(void) {\n    return uint8_t((data[2] ^ (~data[3]))) == 0x00;\n}\n\n\nvoid CNec::holding(void) {\n    // Flag repeat signal via \"invalid\" address and empty command\n    data[0] = 0xFF;\n    data[1] = 0xFF;\n    data[2] = 0x00;\n}\n"
  },
  {
    "path": "src/IRL_NecAPI.h",
    "content": "/*\nCopyright (c) 2014-2018 NicoHood\nSee the readme for credit to other people.\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in\nall copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\nTHE SOFTWARE.\n*/\n\n// Include guard\n#pragma once\n\n#include \"IRL_Nec.h\"\n\n//==============================================================================\n// API Class\n//==============================================================================\n\ntypedef void(*NecEventCallback)(void);\n#define NEC_API_PRESS_TIMEOUT (500UL * 1000UL) // 0.5 seconds\n\ntemplate<const NecEventCallback callback, const uint16_t address = 0x0000>\nclass CNecAPI : public CNec\n{\npublic:\n    // User API to access library data\n    inline void read(void);\n    inline uint8_t command(void);\n    inline uint8_t count(void);\n    inline uint8_t duration(bool raw = false);\n    inline uint8_t released(bool samebutton = false);\n    inline constexpr uint32_t getTimeout(void);\n    inline uint32_t nextTimeout(void);\n\nprotected:\n    // Differenciate between timeout types\n    enum TimeoutType : uint8_t\n    {\n        NO_TIMEOUT,     // Keydown\n        TIMEOUT,         // Key release with timeout\n        NEXT_BUTTON,     // Key release, pressed again\n        NEW_BUTTON,     // Key release, another key is pressed\n    } NecTimeoutType;\n\n    // Keep track which key was pressed/held down how often\n    uint8_t lastCommand = 0;\n    uint8_t lastPressCount = 0;\n    uint8_t lastHoldCount = 0;\n};\n\n//==============================================================================\n// API Class Implementation\n//==============================================================================\n\n// Reads data from the nec protocol (if available) and processes it.\ntemplate<const NecEventCallback callback, const uint16_t address>\nvoid CNecAPI<callback, address>::read(void) {\n  auto data = CNec::read();\n\n  // Check if the correct protocol and address (optional) is used\n  bool firstCommand = data.address != 0xFFFF;\n  if ((data.address == 0) || (address && firstCommand && (data.address != address)))\n  {\n    // Call the remote function again once the keypress timed out\n    if (lastPressCount && (timeout() > getTimeout()))\n    {\n      // Flag timeout event, key was released and the current chain is over\n      NecTimeoutType = TIMEOUT;\n      callback();\n\n      // Reset the button press and hold count after a timeout\n      lastPressCount = 0;\n      lastHoldCount = 0;\n    }\n    return;\n  }\n\n  // Count the first button press\n  if (firstCommand)\n  {\n    // The same button was pressed twice in a short timespawn (500ms)\n    if (data.command == lastCommand)\n    {\n      // Flag that the last button hold is over, the same key is held down again\n      if (lastPressCount) {\n        NecTimeoutType = NEXT_BUTTON;\n        callback();\n      }\n\n      // Increase pressing streak\n      if (lastPressCount < 255) {\n        lastPressCount++;\n      }\n    }\n    // Different button than before\n    else\n    {\n      // Flag that the last button hold is over, a differnt key is now held down\n      if (lastPressCount) {\n        NecTimeoutType = NEW_BUTTON;\n        callback();\n      }\n      lastPressCount = 1;\n    }\n\n    // Start a new series of button holding\n    lastHoldCount = 0;\n\n    // Save the new command. On a repeat (below) don't safe it.\n    lastCommand = data.command;\n  }\n  // Count the button holding\n  else\n  {\n    // Abort if no first press was recognized (after reset)\n    if(!lastPressCount){\n        return;\n    }\n\n    // Increment holding count\n    if (lastHoldCount < 255) {\n      lastHoldCount++;\n    }\n  }\n\n  // Call the remote function and flag that the event was just received\n  NecTimeoutType = NO_TIMEOUT;\n  callback();\n}\n\n\ntemplate<const NecEventCallback callback, const uint16_t address>\nuint8_t CNecAPI<callback, address>::command(void)\n{\n    return lastCommand;\n}\n\n// Number of repeating button presses in a row\ntemplate<const NecEventCallback callback, const uint16_t address>\nuint8_t CNecAPI<callback, address>::count(void)\n{\n    return lastPressCount;\n}\n\n// Duration (count) how long the current button press was held down.\n// Pass true to also recognize keyup events\ntemplate<const NecEventCallback callback, const uint16_t address>\nuint8_t CNecAPI<callback, address>::duration(bool raw)\n{\n    // Only recognize the actual keydown event\n    if (NecTimeoutType == NO_TIMEOUT || raw) // TODO reorder?\n    {\n        return 1 + lastHoldCount;\n    }\n    return 0;\n}\n\n// True when the button is released:\n// 1. Timeout of press series\n// 2. Next press, new button\n// 3. Next press, same button\n// `--> pass true as parameter,\n//      useful when measuring idential or single button press durations\n// False when the button is held down:\n// 1. Initial button press\n// 2. Holding button down\n// 3. Renewed button press\n// Usually you want to use timeout() to check if the series ends\ntemplate<const NecEventCallback callback, const uint16_t address>\nuint8_t CNecAPI<callback, address>::released(bool samebutton)\n{\n    if (NecTimeoutType == TIMEOUT || NecTimeoutType == NEW_BUTTON) {\n        return 1 + lastHoldCount;\n    }\n    if (samebutton && NecTimeoutType == NEXT_BUTTON) {\n        return 1 + lastHoldCount;\n    }\n    return 0;\n}\n\ntemplate<const NecEventCallback callback, const uint16_t address>\nconstexpr uint32_t CNecAPI<callback, address>::getTimeout(void) {\n    return NEC_API_PRESS_TIMEOUT;\n}\n\n// Return when the next timeout triggers.\n// Zero means it already timed out.\ntemplate<const NecEventCallback callback, const uint16_t address>\nuint32_t CNecAPI<callback, address>::nextTimeout(void)\n{\n    auto time = timeout();\n    auto timeout = getTimeout();\n\n    if(time >= timeout) {\n        return 0;\n    }\n\n    return timeout - time;\n}\n"
  },
  {
    "path": "src/IRL_Panasonic.h",
    "content": "/*\nCopyright (c) 2014-2018 NicoHood\nSee the readme for credit to other people.\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in\nall copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\nTHE SOFTWARE.\n*/\n\n// Include guard\n#pragma once\n\n#include \"IRL_Receive.h\"\n#include \"IRL_Time.h\"\n#include \"IRL_Protocol.h\"\n#include \"IRL_Decode.h\"\n\n//==============================================================================\n// Protocol Definitions\n//==============================================================================\n\n// PANASONIC\n// IRP notation:\n// {37k,432}<1,-1|1,-3>(8,-4,3:8,1:8,D:8,S:8,F:8,(D^S^F):8,1,-173)+\n// Lead + Space logic\n#define PANASONIC_HZ                37000\n#define PANASONIC_PULSE             432UL\n#define PANASONIC_ADDRESS_LENGTH    16\n#define PANASONIC_COMMAND_LENGTH    32\n#define PANASONIC_DATA_LENGTH       (PANASONIC_ADDRESS_LENGTH + \\\n                                    PANASONIC_COMMAND_LENGTH)\n#define PANASONIC_BLOCKS            (PANASONIC_DATA_LENGTH / 8)\n// 2 for lead + space, each block has mark and space\n#define PANASONIC_LENGTH            (2 + PANASONIC_DATA_LENGTH * 2)\n#define PANASONIC_TIMEOUT           (PANASONIC_PULSE * 173UL)\n#define PANASONIC_TIMESPAN_HOLDING  (PANASONIC_TIMEOUT + \\\n                                    PANASONIC_LOGICAL_LEAD + \\\n                                    (PANASONIC_DATA_LENGTH / 2) * \\\n                                    PANASONIC_LOGICAL_ONE + \\\n                                    (PANASONIC_DATA_LENGTH / 2) * \\\n                                    PANASONIC_LOGICAL_ZERO)\n#define PANASONIC_MARK_LEAD         (PANASONIC_PULSE * 8UL)\n#define PANASONIC_SPACE_LEAD        (PANASONIC_PULSE * 4UL)\n#define PANASONIC_LOGICAL_LEAD      (PANASONIC_MARK_LEAD + PANASONIC_SPACE_LEAD)\n// No holding function in this protocol\n#define PANASONIC_MARK_ZERO         (PANASONIC_PULSE * 1UL)\n#define PANASONIC_MARK_ONE          (PANASONIC_PULSE * 1UL)\n#define PANASONIC_SPACE_ZERO        (PANASONIC_PULSE * 1UL)\n#define PANASONIC_SPACE_ONE         (PANASONIC_PULSE * 3UL)\n#define PANASONIC_LOGICAL_ZERO      (PANASONIC_MARK_ZERO + PANASONIC_SPACE_ZERO)\n#define PANASONIC_LOGICAL_ONE       (PANASONIC_MARK_ONE + PANASONIC_SPACE_ONE)\n\n// Decoding limits\n#define PANASONIC_LIMIT_LOGIC       ((PANASONIC_LOGICAL_ONE + PANASONIC_LOGICAL_ZERO) / 2)\n#define PANASONIC_LIMIT_HOLDING     ((PANASONIC_LOGICAL_LEAD + PANASONIC_LOGICAL_ONE) / 2)\n#define PANASONIC_LIMIT_LEAD        0\n#define PANASONIC_LIMIT_TIMEOUT     ((PANASONIC_TIMEOUT + PANASONIC_LOGICAL_LEAD) / 2)\n#define PANASONIC_LIMIT_REPEAT      (PANASONIC_TIMESPAN_HOLDING * 3 / 2)\n\n/*\nPanasonic pulse demonstration:\n\n*---|                        |------------|   |---------|   |---|   ... -|   |--\n*   |                        |            |   |         |   |   |   ...  |   |\n*   |                        |            |   |         |   |   |   ...  |   |\n*   |------------------------|            |---|         |---|   |-  ...  |---|\n*   |       Lead Mark        | Lead Space |  Logical 1  | Log 0 |  Data  |End|\n*/\n\ntypedef uint16_t Panasonic_address_t;\ntypedef uint32_t Panasonic_command_t;\n\n// Struct that is returned by the read() function\nunion Panasonic_data_t\n{\n    struct{\n        union {\n            Panasonic_address_t address;\n            uint16_t manufacturer;\n        };\n        Panasonic_command_t command;\n    };\n    struct {\n        union {\n            uint16_t address;\n            uint16_t manufacturer;\n        };\n        uint32_t parity : 4;\n        uint32_t system : 4;\n        uint32_t product : 8;\n        uint32_t function : 8;\n        uint32_t checksum : 8;\n    } japan;\n    struct {\n        union {\n            uint16_t address;\n            uint16_t manufacturer;\n        };\n        uint32_t parity : 4;\n        uint32_t genre1 : 4;\n        uint32_t genre2 : 4;\n        uint32_t data : 10;\n        uint32_t id : 2;\n        uint32_t checksum : 8;\n    } denon;\n};\n\n\n//==============================================================================\n// Panasonic Decoding Class\n//==============================================================================\n\nclass CPanasonic : public CIRL_Receive<CPanasonic>,\n             public CIRL_Time<CPanasonic>,\n             public CIRL_Protocol<CPanasonic, Panasonic_data_t>,\n             public CIRL_DecodeSpaces<CPanasonic, PANASONIC_BLOCKS>\n{\nprotected:\n    static constexpr uint32_t timespanEvent = PANASONIC_TIMESPAN_HOLDING;\n    static constexpr uint32_t limitTimeout = PANASONIC_LIMIT_TIMEOUT;\n    static constexpr uint32_t limitLead = PANASONIC_LIMIT_LEAD;\n    static constexpr uint32_t limitHolding = PANASONIC_LIMIT_HOLDING;\n    static constexpr uint32_t limitLogic = PANASONIC_LIMIT_LOGIC;\n    static constexpr uint32_t limitRepeat = PANASONIC_LIMIT_REPEAT;\n    static constexpr uint8_t irLength = PANASONIC_LENGTH;\n\n    friend CIRL_Receive<CPanasonic>;\n    friend CIRL_Protocol<CPanasonic, Panasonic_data_t>;\n    friend CIRL_DecodeSpaces<CPanasonic, PANASONIC_BLOCKS>;\n\n    // Protocol interface functions\n    inline Panasonic_data_t getData(void);\n    static inline bool checksum(void);\n    static inline void holding(void);\n};\n\n\n//==============================================================================\n// Panasonic Decoding Implementation\n//==============================================================================\n\nPanasonic_data_t CPanasonic::getData(void) {\n    Panasonic_data_t retdata;\n    retdata.address = ((uint16_t)data[1] << 8) |\n                      ((uint16_t)data[0]);\n    retdata.command = ((uint32_t)data[5] << 24) |\n                      ((uint32_t)data[4] << 16) |\n                      ((uint32_t)data[3] << 8)  |\n                      ((uint32_t)data[2]);\n    return retdata;\n}\n\n\nbool CPanasonic::checksum(void) {\n    // Check if the protcol's checksum is correct\n    uint8_t XOR1 = data[2] ^\n                   data[3] ^\n                   data[4];\n    if (XOR1 == data[5])\n    {\n        // Check vendor nibble checksum (optional)\n        //uint8_t XOR2 = data[0] ^ data[1];\n        //if(((XOR2 & 0x0F) ^ (XOR2 >> 4)) == (data[2] & 0x0F))\n        //{\n            return true;\n        //}\n    }\n    return false;\n}\n\n\nvoid CPanasonic::holding(void) {\n    // Holding not available for Panasonic protocol\n    return;\n}\n"
  },
  {
    "path": "src/IRL_Platform.h",
    "content": "/*\nCopyright (c) 2014-2018 NicoHood\nSee the readme for credit to other people.\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in\nall copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\nTHE SOFTWARE.\n*/\n\n// Include guard\n#pragma once\n\n#ifdef ARDUINO\n#include <Arduino.h> // micros()\n#endif\n\n#if defined(ARDUINO_ARCH_AVR) || defined(DMBS_ARCH_AVR8)\n    #include <util/atomic.h>\n#elif defined(ARDUINO_ARCH_ESP8266) || defined(ESP8266)\n    // copied from https://github.com/wizard97/SimplyAtomic/blob/master/esp8266.h\n\n    #ifndef __STRINGIFY\n    #define __STRINGIFY(a) #a\n    #endif\n\n    #ifndef xt_rsil\n        #define xt_rsil(level) (__extension__({uint32_t state; __asm__ __volatile__(\"rsil %0,\" __STRINGIFY(level) : \"=a\" (state)); state;}))\n    #endif\n\n    #ifndef xt_wsr_ps\n        #define xt_wsr_ps(state)  __asm__ __volatile__(\"wsr %0,ps; isync\" :: \"a\" (state) : \"memory\")\n    #endif\n\n    static __inline__ void SA_iRestore(const  uint32_t *__s)\n    {\n        xt_wsr_ps(*__s);\n    }\n\n    // Note value can be 0-15, 0 = Enable all interrupts, 15 = no interrupts\n    #define SA_ATOMIC_RESTORESTATE uint32_t _sa_saved   \\\n        __attribute__((__cleanup__(SA_iRestore))) = xt_rsil(15)\n\n    #define ATOMIC_RESTORESTATE\n    #define ATOMIC_BLOCK(A) \\\n        for ( SA_ATOMIC_RESTORESTATE, _sa_done =  1;    \\\n            _sa_done; _sa_done = 0 )\n#else\n    #error \"This library supports only AVR and ESP8266 Boards.\"\n#endif\n"
  },
  {
    "path": "src/IRL_Protocol.h",
    "content": "/*\nCopyright (c) 2014-2018 NicoHood\nSee the readme for credit to other people.\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in\nall copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\nTHE SOFTWARE.\n*/\n\n// Include guard\n#pragma once\n\n#include \"IRL_Platform.h\"\n\n//==============================================================================\n// IRL_Protocol Class\n//==============================================================================\n\ntemplate<class T, class Protocol_data_t>\nclass CIRL_Protocol\n{\npublic:\n    // User API to access library data\n    Protocol_data_t read(void);\n\nprotected:\n    // Interface that is required to be implemented\n    //inline Nec_data_t getData(void);\n    //inline void resetReading(void);\n};\n\n\n//==============================================================================\n// CIRL_Protocol Implementation\n//==============================================================================\n\ntemplate<class T, class Protocol_data_t>\nProtocol_data_t CIRL_Protocol<T, Protocol_data_t>::read(void)\n{\n    // If nothing was received return an empty struct\n    Protocol_data_t retdata = Protocol_data_t();\n\n    // Disable interrupts while accessing volatile data\n    ATOMIC_BLOCK(ATOMIC_RESTORESTATE)\n    {\n        // Check and get data if we have new.\n        if (static_cast<T*>(this)->available())\n        {\n            // Set last ISR to current time.\n            // This is required to not trigger a timeout afterwards\n            // and read corrupted data. This might happen\n            // if the reading loop is too slow.\n            static_cast<T*>(this)->mlastTime = micros();\n\n            // Save the protocol data\n            retdata = static_cast<T*>(this)->getData();\n\n            // Reset reading\n            static_cast<T*>(this)->resetReading();\n        }\n    }\n\n    // Return the new protocol information to the user\n    return retdata;\n}\n"
  },
  {
    "path": "src/IRL_Receive.h",
    "content": "/*\nCopyright (c) 2014-2018 NicoHood\nSee the readme for credit to other people.\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in\nall copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\nTHE SOFTWARE.\n*/\n\n// Include guard\n#pragma once\n\n#ifdef ARDUINO\n#include <Arduino.h> // pinMode()\n#endif\n\n#ifdef DMBS_MODULE_BOARD\n#include \"board_pins.h\"\n#endif\n\n#ifdef DMBS_MODULE_FASTPIN\n#include \"fastpin.h\"\n#endif\n\n#ifdef DMBS_MODULE_PCINT\n#include \"pcint.h\"\n#endif\n\n//==============================================================================\n// IRL_Receive Class\n//==============================================================================\n\ntemplate<class T>\nclass CIRL_Receive\n{\npublic:\n#ifdef ARDUINO\n    // Attach the interrupt so IR signals are detected\n    inline bool begin(uint8_t pin);\n    inline bool end(uint8_t pin);\n#endif\n\n    // Alternative template option\n    template<uint8_t pin> inline bool begin(void);\n    template<uint8_t pin> inline bool end(void);\n\nprotected:\n    // Interface that is required to be implemented\n    //static inline void interrupt(void);\n    //static constexpr uint8_t interruptMode = FALLING|RISING|CHANGE;\n};\n\n//==============================================================================\n// CIRL_Receive Implementation\n//==============================================================================\n\ntemplate<class T>\ntemplate<uint8_t pin>\nbool CIRL_Receive<T>::begin(void)\n{\n#ifdef ARDUINO\n    return begin(pin);\n#else\n    // Set pin to INPUT_PULLUP\n    FastPin<pin> p;\n    p.setInput();\n    p.hi();\n\n    // If PinChangeInterrupt library is used, try to attach it\n    if (digitalPinToPCINT(pin) != NOT_AN_INTERRUPT){\n        attachPCINT(digitalPinToPCINT(pin), T::interrupt, T::interruptMode);\n        return true;\n    }\n\n    // Return an error if none of them work (pin has no Pin(Change)Interrupt)\n    return false;\n#endif\n}\n\n#ifdef ARDUINO\ntemplate<class T>\nbool CIRL_Receive<T>::begin(uint8_t pin)\n{\n    // Get pin ready for reading.\n    pinMode(pin, INPUT_PULLUP);\n\n    // Try to attach PinInterrupt first\n    if (digitalPinToInterrupt(pin) != NOT_AN_INTERRUPT){\n        attachInterrupt(digitalPinToInterrupt(pin), T::interrupt, T::interruptMode);\n        return true;\n    }\n\n    // If PinChangeInterrupt library is used, try to attach it\n#ifdef PCINT_VERSION\n    else if (digitalPinToPCINT(pin) != NOT_AN_INTERRUPT){\n        attachPCINT(digitalPinToPCINT(pin), T::interrupt, T::interruptMode);\n        return true;\n    }\n#endif\n\n    // Return an error if none of them work (pin has no Pin(Change)Interrupt)\n    return false;\n}\n#endif\n\ntemplate<class T>\ntemplate<uint8_t pin>\nbool CIRL_Receive<T>::end(void)\n{\n#ifdef ARDUINO\n    return end(pin);\n#else\n    // Disable pullup.\n    FastPin<pin> p;\n    p.lo();\n\n    // If PinChangeInterrupt library is used, try to detach it\n    if (digitalPinToPCINT(pin) != NOT_AN_INTERRUPT){\n        detachPCINT(digitalPinToPCINT(pin));\n        return true;\n    }\n\n    // Return an error if none of them work (pin has no Pin(Change)Interrupt)\n    return false;\n#endif\n}\n\n#ifdef ARDUINO\ntemplate<class T>\nbool CIRL_Receive<T>::end(uint8_t pin)\n{\n    // Disable pullup.\n    pinMode(pin, INPUT);\n\n    // Try to detach PinInterrupt first\n    if (digitalPinToInterrupt(pin) != NOT_AN_INTERRUPT){\n        detachInterrupt(digitalPinToInterrupt(pin));\n        return true;\n    }\n\n    // If PinChangeInterrupt library is used, try to detach it\n#ifdef PCINT_VERSION\n    else if (digitalPinToPCINT(pin) != NOT_AN_INTERRUPT){\n        detachPCINT(digitalPinToPCINT(pin));\n        return true;\n    }\n#endif\n\n    // Return an error if none of them work (pin has no Pin(Change)Interrupt)\n    return false;\n}\n#endif\n"
  },
  {
    "path": "src/IRL_Time.h",
    "content": "/*\nCopyright (c) 2014-2018 NicoHood\nSee the readme for credit to other people.\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in\nall copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\nTHE SOFTWARE.\n*/\n\n// Include guard\n#pragma once\n\n#include \"IRL_Platform.h\"\n\n//==============================================================================\n// IRL_Time Class\n//==============================================================================\n\ntemplate<class T>\nclass CIRL_Time\n{\npublic:\n    // User API to access library data\n    inline uint32_t timeout(void);\n    inline uint32_t lastEvent(void);\n    inline uint32_t nextEvent(void);\n\n    // Interface that is required to be implemented\n    //static constexpr uint32_t timespanEvent = VALUE;\n    //static constexpr uint32_t limitTimeout = VALUE;\n\nprotected:\n    // Time mangement functions\n    static inline uint16_t nextTime(void);\n\n    // Time values for the last interrupt and the last valid protocol\n    static uint32_t mlastTime;\n    static volatile uint32_t mlastEvent;\n};\n\n\n//==============================================================================\n// Static Data\n//==============================================================================\n\n// Protocol temporary data\ntemplate<class T> uint32_t CIRL_Time<T>::mlastTime = 0;\ntemplate<class T> volatile uint32_t CIRL_Time<T>::mlastEvent = 0;\n\n\n//==============================================================================\n// CIRL_Time Implementation\n//==============================================================================\n\n/*\n * Returns duration between last interrupt and current time.\n * This will safe the last interrupt time to the current time.\n */\ntemplate<class T>\nuint16_t CIRL_Time<T>::nextTime(void){\n    // Save the duration between the last reading\n    uint32_t time = micros();\n    uint32_t duration_32 = time - mlastTime;\n    mlastTime = time;\n\n    // Calculate 16 bit duration. On overflow sets duration to a clear timeout\n    uint16_t duration = duration_32;\n    if (duration_32 > 0xFFFF) {\n        duration = 0xFFFF;\n    }\n\n    return duration;\n}\n\n\n/*\n * Return relativ time between last event time (in micros)\n */\ntemplate<class T>\nuint32_t CIRL_Time<T>::timeout(void)\n{\n    uint32_t timeout;\n\n    ATOMIC_BLOCK(ATOMIC_RESTORESTATE)\n    {\n        timeout = mlastEvent;\n    }\n\n    uint32_t time = micros();\n    timeout = time - timeout;\n\n    return timeout;\n}\n\n\n/*\n * Return absolute last event time (in micros)\n */\ntemplate<class T>\nuint32_t CIRL_Time<T>::lastEvent(void)\n{\n    uint32_t time;\n    ATOMIC_BLOCK(ATOMIC_RESTORESTATE)\n    {\n        time = mlastEvent;\n    }\n\n    return time;\n}\n\n\n/*\n * Return when the next event can be expected.\n * Zero means at any time.\n * Attention! This value is a little bit too high in general.\n * Also for the first press it is even higher than it should.\n */\ntemplate<class T>\nuint32_t CIRL_Time<T>::nextEvent(void)\n{\n    auto time = timeout();\n    auto timespan = static_cast<T*>(this)->timespanEvent;\n\n    if(time >= timespan) {\n        return 0;\n    }\n\n    return timespan - time;\n}\n"
  },
  {
    "path": "src/IRLremote.cpp",
    "content": "/*\nCopyright (c) 2014-2018 NicoHood\nSee the readme for credit to other people.\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in\nall copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\nTHE SOFTWARE.\n*/\n\n#include \"IRLremote.h\"\n\n//==============================================================================\n// Static Data\n//==============================================================================\n\n// Protocol temporary data\nvolatile uint8_t CHashIR::count = 0;\nuint32_t CHashIR::hash = FNV_BASIS_32;\nvolatile uint16_t CHashIR::lastDuration = 0xFFFF;\n"
  },
  {
    "path": "src/IRLremote.h",
    "content": "/*\nCopyright (c) 2014-2018 NicoHood\nSee the readme for credit to other people.\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in\nall copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\nTHE SOFTWARE.\n*/\n\n// Include guard\n#pragma once\n\n// IDE version check\n#if defined(ARDUINO) && ARDUINO < 10606\n#error IRLremote requires Arduino IDE 1.6.6 or greater. Please update your IDE.\n#endif\n\n// Software version\n#define IRL_VERSION 202\n\n// Delay_basic is only for avrs. With ARM sending is currently not possible\n// TODO implement sending\n#ifdef ARDUINO_ARCH_AVR\n#include <util/delay_basic.h>\n#endif\n\n#include \"IRL_Platform.h\"\n\n// Include all protocol implementations\n#include \"IRL_Nec.h\"\n#include \"IRL_NecAPI.h\"\n#include \"IRL_Panasonic.h\"\n#include \"IRL_Hash.h\"\n\n// Include pre recorded IR codes from IR remotes\n#include \"IRL_Keycodes.h\"\n"
  }
]