Исходная библиотека IRremote

This commit is contained in:
klassents committed 2025-01-25 10:33:13 +07:00
1 parent 2bda6824d5
commit e7eb7babf3
122 files changed
+38600

No files matched your search

@@ -0,0 +1,193 @@
/*
* DemoIRCommandMapping.h
*
* IR remote button codes, strings, and functions to call
*
* Copyright (C) 2019-2022 Armin Joachimsmeyer
* armin.joachimsmeyer@gmail.com
*
*/
#ifndef _IR_COMMAND_MAPPING_H
#define _IR_COMMAND_MAPPING_H
#include <Arduino.h>
//#include "Commands.h" // includes all the commands used in the mapping arrays below
/*
* !!! Choose your remote !!!
*/
//#define USE_KEYES_REMOTE_CLONE With number pad and direction control switched, will be taken as default
//#define USE_KEYES_REMOTE
#if !defined(USE_KEYES_REMOTE) && !defined(USE_KEYES_REMOTE_CLONE)
#define USE_KEYES_REMOTE_CLONE // the one you can buy at aliexpress
#endif
#if (defined(USE_KEYES_REMOTE) && defined(USE_KEYES_REMOTE_CLONE))
#error "Please choose only one remote for compile"
#endif
#if defined(USE_KEYES_REMOTE_CLONE)
#define IR_REMOTE_NAME "KEYES_CLONE"
// Codes for the KEYES CLONE remote control with 17 keys with number pad above direction control
#if defined(USE_IRMP_LIBRARY)
#define IR_ADDRESS 0xFF00 // IRMP interprets NEC addresses always as 16 bit
#else
#define IR_ADDRESS 0x00
#endif
#define IR_UP 0x18
#define IR_DOWN 0x52
#define IR_RIGHT 0x5A
#define IR_LEFT 0x08
#define IR_OK 0x1C
#define IR_1 0x45
#define IR_2 0x46
#define IR_3 0x47
#define IR_4 0x44
#define IR_5 0x40
#define IR_6 0x43
#define IR_7 0x07
#define IR_8 0x15
#define IR_9 0x09
#define IR_0 0x19
#define IR_STAR 0x16
#define IR_HASH 0x0D
/*
* SECOND:
* IR button to command mapping for better reading. IR buttons should only referenced here.
*/
#define COMMAND_ON IR_UP
#define COMMAND_OFF IR_DOWN
#define COMMAND_INCREASE_BLINK IR_RIGHT
#define COMMAND_DECREASE_BLINK IR_LEFT
#define COMMAND_START IR_OK
#define COMMAND_STOP IR_HASH
#define COMMAND_RESET IR_STAR
#define COMMAND_BLINK IR_0
#define COMMAND_TONE1 IR_1
#define COMMAND_TONE2 IR_2
#define COMMAND_TONE3 IR_3
//#define IR_4
//#define IR_5
//#define IR_6
//#define IR_7
//#define IR_8
//#define IR_9
#endif
#if defined(USE_KEYES_REMOTE)
#define IR_REMOTE_NAME "KEYES"
/*
* FIRST:
* IR code to button mapping for better reading. IR codes should only referenced here.
*/
// Codes for the KEYES remote control with 17 keys and direction control above number pad
#if defined(USE_IRMP_LIBRARY)
#define IR_ADDRESS 0xFF00 // IRMP interprets NEC addresses always as 16 bit
#else
#define IR_ADDRESS 0x00
#endif
#define IR_UP 0x46
#define IR_DOWN 0x15
#define IR_RIGHT 0x43
#define IR_LEFT 0x44
#define IR_OK 0x40
#define IR_1 0x16
#define IR_2 0x19
#define IR_3 0x0D
#define IR_4 0x0C
#define IR_5 0x18
#define IR_6 0x5E
#define IR_7 0x08
#define IR_8 0x1C
#define IR_9 0x5A
#define IR_0 0x52
#define IR_STAR 0x42
#define IR_HASH 0x4A
/*
* SECOND:
* IR button to command mapping for better reading. IR buttons should only referenced here.
*/
#define COMMAND_ON IR_UP
#define COMMAND_OFF IR_DOWN
#define COMMAND_INCREASE_BLINK IR_RIGHT
#define COMMAND_DECREASE_BLINK IR_LEFT
#define COMMAND_RESET IR_OK
#define COMMAND_STOP IR_HASH
#define COMMAND_STOP IR_STAR
#define COMMAND_BLINK IR_0
#define COMMAND_TONE2 IR_1
#define COMMAND_TONE1 IR_2
#define COMMAND_TONE2 IR_3
#define COMMAND_TONE2 IR_4
#define COMMAND_TONE2 IR_5
#define COMMAND_TONE2 IR_6
#define COMMAND_TONE2 IR_7
#define COMMAND_TONE2 IR_8
#define COMMAND_TONE2 IR_9
#endif
/*
* THIRD:
* Main mapping of commands to C functions
*/
// IR strings of functions for output
static const char LEDon[] PROGMEM ="LED on";
static const char LEDoff[] PROGMEM ="LED off";
static const char blink20times[] PROGMEM ="blink 20 times";
static const char blinkStart[] PROGMEM ="blink start";
static const char increaseBlink[] PROGMEM ="increase blink frequency";
static const char decreaseBlink[] PROGMEM ="decrease blink frequency";
static const char tone2200[] PROGMEM ="tone 2200";
static const char tone1800[] PROGMEM ="tone 1800";
static const char printMenu[] PROGMEM ="printMenu";
static const char reset[] PROGMEM ="reset";
static const char stop[] PROGMEM ="stop";
// not used yet
static const char test[] PROGMEM ="test";
static const char pattern[] PROGMEM ="pattern";
static const char unknown[] PROGMEM ="unknown";
/*
* Main mapping array of commands to C functions and command strings
*/
const struct IRToCommandMappingStruct IRMapping[] = { /**/
{ COMMAND_BLINK, IR_COMMAND_FLAG_BLOCKING, &doLedBlink20times, blink20times }, /**/
{ COMMAND_STOP, IR_COMMAND_FLAG_BLOCKING, &doStop, stop },
/*
* Short commands, which can be executed always
*/
{ COMMAND_TONE1, IR_COMMAND_FLAG_BLOCKING, &doTone1800, tone1800 }, /**/
{ COMMAND_TONE3, IR_COMMAND_FLAG_BLOCKING, &doPrintMenu, printMenu }, /**/
{ COMMAND_ON, IR_COMMAND_FLAG_NON_BLOCKING, &doLedOn, LEDon }, /**/
{ COMMAND_OFF, IR_COMMAND_FLAG_NON_BLOCKING, &doLedOff, LEDoff }, /**/
{ COMMAND_START, IR_COMMAND_FLAG_NON_BLOCKING, &doLedBlinkStart, blinkStart }, /**/
{ COMMAND_RESET, IR_COMMAND_FLAG_NON_BLOCKING, &doResetBlinkFrequency, reset },
/*
* Repeatable short commands
*/
{ COMMAND_TONE2, IR_COMMAND_FLAG_REPEATABLE_NON_BLOCKING, &doTone2200, tone2200 }, /**/
{ COMMAND_INCREASE_BLINK, IR_COMMAND_FLAG_REPEATABLE_NON_BLOCKING, &doIncreaseBlinkFrequency, increaseBlink }, /**/
{ COMMAND_DECREASE_BLINK, IR_COMMAND_FLAG_REPEATABLE_NON_BLOCKING, &doDecreaseBlinkFrequency, decreaseBlink } };
#endif // _IR_COMMAND_MAPPING_H
@@ -0,0 +1,138 @@
/*
* IRCommandDispatcher.h
*
* Library to process IR commands by calling functions specified in a mapping array.
*
* To run this example you need to install the "IRremote" or "IRMP" library under "Tools -> Manage Libraries..." or "Ctrl+Shift+I"
*
* Copyright (C) 2019-2024 Armin Joachimsmeyer
* armin.joachimsmeyer@gmail.com
*
* This file is part of ServoEasing https://github.com/ArminJo/ServoEasing.
* This file is part of IRMP https://github.com/IRMP-org/IRMP.
* This file is part of Arduino-IRremote https://github.com/Arduino-IRremote/Arduino-IRremote.
*
* IRCommandDispatcher is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/gpl.html>.
*/
#ifndef _IR_COMMAND_DISPATCHER_H
#define _IR_COMMAND_DISPATCHER_H
#include <stdint.h>
/*
* For command mapping file
*/
#define IR_COMMAND_FLAG_BLOCKING 0x00 // default - blocking command, repeat not accepted, only one command at a time. Stops an already running command.
#define IR_COMMAND_FLAG_REPEATABLE 0x01 // repeat accepted
#define IR_COMMAND_FLAG_NON_BLOCKING 0x02 // Non blocking (short) command that can be processed any time and may interrupt other IR commands - used for stop, set direction etc.
#define IR_COMMAND_FLAG_REPEATABLE_NON_BLOCKING (IR_COMMAND_FLAG_REPEATABLE | IR_COMMAND_FLAG_NON_BLOCKING)
#define IR_COMMAND_FLAG_BEEP 0x04 // Do a single short beep before executing command. May not be useful for short or repeating commands.
#define IR_COMMAND_FLAG_BLOCKING_BEEP (IR_COMMAND_FLAG_BLOCKING | IR_COMMAND_FLAG_BEEP)
#if !defined(IS_STOP_REQUESTED)
#define IS_STOP_REQUESTED IRDispatcher.requestToStopReceived
#endif
#if !defined(RETURN_IF_STOP)
#define RETURN_IF_STOP if (IRDispatcher.requestToStopReceived) return
#endif
#if !defined(BREAK_IF_STOP)
#define BREAK_IF_STOP if (IRDispatcher.requestToStopReceived) break
#endif
#if !defined(DELAY_AND_RETURN_IF_STOP)
#define DELAY_AND_RETURN_IF_STOP(aDurationMillis) if (IRDispatcher.delayAndCheckForStop(aDurationMillis)) return
#endif
// Basic mapping structure
struct IRToCommandMappingStruct {
#if defined(IR_COMMAND_HAS_MORE_THAN_8_BIT)
uint16_t IRCode;
#else
uint8_t IRCode;
#endif
uint8_t Flags;
void (*CommandToCall)();
const char *CommandString;
};
struct IRDataForCommandDispatcherStruct {
uint16_t address; // to distinguish between multiple senders
#if defined(IR_COMMAND_HAS_MORE_THAN_8_BIT)
uint16_t command;
#else
uint8_t command;
#endif
bool isRepeat;
uint32_t MillisOfLastCode; // millis() of last IR command -including repeats!- received - for timeouts etc.
volatile bool isAvailable; // flag for a polling interpreting function, that a new command has arrived. Is set true by library and set false by main loop.
};
/*
* Special codes (hopefully) not sent by the remote - otherwise please redefine it here
*/
#if defined(IR_COMMAND_HAS_MORE_THAN_8_BIT)
#define COMMAND_EMPTY 0xFFFF // code no command
#else
#define COMMAND_EMPTY 0xFF // code no command
#endif
class IRCommandDispatcher {
public:
void init();
void printIRInfo(Print *aSerial);
bool checkAndRunNonBlockingCommands();
bool checkAndRunSuspendedBlockingCommands();
#if defined(IR_COMMAND_HAS_MORE_THAN_8_BIT)
void setNextBlockingCommand(uint16_t aBlockingCommandToRunNext);
#else
void setNextBlockingCommand(uint8_t aBlockingCommandToRunNext);
#endif
bool delayAndCheckForStop(uint16_t aDelayMillis);
// The main dispatcher function
void checkAndCallCommand(bool aCallBlockingCommandImmediately);
void printIRCommandString(Print *aSerial);
void setRequestToStopReceived(bool aRequestToStopReceived = true);
#if defined(IR_COMMAND_HAS_MORE_THAN_8_BIT)
uint16_t currentBlockingCommandCalled = COMMAND_EMPTY; // The code for the current called command
uint16_t lastBlockingCommandCalled = COMMAND_EMPTY; // The code for the last called command. Can be evaluated by main loop
uint16_t BlockingCommandToRunNext = COMMAND_EMPTY; // Storage for command currently suspended to allow the current command to end, before it is called by main loop
#else
uint8_t currentBlockingCommandCalled = COMMAND_EMPTY; // The code for the current called command
uint8_t lastBlockingCommandCalled = COMMAND_EMPTY; // The code for the last called command. Can be evaluated by main loop
uint8_t BlockingCommandToRunNext = COMMAND_EMPTY; // Storage for command currently suspended to allow the current command to end, before it is called by main loop
#endif
bool justCalledBlockingCommand = false; // Flag that a blocking command was received and called - is set before call of command
/*
* Flag for running blocking commands to terminate. To check, you can use "if (IRDispatcher.requestToStopReceived) return;" (available as macro RETURN_IF_STOP).
* It is set if a blocking IR command received, which cannot be executed directly. Can be reset by main loop, if command has stopped.
* It is reset before executing a blocking command.
*/
volatile bool requestToStopReceived;
/*
* This flag must be true, if we have a function, which want to interpret the IR codes by itself e.g. the calibrate function of QuadrupedControl
*/
bool doNotUseDispatcher = false;
struct IRDataForCommandDispatcherStruct IRReceivedData;
};
extern IRCommandDispatcher IRDispatcher;
#endif // _IR_COMMAND_DISPATCHER_H
@@ -0,0 +1,366 @@
/*
* IRCommandDispatcher.hpp
*
* Library to process IR commands by calling functions specified in a mapping array.
* Commands can be tagged as blocking or non blocking.
*
* To run this example you need to install the "IRremote" or "IRMP" library.
* Install it under "Tools -> Manage Libraries..." or "Ctrl+Shift+I"
*
* The IR library calls a callback function, which executes a non blocking command directly in ISR (Interrupt Service Routine) context!
* A blocking command is stored and sets a stop flag for an already running blocking function to terminate.
* The blocking command can in turn be executed by main loop by calling IRDispatcher.checkAndRunSuspendedBlockingCommands().
*
* Copyright (C) 2019-2024 Armin Joachimsmeyer
* armin.joachimsmeyer@gmail.com
*
* This file is part of ServoEasing https://github.com/ArminJo/ServoEasing.
* This file is part of IRMP https://github.com/IRMP-org/IRMP.
* This file is part of Arduino-IRremote https://github.com/Arduino-IRremote/Arduino-IRremote.
*
* IRCommandDispatcher is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/gpl.html>.
*/
/*
* Program behavior is modified by the following macros
* USE_TINY_IR_RECEIVER
* USE_IRMP_LIBRARY
* IR_COMMAND_HAS_MORE_THAN_8_BIT
*/
#ifndef _IR_COMMAND_DISPATCHER_HPP
#define _IR_COMMAND_DISPATCHER_HPP
#include <Arduino.h>
#include "IRCommandDispatcher.h"
#if !defined(STR_HELPER)
#define STR_HELPER(x) #x
#define STR(x) STR_HELPER(x)
#endif
/*
* Enable this to see information on each call.
* Since there should be no library which uses Serial, it should only be enabled for development purposes.
*/
#if defined(INFO) && !defined(LOCAL_INFO)
#define LOCAL_INFO
#else
//#define LOCAL_INFO // This enables info output only for this file
#endif
#if defined(DEBUG) && !defined(LOCAL_DEBUG)
#define LOCAL_DEBUG
// Propagate debug level
#define LOCAL_INFO
#else
//#define LOCAL_DEBUG // This enables debug output only for this file
#endif
IRCommandDispatcher IRDispatcher;
#if defined(LOCAL_INFO)
#define CD_INFO_PRINT(...) Serial.print(__VA_ARGS__);
#define CD_INFO_PRINTLN(...) Serial.println(__VA_ARGS__);
#else
#define CD_INFO_PRINT(...) void();
#define CD_INFO_PRINTLN(...) void();
#endif
#if defined(USE_TINY_IR_RECEIVER)
#define USE_CALLBACK_FOR_TINY_RECEIVER // Call the fixed function "void handleReceivedTinyIRData()" each time a frame or repeat is received.
#include "TinyIRReceiver.hpp" // included in "IRremote" library
void IRCommandDispatcher::init() {
initPCIInterruptForTinyReceiver();
}
/*
* @return true, if IR Receiver is attached
*/
void IRCommandDispatcher::printIRInfo(Print *aSerial) {
aSerial->println();
// For available IR commands see IRCommandMapping.h https://github.com/ArminJo/PWMMotorControl/blob/master/examples/SmartCarFollower/IRCommandMapping.h
aSerial->print(F("Listening to IR remote of type "));
aSerial->print(IR_REMOTE_NAME);
aSerial->println(F(" at pin " STR(IR_RECEIVE_PIN)));
}
/*
* This is the TinyReceiver callback function, which is called if a complete command was received
* It checks for right address and then call the dispatcher
*/
# if defined(ESP8266) || defined(ESP32)
IRAM_ATTR
# endif
void handleReceivedTinyIRData() {
IRDispatcher.IRReceivedData.address = TinyIRReceiverData.Address;
IRDispatcher.IRReceivedData.command = TinyIRReceiverData.Command;
IRDispatcher.IRReceivedData.isRepeat = TinyIRReceiverData.Flags & IRDATA_FLAGS_IS_REPEAT;
IRDispatcher.IRReceivedData.MillisOfLastCode = millis();
# if defined(LOCAL_INFO)
printTinyReceiverResultMinimal(&Serial);
# endif
if (TinyIRReceiverData.Address == IR_ADDRESS) { // IR_ADDRESS is defined in *IRCommandMapping.h
IRDispatcher.IRReceivedData.isAvailable = true;
if(!IRDispatcher.doNotUseDispatcher) {
/*
* Only short (non blocking) commands are executed directly in ISR (Interrupt Service Routine) context,
* others are stored for main loop which calls checkAndRunSuspendedBlockingCommands()
*/
IRDispatcher.checkAndCallCommand(false);
}
} else {
CD_INFO_PRINT(F("Wrong address. Expected 0x"));
CD_INFO_PRINTLN(IR_ADDRESS, HEX);
}
}
#elif defined(USE_IRMP_LIBRARY)
# if !defined(IRMP_USE_COMPLETE_CALLBACK)
# error IRMP_USE_COMPLETE_CALLBACK must be activated for IRMP library
# endif
void IRCommandDispatcher::init() {
irmp_init();
}
/*
* This is the callback function, which is called if a complete command was received
*/
#if defined(ESP8266) || defined(ESP32)
IRAM_ATTR
#endif
void handleReceivedIRData() {
IRMP_DATA tTeporaryData;
irmp_get_data(&tTeporaryData);
IRDispatcher.IRReceivedData.address = tTeporaryData.address;
IRDispatcher.IRReceivedData.command = tTeporaryData.command;
IRDispatcher.IRReceivedData.isRepeat = tTeporaryData.flags & IRMP_FLAG_REPETITION;
IRDispatcher.IRReceivedData.MillisOfLastCode = millis();
CD_INFO_PRINT(F("A=0x"));
CD_INFO_PRINT(IRDispatcher.IRReceivedData.address, HEX);
CD_INFO_PRINT(F(" C=0x"));
CD_INFO_PRINT(IRDispatcher.IRReceivedData.command, HEX);
if (IRDispatcher.IRReceivedData.isRepeat) {
CD_INFO_PRINT(F("R"));
}
CD_INFO_PRINTLN();
// To enable delay() for commands
# if !defined(ARDUINO_ARCH_MBED)
interrupts(); // be careful with always executable commands which lasts longer than the IR repeat duration.
# endif
if (IRDispatcher.IRReceivedData.address == IR_ADDRESS) {
IRDispatcher.checkAndCallCommand(true);
} else {
CD_INFO_PRINT(F("Wrong address. Expected 0x"));
CD_INFO_PRINTLN(IR_ADDRESS, HEX);
}
}
#endif // elif defined(USE_IRMP_LIBRARY)
/*
* The main dispatcher function called by IR-ISR, main loop and checkAndRunSuspendedBlockingCommands()
* Non blocking commands are executed directly, blocking commands are executed if enabled by parameter and no other command is just running.
* Otherwise request to stop (requestToStopReceived) is set and command is stored for main loop to be later execute by checkAndRunSuspendedBlockingCommands().
* Sets flags justCalledRegularIRCommand, executingBlockingCommand, requestToStopReceived
* @param aCallBlockingCommandImmediately Run blocking command directly, if no other command is just running. Should be false if called by ISR in order not to block ISR.
*/
void IRCommandDispatcher::checkAndCallCommand(bool aCallBlockingCommandImmediately) {
if (IRReceivedData.command == COMMAND_EMPTY) {
return;
}
/*
* Search for command in Array of IRToCommandMappingStruct
*/
for (uint_fast8_t i = 0; i < sizeof(IRMapping) / sizeof(struct IRToCommandMappingStruct); ++i) {
if (IRReceivedData.command == IRMapping[i].IRCode) {
/*
* Command found
*/
#if defined(LOCAL_INFO)
const __FlashStringHelper *tCommandName = reinterpret_cast<const __FlashStringHelper*>(IRMapping[i].CommandString);
#endif
/*
* Check for repeat and if repeat is allowed for the current command
*/
if (IRReceivedData.isRepeat && !(IRMapping[i].Flags & IR_COMMAND_FLAG_REPEATABLE)) {
#if defined(LOCAL_DEBUG)
Serial.print(F("Repeats of command \""));
Serial.print(tCommandName);
Serial.println("\" not accepted");
#endif
return;
}
/*
* Do not accept recursive call of the same command
*/
if (currentBlockingCommandCalled == IRReceivedData.command) {
#if defined(LOCAL_DEBUG)
Serial.print(F("Recursive command \""));
Serial.print(tCommandName);
Serial.println("\" not accepted");
#endif
return;
}
/*
* Execute commands
*/
bool tIsNonBlockingCommand = (IRMapping[i].Flags & IR_COMMAND_FLAG_NON_BLOCKING);
if (tIsNonBlockingCommand) {
// short command here, just call
CD_INFO_PRINT(F("Run non blocking command: "));
CD_INFO_PRINTLN(tCommandName);
#if defined(BUZZER_PIN) && defined(USE_TINY_IR_RECEIVER)
/*
* Do (non blocking) buzzer feedback before command is executed
*/
if(IRMapping[i].Flags & IR_COMMAND_FLAG_BEEP) {
tone(BUZZER_PIN, 2200, 50);
}
#endif
IRMapping[i].CommandToCall();
} else {
/*
* Blocking command here
*/
if (aCallBlockingCommandImmediately && currentBlockingCommandCalled == COMMAND_EMPTY) {
/*
* Here no blocking command was running and we are called from main loop
*/
requestToStopReceived = false; // Do not stop the command executed now
justCalledBlockingCommand = true;
currentBlockingCommandCalled = IRReceivedData.command; // set lock for recursive calls
lastBlockingCommandCalled = IRReceivedData.command; // set history, can be evaluated by main loop
/*
* This call is blocking!!!
*/
CD_INFO_PRINT(F("Run blocking command: "));
CD_INFO_PRINTLN(tCommandName);
#if defined(BUZZER_PIN) && defined(USE_TINY_IR_RECEIVER)
/*
* Do (non blocking) buzzer feedback before command is executed
*/
if(IRMapping[i].Flags & IR_COMMAND_FLAG_BEEP) {
tone(BUZZER_PIN, 2200, 50);
}
#endif
IRMapping[i].CommandToCall();
#if defined(TRACE)
Serial.println(F("End of blocking command"));
#endif
currentBlockingCommandCalled = COMMAND_EMPTY;
} else {
/*
* Called by ISR or another command still running.
* Do not run command directly, but set request to stop to true and store command
* for main loop to execute by checkAndRunSuspendedBlockingCommands()
*/
BlockingCommandToRunNext = IRReceivedData.command;
requestToStopReceived = true; // to stop running command
CD_INFO_PRINT(F("Requested stop and stored blocking command "));
CD_INFO_PRINT(tCommandName);
CD_INFO_PRINTLN(F(" as next command to run."));
}
}
break; // command found
} // if (IRReceivedData.command == IRMapping[i].IRCode)
} // for loop
return;
}
/*
* Intended to be called from main loop
* @return true, if command was called
*/
bool IRCommandDispatcher::checkAndRunSuspendedBlockingCommands() {
/*
* Take last rejected command and call associated function
*/
if (BlockingCommandToRunNext != COMMAND_EMPTY) {
CD_INFO_PRINT(F("Run stored command=0x"));
CD_INFO_PRINTLN(BlockingCommandToRunNext, HEX);
IRReceivedData.command = BlockingCommandToRunNext;
BlockingCommandToRunNext = COMMAND_EMPTY;
IRReceivedData.isRepeat = false;
requestToStopReceived = false; // Do not stop the command executed now
checkAndCallCommand(true);
return true;
}
return false;
}
/*
* Not used internally
*/
#if defined(IR_COMMAND_HAS_MORE_THAN_8_BIT)
void IRCommandDispatcher::setNextBlockingCommand(uint16_t aBlockingCommandToRunNext)
#else
void IRCommandDispatcher::setNextBlockingCommand(uint8_t aBlockingCommandToRunNext)
#endif
{
CD_INFO_PRINT(F("Set next command to run to 0x"));
CD_INFO_PRINTLN(aBlockingCommandToRunNext, HEX);
BlockingCommandToRunNext = aBlockingCommandToRunNext;
requestToStopReceived = true;
}
/*
* Special delay function for the IRCommandDispatcher. Returns prematurely if requestToStopReceived is set.
* To be used in blocking functions as delay
* @return true - as soon as stop received
*/
bool IRCommandDispatcher::delayAndCheckForStop(uint16_t aDelayMillis) {
uint32_t tStartMillis = millis();
do {
if (requestToStopReceived) {
return true;
}
} while (millis() - tStartMillis < aDelayMillis);
return false;
}
void IRCommandDispatcher::printIRCommandString(Print *aSerial) {
for (uint_fast8_t i = 0; i < sizeof(IRMapping) / sizeof(struct IRToCommandMappingStruct); ++i) {
if (IRReceivedData.command == IRMapping[i].IRCode) {
aSerial->println(reinterpret_cast<const __FlashStringHelper*>(IRMapping[i].CommandString));
return;
}
}
aSerial->println(reinterpret_cast<const __FlashStringHelper*>(unknown));
}
void IRCommandDispatcher::setRequestToStopReceived(bool aRequestToStopReceived) {
requestToStopReceived = aRequestToStopReceived;
}
#if defined(LOCAL_DEBUG)
#undef LOCAL_DEBUG
#endif
#if defined(LOCAL_INFO)
#undef LOCAL_INFO
#endif
#endif // _IR_COMMAND_DISPATCHER_HPP
@@ -0,0 +1,282 @@
/*
* IRDispatcherDemo.cpp
*
* Receives NEC IR commands and maps them to different actions by means of a mapping array.
*
* Copyright (C) 2020-2021 Armin Joachimsmeyer
* armin.joachimsmeyer@gmail.com
*
* This file is part of IRMP https://github.com/IRMP-org/IRMP.
* This file is part of Arduino-IRremote https://github.com/Arduino-IRremote/Arduino-IRremote.
*
* IRMP is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/gpl.html>.
*
*/
#include <Arduino.h>
/*
* Choose the library to be used for IR receiving
*/
#define USE_TINY_IR_RECEIVER // Recommended, but only for NEC protocol!!! If disabled and IRMP_INPUT_PIN is defined, the IRMP library is used for decoding
//#define TINY_RECEIVER_USE_ARDUINO_ATTACH_INTERRUPT // Requires additional 112 bytes program memory + 4 bytes RAM
#include "PinDefinitionsAndMore.h" // Define macros for input and output pin etc.
// Some kind of auto detect library if USE_TINY_IR_RECEIVER is deactivated
#if !defined(USE_TINY_IR_RECEIVER)
# if defined(IR_RECEIVE_PIN)
#define USE_TINY_IR_RECEIVER
# elif !defined(USE_IRMP_LIBRARY) && defined(IRMP_INPUT_PIN)
#define USE_IRMP_LIBRARY
# else
#error No IR library selected
# endif
#endif
//#define NO_LED_FEEDBACK_CODE // You can set it here, before the include of IRCommandDispatcher below
#if defined(USE_TINY_IR_RECEIVER)
//#define NO_LED_FEEDBACK_CODE // Activate this if you want to suppress LED feedback or if you do not have a LED. This saves 14 bytes code and 2 clock cycles per interrupt.
#elif defined(USE_IRMP_LIBRARY)
/*
* IRMP version
*/
#define IR_RECEIVE_PIN 2
#define IRMP_USE_COMPLETE_CALLBACK 1 // Enable callback functionality. It is required if IRMP library is used.
#if defined(ALTERNATIVE_IR_FEEDBACK_LED_PIN)
#define FEEDBACK_LED_PIN ALTERNATIVE_IR_FEEDBACK_LED_PIN
#endif
//#define IRMP_ENABLE_PIN_CHANGE_INTERRUPT // Enable interrupt functionality (not for all protocols) - requires around 376 additional bytes of program memory
#define IRMP_PROTOCOL_NAMES 1 // Enable protocol number mapping to protocol strings - requires some program memory. Must before #include <irmp*>
#define IRMP_SUPPORT_NEC_PROTOCOL 1 // this enables only one protocol
//#define IRMP_SUPPORT_KASEIKYO_PROTOCOL 1
# if defined(ALTERNATIVE_IR_FEEDBACK_LED_PIN)
#define IRMP_FEEDBACK_LED_PIN ALTERNATIVE_IR_FEEDBACK_LED_PIN
# endif
/*
* After setting the definitions we can include the code and compile it.
*/
#include <irmp.hpp>
void handleReceivedIRData();
void irmp_tone(uint8_t _pin, unsigned int frequency, unsigned long duration);
#endif // #if defined(USE_IRMP_LIBRARY)
bool doBlink = false;
uint16_t sBlinkDelay = 200;
void doPrintMenu();
void doLedOn();
void doLedOff();
void doIncreaseBlinkFrequency();
void doDecreaseBlinkFrequency();
void doStop();
void doResetBlinkFrequency();
void doLedBlinkStart();
void doLedBlink20times();
void doTone1800();
void doTone2200();
/*
* Set definitions and include IRCommandDispatcher library after the declaration of all commands to map
*/
#define INFO // to see some informative output
#include "IRCommandDispatcher.h" // Only for required declarations, the library itself is included below after the definitions of the commands
#include "DemoIRCommandMapping.h" // must be included before IRCommandDispatcher.hpp to define IR_ADDRESS and IRMapping and string "unknown".
#include "IRCommandDispatcher.hpp"
/*
* Helper macro for getting a macro definition as string
*/
#define STR_HELPER(x) #x
#define STR(x) STR_HELPER(x)
void setup() {
pinMode(LED_BUILTIN, OUTPUT);
Serial.begin(115200);
while (!Serial)
; // Wait for Serial to become available. Is optimized away for some cores.
#if defined(__AVR_ATmega32U4__) || defined(SERIAL_PORT_USBVIRTUAL) || defined(SERIAL_USB) /*stm32duino*/|| defined(USBCON) /*STM32_stm32*/ \
|| defined(SERIALUSB_PID) || defined(ARDUINO_ARCH_RP2040) || defined(ARDUINO_attiny3217)
delay(4000); // To be able to connect Serial monitor after reset or power up and before first print out. Do not wait for an attached Serial Monitor!
#endif
#if defined(ESP8266)
Serial.println(); // to separate it from the internal boot output
#endif
// Just to know which program is running on my Arduino
#if defined(USE_TINY_IR_RECEIVER)
Serial.println(F("START " __FILE__ " from " __DATE__ "\r\nUsing TinyIRReceiver"));
#elif defined(USE_IRREMOTE_LIBRARY)
Serial.println(F("START " __FILE__ " from " __DATE__ "\r\nUsing IRremote library version " VERSION_IRREMOTE));
#elif defined(USE_IRMP_LIBRARY)
Serial.println(F("START " __FILE__ " from " __DATE__ "\r\nUsing IRMP library version " VERSION_IRMP));
#endif
#if !defined(ESP8266) && !defined(NRF5)
// play feedback tone before setup, since it kills the IR timer settings
tone(TONE_PIN, 1000, 50);
delay(50);
#endif
IRDispatcher.init(); // This just calls irmp_init()
#if defined(USE_TINY_IR_RECEIVER)
Serial.println(F("Ready to receive NEC IR signals at pin " STR(IR_RECEIVE_PIN)));
#else
irmp_register_complete_callback_function(&handleReceivedIRData); // fixed function in IRCommandDispatcher.hpp
Serial.print(F("Ready to receive IR signals of protocols: "));
irmp_print_active_protocols(&Serial);
Serial.println(F("at pin " STR(IRMP_INPUT_PIN)));
# if defined(ALTERNATIVE_IR_FEEDBACK_LED_PIN)
irmp_irsnd_LEDFeedback(true); // Enable receive signal feedback at ALTERNATIVE_IR_FEEDBACK_LED_PIN
Serial.println(F("IR feedback pin is " STR(ALTERNATIVE_IR_FEEDBACK_LED_PIN)));
# endif
#endif
Serial.print(F("Listening to commands of IR remote of type "));
Serial.println(IR_REMOTE_NAME);
doPrintMenu();
}
void loop() {
IRDispatcher.checkAndRunSuspendedBlockingCommands();
if (doBlink) {
digitalWrite(LED_BUILTIN, HIGH);
DELAY_AND_RETURN_IF_STOP(sBlinkDelay);
digitalWrite(LED_BUILTIN, LOW);
DELAY_AND_RETURN_IF_STOP(sBlinkDelay);
}
if (millis() - IRDispatcher.IRReceivedData.MillisOfLastCode > 120000) {
//Short beep as remainder, if we did not receive any command in the last 2 minutes
IRDispatcher.IRReceivedData.MillisOfLastCode += 120000;
doTone1800();
}
// delay(10);
}
void doPrintMenu() {
Serial.println();
Serial.println(F("Press 1 for tone 1800 Hz"));
Serial.println(F("Press 2 for tone 2200 Hz"));
Serial.println(F("Press 3 for this Menu"));
Serial.println(F("Press 0 for LED blink 20 times"));
Serial.println(F("Press UP for LED on"));
Serial.println(F("Press DOWN for LED off"));
Serial.println(F("Press OK for LED blink start"));
Serial.println(F("Press RIGHT for LED increase blink frequency"));
Serial.println(F("Press LEFT for LED decrease blink frequency"));
Serial.println(F("Press STAR for reset blink frequency"));
Serial.println(F("Press HASH for stop"));
Serial.println();
}
/*
* Here the actions that are matched to IR keys
*/
void doLedOn() {
digitalWrite(LED_BUILTIN, HIGH);
doBlink = false;
}
void doLedOff() {
digitalWrite(LED_BUILTIN, LOW);
doBlink = false;
}
void doIncreaseBlinkFrequency() {
doBlink = true;
if (sBlinkDelay > 5) {
sBlinkDelay -= sBlinkDelay / 4;
}
}
void doDecreaseBlinkFrequency() {
doBlink = true;
sBlinkDelay += sBlinkDelay / 4;
}
void doStop() {
doBlink = false;
}
void doResetBlinkFrequency() {
sBlinkDelay = 200;
digitalWrite(LED_BUILTIN, LOW);
}
void doLedBlinkStart() {
doBlink = true;
}
/*
* This is a blocking function and checks periodically for stop
*/
void doLedBlink20times() {
for (int i = 0; i < 20; ++i) {
digitalWrite(LED_BUILTIN, HIGH);
DELAY_AND_RETURN_IF_STOP(200);
digitalWrite(LED_BUILTIN, LOW);
DELAY_AND_RETURN_IF_STOP(200);
}
}
void doTone1800() {
#if defined(USE_IRMP_LIBRARY) && !defined(IRMP_ENABLE_PIN_CHANGE_INTERRUPT)
irmp_tone(TONE_PIN, 1800, 200);
#else
# if !defined(ESP8266) && !defined(NRF5) // tone() stops timer 1 for ESP8266
tone(TONE_PIN, 1800, 200);
# endif
#endif
}
void doTone2200() {
#if defined(USE_IRMP_LIBRARY) && !defined(IRMP_ENABLE_PIN_CHANGE_INTERRUPT)
// use IRMP compatible function for tone()
irmp_tone(TONE_PIN, 2200, 50);
#else
# if !defined(ESP8266) && !defined(NRF5) // tone() stops timer 1 for ESP8266
tone(TONE_PIN, 2200, 50);
# endif
#endif
}
#if defined(USE_IRMP_LIBRARY)
/*
* Convenience IRMP compatible wrapper function for Arduino tone() if IRMP_ENABLE_PIN_CHANGE_INTERRUPT is NOT activated
* It currently disables the receiving of repeats
*/
void irmp_tone(uint8_t _pin, unsigned int frequency, unsigned long duration) {
# if defined(__AVR__) && !defined(IRMP_ENABLE_PIN_CHANGE_INTERRUPT)
storeIRTimer();
tone(_pin, frequency, 0);
if (duration == 0) {
duration = 100;
}
delay(duration);
noTone(_pin);
restoreIRTimer();
#elif defined(ESP8266)
// tone() stops timer 1
(void) _pin;
(void) frequency;
(void) duration;
#else
tone(_pin, frequency, duration);
#endif
}
#endif // #if defined(USE_IRMP_LIBRARY)
@@ -0,0 +1,349 @@
/*
* PinDefinitionsAndMore.h
*
* Contains pin definitions for IRremote examples for various platforms
* as well as definitions for feedback LED and tone() and includes
*
* Copyright (C) 2021-2023 Armin Joachimsmeyer
* armin.joachimsmeyer@gmail.com
*
* This file is part of IRremote https://github.com/Arduino-IRremote/Arduino-IRremote.
*
* Arduino-IRremote is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/gpl.html>.
*
*/
/*
* Pin mapping table for different platforms
*
* Platform IR input IR output Tone Core/Pin schema
* --------------------------------------------------------------
* DEFAULT/AVR 2 3 4 Arduino
* ATtinyX5 0|PB0 4|PB4 3|PB3 ATTinyCore
* ATtiny167 3|PA3 2|PA2 7|PA7 ATTinyCore
* ATtiny167 9|PA3 8|PA2 5|PA7 Digispark original core
* ATtiny84 |PB2 |PA4 |PA3 ATTinyCore
* ATtiny88 3|PD3 4|PD4 9|PB1 ATTinyCore
* ATtiny3217 18|PA1 19|PA2 20|PA3 MegaTinyCore
* ATtiny1604 2 3|PA5 %
* ATtiny816 14|PA1 16|PA3 1|PA5 MegaTinyCore
* ATtiny1614 8|PA1 10|PA3 1|PA5 MegaTinyCore
* SAMD21 3 4 5
* ESP8266 14|D5 12|D6 %
* ESP32 15 4 27
* ESP32-C3 2 3 4
* BluePill PA6 PA7 PA3
* APOLLO3 11 12 5
* RP2040 3|GPIO15 4|GPIO16 5|GPIO17
*/
//#define _IR_MEASURE_TIMING // For debugging purposes.
#if defined(__AVR__)
#if defined(__AVR_ATtiny25__) || defined(__AVR_ATtiny45__) || defined(__AVR_ATtiny85__) // Digispark board. For use with ATTinyCore.
#include "ATtinySerialOut.hpp" // TX is at pin 2 - Available as Arduino library "ATtinySerialOut". Saves 700 bytes program memory and 70 bytes RAM for ATtinyCore.
#define IR_RECEIVE_PIN PIN_PB0
#define IR_SEND_PIN PIN_PB4 // Pin 2 is serial output with ATtinySerialOut. Pin 1 is internal LED and Pin3 is USB+ with pullup on Digispark board.
#define TONE_PIN PIN_PB3
#define _IR_TIMING_TEST_PIN PIN_PB3
# elif defined(__AVR_ATtiny87__) || defined(__AVR_ATtiny167__) // Digispark pro board
#include "ATtinySerialOut.hpp" // Available as Arduino library "ATtinySerialOut"
// For ATtiny167 Pins PB6 and PA3 are usable as interrupt source.
# if defined(ARDUINO_AVR_DIGISPARKPRO)
// For use with Digispark original core
#define IR_RECEIVE_PIN 9 // PA3 - on Digispark board labeled as pin 9
//#define IR_RECEIVE_PIN 14 // PB6 / INT0 is connected to USB+ on DigisparkPro boards
#define IR_SEND_PIN 8 // PA2 - on Digispark board labeled as pin 8
#define TONE_PIN 5 // PA7 - on Digispark board labeled as pin 5
#define _IR_TIMING_TEST_PIN 10 // PA4
# else
// For use with ATTinyCore
#define IR_RECEIVE_PIN PIN_PA3 // On Digispark board labeled as pin 9 - INT0 is connected to USB+ on DigisparkPro boards
#define IR_SEND_PIN PIN_PA2 // On Digispark board labeled as pin 8
#define TONE_PIN PIN_PA7 // On Digispark board labeled as pin 5
# endif
# elif defined(__AVR_ATtiny84__) // For use with ATTinyCore
#include "ATtinySerialOut.hpp" // Available as Arduino library "ATtinySerialOut". Saves 128 bytes program memory.
#define IR_RECEIVE_PIN PIN_PB2 // INT0
#define IR_SEND_PIN PIN_PA4
#define TONE_PIN PIN_PA3
#define _IR_TIMING_TEST_PIN PIN_PA5
# elif defined(__AVR_ATtiny88__) // MH-ET Tiny88 board. For use with ATTinyCore.
#include "ATtinySerialOut.hpp" // Available as Arduino library "ATtinySerialOut". Saves 128 bytes program memory.
// Pin 6 is TX, pin 7 is RX
#define IR_RECEIVE_PIN PIN_PD3 // 3 - INT1
#define IR_SEND_PIN PIN_PD4 // 4
#define TONE_PIN PIN_PB1 // 9
#define _IR_TIMING_TEST_PIN PIN_PB0 // 8
# elif defined(__AVR_ATtiny1616__) || defined(__AVR_ATtiny3216__) || defined(__AVR_ATtiny3217__) // For use with megaTinyCore
// Tiny Core Dev board
// https://www.tindie.com/products/xkimi/tiny-core-16-dev-board-attiny1616/ - Out of Stock
// https://www.tindie.com/products/xkimi/tiny-core-32-dev-board-attiny3217/ - Out of Stock
#define IR_RECEIVE_PIN PIN_PA1 // use 18 instead of PIN_PA1 for TinyCore32
#define IR_SEND_PIN PIN_PA2 // 19
#define TONE_PIN PIN_PA3 // 20
#define APPLICATION_PIN PIN_PA0 // 0
#undef LED_BUILTIN // No LED available on the TinyCore 32 board, take the one on the programming board which is connected to the DAC output
#define LED_BUILTIN PIN_PA6 // use 2 instead of PIN_PA6 for TinyCore32
# elif defined(__AVR_ATtiny816__) // For use with megaTinyCore
#define IR_RECEIVE_PIN PIN_PA1 // 14
#define IR_SEND_PIN PIN_PA1 // 16
#define TONE_PIN PIN_PA5 // 1
#define APPLICATION_PIN PIN_PA4 // 0
#undef LED_BUILTIN // No LED available, take the one which is connected to the DAC output
#define LED_BUILTIN PIN_PB5 // 4
# elif defined(__AVR_ATtiny1614__) // For use with megaTinyCore
#define IR_RECEIVE_PIN PIN_PA1 // 8
#define IR_SEND_PIN PIN_PA3 // 10
#define TONE_PIN PIN_PA5 // 1
#define APPLICATION_PIN PIN_PA4 // 0
# elif defined(__AVR_ATtiny1604__) // For use with megaTinyCore
#define IR_RECEIVE_PIN PIN_PA6 // 2 - To be compatible with interrupt example, pin 2 is chosen here.
#define IR_SEND_PIN PIN_PA7 // 3
#define APPLICATION_PIN PIN_PB2 // 5
#define tone(...) void() // Define as void, since TCB0_INT_vect is also used by tone()
#define noTone(a) void()
#define TONE_PIN 42 // Dummy for examples using it
# elif defined(__AVR_ATmega1284__) || defined(__AVR_ATmega1284P__) \
|| defined(__AVR_ATmega644__) || defined(__AVR_ATmega644P__) \
|| defined(__AVR_ATmega324P__) || defined(__AVR_ATmega324A__) \
|| defined(__AVR_ATmega324PA__) || defined(__AVR_ATmega164A__) \
|| defined(__AVR_ATmega164P__) || defined(__AVR_ATmega32__) \
|| defined(__AVR_ATmega16__) || defined(__AVR_ATmega8535__) \
|| defined(__AVR_ATmega64__) || defined(__AVR_ATmega128__) \
|| defined(__AVR_ATmega1281__) || defined(__AVR_ATmega2561__) \
|| defined(__AVR_ATmega8515__) || defined(__AVR_ATmega162__)
#define IR_RECEIVE_PIN 2
#define IR_SEND_PIN 13
#define TONE_PIN 4
#define APPLICATION_PIN 5
#define ALTERNATIVE_IR_FEEDBACK_LED_PIN 6 // E.g. used for examples which use LED_BUILDIN for example output.
#define _IR_TIMING_TEST_PIN 7
# else // Default as for ATmega328 like on Uno, Nano, Leonardo, Teensy 2.0 etc.
#define IR_RECEIVE_PIN 2 // To be compatible with interrupt example, pin 2 is chosen here.
#define IR_SEND_PIN 3
#define TONE_PIN 4
#define APPLICATION_PIN 5
#define ALTERNATIVE_IR_FEEDBACK_LED_PIN 6 // E.g. used for examples which use LED_BUILDIN for example output.
#define _IR_TIMING_TEST_PIN 7
# if defined(ARDUINO_AVR_PROMICRO) // Sparkfun Pro Micro is __AVR_ATmega32U4__ but has different external circuit
// We have no built in LED at pin 13 -> reuse RX LED
#undef LED_BUILTIN
#define LED_BUILTIN LED_BUILTIN_RX
# endif
# endif // defined(__AVR_ATtiny25__)...
#elif defined(ARDUINO_ARCH_RENESAS_UNO) // Uno R4
// To be compatible with Uno R3.
#define IR_RECEIVE_PIN 2
#define IR_SEND_PIN 3
#define TONE_PIN 4
#define APPLICATION_PIN 5
#define ALTERNATIVE_IR_FEEDBACK_LED_PIN 6 // E.g. used for examples which use LED_BUILDIN for example output.
#define _IR_TIMING_TEST_PIN 7
#elif defined(ESP8266)
#define FEEDBACK_LED_IS_ACTIVE_LOW // The LED on my board (D4) is active LOW
#define IR_RECEIVE_PIN 14 // D5
#define IR_SEND_PIN 12 // D6 - D4/pin 2 is internal LED
#define _IR_TIMING_TEST_PIN 2 // D4
#define APPLICATION_PIN 13 // D7
#define tone(...) void() // tone() inhibits receive timer
#define noTone(a) void()
#define TONE_PIN 42 // Dummy for examples using it#
#elif defined(ARDUINO_NOLOGO_ESP32C3_SUPER_MINI)
#define FEEDBACK_LED_IS_ACTIVE_LOW // The LED on my board (D8) is active LOW
#define IR_RECEIVE_PIN 2
#define IR_SEND_PIN 3
#define TONE_PIN 4
#define APPLICATION_PIN 10
#elif defined(CONFIG_IDF_TARGET_ESP32C3) || defined(ARDUINO_ESP32C3_DEV)
#define NO_LED_FEEDBACK_CODE // The WS2812 on pin 8 of AI-C3 board crashes if used as receive feedback LED, other I/O pins are working...
#define IR_RECEIVE_PIN 6
#define IR_SEND_PIN 7
#define TONE_PIN 10
#define APPLICATION_PIN 18
#elif defined(ESP32)
#include <Arduino.h>
// tone() is included in ESP32 core since 2.0.2
#if !defined(ESP_ARDUINO_VERSION_VAL)
#define ESP_ARDUINO_VERSION_VAL(major, minor, patch) 12345678
#endif
#if ESP_ARDUINO_VERSION <= ESP_ARDUINO_VERSION_VAL(2, 0, 2)
#define TONE_LEDC_CHANNEL 1 // Using channel 1 makes tone() independent of receiving timer -> No need to stop receiving timer.
void tone(uint8_t aPinNumber, unsigned int aFrequency){
ledcAttachPin(aPinNumber, TONE_LEDC_CHANNEL);
ledcWriteTone(TONE_LEDC_CHANNEL, aFrequency);
}
void tone(uint8_t aPinNumber, unsigned int aFrequency, unsigned long aDuration){
ledcAttachPin(aPinNumber, TONE_LEDC_CHANNEL);
ledcWriteTone(TONE_LEDC_CHANNEL, aFrequency);
delay(aDuration);
ledcWriteTone(TONE_LEDC_CHANNEL, 0);
}
void noTone(uint8_t aPinNumber){
ledcWriteTone(TONE_LEDC_CHANNEL, 0);
}
#endif // ESP_ARDUINO_VERSION <= ESP_ARDUINO_VERSION_VAL(2, 0, 2)
#define IR_RECEIVE_PIN 15 // D15
#define IR_SEND_PIN 4 // D4
#define TONE_PIN 27 // D27 25 & 26 are DAC0 and 1
#define APPLICATION_PIN 16 // RX2 pin
#elif defined(ARDUINO_ARCH_STM32) || defined(ARDUINO_ARCH_STM32F1) // BluePill
// Timer 3 blocks PA6, PA7, PB0, PB1 for use by Servo or tone()
#define IR_RECEIVE_PIN PA6
#define IR_RECEIVE_PIN_STRING "PA6"
#define IR_SEND_PIN PA7
#define IR_SEND_PIN_STRING "PA7"
#define TONE_PIN PA3
#define _IR_TIMING_TEST_PIN PA5
#define APPLICATION_PIN PA2
#define APPLICATION_PIN_STRING "PA2"
# if defined(ARDUINO_GENERIC_STM32F103C) || defined(ARDUINO_BLUEPILL_F103C8)
// BluePill LED is active low
#define FEEDBACK_LED_IS_ACTIVE_LOW
# endif
#elif defined(ARDUINO_ARCH_APOLLO3) // Sparkfun Apollo boards
#define IR_RECEIVE_PIN 11
#define IR_SEND_PIN 12
#define TONE_PIN 5
#elif defined(ARDUINO_ARCH_MBED) && defined(ARDUINO_ARCH_MBED_NANO) // Arduino Nano 33 BLE and Arduino Nano Connect layout for MBED
// Must be before ARDUINO_ARCH_RP2040, since it is the layout for the MBED core of Arduino Nano Connect
#define IR_RECEIVE_PIN 3 // GPIO15 Start with pin 3 since pin 2|GPIO25 is connected to LED on Pi pico
#define IR_SEND_PIN 4 // GPIO16
#define TONE_PIN 5
#define APPLICATION_PIN 6
#define ALTERNATIVE_IR_FEEDBACK_LED_PIN 7 // E.g. used for examples which use LED_BUILDIN for example output.
#define _IR_TIMING_TEST_PIN 8
#elif defined(ARDUINO_ARCH_RP2040) // Arduino Nano Connect, Pi Pico with arduino-pico core https://github.com/earlephilhower/arduino-pico
#define IR_RECEIVE_PIN 15 // GPIO15 to be compatible with the Arduino Nano RP2040 Connect (pin3)
#define IR_SEND_PIN 16 // GPIO16
#define TONE_PIN 17
#define APPLICATION_PIN 18
#define ALTERNATIVE_IR_FEEDBACK_LED_PIN 19 // E.g. used for examples which use LED_BUILDIN for example output.
#define _IR_TIMING_TEST_PIN 20
// If you program the Nano RP2040 Connect with this core, then you must redefine LED_BUILTIN
// and use the external reset with 1 kOhm to ground to enter UF2 mode
#undef LED_BUILTIN
#define LED_BUILTIN 6
#elif defined(PARTICLE) // !!!UNTESTED!!!
#define IR_RECEIVE_PIN A4
#define IR_SEND_PIN A5 // Particle supports multiple pins
#define LED_BUILTIN D7
/*
* 4 times the same (default) layout for easy adaption in the future
*/
#elif defined(TEENSYDUINO) // Teensy 2.0 is handled at default for ATmega328 like on Uno, Nano, Leonardo etc.
#define IR_RECEIVE_PIN 2
#define IR_SEND_PIN 3
#define TONE_PIN 4
#define APPLICATION_PIN 5
#define ALTERNATIVE_IR_FEEDBACK_LED_PIN 6 // E.g. used for examples which use LED_BUILDIN for example output.
#define _IR_TIMING_TEST_PIN 7
#elif defined(ARDUINO_ARCH_MBED) // Arduino Nano 33 BLE
#define IR_RECEIVE_PIN 2
#define IR_SEND_PIN 3
#define TONE_PIN 4
#define APPLICATION_PIN 5
#define ALTERNATIVE_IR_FEEDBACK_LED_PIN 6 // E.g. used for examples which use LED_BUILDIN for example output.
#define _IR_TIMING_TEST_PIN 7
#elif defined(ARDUINO_ARCH_SAMD) || defined(ARDUINO_ARCH_SAM)
#define IR_RECEIVE_PIN 2
#define IR_SEND_PIN 3
#define TONE_PIN 4
#define APPLICATION_PIN 5
#define ALTERNATIVE_IR_FEEDBACK_LED_PIN 6 // E.g. used for examples which use LED_BUILDIN for example output.
#define _IR_TIMING_TEST_PIN 7
#if !defined(ARDUINO_SAMD_ADAFRUIT) && !defined(ARDUINO_SEEED_XIAO_M0)
// On the Zero and others we switch explicitly to SerialUSB
#define Serial SerialUSB
#endif
// Definitions for the Chinese SAMD21 M0-Mini clone, which has no led connected to D13/PA17.
// Attention!!! D2 and D4 are swapped on these boards!!!
// If you connect the LED, it is on pin 24/PB11. In this case activate the next two lines.
//#undef LED_BUILTIN
//#define LED_BUILTIN 24 // PB11
// As an alternative you can choose pin 25, it is the RX-LED pin (PB03), but active low.In this case activate the next 3 lines.
//#undef LED_BUILTIN
//#define LED_BUILTIN 25 // PB03
//#define FEEDBACK_LED_IS_ACTIVE_LOW // The RX LED on the M0-Mini is active LOW
#elif defined (NRF51) // BBC micro:bit
#define IR_RECEIVE_PIN 2
#define IR_SEND_PIN 3
#define APPLICATION_PIN 1
#define _IR_TIMING_TEST_PIN 4
#define tone(...) void() // no tone() available
#define noTone(a) void()
#define TONE_PIN 42 // Dummy for examples using it
#else
#warning Board / CPU is not detected using pre-processor symbols -> using default values, which may not fit. Please extend PinDefinitionsAndMore.h.
// Default valued for unidentified boards
#define IR_RECEIVE_PIN 2
#define IR_SEND_PIN 3
#define TONE_PIN 4
#define APPLICATION_PIN 5
#define ALTERNATIVE_IR_FEEDBACK_LED_PIN 6 // E.g. used for examples which use LED_BUILDIN for example output.
#define _IR_TIMING_TEST_PIN 7
#endif // defined(ESP8266)
#if defined(ESP32) || defined(ARDUINO_ARCH_RP2040) || defined(PARTICLE) || defined(ARDUINO_ARCH_MBED)
#define SEND_PWM_BY_TIMER // We do not have pin restrictions for this CPU's, so lets use the hardware PWM for send carrier signal generation
#else
# if defined(SEND_PWM_BY_TIMER)
#undef IR_SEND_PIN // SendPin is determined by timer! This avoids warnings in IRremote.hpp and IRTimer.hpp
# endif
#endif
#if !defined (FLASHEND)
#define FLASHEND 0xFFFF // Dummy value for platforms where FLASHEND is not defined
#endif
/*
* Helper macro for getting a macro definition as string
*/
#if !defined(STR_HELPER)
#define STR_HELPER(x) #x
#define STR(x) STR_HELPER(x)
#endif