v0.5.0
- добавлена поддержка платы ELBEAR ACE-NANO; - добавлена поддержка плат ELSOMIK OEM и SE; - добавлена возможность работы в режиме отладки для всех плат, входящих в состав пакета. Доступно для версии ArduinoIDE 2 и выше; - добавлена поддержка библиотеки FreeRTOS; - добавлена поддержка библиотеки IRremote; - добавлена поддержка библиотеки OneWire; - добавлена поддержка аппаратного I2C0 для плат START-MIK32 и ELSOMIK. Для работы с ним доступен экземпляр класса Wire1; - добавлена поддержка аппаратного SPI0 для всех плат, входящих в пакет. Для работы с ним доступен экземпляр класса SPI1; - увеличено быстродействие функций digitalWrite, digitalRead; - исправлены известные ошибки. Co-authored-by: KlassenTS <klassen@elron.tech> Co-committed-by: KlassenTS <klassen@elron.tech>
This commit was merged in pull request #19.
This commit is contained in:
1 parent
de1f0d7fda
commit
1c8e06634c
211 files changed
+97525
-591
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,249 @@
|
||||
/*
|
||||
* 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.
|
||||
|
||||
#define IR_RECEIVE_PIN 4 // P0_1
|
||||
#define TONE_PIN 5 // P0_2
|
||||
|
||||
// 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.
|
||||
|
||||
//#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
|
||||
|
||||
/*
|
||||
* 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(9600);
|
||||
while (!Serial)
|
||||
; // Wait for Serial to become available. Is optimized away for some cores.
|
||||
|
||||
// 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
|
||||
|
||||
// play feedback tone before setup, since it kills the IR timer settings
|
||||
tone(TONE_PIN, 1000, 50);
|
||||
delay(50);
|
||||
|
||||
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)));
|
||||
#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) {
|
||||
tone(_pin, frequency, duration);
|
||||
}
|
||||
#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
|
||||
Reference in new issue
Block a user