Convenience function isIRReceiverAttachedForTinyReceiver() and 3.party

This commit is contained in:
Armin 2024-02-13 15:46:48 +01:00
parent 7131adf71e
commit 8b9e036889
10 changed files with 215 additions and 39 deletions

View File

@ -58,7 +58,7 @@ PROJECT_LOGO =
# entered, it will be relative to the location where doxygen was started. If
# left blank the current directory will be used.
OUTPUT_DIRECTORY = ..\Arduino-IRremote_gh-pages
OUTPUT_DIRECTORY = E:\WORKSPACE_ARDUINO\lib\Arduino-IRremote_gh-pages
# If the CREATE_SUBDIRS tag is set to YES then doxygen will create 4096 sub-
# directories (in 2 levels) under the output directory of each output format and

View File

@ -598,7 +598,9 @@ A simple example can be tested online with [WOKWI](https://wokwi.com/projects/33
#### TinyReceiver + TinySender
If **code size** or **timer usage** matters, look at these examples.<br/>
The **[TinyReceiver](https://github.com/Arduino-IRremote/Arduino-IRremote/blob/master/examples/TinyReceiver/TinyReceiver.ino)** example uses the **TinyIRReceiver** library which can **only receive NEC, Extended NEC, ONKYO and FAST protocols, but does not require any timer**. They use pin change interrupt for on the fly decoding, which is the reason for the restricted protocol choice.<br/>
The **[TinyReceiver](https://github.com/Arduino-IRremote/Arduino-IRremote/blob/master/examples/TinyReceiver/TinyReceiver.ino)** example uses the **TinyIRReceiver** library
which can **only receive NEC, Extended NEC, ONKYO and FAST protocols, but does not require any timer**.
They use pin change interrupt for on the fly decoding, which is the reason for the restricted protocol choice.<br/>
TinyReceiver can be tested online with [WOKWI](https://wokwi.com/arduino/projects/339264565653013075).
The **[TinySender](https://github.com/Arduino-IRremote/Arduino-IRremote/blob/master/examples/TinySender/TinySender.ino)** example uses the **TinyIRSender** library which can **only send NEC, ONKYO and FAST protocols**.<br/>
@ -718,13 +720,15 @@ These next macros for **TinyIRReceiver** must be defined in your program before
| `NO_LED_FEEDBACK_CODE` | disabled | Disables the feedback LED function. Saves 14 bytes program memory. |
| `DISABLE_PARITY_CHECKS` | disabled | Disables the addres and command parity checks. Saves 48 bytes program memory. |
| `USE_EXTENDED_NEC_PROTOCOL` | disabled | Like NEC, but take the 16 bit address as one 16 bit value and not as 8 bit normal and 8 bit inverted value. |
| `USE_ONKYO_PROTOCOL` | disabled | Like NEC, but take both the 16 bit address and command each as one 16 bit value and not as 8 bit normal and 8 bit inverted value. |
| `USE_ONKYO_PROTOCOL` | disabled | Like NEC, but take the 16 bit address and command each as one 16 bit value and not as 8 bit normal and 8 bit inverted value. |
| `USE_FAST_PROTOCOL` | disabled | Use FAST protocol (no address and 16 bit data, interpreted as 8 bit command and 8 bit inverted command) instead of NEC. |
| `ENABLE_NEC2_REPEATS` | disabled | Instead of sending / receiving the NEC special repeat code, send / receive the original frame for repeat. |
| `USE_CALLBACK_FOR_TINY_RECEIVER` | disabled | Call the fixed function `void handleReceivedTinyIRData()` each time a frame or repeat is received. |
The next macro for **IRCommandDispatcher** must be defined in your program before the line `#include <IRCommandDispatcher.hpp>` to take effect.
| `USE_TINY_IR_RECEIVER` | disabled | Use [TinyReceiver](https://github.com/Arduino-IRremote/Arduino-IRremote#tinyreceiver--tinysender) for receiving IR codes. |
| `IR_COMMAND_HAS_MORE_THAN_8_BIT` | disabled | Enables mapping and dispatching of IR commands consisting of more than 8 bits. Saves up to 160 bytes program memory and 4 bytes RAM + 1 byte RAM per mapping entry. |
| `BUZZER_PIN` | | If `USE_TINY_IR_RECEIVER` is enabled, the pin to be used for the optional 50 ms buzzer feedback before executing a command. Other IR libraries than Tiny are not compatible with tone() command. |
### Changing include (*.h) files with Arduino IDE
First, use *Sketch > Show Sketch Folder (Ctrl+K)*.<br/>

View File

@ -2,6 +2,10 @@
The latest version may not be released!
See also the commit log at github: https://github.com/Arduino-IRremote/Arduino-IRremote/commits/master
# 4.2.2
- Added convenience function isIRReceiverAttachedForTinyReceiver().
- Added Extended NEC Protocol to TinyIR by Butzerb
# 4.2.1
- Fix wrong type of tEnableLEDFeedback in IRSend.hpp and IRReceive.hpp.
- TinyReceiver 2.0

View File

@ -85,6 +85,7 @@
#define ADC_TEMPERATURE_CHANNEL_MUX 15
#define ADC_1_1_VOLT_CHANNEL_MUX 12
#define ADC_GND_CHANNEL_MUX 13
#define ADC_CHANNEL_MUX_MASK 0x0F
#elif defined(__AVR_ATtiny87__) || defined(__AVR_ATtiny167__)
#define ADC_ISCR_CHANNEL_MUX 3
@ -92,20 +93,25 @@
#define ADC_1_1_VOLT_CHANNEL_MUX 12
#define ADC_GND_CHANNEL_MUX 14
#define ADC_VCC_4TH_CHANNEL_MUX 13
#define ADC_CHANNEL_MUX_MASK 0x1F
#elif defined(__AVR_ATmega328P__)
#define ADC_TEMPERATURE_CHANNEL_MUX 8
#define ADC_1_1_VOLT_CHANNEL_MUX 14
#define ADC_GND_CHANNEL_MUX 15
#define ADC_CHANNEL_MUX_MASK 0x0F
#elif defined(__AVR_ATmega32U4__)
#define ADC_TEMPERATURE_CHANNEL_MUX 0x27
#define ADC_1_1_VOLT_CHANNEL_MUX 0x1E
#define ADC_GND_CHANNEL_MUX 0x1F
#define ADC_CHANNEL_MUX_MASK 0x3F
#elif defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__) || defined(__AVR_ATmega1284__) || defined(__AVR_ATmega1284P__) || defined(__AVR_ATmega644__) || defined(__AVR_ATmega644A__) || defined(__AVR_ATmega644P__) || defined(__AVR_ATmega644PA__)
#define ADC_1_1_VOLT_CHANNEL_MUX 0x1E
#define ADC_GND_CHANNEL_MUX 0x1F
#define ADC_CHANNEL_MUX_MASK 0x1F
#define INTERNAL INTERNAL1V1
#else
@ -164,7 +170,10 @@ uint16_t waitAndReadADCChannelWithReferenceAndRestoreADMUXAndReference(uint8_t a
uint16_t readADCChannelWithOversample(uint8_t aADCChannelNumber, uint8_t aOversampleExponent);
void setADCChannelAndReferenceForNextConversion(uint8_t aADCChannelNumber, uint8_t aReference);
uint16_t readADCChannelWithReferenceOversampleFast(uint8_t aADCChannelNumber, uint8_t aReference, uint8_t aOversampleExponent);
uint16_t readADCChannelWithReferenceMultiSamples(uint8_t aADCChannelNumber, uint8_t aReference, uint8_t aNumberOfSamples);
uint32_t readADCChannelMultiSamples(uint8_t aPrescale, uint16_t aNumberOfSamples);
uint16_t readADCChannelMultiSamplesWithReference(uint8_t aADCChannelNumber, uint8_t aReference, uint8_t aNumberOfSamples);
uint32_t readADCChannelMultiSamplesWithReferenceAndPrescaler(uint8_t aADCChannelNumber, uint8_t aReference, uint8_t aPrescale,
uint16_t aNumberOfSamples);
uint16_t readADCChannelWithReferenceMax(uint8_t aADCChannelNumber, uint8_t aReference, uint16_t aNumberOfSamples);
uint16_t readADCChannelWithReferenceMaxMicros(uint8_t aADCChannelNumber, uint8_t aReference, uint16_t aMicrosecondsToAquire);
uint16_t readUntil4ConsecutiveValuesAreEqual(uint8_t aADCChannelNumber, uint8_t aReference, uint8_t aDelay,
@ -192,7 +201,8 @@ float getCPUTemperatureSimple(void);
float getCPUTemperature(void);
float getTemperature(void) __attribute__ ((deprecated ("Renamed to getCPUTemperature()"))); // deprecated
bool isVCCUSBPowered() ;
bool isVCCUSBPowered();
bool isVCCUSBPowered(Print *aSerial);
bool isVCCUndervoltageMultipleTimes();
void resetCounterForVCCUndervoltageMultipleTimes();
bool isVCCUndervoltage();

View File

@ -58,7 +58,7 @@ union WordUnionForADCUtils {
* 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(DEBUG)
#if defined(DEBUG) && !defined(LOCAL_DEBUG)
#define LOCAL_DEBUG
#else
//#define LOCAL_DEBUG // This enables debug output only for this file
@ -161,12 +161,15 @@ uint8_t checkAndWaitForReferenceAndChannelToSwitch(uint8_t aADCChannelNumber, ui
if ((tOldADMUX & MASK_FOR_ADC_REFERENCE) != tNewReference && (aReference == INTERNAL || aReference == INTERNAL2V56)) {
#else
if ((tOldADMUX & MASK_FOR_ADC_REFERENCE) != tNewReference && aReference == INTERNAL) {
#endif
#if defined(LOCAL_DEBUG)
Serial.println(F("Switch from DEFAULT to INTERNAL"));
#endif
/*
* Switch reference from DEFAULT to INTERNAL
*/
delayMicroseconds(8000); // experimental value is >= 7600 us for Nano board and 6200 for Uno board
} else if ((tOldADMUX & 0x0F) != aADCChannelNumber) {
} else if ((tOldADMUX & ADC_CHANNEL_MUX_MASK) != aADCChannelNumber) {
if (aADCChannelNumber == ADC_1_1_VOLT_CHANNEL_MUX) {
/*
* Internal 1.1 Volt channel requires <= 200 us for Nano board
@ -249,9 +252,10 @@ uint16_t readADCChannelWithReferenceOversampleFast(uint8_t aADCChannelNumber, ui
/*
* Returns sum of all sample values
* Conversion time is defined as 0.104 milliseconds for 16 MHz Arduino by ADC_PRESCALE in ADCUtils.h.
* Conversion time is defined as 0.104 milliseconds for 16 MHz Arduino by ADC_PRESCALE (=ADC_PRESCALE128) in ADCUtils.h.
* @ param aNumberOfSamples If > 64 an overflow may occur.
*/
uint16_t readADCChannelWithReferenceMultiSamples(uint8_t aADCChannelNumber, uint8_t aReference, uint8_t aNumberOfSamples) {
uint16_t readADCChannelMultiSamplesWithReference(uint8_t aADCChannelNumber, uint8_t aReference, uint8_t aNumberOfSamples) {
uint16_t tSumValue = 0;
ADMUX = aADCChannelNumber | (aReference << SHIFT_VALUE_FOR_REFERENCE);
@ -275,6 +279,65 @@ uint16_t readADCChannelWithReferenceMultiSamples(uint8_t aADCChannelNumber, uint
return tSumValue;
}
/*
* Returns sum of all sample values
* Conversion time is defined as 0.104 milliseconds for 16 MHz Arduino for ADC_PRESCALE128 in ADCUtils.h.
* @ param aPrescale can be one of ADC_PRESCALE2, ADC_PRESCALE4, 8, 16, 32, 64, 128.
* ADC_PRESCALE32 is recommended for excellent linearity and fast readout of 26 microseconds
* @ param aNumberOfSamples If > 16k an overflow may occur.
*/
uint32_t readADCChannelMultiSamplesWithReferenceAndPrescaler(uint8_t aADCChannelNumber, uint8_t aReference, uint8_t aPrescale,
uint16_t aNumberOfSamples) {
uint32_t tSumValue = 0;
ADMUX = aADCChannelNumber | (aReference << SHIFT_VALUE_FOR_REFERENCE);
ADCSRB = 0; // Free running mode. Only active if ADATE is set to 1.
// ADSC-StartConversion ADATE-AutoTriggerEnable ADIF-Reset Interrupt Flag
ADCSRA = (_BV(ADEN) | _BV(ADSC) | _BV(ADATE) | _BV(ADIF) | aPrescale);
for (uint16_t i = 0; i < aNumberOfSamples; i++) {
/*
* wait for free running conversion to finish.
* Do not wait for ADSC here, since ADSC is only low for 1 ADC Clock cycle on free running conversion.
*/
loop_until_bit_is_set(ADCSRA, ADIF);
ADCSRA |= _BV(ADIF); // clear bit to enable recognizing next conversion has finished
// Add value
tSumValue += ADCL | (ADCH << 8); // using WordUnionForADCUtils does not save space here
// tSumValue += (ADCH << 8) | ADCL; // this does NOT work!
}
ADCSRA &= ~_BV(ADATE); // Disable auto-triggering (free running mode)
return tSumValue;
}
/*
* Returns sum of all sample values
* Assumes, that channel and reference are still set to the right values
* @ param aNumberOfSamples If > 16k an overflow may occur.
*/
uint32_t readADCChannelMultiSamples(uint8_t aPrescale, uint16_t aNumberOfSamples) {
uint32_t tSumValue = 0;
ADCSRB = 0; // Free running mode. Only active if ADATE is set to 1.
// ADSC-StartConversion ADATE-AutoTriggerEnable ADIF-Reset Interrupt Flag
ADCSRA = (_BV(ADEN) | _BV(ADSC) | _BV(ADATE) | _BV(ADIF) | aPrescale);
for (uint16_t i = 0; i < aNumberOfSamples; i++) {
/*
* wait for free running conversion to finish.
* Do not wait for ADSC here, since ADSC is only low for 1 ADC Clock cycle on free running conversion.
*/
loop_until_bit_is_set(ADCSRA, ADIF);
ADCSRA |= _BV(ADIF); // clear bit to enable recognizing next conversion has finished
// Add value
tSumValue += ADCL | (ADCH << 8); // using WordUnionForADCUtils does not save space here
// tSumValue += (ADCH << 8) | ADCL; // this does NOT work!
}
ADCSRA &= ~_BV(ADATE); // Disable auto-triggering (free running mode)
return tSumValue;
}
/*
* use ADC_PRESCALE32 which gives 26 us conversion time and good linearity
* @return the maximum value of aNumberOfSamples samples.
@ -408,7 +471,7 @@ uint16_t readUntil4ConsecutiveValuesAreEqual(uint8_t aADCChannelNumber, uint8_t
*/
float getVCCVoltageSimple(void) {
// use AVCC with (optional) external capacitor at AREF pin as reference
float tVCC = readADCChannelWithReferenceMultiSamples(ADC_1_1_VOLT_CHANNEL_MUX, DEFAULT, 4);
float tVCC = readADCChannelMultiSamplesWithReference(ADC_1_1_VOLT_CHANNEL_MUX, DEFAULT, 4);
return ((1023 * 1.1 * 4) / tVCC);
}
@ -419,7 +482,7 @@ float getVCCVoltageSimple(void) {
*/
uint16_t getVCCVoltageMillivoltSimple(void) {
// use AVCC with external capacitor at AREF pin as reference
uint16_t tVCC = readADCChannelWithReferenceMultiSamples(ADC_1_1_VOLT_CHANNEL_MUX, DEFAULT, 4);
uint16_t tVCC = readADCChannelMultiSamplesWithReference(ADC_1_1_VOLT_CHANNEL_MUX, DEFAULT, 4);
return ((1023L * ADC_INTERNAL_REFERENCE_MILLIVOLT * 4) / tVCC);
}
@ -459,6 +522,9 @@ uint16_t getVCCVoltageMillivolt(void) {
return ((1023L * ADC_INTERNAL_REFERENCE_MILLIVOLT) / tVCC);
}
/*
* Does not set sVCCVoltageMillivolt
*/
uint16_t printVCCVoltageMillivolt(Print *aSerial) {
aSerial->print(F("VCC="));
uint16_t tVCCVoltageMillivolt = getVCCVoltageMillivolt();
@ -480,7 +546,7 @@ void readAndPrintVCCVoltageMillivolt(Print *aSerial) {
*/
void readVCCVoltageSimple(void) {
// use AVCC with (optional) external capacitor at AREF pin as reference
float tVCC = readADCChannelWithReferenceMultiSamples(ADC_1_1_VOLT_CHANNEL_MUX, DEFAULT, 4);
float tVCC = readADCChannelMultiSamplesWithReference(ADC_1_1_VOLT_CHANNEL_MUX, DEFAULT, 4);
sVCCVoltage = (1023 * (((float) ADC_INTERNAL_REFERENCE_MILLIVOLT) / 1000) * 4) / tVCC;
}
@ -491,7 +557,7 @@ void readVCCVoltageSimple(void) {
*/
void readVCCVoltageMillivoltSimple(void) {
// use AVCC with external capacitor at AREF pin as reference
uint16_t tVCCVoltageMillivoltRaw = readADCChannelWithReferenceMultiSamples(ADC_1_1_VOLT_CHANNEL_MUX, DEFAULT, 4);
uint16_t tVCCVoltageMillivoltRaw = readADCChannelMultiSamplesWithReference(ADC_1_1_VOLT_CHANNEL_MUX, DEFAULT, 4);
sVCCVoltageMillivolt = (1023L * ADC_INTERNAL_REFERENCE_MILLIVOLT * 4) / tVCCVoltageMillivoltRaw;
}
@ -548,6 +614,25 @@ bool isVCCUSBPowered() {
&& sVCCVoltageMillivolt < VOLTAGE_USB_POWERED_UPPER_THRESHOLD_MILLIVOLT);
}
/*
* Return true if sVCCVoltageMillivolt is > 4.3 V and < 4.95 V
*/
bool isVCCUSBPowered(Print *aSerial) {
readVCCVoltageMillivolt();
aSerial->print(F("USB powered is "));
bool tReturnValue;
if (VOLTAGE_USB_POWERED_LOWER_THRESHOLD_MILLIVOLT
< sVCCVoltageMillivolt&& sVCCVoltageMillivolt < VOLTAGE_USB_POWERED_UPPER_THRESHOLD_MILLIVOLT) {
tReturnValue = true;
aSerial->print(F("true "));
} else {
tReturnValue = false;
aSerial->print(F("false "));
}
printVCCVoltageMillivolt(aSerial);
return tReturnValue;
}
/*
* @ return true only once, when VCC_UNDERVOLTAGE_CHECKS_BEFORE_STOP (6) times voltage too low -> shutdown
*/
@ -685,7 +770,7 @@ float getCPUTemperature(void) {
}
#else // defined(ADC_UTILS_ARE_AVAILABLE)
// Dummy definition of functions defined in ADCUtils to compile examples without errors
// Dummy definition of functions defined in ADCUtils to compile examples for non AVR platforms without errors
/*
* Persistent storage for VCC value
*/

View File

@ -5,14 +5,14 @@
*
* To run this example you need to install the "IRremote" or "IRMP" library under "Tools -> Manage Libraries..." or "Ctrl+Shift+I"
*
* Copyright (C) 2019-2021 Armin Joachimsmeyer
* 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.
*
* ServoEasing is free software: you can redistribute it and/or modify
* 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.
@ -38,6 +38,22 @@
#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 {
@ -72,13 +88,10 @@ struct IRDataForCommandDispatcherStruct {
#define COMMAND_EMPTY 0xFF // code no command
#endif
#define RETURN_IF_STOP if (IRDispatcher.requestToStopReceived) return
#define BREAK_IF_STOP if (IRDispatcher.requestToStopReceived) break
#define DELAY_AND_RETURN_IF_STOP(aDurationMillis) if (IRDispatcher.delayAndCheckForStop(aDurationMillis)) return
class IRCommandDispatcher {
public:
void init();
void printIRInfo(Print *aSerial);
bool checkAndRunNonBlockingCommands();
bool checkAndRunSuspendedBlockingCommands();
@ -107,7 +120,8 @@ public:
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).
* Is reset by next IR command received. Can be reset by main loop, if command has stopped.
* 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;
/*

View File

@ -11,14 +11,14 @@
* 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-2022 Armin Joachimsmeyer
* 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.
*
* ServoEasing is free software: you can redistribute it and/or modify
* 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.
@ -31,6 +31,14 @@
* 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
@ -38,6 +46,10 @@
#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.
@ -73,6 +85,17 @@ 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
@ -153,11 +176,11 @@ void handleReceivedIRData() {
#endif // elif defined(USE_IRMP_LIBRARY)
/*
* The main dispatcher function
* Sets flags justCalledRegularIRCommand, executingBlockingCommand
* @param aCallBlockingCommandImmediately Run blocking command directly, otherwise set request to stop to true
* and store command for main loop to execute by checkAndRunSuspendedBlockingCommands().
* Should be false if called by ISR.
* 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) {
@ -200,21 +223,31 @@ void IRCommandDispatcher::checkAndCallCommand(bool aCallBlockingCommandImmediate
}
/*
* lets start a new turn
* Execute commands
*/
requestToStopReceived = false;
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 we are called from main loop to execute a command
* 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
@ -224,6 +257,15 @@ void IRCommandDispatcher::checkAndCallCommand(bool aCallBlockingCommandImmediate
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"));
@ -231,7 +273,9 @@ void IRCommandDispatcher::checkAndCallCommand(bool aCallBlockingCommandImmediate
currentBlockingCommandCalled = COMMAND_EMPTY;
} else {
/*
* Do not run command directly, but set request to stop to true and store command for main loop to execute
* 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
@ -256,25 +300,29 @@ bool IRCommandDispatcher::checkAndRunSuspendedBlockingCommands() {
*/
if (BlockingCommandToRunNext != COMMAND_EMPTY) {
CD_INFO_PRINT(F("Take stored command = 0x"));
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 0x"));
CD_INFO_PRINT(F("Set next command to run to 0x"));
CD_INFO_PRINTLN(aBlockingCommandToRunNext, HEX);
BlockingCommandToRunNext = aBlockingCommandToRunNext;
requestToStopReceived = true;
@ -296,7 +344,6 @@ bool IRCommandDispatcher::delayAndCheckForStop(uint16_t aDelayMillis) {
}
void IRCommandDispatcher::printIRCommandString(Print *aSerial) {
aSerial->print(F("IRCommand="));
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));

View File

@ -60,7 +60,7 @@
*/
//#define DISABLE_PARITY_CHECKS // Disable parity checks. Saves 48 bytes of program memory.
//#define USE_EXTENDED_NEC_PROTOCOL // Like NEC, but take the 16 bit address as one 16 bit value and not as 8 bit normal and 8 bit inverted value.
//#define USE_ONKYO_PROTOCOL // Like NEC, but take both the 16 bit address and command each as one 16 bit value and not as 8 bit normal and 8 bit inverted value.
//#define USE_ONKYO_PROTOCOL // Like NEC, but take the 16 bit address and command each as one 16 bit value and not as 8 bit normal and 8 bit inverted value.
//#define USE_FAST_PROTOCOL // Use FAST protocol (no address and 16 bit data, interpreted as 8 bit command and 8 bit inverted command) instead of NEC / ONKYO.
//#define ENABLE_NEC2_REPEATS // Instead of sending / receiving the NEC special repeat code, send / receive the original frame for repeat.
//#define USE_CALLBACK_FOR_TINY_RECEIVER // Call the fixed function "void handleReceivedTinyIRData()" each time a frame or repeat is received.

View File

@ -247,6 +247,7 @@ struct TinyIRReceiverCallbackDataStruct {
};
extern volatile TinyIRReceiverCallbackDataStruct TinyIRReceiverData;
bool isIRReceiverAttachedForTinyReceiver();
bool initPCIInterruptForTinyReceiver();
bool enablePCIInterruptForTinyReceiver();
void disablePCIInterruptForTinyReceiver();

View File

@ -58,7 +58,7 @@
* - IR_FEEDBACK_LED_PIN The pin number for TinyIRReceiver feedback LED.
* - NO_LED_FEEDBACK_CODE Disables the feedback LED function. Saves 14 bytes program memory.
* - DISABLE_PARITY_CHECKS Disable parity checks. Saves 48 bytes of program memory.
* - USE_EXTENDED_NEC_PROTOCOL Like NEC, but take the 16 bit address as one 16 bit value and not as 8 bit normal and 8 bit inverted value.
* - USE_EXTENDED_NEC_PROTOCOL Like NEC, but take the 16 bit address as one 16 bit value and not as 8 bit normal and 8 bit inverted value.
* - USE_ONKYO_PROTOCOL Like NEC, but take both the 16 bit address and command each as one 16 bit value and not as 8 bit normal and 8 bit inverted value.
* - USE_FAST_PROTOCOL Use FAST protocol (no address and 16 bit data, interpreted as 8 bit command and 8 bit inverted command) instead of NEC.
* - ENABLE_NEC2_REPEATS Instead of sending / receiving the NEC special repeat code, send / receive the original frame for repeat.
@ -78,7 +78,7 @@
//#define DISABLE_PARITY_CHECKS // Disable parity checks. Saves 48 bytes of program memory.
//#define USE_EXTENDED_NEC_PROTOCOL // Like NEC, but take the 16 bit address as one 16 bit value and not as 8 bit normal and 8 bit inverted value.
//#define USE_ONKYO_PROTOCOL // Like NEC, but take both the 16 bit address and command each as one 16 bit value and not as 8 bit normal and 8 bit inverted value.
//#define USE_ONKYO_PROTOCOL // Like NEC, but take the 16 bit address and command each as one 16 bit value and not as 8 bit normal and 8 bit inverted value.
//#define USE_FAST_PROTOCOL // Use FAST protocol instead of NEC / ONKYO.
//#define ENABLE_NEC2_REPEATS // Instead of sending / receiving the NEC special repeat code, send / receive the original frame for repeat.
@ -423,6 +423,17 @@ bool isTinyReceiverIdle() {
return (TinyIRReceiverControl.IRReceiverState == IR_RECEIVER_STATE_WAITING_FOR_START_MARK);
}
/*
* Checks if IR_RECEIVE_PIN is connected and high
* @return true, if IR Receiver is attached
*/
bool isIRReceiverAttachedForTinyReceiver() {
pinModeFast(IR_RECEIVE_PIN, OUTPUT);
digitalWriteFast(IR_RECEIVE_PIN, LOW); // discharge pin capacity
pinModeFast(IR_RECEIVE_PIN, INPUT);
return digitalRead(IR_RECEIVE_PIN); // use slow digitalRead here, since the pin capacity is not fully charged again if we use digitalReadFast.
}
/**
* Sets IR_RECEIVE_PIN mode to INPUT, and if IR_FEEDBACK_LED_PIN is defined, sets feedback LED output mode.
* Then call enablePCIInterruptForTinyReceiver()