35 #if defined(DEBUG) && !defined(LOCAL_DEBUG)
41 #if defined(TRACE) && !defined(LOCAL_TRACE)
50 #if defined(IR_SEND_PIN)
51 #define sendPin IR_SEND_PIN
62 #if !defined(IR_SEND_PIN)
66 #if !defined(NO_LED_FEEDBACK_CODE)
71 #if defined(IR_SEND_PIN)
77 # if !defined(NO_LED_FEEDBACK_CODE)
87 void IRsend::begin(
bool aEnableLEDFeedback, uint_fast8_t aFeedbackLEDPin) {
88 #if !defined(NO_LED_FEEDBACK_CODE)
90 if(aEnableLEDFeedback) {
95 (void) aEnableLEDFeedback;
96 (void) aFeedbackLEDPin;
100 #else // defined(IR_SEND_PIN)
103 # if !defined(NO_LED_FEEDBACK_CODE)
114 # if !defined(NO_LED_FEEDBACK_CODE)
129 void IRsend::begin(uint_fast8_t aSendPin,
bool aEnableLEDFeedback, uint_fast8_t aFeedbackLEDPin) {
130 #if defined(IR_SEND_PIN)
136 #if !defined(NO_LED_FEEDBACK_CODE)
138 if (aEnableLEDFeedback) {
143 (void) aEnableLEDFeedback;
144 (void) aFeedbackLEDPin;
147 #endif // defined(IR_SEND_PIN)
157 auto tProtocol = aIRSendData->
protocol;
158 auto tAddress = aIRSendData->
address;
159 auto tCommand = aIRSendData->
command;
199 if (tProtocol ==
NEC) {
202 }
else if (tProtocol ==
SAMSUNG) {
211 }
else if (tProtocol ==
SONY) {
217 }
else if (tProtocol ==
DENON) {
220 }
else if (tProtocol ==
SHARP) {
223 }
else if (tProtocol ==
LG) {
226 }
else if (tProtocol ==
JVC) {
229 }
else if (tProtocol ==
RC5) {
232 }
else if (tProtocol ==
RC6) {
247 }
else if (tProtocol ==
NEC2) {
250 }
else if (tProtocol ==
ONKYO) {
253 }
else if (tProtocol ==
APPLE) {
256 #if !defined(EXCLUDE_EXOTIC_PROTOCOLS)
264 }
else if (tProtocol ==
LEGO_PF) {
278 void IRsend::sendRaw(
const uint16_t aBufferWithMicroseconds[], uint_fast16_t aLengthOfBuffer, uint_fast8_t aIRFrequencyKilohertz) {
285 for (uint_fast16_t i = 0; i < aLengthOfBuffer; i++) {
288 space(aBufferWithMicroseconds[i]);
290 mark(aBufferWithMicroseconds[i]);
294 #if !defined(DISABLE_CODE_FOR_RECEIVER)
303 void IRsend::sendRaw(
const uint8_t aBufferWithTicks[], uint_fast16_t aLengthOfBuffer, uint_fast8_t aIRFrequencyKilohertz) {
307 for (uint_fast16_t i = 0; i < aLengthOfBuffer; i++) {
316 #if !defined(DISABLE_CODE_FOR_RECEIVER)
326 uint_fast8_t aIRFrequencyKilohertz) {
327 #if !defined(__AVR__)
328 sendRaw(aBufferWithMicroseconds, aLengthOfBuffer, aIRFrequencyKilohertz);
335 for (uint_fast16_t i = 0; i < aLengthOfBuffer; i++) {
336 unsigned int duration = pgm_read_word(&aBufferWithMicroseconds[i]);
344 # if !defined(DISABLE_CODE_FOR_RECEIVER)
354 void IRsend::sendRaw_P(
const uint8_t aBufferWithTicks[], uint_fast16_t aLengthOfBuffer, uint_fast8_t aIRFrequencyKilohertz) {
355 #if !defined(__AVR__)
356 sendRaw(aBufferWithTicks, aLengthOfBuffer, aIRFrequencyKilohertz);
361 for (uint_fast16_t i = 0; i < aLengthOfBuffer; i++) {
362 unsigned int duration = pgm_read_byte(&aBufferWithTicks[i]) * (
unsigned int)
MICROS_PER_TICK;
371 # if !defined(DISABLE_CODE_FOR_RECEIVER)
384 unsigned int aHeaderSpaceMicros,
unsigned int aOneMarkMicros,
unsigned int aOneSpaceMicros,
unsigned int aZeroMarkMicros,
385 unsigned int aZeroSpaceMicros,
IRRawDataType *aDecodedRawDataArray,
unsigned int aNumberOfBits,
bool aMSBFirst,
386 bool aSendStopBit,
unsigned int aRepeatPeriodMillis, int_fast8_t aNumberOfRepeats) {
392 uint_fast8_t tNumberOf32BitChunks = ((aNumberOfBits - 1) / 32) + 1;
394 #if defined(LOCAL_DEBUG)
396 Serial.print(F(
"Data[0]=0x"));
397 Serial.print(aDecodedRawDataArray[0], HEX);
398 if (tNumberOf32BitChunks > 1) {
399 Serial.print(F(
" Data[1]=0x"));
400 Serial.print(aDecodedRawDataArray[1], HEX);
402 Serial.print(F(
" #="));
403 Serial.println(aNumberOfBits);
407 while (tNumberOfCommands > 0) {
408 unsigned long tStartOfFrameMillis = millis();
411 mark(aHeaderMarkMicros);
412 space(aHeaderSpaceMicros);
414 for (uint_fast8_t i = 0; i < tNumberOf32BitChunks; ++i) {
415 uint8_t tNumberOfBitsForOneSend;
416 if (aNumberOfBits > 32) {
417 tNumberOfBitsForOneSend = 32;
419 tNumberOfBitsForOneSend = aNumberOfBits;
424 if (i == (tNumberOf32BitChunks - 1)) {
426 tSendStopBit = aSendStopBit;
429 tSendStopBit =
false;
433 tNumberOfBitsForOneSend, aMSBFirst, tSendStopBit);
439 if (tNumberOfCommands > 0) {
443 auto tFrameDurationMillis = millis() - tStartOfFrameMillis;
444 if (aRepeatPeriodMillis > tFrameDurationMillis) {
445 delay(aRepeatPeriodMillis - tFrameDurationMillis);
449 #if !defined(DISABLE_CODE_FOR_RECEIVER)
461 IRRawDataType *aDecodedRawDataArray,
unsigned int aNumberOfBits, int_fast8_t aNumberOfRepeats) {
466 uint_fast8_t tNumberOf32BitChunks = ((aNumberOfBits - 1) / 32) + 1;
468 #if defined(LOCAL_DEBUG)
470 Serial.print(F(
"Data[0]=0x"));
471 Serial.print(aDecodedRawDataArray[0], HEX);
472 if (tNumberOf32BitChunks > 1) {
473 Serial.print(F(
" Data[1]=0x"));
474 Serial.print(aDecodedRawDataArray[1], HEX);
476 Serial.print(F(
" #="));
477 Serial.println(aNumberOfBits);
482 while (tNumberOfCommands > 0) {
483 auto tStartOfFrameMillis = millis();
484 auto tNumberOfBits = aNumberOfBits;
489 bool tHasStopBit = aProtocolConstants->
hasStopBit;
491 for (uint_fast8_t i = 0; i < tNumberOf32BitChunks; ++i) {
492 uint8_t tNumberOfBitsForOneSend;
494 if (i == (tNumberOf32BitChunks - 1)) {
496 tNumberOfBitsForOneSend = tNumberOfBits;
500 tNumberOfBitsForOneSend = 32;
509 if (tNumberOfCommands > 0) {
513 auto tFrameDurationMillis = millis() - tStartOfFrameMillis;
519 #if !defined(DISABLE_CODE_FOR_RECEIVER)
533 uint_fast8_t aNumberOfBits, int_fast8_t aNumberOfRepeats) {
548 while (tNumberOfCommands > 0) {
549 unsigned long tStartOfFrameMillis = millis();
565 if (tNumberOfCommands > 0) {
569 auto tFrameDurationMillis = millis() - tStartOfFrameMillis;
575 #if !defined(DISABLE_CODE_FOR_RECEIVER)
590 unsigned int aOneMarkMicros,
unsigned int aOneSpaceMicros,
unsigned int aZeroMarkMicros,
unsigned int aZeroSpaceMicros,
591 IRRawDataType aData, uint_fast8_t aNumberOfBits,
bool aMSBFirst,
bool aSendStopBit,
unsigned int aRepeatPeriodMillis,
592 int_fast8_t aNumberOfRepeats,
void (*aSpecialSendRepeatFunction)()) {
595 if (aSpecialSendRepeatFunction != NULL) {
596 aSpecialSendRepeatFunction();
607 while (tNumberOfCommands > 0) {
608 unsigned long tStartOfFrameMillis = millis();
610 if (tNumberOfCommands < ((uint_fast8_t)
aNumberOfRepeats + 1) && aSpecialSendRepeatFunction != NULL) {
612 aSpecialSendRepeatFunction();
615 mark(aHeaderMarkMicros);
616 space(aHeaderSpaceMicros);
618 aMSBFirst, aSendStopBit);
623 if (tNumberOfCommands > 0) {
627 auto tFrameDurationMillis = millis() - tStartOfFrameMillis;
628 if (aRepeatPeriodMillis > tFrameDurationMillis) {
629 delay(aRepeatPeriodMillis - tFrameDurationMillis);
633 #if !defined(DISABLE_CODE_FOR_RECEIVER)
644 uint_fast8_t aNumberOfBits) {
656 unsigned int aZeroSpaceMicros,
IRRawDataType aData, uint_fast8_t aNumberOfBits,
bool aMSBFirst,
bool aSendStopBit) {
658 #if defined(LOCAL_DEBUG)
667 for (uint_fast8_t i = aNumberOfBits; i > 0; i--) {
668 if ((aMSBFirst && (aData & tMask)) || (!aMSBFirst && (aData & 1))) {
669 #if defined(LOCAL_TRACE)
672 mark(aOneMarkMicros);
673 space(aOneSpaceMicros);
675 #if defined(LOCAL_TRACE)
678 mark(aZeroMarkMicros);
679 space(aZeroSpaceMicros);
688 #if defined(LOCAL_TRACE)
691 mark(aZeroMarkMicros);
693 #if defined(LOCAL_TRACE)
711 #if defined(LOCAL_TRACE)
717 uint32_t tMask = 1UL << aNumberOfBits;
718 uint_fast8_t tLastBitValue = 1;
719 bool tNextBitIsOne = 1;
720 for (uint_fast8_t i = aNumberOfBits + 1; i > 0; i--) {
721 bool tCurrentBitIsOne = tNextBitIsOne;
723 tNextBitIsOne = ((aData & tMask) != 0) || (i == 1);
724 if (tCurrentBitIsOne) {
725 #if defined(LOCAL_TRACE)
728 space(aBiphaseTimeUnit);
730 mark(aBiphaseTimeUnit);
733 mark(2 * aBiphaseTimeUnit);
738 #if defined(LOCAL_TRACE)
741 if (!tLastBitValue) {
742 mark(aBiphaseTimeUnit);
744 space(aBiphaseTimeUnit);
759 #if defined(SEND_PWM_BY_TIMER) || defined(USE_NO_SEND_PWM)
760 # if !defined(NO_LED_FEEDBACK_CODE)
767 #if defined(SEND_PWM_BY_TIMER)
776 #elif defined(USE_NO_SEND_PWM)
780 # if defined(USE_OPEN_DRAIN_OUTPUT_FOR_SEND_PIN) && !defined(OUTPUT_OPEN_DRAIN)
788 # if !defined(NO_LED_FEEDBACK_CODE)
795 #else // defined(SEND_PWM_BY_TIMER)
799 unsigned long tStartMicros = micros();
800 unsigned long tNextPeriodEnding = tStartMicros;
801 unsigned long tMicros;
802 # if !defined(NO_LED_FEEDBACK_CODE)
803 bool FeedbackLedIsActive =
false;
812 # if defined(USE_OPEN_DRAIN_OUTPUT_FOR_SEND_PIN)
813 # if defined(OUTPUT_OPEN_DRAIN)
828 # if defined(USE_OPEN_DRAIN_OUTPUT_FOR_SEND_PIN) && !defined(OUTPUT_OPEN_DRAIN)
829 # if defined(OUTPUT_OPEN_DRAIN)
840 # if !defined(NO_LED_FEEDBACK_CODE)
844 if (!FeedbackLedIsActive) {
845 FeedbackLedIsActive =
true;
861 unsigned int tDeltaMicros = tMicros - tStartMicros;
864 # if !defined(NO_LED_FEEDBACK_CODE)
865 if (tDeltaMicros >= aMarkMicros - (30 + (112 / CLOCKS_PER_MICRO))) {
873 if (tDeltaMicros >= aMarkMicros - (112 / CLOCKS_PER_MICRO)) {
875 if (tDeltaMicros >= aMarkMicros) {
876 # if !defined(NO_LED_FEEDBACK_CODE)
884 }
while (tMicros < tNextPeriodEnding);
895 #if defined(SEND_PWM_BY_TIMER)
897 #elif defined(USE_NO_SEND_PWM)
898 # if defined(USE_OPEN_DRAIN_OUTPUT_FOR_SEND_PIN) && !defined(OUTPUT_OPEN_DRAIN)
905 # if defined(USE_OPEN_DRAIN_OUTPUT_FOR_SEND_PIN)
906 # if defined(OUTPUT_OPEN_DRAIN)
916 #if !defined(NO_LED_FEEDBACK_CODE)
936 #if defined(ESP32) || defined(ESP8266)
939 delay(aMicroseconds / 1000UL);
941 delayMicroseconds(
static_cast<uint16_t
>(aMicroseconds % 1000UL));
944 # if defined(__AVR__)
945 unsigned long start = micros() - (64 / clockCyclesPerMicrosecond());
947 unsigned long start = micros();
950 while (micros() - start < aMicroseconds) {
962 #if defined(SEND_PWM_BY_TIMER)
965 #elif defined(USE_NO_SEND_PWM)
966 (void) aFrequencyKHz;
970 # if defined(IR_SEND_PIN)
976 #endif // defined(SEND_PWM_BY_TIMER)
978 #if defined(USE_OPEN_DRAIN_OUTPUT_FOR_SEND_PIN) && defined(OUTPUT_OPEN_DRAIN) // the mode INPUT for mimicking open drain is set at IRLedOff()
979 # if defined(IR_SEND_PIN)
988 # if defined(__AVR__) || !defined(SEND_PWM_BY_TIMER)
989 # if defined(IR_SEND_PIN)
995 #endif // defined(USE_OPEN_DRAIN_OUTPUT_FOR_SEND_PIN)
1003 #if defined(LOCAL_TRACE)
1006 #if defined(LOCAL_DEBUG)
1009 #endif // _IR_SEND_HPP