IRremote
IRSend.hpp
Go to the documentation of this file.
1 /*
2  * IRSend.hpp
3  *
4  * Contains common functions for sending
5  *
6  * This file is part of Arduino-IRremote https://github.com/Arduino-IRremote/Arduino-IRremote.
7  *
8  ************************************************************************************
9  * MIT License
10  *
11  * Copyright (c) 2009-2023 Ken Shirriff, Rafi Khan, Armin Joachimsmeyer
12  *
13  * Permission is hereby granted, free of charge, to any person obtaining a copy
14  * of this software and associated documentation files (the "Software"), to deal
15  * in the Software without restriction, including without limitation the rights
16  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
17  * copies of the Software, and to permit persons to whom the Software is furnished
18  * to do so, subject to the following conditions:
19  *
20  * The above copyright notice and this permission notice shall be included in all
21  * copies or substantial portions of the Software.
22  *
23  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
24  * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
25  * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
26  * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
27  * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE
28  * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
29  *
30  ************************************************************************************
31  */
32 #ifndef _IR_SEND_HPP
33 #define _IR_SEND_HPP
34 
35 #if defined(DEBUG)
36 #define LOCAL_DEBUG
37 #else
38 //#define LOCAL_DEBUG // This enables debug output only for this file
39 #endif
40 
41 #if defined(TRACE) && !defined(LOCAL_TRACE)
42 #define LOCAL_TRACE
43 #else
44 //#define LOCAL_TRACE // This enables debug output only for this file
45 #endif
46 
47 /*
48  * Low level hardware timing measurement
49  */
50 //#define _IR_MEASURE_TIMING // for mark()
51 //#define _IR_TIMING_TEST_PIN 7 // "pinModeFast(_IR_TIMING_TEST_PIN, OUTPUT);" is executed at begin()
52 //
53 /*
54  * This improves readability of code by avoiding a lot of #if defined clauses
55  */
56 #if defined(IR_SEND_PIN)
57 #define sendPin IR_SEND_PIN
58 #endif
59 
64 // The sender instance
66 
67 IRsend::IRsend() { // @suppress("Class members should be properly initialized")
68 #if !defined(IR_SEND_PIN)
69  sendPin = 0;
70 #endif
71 
72 #if !defined(NO_LED_FEEDBACK_CODE)
74 #endif
75 }
76 
77 #if defined(IR_SEND_PIN)
78 
82 void IRsend::begin(){
83 # if !defined(NO_LED_FEEDBACK_CODE)
85 # endif
86 #if defined(_IR_MEASURE_TIMING) && defined(_IR_TIMING_TEST_PIN)
87  pinModeFast(_IR_TIMING_TEST_PIN, OUTPUT);
88 #endif
89 }
90 
96 void IRsend::begin(bool aEnableLEDFeedback, uint_fast8_t aFeedbackLEDPin) {
97 #if !defined(NO_LED_FEEDBACK_CODE)
98  uint_fast8_t tEnableLEDFeedback = DO_NOT_ENABLE_LED_FEEDBACK;
99  if(aEnableLEDFeedback) {
100  tEnableLEDFeedback = LED_FEEDBACK_ENABLED_FOR_SEND;
101  }
102  setLEDFeedback(aFeedbackLEDPin, tEnableLEDFeedback);
103 #else
104  (void) aEnableLEDFeedback;
105  (void) aFeedbackLEDPin;
106 #endif
107 }
108 
109 #else // defined(IR_SEND_PIN)
110 IRsend::IRsend(uint_fast8_t aSendPin) { // @suppress("Class members should be properly initialized")
111  sendPin = aSendPin;
112 # if !defined(NO_LED_FEEDBACK_CODE)
114 # endif
115 }
116 
121 void IRsend::begin(uint_fast8_t aSendPin) {
122  sendPin = aSendPin;
123 # if !defined(NO_LED_FEEDBACK_CODE)
125 # endif
126 }
127 
128 void IRsend::setSendPin(uint_fast8_t aSendPin) {
129  sendPin = aSendPin;
130 }
131 
138 void IRsend::begin(uint_fast8_t aSendPin, bool aEnableLEDFeedback, uint_fast8_t aFeedbackLEDPin) {
139 #if defined(IR_SEND_PIN)
140  (void) aSendPin; // for backwards compatibility
141 #else
142  sendPin = aSendPin;
143 #endif
144 
145 #if !defined(NO_LED_FEEDBACK_CODE)
146  uint_fast8_t tEnableLEDFeedback = DO_NOT_ENABLE_LED_FEEDBACK;
147  if (aEnableLEDFeedback) {
148  tEnableLEDFeedback = LED_FEEDBACK_ENABLED_FOR_SEND;
149  }
150  setLEDFeedback(aFeedbackLEDPin, tEnableLEDFeedback);
151 #else
152  (void) aEnableLEDFeedback;
153  (void) aFeedbackLEDPin;
154 #endif
155 }
156 #endif // defined(IR_SEND_PIN)
157 
170 size_t IRsend::write(IRData *aIRSendData, int_fast8_t aNumberOfRepeats) {
171 
172  auto tProtocol = aIRSendData->protocol;
173  auto tAddress = aIRSendData->address;
174  auto tCommand = aIRSendData->command;
175  bool tIsRepeat = (aIRSendData->flags & IRDATA_FLAGS_IS_REPEAT);
176  if (tIsRepeat) {
177  aNumberOfRepeats = -1; // if aNumberOfRepeats < 0 then only a special repeat frame will be sent
178  }
179 // switch (tProtocol) { // 26 bytes bigger than if, else if, else
180 // case NEC:
181 // sendNEC(tAddress, tCommand, aNumberOfRepeats, tSendRepeat);
182 // break;
183 // case SAMSUNG:
184 // sendSamsung(tAddress, tCommand, aNumberOfRepeats);
185 // break;
186 // case SONY:
187 // sendSony(tAddress, tCommand, aNumberOfRepeats, aIRSendData->numberOfBits);
188 // break;
189 // case PANASONIC:
190 // sendPanasonic(tAddress, tCommand, aNumberOfRepeats);
191 // break;
192 // case DENON:
193 // sendDenon(tAddress, tCommand, aNumberOfRepeats);
194 // break;
195 // case SHARP:
196 // sendSharp(tAddress, tCommand, aNumberOfRepeats);
197 // break;
198 // case JVC:
199 // sendJVC((uint8_t) tAddress, (uint8_t) tCommand, aNumberOfRepeats); // casts are required to specify the right function
200 // break;
201 // case RC5:
202 // sendRC5(tAddress, tCommand, aNumberOfRepeats, !tSendRepeat); // No toggle for repeats
203 // break;
204 // case RC6:
205 // // No toggle for repeats// sendRC6(tAddress, tCommand, aNumberOfRepeats, !tSendRepeat); // No toggle for repeats
206 // break;
207 // default:
208 // break;
209 // }
210 
211  /*
212  * Order of protocols is in guessed relevance :-)
213  */
214  if (tProtocol == NEC) {
215  sendNEC(tAddress, tCommand, aNumberOfRepeats);
216 
217  } else if (tProtocol == SAMSUNG) {
218  sendSamsung(tAddress, tCommand, aNumberOfRepeats);
219 
220  } else if (tProtocol == SAMSUNG48) {
221  sendSamsung48(tAddress, tCommand, aNumberOfRepeats);
222 
223  } else if (tProtocol == SAMSUNGLG) {
224  sendSamsungLG(tAddress, tCommand, aNumberOfRepeats);
225 
226  } else if (tProtocol == SONY) {
227  sendSony(tAddress, tCommand, aNumberOfRepeats, aIRSendData->numberOfBits);
228 
229  } else if (tProtocol == PANASONIC) {
230  sendPanasonic(tAddress, tCommand, aNumberOfRepeats);
231 
232  } else if (tProtocol == DENON) {
233  sendDenon(tAddress, tCommand, aNumberOfRepeats);
234 
235  } else if (tProtocol == SHARP) {
236  sendSharp(tAddress, tCommand, aNumberOfRepeats);
237 
238  } else if (tProtocol == LG) {
239  sendLG(tAddress, tCommand, aNumberOfRepeats);
240 
241  } else if (tProtocol == JVC) {
242  sendJVC((uint8_t) tAddress, (uint8_t) tCommand, aNumberOfRepeats); // casts are required to specify the right function
243 
244  } else if (tProtocol == RC5) {
245  sendRC5(tAddress, tCommand, aNumberOfRepeats, !tIsRepeat); // No toggle for repeats
246 
247  } else if (tProtocol == RC6) {
248  sendRC6(tAddress, tCommand, aNumberOfRepeats, !tIsRepeat); // No toggle for repeats
249 
250  } else if (tProtocol == KASEIKYO_JVC) {
251  sendKaseikyo_JVC(tAddress, tCommand, aNumberOfRepeats);
252 
253  } else if (tProtocol == KASEIKYO_DENON) {
254  sendKaseikyo_Denon(tAddress, tCommand, aNumberOfRepeats);
255 
256  } else if (tProtocol == KASEIKYO_SHARP) {
257  sendKaseikyo_Sharp(tAddress, tCommand, aNumberOfRepeats);
258 
259  } else if (tProtocol == KASEIKYO_MITSUBISHI) {
260  sendKaseikyo_Mitsubishi(tAddress, tCommand, aNumberOfRepeats);
261 
262  } else if (tProtocol == NEC2) {
263  sendNEC2(tAddress, tCommand, aNumberOfRepeats);
264 
265  } else if (tProtocol == ONKYO) {
266  sendOnkyo(tAddress, tCommand, aNumberOfRepeats);
267 
268  } else if (tProtocol == APPLE) {
269  sendApple(tAddress, tCommand, aNumberOfRepeats);
270 
271 #if !defined(EXCLUDE_EXOTIC_PROTOCOLS)
272  } else if (tProtocol == BOSEWAVE) {
273  sendBoseWave(tCommand, aNumberOfRepeats);
274 
275  } else if (tProtocol == MAGIQUEST) {
276  // we have a 32 bit ID/address
277  sendMagiQuest(aIRSendData->decodedRawData, tCommand);
278 
279  } else if (tProtocol == FAST) {
280  // We have only 8 bit command
281  sendFAST(tCommand, aNumberOfRepeats);
282 
283  } else if (tProtocol == LEGO_PF) {
284  sendLegoPowerFunctions(tAddress, tCommand, tCommand >> 4, tIsRepeat); // send 5 autorepeats
285 #endif
286 
287  } else {
288  return 0; // Not supported by write. E.g for BANG_OLUFSEN
289  }
290  return 1;
291 }
292 
298 size_t IRsend::write(decode_type_t aProtocol, uint16_t aAddress, uint16_t aCommand, int_fast8_t aNumberOfRepeats) {
299 
300 // switch (aProtocol) { // 26 bytes bigger than if, else if, else
301 // case NEC:
302 // sendNEC(aAddress, aCommand, aNumberOfRepeats, tSendRepeat);
303 // break;
304 // case SAMSUNG:
305 // sendSamsung(aAddress, aCommand, aNumberOfRepeats);
306 // break;
307 // case SONY:
308 // sendSony(aAddress, aCommand, aNumberOfRepeats, aIRSendData->numberOfBits);
309 // break;
310 // case PANASONIC:
311 // sendPanasonic(aAddress, aCommand, aNumberOfRepeats);
312 // break;
313 // case DENON:
314 // sendDenon(aAddress, aCommand, aNumberOfRepeats);
315 // break;
316 // case SHARP:
317 // sendSharp(aAddress, aCommand, aNumberOfRepeats);
318 // break;
319 // case JVC:
320 // sendJVC((uint8_t) aAddress, (uint8_t) aCommand, aNumberOfRepeats); // casts are required to specify the right function
321 // break;
322 // case RC5:
323 // sendRC5(aAddress, aCommand, aNumberOfRepeats, !tSendRepeat); // No toggle for repeats
324 // break;
325 // case RC6:
326 // // No toggle for repeats// sendRC6(aAddress, aCommand, aNumberOfRepeats, !tSendRepeat); // No toggle for repeats
327 // break;
328 // default:
329 // break;
330 // }
331 
332  /*
333  * Order of protocols is in guessed relevance :-)
334  */
335  if (aProtocol == NEC) {
336  sendNEC(aAddress, aCommand, aNumberOfRepeats);
337 
338  } else if (aProtocol == SAMSUNG) {
340 
341  } else if (aProtocol == SAMSUNG48) {
343 
344  } else if (aProtocol == SAMSUNGLG) {
346 
347  } else if (aProtocol == SONY) {
349 
350  } else if (aProtocol == PANASONIC) {
352 
353  } else if (aProtocol == DENON) {
354  sendDenon(aAddress, aCommand, aNumberOfRepeats);
355 
356  } else if (aProtocol == SHARP) {
357  sendSharp(aAddress, aCommand, aNumberOfRepeats);
358 
359  } else if (aProtocol == LG) {
360  sendLG(aAddress, aCommand, aNumberOfRepeats);
361 
362  } else if (aProtocol == JVC) {
363  sendJVC((uint8_t) aAddress, (uint8_t) aCommand, aNumberOfRepeats); // casts are required to specify the right function
364 
365  } else if (aProtocol == RC5) {
366  sendRC5(aAddress, aCommand, aNumberOfRepeats, (aNumberOfRepeats > 0)); // No toggle for repeats
367 
368  } else if (aProtocol == RC6) {
369  sendRC6(aAddress, aCommand, aNumberOfRepeats, (aNumberOfRepeats > 0)); // No toggle for repeats
370 
371  } else if (aProtocol == KASEIKYO_JVC) {
373 
374  } else if (aProtocol == KASEIKYO_DENON) {
376 
377  } else if (aProtocol == KASEIKYO_SHARP) {
379 
380  } else if (aProtocol == KASEIKYO_MITSUBISHI) {
382 
383  } else if (aProtocol == NEC2) {
384  sendNEC2(aAddress, aCommand, aNumberOfRepeats);
385 
386  } else if (aProtocol == ONKYO) {
387  sendOnkyo(aAddress, aCommand, aNumberOfRepeats);
388 
389  } else if (aProtocol == APPLE) {
390  sendApple(aAddress, aCommand, aNumberOfRepeats);
391 
392 #if !defined(EXCLUDE_EXOTIC_PROTOCOLS)
393  } else if (aProtocol == BOSEWAVE) {
395 
396  } else if (aProtocol == FAST) {
397  // We have only 8 bit command
399 
400  } else if (aProtocol == LEGO_PF) {
401  sendLegoPowerFunctions(aAddress, aCommand, aCommand >> 4, (aNumberOfRepeats < 0)); // send 5 autorepeats, except for dedicated repeats
402 #endif
403 
404  } else {
405  return 0; // Not supported by write. E.g for BANG_OLUFSEN
406  }
407  return 1;
408 }
409 
414 void IRsend::sendRaw(const uint16_t aBufferWithMicroseconds[], uint_fast16_t aLengthOfBuffer, uint_fast8_t aIRFrequencyKilohertz) {
415 // Set IR carrier frequency
416  enableIROut(aIRFrequencyKilohertz);
417 
418  /*
419  * Raw data starts with a mark.
420  */
421  for (uint_fast16_t i = 0; i < aLengthOfBuffer; i++) {
422  if (i & 1) {
423  // Odd
424  space(aBufferWithMicroseconds[i]);
425  } else {
426  mark(aBufferWithMicroseconds[i]);
427  }
428  }
429 }
430 
435 void IRsend::sendRaw(const uint8_t aBufferWithTicks[], uint_fast16_t aLengthOfBuffer, uint_fast8_t aIRFrequencyKilohertz) {
436 // Set IR carrier frequency
437  enableIROut(aIRFrequencyKilohertz);
438 
439  for (uint_fast16_t i = 0; i < aLengthOfBuffer; i++) {
440  if (i & 1) {
441  // Odd
442  space(aBufferWithTicks[i] * MICROS_PER_TICK);
443  } else {
444  mark(aBufferWithTicks[i] * MICROS_PER_TICK);
445  }
446  }
447  IRLedOff(); // Always end with the LED off
448 }
449 
454 void IRsend::sendRaw_P(const uint16_t aBufferWithMicroseconds[], uint_fast16_t aLengthOfBuffer,
455  uint_fast8_t aIRFrequencyKilohertz) {
456 #if !defined(__AVR__)
457  sendRaw(aBufferWithMicroseconds, aLengthOfBuffer, aIRFrequencyKilohertz); // Let the function work for non AVR platforms
458 #else
459 // Set IR carrier frequency
460  enableIROut(aIRFrequencyKilohertz);
461  /*
462  * Raw data starts with a mark
463  */
464  for (uint_fast16_t i = 0; i < aLengthOfBuffer; i++) {
465  auto duration = pgm_read_word(&aBufferWithMicroseconds[i]);
466  if (i & 1) {
467  // Odd
468  space(duration);
469 # if defined(LOCAL_DEBUG)
470  Serial.print(F("S="));
471 # endif
472  } else {
473  mark(duration);
474 # if defined(LOCAL_DEBUG)
475  Serial.print(F("M="));
476 # endif
477  }
478 # if defined(LOCAL_DEBUG)
479  Serial.println(duration);
480 # endif
481  }
482 #endif
483 }
484 
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); // Let the function work for non AVR platforms
492 #else
493 // Set IR carrier frequency
494  enableIROut(aIRFrequencyKilohertz);
495 
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;
499  if (i & 1) {
500  // Odd
501  space(duration);
502 # if defined(LOCAL_DEBUG)
503  Serial.print(F("S="));
504 # endif
505  } else {
506  mark(duration);
507 # if defined(LOCAL_DEBUG)
508  Serial.print(F("M="));
509 # endif
510  }
511  }
512  IRLedOff(); // Always end with the LED off
513 # if defined(LOCAL_DEBUG)
514  Serial.println(duration);
515 # endif
516 #endif
517 }
518 
526 void IRsend::sendPulseDistanceWidthFromArray(uint_fast8_t aFrequencyKHz, DistanceWidthTimingInfoStruct *aDistanceWidthTimingInfo,
527  IRRawDataType *aDecodedRawDataArray, uint16_t aNumberOfBits, uint8_t aFlags, uint16_t aRepeatPeriodMillis,
528  int_fast8_t aNumberOfRepeats) {
529  sendPulseDistanceWidthFromArray(aFrequencyKHz, aDistanceWidthTimingInfo->HeaderMarkMicros,
530  aDistanceWidthTimingInfo->HeaderSpaceMicros, aDistanceWidthTimingInfo->OneMarkMicros,
531  aDistanceWidthTimingInfo->OneSpaceMicros, aDistanceWidthTimingInfo->ZeroMarkMicros,
532  aDistanceWidthTimingInfo->ZeroSpaceMicros, aDecodedRawDataArray, aNumberOfBits, aFlags, aRepeatPeriodMillis,
534 }
535 void IRsend::sendPulseDistanceWidthFromArray(uint_fast8_t aFrequencyKHz, uint16_t aHeaderMarkMicros, uint16_t aHeaderSpaceMicros,
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) {
539 
540  // Set IR carrier frequency
541  enableIROut(aFrequencyKHz);
542 
543  uint_fast8_t tNumberOfCommands = aNumberOfRepeats + 1;
544  uint_fast8_t tNumberOf32Or64BitChunks = ((aNumberOfBits - 1) / BITS_IN_RAW_DATA_TYPE) + 1;
545 
546 #if defined(LOCAL_DEBUG)
547  // fist data
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);
553  }
554  Serial.print(F(" #="));
555  Serial.println(aNumberOfBits);
556  Serial.flush();
557 #endif
558 
559  while (tNumberOfCommands > 0) {
560  unsigned long tStartOfFrameMillis = millis();
561 
562  // Header
563  mark(aHeaderMarkMicros);
564  space(aHeaderSpaceMicros);
565 
566  for (uint_fast8_t i = 0; i < tNumberOf32Or64BitChunks; ++i) {
567  uint8_t tNumberOfBitsForOneSend;
568 
569  // Manage stop bit
570  uint8_t tFlags;
571  if (i == (tNumberOf32Or64BitChunks - 1)) {
572  // End of data
573  tNumberOfBitsForOneSend = aNumberOfBits;
574  tFlags = aFlags;
575  } else {
576  // intermediate data
577  tNumberOfBitsForOneSend = BITS_IN_RAW_DATA_TYPE;
578  tFlags = aFlags | SUPPRESS_STOP_BIT; // No stop bit for leading data
579  }
580 
581  sendPulseDistanceWidthData(aOneMarkMicros, aOneSpaceMicros, aZeroMarkMicros, aZeroSpaceMicros, aDecodedRawDataArray[i],
582  tNumberOfBitsForOneSend, tFlags);
583  aNumberOfBits -= BITS_IN_RAW_DATA_TYPE;
584  }
585 
586  tNumberOfCommands--;
587  // skip last delay!
588  if (tNumberOfCommands > 0) {
589  /*
590  * Check and fallback for wrong RepeatPeriodMillis parameter. I.e the repeat period must be greater than each frame duration.
591  */
592  auto tFrameDurationMillis = millis() - tStartOfFrameMillis;
593  if (aRepeatPeriodMillis > tFrameDurationMillis) {
594  delay(aRepeatPeriodMillis - tFrameDurationMillis);
595  }
596  }
597  }
598 }
599 
600 void IRsend::sendPulseDistanceWidthFromPGMArray(uint_fast8_t aFrequencyKHz, uint16_t aHeaderMarkMicros, uint16_t aHeaderSpaceMicros,
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) {
604 
605  // Set IR carrier frequency
606  enableIROut(aFrequencyKHz);
607 
608  uint_fast8_t tNumberOfCommands = aNumberOfRepeats + 1;
609  uint_fast8_t tNumberOf32Or64BitChunks = ((aNumberOfBits - 1) / BITS_IN_RAW_DATA_TYPE) + 1;
610 
611 #if defined(LOCAL_DEBUG)
612  // fist data
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);
618  }
619  Serial.print(F(" #="));
620  Serial.println(aNumberOfBits);
621  Serial.flush();
622 #endif
623 
624  while (tNumberOfCommands > 0) {
625  unsigned long tStartOfFrameMillis = millis();
626 
627  // Header
628  mark(aHeaderMarkMicros);
629  space(aHeaderSpaceMicros);
630 
631  for (uint_fast8_t i = 0; i < tNumberOf32Or64BitChunks; ++i) {
632  uint8_t tNumberOfBitsForOneSend;
633 
634  // Manage stop bit
635  uint8_t tFlags;
636  if (i == (tNumberOf32Or64BitChunks - 1)) {
637  // End of data
638  tNumberOfBitsForOneSend = aNumberOfBits;
639  tFlags = aFlags;
640  } else {
641  // intermediate data
642  tNumberOfBitsForOneSend = BITS_IN_RAW_DATA_TYPE;
643  tFlags = aFlags | SUPPRESS_STOP_BIT; // No stop bit for leading data
644  }
645 
646  IRRawDataType tDecodedRawData;
647 #if (__INT_WIDTH__ < 32)
648  tDecodedRawData = pgm_read_word(&aDecodedRawDataPGMArray[i]);
649 #else
650  tDecodedRawData = pgm_read_dword(&aDecodedRawDataPGMArray[i]);
651 #endif
652  sendPulseDistanceWidthData(aOneMarkMicros, aOneSpaceMicros, aZeroMarkMicros, aZeroSpaceMicros, tDecodedRawData,
653  tNumberOfBitsForOneSend, tFlags);
654  aNumberOfBits -= BITS_IN_RAW_DATA_TYPE;
655  }
656 
657  tNumberOfCommands--;
658  // skip last delay!
659  if (tNumberOfCommands > 0) {
660  /*
661  * Check and fallback for wrong RepeatPeriodMillis parameter. I.e the repeat period must be greater than each frame duration.
662  */
663  auto tFrameDurationMillis = millis() - tStartOfFrameMillis;
664  if (aRepeatPeriodMillis > tFrameDurationMillis) {
665  delay(aRepeatPeriodMillis - tFrameDurationMillis);
666  }
667  }
668  }
669 }
670 
671 void IRsend::sendPulseDistanceWidthFromArray_P(uint_fast8_t aFrequencyKHz,
672  DistanceWidthTimingInfoStruct const *aDistanceWidthTimingInfoPGM, IRRawDataType *aDecodedRawDataArray,
673  uint16_t aNumberOfBits, uint8_t aFlags, uint16_t aRepeatPeriodMillis, int_fast8_t aNumberOfRepeats) {
674 
675  DistanceWidthTimingInfoStruct tTemporaryDistanceWidthTimingInfo;
676  memcpy_P(&tTemporaryDistanceWidthTimingInfo, aDistanceWidthTimingInfoPGM, sizeof(tTemporaryDistanceWidthTimingInfo));
677  sendPulseDistanceWidthFromArray(aFrequencyKHz, &tTemporaryDistanceWidthTimingInfo, aDecodedRawDataArray, aNumberOfBits, aFlags,
678  aRepeatPeriodMillis, aNumberOfRepeats);
679 }
680 
691  IRRawDataType *aDecodedRawDataArray, uint16_t aNumberOfBits, int_fast8_t aNumberOfRepeats) {
692 
693 // Calling sendPulseDistanceWidthFromArray() costs 68 bytes program memory compared to the implementation below
694 // sendPulseDistanceWidthFromArray(aProtocolConstants->FrequencyKHz, aProtocolConstants->DistanceWidthTimingInfo.HeaderMarkMicros,
695 // aProtocolConstants->DistanceWidthTimingInfo.HeaderSpaceMicros,
696 // aProtocolConstants->DistanceWidthTimingInfo.OneMarkMicros, aProtocolConstants->DistanceWidthTimingInfo.OneSpaceMicros,
697 // aProtocolConstants->DistanceWidthTimingInfo.ZeroMarkMicros, aProtocolConstants->DistanceWidthTimingInfo.ZeroSpaceMicros,
698 // aDecodedRawDataArray, aNumberOfBits, aProtocolConstants->Flags, aProtocolConstants->RepeatPeriodMillis,
699 // aNumberOfRepeats);
700  // Set IR carrier frequency
701  enableIROut(aProtocolConstants->FrequencyKHz);
702 
703  uint_fast8_t tNumberOf32Or64BitChunks = ((aNumberOfBits - 1) / BITS_IN_RAW_DATA_TYPE) + 1;
704 
705 #if defined(LOCAL_DEBUG)
706  // fist data
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);
712  }
713  Serial.print(F(" #="));
714  Serial.println(aNumberOfBits);
715  Serial.flush();
716 #endif
717 
718  uint_fast8_t tNumberOfCommands = aNumberOfRepeats + 1;
719  while (tNumberOfCommands > 0) {
720  auto tStartOfFrameMillis = millis();
721  auto tNumberOfBits = aNumberOfBits; // refresh value for repeats
722 
723  // Header
724  mark(aProtocolConstants->DistanceWidthTimingInfo.HeaderMarkMicros);
725  space(aProtocolConstants->DistanceWidthTimingInfo.HeaderSpaceMicros);
726  uint8_t tOriginalFlags = aProtocolConstants->Flags;
727 
728  for (uint_fast8_t i = 0; i < tNumberOf32Or64BitChunks; ++i) {
729  uint8_t tNumberOfBitsForOneSend;
730 
731  uint8_t tFlags;
732  if (i == (tNumberOf32Or64BitChunks - 1)) {
733  // End of data
734  tNumberOfBitsForOneSend = tNumberOfBits;
735  tFlags = tOriginalFlags;
736  } else {
737  // intermediate data
738  tNumberOfBitsForOneSend = BITS_IN_RAW_DATA_TYPE;
739  tFlags = tOriginalFlags | SUPPRESS_STOP_BIT; // No stop bit for leading data
740  }
741 
743  aProtocolConstants->DistanceWidthTimingInfo.OneSpaceMicros,
744  aProtocolConstants->DistanceWidthTimingInfo.ZeroMarkMicros,
745  aProtocolConstants->DistanceWidthTimingInfo.ZeroSpaceMicros, aDecodedRawDataArray[i], tNumberOfBitsForOneSend,
746  tFlags);
747  tNumberOfBits -= BITS_IN_RAW_DATA_TYPE;
748  }
749 
750  tNumberOfCommands--;
751  // skip last delay!
752  if (tNumberOfCommands > 0) {
753  /*
754  * Check and fallback for wrong RepeatPeriodMillis parameter. I.e the repeat period must be greater than each frame duration.
755  */
756  auto tFrameDurationMillis = millis() - tStartOfFrameMillis;
757  if (aProtocolConstants->RepeatPeriodMillis > tFrameDurationMillis) {
758  delay(aProtocolConstants->RepeatPeriodMillis - tFrameDurationMillis);
759  }
760  }
761  }
762 }
763 
765  IRRawDataType *aDecodedRawDataArray, uint16_t aNumberOfBits, int_fast8_t aNumberOfRepeats) {
766 
767  PulseDistanceWidthProtocolConstants tTemporaryPulseDistanceWidthProtocolConstants;
768  memcpy_P(&tTemporaryPulseDistanceWidthProtocolConstants, aProtocolConstantsPGM,
769  sizeof(tTemporaryPulseDistanceWidthProtocolConstants));
770  sendPulseDistanceWidthFromArray(&tTemporaryPulseDistanceWidthProtocolConstants, aDecodedRawDataArray, aNumberOfBits,
772 }
774  IRRawDataType const *aDecodedRawDataPGMArray, uint16_t aNumberOfBits, int_fast8_t aNumberOfRepeats) {
775 
776  PulseDistanceWidthProtocolConstants tTemporaryPulseDistanceWidthProtocolConstants;
777  memcpy_P(&tTemporaryPulseDistanceWidthProtocolConstants, aProtocolConstantsPGM,
778  sizeof(tTemporaryPulseDistanceWidthProtocolConstants));
779  sendPulseDistanceWidthFromPGMArray(&tTemporaryPulseDistanceWidthProtocolConstants, aDecodedRawDataPGMArray, aNumberOfBits,
781 }
782 
784  IRRawDataType const*aDecodedRawDataPGMArray, uint16_t aNumberOfBits, int_fast8_t aNumberOfRepeats) {
785 
786 // Calling sendPulseDistanceWidthFromArray() costs 68 bytes program memory compared to the implementation below
787 // sendPulseDistanceWidthFromArray(aProtocolConstants->FrequencyKHz, aProtocolConstants->DistanceWidthTimingInfo.HeaderMarkMicros,
788 // aProtocolConstants->DistanceWidthTimingInfo.HeaderSpaceMicros,
789 // aProtocolConstants->DistanceWidthTimingInfo.OneMarkMicros, aProtocolConstants->DistanceWidthTimingInfo.OneSpaceMicros,
790 // aProtocolConstants->DistanceWidthTimingInfo.ZeroMarkMicros, aProtocolConstants->DistanceWidthTimingInfo.ZeroSpaceMicros,
791 // aDecodedRawDataArray, aNumberOfBits, aProtocolConstants->Flags, aProtocolConstants->RepeatPeriodMillis,
792 // aNumberOfRepeats);
793  // Set IR carrier frequency
794  enableIROut(aProtocolConstants->FrequencyKHz);
795 
796  uint_fast8_t tNumberOf32Or64BitChunks = ((aNumberOfBits - 1) / BITS_IN_RAW_DATA_TYPE) + 1;
797 
798 #if defined(LOCAL_DEBUG)
799  // fist data
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);
805  }
806  Serial.print(F(" #="));
807  Serial.println(aNumberOfBits);
808  Serial.flush();
809 #endif
810 
811  uint_fast8_t tNumberOfCommands = aNumberOfRepeats + 1;
812  while (tNumberOfCommands > 0) {
813  auto tStartOfFrameMillis = millis();
814  auto tNumberOfBits = aNumberOfBits; // refresh value for repeats
815 
816  // Header
817  mark(aProtocolConstants->DistanceWidthTimingInfo.HeaderMarkMicros);
818  space(aProtocolConstants->DistanceWidthTimingInfo.HeaderSpaceMicros);
819  uint8_t tOriginalFlags = aProtocolConstants->Flags;
820 
821  for (uint_fast8_t i = 0; i < tNumberOf32Or64BitChunks; ++i) {
822  uint8_t tNumberOfBitsForOneSend;
823 
824  uint8_t tFlags;
825  if (i == (tNumberOf32Or64BitChunks - 1)) {
826  // End of data
827  tNumberOfBitsForOneSend = tNumberOfBits;
828  tFlags = tOriginalFlags;
829  } else {
830  // intermediate data
831  tNumberOfBitsForOneSend = BITS_IN_RAW_DATA_TYPE;
832  tFlags = tOriginalFlags | SUPPRESS_STOP_BIT; // No stop bit for leading data
833  }
834 
835  IRRawDataType tDecodedRawData;
836 #if (__INT_WIDTH__ < 32)
837  tDecodedRawData = pgm_read_word(&aDecodedRawDataPGMArray[i]);
838 #else
839  tDecodedRawData = pgm_read_dword(&aDecodedRawDataPGMArray[i]);
840 #endif
842  aProtocolConstants->DistanceWidthTimingInfo.OneSpaceMicros,
843  aProtocolConstants->DistanceWidthTimingInfo.ZeroMarkMicros,
844  aProtocolConstants->DistanceWidthTimingInfo.ZeroSpaceMicros, tDecodedRawData, tNumberOfBitsForOneSend,
845  tFlags);
846  tNumberOfBits -= BITS_IN_RAW_DATA_TYPE;
847  }
848 
849  tNumberOfCommands--;
850  // skip last delay!
851  if (tNumberOfCommands > 0) {
852  /*
853  * Check and fallback for wrong RepeatPeriodMillis parameter. I.e the repeat period must be greater than each frame duration.
854  */
855  auto tFrameDurationMillis = millis() - tStartOfFrameMillis;
856  if (aProtocolConstants->RepeatPeriodMillis > tFrameDurationMillis) {
857  delay(aProtocolConstants->RepeatPeriodMillis - tFrameDurationMillis);
858  }
859  }
860  }
861 }
862 
872  uint_fast8_t aNumberOfBits, int_fast8_t aNumberOfRepeats) {
873 
874 #if defined(LOCAL_DEBUG)
875  Serial.print(F("Data=0x"));
876  Serial.print(aData, HEX);
877  Serial.print(F(" #="));
878  Serial.println(aNumberOfBits);
879  Serial.flush();
880 #endif
881 
882  if (aNumberOfRepeats < 0) {
883  if (aProtocolConstants->SpecialSendRepeatFunction != nullptr) {
884  /*
885  * Send only a special repeat and return
886  */
887  aProtocolConstants->SpecialSendRepeatFunction();
888  return;
889  } else {
890  // Send only one plain frame (as repeat)
891  aNumberOfRepeats = 0;
892  }
893  }
894 
895  // Set IR carrier frequency
896  enableIROut(aProtocolConstants->FrequencyKHz);
897 
898  uint_fast8_t tNumberOfCommands = aNumberOfRepeats + 1;
899  while (tNumberOfCommands > 0) {
900  unsigned long tStartOfFrameMillis = millis();
901 
902  if (tNumberOfCommands < ((uint_fast8_t) aNumberOfRepeats + 1) && aProtocolConstants->SpecialSendRepeatFunction != nullptr) {
903  // send special repeat, if specified and we are not in the first loop
904  aProtocolConstants->SpecialSendRepeatFunction();
905  } else {
906  /*
907  * Send Header and regular frame
908  */
909  mark(aProtocolConstants->DistanceWidthTimingInfo.HeaderMarkMicros);
910  space(aProtocolConstants->DistanceWidthTimingInfo.HeaderSpaceMicros);
911  sendPulseDistanceWidthData(aProtocolConstants, aData, aNumberOfBits);
912  }
913 
914  tNumberOfCommands--;
915  // skip last delay!
916  if (tNumberOfCommands > 0) {
917  auto tCurrentFrameDurationMillis = millis() - tStartOfFrameMillis;
918  /*
919  * Check and fallback for wrong RepeatPeriodMillis parameter. I.e the repeat period must be greater than each frame duration.
920  */
921  if (aProtocolConstants->RepeatPeriodMillis > tCurrentFrameDurationMillis) {
922  delay(aProtocolConstants->RepeatPeriodMillis - tCurrentFrameDurationMillis);
923  }
924  }
925  }
926 }
928  uint_fast8_t aNumberOfBits, int_fast8_t aNumberOfRepeats) {
929  PulseDistanceWidthProtocolConstants tTemporaryPulseDistanceWidthProtocolConstants;
930  memcpy_P(&tTemporaryPulseDistanceWidthProtocolConstants, aProtocolConstantsPGM,
931  sizeof(tTemporaryPulseDistanceWidthProtocolConstants));
932  sendPulseDistanceWidth(&tTemporaryPulseDistanceWidthProtocolConstants, aData, aNumberOfBits, aNumberOfRepeats);
933 }
934 
945 void IRsend::sendPulseDistanceWidth(uint_fast8_t aFrequencyKHz, uint16_t aHeaderMarkMicros, uint16_t aHeaderSpaceMicros,
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)()) {
949 
950  if (aNumberOfRepeats < 0) {
951  if (aSpecialSendRepeatFunction != nullptr) {
952  aSpecialSendRepeatFunction();
953  return;
954  } else {
955  aNumberOfRepeats = 0; // send a plain frame as repeat
956  }
957  }
958 
959  // Set IR carrier frequency
960  enableIROut(aFrequencyKHz);
961 
962  uint_fast8_t tNumberOfCommands = aNumberOfRepeats + 1;
963  while (tNumberOfCommands > 0) {
964  unsigned long tStartOfFrameMillis = millis();
965 
966  if (tNumberOfCommands < ((uint_fast8_t) aNumberOfRepeats + 1) && aSpecialSendRepeatFunction != nullptr) {
967  // send special repeat
968  aSpecialSendRepeatFunction();
969  } else {
970  // Header and regular frame
971  mark(aHeaderMarkMicros);
972  space(aHeaderSpaceMicros);
973  sendPulseDistanceWidthData(aOneMarkMicros, aOneSpaceMicros, aZeroMarkMicros, aZeroSpaceMicros, aData, aNumberOfBits,
974  aFlags);
975  }
976 
977  tNumberOfCommands--;
978  // skip last delay!
979  if (tNumberOfCommands > 0) {
980  /*
981  * Check and fallback for wrong RepeatPeriodMillis parameter. I.e the repeat period must be greater than each frame duration.
982  */
983  auto tFrameDurationMillis = millis() - tStartOfFrameMillis;
984  if (aRepeatPeriodMillis > tFrameDurationMillis) {
985  delay(aRepeatPeriodMillis - tFrameDurationMillis);
986  }
987  }
988  }
989 }
990 
1000  uint_fast8_t aNumberOfBits) {
1001 
1003  aProtocolConstants->DistanceWidthTimingInfo.OneSpaceMicros, aProtocolConstants->DistanceWidthTimingInfo.ZeroMarkMicros,
1004  aProtocolConstants->DistanceWidthTimingInfo.ZeroSpaceMicros, aData, aNumberOfBits, aProtocolConstants->Flags);
1005 }
1006 
1008  uint_fast8_t aNumberOfBits) {
1009 
1010  PulseDistanceWidthProtocolConstants tTemporaryPulseDistanceWidthProtocolConstants;
1011  memcpy_P(&tTemporaryPulseDistanceWidthProtocolConstants, aProtocolConstantsPGM,
1012  sizeof(tTemporaryPulseDistanceWidthProtocolConstants));
1013  sendPulseDistanceWidthData(&tTemporaryPulseDistanceWidthProtocolConstants, aData, aNumberOfBits);
1014 }
1015 
1024 void IRsend::sendPulseDistanceWidthData(uint16_t aOneMarkMicros, uint16_t aOneSpaceMicros, uint16_t aZeroMarkMicros,
1025  uint16_t aZeroSpaceMicros, IRRawDataType aData, uint_fast8_t aNumberOfBits, uint8_t aFlags) {
1026 
1027 #if defined(LOCAL_DEBUG)
1028  Serial.print(aData, HEX);
1029  Serial.print('|');
1030  Serial.println(aNumberOfBits);
1031  Serial.flush();
1032 #endif
1033 
1034  // For MSBFirst, send data from MSB to LSB until mask bit is shifted out
1035  IRRawDataType tMask = 1ULL << (aNumberOfBits - 1);
1036  for (uint_fast8_t i = aNumberOfBits; i > 0; i--) {
1037  if (((aFlags & PROTOCOL_IS_MSB_FIRST) && (aData & tMask)) || (!(aFlags & PROTOCOL_IS_MSB_FIRST) && (aData & 1))) {
1038 #if defined(LOCAL_TRACE)
1039  Serial.print('1');
1040 #endif
1041  mark(aOneMarkMicros);
1042  space(aOneSpaceMicros);
1043  } else {
1044 #if defined(LOCAL_TRACE)
1045  Serial.print('0');
1046 #endif
1047  mark(aZeroMarkMicros);
1048  space(aZeroSpaceMicros);
1049  }
1050  if (aFlags & PROTOCOL_IS_MSB_FIRST) {
1051  tMask >>= 1;
1052  } else {
1053  aData >>= 1;
1054  }
1055  }
1056  /*
1057  * Stop bit is sent for all pulse distance protocols i.e. aOneSpaceMicros != aZeroSpaceMicros.
1058  * Therefore it is not sent for Sony :-)
1059  * For sending from an array, no intermediate stop bit must be sent for all but last data chunk.
1060  */
1061  if ((!(aFlags & SUPPRESS_STOP_BIT)) && (abs(aOneSpaceMicros - aZeroSpaceMicros) > (aOneSpaceMicros / 4))) {
1062  // Send stop bit here
1063 #if defined(LOCAL_TRACE)
1064  Serial.print('S');
1065 #endif
1066  mark(aOneMarkMicros); // Use aOneMarkMicros for stop bits. This seems to be correct for all protocols :-)
1067  }
1068 #if defined(LOCAL_TRACE)
1069  Serial.println();
1070 #endif
1071 }
1072 
1083 void IRsend::sendBiphaseData(uint16_t aBiphaseTimeUnit, uint32_t aData, uint_fast8_t aNumberOfBits) {
1084 
1085  IR_TRACE_PRINT(F("0x"));
1086  IR_TRACE_PRINT(aData, HEX);
1087 
1088 #if defined(LOCAL_TRACE)
1089  Serial.print('S');
1090 #endif
1091 
1092 // Data - Biphase code MSB first
1093 // prepare for start with sending the start bit, which is 1
1094  uint32_t tMask = 1UL << aNumberOfBits; // mask is now set for the virtual start bit
1095  uint_fast8_t tLastBitValue = 1; // Start bit is a 1
1096  bool tNextBitIsOne = 1; // Start bit is a 1
1097  for (uint_fast8_t i = aNumberOfBits + 1; i > 0; i--) {
1098  bool tCurrentBitIsOne = tNextBitIsOne;
1099  tMask >>= 1;
1100  tNextBitIsOne = ((aData & tMask) != 0) || (i == 1); // true for last bit to avoid extension of mark
1101  if (tCurrentBitIsOne) {
1102 #if defined(LOCAL_TRACE)
1103  Serial.print('1');
1104 #endif
1105  space(aBiphaseTimeUnit);
1106  if (tNextBitIsOne) {
1107  mark(aBiphaseTimeUnit);
1108  } else {
1109  // if next bit is 0, extend the current mark in order to generate a continuous signal without short breaks
1110  mark(2 * aBiphaseTimeUnit);
1111  }
1112  tLastBitValue = 1;
1113 
1114  } else {
1115 #if defined(LOCAL_TRACE)
1116  Serial.print('0');
1117 #endif
1118  if (!tLastBitValue) {
1119  mark(aBiphaseTimeUnit);
1120  }
1121  space(aBiphaseTimeUnit);
1122  tLastBitValue = 0;
1123  }
1124  }
1125  IR_TRACE_PRINTLN();
1126 }
1127 
1143 void IRsend::mark(uint16_t aMarkMicros) {
1144 
1145 #if defined(SEND_PWM_BY_TIMER) || defined(USE_NO_SEND_PWM)
1146 # if !defined(NO_LED_FEEDBACK_CODE)
1148  setFeedbackLED(true);
1149  }
1150 # endif
1151 #endif
1152 
1153 #if defined(SEND_PWM_BY_TIMER)
1154  /*
1155  * Generate hardware PWM signal
1156  */
1157  enableSendPWMByTimer(); // Enable timer or ledcWrite() generated PWM output
1158  customDelayMicroseconds(aMarkMicros);
1159  IRLedOff(); // disables hardware PWM and manages feedback LED
1160  return;
1161 
1162 #elif defined(USE_NO_SEND_PWM)
1163  /*
1164  * Here we generate no carrier PWM, just simulate an active low receiver signal.
1165  */
1166 # if defined(USE_OPEN_DRAIN_OUTPUT_FOR_SEND_PIN) && !defined(OUTPUT_OPEN_DRAIN)
1167  // Here we have no hardware supported Open Drain outputs, so we must mimicking it
1168  pinModeFast(sendPin, OUTPUT); // active state for mimicking open drain
1169 # elif defined(USE_ACTIVE_HIGH_OUTPUT_FOR_SEND_PIN)
1170  digitalWriteFast(sendPin, HIGH); // Set output to active high.
1171 # else
1172  digitalWriteFast(sendPin, LOW); // Set output to active low.
1173 # endif
1174 
1175  customDelayMicroseconds(aMarkMicros);
1176  IRLedOff();
1177 # if !defined(NO_LED_FEEDBACK_CODE)
1179  setFeedbackLED(false);
1180  }
1181  return;
1182 # endif
1183 
1184 #else // defined(SEND_PWM_BY_TIMER)
1185  /*
1186  * Generate PWM by bit banging
1187  */
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;
1193 # endif
1194 
1195  do {
1196 // digitalToggleFast(_IR_TIMING_TEST_PIN);
1197  /*
1198  * Output the PWM pulse
1199  */
1200  noInterrupts(); // do not let interrupts extend the short on period
1201 # if defined(USE_OPEN_DRAIN_OUTPUT_FOR_SEND_PIN)
1202 # if defined(OUTPUT_OPEN_DRAIN)
1203  digitalWriteFast(sendPin, LOW); // set output with pin mode OUTPUT_OPEN_DRAIN to active low
1204 # else
1205  pinModeFast(sendPin, OUTPUT); // active state for mimicking open drain
1206 # endif
1207 # else
1208  // 3.5 us from FeedbackLed on to pin setting. 5.7 us from call of mark() to pin setting incl. setting of feedback pin.
1209  // 4.3 us from do{ to pin setting if sendPin is no constant
1210  digitalWriteFast(sendPin, HIGH);
1211 # endif
1212  delayMicroseconds (periodOnTimeMicros); // On time is 8 us for 30% duty cycle. This is normally implemented by a blocking wait.
1213 
1214  /*
1215  * Output the PWM pause
1216  */
1217 # if defined(USE_OPEN_DRAIN_OUTPUT_FOR_SEND_PIN) && !defined(OUTPUT_OPEN_DRAIN)
1218 # if defined(OUTPUT_OPEN_DRAIN)
1219  digitalWriteFast(sendPin, HIGH); // Set output with pin mode OUTPUT_OPEN_DRAIN to inactive high.
1220 # else
1221  pinModeFast(sendPin, INPUT); // to mimic the open drain inactive state
1222 # endif
1223 
1224 # else
1225  digitalWriteFast(sendPin, LOW);
1226 # endif
1227  /*
1228  * Enable interrupts at start of the longer off period. Required at least to keep micros correct.
1229  * If receive interrupt is still active, it takes 3.4 us from now until receive ISR is active (for 7 us + pop's)
1230  */
1231  interrupts();
1232 
1233 # if !defined(NO_LED_FEEDBACK_CODE)
1234  /*
1235  * Delayed call of setFeedbackLED() to get better startup timing, especially required for consecutive marks
1236  */
1237  if (!FeedbackLedIsActive) {
1238  FeedbackLedIsActive = true;
1240  setFeedbackLED(true);
1241  }
1242  }
1243 # endif
1244  /*
1245  * PWM pause timing
1246  * Measured delta between pause duration values are 13 us for a 16 MHz Uno (from 13 to 26), if interrupts are disabled below
1247  * Measured delta between pause duration values are 20 us for a 16 MHz Uno (from 7.8 to 28), if interrupts are not disabled below
1248  * Minimal pause duration is 5.2 us with NO_LED_FEEDBACK_CODE enabled
1249  * and 8.1 us with NO_LED_FEEDBACK_CODE disabled.
1250  */
1251  tNextPeriodEnding += periodTimeMicros;
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
1253  noInterrupts(); // disable interrupts (especially the 20 us receive interrupts) only at start of the PWM pause. Otherwise it may extend the pause too much.
1254 #endif
1255  do {
1256 #if defined(_IR_MEASURE_TIMING) && defined(_IR_TIMING_TEST_PIN)
1257  digitalWriteFast(_IR_TIMING_TEST_PIN, HIGH); // 2 clock cycles
1258 #endif
1259  /*
1260  * For AVR @16MHz we have only 4 us resolution.
1261  * The duration of the micros() call itself is 3 us.
1262  * It takes 0.9 us from signal going low here.
1263  * The rest of the loop takes 1.2 us with NO_LED_FEEDBACK_CODE enabled
1264  * and 3 us with NO_LED_FEEDBACK_CODE disabled.
1265  */
1266 #if defined(_IR_MEASURE_TIMING) && defined(_IR_TIMING_TEST_PIN)
1267  digitalWriteFast(_IR_TIMING_TEST_PIN, LOW); // 2 clock cycles
1268 #endif
1269  /*
1270  * Exit the forever loop if aMarkMicros has reached
1271  */
1272  tMicros = micros();
1273  uint16_t tDeltaMicros = tMicros - tStartMicros;
1274 #if defined(__AVR__)
1275  // reset feedback led in the last pause before end
1276 // tDeltaMicros += (160 / CLOCKS_PER_MICRO); // adding this once increases program size, so do it below !
1277 # if !defined(NO_LED_FEEDBACK_CODE)
1278  if (tDeltaMicros >= aMarkMicros - (30 + (112 / CLOCKS_PER_MICRO))) { // 30 to be constant. Using periodTimeMicros increases program size too much.
1280  setFeedbackLED(false);
1281  }
1282  }
1283 # endif
1284  // Just getting variables and check for end condition takes minimal 3.8 us
1285  if (tDeltaMicros >= aMarkMicros - (112 / CLOCKS_PER_MICRO)) { // To compensate for call duration - 112 is an empirical value
1286 #else
1287  if (tDeltaMicros >= aMarkMicros) {
1288 # if !defined(NO_LED_FEEDBACK_CODE)
1290  setFeedbackLED(false);
1291  }
1292 # endif
1293 #endif
1294 #if defined(__AVR__)
1295  interrupts();
1296 #endif
1297  return;
1298  }
1299  } while (tMicros < tNextPeriodEnding);
1300  } while (true);
1301 # endif
1302 }
1303 
1310 #if defined(SEND_PWM_BY_TIMER)
1311  disableSendPWMByTimer(); // Disable PWM output
1312 #elif defined(USE_NO_SEND_PWM)
1313 # if defined(USE_OPEN_DRAIN_OUTPUT_FOR_SEND_PIN) && !defined(OUTPUT_OPEN_DRAIN)
1314  digitalWriteFast(sendPin, LOW); // prepare for all next active states.
1315  pinModeFast(sendPin, INPUT);// inactive state for open drain
1316 # elif defined(USE_ACTIVE_HIGH_OUTPUT_FOR_SEND_PIN)
1317  digitalWriteFast(sendPin, LOW); // Set output to inactive low.
1318 # else
1319  digitalWriteFast(sendPin, HIGH); // Set output to inactive high.
1320 # endif
1321 #else
1322 # if defined(USE_OPEN_DRAIN_OUTPUT_FOR_SEND_PIN)
1323 # if defined(OUTPUT_OPEN_DRAIN)
1324  digitalWriteFast(sendPin, HIGH); // Set output to inactive high.
1325 # else
1326  pinModeFast(sendPin, INPUT); // inactive state to mimic open drain
1327 # endif
1328 # else
1329  digitalWriteFast(sendPin, LOW);
1330 # endif
1331 #endif
1332 
1333 #if !defined(NO_LED_FEEDBACK_CODE)
1335  setFeedbackLED(false);
1336  }
1337 #endif
1338 }
1339 
1344 void IRsend::space(uint16_t aSpaceMicros) {
1345  customDelayMicroseconds(aSpaceMicros);
1346 }
1347 
1352 void IRsend::customDelayMicroseconds(unsigned long aMicroseconds) {
1353 #if defined(ESP32) || defined(ESP8266)
1354  // from https://github.com/crankyoldgit/IRremoteESP8266/blob/00b27cc7ea2e7ac1e48e91740723c805a38728e0/src/IRsend.cpp#L123
1355  // Invoke a delay(), where possible, to avoid triggering the WDT.
1356  // see https://github.com/Arduino-IRremote/Arduino-IRremote/issues/1114 for the reason of checking for > 16383)
1357  // delayMicroseconds() is only accurate to 16383 us. Ref: https://www.arduino.cc/en/Reference/delayMicroseconds
1358  if (aMicroseconds > 16383) {
1359  delay(aMicroseconds / 1000UL); // Delay for as many whole milliseconds as we can.
1360  // Delay the remaining sub-millisecond.
1361  delayMicroseconds(static_cast<uint16_t>(aMicroseconds % 1000UL));
1362  } else {
1363  delayMicroseconds(aMicroseconds);
1364  }
1365 #else
1366 
1367 # if defined(__AVR__)
1368  unsigned long start = micros() - (64 / clockCyclesPerMicrosecond()); // - (64 / clockCyclesPerMicrosecond()) for reduced resolution and additional overhead
1369 # else
1370  unsigned long start = micros();
1371 # endif
1372 // overflow invariant comparison :-)
1373  while (micros() - start < aMicroseconds) {
1374  }
1375 #endif
1376 }
1377 
1384 void IRsend::enableIROut(uint_fast8_t aFrequencyKHz) {
1385 #if defined(SEND_PWM_BY_TIMER)
1386  timerConfigForSend(aFrequencyKHz); // must set output pin mode and disable receive interrupt if required, e.g. uses the same resource
1387 
1388 #elif defined(USE_NO_SEND_PWM)
1389  (void) aFrequencyKHz;
1390 
1391 #else
1392  periodTimeMicros = (1000U + (aFrequencyKHz / 2)) / aFrequencyKHz; // rounded value -> 26 for 38.46 kHz, 27 for 37.04 kHz, 25 for 40 kHz.
1393 # if defined(IR_SEND_PIN)
1394  periodOnTimeMicros = (((periodTimeMicros * IR_SEND_DUTY_CYCLE_PERCENT) + 50) / 100U); // +50 for rounding -> 830/100 for 30% and 16 MHz
1395 # else
1396 // Heuristics! We require a nanosecond correction for "slow" digitalWrite() functions
1397  periodOnTimeMicros = (((periodTimeMicros * IR_SEND_DUTY_CYCLE_PERCENT) + 50 - (PULSE_CORRECTION_NANOS / 10)) / 100U); // +50 for rounding -> 530/100 for 30% and 16 MHz
1398 # endif
1399 #endif // defined(SEND_PWM_BY_TIMER)
1400 
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)
1403  pinModeFast(IR_SEND_PIN, OUTPUT_OPEN_DRAIN);
1404 # else
1405  pinModeFast(sendPin, OUTPUT_OPEN_DRAIN);
1406 # endif
1407 #else
1408 
1409 // For Non AVR platforms pin mode for SEND_PWM_BY_TIMER must be handled by the timerConfigForSend() function
1410 // because ESP 2.0.2 ledcWrite does not work if pin mode is set, and RP2040 requires gpio_set_function(IR_SEND_PIN, GPIO_FUNC_PWM);
1411 # if defined(__AVR__) || !defined(SEND_PWM_BY_TIMER)
1412 # if defined(IR_SEND_PIN)
1413  pinModeFast(IR_SEND_PIN, OUTPUT);
1414 # else
1415  pinModeFast(sendPin, OUTPUT);
1416 # endif
1417 # endif
1418 #endif // defined(USE_OPEN_DRAIN_OUTPUT_FOR_SEND_PIN)
1419 }
1420 
1421 #if defined(SEND_PWM_BY_TIMER)
1422 // Used for Bang&Olufsen
1423 void IRsend::enableHighFrequencyIROut(uint_fast16_t aFrequencyKHz) {
1424  timerConfigForSend(aFrequencyKHz); // must set output pin mode and disable receive interrupt if required, e.g. uses the same resource
1425  // For Non AVR platforms pin mode for SEND_PWM_BY_TIMER must be handled by the timerConfigForSend() function
1426  // because ESP 2.0.2 ledcWrite does not work if pin mode is set, and RP2040 requires gpio_set_function(IR_SEND_PIN, GPIO_FUNC_PWM);
1427 # if defined(__AVR__)
1428 # if defined(IR_SEND_PIN)
1429  pinModeFast(IR_SEND_PIN, OUTPUT);
1430 # else
1431  pinModeFast(sendPin, OUTPUT);
1432 # endif
1433 # endif
1434 }
1435 #endif
1436 
1438  return PULSE_CORRECTION_NANOS;
1439 }
1440 
1442 #if defined(_IR_MEASURE_TIMING)
1443 #undef _IR_MEASURE_TIMING
1444 #endif
1445 #if defined(LOCAL_TRACE)
1446 #undef LOCAL_TRACE
1447 #endif
1448 #if defined(LOCAL_DEBUG)
1449 #undef LOCAL_DEBUG
1450 #endif
1451 #endif // _IR_SEND_HPP
IRData::address
uint16_t address
Decoded address, Distance protocol (tMarkTicksLong (if tMarkTicksLong == 0, then tMarkTicksShort) << ...
Definition: IRProtocol.h:111
SUPPRESS_STOP_BIT
#define SUPPRESS_STOP_BIT
Definition: IRProtocol.h:149
MICROS_PER_TICK
#define MICROS_PER_TICK
microseconds per clock interrupt tick
Definition: IRremote.hpp:250
BITS_IN_RAW_DATA_TYPE
#define BITS_IN_RAW_DATA_TYPE
Definition: IRremoteInt.h:113
ONKYO
@ ONKYO
Definition: IRProtocol.h:51
DistanceWidthTimingInfoStruct::HeaderMarkMicros
uint16_t HeaderMarkMicros
Definition: IRProtocol.h:81
IRsend::sendApple
void sendApple(uint8_t aAddress, uint8_t aCommand, int_fast8_t aNumberOfRepeats)
Apple: Send NEC with fixed 16 bit Apple address 0x87EE.
Definition: ir_NEC.hpp:212
IRsend::sendMagiQuest
void sendMagiQuest(uint32_t aWandId, uint16_t aMagnitude)
Definition: ir_MagiQuest.hpp:121
KASEIKYO_DENON
@ KASEIKYO_DENON
Definition: IRProtocol.h:54
PROTOCOL_IS_MSB_FIRST
#define PROTOCOL_IS_MSB_FIRST
Definition: IRProtocol.h:150
setFeedbackLED
void setFeedbackLED(bool aSwitchLedOn)
Flash LED while receiving or sending IR data.
Definition: IRFeedbackLED.hpp:108
JVC
@ JVC
Definition: IRProtocol.h:46
IRData::numberOfBits
uint16_t numberOfBits
Number of bits received for data (address + command + parity) - to determine protocol length if diffe...
Definition: IRProtocol.h:120
IRsend::aNumberOfRepeats
void int_fast8_t aNumberOfRepeats
Definition: IRremoteInt.h:580
IRsend::sendPin
uint8_t sendPin
Definition: IRremoteInt.h:681
IRsend::sendJVC
void sendJVC(uint8_t aAddress, uint8_t aCommand, int_fast8_t aNumberOfRepeats)
The JVC protocol repeats by skipping the header mark and space -> this leads to a poor repeat detecti...
Definition: ir_JVC.hpp:92
IRsend::sendKaseikyo_Sharp
void sendKaseikyo_Sharp(uint16_t aAddress, uint8_t aData, int_fast8_t aNumberOfRepeats)
Stub using Kaseikyo with SHARP_VENDOR_ID_CODE.
Definition: ir_Kaseikyo.hpp:185
KASEIKYO_SHARP
@ KASEIKYO_SHARP
Definition: IRProtocol.h:55
FAST
@ FAST
Definition: IRProtocol.h:72
IRsend::setSendPin
void setSendPin(uint_fast8_t aSendPin)
Definition: IRSend.hpp:128
pinModeFast
#define pinModeFast
Definition: digitalWriteFast.h:383
IRsend::sendBoseWave
void sendBoseWave(uint8_t aCommand, int_fast8_t aNumberOfRepeats=NO_REPEATS)
Definition: ir_BoseWave.hpp:57
IRsend::sendSony
void sendSony(uint16_t aAddress, uint8_t aCommand, int_fast8_t aNumberOfRepeats, uint8_t numberOfBits=12)
Definition: ir_Sony.hpp:103
digitalWriteFast
#define digitalWriteFast
Definition: digitalWriteFast.h:347
PULSE_CORRECTION_NANOS
#define PULSE_CORRECTION_NANOS
Define to disable carrier PWM generation in software and use (restricted) hardware PWM.
Definition: IRremote.hpp:235
IRsend::sendPulseDistanceWidth_P
void sendPulseDistanceWidth_P(PulseDistanceWidthProtocolConstants const *aProtocolConstantsPGM, IRRawDataType aData, uint_fast8_t aNumberOfBits, int_fast8_t aNumberOfRepeats)
Definition: IRSend.hpp:927
IRsend::mark
void mark(uint16_t aMarkMicros)
Sends an IR mark for the specified number of microseconds.
Definition: IRSend.hpp:1143
SONY
@ SONY
Definition: IRProtocol.h:65
KASEIKYO_JVC
@ KASEIKYO_JVC
Definition: IRProtocol.h:56
PulseDistanceWidthProtocolConstants::SpecialSendRepeatFunction
void(* SpecialSendRepeatFunction)()
Definition: IRProtocol.h:143
IRsend::sendSamsung48
void sendSamsung48(uint16_t aAddress, uint32_t aCommand, int_fast8_t aNumberOfRepeats)
Here we send Samsung48 We send 2 x (8 bit command and then ~command)
Definition: ir_Samsung.hpp:233
IRsend::sendRC6
void sendRC6(uint8_t aAddress, uint8_t aCommand, int_fast8_t aNumberOfRepeats, bool aEnableAutomaticToggle=true)
Assemble raw data for RC6 from parameters and toggle state and send We do not wait for the minimal tr...
Definition: ir_RC5_RC6.hpp:354
IRDATA_FLAGS_IS_REPEAT
#define IRDATA_FLAGS_IS_REPEAT
The gap between the preceding frame is as smaller than the maximum gap expected for a repeat....
Definition: IRProtocol.h:93
decode_type_t
decode_type_t
An enum consisting of all supported formats.
Definition: IRProtocol.h:40
IRsend::sendPulseDistanceWidthFromPGMArray
void sendPulseDistanceWidthFromPGMArray(uint_fast8_t aFrequencyKHz, uint16_t aHeaderMarkMicros, uint16_t aHeaderSpaceMicros, uint16_t aOneMarkMicros, uint16_t aOneSpaceMicros, uint16_t aZeroMarkMicros, uint16_t aZeroSpaceMicros, IRRawDataType const *aDecodedRawDataPGMArray, uint16_t aNumberOfBits, uint8_t aFlags, uint16_t aRepeatPeriodMillis, int_fast8_t aNumberOfRepeats)
Definition: IRSend.hpp:600
IRsend::customDelayMicroseconds
static void customDelayMicroseconds(unsigned long aMicroseconds)
Custom delay function that circumvents Arduino's delayMicroseconds 16 bit limit and is (mostly) not e...
Definition: IRSend.hpp:1352
IRsend::sendPulseDistanceWidth
void sendPulseDistanceWidth(PulseDistanceWidthProtocolConstants *aProtocolConstants, IRRawDataType aData, uint_fast8_t aNumberOfBits, int_fast8_t aNumberOfRepeats)
Sends PulseDistance frames and repeats.
Definition: IRSend.hpp:871
IRsend::IRsend
IRsend()
Definition: IRSend.hpp:67
SAMSUNG
@ SAMSUNG
Definition: IRProtocol.h:61
BOSEWAVE
@ BOSEWAVE
Definition: IRProtocol.h:68
DistanceWidthTimingInfoStruct::OneSpaceMicros
uint16_t OneSpaceMicros
Definition: IRProtocol.h:84
IRData::decodedRawData
IRRawDataType decodedRawData
Up to 32/64 bit decoded raw data, to be used for send functions.
Definition: IRProtocol.h:114
IRsend::sendRaw_P
void sendRaw_P(const uint8_t aBufferWithTicks[], uint_fast16_t aLengthOfBuffer, uint_fast8_t aIRFrequencyKilohertz)
New function using an 8 byte tick (50 us) timing array in FLASH to save program memory Raw data start...
Definition: IRSend.hpp:489
IRsend
Main class for sending IR signals.
Definition: IRremoteInt.h:466
DistanceWidthTimingInfoStruct::ZeroMarkMicros
uint16_t ZeroMarkMicros
Definition: IRProtocol.h:85
IR_TRACE_PRINT
#define IR_TRACE_PRINT(...)
Definition: IRremoteInt.h:177
MAGIQUEST
@ MAGIQUEST
Definition: IRProtocol.h:70
NEC2
@ NEC2
Definition: IRProtocol.h:50
PulseDistanceWidthProtocolConstants::Flags
uint8_t Flags
Definition: IRProtocol.h:141
IRsend::sendDenon
void sendDenon(uint8_t aAddress, uint8_t aCommand, int_fast8_t aNumberOfRepeats, uint8_t aSendSharpFrameMarker=0)
Definition: ir_Denon.hpp:131
IRsend::sendSamsung
void sendSamsung(uint16_t aAddress, uint16_t aCommand, int_fast8_t aNumberOfRepeats)
Here we send Samsung32 If we get a command < 0x100, we send command and then ~command If we get an ad...
Definition: ir_Samsung.hpp:171
DistanceWidthTimingInfoStruct
Definition: IRProtocol.h:80
IRsend::sendRaw
void sendRaw(const uint8_t aBufferWithTicks[], uint_fast16_t aLengthOfBuffer, uint_fast8_t aIRFrequencyKilohertz)
Sends an 8 byte tick timing array to save program memory.
Definition: IRSend.hpp:435
PulseDistanceWidthProtocolConstants
Definition: IRProtocol.h:137
FeedbackLEDControlStruct::LedFeedbackEnabled
uint8_t LedFeedbackEnabled
LED_FEEDBACK_ENABLED_FOR_RECEIVE or LED_FEEDBACK_ENABLED_FOR_SEND -> enable blinking of pin on IR pro...
Definition: IRFeedbackLED.hpp:44
IRsend::sendPulseDistanceWidthData_P
void sendPulseDistanceWidthData_P(PulseDistanceWidthProtocolConstants const *aProtocolConstantsPGM, IRRawDataType aData, uint_fast8_t aNumberOfBits)
Definition: IRSend.hpp:1007
PANASONIC
@ PANASONIC
Definition: IRProtocol.h:52
timerConfigForSend
void timerConfigForSend(uint16_t aFrequencyKHz)
IF PWM should be generated not by software, but by a timer, this function sets output pin mode,...
Definition: IRTimer.hpp:129
IRData
Data structure for the user application, available as decodedIRData.
Definition: IRProtocol.h:109
IR_SEND_PIN
#define IR_SEND_PIN
Definition: TinyIRSender.hpp:65
IRData::flags
uint8_t flags
IRDATA_FLAGS_IS_REPEAT, IRDATA_FLAGS_WAS_OVERFLOW etc. See IRDATA_FLAGS_* definitions above.
Definition: IRProtocol.h:121
IRsend::sendSamsungLG
void sendSamsungLG(uint16_t aAddress, uint16_t aCommand, int_fast8_t aNumberOfRepeats)
Definition: ir_Samsung.hpp:148
LED_FEEDBACK_ENABLED_FOR_SEND
#define LED_FEEDBACK_ENABLED_FOR_SEND
Definition: IRremoteInt.h:406
DistanceWidthTimingInfoStruct::OneMarkMicros
uint16_t OneMarkMicros
Definition: IRProtocol.h:83
DO_NOT_ENABLE_LED_FEEDBACK
#define DO_NOT_ENABLE_LED_FEEDBACK
Definition: IRremoteInt.h:403
IRsend::sendSharp
void sendSharp(uint8_t aAddress, uint8_t aCommand, int_fast8_t aNumberOfRepeats)
Definition: ir_Denon.hpp:116
IRsend::sendPulseDistanceWidthFromPGMArray_P
void sendPulseDistanceWidthFromPGMArray_P(PulseDistanceWidthProtocolConstants const *aProtocolConstantsPGM, IRRawDataType const *aDecodedRawDataPGMArray, uint16_t aNumberOfBits, int_fast8_t aNumberOfRepeats)
Definition: IRSend.hpp:773
IRsend::begin
void begin(uint_fast8_t aSendPin)
Initializes the send pin and enable LED feedback with board specific FEEDBACK_LED_ON() and FEEDBACK_L...
Definition: IRSend.hpp:121
IRsend::sendKaseikyo_JVC
void sendKaseikyo_JVC(uint16_t aAddress, uint8_t aData, int_fast8_t aNumberOfRepeats)
Stub using Kaseikyo with JVC_VENDOR_ID_CODE.
Definition: ir_Kaseikyo.hpp:192
IRsend::sendNEC
void sendNEC(uint16_t aAddress, uint16_t aCommand, int_fast8_t aNumberOfRepeats)
NEC Send frame and special repeats There is NO delay after the last sent repeat!
Definition: ir_NEC.hpp:182
IRsend::periodOnTimeMicros
uint16_t periodOnTimeMicros
Definition: IRremoteInt.h:684
IRData::command
uint16_t command
Decoded command, Distance protocol (tMarkTicksShort << 8) | tSpaceTicksShort.
Definition: IRProtocol.h:112
NEC
@ NEC
Definition: IRProtocol.h:49
IRsend::sendPanasonic
void sendPanasonic(uint16_t aAddress, uint8_t aData, int_fast8_t aNumberOfRepeats)
Stub using Kaseikyo with PANASONIC_VENDOR_ID_CODE.
Definition: ir_Kaseikyo.hpp:164
APPLE
@ APPLE
Definition: IRProtocol.h:44
IRsend::getPulseCorrectionNanos
uint16_t getPulseCorrectionNanos()
Definition: IRSend.hpp:1437
IRsend::write
size_t write(IRData *aIRSendData, int_fast8_t aNumberOfRepeats=NO_REPEATS)
Interprets and sends a IRData structure.
Definition: IRSend.hpp:170
LEGO_PF
@ LEGO_PF
Definition: IRProtocol.h:69
DistanceWidthTimingInfoStruct::ZeroSpaceMicros
uint16_t ZeroSpaceMicros
Definition: IRProtocol.h:86
IRRawDataType
uint32_t IRRawDataType
Definition: IRremoteInt.h:112
IR_TRACE_PRINTLN
#define IR_TRACE_PRINTLN(...)
Definition: IRremoteInt.h:178
KASEIKYO_MITSUBISHI
@ KASEIKYO_MITSUBISHI
Definition: IRProtocol.h:57
IRsend::sendPulseDistanceWidthFromArray_P
void sendPulseDistanceWidthFromArray_P(PulseDistanceWidthProtocolConstants const *aProtocolConstantsPGM, IRRawDataType *aDecodedRawDataArray, uint16_t aNumberOfBits, int_fast8_t aNumberOfRepeats)
Definition: IRSend.hpp:764
DENON
@ DENON
Definition: IRProtocol.h:45
enableSendPWMByTimer
void enableSendPWMByTimer()
Enables output of the PWM signal of the timer at the timer pin.
Definition: IRTimer.hpp:135
IrSender
IRsend IrSender
Definition: IRSend.hpp:65
IR_SEND_DUTY_CYCLE_PERCENT
#define IR_SEND_DUTY_CYCLE_PERCENT
Duty cycle in percent for sent signals.
Definition: IRremote.hpp:243
SIRCS_12_PROTOCOL
#define SIRCS_12_PROTOCOL
Definition: IRProtocol.h:76
RC5
@ RC5
Definition: IRProtocol.h:58
PulseDistanceWidthProtocolConstants::DistanceWidthTimingInfo
DistanceWidthTimingInfoStruct DistanceWidthTimingInfo
Definition: IRProtocol.h:140
IRsend::periodTimeMicros
uint16_t periodTimeMicros
Definition: IRremoteInt.h:683
IRsend::space
static void space(uint16_t aSpaceMicros)
Sends an IR space for the specified number of microseconds.
Definition: IRSend.hpp:1344
IRsend::sendRC5
void sendRC5(uint8_t aAddress, uint8_t aCommand, int_fast8_t aNumberOfRepeats, bool aEnableAutomaticToggle=true)
Definition: ir_RC5_RC6.hpp:105
FeedbackLEDControl
struct FeedbackLEDControlStruct FeedbackLEDControl
The feedback LED control instance.
Definition: IRFeedbackLED.hpp:47
disableSendPWMByTimer
void disableSendPWMByTimer()
Disables output of the PWM signal of the timer at the timer pin and set it to inactive.
Definition: IRTimer.hpp:140
IRsend::sendNEC2
void sendNEC2(uint16_t aAddress, uint16_t aCommand, int_fast8_t aNumberOfRepeats)
NEC2 Send frame !!! and repeat the frame for each requested repeat !!! There is NO delay after the la...
Definition: ir_NEC.hpp:200
IRsend::sendKaseikyo_Mitsubishi
void sendKaseikyo_Mitsubishi(uint16_t aAddress, uint8_t aData, int_fast8_t aNumberOfRepeats)
Stub using Kaseikyo with MITSUBISHI_VENDOR_ID_CODE.
Definition: ir_Kaseikyo.hpp:178
RC6
@ RC6
Definition: IRProtocol.h:59
IRsend::IRLedOff
void IRLedOff()
Just switch the IR sending LED off to send an IR space A space is "no output", so the PWM output is d...
Definition: IRSend.hpp:1309
IRsend::sendPulseDistanceWidthFromArray
void sendPulseDistanceWidthFromArray(uint_fast8_t aFrequencyKHz, uint16_t aHeaderMarkMicros, uint16_t aHeaderSpaceMicros, uint16_t aOneMarkMicros, uint16_t aOneSpaceMicros, uint16_t aZeroMarkMicros, uint16_t aZeroSpaceMicros, IRRawDataType *aDecodedRawDataArray, uint16_t aNumberOfBits, uint8_t aFlags, uint16_t aRepeatPeriodMillis, int_fast8_t aNumberOfRepeats)
Definition: IRSend.hpp:535
sendFAST
void sendFAST(uint8_t aSendPin, uint16_t aCommand, uint_fast8_t aNumberOfRepeats=0)
Definition: TinyIRSender.hpp:294
IRsend::sendPulseDistanceWidthData
void sendPulseDistanceWidthData(PulseDistanceWidthProtocolConstants *aProtocolConstants, IRRawDataType aData, uint_fast8_t aNumberOfBits)
Sends PulseDistance from data contained in parameter using ProtocolConstants structure for timing etc...
Definition: IRSend.hpp:999
IRsend::sendOnkyo
void sendOnkyo(uint16_t aAddress, uint16_t aCommand, int_fast8_t aNumberOfRepeats)
There is NO delay after the last sent repeat!
Definition: ir_NEC.hpp:191
PulseDistanceWidthProtocolConstants::RepeatPeriodMillis
unsigned int RepeatPeriodMillis
Definition: IRProtocol.h:142
IRsend::sendLegoPowerFunctions
void sendLegoPowerFunctions(uint8_t aChannel, uint8_t tCommand, uint8_t aMode, bool aDoSend5Times=true)
Definition: ir_Lego.hpp:97
USE_DEFAULT_FEEDBACK_LED_PIN
#define USE_DEFAULT_FEEDBACK_LED_PIN
Definition: IRremoteInt.h:64
SAMSUNGLG
@ SAMSUNGLG
Definition: IRProtocol.h:62
IRData::protocol
decode_type_t protocol
UNKNOWN, NEC, SONY, RC5, PULSE_DISTANCE, ...
Definition: IRProtocol.h:110
IRsend::sendBiphaseData
void sendBiphaseData(uint16_t aBiphaseTimeUnit, uint32_t aData, uint_fast8_t aNumberOfBits)
Sends Biphase data MSB first Always send start bit, do not send the trailing space of the start bit 0...
Definition: IRSend.hpp:1083
SAMSUNG48
@ SAMSUNG48
Definition: IRProtocol.h:63
IRsend::sendLG
void sendLG(uint8_t aAddress, uint16_t aCommand, int_fast8_t aNumberOfRepeats)
LG uses the NEC repeat.
Definition: ir_LG.hpp:165
PulseDistanceWidthProtocolConstants::FrequencyKHz
uint_fast8_t FrequencyKHz
Definition: IRProtocol.h:139
DistanceWidthTimingInfoStruct::HeaderSpaceMicros
uint16_t HeaderSpaceMicros
Definition: IRProtocol.h:82
IRsend::aCommand
void aCommand
Definition: IRremoteInt.h:646
LG
@ LG
Definition: IRProtocol.h:47
IRsend::enableIROut
void enableIROut(uint_fast8_t aFrequencyKHz)
Enables IR output.
Definition: IRSend.hpp:1384
IRsend::sendKaseikyo_Denon
void sendKaseikyo_Denon(uint16_t aAddress, uint8_t aData, int_fast8_t aNumberOfRepeats)
Stub using Kaseikyo with DENON_VENDOR_ID_CODE.
Definition: ir_Kaseikyo.hpp:171
setLEDFeedback
void setLEDFeedback(uint8_t aFeedbackLEDPin, uint8_t aEnableLEDFeedback)
Enables blinking of feedback LED (LED_BUILTIN is taken as default) on IR sending and receiving Cannot...
Definition: IRFeedbackLED.hpp:56
SHARP
@ SHARP
Definition: IRProtocol.h:64