├── examples ├── Iot_IR │ ├── IoT_IR │ │ ├── arduino_secrets.h │ │ ├── IoT_IR.ino │ │ └── WiFi101_Util.h │ ├── readme.md │ ├── adafruit_remote.html │ └── cable_and_tv.html ├── serialRemote │ ├── click.wav │ ├── remotebg.png │ ├── serialRemote.ino │ ├── POV-Ray │ │ └── remotebg.pov │ └── serialRemote.py ├── dump │ └── dump.ino ├── send │ └── send.ino ├── rawSend │ └── rawSend.ino ├── autoResume │ └── autoResume.ino ├── rawRecv │ └── rawRecv.ino ├── comboDump │ └── comboDump.ino ├── freq │ └── freq.ino ├── hashDecode │ └── hashDecode.ino ├── dumpFreq │ └── dumpFreq.ino ├── servo │ └── servo.ino ├── record │ └── record.ino ├── pattern │ └── pattern.ino └── analyze │ └── analyze.ino ├── src ├── IRLibRecvBase.h ├── IRLibRecvPCI.cpp ├── IRLibProtocols.cpp ├── IRLibRecv.h ├── IRLibSendBase.h ├── IRLibFreq.h ├── IRLibProtocols.h ├── IRLibRecvLoop.h ├── IRLib2.h ├── IRLibAll.h ├── IRLibRecvPCI.h ├── IRLib_P99_Additional.h ├── IRLibHardware.cpp ├── readme.md ├── IRLibRecvLoop.cpp ├── IRLib_P05_Panasonic_Old.h ├── IRLib_P09_GICable.h ├── IRLib_P06_JVC.h ├── IRLib_P02_Sony.h ├── IRLib_P07_NECx.h ├── IRLibFreq.cpp ├── IRLib_HashRaw.h ├── IRLib_P01_NEC.h ├── IRLib_P03_RC5.h ├── IRLibSAMD51.h ├── IRLib_P10_DirecTV.h ├── IRLib_P08_Samsung36.h ├── IRLibSendBase.cpp ├── IRLibDecodeBase.h ├── IRLib_P11_RCMM.h ├── IRLibSAMD51.cpp ├── IRLib_P04_RC6.h ├── IRLibRecv.cpp ├── IRLibSAMD21.cpp ├── IRLibDecodeBase.cpp ├── IRLibGlobals.h └── IRLibCombo.h ├── library.properties ├── .gitlab-ci.yml ├── .gitattributes ├── keywords.txt ├── .vscode └── settings.json ├── .github └── workflows │ ├── stale.yml │ └── sync_issues.yml ├── .travis.yml ├── .gitignore ├── readme.md ├── COPYRIGHT.txt └── CHANGELOG.txt /examples/Iot_IR/IoT_IR/arduino_secrets.h: -------------------------------------------------------------------------------- 1 | #define SECRET_SSID "" 2 | #define SECRET_PASS "" 3 | 4 | -------------------------------------------------------------------------------- /src/IRLibRecvBase.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Seeed-Studio/Seeed_Arduino_IR/HEAD/src/IRLibRecvBase.h -------------------------------------------------------------------------------- /src/IRLibRecvPCI.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Seeed-Studio/Seeed_Arduino_IR/HEAD/src/IRLibRecvPCI.cpp -------------------------------------------------------------------------------- /examples/serialRemote/click.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Seeed-Studio/Seeed_Arduino_IR/HEAD/examples/serialRemote/click.wav -------------------------------------------------------------------------------- /examples/serialRemote/remotebg.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Seeed-Studio/Seeed_Arduino_IR/HEAD/examples/serialRemote/remotebg.png -------------------------------------------------------------------------------- /library.properties: -------------------------------------------------------------------------------- 1 | name=Seeed Arduino IR 2 | version=1.0.2 3 | author=Hongtai.liu 4 | maintainer=Hongtai.liu 5 | sentence=Seeed Arduino Infrared Library 6 | paragraph=Library for receiving, decoding, and sending infrared signals using Arduino 7 | category=Sensors 8 | url=https://github.com/Seeed-Studio/Seeed_Arduino_IR 9 | architectures=* 10 | -------------------------------------------------------------------------------- /.gitlab-ci.yml: -------------------------------------------------------------------------------- 1 | build: 2 | tags: 3 | - nas 4 | script: 5 | - wget -c https://files.seeedstudio.com/arduino/seeed-arduino-ci.sh 6 | - chmod +x seeed-arduino-ci.sh 7 | - bash $PWD/seeed-arduino-ci.sh Iot_IR:seeed_XIAO_m0/Iot_IR:uno/servo:seeed_XIAO_m0/servo:uno/rawSend:seeed_XIAO_m0/rawSend:uno/serialRemote:seeed_XIAO_m0/serialRemote:uno arduino-libraries/Servo arduino-libraries/Mouse arduino-libraries/Keyboard 8 | 9 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto 3 | 4 | # Custom for Visual Studio 5 | *.cs diff=csharp 6 | 7 | # Standard to msysgit 8 | *.doc diff=astextplain 9 | *.DOC diff=astextplain 10 | *.docx diff=astextplain 11 | *.DOCX diff=astextplain 12 | *.dot diff=astextplain 13 | *.DOT diff=astextplain 14 | *.pdf diff=astextplain 15 | *.PDF diff=astextplain 16 | *.rtf diff=astextplain 17 | *.RTF diff=astextplain 18 | -------------------------------------------------------------------------------- /keywords.txt: -------------------------------------------------------------------------------- 1 | ####################################### 2 | # Syntax Coloring Map 3 | ####################################### 4 | 5 | ####################################### 6 | # Datatypes (KEYWORD1) 7 | ####################################### 8 | 9 | ####################################### 10 | # Methods and Functions (KEYWORD2) 11 | ####################################### 12 | 13 | ####################################### 14 | # Constants (LITERAL1) 15 | ####################################### 16 | 17 | -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "MicroPython.executeButton": [ 3 | { 4 | "text": "▶", 5 | "tooltip": "运行", 6 | "alignment": "left", 7 | "command": "extension.executeFile", 8 | "priority": 3.5 9 | } 10 | ], 11 | "MicroPython.syncButton": [ 12 | { 13 | "text": "$(sync)", 14 | "tooltip": "同步", 15 | "alignment": "left", 16 | "command": "extension.execute", 17 | "priority": 4 18 | } 19 | ] 20 | } -------------------------------------------------------------------------------- /.github/workflows/stale.yml: -------------------------------------------------------------------------------- 1 | name: 'Close stale issues and PRs' 2 | 3 | on: 4 | workflow_dispatch: 5 | schedule: 6 | - cron: '0 4 * * *' 7 | 8 | jobs: 9 | stale: 10 | runs-on: ubuntu-latest 11 | 12 | steps: 13 | - name: Checkout repository 14 | uses: actions/checkout@v4 15 | 16 | - name: Checkout script repository 17 | uses: actions/checkout@v4 18 | with: 19 | repository: Seeed-Studio/sync-github-all-issues 20 | path: ci 21 | 22 | - name: Run script 23 | run: ./ci/tools/stale.sh 24 | env: 25 | GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} 26 | -------------------------------------------------------------------------------- /.github/workflows/sync_issues.yml: -------------------------------------------------------------------------------- 1 | name: Automate Issue Management 2 | 3 | on: 4 | issues: 5 | types: 6 | - opened 7 | - edited 8 | - assigned 9 | - unassigned 10 | - labeled 11 | - unlabeled 12 | - reopened 13 | 14 | jobs: 15 | add_issue_to_project: 16 | runs-on: ubuntu-latest 17 | steps: 18 | - name: Add issue to GitHub Project 19 | uses: actions/add-to-project@v1.0.2 20 | with: 21 | project-url: https://github.com/orgs/Seeed-Studio/projects/17 22 | github-token: ${{ secrets.ISSUE_ASSEMBLE }} 23 | labeled: bug 24 | label-operator: NOT -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | 2 | language: generic 3 | dist: bionic 4 | sudo: false 5 | cache: 6 | directories: 7 | - ~/arduino_ide 8 | - ~/.arduino15/packages/ 9 | 10 | before_install: 11 | - wget -c https://files.seeedstudio.com/arduino/seeed-arduino-ci.sh 12 | 13 | script: 14 | - chmod +x seeed-arduino-ci.sh 15 | - cat $PWD/seeed-arduino-ci.sh 16 | - bash $PWD/seeed-arduino-ci.sh Iot_IR:seeed_XIAO_m0/Iot_IR:uno/servo:seeed_XIAO_m0/servo:uno/rawSend:seeed_XIAO_m0/rawSend:uno/serialRemote:seeed_XIAO_m0/serialRemote:uno arduino-libraries/Servo arduino-libraries/Mouse arduino-libraries/Keyboard 17 | 18 | notifications: 19 | email: 20 | on_success: change 21 | on_failure: change 22 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Windows image file caches 2 | Thumbs.db 3 | ehthumbs.db 4 | 5 | # Folder config file 6 | Desktop.ini 7 | 8 | # Recycle Bin used on file shares 9 | $RECYCLE.BIN/ 10 | 11 | # Windows Installer files 12 | *.cab 13 | *.msi 14 | *.msm 15 | *.msp 16 | 17 | # Windows shortcuts 18 | *.lnk 19 | 20 | # ========================= 21 | # Operating System Files 22 | # ========================= 23 | 24 | # OSX 25 | # ========================= 26 | 27 | .DS_Store 28 | .AppleDouble 29 | .LSOverride 30 | 31 | # Thumbnails 32 | ._* 33 | 34 | # Files that might appear in the root of a volume 35 | .DocumentRevisions-V100 36 | .fseventsd 37 | .Spotlight-V100 38 | .TemporaryItems 39 | .Trashes 40 | .VolumeIcon.icns 41 | 42 | # Directories potentially created on remote AFP share 43 | .AppleDB 44 | .AppleDesktop 45 | Network Trash Folder 46 | Temporary Items 47 | .apdisk 48 | -------------------------------------------------------------------------------- /examples/dump/dump.ino: -------------------------------------------------------------------------------- 1 | /* dump.ino Example sketch for IRLib2 2 | Illustrates how to receive an IR signal, decode it and print 3 | information about it to the serial monitor. 4 | */ 5 | //This includes everything. Not generally recommended. 6 | //It's better to include only the parts of library you really need. 7 | //But for this example it's quick and easy. See "comboDump" example 8 | //for a more efficient way. 9 | #include "IRLibAll.h" 10 | 11 | IRrecvPCI myReceiver(2); //create receiver and pass pin number 12 | IRdecode myDecoder; //create decoder 13 | 14 | void setup() { 15 | Serial.begin(9600); 16 | delay(2000); while (!Serial); //delay for Leonardo 17 | myReceiver.enableIRIn(); // Start the receiver 18 | Serial.println(F("Ready to receive IR signals")); 19 | } 20 | 21 | void loop() { 22 | //Continue looping until you get a complete signal received 23 | if (myReceiver.getResults()) { 24 | myDecoder.decode(); //Decode it 25 | myDecoder.dumpResults(true); //Now print results. Use false for less detail 26 | myReceiver.enableIRIn(); //Restart receiver 27 | } 28 | } 29 | 30 | -------------------------------------------------------------------------------- /src/IRLibProtocols.cpp: -------------------------------------------------------------------------------- 1 | /* IRLibProtocols.cpp 2 | * Part of IRLib Library for Arduino receiving, decoding, and sending 3 | * infrared signals. See COPYRIGHT.txt and LICENSE.txt for more information. 4 | */ 5 | /* 6 | * This module enumerates the various supported protocols and defines a program memory 7 | * string used by the dump routines or your sketches to display the name of a protocol. 8 | * It is used by both Send and Decode sections of the code but not Receive. 9 | */ 10 | #include "IRLibProtocols.h" 11 | 12 | /* 13 | * Returns a pointer to a flash stored string that is the name of the protocol received. 14 | */ 15 | const __FlashStringHelper *Pnames(uint8_t type) { 16 | if(type>89) return F("Unsup"); 17 | if(type>LAST_PROTOCOL) type=UNKNOWN; 18 | // You can add additional strings before the entry for hash code. 19 | const __FlashStringHelper *Names[LAST_PROTOCOL+1]={ 20 | F("Unknown"),F("NEC"),F("Sony"),F("RC5"),F("RC6"),F("Panasonic Old"),F("JVC"), 21 | F("NECx"),F("Samsung36"),F("G.I.Cable"),F("DirecTV"),F("rcmm"),F("CYKM") 22 | //,F("Additional_13")//expand or edit these 23 | }; 24 | return Names[type]; 25 | }; 26 | 27 | -------------------------------------------------------------------------------- /src/IRLibRecv.h: -------------------------------------------------------------------------------- 1 | /* IRLibRecv.h 2 | * Part of IRLib Library for Arduino receiving, decoding, and sending 3 | * infrared signals. See COPYRIGHT.txt and LICENSE.txt for more information. 4 | * 5 | * You should include this header in your sketch if you're using the original IRLibRecv 6 | * receiver class which uses the 50us interrupt timer to poll the input pin. 7 | * While this is generally accurate enough for everyday purposes, it may be difficult to 8 | * port to other hardware unless you know a lot about hardware timers and interrupts. Also 9 | * when trying to analyze unknown protocols, the 50us granularity may not be sufficient. 10 | * In that case use either the IRLibRecvLoop or the IRLibRecvPCI class. 11 | * Applications that do sending only SHOULD NOT include this header. 12 | */ 13 | 14 | #ifndef IRLibRecv_h 15 | #define IRLibRecv_h 16 | #include "IRLibRecvBase.h" 17 | 18 | class IRrecv: public IRrecvBase { 19 | public: 20 | IRrecv(uint8_t recvPin):IRrecvBase(recvPin){}; 21 | void enableIRIn(void); //call to initialize or resume receiving 22 | bool getResults(void); //returns true if new frame of data has been received 23 | void disableIRIn(void); //ISR runs continuously once started. Use this if you want to stop. 24 | void setFrameTimeout(uint16_t frameTimeout); //maximum gap determines end of frame. 25 | }; 26 | #endif //IRLibRecv_h 27 | -------------------------------------------------------------------------------- /src/IRLibSendBase.h: -------------------------------------------------------------------------------- 1 | /* IRLibSendBase.h 2 | * Part of IRLib Library for Arduino receiving, decoding, and sending 3 | * infrared signals. See COPYRIGHT.txt and LICENSE.txt for more information. 4 | */ 5 | /* 6 | * This module contains the base classes for sending. You will not create instances 7 | * of these classes, rather you will use them as base classes in creating derived 8 | * protocol specific decoders. Each protocol specific send class begins 9 | * by calling enableIROut(uint8_t kHz) to set the carrier frequency. 10 | * It then calls mark(int usec) and space(inc usec) to transmit marks and 11 | * spaces of varying length of microseconds in the manner which the protocol defines. 12 | */ 13 | #ifndef IRLIBSENDBASE_H 14 | #define IRLIBSENDBASE_H 15 | 16 | #include "IRLibProtocols.h" 17 | 18 | class IRsendBase { 19 | public: 20 | IRsendBase(); 21 | void sendGeneric(uint32_t data, uint8_t numBits, uint16_t headMark, uint16_t headSpace, 22 | uint16_t markOne, uint16_t markZero, uint16_t spaceOne, uint16_t spaceZero, 23 | uint8_t kHz, bool stopBits, uint32_t maxExtent=0); 24 | protected: 25 | void enableIROut(uint8_t khz); 26 | void mark(uint16_t usec); 27 | void space(uint16_t usec); 28 | uint32_t extent; 29 | uint8_t onTime,offTime,iLength;//used by bit-bang output. 30 | }; 31 | 32 | #endif //IRLIBSENDBASE_H 33 | -------------------------------------------------------------------------------- /src/IRLibFreq.h: -------------------------------------------------------------------------------- 1 | /* IRLibFreq.h 2 | * Part of IRLib Library for Arduino receiving, decoding, and sending 3 | * infrared signals. See COPYRIGHT.txt and LICENSE.txt for more information. 4 | * 5 | * This class facilitates detection of frequency of an IR signal. It requires 6 | * a different kind of receiver specifically a TSMP58000 or equivalent device 7 | * connected to the hardware interrupt pin. Create an instance of the object 8 | * passing the interrupt number. 9 | */ 10 | #ifndef IRLibRecvFreq_h 11 | #define IRLibRecvFreq_h 12 | 13 | //Un-comment only one of the following three lines depending on available RAM 14 | //#define FREQUENCY_BUFFER_TYPE uint8_t 15 | #define FREQUENCY_BUFFER_TYPE uint16_t 16 | //#define FREQUENCY_BUFFER_TYPE uint32_t 17 | class IRfrequency { 18 | public: 19 | IRfrequency(uint8_t pin); 20 | void enableFreqDetect(void); 21 | bool haveData(void); //detect if data is received 22 | void disableFreqDetect(void); 23 | void computeFreq(void); //computes but does not print results 24 | void dumpResults(bool detail); //computes and prints result 25 | double results; //results in kHz 26 | uint8_t samples; //number of samples used in computation 27 | private: 28 | volatile FREQUENCY_BUFFER_TYPE Time_Stamp[256]; 29 | uint8_t intrNum; 30 | uint16_t i; 31 | uint32_t sum; 32 | }; 33 | #endif // ifdef IRLibRecvFreq_h 34 | 35 | -------------------------------------------------------------------------------- /examples/send/send.ino: -------------------------------------------------------------------------------- 1 | /* send.ino Example sketch for IRLib2 2 | * Illustrates how to send a code. 3 | */ 4 | #include // First include the send base 5 | //Now include only the protocols you wish to actually use. 6 | //The lowest numbered protocol should be first but remainder 7 | //can be any order. 8 | #include 9 | #include 10 | #include // After all protocols, include this 11 | // All of the above automatically creates a universal sending 12 | // class called "IRsend" containing only the protocols you want. 13 | // Now declare an instance of that sender. 14 | 15 | IRsend mySender; 16 | 17 | void setup() { 18 | Serial.begin(9600); 19 | delay(2000); while (!Serial); //delay for Leonardo 20 | Serial.println(F("Every time you press a key is a serial monitor we will send.")); 21 | } 22 | 23 | void loop() { 24 | if (Serial.read() != -1) { 25 | //send a code every time a character is received from the 26 | // serial port. You could modify this sketch to send when you 27 | // push a button connected to an digital input pin. 28 | //Substitute values and protocols in the following statement 29 | // for device you have available. 30 | mySender.send(SONY,0xa8bca, 20);//Sony DVD power A8BCA, 20 bits 31 | //mySender.send(NEC,0x61a0f00f,0);//NEC TV power button=0x61a0f00f 32 | Serial.println(F("Sent signal.")); 33 | } 34 | } 35 | 36 | -------------------------------------------------------------------------------- /examples/rawSend/rawSend.ino: -------------------------------------------------------------------------------- 1 | /* rawSend.ino Example sketch for IRLib2 2 | * Illustrates how to send a code Using raw timings which were captured 3 | * from the "rawRecv.ino" sample sketch. Load that sketch and 4 | * capture the values. They will print in the serial monitor. Then you 5 | * cut and paste that output into the appropriate section below. 6 | */ 7 | #include //We need the base code 8 | #include //Only use raw sender 9 | 10 | IRsendRaw mySender; 11 | 12 | void setup() { 13 | Serial.begin(9600); 14 | delay(2000); while (!Serial); //delay for Leonardo 15 | Serial.println(F("Every time you press a key is a serial monitor we will send.")); 16 | } 17 | /* Cut and paste the output from "rawRecv.ino" below here. It will 18 | * consist of a #define RAW_DATA_LEN statement and an array definition 19 | * beginning with "uint16_t rawData[RAW_DATA_LEN]= {…" and concludes 20 | * with "…,1000};" 21 | */ 22 | 23 | 24 | 25 | 26 | 27 | /* 28 | * Cut-and-paste into the area above. 29 | */ 30 | 31 | void loop() { 32 | if (Serial.read() != -1) { 33 | //send a code every time a character is received from the 34 | // serial port. You could modify this sketch to send when you 35 | // push a button connected to an digital input pin. 36 | mySender.send(rawData,RAW_DATA_LEN,36);//Pass the buffer,length, optionally frequency 37 | Serial.println(F("Sent signal.")); 38 | } 39 | } 40 | 41 | -------------------------------------------------------------------------------- /src/IRLibProtocols.h: -------------------------------------------------------------------------------- 1 | /* IRLibProtocols.h 2 | * Part of IRLib Library for Arduino receiving, decoding, and sending 3 | * infrared signals. See COPYRIGHT.txt and LICENSE.txt for more information. 4 | */ 5 | /* 6 | * This module enumerates the various supported protocols and defines a program memory 7 | * string used by the dump routines or your sketches to display the name of a protocol. 8 | * It is used by both Send and Decode sections of the code but not Receive. 9 | */ 10 | #ifndef IRLIBPROTOCOLS_H 11 | #define IRLIBPROTOCOLS_H 12 | #include 13 | 14 | #define UNKNOWN 0 15 | #define NEC 1 16 | #define SONY 2 17 | #define RC5 3 18 | #define RC6 4 19 | #define PANASONIC_OLD 5 20 | #define JVC 6 21 | #define NECX 7 22 | #define SAMSUNG36 8 23 | #define GICABLE 9 24 | #define DIRECTV 10 25 | #define RCMM 11 26 | #define CYKM 12 27 | //#define ADDITIONAL_13 13 //add additional protocols here 28 | //#define ADDITIONAL_14 14 29 | #define LAST_PROTOCOL 12 //Be sure to update this when adding protocols 30 | 31 | /* 32 | * Returns a pointer to a flash stored string that is the name of the protocol received. 33 | */ 34 | const __FlashStringHelper *Pnames(uint8_t Type); 35 | 36 | /* 37 | * Miscellaneous values used by both Send and Decode modules 38 | */ 39 | #define TOPBIT 0x80000000 40 | 41 | // Decoded value for NEC and others when a repeat code is received or to be sent 42 | #define REPEAT_CODE 0xffffffff 43 | 44 | #endif //IRLIBPROTOCOLS_H 45 | -------------------------------------------------------------------------------- /examples/autoResume/autoResume.ino: -------------------------------------------------------------------------------- 1 | /* autoResume.ino Example sketch for IRLib2 2 | Illustrates how to receive an IR signal, decode it and print 3 | information about it to the serial monitor. 4 | Uses an external buffer in the auto resume feature. 5 | */ 6 | //This includes everything. Not generally recommended. 7 | //It's better to include only the parts of library you really need. 8 | //But for this example it's quick and easy. See "comboDump" example 9 | //for a more efficient way. 10 | #include "IRLibAll.h" 11 | 12 | IRrecvPCI myReceiver(2); //create receiver and pass pin number 13 | IRdecode myDecoder; //create decoder 14 | 15 | //Create a buffer that we will use for decoding one stream while 16 | //the receiver is using the default buffer "recvGlobal.recvBuffer" 17 | uint16_t myBuffer[RECV_BUF_LENGTH]; 18 | 19 | void setup() { 20 | Serial.begin(9600); 21 | delay(2000); while (!Serial); //delay for Leonardo 22 | //Enable auto resume and pass it the address of your extra buffer 23 | myReceiver.enableAutoResume(myBuffer); 24 | myReceiver.enableIRIn(); // Start the receiver 25 | Serial.println(F("Ready to receive IR signals")); 26 | } 27 | 28 | void loop() { 29 | //Continue looping until you get a complete signal received 30 | if (myReceiver.getResults()) { 31 | myDecoder.decode(); //Decode it 32 | myDecoder.dumpResults(true); //Now print results. Use false for less detail 33 | myReceiver.enableIRIn(); //Restart receiver 34 | } 35 | } 36 | 37 | -------------------------------------------------------------------------------- /examples/rawRecv/rawRecv.ino: -------------------------------------------------------------------------------- 1 | /* rawR&cv.ino Example sketch for IRLib2 2 | * Illustrate how to capture raw timing values for an unknow protocol. 3 | * You will capture a signal using this sketch. It will output data the 4 | * serial monitor that you can cut and paste into the "rawSend.ino" 5 | * sketch. 6 | */ 7 | // Recommend only use IRLibRecvPCI or IRLibRecvLoop for best results 8 | #include 9 | 10 | IRrecvPCI myReceiver(2);//pin number for the receiver 11 | 12 | void setup() { 13 | Serial.begin(9600); 14 | delay(2000); while (!Serial); //delay for Leonardo 15 | myReceiver.enableIRIn(); // Start the receiver 16 | Serial.println(F("Ready to receive IR signals")); 17 | } 18 | 19 | void loop() { 20 | //Continue looping until you get a complete signal received 21 | if (myReceiver.getResults()) { 22 | Serial.println(F("Do a cut-and-paste of the following lines into the ")); 23 | Serial.println(F("designated location in rawSend.ino")); 24 | Serial.print(F("\n#define RAW_DATA_LEN ")); 25 | Serial.println(recvGlobal.recvLength,DEC); 26 | Serial.print(F("uint16_t rawData[RAW_DATA_LEN]={\n\t")); 27 | for(bufIndex_t i=1;i // First include the decode base 6 | #include // Now include only the protocols you wish 7 | #include // to actually use. The lowest numbered 8 | #include // must be first but others can be any order. 9 | #include 10 | #include 11 | #include // After all protocols, include this 12 | // All of the above automatically creates a universal decoder 13 | // class called "IRdecode" containing only the protocols you want. 14 | // Now declare an instance of that decoder. 15 | IRdecode myDecoder; 16 | 17 | // Include a receiver either this or IRLibRecvPCI or IRLibRecvLoop 18 | #include 19 | IRrecv myReceiver(2); //pin number for the receiver 20 | 21 | void setup() { 22 | Serial.begin(9600); 23 | delay(2000); while (!Serial); //delay for Leonardo 24 | myReceiver.enableIRIn(); // Start the receiver 25 | Serial.println(F("Ready to receive IR signals")); 26 | } 27 | void loop() { 28 | //Continue looping until you get a complete signal received 29 | if (myReceiver.getResults()) { 30 | myDecoder.decode(); //Decode it 31 | myDecoder.dumpResults(true); //Now print results. Use false for less detail 32 | myReceiver.enableIRIn(); //Restart receiver 33 | } 34 | } 35 | 36 | -------------------------------------------------------------------------------- /src/IRLibRecvLoop.h: -------------------------------------------------------------------------------- 1 | /* IRLibRecvLoop.h 2 | * Part of IRLib Library for Arduino receiving, decoding, and sending 3 | * infrared signals. See COPYRIGHT.txt and LICENSE.txt for more information. 4 | * 5 | * You should include this header in your sketch if you're using the IRLibRecvLoop receiver. 6 | * Other interrupt driven receivers allow you to do other things and call getResults at 7 | * your leisure to see if perhaps a sequence has been received. Typically you would put 8 | * getResults in your loop and it would return false until the sequence had been received. 9 | * However because this receiver uses no interrupts, it takes control of your program when 10 | * you call getResults and doesn't let go until it's got something to show you. The advantage 11 | * is you don't need interrupts which would make it easier to use on non-standard hardware 12 | * and will allow you to use any digital input pin. Timing of this routine is only as 13 | * accurate as your "micros();" Note the enableIRIn method should still be called because 14 | * initializes the input pin even though that method does nothing else. Similarly 15 | * disableIRin doesn't do anything. Also auto resume is meaningless because there is no 16 | * multitasking possible. 17 | */ 18 | 19 | #ifndef IRLibRecvLoop_h 20 | #define IRLibRecvLoop_h 21 | #include "IRLibRecvBase.h" 22 | 23 | class IRrecvLoop: public IRrecvBase { 24 | public: 25 | IRrecvLoop(uint8_t recvPin):IRrecvBase(recvPin){}; 26 | bool getResults(void); 27 | }; 28 | 29 | #endif //IRLibRecvLoop_h 30 | -------------------------------------------------------------------------------- /src/IRLib2.h: -------------------------------------------------------------------------------- 1 | /* IRLib2.h 2 | * Part of IRLib Library for Arduino receiving, decoding, and sending 3 | * infrared signals. See COPYRIGHT.txt and LICENSE.txt for more information. 4 | */ 5 | /* 6 | * In previous versions of IRLib you would #include and it would 7 | * include everything from the library into your sketch. Beginning with 8 | * version 2.0+ the design is more modular. You should only include those 9 | * header files that you actually need. See documentation for further details. 10 | * 11 | * The files IRLib2.h and IRLibAll.h have been provided to make it easy to re-create 12 | * the old "everything at once" approach of IRLib.h version 1.xx. In general 13 | * WE RECOMMEND YOU DO NOT USE THIS APPROACH. We provide this file for a small 14 | * measure of backwards compatibility. Use of this file will make your program 15 | * potentially much larger than necessary. 16 | * The file IRLib2.h will include only the original 7 protocols from IRLib 1.xx. 17 | * The file IRLibAll.h will include all currently supported protocols. 18 | */ 19 | 20 | #ifndef IRLIB2_H 21 | #define IRLIB2_H 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include 28 | #include 29 | #include 30 | #include 31 | #include 32 | #include 33 | #include 34 | #include 35 | #include 36 | #endif //IRLIB2_H 37 | -------------------------------------------------------------------------------- /examples/freq/freq.ino: -------------------------------------------------------------------------------- 1 | /* freq.ino Example sketch for IRLib2 2 | * Illustrates how to measure modulation frequency using the 3 | * IRfrequency class in the IRLibFreq library. You must connect 4 | * an IR learner such as TSMP58000 to a hardware interrupt pin. 5 | */ 6 | 7 | #include 8 | 9 | #define FREQUENCY_PIN 3 10 | //NOTE: Previous versions of IRLib required you to pass the 11 | // interrupt number to be passed to the built-in "attachInterrupt()" 12 | // function however starting with IRLib 2.x you now pass the pin number. 13 | IRfrequency My_Freq(FREQUENCY_PIN); 14 | 15 | void setup() { 16 | Serial.begin(9600); 17 | delay(2000);while(!Serial);//delay for Leonardo 18 | if(F_CPU<16000000) { 19 | Serial.println(F("WARNING: CPU speed less than 16 MHz will be inaccurate")); 20 | Serial.print(F("for frequencies over 45 kHz. Your CPU is:")); 21 | Serial.print(F_CPU/1000000,DEC); Serial.println(F(" Mhz")); 22 | } 23 | //Let's double check to make sure this pin will work 24 | int8_t intrNum=digitalPinToInterrupt(FREQUENCY_PIN); 25 | if (intrNum==NOT_AN_INTERRUPT) { 26 | Serial.println(F("Invalid frequency pin number.")); 27 | while (1) {};//infinite loop because of fatal error 28 | } 29 | Serial.print(F("Interrupt=")); Serial.print(intrNum,DEC); 30 | Serial.print(F(" Pin=")); Serial.println(FREQUENCY_PIN,DEC); 31 | My_Freq.enableFreqDetect();//starts interrupt routine to compute frequency 32 | } 33 | 34 | void loop() { 35 | if (My_Freq.haveData()) { 36 | delay(500); //it couldn't hurt to collect a little more just in case 37 | My_Freq.disableFreqDetect(); 38 | My_Freq.dumpResults(true);//Change to "true" for more detail 39 | My_Freq.enableFreqDetect();//Zero out previous results and restart ISR 40 | } 41 | } 42 | 43 | -------------------------------------------------------------------------------- /src/IRLibAll.h: -------------------------------------------------------------------------------- 1 | /* IRLibAll.h 2 | * Part of IRLib Library for Arduino receiving, decoding, and sending 3 | * infrared signals. See COPYRIGHT.txt and LICENSE.txt for more information. 4 | */ 5 | /* 6 | * In previous versions of IRLib you would #include and it would 7 | * include everything from the library into your sketch. Beginning with 8 | * version 2.0+ the design is more modular. You should only include those 9 | * header files that you actually need. See documentation for further details. 10 | * 11 | * The files IRLib2.h and IRLibAll.h have been provided to make it easy to re-create 12 | * the old "everything at once" approach of IRLib.h version 1.xx. In general 13 | * WE RECOMMEND YOU DO NOT USE THIS APPROACH. We provide this file for a small 14 | * measure of backwards compatibility. Use of this file will make your program 15 | * potentially much larger than necessary. 16 | * The file IRLib2.h will include only the original 7 protocols from IRLib 1.xx. 17 | * The file IRLibAll.h will include all currently supported protocols. 18 | */ 19 | 20 | #ifndef IRLIB_ALL_H 21 | #define IRLIB_ALL_H 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include 28 | #include 29 | #include 30 | #include 31 | #include 32 | #include 33 | #include 34 | #include 35 | #include 36 | //include additional protocols here 37 | #include 38 | #include 39 | #include 40 | #include 41 | #include 42 | #endif //IRLIB_ALL_H 43 | -------------------------------------------------------------------------------- /examples/hashDecode/hashDecode.ino: -------------------------------------------------------------------------------- 1 | /* hashDecode.ino Example sketch for IRLib2 2 | * Instead of decoding using a standard encoding scheme 3 | * (e.g. Sony, NEC, RC5), the code is hashed to a 32-bit value. 4 | * This should produce a unique 32-bit number however that number 5 | * cannot be used to retransmit the same code. This is just a quick 6 | * and dirty way to detect a unique code for controlling a device 7 | * when you don't really care what protocol or values are being sent. 8 | */ 9 | //First will create a decoder that handles only NEC, Sony and the hash 10 | // decoder. If it is not NEC or Sony that it will return a 32 bit hash. 11 | #include 12 | #include 13 | #include 14 | #include //Must be last protocol 15 | #include // After all protocols, include this 16 | // All of the above automatically creates a universal decoder 17 | // class called "IRdecode" containing only the protocols you want. 18 | // Now declare an instance of that decoder. 19 | IRdecode myDecoder; 20 | 21 | // Include a receiver either this or IRLibRecvPCI or IRLibRecvLoop 22 | #include 23 | IRrecv myReceiver(2); //create a receiver on pin number 2 24 | 25 | void setup() { 26 | Serial.begin(9600); 27 | delay(2000); while (!Serial); //delay for Leonardo 28 | myReceiver.enableIRIn(); // Start the receiver 29 | Serial.println(F("Ready to receive IR signals")); 30 | } 31 | 32 | void loop() { 33 | if(myReceiver.getResults()) { 34 | myDecoder.decode(); 35 | if(myDecoder.protocolNum==UNKNOWN) { 36 | Serial.print(F("Unknown protocol. Hash value is: 0x")); 37 | Serial.println(myDecoder.value,HEX); 38 | } else { 39 | myDecoder.dumpResults(false); 40 | }; 41 | myReceiver.enableIRIn(); 42 | } 43 | } 44 | 45 | -------------------------------------------------------------------------------- /src/IRLibRecvPCI.h: -------------------------------------------------------------------------------- 1 | /* IRLibRecvPCI.h 2 | * Part of IRLib Library for Arduino receiving, decoding, and sending 3 | * infrared signals. See COPYRIGHT.txt and LICENSE.txt for more information. 4 | * 5 | * You should include this header in your sketch if you're using the IRLibRecvPCI 6 | * receiver class which uses pin change interrupts to poll the input pin. 7 | * This version gives more accurate results than the 50us timer based IRrecv but it has 8 | * other limitations. It uses the Arduino "attachInterrupt()" function which can conflict 9 | * with other libraries. Also unless you use an external buffer and enable auto resume 10 | * this receiver occasionally fails to receive the second of 2 quickly sent frames. 11 | * If you do not have sufficient RAM for a second buffer you should consider using the 12 | * other two available receiver classes. 13 | * Applications that do sending only SHOULD NOT include this header. 14 | * 15 | * This receiver is based in part on Arduino firmware for use with AnalysIR IR signal analysis 16 | * software for Windows PCs. Many thanks to the people at http://analysir.com for their 17 | * assistance in developing this section of code. 18 | */ 19 | 20 | #ifndef IRLibRecvPCI_h 21 | #define IRLibRecvPCI_h 22 | #include "IRLibRecvBase.h" 23 | 24 | class IRrecvPCI: public IRrecvBase { 25 | public: 26 | IRrecvPCI(void){}; //Use only when receiver object is part of larger object. 27 | // Still must initialize using constructor below. 28 | IRrecvPCI(uint8_t pin); 29 | void enableIRIn(void); //call to initialize or resume receiving 30 | bool getResults(void); //returns true if new frame of data has been received 31 | void disableIRIn(void); //ISR runs continuously once started. Use this if you want to stop. 32 | private: 33 | uint8_t intrNum; 34 | }; 35 | #endif //IRLibRecvPCI_h 36 | -------------------------------------------------------------------------------- /src/IRLib_P99_Additional.h: -------------------------------------------------------------------------------- 1 | /* IRLib_P99_Additional.h 2 | * Part of IRLib Library for Arduino receiving, decoding, and sending 3 | * infrared signals. See COPYRIGHT.txt and LICENSE.txt for more information. 4 | */ 5 | /* 6 | * This is dummy code that you can copy and rename and modify when implementing new protocols. 7 | */ 8 | 9 | #ifndef IRLIB_PROTOCOL_99_H 10 | #define IRLIB_PROTOCOL_99_H 11 | #define IR_SEND_PROTOCOL_99 case 99: IRsendAdditional::send(data); break; 12 | #define IR_DECODE_PROTOCOL_99 if(IRdecodeAdditional::decode()) return true; 13 | #ifdef IRLIB_HAVE_COMBO 14 | #define PV_IR_DECODE_PROTOCOL_99 ,public virtual IRdecodeAdditional 15 | #define PV_IR_SEND_PROTOCOL_99 ,public virtual IRsendAdditional 16 | #else 17 | #define PV_IR_DECODE_PROTOCOL_99 public virtual IRdecodeAdditional 18 | #define PV_IR_SEND_PROTOCOL_99 public virtual IRsendAdditional 19 | #endif 20 | 21 | #ifdef IRLIBSENDBASE_H 22 | class IRsendAdditional: public virtual IRsendBase { 23 | public: 24 | void IRsendAdditional::send(uint32_t data) { 25 | //void IRsendAdditional::send(uint32_t data, uint32_t data2)//optional form 26 | /********* 27 | * Insert your code here. 28 | *********/ 29 | }; 30 | }; 31 | #endif //IRLIBSENDBASE_H 32 | 33 | #ifdef IRLIBDECODEBASE_H 34 | class IRdecodeAdditional: public virtual IRdecodeBase { 35 | public: 36 | bool IRdecodeAdditional::decode(void) { 37 | IRLIB_ATTEMPT_MESSAGE(F("Additional")); 38 | /********* 39 | * Insert your code here. Return false if it fails. 40 | * Don't forget to include the following lines or 41 | * equivalent somewhere in the code. 42 | * 43 | * bits = 32; //Substitute proper value here 44 | * value = data; //return data in "value" 45 | * protocolNum = ADDITIONAL; //set the protocol number here. 46 | */ 47 | return true; 48 | } 49 | }; 50 | 51 | #endif //IRLIBDECODEBASE_H 52 | 53 | #define IRLIB_HAVE_COMBO 54 | 55 | #endif //IRLIB_PROTOCOL_99_H 56 | -------------------------------------------------------------------------------- /src/IRLibHardware.cpp: -------------------------------------------------------------------------------- 1 | /* IRLibHardware.cpp 2 | * Part of IRLib Library for Arduino receiving, decoding, and sending 3 | * infrared signals. See COPYRIGHT.txt and LICENSE.txt for more information. 4 | * 5 | * We need a way for the sending object to communicate with the receiving object. 6 | * Sending an IR signal can disable further receiving because the timer needed for the 50us 7 | * interrupts is used to modulate the frequency of the PWM output signal. We need a flag 8 | * for the send object to inform you receive object that this occurred. 9 | * 10 | * Some applications do sending only and would only require you to include IRLibSendBase.h 11 | * while others only do receiving/decoding and would include IRLibRecvBase.h but not 12 | * IRLibSendBase.h. The only include file that is used by both sending and receiving is 13 | * the IRLibHardware.h which was formerly called IRLibTimer.h. Therefore we put the flag 14 | * in this newly created IRLibHardware.cpp module. That way a send only can put the flag 15 | * here whether or not there is a receiver. Similarly the receiver can check the flag 16 | * whether or not there is a sender. 17 | * 18 | * The below is a global flag IRLib_didIROut that gets set true with every call to enableIROut. 19 | * Then any call to IRrecv::enableIRIn checks this to see if it needs to restart the ISR. 20 | * Regardless IRrecv::enableIRIn will always reset it it false for the next time. 21 | * Note as always if you try to send while in the middle of receiving, the partially received 22 | * data is lost. If the application wishes to create a system where the sending waits until 23 | * the receiver is idle, the programmer can implement such a system themselves and deal with 24 | * the consequences. 25 | * 26 | * The bottom line is the application no longer needs to figure out if it needs to 27 | * call enableIRIn or the "resume" method. There is no more "resume". You always do 28 | * enableIRIn after every decode and the system handles it. 29 | */ 30 | #include "IRLibHardware.h" 31 | uint8_t IRLib_didIROut=false; 32 | -------------------------------------------------------------------------------- /src/readme.md: -------------------------------------------------------------------------------- 1 | # IRLib2 A Library for Receiving, Decoding and Sending Infrared Signals Using Arduino. 2 | 3 | IRLib2 is copyright 2017 by Chris Young. It it is a major rewrite of the original IRLib 1.x by Chris Young which in turn was based on IRremote by Ken Shirriff. See COPYRIGHT.txt for details. 4 | 5 | This library is covered under the GNU GENERAL PUBLIC LICENSE Version 3. See LICENSE.txt for a copy of the license. 6 | 7 | See CHANGELOG.txt for recent changes. 8 | 9 | A detailed Users Manual consisting of a reference, several tutorials, and information on how to implement new protocols is available in .docx, .pdf and .epub formats in the IRLib2/manuals/ folder. 10 | 11 | **Because this is such an extensive rewrite of IRLib1 and is not backwards compatible, we have made this a separate GitHub repository. The code for IRLib 1.51 is the final version and will no longer be updated or maintained. New users should use this library. Only use the original versions for existing projects that require its original design. In other words IRLib 1.x should be considered depreciated.** 12 | 13 | This repository consists of a total of five libraries each of which must be in your arduino/libraries/ folder. So for example it should be installed as follows… 14 | 15 | * arduino/libraries/IRLib2 16 | * arduino/libraries/IRLibFreq 17 | * arduino/libraries/IRLibProtocols 18 | * arduino/libraries/IRLibRecv 19 | * arduino/libraries/IRLibRecvPCI 20 | 21 | Do not install them in a single folder such as this… 22 | 23 | * arduino/libraries/IRLib2_master 24 | * IRLib2 25 | * IRLibFreq 26 | * IRLibProtocols 27 | * IRLibRecv 28 | * IRLibRecvPCI 29 | 30 | Supported platforms include most 8-bit AVR Arduino boards such as Arduino Uno, Leonardo, and Mega 256. 31 | Also supports boards with SAMD 21 processor such as Arduino Zero, Arduino M0 Pro, Adafruit Feather M0, Adafruit Circuit Playground Express, Adafruit Trinket M0, Adafruit Gemma M0, and Arduino MKR 1000. Now supports SAMD51 boards such as Adafruit Feather M4, Adafruit Metro M4, and Adafruit Grand Central M4. Documentation has been updated to include all new protocols and platforms. 32 | 33 | -------------------------------------------------------------------------------- /examples/serialRemote/serialRemote.ino: -------------------------------------------------------------------------------- 1 | /* serialRemote.ino Example sketch for IRLib2 2 | * Illustrates how to send an IR signal based on data from a 3 | * serial port. You can type the data into the serial monitor 4 | * or send it from some other application such as the Python 5 | * program included in this folder. 6 | * 7 | * Send the data as 2 or 3 values. Separate them by any non-hex character. 8 | * The first is protocol number in decimal, followed by data value, 9 | * optionally followed by number of bits. 10 | */ 11 | 12 | //This includes everything. Not generally recommended. 13 | #include "IRLibAll.h" 14 | 15 | IRsend mySender; //create an instance of the sending object 16 | 17 | uint8_t protocol; 18 | uint32_t code; 19 | uint16_t bits;//also used as "address" on some protocols greater than 32 bits 20 | 21 | void setup() { 22 | Serial.begin(9600); 23 | delay(2000);while(!Serial);//delay for Leonardo 24 | Serial.println(F("Enter protocol number, data in hex, and bits separated by commas.")); 25 | } 26 | 27 | long parseHex (void) { 28 | long Value=0; char C;delay(100); 29 | while (Serial.available()>0) { 30 | C= tolower(Serial.read()); 31 | if ((C>='0')&&(C<='9')) 32 | C=C-'0'; 33 | else 34 | if ((C>='a') && (C<='f')) 35 | C=C-'a'+10; 36 | else 37 | return Value; 38 | Value= C+(Value<<4); 39 | }; 40 | return Value; 41 | } 42 | void parseDelimiter () { 43 | char C; 44 | while(Serial.available()>0) { 45 | C=tolower(Serial.peek()); 46 | if( (C>='0') && (C<='9') )return; 47 | if( (C>='a') && (C<='f') )return; 48 | C=Serial.read();//throwaway delimiters 49 | delay (5); 50 | } 51 | } 52 | 53 | void loop() { 54 | if (Serial.available ()>0) { 55 | protocol = Serial.parseInt (); parseDelimiter(); 56 | code = parseHex (); parseDelimiter(); 57 | bits = Serial.parseInt (); parseDelimiter(); 58 | Serial.print("Prot:"); Serial.print(protocol); 59 | Serial.print(" Code:"); Serial.print(code,HEX); 60 | Serial.print(" Bits:"); Serial.println(bits); 61 | mySender.send(protocol, code, bits); 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /examples/serialRemote/POV-Ray/remotebg.pov: -------------------------------------------------------------------------------- 1 | //POV-Ray source to generate the background image for IRserial_remote 2 | // create rectangular areas with rounded corners for use as 3 | // buttons and background objects. 4 | 5 | // Render at 1024x768 then crop 312 pixels from each side 6 | // leaving 400x768 final image. 7 | #declare Area=15; //size of area lights 8 | #declare CR=0.1; //corner radius 9 | #declare ER= 0.5; //edge radius 10 | #declare CX= 3; //width from corner to corner 11 | #declare CY= 7.75; //height from corner to corner 12 | #declare BZ=-ER; //Z offset for buttons 13 | 14 | plane {z,0 pigment{rgb<0.8,0.85,1>*0.8}}//background 15 | 16 | #macro Thing (ER,CR,CX,CY,T) 17 | #local Corner= 18 | union { 19 | torus {CR,ER rotate x*90} 20 | cylinder {ER*z,-ER*z,CR} 21 | } 22 | union { 23 | object{Corner translate< CX,CY,0>} 24 | object{Corner translate<-CX,CY,0>} 25 | object{Corner translate< CX,-CY,0>} 26 | object{Corner translate<-CX,-CY,0>} 27 | cylinder{CY*y,-CY*y,ER translate<-CX-CR,0,0>} 28 | cylinder{CY*y,-CY*y,ER translate< CX+CR,0,0>} 29 | cylinder{CX*x,-CX*x,ER translate<0,-CY-CR,0>} 30 | cylinder{CX*x,-CX*x,ER translate<0, CY+CR,0>} 31 | box{<-CX,-CY-CR,-ER>} 32 | box{<-CX-CR,-CY,-ER>} 33 | texture {T} 34 | } 35 | #end 36 | 37 | #declare BX= 0.4; #declare BY=BX;//size of the buttons 38 | #declare White_Texture=texture{pigment{rgb 1}finish {ambient 0.3}} 39 | #declare Blue_Texture=texture{pigment {rgb<0.85,0.9 ,1>}} 40 | 41 | object {Thing(ER,CR,CX,CY, White_Texture)}//main object 42 | //loop through the buttons 43 | #declare R=-4.5; 44 | #while (R<5.5) 45 | #declare C=-1.5; 46 | #while (C<=1.5) 47 | object{Thing(0.1,0.2,(BX*0.8),(BY*0.8), Blue_Texture) 48 | translate 49 | } 50 | #declare C=C+1; 51 | #end 52 | #declare R=R+1; 53 | #end 54 | 55 | 56 | light_source{<50,50,-100>*5 color 0.8 57 | #if (Area)area_light x*Area,y*Area,9,9#end 58 | } 59 | light_source{<0,0,-400>*3 rgb 1} 60 | 61 | camera{orthographic location <0,0,-120> look_at <0,0,0> angle 11 } 62 | //That's all folks! -------------------------------------------------------------------------------- /examples/Iot_IR/IoT_IR/IoT_IR.ino: -------------------------------------------------------------------------------- 1 | /* 2 | * IR IOT demo program 3 | * by Chris Young 4 | * use with Adafruit M0 Wi-Fi 5 | */ 6 | 7 | #include 8 | #include 9 | #include "WiFi101_Util.h" 10 | 11 | #include // First include the send base 12 | #include // Now include only the protocols you wish 13 | #include // to actually use. The lowest numbered 14 | #include // must be first but others can be any order. 15 | #include 16 | #include // After all protocols, include this 17 | 18 | IRsend My_Sender; 19 | 20 | void processIR(WiFiClient client) { 21 | int protocol = client.parseInt(); 22 | if (client.read() != '/') return; //Need more. If not there then ignore 23 | unsigned long code= client.parseInt(); 24 | //If next character is a '/' then we will parse number of bits 25 | //otherwise assume bits are zero 26 | int bits =0; 27 | if (client.read() == '/') { 28 | bits = client.parseInt(); 29 | } 30 | client.print("{\"command\":\"irsend\""); 31 | client.print(",\"protocol\":"); client.print(protocol); 32 | client.print(",\"code\":"); client.print(code); 33 | client.print(",\"bits\":"); client.print(bits); 34 | client.println('}'); 35 | My_Sender.send(protocol, code, bits); 36 | } 37 | 38 | void setup() { 39 | WiFi101_Setup(); //moved all the setup code to a separate tab for clarity 40 | } 41 | 42 | void loop() { 43 | // listen for incoming clients 44 | WiFiClient client = server.available(); 45 | if(client.available()) { 46 | //char c = client.read();//skip initial "/" 47 | #if(0) //use for debugging 48 | String command=client.readString (); 49 | Serial.print('"');Serial.print(command);Serial.print('"'); 50 | #else 51 | String command= client.readStringUntil('/');//Skips over "Put" to the start of the commands 52 | command= client.readStringUntil('/'); 53 | if(command == "irsend") { //is this IR send command 54 | processIR(client); 55 | } //add an else if there are other kinds of commands 56 | #endif 57 | client.stop(); 58 | } 59 | delay(50);//Poll every 50ms 60 | } 61 | 62 | 63 | -------------------------------------------------------------------------------- /readme.md: -------------------------------------------------------------------------------- 1 | # Seeed_Arduino_IR [![Build Status](https://travis-ci.com/Seeed-Studio/IRLib2.svg?branch=master)](https://travis-ci.com/Seeed-Studio/IRLib2) 2 | Seeed_Arduino_IR forked from [RLib2](https://github.com/cyborg5/IRLib2). It is a Library for Receiving, Decoding and Sending Infrared Signals Using Arduino. 3 | 4 | IRLib2 is copyright 2017 by Chris Young. It it is a major rewrite of the original IRLib 1.x by Chris Young which in turn was based on IRremote by Ken Shirriff. See COPYRIGHT.txt for details. 5 | 6 | This library is covered under the GNU GENERAL PUBLIC LICENSE Version 3. See LICENSE.txt for a copy of the license. 7 | 8 | See CHANGELOG.txt for recent changes. 9 | 10 | A detailed Users Manual consisting of a reference, several tutorials, and information on how to implement new protocols is available in .docx, .pdf and .epub formats in the IRLib2/manuals/ folder. 11 | 12 | **Because this is such an extensive rewrite of IRLib1 and is not backwards compatible, we have made this a separate GitHub repository. The code for IRLib 1.51 is the final version and will no longer be updated or maintained. New users should use this library. Only use the original versions for existing projects that require its original design. In other words IRLib 1.x should be considered depreciated.** 13 | 14 | This repository consists of a total of five libraries each of which must be in your arduino/libraries/ folder. So for example it should be installed as follows… 15 | 16 | * arduino/libraries/IRLib2 17 | * arduino/libraries/IRLibFreq 18 | * arduino/libraries/IRLibProtocols 19 | * arduino/libraries/IRLibRecv 20 | * arduino/libraries/IRLibRecvPCI 21 | 22 | Do not install them in a single folder such as this… 23 | 24 | * arduino/libraries/IRLib2_master 25 | * IRLib2 26 | * IRLibFreq 27 | * IRLibProtocols 28 | * IRLibRecv 29 | * IRLibRecvPCI 30 | 31 | Supported platforms include most 8-bit AVR Arduino boards such as Arduino Uno, Leonardo, and Mega 256. 32 | Also supports boards with SAMD 21 processor such as Arduino Zero, Arduino M0 Pro, Adafruit Feather M0, Adafruit Circuit Playground Express, Adafruit Trinket M0, Adafruit Gemma M0, and Arduino MKR 1000. Now supports SAMD51 boards such as Adafruit Feather M4, Adafruit Metro M4, and Adafruit Grand Central M4. Documentation has been updated to include all new protocols and platforms. 33 | 34 | -------------------------------------------------------------------------------- /src/IRLibRecvLoop.cpp: -------------------------------------------------------------------------------- 1 | /* IRLibRecvLoop.cpp 2 | * Part of IRLib Library for Arduino receiving, decoding, and sending 3 | * infrared signals. See COPYRIGHT.txt and LICENSE.txt for more information. 4 | * 5 | * This module implements the IRLibRecvLoop receiver. 6 | * Other interrupt driven receivers allow you to do other things and call getResults at 7 | * your leisure to see if perhaps a sequence has been received. Typically you would put 8 | * getResults in your loop and it would return false until the sequence had been received. 9 | * However because this receiver uses no interrupts, it takes control of your program when 10 | * you call getResults and doesn't let go until it's got something to show you. The advantage 11 | * is you don't need interrupts which would make it easier to use on non-standard hardware 12 | * and will allow you to use any digital input pin. Timing of this routine is only as 13 | * accurate as your "micros();" Note the enableIRIn method should still be called because 14 | * initializes the input pin even though that method does nothing else. Similarly 15 | * disableIRin doesn't do anything. Also auto resume is meaningless because there is no 16 | * multitasking possible. 17 | */ 18 | 19 | #include "IRLibRecvLoop.h" 20 | 21 | bool IRrecvLoop::getResults(void) { 22 | uint8_t oldState=HIGH;uint8_t newState; 23 | uint32_t startTime, endTime; 24 | startTime=micros(); 25 | recvGlobal.currentState=STATE_RUNNING; 26 | while(recvGlobal.currentState==STATE_RUNNING) { 27 | while(oldState==(newState=digitalRead(recvGlobal.recvPin))) { //while pin unchanged 28 | //if SPACE and not initial gap test for timeout 29 | if(oldState && recvGlobal.recvLength) {//oldState=HIGH means SPACE. 30 | //If it's a very long wait 31 | if( (micros()-startTime) > recvGlobal.frameTimeout) { 32 | recvGlobal.currentState= STATE_FINISHED; 33 | break; //exit the pin unchanged loop 34 | } 35 | } 36 | } 37 | IRLib_doBlink(); 38 | recvGlobal.recvBuffer[recvGlobal.recvLength]=(endTime=micros()) - startTime; 39 | oldState=newState; 40 | startTime=endTime; 41 | if(++recvGlobal.recvLength>=RECV_BUF_LENGTH) { 42 | recvGlobal.currentState=STATE_FINISHED; 43 | } 44 | } 45 | recvGlobal.recvLength--;//ignore final SPACE 46 | recvGlobal.didAutoResume=false;//no multi processing possible with IRrecvLoop 47 | IRrecvBase::getResults(); 48 | return true; 49 | } 50 | -------------------------------------------------------------------------------- /examples/Iot_IR/IoT_IR/WiFi101_Util.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Moved all of the Wi-Fi initialization and debugging code here for clarity 3 | */ 4 | #include "arduino_secrets.h" 5 | ///////please enter your sensitive data in the Secret tab/arduino_secrets.h 6 | char ssid[] = SECRET_SSID; // your network SSID (name) 7 | char pass[] = SECRET_PASS; // your network password (use for WPA, or use as key for WEP) 8 | int keyIndex = 0; // your network key Index number (needed only for WEP) 9 | 10 | //Set to 1 if you are going to open the serial monitor 11 | #define SERIAL_DEBUG 0 12 | IPAddress ip; 13 | int status = WL_IDLE_STATUS; 14 | // Initialize the WiFi server library 15 | WiFiServer server(80); 16 | 17 | #if SERIAL_DEBUG 18 | void printWifiStatus() { 19 | // print the SSID of the network you're attached to: 20 | Serial.print("SSID: "); 21 | Serial.println(WiFi.SSID()); 22 | 23 | // print your WiFi shield's IP address: 24 | Serial.print("IP Address: "); 25 | Serial.println(ip); 26 | 27 | // print the received signal strength: 28 | long rssi = WiFi.RSSI(); 29 | Serial.print("signal strength (RSSI):"); 30 | Serial.print(rssi); 31 | Serial.println(" dBm"); 32 | } 33 | #endif 34 | 35 | void WiFi101_Setup(void) { 36 | #if defined(ARDUINO_SAMD_FEATHER_M0) 37 | //Configure pins for Adafruit ATWINC1500 Feather 38 | WiFi.setPins(8,7,4,2); 39 | #endif 40 | 41 | #if SERIAL_DEBUG 42 | // Start Serial 43 | Serial.begin(115200); 44 | 45 | // check for the presence of the shield: 46 | if (WiFi.status() == WL_NO_SHIELD) { 47 | Serial.println("WiFi shield not present"); 48 | // don't continue: 49 | while (true); 50 | } 51 | 52 | String fv = WiFi.firmwareVersion(); 53 | if ( fv != "1.1.0" ) 54 | Serial.println("Please upgrade the firmware"); 55 | #endif 56 | // Attempt to connect to Wifi network: 57 | while ( status != WL_CONNECTED) { 58 | #if SERIAL_DEBUG 59 | Serial.print("Attempting to connect to SSID: "); 60 | Serial.println(ssid); 61 | #endif 62 | // Connect to WPA/WPA2 network. Change this line if using open or WEP network: 63 | status = WiFi.begin(ssid, pass); 64 | // Wait 10 seconds for connection 65 | delay(10000); 66 | } 67 | // Start the server 68 | server.begin(); 69 | ip = WiFi.localIP(); 70 | #if SERIAL_DEBUG 71 | // Print out the status 72 | printWifiStatus(); 73 | #endif 74 | } 75 | 76 | 77 | -------------------------------------------------------------------------------- /examples/dumpFreq/dumpFreq.ino: -------------------------------------------------------------------------------- 1 | /* dumpFreq.ino Example sketch for IRLib2 2 | * Illustrates how to simultaneously decode an IR stream and 3 | * measure modulation frequency using the IRfrequency class in 4 | * the IRLibFreq library. You must connect an IR learner such 5 | * as TSMP58000 to a hardware interrupt pin. Rather than use the 6 | * IRrecv receiver we recommend using the IRrecvPCI or IRrecvLoop 7 | * receiver because the 50 microsecond interrupts from IRrecv 8 | * can cause inaccurate results. 9 | */ 10 | #include //Note this also includes "IRLibFreq.h" 11 | 12 | //NOTE: Previous versions of IRLib required you to pass the 13 | // interrupt number to be passed to the built-in "attachInterrupt()" 14 | // function however starting with IRLib 2.x you now pass the pin number. 15 | #define RECEIVER_PIN 2 16 | #define FREQUENCY_PIN 3 17 | 18 | IRrecvPCI myReceiver(RECEIVER_PIN); 19 | //IRrecvLoop myReceiver(RECEIVER_PIN); //comment out previous line and un-comment this for loop version 20 | IRfrequency myFreq(FREQUENCY_PIN); 21 | IRdecode myDecoder; 22 | 23 | void setup() { 24 | Serial.begin(9600); 25 | delay(2000);while(!Serial);//delay for Leonardo 26 | if(F_CPU<16000000) { 27 | Serial.println(F("WARNING: CPU speed less than 16 MHz will be inaccurate")); 28 | Serial.print(F("for frequencies over 45 kHz. Your CPU is:")); 29 | Serial.print(F_CPU/1000000,DEC); Serial.println(F(" Mhz")); 30 | } 31 | int8_t intrNum=digitalPinToInterrupt(FREQUENCY_PIN); 32 | if(intrNum==NOT_AN_INTERRUPT) { 33 | Serial.println(F("Invalid frequency pin number.")); 34 | while (1) {};//infinite loop because of fatal error 35 | } 36 | Serial.print(F("Frequency interrupt=")); Serial.print(intrNum,DEC); 37 | Serial.print(F(" Pin=")); Serial.println(FREQUENCY_PIN,DEC); 38 | intrNum=digitalPinToInterrupt(RECEIVER_PIN); 39 | if (intrNum==NOT_AN_INTERRUPT) { 40 | Serial.println(F("Invalid receiver pin number.")); 41 | while (1) {};//infinite loop because of fatal error 42 | } 43 | Serial.print(F("Receiver interrupt=")); Serial.print(intrNum,DEC); 44 | Serial.print(F(" Pin=")); Serial.println(RECEIVER_PIN,DEC); 45 | 46 | myReceiver.enableIRIn(); // Start the receiver 47 | myFreq.enableFreqDetect();//starts interrupt routine to compute frequency 48 | } 49 | 50 | void loop() { 51 | if (myReceiver.getResults()) { 52 | myFreq.disableFreqDetect();//Stop interrupt as soon as possible 53 | myDecoder.decode(); 54 | myFreq.dumpResults(false);//Change to "true" for more detail 55 | myDecoder.dumpResults(); 56 | myReceiver.enableIRIn(); 57 | myFreq.enableFreqDetect();//Zero out previous results and restart ISR 58 | } 59 | } 60 | 61 | -------------------------------------------------------------------------------- /src/IRLib_P05_Panasonic_Old.h: -------------------------------------------------------------------------------- 1 | /* IRLib_P05_Panasonic_Old.h 2 | * Part of IRLib Library for Arduino receiving, decoding, and sending 3 | * infrared signals. See COPYRIGHT.txt and LICENSE.txt for more information. 4 | */ 5 | /* 6 | * This protocol #5 named "Panasonic_Old" is a 57 kHz protocol with 22 bits 7 | * of data. The second 11 bits are the bitwise logical complement of the first 11 bits. 8 | * The protocol is used by many cable boxes and DVR's made by Scientific Atlantic and 9 | * Cisco. They are common for Bright House and Time Warner cable systems. 10 | */ 11 | 12 | #ifndef IRLIB_PROTOCOL_05_H 13 | #define IRLIB_PROTOCOL_05_H 14 | #define IR_SEND_PROTOCOL_05 case 5: IRsendPanasonic_Old::send(data); break; 15 | #define IR_DECODE_PROTOCOL_05 if(IRdecodePanasonic_Old::decode()) return true; 16 | #ifdef IRLIB_HAVE_COMBO 17 | #define PV_IR_DECODE_PROTOCOL_05 ,public virtual IRdecodePanasonic_Old 18 | #define PV_IR_SEND_PROTOCOL_05 ,public virtual IRsendPanasonic_Old 19 | #else 20 | #define PV_IR_DECODE_PROTOCOL_05 public virtual IRdecodePanasonic_Old 21 | #define PV_IR_SEND_PROTOCOL_05 public virtual IRsendPanasonic_Old 22 | #endif 23 | 24 | #ifdef IRLIBSENDBASE_H 25 | class IRsendPanasonic_Old: public virtual IRsendBase { 26 | public: 27 | void send(uint32_t data) { 28 | sendGeneric(data,22, 833*4, 833*4, 833, 833, 833*3, 833,57, true); 29 | }; 30 | }; 31 | #endif //IRLIBSENDBASE_H 32 | 33 | #ifdef IRLIBDECODEBASE_H 34 | class IRdecodePanasonic_Old: public virtual IRdecodeBase { 35 | public: 36 | virtual bool decode(void) { 37 | IRLIB_ATTEMPT_MESSAGE(F("Panasonic_Old")); 38 | if(!decodeGeneric(48,833*4,833*4,833,833*3,833)) return false; 39 | // The protocol spec says that the first 11 bits described the device and function. 40 | // The next 11 bits are the same thing only it is the logical Bitwise complement. 41 | // Many protocols have such check features in their definition but our code typically 42 | // doesn't perform these checks. For example NEC's least significant 8 bits are the 43 | // complement of the next more significant 8 bits. While it's probably not necessary 44 | // to error check this, you can un-comment the next 4 lines of code to do this extra 45 | // checking. 46 | // long S1= (value & 0x0007ff); // 00 0000 0000 0111 1111 1111 47 | // long S2= (value & 0x3ff800)>> 11; // 11 1111 1111 1000 0000 0000 48 | // S2= (~S2) & 0x0007ff; 49 | // if (S1!=S2) return IRLIB_REJECTION_MESSAGE(F("inverted bit redundancy")); 50 | protocolNum = PANASONIC_OLD; 51 | return true; 52 | }; 53 | }; 54 | #endif //IRLIBDECODEBASE_H 55 | 56 | #define IRLIB_HAVE_COMBO 57 | 58 | #endif //IRLIB_PROTOCOL_05_H 59 | -------------------------------------------------------------------------------- /src/IRLib_P09_GICable.h: -------------------------------------------------------------------------------- 1 | /* IRLib_P09_GICable.h 2 | * Part of IRLib Library for Arduino receiving, decoding, and sending 3 | * infrared signals. See COPYRIGHT.txt and LICENSE.txt for more information. 4 | */ 5 | 6 | /* The G.I. Cable protocol is is used by many Motorola brand cable boxes manufactured by 7 | * General Instruments. The IRP notation for this protocol is 8 | * "{38.7k,490}<1,-4.5|1,-9>(18,-9,F:8,D:4,C:4,1,-84,(18,-4.5,1,-178)*) {C = -(D + F:4 + F:4:4)}" 9 | * It is a 16-bit code which uses an unusual "ditto" repeat sequence similar to NEC. 10 | * In fact it is so similar that IRLib generally not distinguish between the two. 11 | * The header timing for G.I. Cable ditto is 8820,1960 and for NEC is 9024,2256 12 | * If you are using both protocols and you receive an NEC ditto immediately after 13 | * receiving a G.I.Cable then you should presume it is a G.I.Cable and vice versa. 14 | */ 15 | #ifndef IRLIB_PROTOCOL_09_H 16 | #define IRLIB_PROTOCOL_09_H 17 | #define IR_SEND_PROTOCOL_09 case 9: IRsendGICable::send(data); break; 18 | #define IR_DECODE_PROTOCOL_09 if(IRdecodeGICable::decode()) return true; 19 | #ifdef IRLIB_HAVE_COMBO 20 | #define PV_IR_DECODE_PROTOCOL_09 ,public virtual IRdecodeGICable 21 | #define PV_IR_SEND_PROTOCOL_09 ,public virtual IRsendGICable 22 | #else 23 | #define PV_IR_DECODE_PROTOCOL_09 public virtual IRdecodeGICable 24 | #define PV_IR_SEND_PROTOCOL_09 public virtual IRsendGICable 25 | #endif 26 | 27 | #ifdef IRLIBSENDBASE_H 28 | class IRsendGICable: public virtual IRsendBase { 29 | public: 30 | void send(uint32_t data) { 31 | if(data==REPEAT_CODE) { 32 | enableIROut(39); 33 | mark (490*18); space(2205);//actually "490*4.5" 34 | mark (490); space(220);delay(87);//actually 490*178 or "space(87220);" 35 | } else { 36 | sendGeneric(data,16, 490*18, 490*9, 490, 490, 490*9, 2205/*(4.5*490)*/, 39, true); 37 | space(37*490); 38 | } 39 | } 40 | }; 41 | #endif //IRLIBSENDBASE_H 42 | 43 | #ifdef IRLIBDECODEBASE_H 44 | class IRdecodeGICable: public virtual IRdecodeBase { 45 | public: 46 | bool decode(void) { 47 | IRLIB_ATTEMPT_MESSAGE(F("G.I.cable")); 48 | // Check for repeat 49 | if (recvGlobal.decodeLength == 4 && MATCH(recvGlobal.decodeBuffer[1], 490*18) && MATCH(recvGlobal.decodeBuffer[2],2205) 50 | && MATCH(recvGlobal.decodeBuffer[3],490)) { 51 | bits = 0; 52 | value = REPEAT_CODE; 53 | protocolNum=GICABLE; 54 | return true; 55 | } 56 | if(!decodeGeneric(36, 18*490, 9*490, 490, 9*490, 2205/*(4.5*490)*/)) return false; 57 | protocolNum=GICABLE; 58 | return true; 59 | } 60 | }; 61 | #endif //IRLIBDECODEBASE_H 62 | 63 | #define IRLIB_HAVE_COMBO 64 | 65 | #endif //IRLIB_PROTOCOL_09_H 66 | -------------------------------------------------------------------------------- /src/IRLib_P06_JVC.h: -------------------------------------------------------------------------------- 1 | /* IRLib_P06_JVC.h 2 | * Part of IRLib Library for Arduino receiving, decoding, and sending 3 | * infrared signals. See COPYRIGHT.txt and LICENSE.txt for more information. 4 | */ 5 | /* 6 | * JVC omits the mark/space header on repeat sending. Therefore we multiply 7 | * it by 0 if it's a repeat. The only device I had to test this protocol was 8 | * an old JVC VCR. It would only work if at least 2 frames are sent separated 9 | * by 45 time periods of "space". Therefore you should call this routine once 10 | * with "first=true" and it will send a first frame followed by one repeat 11 | * frame. If First==false, it will only send a single repeat frame. 12 | */ 13 | 14 | #ifndef IRLIB_PROTOCOL_06_H 15 | #define IRLIB_PROTOCOL_06_H 16 | #define IR_SEND_PROTOCOL_06 case 06: IRsendJVC::send(data,(bool)data2); break; 17 | #define IR_DECODE_PROTOCOL_06 if(IRdecodeJVC::decode()) return true; 18 | #ifdef IRLIB_HAVE_COMBO 19 | #define PV_IR_DECODE_PROTOCOL_06 ,public virtual IRdecodeJVC 20 | #define PV_IR_SEND_PROTOCOL_06 ,public virtual IRsendJVC 21 | #else 22 | #define PV_IR_DECODE_PROTOCOL_06 public virtual IRdecodeJVC 23 | #define PV_IR_SEND_PROTOCOL_06 public virtual IRsendJVC 24 | #endif 25 | 26 | #ifdef IRLIBSENDBASE_H 27 | class IRsendJVC: public virtual IRsendBase { 28 | public: 29 | void send(uint32_t data, bool first=true) { 30 | sendGeneric(data, 16,525*16*first, 525*8*first, 525, 525,525*3, 525, 38, true); 31 | space(525*45); 32 | if(first) { 33 | sendGeneric(data, 16,0,0, 525, 525,525*3, 525, 38, true); 34 | space(525*45); 35 | } 36 | } 37 | }; 38 | #endif //IRLIBSENDBASE_H 39 | 40 | #ifdef IRLIBDECODEBASE_H 41 | class IRdecodeJVC: public virtual IRdecodeBase { 42 | public: 43 | bool decode(void) { 44 | // JVC does not send any header if there is a repeat. 45 | // first try with the header. If that fails, try without. 46 | IRLIB_ATTEMPT_MESSAGE(F("JVC")); 47 | if(!decodeGeneric(36,525*16,525*8,525,525*3,525)) { 48 | IRLIB_ATTEMPT_MESSAGE(F("JVC Repeat")); 49 | if (recvGlobal.decodeLength==34) { 50 | if(!decodeGeneric(0,525,0,525,525*3,525)) { 51 | return IRLIB_REJECTION_MESSAGE(F("JVC repeat failed generic")); 52 | } else { 53 | //If this is a repeat code then IRdecodeBase::decodeGeneric fails to add the most significant bit 54 | if (MATCH(recvGlobal.decodeBuffer[2],(525*3))) { 55 | value |= 0x8000; 56 | } else { 57 | if (!MATCH(recvGlobal.decodeBuffer[2],525)) return DATA_SPACE_ERROR(525); 58 | } 59 | } 60 | bits++; 61 | } 62 | else return RAW_COUNT_ERROR; 63 | } 64 | address=(recvGlobal.decodeLength==36); 65 | protocolNum =JVC; 66 | return true; 67 | } 68 | }; 69 | #endif //IRLIBDECODEBASE_H 70 | 71 | #define IRLIB_HAVE_COMBO 72 | 73 | #endif //IRLIB_PROTOCOL_06_H 74 | -------------------------------------------------------------------------------- /src/IRLib_P02_Sony.h: -------------------------------------------------------------------------------- 1 | /* IRLib_P02_Sony.h 2 | * Part of IRLib Library for Arduino receiving, decoding, and sending 3 | * infrared signals. See COPYRIGHT.txt and LICENSE.txt for more information. 4 | */ 5 | /* 6 | * Sony is backwards from most protocols. It uses a variable length mark and a fixed length 7 | * space rather than a fixed mark and a variable space. Our generic send will still work 8 | * however we need a custom decoding routine because it's difficult to get the generic 9 | * decoder to handle a variable length mark without cluttering up the code to much. 10 | * According to the protocol you must send Sony commands at least three times so we 11 | * automatically do it here. Sony can be 8, 12, 15, or 20 bits in length. 12 | * The 8 bit version uses a shorter trailing space at the end. The signal is modulated 13 | * at 40 kHz however most 38 kHz receivers are broad enough to receive it. 14 | */ 15 | 16 | #ifndef IRLIB_PROTOCOL_02_H 17 | #define IRLIB_PROTOCOL_02_H 18 | #define IR_SEND_PROTOCOL_02 case 2: IRsendSony::send(data,data2); break; 19 | #define IR_DECODE_PROTOCOL_02 if(IRdecodeSony::decode()) return true; 20 | #ifdef IRLIB_HAVE_COMBO 21 | #define PV_IR_DECODE_PROTOCOL_02 ,public virtual IRdecodeSony 22 | #define PV_IR_SEND_PROTOCOL_02 ,public virtual IRsendSony 23 | #else 24 | #define PV_IR_DECODE_PROTOCOL_02 public virtual IRdecodeSony 25 | #define PV_IR_SEND_PROTOCOL_02 public virtual IRsendSony 26 | #endif 27 | 28 | #ifdef IRLIBSENDBASE_H 29 | class IRsendSony: public virtual IRsendBase { 30 | public: 31 | void send(uint32_t data, uint8_t nbits) { 32 | for(uint8_t i=0; i<3;i++){ 33 | sendGeneric(data,nbits, 600*4, 600, 600*2, 600, 600, 600, 40, false,45000); 34 | } 35 | } 36 | }; 37 | #endif //IRLIBSENDBASE_H 38 | 39 | #ifdef IRLIBDECODEBASE_H 40 | class IRdecodeSony: public virtual IRdecodeBase { 41 | public: 42 | virtual bool decode(void) { 43 | IRLIB_ATTEMPT_MESSAGE(F("Sony")); 44 | resetDecoder();//This used to be in the receiver getResults. 45 | if(recvGlobal.decodeLength!=2*8+2 && recvGlobal.decodeLength!=2*12+2 && recvGlobal.decodeLength!=2*15+2 46 | && recvGlobal.decodeLength!=2*20+2) return RAW_COUNT_ERROR; 47 | if(!ignoreHeader) { 48 | if (!MATCH(recvGlobal.decodeBuffer[1],600*4)) return HEADER_MARK_ERROR(600*4); 49 | } 50 | offset=2;//skip initial gap plus header Mark. 51 | while (offset < recvGlobal.decodeLength) { 52 | if (!MATCH(recvGlobal.decodeBuffer[offset],600)) return DATA_SPACE_ERROR(600); 53 | offset++; 54 | if (MATCH(recvGlobal.decodeBuffer[offset],600*2)) { 55 | value = (value << 1) | 1; 56 | } 57 | else if (MATCH(recvGlobal.decodeBuffer[offset],600)) { 58 | value <<= 1; 59 | } 60 | else return DATA_MARK_ERROR(600); 61 | offset++; 62 | } 63 | bits = (offset - 1) / 2; 64 | protocolNum = SONY; 65 | return true; 66 | } 67 | }; 68 | #endif //IRLIBDECODEBASE_H 69 | 70 | #define IRLIB_HAVE_COMBO 71 | 72 | #endif //IRLIB_PROTOCOL_02_H 73 | -------------------------------------------------------------------------------- /COPYRIGHT.txt: -------------------------------------------------------------------------------- 1 | Copyright information for IRLib – an Arduino library for 2 | infrared encoding and decoding 3 | 4 | IRLib2 is a collection of libraries which we will collectively referred 5 | to as the PACKAGE. The PACKAGE consists of all files in the IRLib2, 6 | IRLibFreq, IRLibRecv, IRLibRecvPCI, and IRLibProtocols folders. 7 | 8 | The PACKAGE is Copyright (c) 2014-2017 by Chris Young 9 | 10 | This program is free software: you can redistribute it and/or modify 11 | it under the terms of the GNU General Public License as published by 12 | the Free Software Foundation, either version 3 of the License, or 13 | (at your option) any later version. 14 | 15 | This program is distributed in the hope that it will be useful, 16 | but WITHOUT ANY WARRANTY; without even the implied warranty of 17 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 | GNU General Public License for more details. 19 | 20 | These files will be maintained at https://github.com/cyborg5/IRLib2 21 | Documentation and other support info at http://tech.cyborg5.com/irlib 22 | 23 | This is an updated version of my original IRLib which is still available at 24 | https://github.com/cyborg5/IRLib which will not be updated after this 25 | PACKAGE has its first stable non-beta release. 26 | 27 | Both libraries are derived from the original source code in a library called 28 | IRemote by Ken Shirriff which was covered by GNU LESSER GENERAL PUBLIC 29 | LICENSE version 2.1. This package is covered by the GNU GENERAL PUBLIC 30 | LICENSE 3.0. See LICENSE.txt for a copy of that license or visit 31 | https://www.gnu.org/licenses/ 32 | 33 | As I understand these licenses it is permissible to upgrade the license 34 | this way. Additionally this license change was made with the approval of 35 | Mr. Shirriff in an email conversation I had with him. In accord with his 36 | wishes and out of respect for his work, his original copyright message is 37 | shown below. 38 | 39 | /* 40 | * IRremote 41 | * Version 0.1 July, 2009 42 | * Copyright 2009 Ken Shirriff 43 | * For details, see http://www.righto.com/2009/08/multi-protocol-infrared-remote-library.html http://www.righto.com/ 44 | * 45 | * Interrupt code based on NECIRrcv by Joe Knapp 46 | * http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1210243556 47 | * Also influenced by http://zovirl.com/2008/11/12/building-a-universal-remote-with-an-arduino/ 48 | */ 49 | 50 | We also acknowledge and thank the developers of the AnalysIR program. AnalysIR is a Windows-based application which allows you to graphically analyze IR input signals through an Arduino, Raspberry Pi or other microcontrollers systems. The frequency analysis and other PCI based versions of the program are based upon and inspired by their work. We value their input into the development of that portion of the code. You can find more about their software at http://analysir.com 51 | 52 | We also knowledge and thank programmer Gabriel Staples contributed bug fixes and an earlier version of the auto resume feature. Although much of his code was rewritten it could not have been possible without his contributions. 53 | 54 | Other major contributors will be acknowledged in this file in the future. -------------------------------------------------------------------------------- /src/IRLib_P07_NECx.h: -------------------------------------------------------------------------------- 1 | /* IRLib_P07_NECx.h 2 | * Part of IRLib Library for Arduino receiving, decoding, and sending 3 | * infrared signals. See COPYRIGHT.txt and LICENSE.txt for more information. 4 | */ 5 | /* 6 | * NECx is a variation of NEC protocol. The only difference is in the timing of the 7 | * header. There are two variations NECx1 and NECx2. They differ only in the way in 8 | * which they handle repeat codes. If you hold a button using NECx1 it does not repeat 9 | * the same sequence. Rather it sends a special sequence consisting of the usual header 10 | * followed by a normal mark, a "1" bit, and then a long space with a 108ms extent. Note 11 | * this so-called "ditto" repeat code is slightly different than the one for regular NEC. 12 | * When IRLib receives one of these special repeat sequences, it returns the 13 | * value REPEAT_CODE which is defined in IRLibProtocols.h as the value 0xffffffff. If you 14 | * send REPEAT_CODE, the send routine will create a special sequence for you. 15 | * Whether it is a normal code or a repeat code the entire frame has a 108ms extent. 16 | * The IRP notation for these protocols are: 17 | * NECx1: {38k,564}<1,-1|1,-3>(8,-8,D:8,S:8,F:8,~F:8,1,^108,(8,-8,D:1,1,^108m)*) 18 | * NECx2: {38k,564}<1,-1|1,-3>(8,-8,D:8,S:8,F:8,~F:8,1,^108)+ 19 | */ 20 | 21 | #ifndef IRLIB_PROTOCOL_07_H 22 | #define IRLIB_PROTOCOL_07_H 23 | #define IR_SEND_PROTOCOL_07 case 07: IRsendNECx::send(data); break; 24 | #define IR_DECODE_PROTOCOL_07 if(IRdecodeNECx::decode()) return true; 25 | #ifdef IRLIB_HAVE_COMBO 26 | #define PV_IR_DECODE_PROTOCOL_07 ,public virtual IRdecodeNECx 27 | #define PV_IR_SEND_PROTOCOL_07 ,public virtual IRsendNECx 28 | #else 29 | #define PV_IR_DECODE_PROTOCOL_07 public virtual IRdecodeNECx 30 | #define PV_IR_SEND_PROTOCOL_07 public virtual IRsendNECx 31 | #endif 32 | 33 | #ifdef IRLIBSENDBASE_H 34 | class IRsendNECx: public virtual IRsendBase { 35 | public: 36 | void send(uint32_t data) { 37 | if (data==REPEAT_CODE) { 38 | enableIROut(38); 39 | mark(564*8); space(564*8); mark(564);space(564); 40 | mark(564); space(412);delay(98);//actually 98412us 41 | } 42 | else { 43 | sendGeneric(data,32, 564*8, 564*8, 564, 564, 564*3, 564, 38, true); 44 | } 45 | }; 46 | }; 47 | #endif //IRLIBSENDBASE_H 48 | 49 | #ifdef IRLIBDECODEBASE_H 50 | class IRdecodeNECx: public virtual IRdecodeBase { 51 | public: 52 | virtual bool decode(void) { 53 | IRLIB_ATTEMPT_MESSAGE(F("NECx")); 54 | resetDecoder();//This used to be in the receiver getResults. 55 | // Check for repeat 56 | if (recvGlobal.decodeLength == 6 && MATCH(recvGlobal.decodeBuffer[1], 564*8) && MATCH(recvGlobal.decodeBuffer[2],564*8) 57 | && MATCH(recvGlobal.decodeBuffer[3],564) && MATCH(recvGlobal.decodeBuffer[5],564) 58 | ) { 59 | bits = 0; 60 | value = REPEAT_CODE; 61 | protocolNum = NECX; 62 | return true; 63 | } 64 | if(!decodeGeneric(68, 564*8, 564*8, 564, 564*3, 564)) return false; 65 | protocolNum = NECX; 66 | return true; 67 | } 68 | }; 69 | #endif //IRLIBDECODEBASE_H 70 | 71 | #define IRLIB_HAVE_COMBO 72 | 73 | #endif //IRLIB_PROTOCOL_07_H 74 | -------------------------------------------------------------------------------- /src/IRLibFreq.cpp: -------------------------------------------------------------------------------- 1 | /* IRLibFreq.cpp 2 | * Part of IRLib Library for Arduino receiving, decoding, and sending 3 | * infrared signals. See COPYRIGHT.txt and LICENSE.txt for more information. 4 | * 5 | * This class facilitates detection of frequency of an IR signal. It requires 6 | * a different kind of receiver specifically a TSMP58000 or equivalent device 7 | * connected to the hardware interrupt pin. Create an instance of the object 8 | * passing the interrupt number. 9 | */ 10 | #include 11 | #include 12 | #include "IRLibFreq.h" 13 | 14 | volatile FREQUENCY_BUFFER_TYPE *IRfreqTimes; 15 | volatile uint8_t IRfreqCount; 16 | IRfrequency::IRfrequency(uint8_t pin) { 17 | intrNum=digitalPinToInterrupt(pin); 18 | //ISR cannot be passed parameters. If I declare the buffer global it would 19 | //always eat RAN even if this object was not declared. So we make global pointer 20 | //and copy the address to it. ISR still puts data in the object. 21 | IRfreqTimes= & (Time_Stamp[0]); 22 | }; 23 | 24 | // Note ISR handler cannot be part of a class/object 25 | void IRfreqISR(void) { 26 | IRfreqTimes[IRfreqCount++]=micros(); 27 | } 28 | 29 | void IRfrequency::enableFreqDetect(void){ 30 | attachInterrupt(intrNum,IRfreqISR,FALLING); 31 | for(i=0; i<256; i++) Time_Stamp[i]=0; 32 | IRfreqCount=0; 33 | results=0.0; 34 | samples=0; 35 | }; 36 | 37 | /* Test to see if we have collected at least one full buffer of data. 38 | * Note values are always zeroed before beginning so any non-zero data 39 | * in the final elements means we have collected at least a buffer full. 40 | * By chance the final might be zero so we test two of them. Would be 41 | * nearly impossible for two consecutive elements to be zero unless 42 | * we had not yet collected data. 43 | */ 44 | bool IRfrequency::haveData(void) { 45 | return (Time_Stamp[255] || Time_Stamp[254]); 46 | }; 47 | 48 | void IRfrequency::disableFreqDetect(void){ 49 | detachInterrupt(intrNum); 50 | }; 51 | 52 | void IRfrequency::computeFreq(void){ 53 | samples=0; sum=0; 54 | for(i=1; i<256; i++) { 55 | uint8_t interval=Time_Stamp[i]-Time_Stamp[i-1]; 56 | if(interval>50 || interval<10) continue;//ignore extraneous results 57 | sum+=interval;//accumulate usable intervals 58 | samples++; //account usable intervals 59 | }; 60 | if(sum) 61 | results=(double) samples/(double)sum*1000; 62 | else 63 | results= 0.0; 64 | }; 65 | 66 | void IRfrequency::dumpResults(bool detail) { 67 | computeFreq(); 68 | Serial.print(F("Number of samples:")); Serial.print(samples,DEC); 69 | Serial.print(F("\t Total interval (us):")); Serial.println(sum,DEC); 70 | Serial.print(F("Avg. interval(us):")); Serial.print(1.0*sum/samples,2); 71 | Serial.print(F("\t Aprx. Frequency(kHz):")); Serial.print(results,2); 72 | Serial.print(F(" (")); Serial.print(int(results+0.5),DEC); 73 | Serial.println(F(")")); 74 | if(detail) { 75 | for(i=1; i<256; i++) { 76 | uint16_t interval=Time_Stamp[i]-Time_Stamp[i-1]; 77 | Serial.print(interval,DEC); Serial.print("\t"); 78 | if ((i % 4)==0)Serial.print(F("\t ")); 79 | if ((i % 8)==0)Serial.println(); 80 | if ((i % 32)==0)Serial.println(); 81 | } 82 | Serial.println(); 83 | } 84 | }; 85 | -------------------------------------------------------------------------------- /examples/Iot_IR/readme.md: -------------------------------------------------------------------------------- 1 | # IoT_IR Internet of Things Infrared Remote 2 | 3 | This folder contains a sample implementation of an Internet of things IR remote using Adafruit Feather M0 Wi-Fi and Arduino MKR 1000. 4 | 5 | Recommended that you familiarize yourself with the board before proceeding with this example. For the Adafruit Feather M0 Wi-Fi the tutorial at 6 | https://learn.adafruit.com/adafruit-feather-m0-wifi-atwinc1500?view=all 7 | 8 | For the Arduino MKR 1000 see the guide at 9 | https://www.arduino.cc/en/Guide/MKR1000 10 | 11 | Go through all of the Wi-Fi examples in that tutorial to make sure that your board is working. You will have to edit the "arduino_secrets.h" file to include your Wi-Fi name and password. 12 | 13 | There are two sample pages included in this folder. The file "adafruit_remote.html" emulates the Adafruit Mini Remote https://www.adafruit.com/product/389 14 | 15 | The other sample page is "cable_and_tv.html" which has codes for a BrightHouse/Spectrum cable box using the Panasonic_Old protocol and a Samsung TV using NECx protocol. 16 | 17 | You can simply open these files in your computer without actually hosting on a Web server. It has been tested with Internet Explorer, Google Chrome, Mozilla Firefox, and Opera Browser. Explorer will require you to click on a button to enable active X controls but the others do not. Note also Explorer will automatically resize and dock the webpage but the others do not implement that feature. 18 | 19 | You will have to edit the source of the html pages to configure your IP address for your device. 20 | 21 | You can edit the codes for any remote supported by IRLib2. Each button is defined by 4 values in the table beginning at line 26. For example the first button in the Adafruit remote example reads: 22 | 23 | [1,0xfd00ff,0, "Vol-",189], 24 | 25 | The first value is the protocol number. The next value is the actual code to be transmitted in hex. The next value is the number of bits which is ignored in the case of NEC protocol 1 but may be important depending on your protocol. The fourth value is the string of text to be displayed on the remote. The file value is a keystroke code which can be used to activate the button in addition to clicking on it with the mouse. In this case code 189 corresponds to the "minus sign" keyboard code. The webpage will display keyboard codes as you press them so if you want to implement a new code just press the key and the webpage will tell you is code. 26 | 27 | Note that the display text can include HTML such as span, linebreaks using br and other formatting as you can see in the examples. 28 | 29 | You also have to edit the URL in the webpage outline 21 so that it matches your device. 30 | 31 | If you press the escape key, the webpage will toggle between the symbols that you defined and an indication of which keyboard characters you have assigned to that particular button. 32 | 33 | We have implemented both a mouseclick and a keyboard press capability into this webpage so that it is easier to be used with voice control software such as Dragon Naturally Speaking. For example when I control my cable box I can speak the words "press G" to call up the on-screen guide and then I can say "Move Right 5" to move the cursor along the guide. This makes this implementation and especially useful piece of assistive technology for the disabled. 34 | 35 | We will be writing an extensive tutorial in the Adafruit learning system about this particular project very soon. 36 | 37 | -------------------------------------------------------------------------------- /examples/servo/servo.ino: -------------------------------------------------------------------------------- 1 | /* servo.ino Example sketch for IRLib2 2 | * Illustrate how to now to control a servo using IR signals. 3 | */ 4 | #include // First include the decode base 5 | #include // Include only the protocol you are using 6 | 7 | IRdecodeSony myDecoder; // Now declare an instance of that decoder. 8 | 9 | #include 10 | /* Note: Servo library uses TIMER1. The default timer for IRLibRecv 11 | * on Arduino Uno is TIMER2 so there is no conflict. However a 12 | * default timer on Arduino Leonardo is TIMER1 so you Have the choice 13 | * of either will have to switch to IRLibRecvPCI or IRLibRecvLoop 14 | * to avoid the conflict. Alternatively you can modify the timer used 15 | * to use TIMER3 or TIMER4 as specified in IRLibHardware.h. Also you 16 | * will need to modify the input being used. 17 | */ 18 | 19 | #include 20 | IRrecv myReceiver(2); //pin number for the receiver 21 | 22 | Servo myServo; // create servo object to control a servo 23 | int16_t pos; // variable to store the servo position 24 | int16_t speed; // Number of degrees to move each time a left/right button is pressed 25 | 26 | void setup() { 27 | myServo.attach(9); // attaches the servo on pin 9 to the servo object 28 | pos = 90; // start at midpoint 90 degrees 29 | speed = 3; // servo moves 3 degrees each time left/right is pushed 30 | myServo.write(pos); // Set initial position 31 | myReceiver.enableIRIn(); // Start the receiver 32 | } 33 | 34 | // You will have to set these values depending on the protocol 35 | // and remote codes that you are using. These are from my Sony DVD/VCR 36 | #define MYPROTOCOL SONY 37 | #define RIGHT_ARROW 0x86bca //Move several clockwise 38 | #define LEFT_ARROW 0x46bca //Move servo counterclockwise 39 | #define SELECT_BUTTON 0xd0bca //Center the servo 40 | #define UP_ARROW 0x42bca //Increased number of degrees servo moves 41 | #define DOWN_ARROW 0xc2bca //Decrease number of degrees servo moves 42 | #define BUTTON_0 0x90bca //Pushing buttons 0-9 moves to fix positions 43 | #define BUTTON_1 0x00bca // each 20 degrees greater 44 | #define BUTTON_2 0x80bca 45 | #define BUTTON_3 0x40bca 46 | #define BUTTON_4 0xc0bca 47 | #define BUTTON_5 0x20bca 48 | #define BUTTON_6 0xa0bca 49 | #define BUTTON_7 0x60bca 50 | #define BUTTON_8 0xe0bca 51 | #define BUTTON_9 0x10bca 52 | 53 | void loop() { 54 | if (myReceiver.getResults()) { 55 | if(myDecoder.decode()) { 56 | switch(myDecoder.value) { 57 | case LEFT_ARROW: pos=min(180,pos+speed); break; 58 | case RIGHT_ARROW: pos=max(0,pos-speed); break; 59 | case SELECT_BUTTON: pos=90; break; 60 | case UP_ARROW: speed=min(10, speed+1); break; 61 | case DOWN_ARROW: speed=max(1, speed-1); break; 62 | case BUTTON_0: pos=0*20; break; 63 | case BUTTON_1: pos=1*20; break; 64 | case BUTTON_2: pos=2*20; break; 65 | case BUTTON_3: pos=3*20; break; 66 | case BUTTON_4: pos=4*20; break; 67 | case BUTTON_5: pos=5*20; break; 68 | case BUTTON_6: pos=6*20; break; 69 | case BUTTON_7: pos=7*20; break; 70 | case BUTTON_8: pos=8*20; break; 71 | case BUTTON_9: pos=9*20; break; 72 | } 73 | myServo.write(pos); // tell servo to go to position in variable 'pos' 74 | } 75 | myReceiver.enableIRIn(); 76 | } 77 | } 78 | 79 | -------------------------------------------------------------------------------- /src/IRLib_HashRaw.h: -------------------------------------------------------------------------------- 1 | /* IRLib_P00_HashRaw.h 2 | * Part of IRLib Library for Arduino receiving, decoding, and sending 3 | * infrared signals. See COPYRIGHT.txt and LICENSE.txt for more information. 4 | */ 5 | /* 6 | * If you have a protocol which is unsupported by this library, you can still receive 7 | * and transmit the data. You can store the raw data values in a buffer and retransmit the 8 | * data exactly as you received it. Of course it takes a lot of memory to store such data 9 | * so it is inefficient but it is better than nothing. 10 | * If all you need to do is detect a unique value for an unsupported protocol and you do 11 | * not need to resend the data, you can use the hash code decoder. It looks at the 12 | * array of raw timing values and create a 32 bit value based on the data. It is 13 | * highly likely to be unique however you cannot reverse engineer the process. 14 | * You cannot re-create the original data stream for 32 bit hash code. 15 | * This module also implements the raw send method. You have to have the original 16 | * timing values. 17 | */ 18 | 19 | #ifndef IRLIB_HASHRAW_H 20 | #define IRLIB_HASHRAW_H 21 | #define IR_SEND_RAW case 0: IRsendRaw::send((uint16_t*)data,data2,khz); break; 22 | #define IR_DECODE_HASH if(IRdecodeHash::decode()) return true; 23 | #ifdef IRLIB_HAVE_COMBO 24 | #define PV_IR_DECODE_HASH ,public virtual IRdecodeHash 25 | #define PV_IR_SEND_RAW ,public virtual IRsendRaw 26 | #else 27 | #define PV_IR_DECODE_HASH public virtual IRdecodeHash 28 | #define PV_IR_SEND_RAW public virtual IRsendRaw 29 | #endif 30 | 31 | #ifdef IRLIBSENDBASE_H 32 | /* The first parameter to the "IRendRaw" method is a pointer to the first element of an 33 | * array of uint16_t values. These values are the raw timing values in microseconds. Note 34 | * it is possible to simply pass "(uint16_t*) &My_Decoder.decodeBuffer[1]" if you have just 35 | * received a code and wish to echo it. You have to point to the index "1" because index "0" 36 | * of that buffer contains the gap between successive frames data and it should be ignored. 37 | * If the frequency to be used in transmission is not specified, it defaults to 38kHz. 38 | */ 39 | class IRsendRaw: public virtual IRsendBase { 40 | public: 41 | void send(uint16_t *buf, uint8_t len, uint8_t khz) { 42 | enableIROut(khz); 43 | for (uint8_t i = 0; i < len; i++) { 44 | if (i & 1) { 45 | space(buf[i]); 46 | } 47 | else { 48 | mark(buf[i]); 49 | } 50 | } 51 | space(0); // Just to be sure 52 | } 53 | }; 54 | #endif //IRLIBSENDBASE_H 55 | 56 | #ifdef IRLIBDECODEBASE_H 57 | /* This Hash decoder is based on IRhashcode Copyright 2010 Ken Shirriff 58 | * For details see http://www.righto.com/2010/01/using-arbitrary-remotes-with-arduino.html 59 | * Use FNV hash algorithm: http://isthe.com/chongo/tech/comp/fnv/#FNV-param 60 | * Converts the raw code values into a 32-bit hash code. 61 | * Hopefully this code is unique for each button. 62 | */ 63 | #define FNV_PRIME_32 16777619 64 | #define FNV_BASIS_32 2166136261 65 | // Compare two tick values, return 0 if v1 is lower, 1 if equal, and 2 if v2 is higher 66 | #define TICKS_COMPARE(v1,v2) ( (v2< v1*0.8)?0:( (v1< v2*0.8)?2:1) ) 67 | class IRdecodeHash: public virtual IRdecodeBase { 68 | public: 69 | bool decode(void) { 70 | value = FNV_BASIS_32; 71 | for (int i = 1; i+2 < recvGlobal.decodeLength; i++) { 72 | value = (value * FNV_PRIME_32) ^ TICKS_COMPARE(recvGlobal.decodeBuffer[i], recvGlobal.decodeBuffer[i+2]); 73 | } 74 | protocolNum = UNKNOWN; 75 | bits= (recvGlobal.decodeLength-3)/2;//Estimated number of bits of unknown protocol 76 | //Note that value is always 32 bit hash code. 77 | return true; 78 | } 79 | }; 80 | #endif //IRLIBDECODEBASE_H 81 | 82 | #define IRLIB_HAVE_COMBO 83 | 84 | #endif //IRLIB_HASHRAW_H 85 | -------------------------------------------------------------------------------- /src/IRLib_P01_NEC.h: -------------------------------------------------------------------------------- 1 | /* IRLib_P01_NEC.h 2 | * Part of IRLib Library for Arduino receiving, decoding, and sending 3 | * infrared signals. See COPYRIGHT.txt and LICENSE.txt for more information. 4 | */ 5 | /* 6 | * NEC is an extremely common protocol. There are two variations NEC1 and NEC2. 7 | * They differ only in the way in which they handle repeat codes. If you hold a button 8 | * using NEC1 it does not repeat the same sequence. Rather it sends a special sequence 9 | * consisting of the usual header mark, a half-size header space, a normal mark. 10 | * When IRLib receives one of these special repeat sequences, it returns the 11 | * value REPEAT_CODE which is defined in IRLibProtocols.h as the value 0xffffffff. If you 12 | * send REPEAT_CODE, the send routine will create a special sequence for you. 13 | * NOTE that the timing for this special did sequence is nearly identical to a ditto 14 | * used by the G.I.Cable protocol and IRLib generally not distinguish between the two. 15 | * The header timing for G.I. Cable ditto is 8820,1960 and for NEC is 9024,2256 16 | * If you are using both protocols and you receive an NEC ditto immediately after 17 | * receiving a G.I.Cable then you should presume it is a G.I.Cable and vice versa. 18 | * Whether it is a normal code or a repeat code the entire frame has a 108ms extent. 19 | * The IRP notation for these protocols are: 20 | * NEC1: {38k,564}<1,-1|1,-3>(16,-8,D:8,S:8,F:8,~F:8,1,^108,(16,-4,1,^108)*) 21 | * NEC2: {38k,564}<1,-1|1,-3>(16,-8,D:8,S:8,F:8,~F:8,1,^108)+ 22 | * Other protocols use the same timing and 32 bits of data but they interpret the data fields 23 | * differently. These include Apple and TiVo. Also Pioneer protocol is identical to NEC2 24 | * however uses 40k rather than 38k modulation. Pioneer sometimes requires a 2 frame 25 | * sequence of different data for a single pushbutton function. The optional 2nd 26 | * parameter to the "send" method allows you to change the frequency from the default 38. 27 | */ 28 | 29 | #ifndef IRLIB_PROTOCOL_01_H 30 | #define IRLIB_PROTOCOL_01_H 31 | #define IR_SEND_PROTOCOL_01 case 1: if(data2==0)data2=38;IRsendNEC::send(data,data2); break; 32 | #define IR_DECODE_PROTOCOL_01 if(IRdecodeNEC::decode()) return true; 33 | #ifdef IRLIB_HAVE_COMBO 34 | #define PV_IR_DECODE_PROTOCOL_01 ,public virtual IRdecodeNEC 35 | #define PV_IR_SEND_PROTOCOL_01 ,public virtual IRsendNEC 36 | #else 37 | #define PV_IR_DECODE_PROTOCOL_01 public virtual IRdecodeNEC 38 | #define PV_IR_SEND_PROTOCOL_01 public virtual IRsendNEC 39 | #endif 40 | #ifdef IRLIBSENDBASE_H 41 | 42 | class IRsendNEC: public virtual IRsendBase { 43 | public: 44 | void send(uint32_t data, uint8_t kHz=38) { 45 | if (data==REPEAT_CODE) { 46 | enableIROut(kHz); 47 | mark (564* 16); space(564*4); mark(564);space(572);delay(97);//actually 97572us 48 | } else { 49 | sendGeneric(data,32, 564*16, 564*8, 564, 564, 564*3, 564, kHz, true,108000); 50 | } 51 | }; 52 | }; 53 | #endif //IRLIBSENDBASE_H 54 | 55 | #ifdef IRLIBDECODEBASE_H 56 | class IRdecodeNEC: public virtual IRdecodeBase { 57 | public: 58 | bool decode(void) { 59 | resetDecoder();//This used to be in the receiver getResults. 60 | IRLIB_ATTEMPT_MESSAGE(F("NEC repeat")); 61 | // Check for repeat 62 | if (recvGlobal.decodeLength == 4 && MATCH(recvGlobal.decodeBuffer[1],564*16) && MATCH(recvGlobal.decodeBuffer[2],564*4) 63 | && MATCH(recvGlobal.decodeBuffer[3],564)) { 64 | bits = 0; 65 | value = REPEAT_CODE; 66 | protocolNum = NEC; 67 | return true; 68 | } 69 | IRLIB_ATTEMPT_MESSAGE(F("NEC")); 70 | if(!decodeGeneric(68, 564*16, 564*8, 564, 564*3, 564)) return false; 71 | protocolNum = NEC; 72 | return true; 73 | } 74 | }; 75 | 76 | #endif //IRLIBDECODEBASE_H 77 | 78 | #define IRLIB_HAVE_COMBO 79 | 80 | #endif //IRLIB_PROTOCOL_01_H 81 | -------------------------------------------------------------------------------- /examples/record/record.ino: -------------------------------------------------------------------------------- 1 | /* record.ino Example sketch for IRLib2 2 | * Illustrate how to record a signal and then play it back. 3 | */ 4 | #include //We need both the coding and 5 | #include // sending base classes 6 | #include //Lowest numbered protocol 1st 7 | #include // Include only protocols you want 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include //We need this for IRsendRaw 13 | #include // After all protocols, include this 14 | // All of the above automatically creates a universal decoder 15 | // class called "IRdecode" and a universal sender class "IRsend" 16 | // containing only the protocols you want. 17 | // Now declare instances of the decoder and the sender. 18 | IRdecode myDecoder; 19 | IRsend mySender; 20 | 21 | // Include a receiver either this or IRLibRecvPCI or IRLibRecvLoop 22 | #include 23 | IRrecv myReceiver(2); //pin number for the receiver 24 | 25 | // Storage for the recorded code 26 | uint8_t codeProtocol; // The type of code 27 | uint32_t codeValue; // The data bits if type is not raw 28 | uint8_t codeBits; // The length of the code in bits 29 | 30 | //These flags keep track of whether we received the first code 31 | //and if we have have received a new different code from a previous one. 32 | bool gotOne, gotNew; 33 | 34 | void setup() { 35 | gotOne=false; gotNew=false; 36 | codeProtocol=UNKNOWN; 37 | codeValue=0; 38 | Serial.begin(9600); 39 | delay(2000);while(!Serial);//delay for Leonardo 40 | Serial.println(F("Send a code from your remote and we will record it.")); 41 | Serial.println(F("Type any character and press enter. We will send the recorded code.")); 42 | Serial.println(F("Type 'r' special repeat sequence.")); 43 | myReceiver.enableIRIn(); // Start the receiver 44 | } 45 | 46 | // Stores the code for later playback 47 | void storeCode(void) { 48 | gotNew=true; gotOne=true; 49 | codeProtocol = myDecoder.protocolNum; 50 | Serial.print(F("Received ")); 51 | Serial.print(Pnames(codeProtocol)); 52 | if (codeProtocol==UNKNOWN) { 53 | Serial.println(F(" saving raw data.")); 54 | myDecoder.dumpResults(); 55 | codeValue = myDecoder.value; 56 | } 57 | else { 58 | if (myDecoder.value == REPEAT_CODE) { 59 | // Don't record a NEC repeat value as that's useless. 60 | Serial.println(F("repeat; ignoring.")); 61 | } else { 62 | codeValue = myDecoder.value; 63 | codeBits = myDecoder.bits; 64 | } 65 | Serial.print(F(" Value:0x")); 66 | Serial.println(codeValue, HEX); 67 | } 68 | } 69 | void sendCode(void) { 70 | if( !gotNew ) {//We've already sent this so handle toggle bits 71 | if (codeProtocol == RC5) { 72 | codeValue ^= 0x0800; 73 | } 74 | else if (codeProtocol == RC6) { 75 | switch(codeBits) { 76 | case 20: codeValue ^= 0x10000; break; 77 | case 24: codeValue ^= 0x100000; break; 78 | case 28: codeValue ^= 0x1000000; break; 79 | case 32: codeValue ^= 0x8000; break; 80 | } 81 | } 82 | } 83 | gotNew=false; 84 | if(codeProtocol== UNKNOWN) { 85 | //The raw time values start in decodeBuffer[1] because 86 | //the [0] entry is the gap between frames. The address 87 | //is passed to the raw send routine. 88 | codeValue=(uint32_t)&(recvGlobal.decodeBuffer[1]); 89 | //This isn't really number of bits. It's the number of entries 90 | //in the buffer. 91 | codeBits=recvGlobal.decodeLength-1; 92 | Serial.println(F("Sent raw")); 93 | } 94 | mySender.send(codeProtocol,codeValue,codeBits); 95 | if(codeProtocol==UNKNOWN) return; 96 | Serial.print(F("Sent ")); 97 | Serial.print(Pnames(codeProtocol)); 98 | Serial.print(F(" Value:0x")); 99 | Serial.println(codeValue, HEX); 100 | } 101 | 102 | void loop() { 103 | if (Serial.available()) { 104 | uint8_t C= Serial.read(); 105 | if(C=='r')codeValue=REPEAT_CODE; 106 | if(gotOne) { 107 | sendCode(); 108 | myReceiver.enableIRIn(); // Re-enable receiver 109 | } 110 | } 111 | else if (myReceiver.getResults()) { 112 | myDecoder.decode(); 113 | storeCode(); 114 | myReceiver.enableIRIn(); // Re-enable receiver 115 | } 116 | } 117 | 118 | -------------------------------------------------------------------------------- /CHANGELOG.txt: -------------------------------------------------------------------------------- 1 | Version 2.0.19 September 20, 2019 2 | Fixed problems with SAMD51 support. Added support for Adafruit Grand Central M4 and Adafruit Feather M4. 3 | Version 2.0.18 September 1, 2019 4 | Fixed problem with protocol 12 SAMD21 & SAMD51 detection. 5 | Added extended USB keyboard scan codes 6 | Version 2.0.17 August 31, 2019 7 | Fixed problem with Feather M0 detection 8 | Version 2.0.16 May 3, 2018 9 | Support SAMD51 M4 processor on the Adafruit Metro M4. See SAMD51.txt for details. 10 | Version 2.0.15 April 4, 2018 11 | Major rewrite of SAMD21 support makes it easier to add more boards. 12 | Updated documentation to include protocol 12 CYKM for keyboard and mouse control. 13 | Updated documentation for SAMD21 boards. General reproof reading of entire documentation. 14 | Version 2.0.14 March 10, 2018 15 | Added support for Arduino MKR 1000. Note IoT_IR example also works with this board. 16 | See SAMD21.txt for details about available output and input pins. Default output pin 6. 17 | Version 2.0.13 March 9, 2018 18 | Added IoT_IR Internet of Things IR remote example for use with Adafruit Feather M0 Wi-Fi 19 | Version 2.0.12 February 9, 2018 20 | Fix problems with certain pins on Trinket M0. Problem with Gemma M0 didn't exist. 21 | It worked all along but my testing failed. 22 | Many thanks to LadyAda for identifying problem. 23 | Version 2.0.11 January 26, 2018 24 | Added support for Adafruit Trinket M0 and Adafruit Gemma M0 however there are known 25 | limitations on certain pin numbers. See SAMD21.txt for details. 26 | Includes previously merged fixed to problem with buffer sizes greater than 255 27 | Version 2.0.10 July 17, 2017 28 | Unsigned manager overflow problem in Samsung36 29 | Version 2.09 July 2, 2017 30 | Updated pin numbers for Circuit Playground Express 31 | Added 8-bit Sony test to examples/pattern.ino 32 | Version 2.08 May 18, 2017 33 | Converted MATCH and ABS_MATCH from macros to methods saving 34 | over 1K of program space on "dump.ino" for example. 35 | Changed the extent of lead out on Sony 8 protocol 36 | Made cmdType and cmdData in CYKM protocol public 37 | Version 2.07 May 5, 2017 38 | Fixed problem with dumpResults related to CYKM. 39 | Miscellaneous changes to facilitate integration into 40 | Adafruit_CircuitPlayground library. 41 | Version 2.06 May 5, 2017 42 | Added protocol 12 CYKM. A protocol designed by me Chris Young 43 | to facilitate transmission and reception of keyboard and 44 | mouse commands. Some documentation in the files. More 45 | detailed documentation will be available in the manual 46 | soon. 47 | Version 2.05 April 30, 2017 48 | Added support for Adafruit Circuit Playground Express with 49 | SAMD 21 processor using its built-in IR receiver and transmitter. 50 | Built-in receiver on GPIO 39. Automatically selects output on 51 | GPIO 29 as default. 52 | Expanded IRLibcombo.h to support unsupported protocol 91 in 53 | addition to 90. Allows you to work with 2 unsupported protocols. 54 | Version 2.04 March 21, 2017 55 | Typo in IRLibSAMD21.h 56 | Version 2.03 March 17, 2017 57 | Removed restrictions on Adafruit Feather 32u4 pin 9 58 | Version 2.02 March 15, 2017 59 | Expanded support for SAMD 21. Now can use any available PWM 60 | pins for output. TCC0 and TCC1 selected automatically based 61 | on pin number. Receiving using 50 microsecond interrupt defaults 62 | to using TC3 however TC4 and TC5 can be used optionally to avoid 63 | conflicts with other libraries. GCLK0 is used for both sending and 64 | receiving however it uses the default 48 MHz clock source without 65 | any divisor so it's safe to use despite the fact it's normally 66 | reserved for internal Arduino infrastructure. 67 | Version 2.01 February 28, 2017 68 | Added preliminary support for SAMD 21 platforms such as 69 | Arduino Zero, Arduino M0 Pro, and Adafruit Feather M0. 70 | Note: Documentation has not yet been updated to support SAMD 21. 71 | See IRLib2/SAMD21.txt for details. 72 | 73 | Version beta 0.11 September 21, 2016 74 | Fixed extra character in IRLibProtocols/IRLibCombo.h 75 | 76 | Additional release beta version 0.1 September 20, 2016 77 | Major rewrite of IRLib1 restructuring everything 78 | Added auto resume feature when using external buffer 79 | But fixes 80 | Included new protocols which were previously supported only 81 | by sample code into the main libraries. 82 | See users manual Appendix A for details of changes and explanation 83 | of reasons that this is no longer backward-compatible with IRLib1. 84 | Added Section 2 Beginners Tutorial and long-awaited Section 3 on 85 | how to add new protocols. 86 | -------------------------------------------------------------------------------- /src/IRLib_P03_RC5.h: -------------------------------------------------------------------------------- 1 | /* IRLib_P03_RC5.h 2 | * Part of IRLib Library for Arduino receiving, decoding, and sending 3 | * infrared signals. See COPYRIGHT.txt and LICENSE.txt for more information. 4 | */ 5 | /* 6 | * The RC5 protocol was invented by Phillips but is used by wide variety of manufacturers. 7 | * It uses a phase encoding of data bits. A space/mark pair indicates "1" 8 | * and a mark/space indicates a "0". It begins with a single "1" bit which is not encoded 9 | * in the data. The second highest order data bit is a toggle bit that indicates individual 10 | * keypresses. You must toggle this bit yourself when sending data. The protocol uses 36 kHz 11 | * modulation however 38 kHz receivers can typically receive the codes okay. 12 | * There are three supported varieties as follows: 13 | * RC5 13 bits, 36 kHz (default, most common variety. 14 | * RC5-F7 14 bits, 36 kHz 15 | * RC5-F7-57 14 bits, 57 kHz 16 | * There's also a 19 bit variety called RC5x that is not supported here but may be a separate 17 | * module eventually. 18 | */ 19 | 20 | #ifndef IRLIB_PROTOCOL_03_H 21 | #define IRLIB_PROTOCOL_03_H 22 | #define IR_SEND_PROTOCOL_03 case 03: if(khz==38)khz=36; IRsendRC5::send(data,data2,khz); break; 23 | #define IR_DECODE_PROTOCOL_03 if(IRdecodeRC5::decode()) return true; 24 | #ifdef IRLIB_HAVE_COMBO 25 | #define PV_IR_DECODE_PROTOCOL_03 ,public virtual IRdecodeRC5 26 | #define PV_IR_SEND_PROTOCOL_03 ,public virtual IRsendRC5 27 | #else 28 | #define PV_IR_DECODE_PROTOCOL_03 public virtual IRdecodeRC5 29 | #define PV_IR_SEND_PROTOCOL_03 public virtual IRsendRC5 30 | #endif 31 | #define RC5_T1 889 32 | 33 | #ifdef IRLIBSENDBASE_H 34 | 35 | class IRsendRC5: public virtual IRsendBase { 36 | public: 37 | void send(uint32_t data, uint8_t nBits=13, uint8_t kHz=36) { 38 | if(nBits==0)nBits=13; 39 | if(kHz==0)kHz=36; 40 | enableIROut(kHz); 41 | data = data << (32 - nBits); 42 | extent=0; 43 | mark(RC5_T1); // First start bit 44 | //Note: Original IRremote library incorrectly assumed second bit was 45 | //always a "1". Bit patterns from this decoder are not backward compatible 46 | //with patterns produced by the original library. Uncomment the following two 47 | //lines to maintain backward compatibility. 48 | //space(RC5_T1); // Second start bit 49 | //mark(RC5_T1); // Second start bit 50 | for (uint8_t i = 0; i < nBits; i++) { 51 | if (data & TOPBIT) { 52 | space(RC5_T1); mark(RC5_T1);// 1 is space, then mark 53 | } else { 54 | mark(RC5_T1); space(RC5_T1);// 0 is mark, then space 55 | } 56 | data <<= 1; 57 | } 58 | space(114000-extent); // Turn off at end 59 | } 60 | }; 61 | #endif //IRLIBSENDBASE_H 62 | 63 | #ifdef IRLIBDECODEBASE_H 64 | 65 | /* Note this decoder is a derived class from the IRdecodeRC base class 66 | * rather than IRdecodeBase. The base class defines the method "getRClevel" 67 | * which is common to both RC5 and RC6 protocols. It facilitates the decoding 68 | * of phase encoded data. 69 | */ 70 | 71 | class IRdecodeRC5: public virtual IRdecodeRC { 72 | public: 73 | virtual bool decode(void) { 74 | IRLIB_ATTEMPT_MESSAGE(F("RC5")); 75 | resetDecoder();//This used to be in the receiver getResults. 76 | if (recvGlobal.decodeLength < 13) return RAW_COUNT_ERROR; 77 | offset = 1; // Skip gap space 78 | data = 0; 79 | used = 0; 80 | // Get start bits 81 | if (getRClevel(&used, RC5_T1) != MARK) return HEADER_MARK_ERROR(RC5_T1); 82 | //Note: Original IRremote library incorrectly assumed second bit was always 83 | // a "1". Bit patterns from this decoder are not backward compatible with 84 | // patterns produced by original library. Uncomment the following two lines 85 | // to maintain backward compatibility. 86 | //if (getRClevel(&used, RC5_T1) != SPACE) return HEADER_SPACE_ERROR(RC5_T1); 87 | //if (getRClevel(&used, RC5_T1) != MARK) return HEADER_MARK_ERROR(RC5_T1); 88 | for (nBits = 0; offset < recvGlobal.decodeLength; nBits++) { 89 | RCLevel levelA = getRClevel(&used, RC5_T1); 90 | RCLevel levelB = getRClevel(&used, RC5_T1); 91 | if (levelA == SPACE && levelB == MARK) { 92 | data = (data << 1) | 1; // 1 bit 93 | } else if (levelA == MARK && levelB == SPACE) { 94 | data <<= 1; // zero bit 95 | } else return DATA_MARK_ERROR(RC5_T1); 96 | } 97 | // Success 98 | bits = nBits; 99 | value = data; 100 | protocolNum = RC5; 101 | return true; 102 | } 103 | }; 104 | #endif //IRLIBDECODEBASE_H 105 | 106 | #define IRLIB_HAVE_COMBO 107 | 108 | #endif //IRLIB_PROTOCOL_03_H 109 | -------------------------------------------------------------------------------- /src/IRLibSAMD51.h: -------------------------------------------------------------------------------- 1 | /* IRLibSAMD51.h 2 | * Part of IRLib Library for Arduino receiving, decoding, and sending 3 | * infrared signals. See COPYRIGHT.txt and LICENSE.txt for more information. 4 | * 5 | * This type of content is normally stored in IRLibHardware.h but we have 6 | * moved at her because the SAMD51 support is significantly different than the 7 | * AVR 8-bit hardware support. Separating it out into a separate file 8 | * will make it easier to include comments and to maintain the code. 9 | */ 10 | #ifndef IRLibSAMD51_h 11 | #define IRLibSAMD51_h 12 | /* 13 | * This section contains user changeable values. You can probably stick with the defaults 14 | * but if there are hardware conflicts with other libraries, you can change these values. 15 | */ 16 | //Choose which timer counter to use for the 50 microsecond interrupt 17 | //Un-comment only one of these. 18 | #define IR_TCn 3 19 | //#define IR_TCn 4 20 | //#define IR_TCn 5 21 | 22 | //Each section below is the default for each particular board we support. 23 | //Edit the #define IR_SEND_PWM_PIN value to one of the available pin numbers 24 | //There are conditional compile statements after that definition which attempt 25 | // to generate an error if you choose an unsupported pin number. 26 | #if defined (ADAFRUIT_METRO_M4_EXPRESS) 27 | //Settings for Adafruit Metro M4 28 | //Default is 9. Available 0-13 29 | #define IR_SEND_PWM_PIN 9 30 | #if (IR_SEND_PWM_PIN > 13) 31 | #error "Unsupported output pin on Adafruit Metro M4 32 | #endif 33 | #elif defined (ADAFRUIT_FEATHER_M4_EXPRESS) 34 | //Settings for Adafruit Feather M4 Express 35 | //Default is 9. Available 0,1,4-6,9-13,16-19(A2-A5), 21(SDA), 22(SCL) 36 | #define IR_SEND_PWM_PIN 9 37 | #if (! ( (IR_SEND_PWM_PIN==0) || (IR_SEND_PWM_PIN==1) || \ 38 | ((IR_SEND_PWM_PIN>=4) && (IR_SEND_PWM_PIN<=6) ) || \ 39 | ((IR_SEND_PWM_PIN>=9) && (IR_SEND_PWM_PIN<=13) ) || \ 40 | ((IR_SEND_PWM_PIN>=16) && (IR_SEND_PWM_PIN<=19) ) || \ 41 | (IR_SEND_PWM_PIN==21) || (IR_SEND_PWM_PIN==22) ) ) 42 | #error "Unsupported output pin Adafruit Feather M4 Express" 43 | #endif 44 | #elif defined (ADAFRUIT_GRAND_CENTRAL_M4) 45 | //Settings for Adafruit Grand Central Metro M4. Default is 9. 46 | //Available 2-10, 12-14, 18-19, 23-28, 30-31, 38-39, 59-61(A13-A15), 69(A2) 47 | #define IR_SEND_PWM_PIN 9 48 | #if (! ( ((IR_SEND_PWM_PIN>=2) && (IR_SEND_PWM_PIN<=10) ) || \ 49 | ((IR_SEND_PWM_PIN>=12) && (IR_SEND_PWM_PIN<=14) ) || \ 50 | (IR_SEND_PWM_PIN==18) || (IR_SEND_PWM_PIN==19) || \ 51 | ((IR_SEND_PWM_PIN>=23) && (IR_SEND_PWM_PIN<=28) ) || \ 52 | (IR_SEND_PWM_PIN==30) || (IR_SEND_PWM_PIN==31) || \ 53 | (IR_SEND_PWM_PIN==38) || (IR_SEND_PWM_PIN==39) || \ 54 | ((IR_SEND_PWM_PIN>=59) && (IR_SEND_PWM_PIN<=61) ) || (IR_SEND_PWM_PIN== 69))) 55 | #error "Unsupported output pin Adafruit Grand Central Metro M4" 56 | #endif 57 | #elif defined (SEEED_WIO_TERMINAL) 58 | #define IR_SEND_PWM_PIN WIO_IR 59 | #else //Other generic SAMD 51 boards 60 | //Default is 9. 61 | #define IR_SEND_PWM_PIN 9 62 | #endif 63 | 64 | /* 65 | * Everything below this point should not be changed. It computes needed defines 66 | * based on the user set values above. 67 | */ 68 | 69 | 70 | // Turns PWM on and off after already set up 71 | #define IR_SEND_PWM_START IRLibStartPWM51(); 72 | #define IR_SEND_MARK_TIME(time) IRLibDelayUSecs(time) 73 | #define IR_SEND_PWM_STOP IRLibStopPWM51(); 74 | #define IR_SEND_CONFIG_KHZ(val) initializeSAMD51PWM(val); 75 | 76 | /* These are the definitions for setting up the 50 microsecond 77 | * timer interrupt for the IRrecv class. 78 | */ 79 | #define GCLK_TC3 26 80 | #define GCLK_TC4 30 81 | #define GCLK_TC5 30 82 | #if (IR_TCn==3) 83 | #define IR_TCx TC3 84 | #define IR_TCx_ID GCLK_TC3 85 | #define IR_RECV_INTR_NAME void TC3_Handler() 86 | #define IR_IRQ TC3_IRQn 87 | #elif (IR_TCn==4) 88 | #define IR_TCx TC4 89 | #define IR_TCx_ID GCLK_TC4 90 | #define IR_RECV_INTR_NAME void TC4_Handler() 91 | #define IR_IRQ TC4_IRQn 92 | #elif (IR_TCn==5) 93 | #define IR_TCx TC5 94 | #define IR_TCx_ID GCLK_TC5 95 | #define IR_RECV_INTR_NAME void TC5_Handler() 96 | #define IR_IRQ TC5_IRQn 97 | #else 98 | #error "Invalid IR_TCn value" 99 | #endif 100 | 101 | #define IR_RECV_ENABLE_INTR ({NVIC_EnableIRQ(IR_IRQ);\ 102 | IR_TCx->COUNT16.INTENSET.reg = TC_INTENSET_OVF;\ 103 | IR_TCx->COUNT16.CTRLA.reg |= TC_CTRLA_ENABLE; \ 104 | while (IR_TCx->COUNT16.SYNCBUSY.reg);}) 105 | #define IR_RECV_DISABLE_INTR IR_TCx->COUNT16.INTENCLR.reg = TC_INTENCLR_OVF; 106 | #define IR_RECV_CONFIG_TICKS() initializeSAMD51timerInterrupt() 107 | 108 | //Clear interrupt 109 | #ifdef IR_CLEAR_INTERRUPT 110 | #undef IR_CLEAR_INTERRUPT 111 | #endif 112 | #define IR_CLEAR_INTERRUPT IR_TCx->COUNT16.INTFLAG.bit.MC0 = 1; 113 | 114 | //prototypes 115 | void initializeSAMD51PWM(uint16_t khz); 116 | void initializeSAMD51timerInterrupt(void); 117 | void IRLibStopPWM51(void); 118 | void IRLibStartPWM51(void); 119 | #endif //IRLibSAMD51_h 120 | -------------------------------------------------------------------------------- /src/IRLib_P10_DirecTV.h: -------------------------------------------------------------------------------- 1 | /* IRLib_P10_DirecTV.h 2 | * Part of IRLib Library for Arduino receiving, decoding, and sending 3 | * infrared signals. See COPYRIGHT.txt and LICENSE.txt for more information. 4 | */ 5 | /* 6 | * This module implements the protocol used by DirecTV. It comes in six different 7 | * varieties. It uses three different frequencies 38, 40, or 57 kHz. It also 8 | * uses two different varieties lead out times either 9000us or 30000us. The 9 | * default is 38 kHz and 30000us. Because the decoder does not usually detect 10 | * frequency and does not record the lead out time, you may have difficulty 11 | * determining which variety your device uses. 12 | * 13 | * According to http://www.hifi-remote.com/johnsfine/DecodeIR.html#DirecTV 14 | * The IRP notation for this protocol is: 15 | * {38k,600,msb}<1,-1|1,-2|2,-1|2,-2>(5,(5,-2,D:4,F:8,C:4,1,-50)+) 16 | * {C=7*(F:2:6)+5*(F:2:4)+3*(F:2:2)+(F:2)} 17 | * Unlike most protocols which use a fixed length mark and a variable length or 18 | * a variable length mark a fixed length space, this protocol varies both the 19 | * mark and the space. The stream is still a series of marks and spaces but the 20 | * length of either of those denotes a one or zero. A length of 1200us=logical 1 21 | * and length 600us=logical 0. So whereas the normal protocol requires both a mark 22 | * and a space to encode a single bit, this protocol encodes one bit in each mark 23 | * and space. It also makes changes to the length of the header mark to devote 24 | * repeat codes. The first header mark should be 6000us but repeat codes should 25 | * only be 3000us. The decode routine sets "address=true" if it is a first 26 | * and "address=false" otherwise. 27 | */ 28 | 29 | #ifndef IRLIB_PROTOCOL_10_H 30 | #define IRLIB_PROTOCOL_10_H 31 | /* When used with IRLibCombo.h the data2 value is a flag for repeat frame. 32 | * You can also optionally change the frequency. To change the lead out 33 | * time after you have created the instance of your sending object such as 34 | * IRsend My_Send; 35 | * you can change the leadout with 36 | * My_Send.longLeadOut= false; 37 | * The default value is true. 38 | */ 39 | #define IR_SEND_PROTOCOL_10 case 10: IRsendDirecTV::send(data,data2,khz); break; 40 | #define IR_DECODE_PROTOCOL_10 if(IRdecodeDirecTV::decode()) return true; 41 | #ifdef IRLIB_HAVE_COMBO 42 | #define PV_IR_DECODE_PROTOCOL_10 ,public virtual IRdecodeDirecTV 43 | #define PV_IR_SEND_PROTOCOL_10 ,public virtual IRsendDirecTV 44 | #else 45 | #define PV_IR_DECODE_PROTOCOL_10 public virtual IRdecodeDirecTV 46 | #define PV_IR_SEND_PROTOCOL_10 public virtual IRsendDirecTV 47 | #endif 48 | 49 | #ifdef IRLIBSENDBASE_H 50 | class IRsendDirecTV: public virtual IRsendBase { 51 | public: 52 | IRsendDirecTV(void):longLeadOut(true){}; 53 | void send(uint32_t data, bool first=true, uint8_t khz=38) { 54 | enableIROut(khz); 55 | if(first) mark(6000); else mark(3000); 56 | space(1200);//Send header 57 | for (uint8_t i = 0; i < 8; i++) { 58 | if (data & 0x8000) mark(1200); else mark(600); 59 | data <<= 1; 60 | if (data & 0x8000) space(1200); else space(600); 61 | data <<= 1; 62 | }; 63 | mark(600); 64 | space(longLeadOut?50*600:15*600); 65 | }; 66 | bool longLeadOut; 67 | }; 68 | #endif //IRLIBSENDBASE_H 69 | 70 | #ifdef IRLIBDECODEBASE_H 71 | class IRdecodeDirecTV: public virtual IRdecodeBase { 72 | public: 73 | bool decode(void) { 74 | resetDecoder();//This used to be in the receiver getResults. 75 | IRLIB_ATTEMPT_MESSAGE(F("DirecTV")); 76 | if (recvGlobal.decodeLength != 20) return RAW_COUNT_ERROR; 77 | //We use the "address" value as a repeat flag 78 | if(!ignoreHeader) { 79 | if (MATCH(recvGlobal.decodeBuffer[1],3000)) { 80 | address=false; 81 | } else { 82 | if (!MATCH(recvGlobal.decodeBuffer[1],6000)) { 83 | return HEADER_MARK_ERROR(6000); 84 | } else { 85 | address=true; 86 | } 87 | } 88 | } 89 | if (!MATCH(recvGlobal.decodeBuffer[2],1200)) return HEADER_SPACE_ERROR(1200); 90 | uint32_t data=0; offset=3; 91 | while (offset < 18) { 92 | if (MATCH(recvGlobal.decodeBuffer[offset],1200)) { 93 | data = (data << 1) | 1; 94 | } else { 95 | if (MATCH(recvGlobal.decodeBuffer[offset],600)) { 96 | data <<= 1; 97 | } else { 98 | return DATA_MARK_ERROR(1200); 99 | } 100 | } 101 | offset++; 102 | if (MATCH(recvGlobal.decodeBuffer[offset],1200)) { 103 | data = (data << 1) | 1; 104 | } else { 105 | if (MATCH (recvGlobal.decodeBuffer[offset],600)) { 106 | data <<= 1; 107 | } else { 108 | return DATA_SPACE_ERROR(1200); 109 | } 110 | } 111 | offset++; 112 | } 113 | bits = 16; 114 | value = data; 115 | protocolNum=DIRECTV; 116 | return true; 117 | } 118 | }; 119 | #endif //IRLIBDECODEBASE_H 120 | 121 | #define IRLIB_HAVE_COMBO 122 | 123 | #endif //IRLIB_PROTOCOL_10_H 124 | -------------------------------------------------------------------------------- /src/IRLib_P08_Samsung36.h: -------------------------------------------------------------------------------- 1 | /* IRLib_P08_Samsung36.h 2 | * Part of IRLib Library for Arduino receiving, decoding, and sending 3 | * infrared signals. See COPYRIGHT.txt and LICENSE.txt for more information. 4 | */ 5 | 6 | /* 7 | * This 36 bit protocol is used by some Samsung devices such as Blu-ray players. 8 | * It consists of a 16 bit address and 20 bits of data with strange timing in between. 9 | */ 10 | /* The IRP notation for this protocol is: 11 | * {38k,500}<1,-1|1,-3>(9,-9,D:8,S:8,1,-9,E:4,F:8,-68u,~F:8,1,-118)+ 12 | * This means it uses 38k frequency. Base timing is multiples of 500. 13 | * A "0" is mark(500) space(500). A "1" is mark (500) space(500*3) 14 | * The header is mark(500*9) space(500*9). 15 | * The header is followed by 16 bit address (8 device, 8 sub device) 16 | * This is followed by a mark(500) space(500*9). 17 | * This is followed by 12 more bits (4+8) 18 | * This is followed by 68us of space. Actually this means that the space 19 | * of the last bit of that segment is simply 68us longer than normal. 20 | * This is followed by 8 more bits and a final stop bit. 21 | */ 22 | #ifndef IRLIB_PROTOCOL_08_H 23 | #define IRLIB_PROTOCOL_08_H 24 | #define IR_SEND_PROTOCOL_08 case 8: IRsendSamsung36::send(data,data2); break; 25 | #define IR_DECODE_PROTOCOL_08 if(IRdecodeSamsung36::decode()) return true; 26 | #ifdef IRLIB_HAVE_COMBO 27 | #define PV_IR_DECODE_PROTOCOL_08 ,public virtual IRdecodeSamsung36 28 | #define PV_IR_SEND_PROTOCOL_08 ,public virtual IRsendSamsung36 29 | #else 30 | #define PV_IR_DECODE_PROTOCOL_08 public virtual IRdecodeSamsung36 31 | #define PV_IR_SEND_PROTOCOL_08 public virtual IRsendSamsung36 32 | #endif 33 | 34 | #ifdef IRLIBSENDBASE_H 35 | class IRsendSamsung36: public virtual IRsendBase { 36 | public: 37 | void send(uint32_t data, uint32_t address) { 38 | data <<= 32-20; 39 | address <<= 32-16; 40 | enableIROut(38); 41 | mark(500*9); space(500*9); //Send header 42 | putBits (address, 16); //Send address 16 bits 43 | mark (500); space (500*9); //Send break 44 | putBits (data, 12); //Send 12 bits 45 | space(68); //Send tiny break 46 | data <<= 12; 47 | putBits (data, 8);mark(500); //Final eight bits and one stop bit 48 | space(118U*500U); //Lead out is 118 times the base time 500 49 | }; 50 | private: 51 | /* Because not all of the data bits are contiguous in the stream, 52 | * we created this little routine to be called multiple times to send a 53 | * segment of the data. 54 | */ 55 | void putBits (uint32_t data, uint8_t nbits) { 56 | for (uint8_t i = 0; i < nbits; i++) { 57 | if (data & TOPBIT) { 58 | mark(500); space(500*3); 59 | } else { 60 | mark(500); space(500); 61 | }; 62 | data <<= 1; 63 | } 64 | } 65 | }; 66 | 67 | #endif //IRLIBSENDBASE_H 68 | 69 | #ifdef IRLIBDECODEBASE_H 70 | class IRdecodeSamsung36: public virtual IRdecodeBase { 71 | public: 72 | bool decode(void) { 73 | IRLIB_ATTEMPT_MESSAGE(F("Samsung36")); 74 | if (recvGlobal.decodeLength != 78) return RAW_COUNT_ERROR; 75 | if (!MATCH(recvGlobal.decodeBuffer[1],500*9)) return HEADER_MARK_ERROR(500*9); 76 | if (!MATCH(recvGlobal.decodeBuffer[2],500*9)) return HEADER_SPACE_ERROR(500*9); 77 | offset=3; data=0; 78 | //Get first 16 bits 79 | if(!getBits(16*2+2))return false; 80 | //Skip middle header 81 | if (!MATCH(recvGlobal.decodeBuffer[offset],500)) return DATA_MARK_ERROR(500); 82 | offset++; 83 | if (!MATCH(recvGlobal.decodeBuffer[offset],500*9)) return DATA_SPACE_ERROR(4400); 84 | //save first 16 bits in "address" and reset data 85 | offset++; address=data; data=0; 86 | //12 bits into this second segment, the space is extended by 68us. 87 | // so we adjust the value to its normal length without the extra 68us. 88 | recvGlobal.decodeBuffer[62]-=68; 89 | //Now get the remaining 20 bits 90 | if(!getBits(77))return false; 91 | bits =36; //set bit length 92 | value = data; //put remaining 20 bits in value 93 | protocolNum= SAMSUNG36; 94 | return true; 95 | }; 96 | private: 97 | /* Because not all of the data bits are contiguous in the stream 98 | * we created this little routine to be called multiple times 99 | * to decode a segment of the data. Parameter "last_offset" is when we 100 | * stop decoding the segment. 101 | */ 102 | bool getBits(uint8_t last_offset) { 103 | while (offset < last_offset) { 104 | if (!MATCH(recvGlobal.decodeBuffer[offset],500)) return DATA_MARK_ERROR(500); 105 | offset++; 106 | if (MATCH(recvGlobal.decodeBuffer[offset],500*3)) 107 | data = (data << 1) | 1; 108 | else if (MATCH(recvGlobal.decodeBuffer[offset],500)) 109 | data <<= 1; 110 | else return DATA_SPACE_ERROR(500*3); 111 | offset++; 112 | }; 113 | return true; 114 | }; 115 | uint8_t offset; 116 | uint32_t data; 117 | }; 118 | #endif //IRLIBDECODEBASE_H 119 | 120 | #define IRLIB_HAVE_COMBO 121 | 122 | #endif //IRLIB_PROTOCOL_08_H 123 | -------------------------------------------------------------------------------- /src/IRLibSendBase.cpp: -------------------------------------------------------------------------------- 1 | /* IRLibSendBase.cpp 2 | * Part of IRLib Library for Arduino receiving, decoding, and sending 3 | * infrared signals. See COPYRIGHT.txt and LICENSE.txt for more information. 4 | */ 5 | /* 6 | * This module contains the base classes for sending. You will not create instances 7 | * of these classes, rather you will use them as base classes in creating derived 8 | * protocol specific decoders. Each protocol specific send class begins 9 | * by calling enableIROut(uint8_t kHz) to set the carrier frequency. 10 | * It then calls mark(int usec) and space(inc usec) to transmit marks and 11 | * spaces of varying length of microseconds in the manner which the protocol defines. 12 | */ 13 | #include "IRLibSendBase.h" 14 | #include "IRLibHardware.h" 15 | 16 | /* 17 | * Most of the protocols have a header consisting of a mark/space of a particular length followed by 18 | * a series of variable length mark/space signals. Depending on the protocol they very the lengths of the 19 | * mark or the space to indicate a data bit of "0" or "1". Most also end with a stop bit of "1". 20 | * The basic structure of the sending and decoding these protocols led to lots of redundant code. 21 | * Therefore I have implemented generic sending and decoding routines. You just need to pass a bunch of customized 22 | * parameters and it does the work. This reduces compiled code size with only minor speed degradation. 23 | * You may be able to implement new protocols by simply passing the proper values to these generic routines. 24 | * The decoding routines do not encode stop bits. So you have to tell this routine whether or not to send one. 25 | * Some protocols have a fixed amount of space between frames while others require that the entire frame 26 | * be a particularly length despite the fact that the data transmission time may be veritable. Pass this 27 | * frame length of time the parameter maxExtent. It's default value is zero. 28 | */ 29 | void IRsendBase::sendGeneric(uint32_t data, uint8_t numBits, uint16_t headMark, uint16_t headSpace, 30 | uint16_t markOne, uint16_t markZero, uint16_t spaceOne, uint16_t spaceZero, 31 | uint8_t kHz, bool useStop, uint32_t maxExtent) { 32 | extent=0; 33 | data = data << (32 - numBits); 34 | enableIROut(kHz); 35 | //Some protocols do not send a header when sending repeat codes. So we pass a zero value to indicate skipping this. 36 | if(headMark) mark(headMark); 37 | if(headSpace) space(headSpace); 38 | for (uint8_t i = 0; i // First include the send base 9 | //Now include only the protocols you wish to actually use. 10 | //The was numbered protocol should be first but remainder can be any order. 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include // After all protocols, include this 24 | // All of the above automatically creates a universal sending 25 | // class called "IRsend" containing only the protocols you want. 26 | // Now declare an instance of that sender. 27 | 28 | IRsend mySender; 29 | 30 | void setup() { 31 | Serial.begin(9600); 32 | delay(2000); while (!Serial); //delay for Leonardo 33 | Serial.println(F("Type the protocol number:1-12 Or '-1' for all")); 34 | } 35 | void sendOne(uint8_t protocol, uint32_t data, uint16_t data2=0,uint8_t khz=0) { 36 | Serial.print(F("Protocol #")); Serial.print(protocol,DEC); 37 | Serial.print(F("\t")); Serial.print(Pnames(protocol)); 38 | Serial.print(F("\tdata=0x")); Serial.print(data,HEX); 39 | if(data2) { 40 | Serial.print(F("\tdata2=0x")); Serial.print(data2,HEX); 41 | Serial.print(F(" ")); Serial.print(data2,DEC); 42 | Serial.print(F(" dec")); 43 | } 44 | if(khz) { 45 | mySender.send(protocol,data,data2,khz); 46 | Serial.print(F(" khz=")); Serial.println(khz,DEC); 47 | } else { 48 | mySender.send(protocol,data,data2); 49 | Serial.println(); 50 | } 51 | delay(2000); 52 | } 53 | #define PATTERN1 0x12345678 54 | #define ALL1S 0xFFFFFFFF 55 | 56 | void doTest (uint8_t P) { 57 | switch (P) { 58 | case 1: sendOne(1,PATTERN1); //NEC Regular data 59 | sendOne(1,REPEAT_CODE); //NEC Special ditto repeat code 60 | sendOne(1,PATTERN1,40); //Pioneer is NEC with 40 kHz modulation 61 | break; 62 | case 2: sendOne(2,PATTERN1,8); //Sony 8 bits 63 | sendOne(2,PATTERN1,12); //Sony 12 bits 64 | sendOne(2,PATTERN1,15); //Sony 15 bits 65 | sendOne(2,PATTERN1,20); //Sony 20 bits 66 | break; //Note: Sony always sends three copies of signal 67 | case 3: sendOne(3,ALL1S,13); //RC5 68 | sendOne(3,ALL1S,14); //RC5-F7 69 | sendOne(3,ALL1S,14,57); //RC5-F7-57 70 | break; 71 | case 4: sendOne(4,0x0ffff,20); //RC6-0-16 Original Phillips RC6 72 | sendOne(4,0xcfffff,24); //RC6-6-20 Used by some Sky and Sky+ remotes 73 | sendOne(4,0xcfffff,28); //RC6-6-24 a.k.a. "Replay" protocol 74 | sendOne(4,ALL1S,32); //RC6-6-32 a.k.a. "MCE" protocol 75 | break; 76 | case 5: sendOne(5,ALL1S); //Panasonic_Old 22 bits used by some SA and Cisco cable boxes 77 | break; 78 | case 6: //JVC use "true" for first frame, "false" for repeats 79 | //When "true" it automatically sends one repeat. Use "false" 80 | //for additional repeats. The 2 lines below will actually send 81 | //a total of 3 frames... A first and 2 repeats. 82 | sendOne(6,PATTERN1,true); 83 | sendOne(6,PATTERN1,false); 84 | break; 85 | case 7: sendOne(7,PATTERN1); //NECx used by many Samsung TVs 86 | sendOne(7,REPEAT_CODE); //Some varieties use ditto 87 | break; 88 | case 8: sendOne(8,0x12345,0x1234);//Samsung36 16 bit address +20 data 89 | break; 90 | case 9: sendOne(9,PATTERN1); //G.I.Cable 16 bits with ditto repeat 91 | sendOne(9,REPEAT_CODE); //This will report NEC if both protocols used 92 | break; 93 | case 10: sendOne(10,PATTERN1); //DirecTV default no repeat, 38 khz 94 | sendOne(10,PATTERN1,true);//3rd parameter is repeat flag 95 | sendOne(10,PATTERN1,false,40);//4th is khz, 38, 40, 57 are legal 96 | break; 97 | case 11: sendOne(11,ALL1S,12); //RCMM Phillips protocol used by U-Verse 98 | sendOne(11,ALL1S,24); //also 24 or 32 bit possible 99 | sendOne(11,ALL1S,32); 100 | break; 101 | case 12: sendOne(12,CYKM_MOUSE_MOVE+CYKM_DIR_RIGHT);//Move mouse right 102 | sendOne(12,CYKM_MOUSE_MOVE+CYKM_DIR_UP); //Move mouse up 103 | sendOne(12,CYKM_MOUSE_MOVE+CYKM_DIR_LEFT); //Move mouse left 104 | sendOne(12,CYKM_MOUSE_MOVE+CYKM_DIR_DOWN); //Move mouse down 105 | break; 106 | }; 107 | 108 | } 109 | void loop() { 110 | if (Serial.available () > 0) { 111 | int16_t i = Serial.parseInt(); 112 | if(i==-1) { 113 | for(i=1;i<=12;i++) { 114 | doTest(i); 115 | }; 116 | } else { 117 | doTest(i); 118 | } 119 | } 120 | } 121 | -------------------------------------------------------------------------------- /examples/serialRemote/serialRemote.py: -------------------------------------------------------------------------------- 1 | # IRLib demo script 2 | # version 1.0 by Chris Young http://tech.cyborg5.com/irlib/ 3 | # Displays a "Virtual remote" on your screen. Clicking on the 4 | # buttons sends serial datato the Arduino which in turn 5 | # since IR signals to a cable box in TV. 6 | # This requires Python 3 and pyserial and pygame modules 7 | 8 | # Import all of the necessary pieces of code 9 | import serial, sys, pygame, pygame.mixer 10 | from pygame.locals import * 11 | 12 | # You will have to edit this to the proper port and speed 13 | ser = serial.Serial('COM11', 9600) 14 | 15 | pygame.init() 16 | # Established screen size, size of buttons and position 17 | size = width, height = 400, 768 18 | button_size=54; button_offset=71 19 | button_x1=65;button_y1=39 20 | max_rows=10; max_columns=4 21 | 22 | # Specify a font. I'm using Arial narrow bold from my Windows 23 | # font folder. However the default font shown below also works. 24 | myfont =pygame.font.Font ("c:/windows/fonts/ARIALNB.TTF",30) 25 | #myfont=pygame.font.Font(None,36) 26 | 27 | # These are the text labels that will appear on each button 28 | label_text=("TVp", "CBp", "P^", "Pv",\ 29 | "<<", ">", ">>", "->",\ 30 | "Rec", "=", "s", "<-",\ 31 | "Gd", "^", "Fav", "Inf",\ 32 | 33 | "<", "sel", ">", "Lis",\ 34 | "ret", "v", "Prv", "Mnu",\ 35 | "1", "2", "3", "Ch+",\ 36 | 37 | "4", "5", "6", "Ch-",\ 38 | "7", "8", "9", "Vol+",\ 39 | "Pip", "0", "Mut", "Vol-",\ 40 | ) 41 | # Each of these 40 strings of text correspond to the 42 | # protocol in code which will be sent over the USB serial 43 | # to the Arduino. The first number is the protocol number. 44 | # See the defined protocols in "IRLib.h"for the 45 | # enum IRTYPES at about line 50. This example uses 46 | # protocol 3 which is "RC5" used by my Magnavox TV 47 | # and protocol 5 "PANASONIC_OLD" used by my Scientific 48 | # Atlantic SA 8300 DVR. The protocol number is followed by 49 | # the hex code to be transmitted. That is followed by the 50 | # number of bits. Note that the PANASONIC_OLD protocol 51 | # does not need the number of bits specified so they are omitted. 52 | IR_Codes= ("3,180c,13","5,37c107","5,36d924","5,37d904",\ 53 | "5,37291a","5,37990c","5,36293a","5,36b129",\ 54 | "5,375914","5,374117","5,365934","5,37c906",\ 55 | "5,36c127","5,36812f","5,37f101","5,36213b",\ 56 | 57 | "5,37810f","5,366133","5,364137","5,36c926",\ 58 | "5,366932","5,37a10b","5,36e123","5,373918",\ 59 | "5,36113d","5,37111d","5,36912d","5,377111",\ 60 | 61 | "5,37910d","5,365135","5,375115","5,36f121",\ 62 | "5,36d125","5,37d105","5,363139","3,1810,13",\ 63 | "5,37b908","5,373119","3,180d,13","3,1811,13",\ 64 | ) 65 | # This function gets called to shut everything down 66 | def Finished(): 67 | pygame.quit() 68 | sys.exit() 69 | 70 | # Gets the button index based on mouse position. Returned 71 | # value is from 0 to 39 (number of buttons-1) 72 | # Returns -1 if you are not over a button. 73 | def ComputeButton(): 74 | mx,my=pygame.mouse.get_pos() 75 | mx=mx-button_x1 76 | my=my-button_y1 77 | bx=mx//button_offset; by=my//button_offset 78 | if bx<0 or bx>=max_columns:return -1 79 | if by<0 or by> max_rows:return -1 80 | if (mx%button_offset)>button_size:return -1 81 | if (my%button_offset)>button_size:return -1 82 | return bx+by*max_columns 83 | 84 | # Blits the button text from button number "i" 85 | # onto the specified layer using the specified color. 86 | def Show_Text(i,Layer,color=(0,0,0)): 87 | t=label_text[i] 88 | label = myfont.render (t,1,color) 89 | labelpos= label.get_rect() 90 | labelpos.centerx=button_x1+button_size/2+i%max_columns*button_offset 91 | labelpos.centery=button_y1+button_size/2+i//max_columns*button_offset 92 | Layer.blit(label,labelpos) 93 | 94 | # Create the screen and load the background image. 95 | screen = pygame.display.set_mode(size) 96 | bg = pygame.image.load("remotebg.png") 97 | 98 | # Blit black text labels onto the background image 99 | for i in range (max_rows*max_columns): 100 | Show_Text(i, bg) 101 | # Copy the background to the display 102 | screen.blit(bg,(0,0)) 103 | pygame.display.flip() 104 | 105 | # Load the clicking sound 106 | Click=pygame.mixer.Sound("click.wav") 107 | 108 | # Used to detect when the mouse hovers over a different button 109 | previous=-1 110 | 111 | while 1: 112 | for event in pygame.event.get(): 113 | if event.type == pygame.QUIT: 114 | Finished() 115 | elif event.type == KEYDOWN and event.key == K_ESCAPE: 116 | Finished () 117 | elif event.type == MOUSEBUTTONDOWN: 118 | i=ComputeButton() #which button did we click 119 | if i>=0: 120 | Click.play() #play the sound 121 | ser.write(IR_Codes[i].encode()) #send the codes 122 | elif event.type==MOUSEMOTION: 123 | i=ComputeButton() #which button are we over 124 | if i!=previous: #difference in the last one? 125 | if i>=0: #turn it red 126 | Show_Text(i,screen,(255,0,0)) 127 | else: #or put it back the way it was 128 | screen.blit(bg,(0,0)) 129 | previous=i 130 | pygame.display.flip() #update the display 131 | # That's all folks 132 | 133 | 134 | 135 | -------------------------------------------------------------------------------- /src/IRLibDecodeBase.h: -------------------------------------------------------------------------------- 1 | /* IRLibDecodeBase.h 2 | * Part of IRLib Library for Arduino receiving, decoding, and sending 3 | * infrared signals. See COPYRIGHT.txt and LICENSE.txt for more information. 4 | */ 5 | /* 6 | * This module contains the base classes for decoding. You will not create instances 7 | * of these classes, rather you will use them as base classes in creating derived 8 | * protocol specific decoders. 9 | */ 10 | #ifndef IRLIBDECODEBASE_H 11 | #define IRLIBDECODEBASE_H 12 | #include "IRLibGlobals.h" 13 | #include "IRLibProtocols.h" 14 | 15 | // Base class for decoding raw results 16 | class IRdecodeBase { 17 | public: 18 | IRdecodeBase(void); 19 | uint8_t protocolNum; // NEC, SONY, RC5, UNKNOWN etc. 20 | uint32_t value; // Decoded value 21 | uint16_t address; // Additional data for protocols using more than 32 bits 22 | uint8_t bits; // Number of bits in decoded value 23 | bool ignoreHeader; // Relaxed header detection allows AGC to settle 24 | bool decodeGeneric(uint8_t expectedLength, uint16_t headMark, uint16_t headSpace, 25 | uint16_t markData, uint16_t spaceOne, uint16_t spaceZero); 26 | void dumpResults(bool verbose=true);//full dump of all timing values 27 | bool MATCH(int16_t val,int16_t expected); 28 | bool ABS_MATCH(int16_t val,int16_t expected,int16_t tolerance); 29 | protected: 30 | virtual void resetDecoder(void); // Initializes the decoder 31 | bufIndex_t offset; // Index into decodeBuffer used various places 32 | }; 33 | 34 | // Base class used by RC5 and RC6 protocols 35 | class IRdecodeRC: public virtual IRdecodeBase { 36 | public: 37 | enum RCLevel {MARK, SPACE, ERROR};//used by decoders for RC5/RC6 38 | RCLevel getRClevel(uint8_t *used, const uint16_t t1); 39 | protected: 40 | uint8_t nBits; 41 | uint8_t used; 42 | uint32_t data; 43 | }; 44 | 45 | /* The remainder of this file a variety of default values and macros which are 46 | * used internally. They used to be in a separate file IRLibMatch.h but it's easier 47 | * to include them here. You need not worry about them unless you are creating 48 | * your own decoding routines. See the documentation how to implement new protocols 49 | * for a more detailed explanation of these definitions and routines. 50 | */ 51 | 52 | /* 53 | * Originally all timing comparisons for decoding were based on a percent of the 54 | * target value. However when target values are relatively large, the percent tolerance 55 | * is too much. In some instances an absolute tolerance is needed. In order to maintain 56 | * backward compatibility, the default will be to continue to use percent. If you wish 57 | * to default to an absolute tolerance, you should comment out the line below. 58 | */ 59 | #define IRLIB_USE_PERCENT 60 | 61 | /* 62 | * These are some miscellaneous definitions that are needed by the decoding routines. 63 | * You need not include this file unless you are creating custom decode routines 64 | * which will require these macros and definitions. Even if you include it, you probably 65 | * don't need to be intimately familiar with the internal details. 66 | */ 67 | 68 | #define TOPBIT 0x80000000 69 | #define PERCENT_TOLERANCE 25 // percent tolerance in measurements 70 | #define DEFAULT_ABS_TOLERANCE 75 //absolute tolerance in microseconds 71 | /* If you insert #define IRLIB_TRACE in your sketch before including this file, 72 | * various debugging routines will be enabled in the dumpResults() method. 73 | */ 74 | #ifdef IRLIB_TRACE 75 | void IRLIB_ATTEMPT_MESSAGE(const __FlashStringHelper * s) {Serial.print(F("Attempting ")); Serial.print(s); Serial.println(F(" decode:"));}; 76 | void IRLIB_TRACE_MESSAGE(const __FlashStringHelper * s) {Serial.print(F("Executing ")); Serial.println(s);}; 77 | uint8_t IRLIB_REJECTION_MESSAGE(const __FlashStringHelper * s) { Serial.print(F(" Protocol failed because ")); Serial.print(s); Serial.println(F(" wrong.")); return false;}; 78 | uint8_t IRLIB_DATA_ERROR_MESSAGE(const __FlashStringHelper * s, uint8_t index, uint16_t value, uint16_t expected) { 79 | IRLIB_REJECTION_MESSAGE(s); Serial.print(F("Error occurred with decodeBuffer[")); Serial.print(index,DEC); Serial.print(F("]=")); Serial.print(value,DEC); 80 | Serial.print(F(" expected:")); Serial.println(expected,DEC); return false; 81 | }; 82 | #define RAW_COUNT_ERROR IRLIB_REJECTION_MESSAGE(F("number of raw samples")); 83 | #define HEADER_MARK_ERROR(expected) IRLIB_DATA_ERROR_MESSAGE(F("header mark"),1,recvGlobal.decodeBuffer[1],expected); 84 | #define HEADER_SPACE_ERROR(expected) IRLIB_DATA_ERROR_MESSAGE(F("header space"),2,recvGlobal.decodeBuffer[2],expected); 85 | #define DATA_MARK_ERROR(expected) IRLIB_DATA_ERROR_MESSAGE(F("data mark"),offset,recvGlobal.decodeBuffer[offset],expected); 86 | #define DATA_SPACE_ERROR(expected) IRLIB_DATA_ERROR_MESSAGE(F("data space"),offset,recvGlobal.decodeBuffer[offset],expected); 87 | #define TRAILER_BIT_ERROR(expected) IRLIB_DATA_ERROR_MESSAGE(F("RC6 trailer bit length"),offset,recvGlobal.decodeBuffer[offset],expected); 88 | #define BIT_COUNT_ERROR IRLIB_REJECTION_MESSAGE(F("invalid number of bits")); 89 | #else 90 | #define IRLIB_ATTEMPT_MESSAGE(s) 91 | #define IRLIB_TRACE_MESSAGE(s) 92 | #define IRLIB_REJECTION_MESSAGE(s) false 93 | #define IRLIB_DATA_ERROR_MESSAGE(s,i,v,e) false 94 | #define RAW_COUNT_ERROR false 95 | #define HEADER_MARK_ERROR(expected) false 96 | #define HEADER_SPACE_ERROR(expected) false 97 | #define DATA_MARK_ERROR(expected) false 98 | #define DATA_SPACE_ERROR(expected) false 99 | #define TRAILER_BIT_ERROR(expected) false 100 | #define BIT_COUNT_ERROR false 101 | #endif 102 | 103 | #endif //IRLIBDECODEBASE_H 104 | -------------------------------------------------------------------------------- /src/IRLib_P11_RCMM.h: -------------------------------------------------------------------------------- 1 | /* IRLib_P11_RCMM.h 2 | * Part of IRLib Library for Arduino receiving, decoding, and sending 3 | * infrared signals. See COPYRIGHT.txt and LICENSE.txt for more information. 4 | */ 5 | /* This module implements the Phillips RC-MM also known as Nokia Protocol. Is used by 6 | * AT&T U-Verse cable boxes. There are three different varieties that are 12, 24, or 32 bits. 7 | * According to http://www.hifi-remote.com/johnsfine/DecodeIR.html#Nokia 8 | * The IRP notation for these protocols are: 9 | * Nokia 12 bit: {36k,msb}<164,-276|164,-445|164,-614|164,-783>(412,-276,D:4,F:8,164,-???)+ 10 | * Nokia 24-bit: {36k,msb}<164,-276|164,-445|164,-614|164,-783>(412,-276,D:8,S:8,F:8,164,-???)+ 11 | * Nokia 32 bit: {36k,msb}<164,-276|164,-445|164,-614|164,-783>(412,-276,D:8,S:8,T:1X:7,F:8,164,^100m)+ 12 | * Slightly different timing values are documented at 13 | * http://www.sbprojects.com/knowledge/ir/rcmm.php 14 | * We will use the timing from the latter reference. 15 | * Unlike most protocols which defined sequences for a logical "0" and "1", this protocol 16 | * encodes 2 bits per pulse. Therefore it encodes a logical "2" and "3" as well. 17 | * The length of the mark is constant but the length of the space denotes the bit values. 18 | * Note the 32-bit version uses a toggle bit of 0x8000 and as usual it is up to the end-user 19 | * to implement it outside the library routines. 20 | */ 21 | #define RCMM_HEAD_MARK 417 22 | #define RCMM_DATA_MARK 167 23 | #define RCMM_ZERO 278 24 | #define RCMM_ONE 444 25 | #define RCMM_TWO 611 26 | #define RCMM_THREE 778 27 | 28 | #ifndef IRLIB_PROTOCOL_11_H 29 | #define IRLIB_PROTOCOL_11_H 30 | #define IR_SEND_PROTOCOL_11 case 11: IRsendRCMM::send(data,data2); break;//data2 is the number of bits 31 | #define IR_DECODE_PROTOCOL_11 if(IRdecodeRCMM::decode()) return true; 32 | #ifdef IRLIB_HAVE_COMBO 33 | #define PV_IR_DECODE_PROTOCOL_11 ,public virtual IRdecodeRCMM 34 | #define PV_IR_SEND_PROTOCOL_11 ,public virtual IRsendRCMM 35 | #else 36 | #define PV_IR_DECODE_PROTOCOL_11 public virtual IRdecodeRCMM 37 | #define PV_IR_SEND_PROTOCOL_11 public virtual IRsendRCMM 38 | #endif 39 | 40 | #ifdef IRLIBSENDBASE_H 41 | class IRsendRCMM: public virtual IRsendBase { 42 | public: 43 | void send(uint32_t data, uint8_t nBits= 12) { 44 | if (nBits==0) nBits=12; 45 | extent=0; 46 | data <<= (32 - nBits); 47 | nBits=nBits/2; 48 | enableIROut(36); 49 | mark(RCMM_HEAD_MARK); space(RCMM_ZERO);//Send header 50 | for (uint8_t i = 0; i < nBits; i++) { 51 | mark(RCMM_DATA_MARK); 52 | switch (data & 0xC0000000UL) {//use the leftmost two bits 53 | case 0x00000000UL: space(RCMM_ZERO); break; 54 | case 0x40000000UL: space(RCMM_ONE); break; 55 | case 0x80000000UL: space(RCMM_TWO); break; 56 | case 0xC0000000UL: space(RCMM_THREE); break; 57 | } 58 | data <<= 2; 59 | }; 60 | mark(RCMM_DATA_MARK); 61 | space(27778-extent); 62 | }; 63 | }; 64 | #endif //IRLIBSENDBASE_H 65 | 66 | #ifdef IRLIBDECODEBASE_H 67 | /* 68 | * Normally IRLib uses a plus or minus percentage to determine if an interval matches the 69 | * desired value. However this protocol uses extremely long intervals of similar length. 70 | * For example using the default 25% tolerance the RCMM_TWO value 611 would be accepted for 71 | * anything between 458 and 763. The low end is actually closer to RCMM_ONE value of 444 72 | * and the upper range is closer to RCM_THREE value of 778. To implement this protocol 73 | * we created a new match routine ABS_MATCH which allows you to specify an absolute 74 | * number of microseconds of tolerance for comparison. 75 | */ 76 | #define RCMM_TOLERANCE 80 77 | class IRdecodeRCMM: public virtual IRdecodeBase { 78 | public: 79 | bool decode(void) { 80 | resetDecoder();//This used to be in the receiver getResults. 81 | IRLIB_ATTEMPT_MESSAGE(F("RCMM")); 82 | if ( (recvGlobal.decodeLength!=(12+4)) && (recvGlobal.decodeLength!=(24+4)) && (recvGlobal.decodeLength!=(32+4)) ) return RAW_COUNT_ERROR; 83 | if (!ignoreHeader) if (!MATCH(recvGlobal.decodeBuffer[1],RCMM_HEAD_MARK)) return HEADER_MARK_ERROR(RCMM_HEAD_MARK); 84 | if (!MATCH(recvGlobal.decodeBuffer[2],RCMM_ZERO)) return HEADER_SPACE_ERROR(RCMM_ZERO); 85 | offset=3; uint32_t data=0; 86 | while (offset < (recvGlobal.decodeLength-1)) { 87 | if (!ABS_MATCH(recvGlobal.decodeBuffer[offset],RCMM_DATA_MARK,RCMM_TOLERANCE)) return DATA_MARK_ERROR(RCMM_DATA_MARK); 88 | offset++; 89 | if (ABS_MATCH(recvGlobal.decodeBuffer[offset],RCMM_ZERO, RCMM_TOLERANCE) ) { //Logical "0" 90 | data <<= 2; 91 | } 92 | else if (ABS_MATCH(recvGlobal.decodeBuffer[offset],RCMM_ONE, RCMM_TOLERANCE) ) { //Logical "1" 93 | data = (data<<2) + 1; 94 | } 95 | else if (ABS_MATCH(recvGlobal.decodeBuffer[offset],RCMM_TWO, RCMM_TOLERANCE) ) { //Logical "2" 96 | data = (data<<2) + 2; 97 | } 98 | else if (ABS_MATCH(recvGlobal.decodeBuffer[offset],RCMM_THREE, RCMM_TOLERANCE) ) { //Logical "3" 99 | data = (data<<2) + 3; 100 | } 101 | else return DATA_SPACE_ERROR(RCMM_ZERO); 102 | offset++; 103 | } 104 | if (!MATCH(recvGlobal.decodeBuffer[offset],RCMM_DATA_MARK)) return DATA_MARK_ERROR(RCMM_DATA_MARK); 105 | bits = recvGlobal.decodeLength-4;//set bit length 106 | value = data;//put remaining bits in value 107 | protocolNum=RCMM; 108 | return true; 109 | } 110 | }; 111 | #endif //IRLIBDECODEBASE_H 112 | 113 | #define IRLIB_HAVE_COMBO 114 | 115 | #endif //IRLIB_PROTOCOL_11_H 116 | -------------------------------------------------------------------------------- /src/IRLibSAMD51.cpp: -------------------------------------------------------------------------------- 1 | /* IRLibSAMD51.h 2 | * Part of IRLib Library for Arduino receiving, decoding, and sending 3 | * infrared signals. See COPYRIGHT.txt and LICENSE.txt for more information. 4 | * 5 | * This type of content is normally stored in IRLibHardware.h but we have 6 | * moved at her because the SAMD51 support is significantly different than the 7 | * AVR 8-bit hardware support. Separating it out into a separate file 8 | * will make it easier to include comments and to maintain the code. 9 | */ 10 | 11 | /* See IRLibSAMD51.h for details about this implementation. 12 | */ 13 | #if defined (__SAMD51__) 14 | #include "IRLibHardware.h" 15 | 16 | 17 | //Timer used for PWM. Is initialized in initializeSAMD51PWM(...) 18 | Tcc* IR_TCCx; 19 | Tc* IR_PWM_TCx; 20 | uint8_t IR_Use_TC; 21 | uint8_t IR_kHz; 22 | 23 | #include "wiring_private.h" 24 | 25 | void IRLibStartPWM51(void) { 26 | if(IR_Use_TC) { 27 | PinDescription pinDesc = g_APinDescription[IR_SEND_PWM_PIN]; 28 | uint8_t tcChannel = GetTCChannelNumber(pinDesc.ulPWMChannel); 29 | // -- Configure TC 30 | Tc* IR_PWM_TCx = (Tc*) GetTC(pinDesc.ulPWMChannel); 31 | //reset 32 | IR_PWM_TCx->COUNT8.CTRLA.bit.SWRST = 1; 33 | while (IR_PWM_TCx->COUNT8.SYNCBUSY.bit.SWRST); 34 | // Disable TCx 35 | IR_PWM_TCx->COUNT8.CTRLA.bit.ENABLE = 0; 36 | while (IR_PWM_TCx->COUNT8.SYNCBUSY.bit.ENABLE); 37 | // Set Timer counter Mode to 8 bits, normal PWM, prescaler 1/16 38 | IR_PWM_TCx->COUNT8.CTRLA.reg = TC_CTRLA_MODE_COUNT8 | TC_CTRLA_PRESCALER_DIV16;// | 39 | // TC_CTRLA_PRESCSYNC_PRESC; 40 | IR_PWM_TCx->COUNT8.WAVE.reg = TC_WAVE_WAVEGEN_NPWM; 41 | while (IR_PWM_TCx->COUNT8.SYNCBUSY.bit.CC0); 42 | // Set the initial value 43 | // Each timer counts up to a maximum or TOP value set by the PER register, 44 | // this determines the frequency of the PWM operation. 45 | uint32_t cc = 120000000UL/16/(IR_kHz*1000) - 1; 46 | // The CCx register value corresponds to the pulsewidth in microseconds (us) 47 | // Set the duty cycle of the PWM on TCx to 33% 48 | IR_PWM_TCx->COUNT8.CC[tcChannel].reg = (uint8_t)cc/3;//(uint8_t) cc/3; 49 | while (IR_PWM_TCx->COUNT8.SYNCBUSY.bit.CC0); 50 | IR_PWM_TCx->COUNT8.PER.reg = cc; 51 | while (IR_PWM_TCx->COUNT8.SYNCBUSY.bit.PER); 52 | IR_PWM_TCx->COUNT8.CTRLA.bit.ENABLE = 1; //temporarily disable, will enable later 53 | while (IR_PWM_TCx->COUNT8.SYNCBUSY.bit.ENABLE); 54 | } else { 55 | IR_TCCx->CTRLA.bit.ENABLE = 1; 56 | while (IR_TCCx->SYNCBUSY.bit.ENABLE); 57 | } 58 | }; 59 | 60 | void IRLibStopPWM51(void) { 61 | if(IR_Use_TC) { 62 | analogWrite(IR_SEND_PWM_PIN, 0); 63 | } else { 64 | IR_TCCx->CTRLA.bit.ENABLE = 0; 65 | while (IR_TCCx->SYNCBUSY.bit.ENABLE); 66 | } 67 | }; 68 | void initializeSAMD51PWM(uint16_t khz) { 69 | IR_kHz=khz; 70 | PinDescription pinDesc = g_APinDescription[IR_SEND_PWM_PIN]; 71 | uint32_t attr = pinDesc.ulPinAttribute; 72 | //If PWM unsupported then do nothing and exit 73 | if( !(attr & (PIN_ATTR_PWM_E|PIN_ATTR_PWM_F|PIN_ATTR_PWM_G))){ 74 | return; 75 | } 76 | uint32_t tcNum = GetTCNumber(pinDesc.ulPWMChannel); 77 | uint8_t tcChannel = GetTCChannelNumber(pinDesc.ulPWMChannel); 78 | 79 | if(attr & PIN_ATTR_PWM_E) 80 | pinPeripheral(IR_SEND_PWM_PIN, PIO_TIMER); 81 | else if(attr & PIN_ATTR_PWM_F) 82 | pinPeripheral(IR_SEND_PWM_PIN, PIO_TIMER_ALT); 83 | else if(attr & PIN_ATTR_PWM_G) 84 | pinPeripheral(IR_SEND_PWM_PIN, PIO_TCC_PDEC); 85 | 86 | GCLK->PCHCTRL[GCLK_CLKCTRL_IDs[tcNum]].reg = 87 | GCLK_PCHCTRL_GEN_GCLK0_Val | (1 << GCLK_PCHCTRL_CHEN_Pos); //use clock generator 0 88 | if (tcNum >= TCC_INST_NUM) { 89 | IR_Use_TC= true; 90 | analogWrite(IR_SEND_PWM_PIN,0);//Not sure if this is necessary but it doesn't hurt 91 | } else { 92 | IR_Use_TC= false; 93 | // Normal (single slope) PWM operation: timers countinuously count up to PER 94 | // register value and then is reset to 0 95 | //Configure TCC 96 | IR_TCCx = (Tcc*) GetTC(pinDesc.ulPWMChannel); 97 | //Reset 98 | IR_TCCx->CTRLA.bit.SWRST = 1; 99 | while (IR_TCCx->SYNCBUSY.bit.SWRST); 100 | // Disable TCCx 101 | IR_TCCx->CTRLA.bit.ENABLE = 0; 102 | while (IR_TCCx->SYNCBUSY.bit.ENABLE); 103 | // Sent pre-scaler to 1 104 | IR_TCCx->CTRLA.reg = TCC_CTRLA_PRESCALER_DIV1 | TCC_CTRLA_PRESCSYNC_GCLK; 105 | //Set TCCx as normal PWM 106 | IR_TCCx->WAVE.reg = TCC_WAVE_WAVEGEN_NPWM; 107 | while (IR_TCCx->SYNCBUSY.bit.WAVE); 108 | while (IR_TCCx->SYNCBUSY.bit.CC0 || IR_TCCx->SYNCBUSY.bit.CC1); 109 | 110 | // Each timer counts up to a maximum or TOP value set by the PER register, 111 | // this determines the frequency of the PWM operation. 112 | uint32_t cc = 120000000UL/(khz*1000) - 1; 113 | // The CCx register value corresponds to the pulsewidth in microseconds (us) 114 | // Set the duty cycle of the PWM on TCCx to 33% 115 | IR_TCCx->CC[tcChannel].reg = (uint32_t) cc/3; 116 | while (IR_TCCx->SYNCBUSY.bit.CC0 || IR_TCCx->SYNCBUSY.bit.CC1); 117 | 118 | IR_TCCx->PER.reg = cc; // Set the frequency of the PWM on IR_TCCx 119 | while(IR_TCCx->SYNCBUSY.bit.PER); 120 | 121 | IR_TCCx->CTRLA.bit.ENABLE = 0; //initially off will turn on later 122 | while (IR_TCCx->SYNCBUSY.bit.ENABLE); 123 | }; 124 | } 125 | 126 | /* 127 | * Setup the 50 microsecond timer hardware interrupt for the IRrecv class. 128 | */ 129 | void initializeSAMD51timerInterrupt(void) { 130 | GCLK->PCHCTRL[IR_TCx_ID].reg = GCLK_PCHCTRL_GEN_GCLK0 | GCLK_PCHCTRL_CHEN; 131 | while (GCLK->SYNCBUSY.bit.GENCTRL0); 132 | IR_TCx->COUNT16.CTRLA.reg &= ~TC_CTRLA_ENABLE; 133 | while (IR_TCx->COUNT16.SYNCBUSY.reg); 134 | IR_TCx->COUNT16.CTRLA.reg = TC_CTRLA_SWRST; 135 | while (IR_TCx->COUNT16.CTRLA.bit.SWRST); 136 | IR_TCx->COUNT16.CTRLA.bit.SWRST |= TC_CTRLA_MODE_COUNT16; 137 | IR_TCx->COUNT16.WAVE.reg = TC_WAVE_WAVEGEN_MPWM; 138 | IR_TCx->COUNT16.CC[0].reg = 120000000/(1000000/USEC_PER_TICK) - 1; 139 | while (IR_TCx->COUNT16.SYNCBUSY.reg); 140 | } 141 | #endif 142 | -------------------------------------------------------------------------------- /examples/analyze/analyze.ino: -------------------------------------------------------------------------------- 1 | /* analyze.ino Example sketch for IRLib2 2 | * This sketch is used to analyze unknown protocols. It receives 3 | * repeated values and averages the results. You have to press the 4 | * same key on a remote repeatedly. If you press a different key 5 | * it will reset and compute a new average. 6 | */ 7 | 8 | //This includes everything. Not generally recommended. 9 | #include 10 | #include 11 | #include 12 | #include 13 | 14 | IRdecode myDecoder; //create decoder 15 | //Recommend using either the PCI or Loop receivers 16 | #include 17 | IRrecvPCI myReceiver(2); //receiver on pin 2 18 | //#include 19 | //IRrecvLoop myReceiver(2);//receiver on pin 2 20 | 21 | uint16_t sampleCount,i, lowSpace, lowMark, highMark, highSpace, interval, 22 | balm,aalm,bahm,aahm,bals,aals,bahs,aahs; 23 | uint8_t bacm,aacm,bacs,aacs, markCount,spaceCount,oldProtocol; 24 | uint16_t accumulatedTime[RECV_BUF_LENGTH]; 25 | uint32_t markAvg, spaceAvg,baam,aaam,baas,aaas, oldValue; 26 | 27 | void setup() { 28 | Serial.begin(9600); 29 | delay(1000);while(!Serial); 30 | myReceiver.enableIRIn(); 31 | sampleCount=0;oldValue=0; oldProtocol=UNKNOWN; 32 | Serial.println(F("Send a signal repeatedly. We will report averages and statistics.")); 33 | } 34 | void Tab(void) {Serial.print("\t");}; 35 | void loop() { 36 | if (myReceiver.getResults()) { 37 | myDecoder.decode(); 38 | if( (myDecoder.protocolNum != oldProtocol) || (myDecoder.value != oldValue)) { 39 | Serial.println(F("Resetting counters")); 40 | for(i=0;i 5 | 19 | 178 | 179 | 180 |

ADAFRUIT REMOTE

181 |
182 |
 
183 |
 
184 |
185 | 186 |
187 | 188 | 189 | 190 | -------------------------------------------------------------------------------- /src/IRLib_P04_RC6.h: -------------------------------------------------------------------------------- 1 | /* IRLib_P04_RC6.h 2 | * Part of IRLib Library for Arduino receiving, decoding, and sending 3 | * infrared signals. See COPYRIGHT.txt and LICENSE.txt for more information. 4 | */ 5 | /* 6 | * The RC6 protocol was invented by Phillips but is used by wide variety of manufacturers. 7 | * Like the Phillips RC5 protocol it uses phased coding however the phase is backwards 8 | * from RC5. With RC6 a space/mark pair indicates "0" and a mark/space indicates a "1". 9 | * in the data. The protocol uses 36 kHz modulation however 38 kHz receivers can typically 10 | * receive the codes okay. 11 | * The protocol consists of a header followed by a "1" bit which is always on and we do not 12 | * encode. This is followed by a 3 bit OEM code that is usually 0 or 6. This is followed by 13 | * special trailer bit whose time is twice that of normal. It all but the 32-bit version, 14 | * the trailer bit also serves as a toggle bit. The toggle bit changes if the button was 15 | * pressed and released however remains the same if the button was held. You must toggle 16 | * this bit yourself when sending data and account for it when interpreting decoded values. 17 | * Next are the actual data bits. Varieties include 16, 20, 24, and 32 bit versions. 18 | * Because we encode the 3 OEM bits and the toggle bit, our actual bit lengths are 20, 24, 19 | * and 28 for the first three varieties. The 32-bit variety is different because it uses 20 | * OEM bits of 011 followed by a 0 in what is traditionally the toggle bit. 21 | * Because the 32-bit version is invariant in these first 4 bits, we do not encode them 22 | * and presume they are always "0110". The 32-bit version uses the highest order of the 23 | * data bits as a toggle bit. At this time the 16-bit version always uses OEM = 0 and 24 | * other known varieties always use OEM = 6 but we will only make that presumption for the 25 | * 32-bit version. Encoding the OEM bits allows for other OEM values to be used without 26 | * modifying the library. If we ever encounter a 32-bit version with an OEM other than 6 27 | * it will require a special modified encoder and decoder. 28 | * Here is a description of known varieties: 29 | * RC6-0-16: Original version by Phillips. 16 bits, we encode 20, toggle is 0x00010000 30 | * RC6-6-20: Used by some Sky and Sky+ remotes. 20 bits, we encode 24, toggle is 0x00100000 31 | * RC6-6-24: Also known as "Replay" protocol. 24 bits, we encode 28, toggle is 0x01000000 32 | * RC6-6-32: Also known as "MCE" protocol. 32 bits, we encode 32, toggle is 0x00008000 33 | */ 34 | #ifndef IRLIB_PROTOCOL_04_H 35 | #define IRLIB_PROTOCOL_04_H 36 | #define IR_SEND_PROTOCOL_04 case 04: IRsendRC6::send(data,data2); break; 37 | #define IR_DECODE_PROTOCOL_04 if(IRdecodeRC6::decode()) return true; 38 | #ifdef IRLIB_HAVE_COMBO 39 | #define PV_IR_DECODE_PROTOCOL_04 ,public virtual IRdecodeRC6 40 | #define PV_IR_SEND_PROTOCOL_04 ,public virtual IRsendRC6 41 | #else 42 | #define PV_IR_DECODE_PROTOCOL_04 public virtual IRdecodeRC6 43 | #define PV_IR_SEND_PROTOCOL_04 public virtual IRsendRC6 44 | #endif 45 | #define RC6_HDR_MARK 2666 46 | #define RC6_HDR_SPACE 889 47 | #define RC6_T1 444 48 | 49 | #ifdef IRLIBSENDBASE_H 50 | class IRsendRC6: public virtual IRsendBase { 51 | public: 52 | void send(uint32_t data, uint8_t nBits=16) { 53 | if (nBits==0) nBits=16; 54 | enableIROut(36); 55 | uint64_t bigData = data; 56 | if (nBits==32) { 57 | bigData+=0xc00000000ull;//add OEM value 58 | nBits=36; 59 | }; 60 | bigData=bigData << (64 - nBits); 61 | extent=0; 62 | mark(RC6_HDR_MARK); space(RC6_HDR_SPACE); 63 | mark(RC6_T1); space(RC6_T1);// start bit "1" 64 | uint16_t t; 65 | for (uint8_t i = 0; i < nBits; i++) { 66 | if (i == 3) { 67 | t = 2 * RC6_T1; // double-wide trailer bit 68 | } else { 69 | t = RC6_T1; 70 | } 71 | if (bigData & 0x8000000000000000ull) { 72 | mark(t); space(t);//"1" is a Mark/space 73 | } else { 74 | space(t); mark(t);//"0" is a space/Mark 75 | } 76 | bigData <<= 1; 77 | } 78 | space(107000-extent); // Turn off at end 79 | } 80 | }; 81 | #endif //IRLIBSENDBASE_H 82 | 83 | #ifdef IRLIBDECODEBASE_H 84 | 85 | /* Note this decoder is a derived class from the IRdecodeRC base 86 | * class rather than IRdecodeBase. The base class defines the 87 | * method "getRClevel" which is common to both RC5 and RC6 protocols. 88 | * It facilitates the decoding of phase encoded data. 89 | */ 90 | class IRdecodeRC6: public virtual IRdecodeRC { 91 | public: 92 | virtual bool decode(void) { 93 | IRLIB_ATTEMPT_MESSAGE(F("RC6")); 94 | resetDecoder();//This used to be in the receiver getResults. 95 | //Legal lengths range from 24 through 76 we went one bigger just in case. 96 | if( (recvGlobal.decodeLength < 23) || (recvGlobal.decodeLength > 77) )return RAW_COUNT_ERROR; 97 | // Initial mark 98 | if (!ignoreHeader) { 99 | if (!MATCH(recvGlobal.decodeBuffer[1], RC6_HDR_MARK)) return HEADER_MARK_ERROR(RC6_HDR_MARK); 100 | } 101 | if (!MATCH(recvGlobal.decodeBuffer[2], RC6_HDR_SPACE)) return HEADER_SPACE_ERROR(RC6_HDR_SPACE); 102 | offset=3;//Skip gap and header 103 | data = 0; 104 | used = 0; 105 | // Get start bit (1) 106 | if (getRClevel(&used, RC6_T1) != MARK) return DATA_MARK_ERROR(RC6_T1); 107 | if (getRClevel(&used, RC6_T1) != SPACE) return DATA_SPACE_ERROR(RC6_T1); 108 | for (nBits = 0; offset < recvGlobal.decodeLength; nBits++) { 109 | RCLevel levelA, levelB; // Next two levels 110 | levelA = getRClevel(&used, RC6_T1); 111 | if (nBits == 3) { 112 | // T bit is double wide; make sure second half matches 113 | if (levelA != getRClevel(&used, RC6_T1)) return TRAILER_BIT_ERROR(RC6_T1); 114 | } 115 | levelB = getRClevel(&used, RC6_T1); 116 | if (nBits == 3) { 117 | // T bit is double wide; make sure second half matches 118 | if (levelB != getRClevel(&used, RC6_T1)) return TRAILER_BIT_ERROR(RC6_T1); 119 | } 120 | if (levelA == MARK && levelB == SPACE) { // reversed compared to RC5 121 | data = (data << 1) | 1; // 1 bit 122 | } else if (levelA == SPACE && levelB == MARK) { 123 | data <<= 1; // zero bit 124 | } else { 125 | return DATA_MARK_ERROR(RC6_T1); 126 | } 127 | } 128 | // Success 129 | if (nBits==36) { 130 | nBits=32;//OEM & trailer bits are discarded on 32-bit version 131 | } else { 132 | //if ( (nBits!=20) || (nBits!=24) || (nBits!=28) ) return BIT_COUNT_ERROR; 133 | } 134 | bits = nBits; 135 | value = data; 136 | protocolNum = RC6; 137 | return true; 138 | } 139 | }; 140 | #endif //IRLIBDECODEBASE_H 141 | 142 | #define IRLIB_HAVE_COMBO 143 | 144 | #endif //IRLIB_PROTOCOL_04_H 145 | -------------------------------------------------------------------------------- /src/IRLibRecv.cpp: -------------------------------------------------------------------------------- 1 | /* IRrecv.cpp 2 | * Part of IRLib Library for Arduino receiving, decoding, and sending 3 | * infrared signals. See COPYRIGHT.txt and LICENSE.txt for more information. 4 | * 5 | * This module implements the original IRrecv receiver class which uses the 50us 6 | * interrupt timer to poll the input pin. While this is generally accurate enough for 7 | * everyday purposes, it may be difficult to port to other hardware unless you know a lot 8 | * about hardware timers and interrupts. Also when trying to analyze unknown protocols, 9 | * the 50us granularity may not be sufficient. In that case use either the IRrecvLoop or 10 | * the IRrecvPCI class. 11 | */ 12 | 13 | #include "IRLibRecv.h" 14 | #include "IRLibHardware.h" //needed for IRLib_didIROut 15 | #if !defined (__SAMD21G18A__) 16 | #include 17 | #endif 18 | 19 | /* Initializes receiving and starts up the 50us interrupt timer. Call this to initialize 20 | * and call it again to resume receiving after completing the decoding. Previous versions of 21 | * IRLib had a "resume" method but you should use this in either initializing or resuming. 22 | */ 23 | void IRrecv::enableIRIn(void) { 24 | //If newDataAvailable means that we did an auto resume and while the decoder 25 | //was processing the first frame, the second frame completed. We came here 26 | //essentially saying "get me another frame" but the another frame was already here. 27 | //Therefore we get out, the decoder will call getResults which will be true and 28 | //everything proceeds as normal. 29 | if(recvGlobal.newDataAvailable) 30 | return; 31 | recvGlobal.decoderWantsData=true;//otherwise he wouldn't have called 32 | //We cannot simply restart the receiver because if it did an auto resume then it is 33 | //already running. If state is STATE_FINISHED it means the ISR finished and did not auto 34 | //resume. If IRLib_didIROut is true then the send object shut us down due to the hardware 35 | //conflict between PWM output and the timer interrupt. It means we need to reinitialize 36 | //everything. 37 | if( (recvGlobal.currentState==STATE_FINISHED) || IRLib_didIROut ) { 38 | IRrecvBase::enableIRIn(); 39 | recvGlobal.timer = 0; 40 | // setup pulse clock timer interrupt 41 | noInterrupts(); 42 | IR_RECV_CONFIG_TICKS(); 43 | IR_RECV_ENABLE_INTR; 44 | interrupts(); 45 | } 46 | } 47 | 48 | /* Even when not sampling inputs and recording pulse timing, the ISR remains active 49 | * continues to interrupt every 50us however it remains in a do-nothing state. If 50 | * the user wants to truly shut down the ISR they can call this method. 51 | */ 52 | void IRrecv::disableIRIn(void) { 53 | IR_RECV_DISABLE_INTR; //Defined in IRLibTimer.h disables 50us timer interrupt 54 | IRrecvBase::disableIRIn(); //Base method resets a variety variables 55 | } 56 | 57 | /* Returns true if a frame of data is available in the buffer. Most of the 58 | * handling is done by the base method. The parameter passed the number of 59 | * microseconds per timing interval (usually 50) 60 | */ 61 | bool IRrecv::getResults(void) { 62 | if (recvGlobal.newDataAvailable) { 63 | IRrecvBase::getResults(USEC_PER_TICK); 64 | return true; 65 | } 66 | return false; 67 | } 68 | 69 | /* Call this method to specify how long of a space designates 70 | * the end of the frame data. You cannot set the value directly 71 | * but have to do it by this method. 72 | */ 73 | void IRrecv::setFrameTimeout(uint16_t frameTimeout) { 74 | recvGlobal.frameTimeoutTicks=frameTimeout/USEC_PER_TICK; 75 | IRrecv::setFrameTimeout(frameTimeout); 76 | } 77 | 78 | /* 79 | * This interrupt service routine is used by IRrecv. Interrupt is triggered every 80 | * 50 us using hardware timers. At each interrupt, input pin is polled to see if it is a 81 | * MARK or SPACE. We count the number of these 50 us ticks to estimate the length 82 | * of each MARK or SPACE interval. This code is implemented as a state machine. 83 | * A description of each state is given in the code below. More details on the ISR macro 84 | * see http://www.atmel.com/webdoc/AVRLibcReferenceManual/group__avr__interrupts.html 85 | */ 86 | IR_RECV_INTR_NAME { 87 | //If the receiver pin is low, data is a MARK, if high, data is a SPACE 88 | #define IR_MARK 0 89 | #define IR_SPACE 1 90 | uint8_t irData = digitalRead(recvGlobal.recvPin); 91 | recvGlobal.timer++; // One more 50us tick 92 | IR_CLEAR_INTERRUPT 93 | if (recvGlobal.recvLength >= RECV_BUF_LENGTH) { // Buffer overflow 94 | IRLib_IRrecvComplete(4); 95 | } 96 | switch(recvGlobal.currentState) { 97 | case STATE_READY_TO_BEGIN: 98 | // The state machine is initialized in STATE_READY_TO_BEGIN which means that it is 99 | // looking for the initial MARK signal of a frame of data. It continues to count ticks 100 | // in order to measure the interval of the gap between data frames. When it finds the 101 | // initial MARK, it records the length of the gap, resets the tick counter, 102 | // and changes the state to STATE_TIMING_MARK. 103 | if (irData == IR_MARK) { 104 | recvGlobal.recvLength = 0; 105 | recvGlobal.recvBuffer[recvGlobal.recvLength++] = recvGlobal.timer; 106 | recvGlobal.timer = 0; 107 | recvGlobal.currentState = STATE_TIMING_MARK; 108 | } 109 | break; 110 | case STATE_TIMING_MARK: 111 | // This state means that the previous sample was a MARK. If it reads a SPACE 112 | // then it records the number of ticks, resets the counter, and changes the state to 113 | // STATE_TIMING_SPACE. If it was still a MARK we just keep counting. 114 | if (irData == IR_SPACE) { // MARK ended, record time 115 | recvGlobal.recvBuffer[recvGlobal.recvLength++] = recvGlobal.timer; 116 | recvGlobal.timer = 0; 117 | recvGlobal.currentState = STATE_TIMING_SPACE; 118 | } 119 | break; 120 | case STATE_TIMING_SPACE: 121 | // This state means that the previous sample was a SPACE. If it reads a MARK 122 | // then it records the number of ticks, reset the counter, and changes the state to 123 | // STATE_TIMING_MARK. However if it is still a SPACE, we need to see if it was so big 124 | // that we are seeing the gap between frames. If the gap is long, we need to finish 125 | // and somehow indicate that we have completed a full frame data. 126 | if (irData == IR_MARK) { // SPACE just ended, record it 127 | recvGlobal.recvBuffer[recvGlobal.recvLength++] = recvGlobal.timer; 128 | recvGlobal.timer = 0; 129 | recvGlobal.currentState = STATE_TIMING_MARK; 130 | } 131 | else { 132 | // If we get here we know that the previous was a SPACE and it still is a SPACE. 133 | // Now we have to see if the SPACE has gotten is long enough that we know it 134 | // must be the end of the frame. 135 | if (recvGlobal.timer > recvGlobal.frameTimeoutTicks) { 136 | IRLib_IRrecvComplete(5); 137 | } 138 | } 139 | break; 140 | case STATE_FINISHED: 141 | // The state means that we completed receiving a frame and are waiting for 142 | // the user to ask us for another one. We will keep counting the time of the 143 | // gap and reset that timer if we ever see a MARK. 144 | if (irData == IR_MARK) { 145 | recvGlobal.timer = 0; 146 | } 147 | break; 148 | } 149 | IRLib_doBlink(); 150 | } 151 | -------------------------------------------------------------------------------- /src/IRLibSAMD21.cpp: -------------------------------------------------------------------------------- 1 | /* IRLibSAMD21.h 2 | * Part of IRLib Library for Arduino receiving, decoding, and sending 3 | * infrared signals. See COPYRIGHT.txt and LICENSE.txt for more information. 4 | * 5 | * This type of content is normally stored in IRLibHardware.h but we have 6 | * moved at her because the SAMD21 support is significantly different than the 7 | * AVR 8-bit hardware support. Separating it out into a separate file 8 | * will make it easier to include comments and to maintain the code. 9 | */ 10 | 11 | /* See IRLibSAMD21.h for details about this implementation. 12 | */ 13 | #if defined (__SAMD21G18A__) || (__SAMD21E18A__) 14 | #include "IRLibHardware.h" 15 | 16 | //Save some typing 17 | #define IR_APD g_APinDescription[IR_SEND_PWM_PIN] 18 | #define syncGCLK while (GCLK->STATUS.bit.SYNCBUSY) 19 | 20 | //Timer used for PWM. Is initialized in initializeSAMD21PWM(...) 21 | Tcc* IR_TCCx; 22 | 23 | /* Types used for the table below */ 24 | 25 | //Cannot use g_APinDescription to determine PWM channel because we insist on only 26 | //using only TCC0 or TCC1. Therefore we create our own lookup table 27 | typedef struct _IR_PWM_Map 28 | { 29 | ETCChannel IR_TCC_Channel; 30 | int8_t IR_PER_EorF; 31 | } IR_PWM_Map_t; 32 | 33 | IR_PWM_Map_t IR_PWM_Map[64]= 34 | { 35 | //PORTA 0-31 36 | {NOT_ON_TIMER,NOT_ON_TIMER}, //PA00 37 | {NOT_ON_TIMER,NOT_ON_TIMER}, //PA01 38 | {NOT_ON_TIMER,NOT_ON_TIMER}, //PA02 39 | {NOT_ON_TIMER,NOT_ON_TIMER}, //PA03 40 | {TCC0_CH0,PORT_PMUX_PMUXE_E}, //PA04 works 41 | {TCC0_CH1,PORT_PMUX_PMUXO_E}, //PA05 works 42 | {TCC1_CH0,PORT_PMUX_PMUXE_E}, //PA06 works 43 | {TCC1_CH1,PORT_PMUX_PMUXO_E}, //PA07 works 44 | 45 | {TCC0_CH0,PORT_PMUX_PMUXE_E}, //PA08 works 46 | {TCC0_CH1,PORT_PMUX_PMUXO_E}, //PA09 works 47 | {TCC0_CH2,PORT_PMUX_PMUXE_F}, //PA10 works 48 | {TCC0_CH3,PORT_PMUX_PMUXO_F}, //PA11 works 49 | {TCC0_CH6,PORT_PMUX_PMUXE_F}, //PA12 works 50 | {TCC0_CH7,PORT_PMUX_PMUXO_F}, //PA13 untested 51 | {TCC0_CH4,PORT_PMUX_PMUXE_F}, //PA14 works 52 | {TCC0_CH5,PORT_PMUX_PMUXO_F}, //PA15 works 53 | 54 | {TCC0_CH6,PORT_PMUX_PMUXE_F}, //PA16 works 55 | {TCC0_CH7,PORT_PMUX_PMUXO_F}, //PA17 works 56 | {TCC0_CH2,PORT_PMUX_PMUXE_F}, //PA18 works 57 | {TCC0_CH3,PORT_PMUX_PMUXO_F}, //PA19 works 58 | {TCC0_CH6,PORT_PMUX_PMUXE_F}, //PA20 works 59 | {TCC0_CH7,PORT_PMUX_PMUXO_F}, //PA21 works 60 | {TCC0_CH4,PORT_PMUX_PMUXE_F}, //PA22 works 61 | {TCC0_CH5,PORT_PMUX_PMUXO_F}, //PA23 works 62 | 63 | {TCC1_CH2,PORT_PMUX_PMUXE_F}, //PA24 untested 64 | {TCC1_CH3,PORT_PMUX_PMUXO_F}, //PA25 untested 65 | {NOT_ON_TIMER,NOT_ON_TIMER}, //PA26 66 | {NOT_ON_TIMER,NOT_ON_TIMER}, //PA27 67 | {NOT_ON_TIMER,NOT_ON_TIMER}, //PA28 68 | {NOT_ON_TIMER,NOT_ON_TIMER}, //PA29 69 | {TCC1_CH0,PORT_PMUX_PMUXE_E}, //PA30 untested 70 | {TCC1_CH1,PORT_PMUX_PMUXO_E}, //PA31 untested 71 | 72 | //PORTB 0-31 73 | {NOT_ON_TIMER,NOT_ON_TIMER}, //PB00 74 | {NOT_ON_TIMER,NOT_ON_TIMER}, //PB01 75 | {NOT_ON_TIMER,NOT_ON_TIMER}, //PB02 76 | {NOT_ON_TIMER,NOT_ON_TIMER}, //PB03 77 | {NOT_ON_TIMER,NOT_ON_TIMER}, //PB04 78 | {NOT_ON_TIMER,NOT_ON_TIMER}, //PB05 79 | {NOT_ON_TIMER,NOT_ON_TIMER}, //PB06 80 | {NOT_ON_TIMER,NOT_ON_TIMER}, //PB07 81 | 82 | {NOT_ON_TIMER,NOT_ON_TIMER}, //PB08 83 | {NOT_ON_TIMER,NOT_ON_TIMER}, //PB09 84 | {TCC0_CH4,PORT_PMUX_PMUXE_F}, //PB10 works 85 | {TCC0_CH5,PORT_PMUX_PMUXO_F}, //PB11 works 86 | {TCC0_CH6,PORT_PMUX_PMUXE_F}, //PB12 untested 87 | {TCC0_CH7,PORT_PMUX_PMUXO_F}, //PB13 untested 88 | {NOT_ON_TIMER,NOT_ON_TIMER}, //PB14 89 | {NOT_ON_TIMER,NOT_ON_TIMER}, //PB15 90 | 91 | {TCC0_CH4,PORT_PMUX_PMUXE_F}, //PB16 untested 92 | {TCC0_CH5,PORT_PMUX_PMUXO_F}, //PB17 untested 93 | {NOT_ON_TIMER,NOT_ON_TIMER}, //PB18 94 | {NOT_ON_TIMER,NOT_ON_TIMER}, //PB19 95 | {NOT_ON_TIMER,NOT_ON_TIMER}, //PB20 96 | {NOT_ON_TIMER,NOT_ON_TIMER}, //PB21 97 | {NOT_ON_TIMER,NOT_ON_TIMER}, //PB22 98 | {NOT_ON_TIMER,NOT_ON_TIMER}, //PB23 99 | 100 | {NOT_ON_TIMER,NOT_ON_TIMER}, //PB24 101 | {NOT_ON_TIMER,NOT_ON_TIMER}, //PB25 102 | {NOT_ON_TIMER,NOT_ON_TIMER}, //PB26 103 | {NOT_ON_TIMER,NOT_ON_TIMER}, //PB27 104 | {NOT_ON_TIMER,NOT_ON_TIMER}, //PB28 105 | {NOT_ON_TIMER,NOT_ON_TIMER}, //PB29 106 | {TCC0_CH0,PORT_PMUX_PMUXE_E}, //PB30 untested 107 | {TCC0_CH1,PORT_PMUX_PMUXO_E} //PB31 untested 108 | }; 109 | 110 | void initializeSAMD21PWM(uint16_t khz) { 111 | uint8_t port=IR_APD.ulPort; 112 | uint8_t pin=IR_APD.ulPin; 113 | uint8_t IR_mapIndex=port*32 + pin; 114 | //If PWM unsupported then do nothing and exit 115 | if(IR_PWM_Map[IR_mapIndex].IR_TCC_Channel == NOT_ON_TIMER) { 116 | return; 117 | } 118 | //println();Serial.print("Port:"); Serial.print(port,DEC); Serial.print(" Pin:"); Serial.println(pin,DEC); 119 | // Enable the port multiplexer for the PWM channel on pin 120 | PORT->Group[port].PINCFG[pin].bit.PMUXEN = 1; 121 | 122 | // Connect the TCC timer to the port outputs - port pins are paired odd PMUXO and even PMUXEII 123 | // F & E peripherals specify the timers: TCC0, TCC1 and TCC2 124 | PORT->Group[port].PMUX[pin >> 1].reg |= IR_PWM_Map[IR_mapIndex].IR_PER_EorF; 125 | 126 | // pinPeripheral (IR_SEND_PWM_PIN,PIO_TIMER_ALT); 127 | // Feed GCLK0 to TCC0 and TCC1 128 | REG_GCLK_CLKCTRL = GCLK_CLKCTRL_CLKEN | // Enable GCLK0 to TCC0 and TCC1 129 | GCLK_CLKCTRL_GEN_GCLK0 | // Select GCLK0 130 | GCLK_CLKCTRL_ID_TCC0_TCC1; // Feed GCLK0 to TCC0 and TCC1 131 | syncGCLK; // Wait for synchronization 132 | 133 | // Normal (single slope) PWM operation: timers countinuously count up to PER 134 | // register value and then is reset to 0 135 | IR_TCCx = (Tcc*) GetTC(IR_PWM_Map[IR_mapIndex].IR_TCC_Channel); 136 | IR_TCCx->WAVE.reg |= TCC_WAVE_WAVEGEN_NPWM; // Setup single slope PWM on TCCx 137 | while (IR_TCCx->SYNCBUSY.bit.WAVE); // Wait for synchronization 138 | 139 | // Each timer counts up to a maximum or TOP value set by the PER register, 140 | // this determines the frequency of the PWM operation. 141 | uint32_t cc = F_CPU/(khz*1000) - 1; 142 | IR_TCCx->PER.reg = cc; // Set the frequency of the PWM on IR_TCCx 143 | while(IR_TCCx->SYNCBUSY.bit.PER); 144 | 145 | // The CCx register value corresponds to the pulsewidth in microseconds (us) 146 | // Set the duty cycle of the PWM on TCC0 to 33% 147 | IR_TCCx->CC[GetTCChannelNumber(IR_PWM_Map[IR_mapIndex].IR_TCC_Channel)].reg = cc/3; 148 | while (IR_TCCx->SYNCBUSY.reg & TCC_SYNCBUSY_MASK); 149 | //while(IR_TCCx->SYNCBUSY.bit.CC3); 150 | 151 | // Enable IR_TCCx timer but do not turn on PWM yet. Will turn it on later. 152 | IR_TCCx->CTRLA.reg |= TCC_CTRLA_PRESCALER_DIV1; // Divide GCLK0 by 1 153 | while (IR_TCCx->SYNCBUSY.bit.ENABLE); 154 | IR_TCCx->CTRLA.reg &= ~TCC_CTRLA_ENABLE; //initially off will turn on later 155 | while (IR_TCCx->SYNCBUSY.bit.ENABLE); 156 | } 157 | /* 158 | * Setup the 50 microsecond timer hardware interrupt for the IRrecv class. 159 | */ 160 | void initializeSAMD21timerInterrupt(void) { 161 | GCLK->CLKCTRL.reg = (uint16_t)(GCLK_CLKCTRL_CLKEN | 162 | GCLK_CLKCTRL_GEN_GCLK0 | 163 | GCLK_CLKCTRL_ID(IR_GCM)); 164 | syncGCLK; 165 | IR_TCx->COUNT16.CTRLA.reg &= ~TC_CTRLA_ENABLE; 166 | syncTC; 167 | IR_TCx->COUNT16.CTRLA.reg = TC_CTRLA_SWRST; 168 | while (IR_TCx->COUNT16.CTRLA.bit.SWRST); 169 | IR_TCx->COUNT16.CTRLA.reg |= TC_CTRLA_MODE_COUNT16; 170 | IR_TCx->COUNT16.CTRLA.reg |= TC_CTRLA_WAVEGEN_MFRQ; 171 | IR_TCx->COUNT16.CC[0].reg = F_CPU/(1000000/USEC_PER_TICK) - 1; 172 | syncTC; 173 | } 174 | #endif 175 | -------------------------------------------------------------------------------- /examples/Iot_IR/cable_and_tv.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 18 | 207 | 208 | 209 |

Cable and TV

210 |
211 |
 
212 |
 
213 |
214 | 215 |
216 | 217 | 218 | 219 | -------------------------------------------------------------------------------- /src/IRLibDecodeBase.cpp: -------------------------------------------------------------------------------- 1 | /* IRLibDecodeBase.cpp 2 | * Part of IRLib Library for Arduino receiving, decoding, and sending 3 | * infrared signals. See COPYRIGHT.txt and LICENSE.txt for more information. 4 | */ 5 | /* 6 | * This module contains the base classes for decoding. You will not create instances 7 | * of these classes, rather you will use them as base classes in creating derived 8 | * protocol specific decoders. 9 | */ 10 | #include "IRLibDecodeBase.h" 11 | #include "IRLibHardware.h" 12 | 13 | IRdecodeBase::IRdecodeBase(void) { 14 | recvGlobal.decoderWantsData=false; //turned on by enableIRIn. 15 | recvGlobal.decodeBuffer=recvGlobal.recvBuffer;//default buffer 16 | ignoreHeader=false; 17 | resetDecoder(); 18 | }; 19 | 20 | /* 21 | * Reinitialize the decoder clearing out previous data. 22 | */ 23 | void IRdecodeBase::resetDecoder(void) { 24 | protocolNum= UNKNOWN; 25 | value=0; 26 | address=0; 27 | bits=0; 28 | }; 29 | void IRdecodeBase::dumpResults(bool verbose) { 30 | int i;uint32_t Extent;int interval; 31 | if((protocolNum>89) || (protocolNum<=LAST_PROTOCOL)) { 32 | Serial.print(F("Decoded ")); Serial.print(Pnames(protocolNum)); 33 | Serial.print(F("(")); Serial.print(protocolNum,DEC); 34 | Serial.print(F("): Value:")); Serial.print(value, HEX); 35 | Serial.print(F(" Adrs:" )); Serial.print(address, HEX); 36 | }; 37 | Serial.print(F(" (")); Serial.print(bits, DEC); Serial.print(F(" bits) ")); 38 | if(recvGlobal.didAutoResume) Serial.print(F("Auto Resumed")); 39 | Serial.println(); 40 | if(!verbose) 41 | return; 42 | Serial.print(F("Raw samples(")); Serial.print(recvGlobal.decodeLength, DEC); 43 | Serial.print(F("): Gap:")); Serial.println(recvGlobal.decodeBuffer[0], DEC); 44 | Serial.print(F(" Head: m")); Serial.print(recvGlobal.decodeBuffer[1], DEC); 45 | Serial.print(F(" s")); Serial.println(recvGlobal.decodeBuffer[2], DEC); 46 | int LowSpace= 32767; int LowMark= 32767; 47 | int HiSpace=0; int HiMark= 0; 48 | Extent=recvGlobal.decodeBuffer[1]+recvGlobal.decodeBuffer[2]; 49 | for (i = 3; i < recvGlobal.decodeLength; i++) { 50 | Extent+=(interval= recvGlobal.decodeBuffer[i]); 51 | if (i % 2) { 52 | LowMark=min(LowMark, interval); HiMark=max(HiMark, interval); 53 | Serial.print(i/2-1,DEC); Serial.print(F(":m")); 54 | } 55 | else { 56 | if(interval>0)LowSpace=min(LowSpace, interval); HiSpace=max (HiSpace, interval); 57 | Serial.print(F(" s")); 58 | } 59 | Serial.print(interval, DEC); 60 | int j=i-1; 61 | if ((j % 2)==1)Serial.print(F("\t")); 62 | if ((j % 4)==1)Serial.print(F("\t ")); 63 | if ((j % 8)==1)Serial.println(); 64 | if ((j % 32)==1)Serial.println(); 65 | } 66 | Serial.println(); 67 | Serial.print(F("Extent=")); Serial.println(Extent,DEC); 68 | Serial.print(F("Mark min:")); Serial.print(LowMark,DEC);Serial.print(F("\t max:")); Serial.println(HiMark,DEC); 69 | Serial.print(F("Space min:")); Serial.print(LowSpace,DEC);Serial.print(F("\t max:")); Serial.println(HiSpace,DEC); 70 | Serial.println(); 71 | } 72 | 73 | /* We use a generic routine because most protocols have the same basic structure. 74 | * Previous versions of this method would handle protocols with variable marks 75 | * or variable spaces. However we have discovered that only Sony protocol uses 76 | * variable marks so we have stripped out that portion of the code. This changes 77 | * the number of necessary parameters. We no longer need markOne and markZero 78 | * because they are both the same which we will pass in markData. Note this new 79 | * version will handle up to 48 bits putting the most significant 16 bits in 80 | * "this.address" in the least significant 32 bits in "this.data". We could have 81 | * allowed for 64 bit but we have not seen generic protocols that large. 82 | */ 83 | bool IRdecodeBase::decodeGeneric(uint8_t expectedLength, 84 | uint16_t headMark, uint16_t headSpace, uint16_t markData, 85 | uint16_t spaceOne, uint16_t spaceZero) { 86 | resetDecoder();//This used to be in the receiver getResults. 87 | // If "expectedLenght" or "headMark" or "headSpace" are zero or if "ignoreHeader" 88 | // is true then don't perform these tests. This is because some protocols need 89 | // to do their own custom header work. 90 | uint64_t data = 0; 91 | bufIndex_t Max=recvGlobal.decodeLength-1; 92 | if (expectedLength) { 93 | if (recvGlobal.decodeLength != expectedLength) return RAW_COUNT_ERROR; 94 | } 95 | if(!ignoreHeader) { 96 | if (headMark) { 97 | if (!MATCH(recvGlobal.decodeBuffer[1],headMark)) return HEADER_MARK_ERROR(headMark); 98 | } 99 | } 100 | if (headSpace) { 101 | if (!MATCH(recvGlobal.decodeBuffer[2],headSpace)) return HEADER_SPACE_ERROR(headSpace); 102 | } 103 | offset=3;//skip initial gap plus two header items 104 | while (offset < Max) { 105 | if (!MATCH (recvGlobal.decodeBuffer[offset],markData)) return DATA_MARK_ERROR(markData); 106 | offset++; 107 | if (MATCH(recvGlobal.decodeBuffer[offset],spaceOne)) { 108 | data = (data << 1) | 1; 109 | } 110 | else if (MATCH (recvGlobal.decodeBuffer[offset],spaceZero)) { 111 | data <<= 1; 112 | } 113 | else return DATA_SPACE_ERROR(spaceZero); 114 | offset++; 115 | } 116 | bits = (offset - 1) / 2 -1;//didn't encode stop bit 117 | // Success 118 | value = (uint32_t)data; //low order 32 bits 119 | address = (uint16_t) (data>>32); //high order 16 bits 120 | return true; 121 | } 122 | 123 | /* 124 | * These MATCH methods used to be macros but we saved nearly 125 | * 800 bytes of program space by making them actual methods. 126 | */ 127 | 128 | bool IRdecodeBase::MATCH(int16_t val,int16_t expected){ 129 | #ifdef IRLIB_USE_PERCENT 130 | return (val >= (uint16_t)(expected*(1.0-PERCENT_TOLERANCE/100.0))) 131 | && (val <= (uint16_t)(expected*(1.0+PERCENT_TOLERANCE/100.0))); 132 | #else 133 | return ABS_MATCH(val,expected,DEFAULT_ABS_TOLERANCE); 134 | #endif 135 | } 136 | bool IRdecodeBase::ABS_MATCH(int16_t val,int16_t expected,int16_t tolerance){ 137 | return (val >= (expected-tolerance)) && (val <= (expected+tolerance)); 138 | } 139 | 140 | /* 141 | * The RC5 and RC6 and similar protocols used phase encoding and leave a 142 | * routine to extract zeros and ones. This routine gets one undecoded 143 | * level at a time from the raw buffer. personally The RC5/6 decoding 144 | * is easier if the data is broken into time intervals. 145 | * E.g. if the buffer has MARK for 2 time intervals and SPACE for 1, 146 | * successive calls to getRClevel will return MARK, MARK, SPACE. 147 | * The variables "offset" and "used" are updated to keep track of the 148 | * current position. The variable "t1" is the time interval for a single 149 | * bit in microseconds. Returns ERROR if the measured time interval is 150 | * not a multiple of "t1". 151 | */ 152 | IRdecodeRC::RCLevel IRdecodeRC::getRClevel(uint8_t *used, const uint16_t t1) { 153 | if (offset >= recvGlobal.decodeLength) { 154 | // After end of recorded buffer, assume SPACE. 155 | return SPACE; 156 | } 157 | uint16_t width = recvGlobal.decodeBuffer[offset]; 158 | IRdecodeRC::RCLevel val; 159 | if ((offset) % 2) val=MARK; else val=SPACE; 160 | uint8_t avail; 161 | if (MATCH(width, t1)) { 162 | avail = 1; 163 | } 164 | else if (MATCH(width, 2*t1)) { 165 | avail = 2; 166 | } 167 | else if (MATCH(width, 3*t1)) { 168 | avail = 3; 169 | } else { 170 | if((ignoreHeader) && (offset==1) && (width= avail) { 178 | *used = 0; 179 | (offset)++; 180 | } 181 | return val; 182 | } 183 | -------------------------------------------------------------------------------- /src/IRLibGlobals.h: -------------------------------------------------------------------------------- 1 | /* IRLibGlobals.h 2 | * Part of IRLib Library for Arduino receiving, decoding, and sending 3 | * infrared signals. See COPYRIGHT.txt and LICENSE.txt for more information. 4 | * 5 | * This file replaces the previous IRLibRData.h file. It contains definition of global 6 | * items which are used by both the receiver and decoding classes. They have to be 7 | * declared global in scope because they are accessed by the ISR and you cannot pass 8 | * parameters nor objects to an ISR routine. 9 | * 10 | * In general, applications would not include this file. Unless you are creating your own 11 | * customized receiver class apart from the provided IRrcev, IRrcevPCI, or IRrcevLoop 12 | * classes, you can ignore the contents of this file. 13 | * The RECV_BUF_LENGTH is the only item you would ever modify unless you are completely 14 | * rewriting how the system works in general. 15 | */ 16 | #ifndef IRLibGlobals_h 17 | #define IRLibGlobals_h 18 | #include 19 | 20 | /* Timing data is stored in a buffer by the receiver object. It is an array of 21 | * uint16_t that should be at least 100 entries as defined by this default below. 22 | * However some IR sequences will require longer buffers especially those used for 23 | * air conditioner controls. In general we recommend you keep this value below 255 24 | * so that the index into the array can remain 8 bits. This library can handle larger 25 | * arrays however it will make your code longer in addition to taking more RAM. 26 | */ 27 | #define RECV_BUF_LENGTH 100 28 | #if (RECV_BUF_LENGTH > 255) 29 | typedef uint16_t bufIndex_t; 30 | #else 31 | typedef uint8_t bufIndex_t; 32 | #endif 33 | 34 | // Receiver states. This previously was enum but changed it to uint8_t 35 | // to guarantee it was a single atomic 8-bit value. 36 | #define STATE_UNKNOWN 0 37 | #define STATE_READY_TO_BEGIN 1 38 | #define STATE_TIMING_MARK 2 39 | #define STATE_TIMING_SPACE 3 40 | #define STATE_FINISHED 4 41 | #define STATE_RUNNING 5 42 | typedef uint8_t currentState_t; 43 | /* The structure contains information used by the ISR routines. Because we cannot 44 | * pass parameters to an ISR, it must be global. Values which can be changed by 45 | * the ISR but are accessed outside the ISR must be volatile. 46 | */ 47 | typedef struct { 48 | //These next 4 fields are initialized by the receiver class and unlikely to change once 49 | //they have been initialized. Only change them on the fly at your own peril. 50 | uint8_t recvPin; // pin number or interrupt number for receiver 51 | bool enableAutoResume; //ISR can copy data to decodeBuffer and restart by itself 52 | uint16_t frameTimeout; //Maximum length of a SPACE before we decide the frame has ended 53 | //Used by IRrecv only 54 | uint16_t frameTimeoutTicks;// = frameTimeout/USEC_PER_TICKS 55 | bool enableBlinkLED; 56 | 57 | //These fields are both read and written inside and outside ISRs. Must be volatile. 58 | volatile bool decoderWantsData; //tells ISR previous decode is finished. Buffer available. 59 | volatile bool newDataAvailable; //ISR flag informs getResults that data is available. 60 | volatile bool didAutoResume; //ISR tells getResults we already copied, just do math. 61 | //The buffers are filled with timing values by the ISRs. The recvLength is the number of 62 | //entries when the frame is complete. See the note at the end of this file about buffers. 63 | volatile uint16_t recvBuffer[RECV_BUF_LENGTH]; 64 | // volatile uint16_t* recvBuffer; 65 | volatile bufIndex_t recvLength; 66 | //These next two fields are how the receiver communicates with the decoder. Previously 67 | //this was accomplished by passing to the receiver a pointer to the decoder in getResults. 68 | //However with auto resume we now may need to communicate before getResults is called. 69 | //The decoderBuffer pointer is maintained by the decoder. It points to where the 70 | //decoder wants the data put by the receiver. It will point to either recvGlobal.recvBuffer 71 | //or an external buffer provided by the user via useExtnBuf. The decodeLength 72 | //is set by the receiver telling the decoder the data length. 73 | volatile uint16_t* decodeBuffer; 74 | volatile bufIndex_t decodeLength; 75 | //This field accumulates the elapsed time of a MARK or SPACE. IRrecv uses it only inside 76 | //the ISR however IRrecvPCI accesses it outside the ISR. Therefore it is volatile 77 | //and because it is multi-byte it will need atomic guards when accessed outside the ISR. 78 | volatile uint32_t timer; // state timer, counts 50uS ticks.(and other uses) 79 | //Used by both IRrecv and IRrecvPCI. 80 | volatile currentState_t currentState; // state machine Legal values defined above. 81 | } 82 | recvGlobal_t; 83 | extern recvGlobal_t recvGlobal; //declared in IRLibRecvBase.cpp 84 | 85 | /**** NOTE CONCERNING BUFFER NAMES AND VOLATILITY 86 | * In versions of IRLib prior to 2.0 we had the capability to declare an external 87 | * buffer so that the receiver could resume receiving while the decoding was taking place. 88 | * However it was up to the decoder to notice that the data had been received via a call to 89 | * getResults() and it had to tell the receiver to resume. Starting with version 2.0 90 | * it is now possible that the receiver can automatically copy the data to the external 91 | * buffer and auto resume. Rather than using names like rawbuf1 and rawbuf2 we have come 92 | * up with a new naming system. Also irparams wasn't the most descriptive name 93 | * ever conceived. Here is our new naming system which we hope is slightly less confusing. 94 | * 95 | * First irparams was a structure that contained global variables used by the receiver ISR. 96 | * They should not be part of the receiver class because you can't pass parameters 97 | * to an ISR. We think recvGlobal is a better name. 98 | * 99 | * Previously the ISR did not need access to any external buffer so it only needed one 100 | * buffer and one length variable. If there was an external buffer, only the decoder 101 | * needed to access it. Now the receiver and ISR needs access to that external buffer 102 | * in order to implement auto resume. Therefore the extra buffer needs to be linked 103 | * to recvGlobal as well. The receiver puts the data in recvGlobal.recvBuffer and it's 104 | * length is in recvGlobal.recvLength. It is for the receiver's internal use. 105 | * Additionally we have "decodeBuffer" and "decodeLength" which 106 | * are defined as where the decoder wants the receiver to put its data. The decoder 107 | * decides where decodeBuffer points. The receiver puts the data at that address 108 | * and has no idea where it points. The receiver puts the length in decodeLength. 109 | * It is the receiver's responsibility to copy the data from recvBuffer to decodeBuffer. 110 | * The math is always done in getResults however deciding when to do the copying is 111 | * a bit more complicated. If we are doing auto resume, we do a bufcpy to copy as 112 | * quickly as possible and defer the math until the actual poll to getResults. 113 | * The getResults needs to know whether it should copy or just do the math in place. 114 | * If you determine that by the flag didAutoResume. 115 | * 116 | * Now we tackle the volatile issue of "volatile". Aptly named because it starts flame wars. 117 | * In general the rule is, if data is to be accessed inside and outside an ISR you need to 118 | * add the volatile qualifier to its definition. This ensures that the compiler does not 119 | * optimize the code in such a way that a bad copy of a variable might be used. It forces 120 | * the compiler to fetch the data every time he uses it and not to store it in a register. 121 | * We are going to presume that our ISRs never interrupt themselves. I believe the volatile 122 | * qualifier may not be necessary because the decoder is only accessing the data once the 123 | * receiver is finished working with it. The only items that really need to be volatile 124 | * are some of the flags. However making the buffer volatile does not seem to measurably 125 | * slowdown the decoding process (I ran some tests). So as part of "good programming 126 | * practices we are marking the buffers and lengths as volatile just in case. We need not 127 | * use atomic blocks to access the buffer except in very rare cases. 128 | */ 129 | #define DEBUG_VALUE(l, v) Serial.print(l); Serial.print(":"); Serial.println(v,DEC); 130 | #endif 131 | -------------------------------------------------------------------------------- /src/IRLibCombo.h: -------------------------------------------------------------------------------- 1 | /* IRLibCombo.h 2 | * Part of IRLib Library for Arduino receiving, decoding, and sending 3 | * infrared signals. See COPYRIGHT.txt and LICENSE.txt for more information. 4 | */ 5 | /* 6 | * This file is for creating a customer decode or send class which contains only 7 | * the protocols that you will actually use. At the top of your sketch you should 8 | * include the Send and/or Decode base modules followed by at least one or more 9 | * protocol module. Then conclude with this module. 10 | * WARNING: The lowest numbered protocol which you are using MUST be included first. 11 | * The remaining protocol modules technically could be in any order however we 12 | * recommend that you maintain numerical order because you might at some point 13 | * comment out the top one and then the lowest would not be first causing an error. 14 | * 15 | * Here is an example... 16 | * 17 | * #include //Only include if you are sending 18 | * #include //Only include if you are decoding 19 | * #include //Include at least one protocol 20 | * #include //Include as many as you want 21 | * #include //Include this file 22 | * IRdecode My_Decoder; //declare an instance of the decoder if needed 23 | * IRsend My_Sender; //declarative sense of the sending routine if needed 24 | * //The rest of your code goes here 25 | */ 26 | 27 | #ifndef IRLIB_COMBO_H 28 | #define IRLIB_COMBO_H 29 | 30 | #ifndef IRLIB_HASHRAW_H 31 | #define IR_SEND_RAW 32 | #define IR_DECODE_HASH 33 | #define PV_IR_DECODE_HASH 34 | #define PV_IR_SEND_RAW 35 | #endif 36 | #ifndef IRLIB_PROTOCOL_01_H 37 | #define IR_SEND_PROTOCOL_01 38 | #define IR_DECODE_PROTOCOL_01 39 | #define PV_IR_DECODE_PROTOCOL_01 40 | #define PV_IR_SEND_PROTOCOL_01 41 | #endif 42 | #ifndef IRLIB_PROTOCOL_02_H 43 | #define IR_SEND_PROTOCOL_02 44 | #define IR_DECODE_PROTOCOL_02 45 | #define PV_IR_DECODE_PROTOCOL_02 46 | #define PV_IR_SEND_PROTOCOL_02 47 | #endif 48 | #ifndef IRLIB_PROTOCOL_03_H 49 | #define IR_SEND_PROTOCOL_03 50 | #define IR_DECODE_PROTOCOL_03 51 | #define PV_IR_DECODE_PROTOCOL_03 52 | #define PV_IR_SEND_PROTOCOL_03 53 | #endif 54 | #ifndef IRLIB_PROTOCOL_04_H 55 | #define IR_SEND_PROTOCOL_04 56 | #define IR_DECODE_PROTOCOL_04 57 | #define PV_IR_DECODE_PROTOCOL_04 58 | #define PV_IR_SEND_PROTOCOL_04 59 | #endif 60 | #ifndef IRLIB_PROTOCOL_05_H 61 | #define IR_SEND_PROTOCOL_05 62 | #define IR_DECODE_PROTOCOL_05 63 | #define PV_IR_DECODE_PROTOCOL_05 64 | #define PV_IR_SEND_PROTOCOL_05 65 | #endif 66 | #ifndef IRLIB_PROTOCOL_06_H 67 | #define IR_SEND_PROTOCOL_06 68 | #define IR_DECODE_PROTOCOL_06 69 | #define PV_IR_DECODE_PROTOCOL_06 70 | #define PV_IR_SEND_PROTOCOL_06 71 | #endif 72 | #ifndef IRLIB_PROTOCOL_07_H 73 | #define IR_SEND_PROTOCOL_07 74 | #define IR_DECODE_PROTOCOL_07 75 | #define PV_IR_DECODE_PROTOCOL_07 76 | #define PV_IR_SEND_PROTOCOL_07 77 | #endif 78 | #ifndef IRLIB_PROTOCOL_08_H 79 | #define IR_SEND_PROTOCOL_08 80 | #define IR_DECODE_PROTOCOL_08 81 | #define PV_IR_DECODE_PROTOCOL_08 82 | #define PV_IR_SEND_PROTOCOL_08 83 | #endif 84 | #ifndef IRLIB_PROTOCOL_09_H 85 | #define IR_SEND_PROTOCOL_09 86 | #define IR_DECODE_PROTOCOL_09 87 | #define PV_IR_DECODE_PROTOCOL_09 88 | #define PV_IR_SEND_PROTOCOL_09 89 | #endif 90 | #ifndef IRLIB_PROTOCOL_10_H 91 | #define IR_SEND_PROTOCOL_10 92 | #define IR_DECODE_PROTOCOL_10 93 | #define PV_IR_DECODE_PROTOCOL_10 94 | #define PV_IR_SEND_PROTOCOL_10 95 | #endif 96 | #ifndef IRLIB_PROTOCOL_11_H 97 | #define IR_SEND_PROTOCOL_11 98 | #define IR_DECODE_PROTOCOL_11 99 | #define PV_IR_DECODE_PROTOCOL_11 100 | #define PV_IR_SEND_PROTOCOL_11 101 | #endif 102 | #ifndef IRLIB_PROTOCOL_12_H 103 | #define IR_SEND_PROTOCOL_12 104 | #define IR_DECODE_PROTOCOL_12 105 | #define PV_IR_DECODE_PROTOCOL_12 106 | #define PV_IR_SEND_PROTOCOL_12 107 | #endif 108 | #ifndef IRLIB_PROTOCOL_13_H 109 | #define IR_SEND_PROTOCOL_13 110 | #define IR_DECODE_PROTOCOL_13 111 | #define PV_IR_DECODE_PROTOCOL_13 112 | #define PV_IR_SEND_PROTOCOL_13 113 | #endif 114 | #ifndef IRLIB_PROTOCOL_14_H 115 | #define IR_SEND_PROTOCOL_14 116 | #define IR_DECODE_PROTOCOL_14 117 | #define PV_IR_DECODE_PROTOCOL_14 118 | #define PV_IR_SEND_PROTOCOL_14 119 | #endif 120 | //Add additional protocols 15, 16, etc. above. 121 | 122 | //Note protocol 90- 99 for sample code that will be unsupported in the final version. 123 | //See IRLibProtocols/unsupported/IRLib_P90_Unsupported.h for details 124 | #ifndef IRLIB_PROTOCOL_90_H 125 | #define IR_SEND_PROTOCOL_90 126 | #define IR_DECODE_PROTOCOL_90 127 | #define PV_IR_DECODE_PROTOCOL_90 128 | #define PV_IR_SEND_PROTOCOL_90 129 | #endif 130 | #ifndef IRLIB_PROTOCOL_91_H 131 | #define IR_SEND_PROTOCOL_91 132 | #define IR_DECODE_PROTOCOL_91 133 | #define PV_IR_DECODE_PROTOCOL_91 134 | #define PV_IR_SEND_PROTOCOL_91 135 | #endif 136 | #ifndef IRLIB_PROTOCOL_92_H 137 | #define IR_SEND_PROTOCOL_92 138 | #define IR_DECODE_PROTOCOL_92 139 | #define PV_IR_DECODE_PROTOCOL_92 140 | #define PV_IR_SEND_PROTOCOL_92 141 | #endif 142 | /* 143 | * You may add additional protocols by copying and modifying the previous six lines. 144 | * You must also add appropriate macros in each segment below. Be sure to maintain 145 | * numerical order. Also the final entry in each list MUST BE the Hash_Raw version. 146 | */ 147 | #ifdef IRLIBDECODEBASE_H 148 | class IRdecode: 149 | PV_IR_DECODE_PROTOCOL_01 150 | PV_IR_DECODE_PROTOCOL_02 151 | PV_IR_DECODE_PROTOCOL_03 152 | PV_IR_DECODE_PROTOCOL_04 153 | PV_IR_DECODE_PROTOCOL_05 154 | PV_IR_DECODE_PROTOCOL_06 155 | PV_IR_DECODE_PROTOCOL_07 156 | PV_IR_DECODE_PROTOCOL_08 157 | PV_IR_DECODE_PROTOCOL_09 158 | PV_IR_DECODE_PROTOCOL_10 159 | PV_IR_DECODE_PROTOCOL_11 160 | PV_IR_DECODE_PROTOCOL_12 161 | PV_IR_DECODE_PROTOCOL_13 162 | PV_IR_DECODE_PROTOCOL_14 163 | PV_IR_DECODE_PROTOCOL_90 //Add additional 15, 16 etc. above this 164 | PV_IR_DECODE_PROTOCOL_91 165 | PV_IR_DECODE_PROTOCOL_92 166 | PV_IR_DECODE_HASH //Must be last one. 167 | { 168 | public: 169 | bool decode(void) { 170 | IR_DECODE_PROTOCOL_01 171 | IR_DECODE_PROTOCOL_02 172 | IR_DECODE_PROTOCOL_03 173 | IR_DECODE_PROTOCOL_04 174 | IR_DECODE_PROTOCOL_05 175 | IR_DECODE_PROTOCOL_06 176 | IR_DECODE_PROTOCOL_07 177 | IR_DECODE_PROTOCOL_08 178 | IR_DECODE_PROTOCOL_09 179 | IR_DECODE_PROTOCOL_10 180 | IR_DECODE_PROTOCOL_11 181 | IR_DECODE_PROTOCOL_12 182 | IR_DECODE_PROTOCOL_13 183 | IR_DECODE_PROTOCOL_14 184 | IR_DECODE_PROTOCOL_90 //Add additional 15, 16 etc. above this 185 | IR_DECODE_PROTOCOL_91 186 | IR_DECODE_PROTOCOL_92 187 | IR_DECODE_HASH //Must be last one. 188 | return false; 189 | }; 190 | #ifdef IRLIB_PROTOCOL_12_H 191 | void dumpResults(bool verbose=true) { 192 | if(protocolNum==12) { 193 | IRdecodeCYKM::dumpResults(); 194 | if(verbose)IRdecodeBase::dumpResults(true); 195 | } else { 196 | IRdecodeBase::dumpResults(verbose); 197 | } 198 | } 199 | #endif 200 | }; 201 | #endif //IRLIBDECODEBASE_H 202 | 203 | #ifdef IRLIBSENDBASE_H 204 | class IRsend: 205 | PV_IR_SEND_PROTOCOL_01 206 | PV_IR_SEND_PROTOCOL_02 207 | PV_IR_SEND_PROTOCOL_03 208 | PV_IR_SEND_PROTOCOL_04 209 | PV_IR_SEND_PROTOCOL_05 210 | PV_IR_SEND_PROTOCOL_06 211 | PV_IR_SEND_PROTOCOL_07 212 | PV_IR_SEND_PROTOCOL_08 213 | PV_IR_SEND_PROTOCOL_09 214 | PV_IR_SEND_PROTOCOL_10 215 | PV_IR_SEND_PROTOCOL_11 216 | PV_IR_SEND_PROTOCOL_12 217 | PV_IR_SEND_PROTOCOL_13 218 | PV_IR_SEND_PROTOCOL_14 219 | PV_IR_SEND_PROTOCOL_90 //Add additional 15, 16 etc. above this 220 | PV_IR_SEND_PROTOCOL_91 221 | PV_IR_SEND_PROTOCOL_92 222 | PV_IR_SEND_RAW //Must be last one. 223 | { 224 | public: 225 | void send(uint8_t protocolNum, uint32_t data, uint16_t data2=0, uint8_t khz=38) { 226 | if(khz==0)khz=38; 227 | switch(protocolNum) { 228 | IR_SEND_PROTOCOL_01 229 | IR_SEND_PROTOCOL_02 230 | IR_SEND_PROTOCOL_03 231 | IR_SEND_PROTOCOL_04 232 | IR_SEND_PROTOCOL_05 233 | IR_SEND_PROTOCOL_06 234 | IR_SEND_PROTOCOL_07 235 | IR_SEND_PROTOCOL_08 236 | IR_SEND_PROTOCOL_09 237 | IR_SEND_PROTOCOL_10 238 | IR_SEND_PROTOCOL_11 239 | IR_SEND_PROTOCOL_12 240 | IR_SEND_PROTOCOL_13 241 | IR_SEND_PROTOCOL_14 242 | IR_SEND_PROTOCOL_90 //Add additional 15, 16 etc. above this 243 | IR_SEND_PROTOCOL_91 244 | IR_SEND_PROTOCOL_92 245 | IR_SEND_RAW //Must be last one. 246 | } 247 | } 248 | }; 249 | #endif //IRLIBSENDBASE_H 250 | 251 | #endif //IRLIB_COMBO_H 252 | --------------------------------------------------------------------------------