35 #if defined(DEBUG) && !defined(LOCAL_DEBUG)
41 #if defined(TRACE) && !defined(LOCAL_TRACE)
56 #if defined(IR_SEND_PIN)
57 #define sendPin IR_SEND_PIN
68 #if !defined(IR_SEND_PIN)
72 #if !defined(NO_LED_FEEDBACK_CODE)
77 #if defined(IR_SEND_PIN)
83 # if !defined(NO_LED_FEEDBACK_CODE)
86 #if defined(_IR_MEASURE_TIMING) && defined(_IR_TIMING_TEST_PIN)
96 void IRsend::begin(
bool aEnableLEDFeedback, uint_fast8_t aFeedbackLEDPin) {
97 #if !defined(NO_LED_FEEDBACK_CODE)
99 if(aEnableLEDFeedback) {
104 (void) aEnableLEDFeedback;
105 (void) aFeedbackLEDPin;
109 #else // defined(IR_SEND_PIN)
112 # if !defined(NO_LED_FEEDBACK_CODE)
123 # if !defined(NO_LED_FEEDBACK_CODE)
138 void IRsend::begin(uint_fast8_t aSendPin,
bool aEnableLEDFeedback, uint_fast8_t aFeedbackLEDPin) {
139 #if defined(IR_SEND_PIN)
145 #if !defined(NO_LED_FEEDBACK_CODE)
147 if (aEnableLEDFeedback) {
152 (void) aEnableLEDFeedback;
153 (void) aFeedbackLEDPin;
156 #endif // defined(IR_SEND_PIN)
172 auto tProtocol = aIRSendData->
protocol;
173 auto tAddress = aIRSendData->
address;
174 auto tCommand = aIRSendData->
command;
214 if (tProtocol ==
NEC) {
217 }
else if (tProtocol ==
SAMSUNG) {
226 }
else if (tProtocol ==
SONY) {
232 }
else if (tProtocol ==
DENON) {
235 }
else if (tProtocol ==
SHARP) {
238 }
else if (tProtocol ==
LG) {
241 }
else if (tProtocol ==
JVC) {
244 }
else if (tProtocol ==
RC5) {
247 }
else if (tProtocol ==
RC6) {
262 }
else if (tProtocol ==
NEC2) {
265 }
else if (tProtocol ==
ONKYO) {
268 }
else if (tProtocol ==
APPLE) {
271 #if !defined(EXCLUDE_EXOTIC_PROTOCOLS)
279 }
else if (tProtocol ==
FAST) {
283 }
else if (tProtocol ==
LEGO_PF) {
335 if (aProtocol ==
NEC) {
338 }
else if (aProtocol ==
SAMSUNG) {
347 }
else if (aProtocol ==
SONY) {
353 }
else if (aProtocol ==
DENON) {
356 }
else if (aProtocol ==
SHARP) {
359 }
else if (aProtocol ==
LG) {
362 }
else if (aProtocol ==
JVC) {
365 }
else if (aProtocol ==
RC5) {
368 }
else if (aProtocol ==
RC6) {
383 }
else if (aProtocol ==
NEC2) {
386 }
else if (aProtocol ==
ONKYO) {
389 }
else if (aProtocol ==
APPLE) {
392 #if !defined(EXCLUDE_EXOTIC_PROTOCOLS)
396 }
else if (aProtocol ==
FAST) {
400 }
else if (aProtocol ==
LEGO_PF) {
414 void IRsend::sendRaw(
const uint16_t aBufferWithMicroseconds[], uint_fast16_t aLengthOfBuffer, uint_fast8_t aIRFrequencyKilohertz) {
421 for (uint_fast16_t i = 0; i < aLengthOfBuffer; i++) {
424 space(aBufferWithMicroseconds[i]);
426 mark(aBufferWithMicroseconds[i]);
435 void IRsend::sendRaw(
const uint8_t aBufferWithTicks[], uint_fast16_t aLengthOfBuffer, uint_fast8_t aIRFrequencyKilohertz) {
439 for (uint_fast16_t i = 0; i < aLengthOfBuffer; i++) {
455 uint_fast8_t aIRFrequencyKilohertz) {
456 #if !defined(__AVR__)
457 sendRaw(aBufferWithMicroseconds, aLengthOfBuffer, aIRFrequencyKilohertz);
464 for (uint_fast16_t i = 0; i < aLengthOfBuffer; i++) {
465 auto duration = pgm_read_word(&aBufferWithMicroseconds[i]);
469 # if defined(LOCAL_DEBUG)
470 Serial.print(F(
"S="));
474 # if defined(LOCAL_DEBUG)
475 Serial.print(F(
"M="));
478 # if defined(LOCAL_DEBUG)
479 Serial.println(duration);
489 void IRsend::sendRaw_P(
const uint8_t aBufferWithTicks[], uint_fast16_t aLengthOfBuffer, uint_fast8_t aIRFrequencyKilohertz) {
490 #if !defined(__AVR__)
491 sendRaw(aBufferWithTicks, aLengthOfBuffer, aIRFrequencyKilohertz);
496 uint_fast16_t duration;
497 for (uint_fast16_t i = 0; i < aLengthOfBuffer; i++) {
498 duration = pgm_read_byte(&aBufferWithTicks[i]) * (uint_fast16_t)
MICROS_PER_TICK;
502 # if defined(LOCAL_DEBUG)
503 Serial.print(F(
"S="));
507 # if defined(LOCAL_DEBUG)
508 Serial.print(F(
"M="));
513 # if defined(LOCAL_DEBUG)
514 Serial.println(duration);
527 IRRawDataType *aDecodedRawDataArray, uint16_t aNumberOfBits, uint8_t aFlags, uint16_t aRepeatPeriodMillis,
528 int_fast8_t aNumberOfRepeats) {
532 aDistanceWidthTimingInfo->
ZeroSpaceMicros, aDecodedRawDataArray, aNumberOfBits, aFlags, aRepeatPeriodMillis,
536 uint16_t aOneMarkMicros, uint16_t aOneSpaceMicros, uint16_t aZeroMarkMicros, uint16_t aZeroSpaceMicros,
537 IRRawDataType *aDecodedRawDataArray, uint16_t aNumberOfBits, uint8_t aFlags, uint16_t aRepeatPeriodMillis,
538 int_fast8_t aNumberOfRepeats) {
546 #if defined(LOCAL_DEBUG)
548 Serial.print(F(
"Data[0]=0x"));
549 Serial.print(aDecodedRawDataArray[0], HEX);
550 if (tNumberOf32Or64BitChunks > 1) {
551 Serial.print(F(
" Data[1]=0x"));
552 Serial.print(aDecodedRawDataArray[1], HEX);
554 Serial.print(F(
" #="));
555 Serial.println(aNumberOfBits);
559 while (tNumberOfCommands > 0) {
560 unsigned long tStartOfFrameMillis = millis();
563 mark(aHeaderMarkMicros);
564 space(aHeaderSpaceMicros);
566 for (uint_fast8_t i = 0; i < tNumberOf32Or64BitChunks; ++i) {
567 uint8_t tNumberOfBitsForOneSend;
571 if (i == (tNumberOf32Or64BitChunks - 1)) {
573 tNumberOfBitsForOneSend = aNumberOfBits;
582 tNumberOfBitsForOneSend, tFlags);
588 if (tNumberOfCommands > 0) {
592 auto tFrameDurationMillis = millis() - tStartOfFrameMillis;
593 if (aRepeatPeriodMillis > tFrameDurationMillis) {
594 delay(aRepeatPeriodMillis - tFrameDurationMillis);
610 IRRawDataType *aDecodedRawDataArray, uint16_t aNumberOfBits, int_fast8_t aNumberOfRepeats) {
624 #if defined(LOCAL_DEBUG)
626 Serial.print(F(
"Data[0]=0x"));
627 Serial.print(aDecodedRawDataArray[0], HEX);
628 if (tNumberOf32Or64BitChunks > 1) {
629 Serial.print(F(
" Data[1]=0x"));
630 Serial.print(aDecodedRawDataArray[1], HEX);
632 Serial.print(F(
" #="));
633 Serial.println(aNumberOfBits);
638 while (tNumberOfCommands > 0) {
639 auto tStartOfFrameMillis = millis();
640 auto tNumberOfBits = aNumberOfBits;
645 uint8_t tOriginalFlags = aProtocolConstants->
Flags;
647 for (uint_fast8_t i = 0; i < tNumberOf32Or64BitChunks; ++i) {
648 uint8_t tNumberOfBitsForOneSend;
651 if (i == (tNumberOf32Or64BitChunks - 1)) {
653 tNumberOfBitsForOneSend = tNumberOfBits;
654 tFlags = tOriginalFlags;
671 if (tNumberOfCommands > 0) {
675 auto tFrameDurationMillis = millis() - tStartOfFrameMillis;
692 uint_fast8_t aNumberOfBits, int_fast8_t aNumberOfRepeats) {
694 #if defined(LOCAL_DEBUG)
695 Serial.print(F(
"Data=0x"));
696 Serial.print(aData, HEX);
697 Serial.print(F(
" #="));
698 Serial.println(aNumberOfBits);
719 while (tNumberOfCommands > 0) {
720 unsigned long tStartOfFrameMillis = millis();
736 if (tNumberOfCommands > 0) {
737 auto tCurrentFrameDurationMillis = millis() - tStartOfFrameMillis;
759 uint16_t aOneMarkMicros, uint16_t aOneSpaceMicros, uint16_t aZeroMarkMicros, uint16_t aZeroSpaceMicros,
IRRawDataType aData,
760 uint_fast8_t aNumberOfBits, uint8_t aFlags, uint16_t aRepeatPeriodMillis, int_fast8_t aNumberOfRepeats,
761 void (*aSpecialSendRepeatFunction)()) {
764 if (aSpecialSendRepeatFunction != NULL) {
765 aSpecialSendRepeatFunction();
776 while (tNumberOfCommands > 0) {
777 unsigned long tStartOfFrameMillis = millis();
779 if (tNumberOfCommands < ((uint_fast8_t)
aNumberOfRepeats + 1) && aSpecialSendRepeatFunction != NULL) {
781 aSpecialSendRepeatFunction();
784 mark(aHeaderMarkMicros);
785 space(aHeaderSpaceMicros);
792 if (tNumberOfCommands > 0) {
796 auto tFrameDurationMillis = millis() - tStartOfFrameMillis;
797 if (aRepeatPeriodMillis > tFrameDurationMillis) {
798 delay(aRepeatPeriodMillis - tFrameDurationMillis);
813 uint_fast8_t aNumberOfBits) {
829 uint16_t aZeroSpaceMicros,
IRRawDataType aData, uint_fast8_t aNumberOfBits, uint8_t aFlags) {
831 #if defined(LOCAL_DEBUG)
832 Serial.print(aData, HEX);
834 Serial.println(aNumberOfBits);
840 for (uint_fast8_t i = aNumberOfBits; i > 0; i--) {
842 #if defined(LOCAL_TRACE)
845 mark(aOneMarkMicros);
846 space(aOneSpaceMicros);
848 #if defined(LOCAL_TRACE)
851 mark(aZeroMarkMicros);
852 space(aZeroSpaceMicros);
865 if ((!(aFlags &
SUPPRESS_STOP_BIT)) && (abs(aOneSpaceMicros - aZeroSpaceMicros) > (aOneSpaceMicros / 4))) {
867 #if defined(LOCAL_TRACE)
870 mark(aOneMarkMicros);
872 #if defined(LOCAL_TRACE)
892 #if defined(LOCAL_TRACE)
898 uint32_t tMask = 1UL << aNumberOfBits;
899 uint_fast8_t tLastBitValue = 1;
900 bool tNextBitIsOne = 1;
901 for (uint_fast8_t i = aNumberOfBits + 1; i > 0; i--) {
902 bool tCurrentBitIsOne = tNextBitIsOne;
904 tNextBitIsOne = ((aData & tMask) != 0) || (i == 1);
905 if (tCurrentBitIsOne) {
906 #if defined(LOCAL_TRACE)
909 space(aBiphaseTimeUnit);
911 mark(aBiphaseTimeUnit);
914 mark(2 * aBiphaseTimeUnit);
919 #if defined(LOCAL_TRACE)
922 if (!tLastBitValue) {
923 mark(aBiphaseTimeUnit);
925 space(aBiphaseTimeUnit);
949 #if defined(SEND_PWM_BY_TIMER) || defined(USE_NO_SEND_PWM)
950 # if !defined(NO_LED_FEEDBACK_CODE)
957 #if defined(SEND_PWM_BY_TIMER)
966 #elif defined(USE_NO_SEND_PWM)
970 # if defined(USE_OPEN_DRAIN_OUTPUT_FOR_SEND_PIN) && !defined(OUTPUT_OPEN_DRAIN)
973 # elif defined(USE_ACTIVE_HIGH_OUTPUT_FOR_SEND_PIN)
981 # if !defined(NO_LED_FEEDBACK_CODE)
988 #else // defined(SEND_PWM_BY_TIMER)
992 unsigned long tStartMicros = micros();
993 unsigned long tNextPeriodEnding = tStartMicros;
994 unsigned long tMicros;
995 # if !defined(NO_LED_FEEDBACK_CODE)
996 bool FeedbackLedIsActive =
false;
1005 # if defined(USE_OPEN_DRAIN_OUTPUT_FOR_SEND_PIN)
1006 # if defined(OUTPUT_OPEN_DRAIN)
1021 # if defined(USE_OPEN_DRAIN_OUTPUT_FOR_SEND_PIN) && !defined(OUTPUT_OPEN_DRAIN)
1022 # if defined(OUTPUT_OPEN_DRAIN)
1037 # if !defined(NO_LED_FEEDBACK_CODE)
1041 if (!FeedbackLedIsActive) {
1042 FeedbackLedIsActive =
true;
1056 #if defined(__AVR__) // micros() for STM sometimes give decreasing values if interrupts are disabled. See https://github.com/stm32duino/Arduino_Core_STM32/issues/1680
1060 #if defined(_IR_MEASURE_TIMING) && defined(_IR_TIMING_TEST_PIN)
1070 #if defined(_IR_MEASURE_TIMING) && defined(_IR_TIMING_TEST_PIN)
1077 uint16_t tDeltaMicros = tMicros - tStartMicros;
1078 #if defined(__AVR__)
1081 # if !defined(NO_LED_FEEDBACK_CODE)
1082 if (tDeltaMicros >= aMarkMicros - (30 + (112 / CLOCKS_PER_MICRO))) {
1089 if (tDeltaMicros >= aMarkMicros - (112 / CLOCKS_PER_MICRO)) {
1091 if (tDeltaMicros >= aMarkMicros) {
1092 # if !defined(NO_LED_FEEDBACK_CODE)
1098 #if defined(__AVR__)
1103 }
while (tMicros < tNextPeriodEnding);
1114 #if defined(SEND_PWM_BY_TIMER)
1116 #elif defined(USE_NO_SEND_PWM)
1117 # if defined(USE_OPEN_DRAIN_OUTPUT_FOR_SEND_PIN) && !defined(OUTPUT_OPEN_DRAIN)
1120 # elif defined(USE_ACTIVE_HIGH_OUTPUT_FOR_SEND_PIN)
1126 # if defined(USE_OPEN_DRAIN_OUTPUT_FOR_SEND_PIN)
1127 # if defined(OUTPUT_OPEN_DRAIN)
1137 #if !defined(NO_LED_FEEDBACK_CODE)
1157 #if defined(ESP32) || defined(ESP8266)
1162 if (aMicroseconds > 16383) {
1163 delay(aMicroseconds / 1000UL);
1165 delayMicroseconds(
static_cast<uint16_t
>(aMicroseconds % 1000UL));
1167 delayMicroseconds(aMicroseconds);
1171 # if defined(__AVR__)
1172 unsigned long start = micros() - (64 / clockCyclesPerMicrosecond());
1174 unsigned long start = micros();
1177 while (micros() - start < aMicroseconds) {
1189 #if defined(SEND_PWM_BY_TIMER)
1192 #elif defined(USE_NO_SEND_PWM)
1193 (void) aFrequencyKHz;
1197 # if defined(IR_SEND_PIN)
1203 #endif // defined(SEND_PWM_BY_TIMER)
1205 #if defined(USE_OPEN_DRAIN_OUTPUT_FOR_SEND_PIN) && defined(OUTPUT_OPEN_DRAIN) // the mode INPUT for mimicking open drain is set at IRLedOff()
1206 # if defined(IR_SEND_PIN)
1215 # if defined(__AVR__) || !defined(SEND_PWM_BY_TIMER)
1216 # if defined(IR_SEND_PIN)
1222 #endif // defined(USE_OPEN_DRAIN_OUTPUT_FOR_SEND_PIN)
1225 #if defined(SEND_PWM_BY_TIMER)
1227 void IRsend::enableHighFrequencyIROut(uint_fast16_t aFrequencyKHz) {
1231 # if defined(__AVR__)
1232 # if defined(IR_SEND_PIN)
1246 #if defined(_IR_MEASURE_TIMING)
1247 #undef _IR_MEASURE_TIMING
1249 #if defined(LOCAL_TRACE)
1252 #if defined(LOCAL_DEBUG)
1255 #endif // _IR_SEND_HPP