Convenience function isIRReceiverAttachedForTinyReceiver() and 3.party
This commit is contained in:
parent
7131adf71e
commit
8b9e036889
2
Doxyfile
2
Doxyfile
|
@ -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
|
||||
|
|
|
@ -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/>
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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
|
||||
*/
|
||||
|
|
|
@ -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;
|
||||
/*
|
||||
|
|
|
@ -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));
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -247,6 +247,7 @@ struct TinyIRReceiverCallbackDataStruct {
|
|||
};
|
||||
extern volatile TinyIRReceiverCallbackDataStruct TinyIRReceiverData;
|
||||
|
||||
bool isIRReceiverAttachedForTinyReceiver();
|
||||
bool initPCIInterruptForTinyReceiver();
|
||||
bool enablePCIInterruptForTinyReceiver();
|
||||
void disablePCIInterruptForTinyReceiver();
|
||||
|
|
|
@ -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()
|
||||
|
|
Loading…
Reference in New Issue