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);
601 uint16_t aOneMarkMicros, uint16_t aOneSpaceMicros, uint16_t aZeroMarkMicros, uint16_t aZeroSpaceMicros,
602 IRRawDataType const *aDecodedRawDataPGMArray, uint16_t aNumberOfBits, uint8_t aFlags, uint16_t aRepeatPeriodMillis,
603 int_fast8_t aNumberOfRepeats) {
611 #if defined(LOCAL_DEBUG)
613 Serial.print(F(
"Data[0]=0x"));
614 Serial.print(aDecodedRawDataArray[0], HEX);
615 if (tNumberOf32Or64BitChunks > 1) {
616 Serial.print(F(
" Data[1]=0x"));
617 Serial.print(aDecodedRawDataArray[1], HEX);
619 Serial.print(F(
" #="));
620 Serial.println(aNumberOfBits);
624 while (tNumberOfCommands > 0) {
625 unsigned long tStartOfFrameMillis = millis();
628 mark(aHeaderMarkMicros);
629 space(aHeaderSpaceMicros);
631 for (uint_fast8_t i = 0; i < tNumberOf32Or64BitChunks; ++i) {
632 uint8_t tNumberOfBitsForOneSend;
636 if (i == (tNumberOf32Or64BitChunks - 1)) {
638 tNumberOfBitsForOneSend = aNumberOfBits;
647 #if (__INT_WIDTH__ < 32)
648 tDecodedRawData = pgm_read_word(&aDecodedRawDataPGMArray[i]);
650 tDecodedRawData = pgm_read_dword(&aDecodedRawDataPGMArray[i]);
653 tNumberOfBitsForOneSend, tFlags);
659 if (tNumberOfCommands > 0) {
663 auto tFrameDurationMillis = millis() - tStartOfFrameMillis;
664 if (aRepeatPeriodMillis > tFrameDurationMillis) {
665 delay(aRepeatPeriodMillis - tFrameDurationMillis);
673 uint16_t aNumberOfBits, uint8_t aFlags, uint16_t aRepeatPeriodMillis, int_fast8_t aNumberOfRepeats) {
676 memcpy_P(&tTemporaryDistanceWidthTimingInfo, aDistanceWidthTimingInfoPGM,
sizeof(tTemporaryDistanceWidthTimingInfo));
691 IRRawDataType *aDecodedRawDataArray, uint16_t aNumberOfBits, int_fast8_t aNumberOfRepeats) {
705 #if defined(LOCAL_DEBUG)
707 Serial.print(F(
"Data[0]=0x"));
708 Serial.print(aDecodedRawDataArray[0], HEX);
709 if (tNumberOf32Or64BitChunks > 1) {
710 Serial.print(F(
" Data[1]=0x"));
711 Serial.print(aDecodedRawDataArray[1], HEX);
713 Serial.print(F(
" #="));
714 Serial.println(aNumberOfBits);
719 while (tNumberOfCommands > 0) {
720 auto tStartOfFrameMillis = millis();
721 auto tNumberOfBits = aNumberOfBits;
726 uint8_t tOriginalFlags = aProtocolConstants->
Flags;
728 for (uint_fast8_t i = 0; i < tNumberOf32Or64BitChunks; ++i) {
729 uint8_t tNumberOfBitsForOneSend;
732 if (i == (tNumberOf32Or64BitChunks - 1)) {
734 tNumberOfBitsForOneSend = tNumberOfBits;
735 tFlags = tOriginalFlags;
752 if (tNumberOfCommands > 0) {
756 auto tFrameDurationMillis = millis() - tStartOfFrameMillis;
765 IRRawDataType *aDecodedRawDataArray, uint16_t aNumberOfBits, int_fast8_t aNumberOfRepeats) {
768 memcpy_P(&tTemporaryPulseDistanceWidthProtocolConstants, aProtocolConstantsPGM,
769 sizeof(tTemporaryPulseDistanceWidthProtocolConstants));
774 IRRawDataType const *aDecodedRawDataPGMArray, uint16_t aNumberOfBits, int_fast8_t aNumberOfRepeats) {
777 memcpy_P(&tTemporaryPulseDistanceWidthProtocolConstants, aProtocolConstantsPGM,
778 sizeof(tTemporaryPulseDistanceWidthProtocolConstants));
784 IRRawDataType const*aDecodedRawDataPGMArray, uint16_t aNumberOfBits, int_fast8_t aNumberOfRepeats) {
798 #if defined(LOCAL_DEBUG)
800 Serial.print(F(
"Data[0]=0x"));
801 Serial.print(aDecodedRawDataArray[0], HEX);
802 if (tNumberOf32Or64BitChunks > 1) {
803 Serial.print(F(
" Data[1]=0x"));
804 Serial.print(aDecodedRawDataArray[1], HEX);
806 Serial.print(F(
" #="));
807 Serial.println(aNumberOfBits);
812 while (tNumberOfCommands > 0) {
813 auto tStartOfFrameMillis = millis();
814 auto tNumberOfBits = aNumberOfBits;
819 uint8_t tOriginalFlags = aProtocolConstants->
Flags;
821 for (uint_fast8_t i = 0; i < tNumberOf32Or64BitChunks; ++i) {
822 uint8_t tNumberOfBitsForOneSend;
825 if (i == (tNumberOf32Or64BitChunks - 1)) {
827 tNumberOfBitsForOneSend = tNumberOfBits;
828 tFlags = tOriginalFlags;
836 #if (__INT_WIDTH__ < 32)
837 tDecodedRawData = pgm_read_word(&aDecodedRawDataPGMArray[i]);
839 tDecodedRawData = pgm_read_dword(&aDecodedRawDataPGMArray[i]);
851 if (tNumberOfCommands > 0) {
855 auto tFrameDurationMillis = millis() - tStartOfFrameMillis;
872 uint_fast8_t aNumberOfBits, int_fast8_t aNumberOfRepeats) {
874 #if defined(LOCAL_DEBUG)
875 Serial.print(F(
"Data=0x"));
876 Serial.print(aData, HEX);
877 Serial.print(F(
" #="));
878 Serial.println(aNumberOfBits);
899 while (tNumberOfCommands > 0) {
900 unsigned long tStartOfFrameMillis = millis();
916 if (tNumberOfCommands > 0) {
917 auto tCurrentFrameDurationMillis = millis() - tStartOfFrameMillis;
928 uint_fast8_t aNumberOfBits, int_fast8_t aNumberOfRepeats) {
930 memcpy_P(&tTemporaryPulseDistanceWidthProtocolConstants, aProtocolConstantsPGM,
931 sizeof(tTemporaryPulseDistanceWidthProtocolConstants));
946 uint16_t aOneMarkMicros, uint16_t aOneSpaceMicros, uint16_t aZeroMarkMicros, uint16_t aZeroSpaceMicros,
IRRawDataType aData,
947 uint_fast8_t aNumberOfBits, uint8_t aFlags, uint16_t aRepeatPeriodMillis, int_fast8_t aNumberOfRepeats,
948 void (*aSpecialSendRepeatFunction)()) {
951 if (aSpecialSendRepeatFunction !=
nullptr) {
952 aSpecialSendRepeatFunction();
963 while (tNumberOfCommands > 0) {
964 unsigned long tStartOfFrameMillis = millis();
966 if (tNumberOfCommands < ((uint_fast8_t)
aNumberOfRepeats + 1) && aSpecialSendRepeatFunction !=
nullptr) {
968 aSpecialSendRepeatFunction();
971 mark(aHeaderMarkMicros);
972 space(aHeaderSpaceMicros);
979 if (tNumberOfCommands > 0) {
983 auto tFrameDurationMillis = millis() - tStartOfFrameMillis;
984 if (aRepeatPeriodMillis > tFrameDurationMillis) {
985 delay(aRepeatPeriodMillis - tFrameDurationMillis);
1000 uint_fast8_t aNumberOfBits) {
1008 uint_fast8_t aNumberOfBits) {
1011 memcpy_P(&tTemporaryPulseDistanceWidthProtocolConstants, aProtocolConstantsPGM,
1012 sizeof(tTemporaryPulseDistanceWidthProtocolConstants));
1025 uint16_t aZeroSpaceMicros,
IRRawDataType aData, uint_fast8_t aNumberOfBits, uint8_t aFlags) {
1027 #if defined(LOCAL_DEBUG)
1028 Serial.print(aData, HEX);
1030 Serial.println(aNumberOfBits);
1036 for (uint_fast8_t i = aNumberOfBits; i > 0; i--) {
1038 #if defined(LOCAL_TRACE)
1041 mark(aOneMarkMicros);
1042 space(aOneSpaceMicros);
1044 #if defined(LOCAL_TRACE)
1047 mark(aZeroMarkMicros);
1048 space(aZeroSpaceMicros);
1061 if ((!(aFlags &
SUPPRESS_STOP_BIT)) && (abs(aOneSpaceMicros - aZeroSpaceMicros) > (aOneSpaceMicros / 4))) {
1063 #if defined(LOCAL_TRACE)
1066 mark(aOneMarkMicros);
1068 #if defined(LOCAL_TRACE)
1088 #if defined(LOCAL_TRACE)
1094 uint32_t tMask = 1UL << aNumberOfBits;
1095 uint_fast8_t tLastBitValue = 1;
1096 bool tNextBitIsOne = 1;
1097 for (uint_fast8_t i = aNumberOfBits + 1; i > 0; i--) {
1098 bool tCurrentBitIsOne = tNextBitIsOne;
1100 tNextBitIsOne = ((aData & tMask) != 0) || (i == 1);
1101 if (tCurrentBitIsOne) {
1102 #if defined(LOCAL_TRACE)
1105 space(aBiphaseTimeUnit);
1106 if (tNextBitIsOne) {
1107 mark(aBiphaseTimeUnit);
1110 mark(2 * aBiphaseTimeUnit);
1115 #if defined(LOCAL_TRACE)
1118 if (!tLastBitValue) {
1119 mark(aBiphaseTimeUnit);
1121 space(aBiphaseTimeUnit);
1145 #if defined(SEND_PWM_BY_TIMER) || defined(USE_NO_SEND_PWM)
1146 # if !defined(NO_LED_FEEDBACK_CODE)
1153 #if defined(SEND_PWM_BY_TIMER)
1162 #elif defined(USE_NO_SEND_PWM)
1166 # if defined(USE_OPEN_DRAIN_OUTPUT_FOR_SEND_PIN) && !defined(OUTPUT_OPEN_DRAIN)
1169 # elif defined(USE_ACTIVE_HIGH_OUTPUT_FOR_SEND_PIN)
1177 # if !defined(NO_LED_FEEDBACK_CODE)
1184 #else // defined(SEND_PWM_BY_TIMER)
1188 unsigned long tStartMicros = micros();
1189 unsigned long tNextPeriodEnding = tStartMicros;
1190 unsigned long tMicros;
1191 # if !defined(NO_LED_FEEDBACK_CODE)
1192 bool FeedbackLedIsActive =
false;
1201 # if defined(USE_OPEN_DRAIN_OUTPUT_FOR_SEND_PIN)
1202 # if defined(OUTPUT_OPEN_DRAIN)
1217 # if defined(USE_OPEN_DRAIN_OUTPUT_FOR_SEND_PIN) && !defined(OUTPUT_OPEN_DRAIN)
1218 # if defined(OUTPUT_OPEN_DRAIN)
1233 # if !defined(NO_LED_FEEDBACK_CODE)
1237 if (!FeedbackLedIsActive) {
1238 FeedbackLedIsActive =
true;
1252 #if defined(__AVR__) // micros() for STM sometimes give decreasing values if interrupts are disabled. See https://github.com/stm32duino/Arduino_Core_STM32/issues/1680
1256 #if defined(_IR_MEASURE_TIMING) && defined(_IR_TIMING_TEST_PIN)
1266 #if defined(_IR_MEASURE_TIMING) && defined(_IR_TIMING_TEST_PIN)
1273 uint16_t tDeltaMicros = tMicros - tStartMicros;
1274 #if defined(__AVR__)
1277 # if !defined(NO_LED_FEEDBACK_CODE)
1278 if (tDeltaMicros >= aMarkMicros - (30 + (112 / CLOCKS_PER_MICRO))) {
1285 if (tDeltaMicros >= aMarkMicros - (112 / CLOCKS_PER_MICRO)) {
1287 if (tDeltaMicros >= aMarkMicros) {
1288 # if !defined(NO_LED_FEEDBACK_CODE)
1294 #if defined(__AVR__)
1299 }
while (tMicros < tNextPeriodEnding);
1310 #if defined(SEND_PWM_BY_TIMER)
1312 #elif defined(USE_NO_SEND_PWM)
1313 # if defined(USE_OPEN_DRAIN_OUTPUT_FOR_SEND_PIN) && !defined(OUTPUT_OPEN_DRAIN)
1316 # elif defined(USE_ACTIVE_HIGH_OUTPUT_FOR_SEND_PIN)
1322 # if defined(USE_OPEN_DRAIN_OUTPUT_FOR_SEND_PIN)
1323 # if defined(OUTPUT_OPEN_DRAIN)
1333 #if !defined(NO_LED_FEEDBACK_CODE)
1353 #if defined(ESP32) || defined(ESP8266)
1358 if (aMicroseconds > 16383) {
1359 delay(aMicroseconds / 1000UL);
1361 delayMicroseconds(
static_cast<uint16_t
>(aMicroseconds % 1000UL));
1363 delayMicroseconds(aMicroseconds);
1367 # if defined(__AVR__)
1368 unsigned long start = micros() - (64 / clockCyclesPerMicrosecond());
1370 unsigned long start = micros();
1373 while (micros() - start < aMicroseconds) {
1385 #if defined(SEND_PWM_BY_TIMER)
1388 #elif defined(USE_NO_SEND_PWM)
1389 (void) aFrequencyKHz;
1393 # if defined(IR_SEND_PIN)
1399 #endif // defined(SEND_PWM_BY_TIMER)
1401 #if defined(USE_OPEN_DRAIN_OUTPUT_FOR_SEND_PIN) && defined(OUTPUT_OPEN_DRAIN) // the mode INPUT for mimicking open drain is set at IRLedOff()
1402 # if defined(IR_SEND_PIN)
1411 # if defined(__AVR__) || !defined(SEND_PWM_BY_TIMER)
1412 # if defined(IR_SEND_PIN)
1418 #endif // defined(USE_OPEN_DRAIN_OUTPUT_FOR_SEND_PIN)
1421 #if defined(SEND_PWM_BY_TIMER)
1423 void IRsend::enableHighFrequencyIROut(uint_fast16_t aFrequencyKHz) {
1427 # if defined(__AVR__)
1428 # if defined(IR_SEND_PIN)
1442 #if defined(_IR_MEASURE_TIMING)
1443 #undef _IR_MEASURE_TIMING
1445 #if defined(LOCAL_TRACE)
1448 #if defined(LOCAL_DEBUG)
1451 #endif // _IR_SEND_HPP