55 #if defined(SEND_PWM_BY_TIMER) && ( (defined(ESP32) || defined(ARDUINO_ARCH_RP2040) || defined(PARTICLE)) || defined(ARDUINO_ARCH_MBED) )
56 #define SEND_PWM_DOES_NOT_USE_RECEIVE_TIMER // Receive timer and send generation are independent, so it is recommended to always define SEND_PWM_BY_TIMER
59 #if defined(IR_SEND_PIN) && defined(SEND_PWM_BY_TIMER) && !defined(SEND_PWM_DOES_NOT_USE_RECEIVE_TIMER) // For e.g ESP32 IR_SEND_PIN definition is useful
60 #undef IR_SEND_PIN // avoid warning below, user warning is done at IRremote.hpp
139 #elif defined(__AVR__)
148 #if defined(__AVR_ATmega328P__) || defined(__AVR_ATmega328PB__) || defined(__AVR_ATmega168__) \
149 || defined(__AVR_ATmega88P__) || defined(__AVR_ATmega88PB__) || defined(__AVR_ATmega8__)
150 # if !defined(IR_USE_AVR_TIMER1) && !defined(IR_USE_AVR_TIMER2)
152 #define IR_USE_AVR_TIMER2 // send pin = pin 3
156 #elif defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__)
157 # if !defined(IR_USE_AVR_TIMER1) && !defined(IR_USE_AVR_TIMER2) && !defined(IR_USE_AVR_TIMER3) && !defined(IR_USE_AVR_TIMER4) && !defined(IR_USE_AVR_TIMER5)
159 #define IR_USE_AVR_TIMER2 // send pin = pin 9
166 #elif defined(__AVR_ATmega32U4__) && ! defined(TEENSYDUINO) && ! defined(ARDUINO_AVR_PROMICRO)
167 # if !defined(IR_USE_AVR_TIMER1) && !defined(IR_USE_AVR_TIMER3) && !defined(IR_USE_AVR_TIMER4_HS)
169 #define IR_USE_AVR_TIMER3 // send pin = pin 5
174 #elif defined(__AVR_ATmega808__) || defined(__AVR_ATmega809__) || defined(__AVR_ATmega3208__) || defined(__AVR_ATmega3209__) \
175 || defined(__AVR_ATmega1608__) || defined(__AVR_ATmega1609__) || defined(__AVR_ATmega4808__) || defined(__AVR_ATmega4809__) || defined(__AVR_ATtiny1604__)
176 # if !defined(IR_USE_AVR_TIMER_B)
177 #define IR_USE_AVR_TIMER_B // send pin = pin 6 on ATmega4809 1 on ATmega4809
180 #elif defined(__AVR_ATtiny816__) || defined(__AVR_ATtiny1614__) || defined(__AVR_ATtiny1616__) || defined(__AVR_ATtiny3216__) || defined(__AVR_ATtiny3217__) // e.g. TinyCore boards
181 # if !defined(IR_USE_AVR_TIMER_A) && !defined(IR_USE_AVR_TIMER_D)
182 #define IR_USE_AVR_TIMER_A // use this if you use MegaTinyCore, Tone is on TCB and millis() on TCD
187 #elif defined(__AVR_ATmega8U2__) || defined(__AVR_ATmega16U2__) || defined(__AVR_ATmega32U2__)
188 # if !defined(IR_USE_AVR_TIMER1)
189 #define IR_USE_AVR_TIMER1 // send pin = pin C6
193 #elif defined(__AVR_ATtiny84__) || defined(__AVR_ATtiny88__)
194 # if !defined(IR_USE_AVR_TIMER1)
195 #define IR_USE_AVR_TIMER1 // send pin = pin 6
198 #elif defined(__AVR_ATtiny87__) || defined(__AVR_ATtiny167__)
199 # if !defined(IR_USE_AVR_TIMER1)
200 #define IR_USE_AVR_TIMER1 // send pin = pin PB1 / 8
202 #define USE_TIMER_CHANNEL_B
205 #elif defined(__AVR_ATtiny25__) || defined(__AVR_ATtiny45__) || defined(__AVR_ATtiny85__)
206 # if !defined(IR_USE_AVR_TIMER_TINY0) && !defined(IR_USE_AVR_TIMER_TINY1)
207 # if defined(ARDUINO_AVR_DIGISPARK) // tested with 16 and 8 MHz
208 #define IR_USE_AVR_TIMER_TINY0 // send pin = pin 1
212 #define IR_USE_AVR_TIMER_TINY1 // send pin = pin 4
219 #elif defined(ARDUINO_AVR_PROMICRO)
220 # if !defined(IR_USE_AVR_TIMER1) && !defined(IR_USE_AVR_TIMER3) && !defined(IR_USE_AVR_TIMER4_HS)
222 #define IR_USE_AVR_TIMER3 // send pin = pin 5
230 #elif defined(__AVR_AT90USB162__)
231 # if !defined(IR_USE_AVR_TIMER1)
232 #define IR_USE_AVR_TIMER1 // send pin = pin 17
236 #elif defined(__AVR_AT90USB646__) || defined(__AVR_AT90USB1286__)
237 # if !defined(IR_USE_AVR_TIMER1) && !defined(IR_USE_AVR_TIMER2) && !defined(IR_USE_AVR_TIMER3)
239 #define IR_USE_AVR_TIMER2 // send pin = pin 1
244 #elif defined(__AVR_ATmega32U4__) && defined(TEENSYDUINO)
245 # if !defined(IR_USE_AVR_TIMER1) && !defined(IR_USE_AVR_TIMER3) && !defined(IR_USE_AVR_TIMER4_HS)
248 #define IR_USE_AVR_TIMER4_HS // send pin = pin 10 (Teensy 2.0 - physical pin: C7)
255 #elif defined(__AVR_ATmega64__) || defined(__AVR_ATmega128__) || defined(__AVR_ATmega1281__) || defined(__AVR_ATmega2560__)
256 # if !defined(IR_USE_AVR_TIMER1)
257 #define IR_USE_AVR_TIMER1 // send pin = pin 13
263 #elif defined(__AVR_ATmega8515__) || defined(__AVR_ATmega162__)
264 # if !defined(IR_USE_AVR_TIMER1) && !defined(IR_USE_AVR_TIMER3)
265 #define IR_USE_AVR_TIMER1 // send pin = pin 13
273 #elif defined(__AVR_ATmega1284__) || defined(__AVR_ATmega1284P__)
274 # if !defined(IR_USE_AVR_TIMER1) && !defined(IR_USE_AVR_TIMER2) && !defined(IR_USE_AVR_TIMER3)
276 #define IR_USE_AVR_TIMER2 // send pin = pin 14
281 #elif defined(__AVR_ATmega644__) || defined(__AVR_ATmega644P__) \
282 || defined(__AVR_ATmega324P__) || defined(__AVR_ATmega324A__) \
283 || defined(__AVR_ATmega324PA__) || defined(__AVR_ATmega164A__) \
284 || defined(__AVR_ATmega164P__)
285 # if !defined(IR_USE_AVR_TIMER1) && !defined(IR_USE_AVR_TIMER2)
287 #define IR_USE_AVR_TIMER2 // send pin = pin 14
291 #elif defined(__AVR_ATmega8535__) || defined(__AVR_ATmega16__) || defined(__AVR_ATmega32__)
292 # if !defined(IR_USE_AVR_TIMER1)
293 #define IR_USE_AVR_TIMER1 // send pin = pin 13
303 #if defined(IR_USE_AVR_TIMER1)
307 TIMSK1 = _BV(OCIE1A);
310 TIMSK1 &= ~_BV(OCIE1A);
314 TIMSK |= _BV(OCIE1A);
317 TIMSK &= ~_BV(OCIE1A);
321 # if defined(USE_TIMER_CHANNEL_B)
322 # if defined(TIMER1_COMPB_vect)
323 #define TIMER_INTR_NAME TIMER1_COMPB_vect
324 # elif defined(TIM1_COMPB_vect)
325 #define TIMER_INTR_NAME TIM1_COMPB_vect
328 # if defined(TIMER1_COMPA_vect)
329 #define TIMER_INTR_NAME TIMER1_COMPA_vect
330 # elif defined(TIM1_COMPA_vect)
331 #define TIMER_INTR_NAME TIM1_COMPA_vect
337 TCCR1B = _BV(WGM12) | _BV(CS10);
342 # if defined(SEND_PWM_BY_TIMER)
343 # if defined(CORE_OC1A_PIN)
344 #define IR_SEND_PIN CORE_OC1A_PIN // Teensy
346 # elif defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__)
347 #define IR_SEND_PIN 11 // Arduino Mega
350 # elif defined(__AVR_ATmega1284__) || defined(__AVR_ATmega1284P__) \
351 || defined(__AVR_ATmega644__) || defined(__AVR_ATmega644P__) \
352 || defined(__AVR_ATmega324P__) || defined(__AVR_ATmega324A__) \
353 || defined(__AVR_ATmega324PA__) || defined(__AVR_ATmega164A__) \
354 || defined(__AVR_ATmega164P__) || defined(__AVR_ATmega32__) \
355 || defined(__AVR_ATmega16__) || defined(__AVR_ATmega8535__) \
356 || defined(__AVR_ATmega64__) || defined(__AVR_ATmega128__) \
357 || defined(__AVR_ATmega1281__) || defined(__AVR_ATmega2561__) \
358 || defined(__AVR_ATmega8515__) || defined(__AVR_ATmega162__)
359 #define IR_SEND_PIN 13
361 # elif defined(__AVR_ATtiny84__)
362 #define IR_SEND_PIN 6
364 # elif defined(__AVR_ATtiny88__)
365 #define IR_SEND_PIN 8
367 # elif defined(__AVR_ATtiny87__) || defined(__AVR_ATtiny167__)
371 # if defined(USE_TIMER_CHANNEL_B)
372 #define IR_SEND_PIN PIN_PB1 // OC1BU / PB1 / Pin9 at ATTinyCore
377 #define IR_SEND_PIN PIN_PB0 // OC1AU / PB1 / Pin8 at ATTinyCore
384 #define IR_SEND_PIN 9 // OC1A Arduino Duemilanove, Diecimila, LilyPad, Sparkfun Pro Micro, Leonardo, MH-ET Tiny88 etc.
385 # endif // defined(CORE_OC1A_PIN)
387 # if defined(__AVR_ATtiny87__) || defined(__AVR_ATtiny167__)
389 # if defined(USE_TIMER_CHANNEL_B)
392 TCCR1A |= _BV(COM1B1);
393 TCCR1D |= _BV(OC1BU);
401 TCCR1A |= _BV(COM1A1);
402 TCCR1D |= _BV(OC1AU);
413 # if defined(USE_TIMER_CHANNEL_B)
415 TCNT1 = 0; (TCCR1A |= _BV(COM1B1))
418 TCCR1A &= ~(_BV(COM1B1));
423 TCCR1A |= _BV(COM1A1);
426 TCCR1A &= ~(_BV(COM1A1));
438 # if (((F_CPU / 2000) / 38) < 256)
439 const uint16_t tPWMWrapValue = (F_CPU / 2000) / (aFrequencyKHz);
441 TCCR1B = _BV(WGM13) | _BV(CS10);
442 ICR1 = tPWMWrapValue - 1;
443 # if defined(USE_TIMER_CHANNEL_B)
450 const uint16_t tPWMWrapValue = ((F_CPU / 8) / 2000) / (aFrequencyKHz);
452 TCCR1B = _BV(WGM13) | _BV(CS11);
453 ICR1 = tPWMWrapValue - 1;
454 # if defined(USE_TIMER_CHANNEL_B)
462 # endif // defined(SEND_PWM_BY_TIMER)
467 #elif defined(IR_USE_AVR_TIMER2)
470 TIMSK2 = _BV(OCIE2B);
475 #define TIMER_INTR_NAME TIMER2_COMPB_vect // We use TIMER2_COMPB_vect to be compatible with tone() library
477 #define TIMER_COUNT_TOP (F_CPU * MICROS_PER_TICK / MICROS_IN_ONE_SECOND)
480 # if (TIMER_COUNT_TOP < 256)
483 OCR2A = TIMER_COUNT_TOP;
484 OCR2B = TIMER_COUNT_TOP;
489 OCR2A = TIMER_COUNT_TOP / 8;
490 OCR2B = TIMER_COUNT_TOP / 8;
495 # if defined(SEND_PWM_BY_TIMER)
496 # if defined(CORE_OC2B_PIN)
497 #define IR_SEND_PIN CORE_OC2B_PIN // Teensy
499 # elif defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__)
500 #define IR_SEND_PIN 9 // Arduino Mega
502 # elif defined(__AVR_ATmega1284__) || defined(__AVR_ATmega1284P__) \
503 || defined(__AVR_ATmega644__) || defined(__AVR_ATmega644P__) \
504 || defined(__AVR_ATmega324P__) || defined(__AVR_ATmega324A__) \
505 || defined(__AVR_ATmega324PA__) || defined(__AVR_ATmega164A__) \
506 || defined(__AVR_ATmega164P__)
507 #define IR_SEND_PIN 14 // MightyCore, MegaCore
510 #define IR_SEND_PIN 3 // Arduino Duemilanove, Diecimila, LilyPad, etc
511 # endif // defined(CORE_OC2B_PIN)
515 TCCR2A |= _BV(COM2B1);
518 TCCR2A &= ~(_BV(COM2B1));
528 # if (((F_CPU / 2000) / 38) < 256)
529 const uint16_t tPWMWrapValue = (F_CPU / 2000) / (aFrequencyKHz);
531 TCCR2B = _BV(WGM22) | _BV(CS20);
532 OCR2A = tPWMWrapValue - 1;
536 const uint16_t tPWMWrapValue = ((F_CPU / 8) / 2000) / (aFrequencyKHz);
538 TCCR2B = _BV(WGM22) | _BV(CS21);
539 OCR2A = tPWMWrapValue - 1;
544 # endif // defined(SEND_PWM_BY_TIMER)
549 #elif defined(IR_USE_AVR_TIMER3)
552 TIMSK3 = _BV(OCIE3B);
557 #define TIMER_INTR_NAME TIMER3_COMPB_vect
561 TCCR3B = _BV(WGM32) | _BV(CS30);
567 # if defined(SEND_PWM_BY_TIMER)
568 # if defined(CORE_OC3A_PIN)
569 #define IR_SEND_PIN CORE_OC3A_PIN // Teensy
571 # elif defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__) \
572 || defined(__AVR_ATmega32U4__) || defined(ARDUINO_AVR_PROMICRO)
573 #define IR_SEND_PIN 5 // Arduino Mega, Arduino Leonardo, Sparkfun Pro Micro
575 # elif defined(__AVR_ATmega1284__) || defined(__AVR_ATmega1284P__)
576 #define IR_SEND_PIN 6 // MightyCore, MegaCore
579 #error Please add OC3A pin number here
584 TCCR3A |= _BV(COM3A1);
587 TCCR3A &= ~(_BV(COM3A1));
596 #error "Creating timer PWM with timer 3 is not supported for F_CPU > 16 MHz"
600 const uint16_t tPWMWrapValue = (F_CPU / 2000) / (aFrequencyKHz);
602 TCCR3B = _BV(WGM33) | _BV(CS30);
603 ICR3 = tPWMWrapValue - 1;
607 # endif // defined(SEND_PWM_BY_TIMER)
612 #elif defined(IR_USE_AVR_TIMER4)
614 TIMSK4 = _BV(OCIE4A);
619 #define TIMER_INTR_NAME TIMER4_COMPA_vect
623 TCCR4B = _BV(WGM42) | _BV(CS40);
628 # if defined(SEND_PWM_BY_TIMER)
629 # if defined(CORE_OC4A_PIN)
630 #define IR_SEND_PIN CORE_OC4A_PIN
631 # elif defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__)
632 #define IR_SEND_PIN 6 // Arduino Mega
634 #error Please add OC4A pin number here
639 TCCR4A |= _BV(COM4A1);
642 TCCR4A &= ~(_BV(COM4A1));
647 #error "Creating timer PWM with timer 4 is not supported for F_CPU > 16 MHz"
650 const uint16_t tPWMWrapValue = (F_CPU / 2000) / (aFrequencyKHz);
652 TCCR4B = _BV(WGM43) | _BV(CS40);
653 ICR4 = tPWMWrapValue - 1;
657 # endif // defined(SEND_PWM_BY_TIMER)
662 #elif defined(IR_USE_AVR_TIMER4_HS)
670 #define TIMER_INTR_NAME TIMER4_OVF_vect
684 # if defined(SEND_PWM_BY_TIMER)
685 # if defined(CORE_OC4A_PIN)
686 #define IR_SEND_PIN CORE_OC4A_PIN // Teensy 2.0
687 # elif defined(ARDUINO_AVR_PROMICRO)
688 #define IR_SEND_PIN 5 // Sparkfun Pro Micro
689 # elif defined(__AVR_ATmega32U4__)
690 #define IR_SEND_PIN 13 // Leonardo
692 #error Please add OC4A pin number here
695 # if defined(ARDUINO_AVR_PROMICRO) // Sparkfun Pro Micro
702 TCCR4A |= _BV(COM4A1);
706 TCCR4A &= ~(_BV(COM4A1));
716 #error "Creating timer PWM with timer 4 HS is not supported for F_CPU > 16 MHz"
720 const uint16_t tPWMWrapValue = ((F_CPU / 2000) / (aFrequencyKHz)) - 1;
721 TCCR4A = (1 << PWM4A);
724 TCCR4D = (1 << WGM40);
726 TC4H = tPWMWrapValue >> 8;
727 OCR4C = tPWMWrapValue;
732 # endif // defined(SEND_PWM_BY_TIMER)
737 #elif defined(IR_USE_AVR_TIMER5)
740 TIMSK5 = _BV(OCIE5A);
745 #define TIMER_INTR_NAME TIMER5_COMPA_vect
749 TCCR5B = _BV(WGM52) | _BV(CS50);
754 # if defined(SEND_PWM_BY_TIMER)
755 # if defined(CORE_OC5A_PIN)
756 #define IR_SEND_PIN CORE_OC5A_PIN
757 # elif defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__)
758 #define IR_SEND_PIN 46 // Arduino Mega
760 #error Please add OC5A pin number here
765 TCCR5A |= _BV(COM5A1);
768 TCCR5A &= ~(_BV(COM5A1));
777 #error "Creating timer PWM with timer 5 is not supported for F_CPU > 16 MHz"
781 const uint16_t tPWMWrapValue = (F_CPU / 2000) / (aFrequencyKHz);
783 TCCR5B = _BV(WGM53) | _BV(CS50);
784 ICR5 = tPWMWrapValue - 1;
788 # endif // defined(SEND_PWM_BY_TIMER)
793 #elif defined(IR_USE_AVR_TIMER_TINY0)
796 TIMSK |= _BV(OCIE0A);
799 TIMSK &= ~(_BV(OCIE0A));
801 #define TIMER_INTR_NAME TIMER0_COMPA_vect
803 #define TIMER_COUNT_TOP (F_CPU * MICROS_PER_TICK / MICROS_IN_ONE_SECOND)
806 # if (TIMER_COUNT_TOP < 256)
809 OCR0A = TIMER_COUNT_TOP;
814 OCR0A = TIMER_COUNT_TOP / 8;
819 # if defined(SEND_PWM_BY_TIMER)
820 #define IR_SEND_PIN 1
824 TCCR0A |= _BV(COM0B1);
827 TCCR0A &= ~(_BV(COM0B1));
836 #error "Creating timer PWM with timer TINY0 is not supported for F_CPU > 16 MHz"
840 const uint16_t tPWMWrapValue = (F_CPU / 2000) / (aFrequencyKHz);
842 TCCR0B = _BV(WGM02) | _BV(CS00);
843 OCR0A = tPWMWrapValue - 1;
847 # endif // defined(SEND_PWM_BY_TIMER)
852 #elif defined(IR_USE_AVR_TIMER_TINY1)
855 TIMSK |= _BV(OCIE1B);
858 TIMSK &= ~(_BV(OCIE1B));
860 #define TIMER_INTR_NAME TIMER1_COMPB_vect
862 #define TIMER_COUNT_TOP (F_CPU * MICROS_PER_TICK / MICROS_IN_ONE_SECOND)
865 # if (TIMER_COUNT_TOP < 256)
866 TCCR1 = _BV(CTC1) | _BV(CS10);
868 OCR1C = TIMER_COUNT_TOP;
871 TCCR1 = _BV(CTC1) | _BV(CS12);
873 OCR1C = TIMER_COUNT_TOP / 8;
878 # if defined(SEND_PWM_BY_TIMER)
879 #define IR_SEND_PIN 4
883 GTCCR |= _BV(PWM1B) | _BV(COM1B0);
886 GTCCR &= ~(_BV(PWM1B) | _BV(COM1B0));
896 # if (((F_CPU / 1000) / 38) < 256)
897 const uint16_t tPWMWrapValue = (F_CPU / 1000) / (aFrequencyKHz);
898 TCCR1 = _BV(CTC1) | _BV(CS10);
899 OCR1C = tPWMWrapValue - 1;
902 GTCCR = _BV(PWM1B) | _BV(COM1B0);
904 const uint16_t tPWMWrapValue = ((F_CPU / 2) / 1000) / (aFrequencyKHz);
905 TCCR1 = _BV(CTC1) | _BV(CS11);
906 OCR1C = tPWMWrapValue - 1;
909 GTCCR = _BV(PWM1B) | _BV(COM1B0);
912 # endif // defined(SEND_PWM_BY_TIMER)
917 #elif defined(IR_USE_AVR_TIMER_A)
918 #define TIMER_REQUIRES_RESET_INTR_PENDING
920 TCA0.SINGLE.INTFLAGS = TCA_SINGLE_OVF_bm;
923 TCA0.SINGLE.INTCTRL = TCA_SINGLE_OVF_bm;
926 TCA0.SINGLE.INTCTRL &= ~(TCA_SINGLE_OVF_bm);
928 #define TIMER_INTR_NAME TCA0_OVF_vect
935 TCA0.SINGLE.CTRLD = 0;
936 TCA0.SINGLE.CTRLB = TCA_SINGLE_WGMODE_NORMAL_gc;
938 TCA0.SINGLE.CTRLA = TCA_SINGLE_CLKSEL_DIV1_gc | TCA_SINGLE_ENABLE_bm;
941 # if defined(SEND_PWM_BY_TIMER)
942 #error "No support for hardware PWM generation for ATtiny3216/17 etc."
943 # endif // defined(SEND_PWM_BY_TIMER)
948 #elif defined(IR_USE_AVR_TIMER_B)
951 #define TIMER_REQUIRES_RESET_INTR_PENDING
953 TCB0.INTFLAGS = TCB_CAPT_bm;
956 TCB0.INTCTRL = TCB_CAPT_bm;
959 TCB0.INTCTRL &= ~(TCB_CAPT_bm);
961 #define TIMER_INTR_NAME TCB0_INT_vect
964 TCB0.CTRLB = (TCB_CNTMODE_INT_gc);
966 TCB0.INTFLAGS = TCB_CAPT_bm;
967 TCB0.CTRLA = (TCB_CLKSEL_CLKDIV1_gc) | (TCB_ENABLE_bm);
970 # if defined(SEND_PWM_BY_TIMER)
971 # if defined(__AVR_ATmega4808__) || defined(__AVR_ATmega4809__)
972 #define IR_SEND_PIN 6 // PF4 on ATmega4809 / Nano Every (see pins_arduino.h digital_pin_to_timer)
974 #error SEND_PWM_BY_TIMER not yet supported for this CPU
979 TCB0.CTRLB |= TCB_CCMPEN_bm;
982 TCB0.CTRLB &= ~(TCB_CCMPEN_bm);
992 #error "Creating timer PWM with timer TCB0 is not possible for F_CPU > 16 MHz"
996 const uint16_t tPWMWrapValue = (F_CPU / 2000) / (aFrequencyKHz);
997 TCB0.CTRLB = TCB_CNTMODE_PWM8_gc;
998 TCB0.CCMPL = tPWMWrapValue - 1;
1000 TCB0.CTRLA = (TCB_CLKSEL_CLKDIV2_gc) | (TCB_ENABLE_bm);
1003 # endif // defined(SEND_PWM_BY_TIMER)
1008 #elif defined(IR_USE_AVR_TIMER_D)
1010 #define TIMER_REQUIRES_RESET_INTR_PENDING
1012 TCD0.INTFLAGS = TCD_OVF_bm;
1015 TCD0.INTCTRL = TCD_OVF_bm;
1020 #define TIMER_INTR_NAME TCD0_OVF_vect
1024 TCD0.CTRLB = TCD_WGMODE_ONERAMP_gc;
1028 _PROTECTED_WRITE(TCD0.FAULTCTRL, 0);
1030 TCD0.INTFLAGS = TCD_OVF_bm;
1034 TCD0.CTRLA = TCD_ENABLE_bm | TCD_CLKSEL_SYSCLK_gc | TCD_CNTPRES_DIV1_gc;
1037 # if defined(SEND_PWM_BY_TIMER)
1038 #define IR_SEND_PIN 13
1040 void timerEnableSendPWM() {
1042 _PROTECTED_WRITE(TCD0.FAULTCTRL, FUSE_CMPAEN_bm);
1044 TCD0.CTRLA = TCD_ENABLE_bm | TCD_CLKSEL_SYSCLK_gc | TCD_CNTPRES_DIV1_gc;
1048 timerEnableSendPWM();
1061 const uint16_t tPWMWrapValue = (F_CPU / 1000) / (aFrequencyKHz);
1065 TCD0.CTRLB = TCD_WGMODE_ONERAMP_gc;
1068 TCD0.CMPBCLR = tPWMWrapValue - 1;
1074 TCD0.INTFLAGS = TCD_OVF_bm;
1075 TCD0.INTCTRL = TCD_OVF_bm;
1078 # endif // defined(SEND_PWM_BY_TIMER)
1081 #error Internal code configuration error, no timer functions implemented for this AVR CPU / board
1082 #endif //defined(IR_USE_AVR_TIMER*)
1090 #elif defined(__MK20DX128__) || defined(__MK20DX256__) || defined(__MK64FX512__) || defined(__MK66FX1M0__)
1093 #define TIMER_REQUIRES_RESET_INTR_PENDING
1095 uint8_t tmp __attribute__((unused)) = CMT_MSC;
1099 NVIC_ENABLE_IRQ(IRQ_CMT);
1100 NVIC_SET_PRIORITY(IRQ_CMT, 48);
1103 NVIC_DISABLE_IRQ(IRQ_CMT);
1105 #define TIMER_INTR_NAME cmt_isr
1110 #define ISR(f) void f(void)
1112 #define CMT_PPS_DIV ((F_BUS + 7999999) / 8000000)
1113 # if F_BUS < 8000000
1114 #error IRremote requires at least 8 MHz on Teensy 3.x
1118 SIM_SCGC4 |= SIM_SCGC4_CMT;
1119 CMT_PPS = CMT_PPS_DIV - 1;
1125 CMT_CMD4 = (F_BUS / 160000 + CMT_PPS_DIV / 2) / CMT_PPS_DIV - 31;
1130 # if defined(SEND_PWM_BY_TIMER)
1131 #define IR_SEND_PIN 5
1135 CORE_PIN5_CONFIG = PORT_PCR_MUX(2) | PORT_PCR_DSE | PORT_PCR_SRE;
1140 CORE_PIN5_CONFIG = PORT_PCR_MUX(1) | PORT_PCR_DSE | PORT_PCR_SRE;
1150 # if defined(IR_SEND_PIN)
1156 SIM_SCGC4 |= SIM_SCGC4_CMT;
1157 SIM_SOPT2 |= SIM_SOPT2_PTD7PAD;
1158 CMT_PPS = CMT_PPS_DIV - 1;
1159 CMT_CGH1 = ((F_BUS / CMT_PPS_DIV / 3000) + ((aFrequencyKHz) / 2)) / (aFrequencyKHz);
1160 CMT_CGL1 = ((F_BUS / CMT_PPS_DIV / 1500) + ((aFrequencyKHz) / 2)) / (aFrequencyKHz);
1168 # endif // defined(SEND_PWM_BY_TIMER)
1173 #elif defined(__MKL26Z64__)
1176 #define TIMER_REQUIRES_RESET_INTR_PENDING
1178 FTM1_SC |= FTM_SC_TOF;
1181 NVIC_ENABLE_IRQ(IRQ_FTM1);
1182 NVIC_SET_PRIORITY(IRQ_FTM1, 0);
1185 NVIC_DISABLE_IRQ(IRQ_FTM1);
1187 #define TIMER_INTR_NAME ftm1_isr
1191 #define ISR(f) void f(void)
1194 SIM_SCGC6 |= SIM_SCGC6_TPM1;
1197 FTM1_MOD = (F_PLL / 40000) - 1;
1199 FTM1_SC = FTM_SC_CLKS(1) | FTM_SC_PS(0) | FTM_SC_TOF | FTM_SC_TOIE;
1202 # if defined(SEND_PWM_BY_TIMER)
1203 #define IR_SEND_PIN 16
1207 CORE_PIN16_CONFIG = PORT_PCR_MUX(3) | PORT_PCR_DSE | PORT_PCR_SRE;
1210 CORE_PIN16_CONFIG = PORT_PCR_MUX(1) | PORT_PCR_SRE;
1219 # if defined(IR_SEND_PIN)
1225 SIM_SCGC6 |= SIM_SCGC6_TPM1;
1228 FTM1_MOD = ((F_PLL / 2000) / aFrequencyKHz) - 1;
1229 FTM1_C0V = ((F_PLL / 6000) / aFrequencyKHz) - 1;
1230 FTM1_SC = FTM_SC_CLKS(1) | FTM_SC_PS(0);
1232 # endif // defined(SEND_PWM_BY_TIMER)
1237 #elif defined(__IMXRT1062__)
1240 #define TIMER_REQUIRES_RESET_INTR_PENDING
1242 FLEXPWM1_SM3STS = FLEXPWM_SMSTS_RF;
1245 attachInterruptVector(IRQ_FLEXPWM1_3, pwm1_3_isr);
1246 FLEXPWM1_SM3STS = FLEXPWM_SMSTS_RF;
1247 FLEXPWM1_SM3INTEN = FLEXPWM_SMINTEN_RIE;
1248 NVIC_ENABLE_IRQ (IRQ_FLEXPWM1_3), NVIC_SET_PRIORITY(IRQ_FLEXPWM1_3, 48);
1251 NVIC_DISABLE_IRQ (IRQ_FLEXPWM1_3);
1253 #define TIMER_INTR_NAME pwm1_3_isr
1257 #define ISR(f) void (f)(void)
1261 uint32_t period = (float) F_BUS_ACTUAL * (
float) (
MICROS_PER_TICK) * 0.0000005f;
1262 uint32_t prescale = 0;
1263 while (period > 32767) {
1264 period = period >> 1;
1268 FLEXPWM1_FCTRL0 |= FLEXPWM_FCTRL0_FLVL(8);
1269 FLEXPWM1_FSTS0 = 0x0008;
1270 FLEXPWM1_MCTRL |= FLEXPWM_MCTRL_CLDOK(8);
1271 FLEXPWM1_SM3CTRL2 = FLEXPWM_SMCTRL2_INDEP;
1272 FLEXPWM1_SM3CTRL = FLEXPWM_SMCTRL_HALF | FLEXPWM_SMCTRL_PRSC(prescale);
1273 FLEXPWM1_SM3INIT = -period;
1274 FLEXPWM1_SM3VAL0 = 0;
1275 FLEXPWM1_SM3VAL1 = period;
1276 FLEXPWM1_SM3VAL2 = 0;
1277 FLEXPWM1_SM3VAL3 = 0;
1278 FLEXPWM1_SM3VAL4 = 0;
1279 FLEXPWM1_SM3VAL5 = 0;
1280 FLEXPWM1_MCTRL |= FLEXPWM_MCTRL_LDOK(8) | FLEXPWM_MCTRL_RUN(8);
1283 # if defined(SEND_PWM_BY_TIMER)
1284 #define IR_SEND_PIN 7
1286 FLEXPWM1_OUTEN |= FLEXPWM_OUTEN_PWMA_EN(8);
1287 IOMUXC_SW_MUX_CTL_PAD_GPIO_B1_00 = 6;
1291 IOMUXC_SW_MUX_CTL_PAD_GPIO_B1_00 = 5;
1292 FLEXPWM1_OUTEN &= ~FLEXPWM_OUTEN_PWMA_EN(8);
1301 # if defined(IR_SEND_PIN)
1307 uint32_t period = (float) F_BUS_ACTUAL / (
float) ((aFrequencyKHz) * 2000);
1308 uint32_t prescale = 0;
1309 while (period > 32767) {
1310 period = period >> 1;
1314 FLEXPWM1_FCTRL0 |= FLEXPWM_FCTRL0_FLVL(8);
1315 FLEXPWM1_FSTS0 = 0x0008;
1316 FLEXPWM1_MCTRL |= FLEXPWM_MCTRL_CLDOK(8);
1317 FLEXPWM1_SM3CTRL2 = FLEXPWM_SMCTRL2_INDEP;
1318 FLEXPWM1_SM3CTRL = FLEXPWM_SMCTRL_HALF | FLEXPWM_SMCTRL_PRSC(prescale);
1319 FLEXPWM1_SM3INIT = -period;
1320 FLEXPWM1_SM3VAL0 = 0;
1321 FLEXPWM1_SM3VAL1 = period;
1322 FLEXPWM1_SM3VAL2 = -(period / 3);
1323 FLEXPWM1_SM3VAL3 = period / 3;
1324 FLEXPWM1_SM3VAL4 = 0;
1325 FLEXPWM1_SM3VAL5 = 0;
1326 FLEXPWM1_MCTRL |= FLEXPWM_MCTRL_LDOK(8) | FLEXPWM_MCTRL_RUN(8);
1328 # endif // defined(SEND_PWM_BY_TIMER)
1330 #elif defined(ESP8266)
1331 # if defined(SEND_PWM_BY_TIMER)
1332 #error "No support for hardware PWM generation for ESP8266"
1333 # endif // defined(SEND_PWM_BY_TIMER)
1339 #define ISR() IRAM_ATTR void IRTimerInterruptHandler()
1340 IRAM_ATTR
void IRTimerInterruptHandler();
1343 timer1_attachInterrupt(&IRTimerInterruptHandler);
1346 timer1_detachInterrupt();
1356 timer1_enable(TIM_DIV16, TIM_EDGE, TIM_LOOP);
1365 #elif defined(ESP32)
1368 hw_timer_t *s50usTimer;
1371 # if !defined(SEND_AND_RECEIVE_TIMER_LEDC_CHANNEL)
1372 #define SEND_AND_RECEIVE_TIMER_LEDC_CHANNEL 0 // The channel used for PWM 0 to 7 are high speed PWM channels
1376 timerAlarmEnable (s50usTimer);
1378 #if ESP_ARDUINO_VERSION < ESP_ARDUINO_VERSION_VAL(2, 0, 2)
1380 if (s50usTimer != NULL) {
1381 timerEnd(s50usTimer);
1382 timerDetachInterrupt(s50usTimer);
1387 if (s50usTimer != NULL) {
1388 timerAlarmDisable (s50usTimer);
1396 #define ISR() IRAM_ATTR void IRTimerInterruptHandler()
1397 IRAM_ATTR
void IRTimerInterruptHandler();
1403 s50usTimer = timerBegin(1, 80,
true);
1404 timerAttachInterrupt(s50usTimer, &IRTimerInterruptHandler,
false);
1409 # if defined(SEND_PWM_BY_TIMER)
1414 ledcWrite(SEND_AND_RECEIVE_TIMER_LEDC_CHANNEL, 0);
1422 ledcSetup(SEND_AND_RECEIVE_TIMER_LEDC_CHANNEL, aFrequencyKHz * 1000, 8);
1423 # if defined(IR_SEND_PIN)
1424 ledcAttachPin(
IR_SEND_PIN, SEND_AND_RECEIVE_TIMER_LEDC_CHANNEL);
1429 # endif // defined(SEND_PWM_BY_TIMER)
1434 #elif defined(ARDUINO_ARCH_SAMD)
1435 # if defined(SEND_PWM_BY_TIMER)
1436 #error PWM generation by hardware is not yet implemented for SAMD
1439 # if !defined(IR_SAMD_TIMER)
1440 # if defined(__SAMD51__)
1441 #define IR_SAMD_TIMER TC5
1442 #define IR_SAMD_TIMER_IRQ TC5_IRQn
1445 #define IR_SAMD_TIMER TC3
1446 #define IR_SAMD_TIMER_ID GCLK_CLKCTRL_ID_TCC2_TC3
1447 #define IR_SAMD_TIMER_IRQ TC3_IRQn
1452 NVIC_EnableIRQ (IR_SAMD_TIMER_IRQ);
1455 NVIC_DisableIRQ (IR_SAMD_TIMER_IRQ);
1463 #define ISR(f) void IRTimerInterruptHandler(void)
1465 void IRTimerInterruptHandler();
1476 TcCount16 *TC = (TcCount16*) IR_SAMD_TIMER;
1478 # if defined(__SAMD51__)
1480 GCLK->PCHCTRL[TC5_GCLK_ID].reg = GCLK_PCHCTRL_GEN_GCLK0_Val | (1 << GCLK_PCHCTRL_CHEN_Pos);
1483 TC->CTRLA.reg &= ~TC_CTRLA_ENABLE;
1484 while (TC->SYNCBUSY.bit.ENABLE)
1487 TC->CTRLA.reg = TC_CTRLA_SWRST;
1489 while (TC->SYNCBUSY.bit.SWRST)
1498 TC->CTRLA.reg |= TC_CTRLA_MODE_COUNT16 | TC_WAVE_WAVEGEN_MFRQ | TC_CTRLA_PRESCALER_DIV16 | TC_CTRLA_ENABLE;
1502 REG_GCLK_CLKCTRL = (uint16_t)(GCLK_CLKCTRL_CLKEN | GCLK_CLKCTRL_GEN_GCLK0 | IR_SAMD_TIMER_ID);
1503 while (GCLK->STATUS.bit.SYNCBUSY == 1)
1507 TC->CTRLA.reg &= ~TC_CTRLA_ENABLE;
1509 while (TC->STATUS.bit.SYNCBUSY == 1)
1512 TC->CTRLA.reg = TC_CTRLA_SWRST;
1514 while (TC->CTRLA.bit.SWRST)
1523 TC->CTRLA.reg |= TC_CTRLA_MODE_COUNT16 | TC_CTRLA_WAVEGEN_MFRQ | TC_CTRLA_PRESCALER_DIV16 | TC_CTRLA_ENABLE;
1527 NVIC_DisableIRQ (IR_SAMD_TIMER_IRQ);
1528 NVIC_ClearPendingIRQ(IR_SAMD_TIMER_IRQ);
1529 NVIC_SetPriority(IR_SAMD_TIMER_IRQ, 0);
1530 NVIC_EnableIRQ(IR_SAMD_TIMER_IRQ);
1533 TC->INTENSET.bit.MC0 = 1;
1536 # if !defined(DISABLE_CODE_FOR_RECEIVER)
1537 # if defined(__SAMD51__)
1538 void TC5_Handler(
void) {
1539 TcCount16 *TC = (TcCount16*) IR_SAMD_TIMER;
1541 if (TC->INTFLAG.bit.MC0 == 1) {
1543 TC->INTFLAG.bit.MC0 = 1;
1544 IRTimerInterruptHandler();
1548 void TC3_Handler(
void) {
1549 TcCount16 *TC = (TcCount16*) IR_SAMD_TIMER;
1551 if (TC->INTFLAG.bit.MC0 == 1) {
1553 TC->INTFLAG.bit.MC0 = 1;
1554 IRTimerInterruptHandler();
1557 # endif // defined(__SAMD51__)
1558 # endif // !defined(DISABLE_CODE_FOR_RECEIVER)
1563 #elif defined(ARDUINO_ARCH_MBED) // Arduino Nano 33 BLE + Sparkfun Apollo3 + Nano RP2040 Connect
1565 mbed::Ticker s50usTimer;
1571 #define ISR() void IRTimerInterruptHandler(void)
1572 void IRTimerInterruptHandler();
1575 s50usTimer.attach(IRTimerInterruptHandler, std::chrono::microseconds(
MICROS_PER_TICK));
1578 s50usTimer.detach();
1582 s50usTimer.attach(IRTimerInterruptHandler, std::chrono::microseconds(
MICROS_PER_TICK));
1585 # if defined(SEND_PWM_BY_TIMER)
1586 #include "pins_arduino.h"
1588 # if defined(IR_SEND_PIN)
1589 mbed::PwmOut sPwmOutForSendPWM(digitalPinToPinName(
IR_SEND_PIN));
1591 mbed::PwmOut sPwmOutForSendPWM(digitalPinToPinName(
IrSender.
sendPin));
1593 uint8_t sIROutPuseWidth;
1596 sPwmOutForSendPWM.pulsewidth_us(sIROutPuseWidth);
1602 sPwmOutForSendPWM.pulsewidth_us(0);
1610 sPwmOutForSendPWM.period_us(1000 / aFrequencyKHz);
1613 # endif // defined(SEND_PWM_BY_TIMER)
1621 #elif defined(ARDUINO_ARCH_RP2040) // Raspberry Pi Pico, Adafruit Feather RP2040, etc.
1622 #include "pico/time.h"
1624 repeating_timer_t s50usTimer;
1630 #define ISR() void IRTimerInterruptHandler(void)
1631 void IRTimerInterruptHandler();
1633 bool IRTimerInterruptHandlerHelper(repeating_timer_t*) {
1634 IRTimerInterruptHandler();
1639 add_repeating_timer_us(-(
MICROS_PER_TICK), IRTimerInterruptHandlerHelper, NULL, &s50usTimer);
1642 cancel_repeating_timer(&s50usTimer);
1649 # if defined(SEND_PWM_BY_TIMER)
1650 #include "hardware/pwm.h"
1652 uint sSliceNumberForSendPWM;
1653 uint sChannelNumberForSendPWM;
1654 uint sIROutPuseWidth;
1660 pwm_set_counter(sSliceNumberForSendPWM, 0);
1661 pwm_set_chan_level(sSliceNumberForSendPWM, sChannelNumberForSendPWM, sIROutPuseWidth);
1664 pwm_set_chan_level(sSliceNumberForSendPWM, sChannelNumberForSendPWM, 0);
1672 # if defined(IR_SEND_PIN)
1675 sSliceNumberForSendPWM = pwm_gpio_to_slice_num(
IR_SEND_PIN);
1676 sChannelNumberForSendPWM = pwm_gpio_to_channel(
IR_SEND_PIN);
1683 uint16_t tPWMWrapValue = (clock_get_hz(clk_sys)) / (aFrequencyKHz * 1000);
1685 pwm_config tPWMConfig = pwm_get_default_config();
1686 pwm_config_set_wrap(&tPWMConfig, tPWMWrapValue - 1);
1687 pwm_init(sSliceNumberForSendPWM, &tPWMConfig,
false);
1689 pwm_set_chan_level(sSliceNumberForSendPWM, sChannelNumberForSendPWM, 0);
1690 pwm_set_enabled(sSliceNumberForSendPWM,
true);
1692 # endif // defined(SEND_PWM_BY_TIMER)
1697 #elif defined(NRF5) || defined(ARDUINO_ARCH_NRF52840)
1698 # if defined(SEND_PWM_BY_TIMER)
1699 #error PWM generation by hardware not implemented for NRF5
1703 NVIC_EnableIRQ (TIMER2_IRQn);
1706 NVIC_DisableIRQ (TIMER2_IRQn);
1711 #define ISR(f) void IRTimerInterruptHandler(void)
1712 void IRTimerInterruptHandler();
1715 NRF_TIMER2->MODE = TIMER_MODE_MODE_Timer;
1716 NRF_TIMER2->TASKS_CLEAR = 1;
1717 NRF_TIMER2->PRESCALER = 4;
1718 NRF_TIMER2->BITMODE = TIMER_BITMODE_BITMODE_16Bit;
1720 NRF_TIMER2->CC[1] = 0;
1723 NRF_TIMER2->INTENSET = (TIMER_INTENSET_COMPARE0_Enabled << TIMER_INTENSET_COMPARE0_Pos);
1724 NRF_TIMER2->TASKS_START = 1;
1729 #if !defined(DISABLE_CODE_FOR_RECEIVER)
1734 void TIMER2_IRQHandler(
void) {
1736 if ((NRF_TIMER2->EVENTS_COMPARE[0] != 0) && ((NRF_TIMER2->INTENSET & TIMER_INTENSET_COMPARE0_Msk) != 0)) {
1737 NRF_TIMER2->EVENTS_COMPARE[0] = 0;
1738 IRTimerInterruptHandler();
1739 NRF_TIMER2->CC[0] += 50;
1752 #elif defined(__STM32F1__) || defined(ARDUINO_ARCH_STM32F1)
1753 #include <HardwareTimer.h>
1754 # if defined(SEND_PWM_BY_TIMER)
1755 #error PWM generation by hardware not implemented for STM32
1762 HardwareTimer s50usTimer(3);
1765 s50usTimer.resume();
1775 #define ISR() void IRTimerInterruptHandler(void)
1776 void IRTimerInterruptHandler();
1779 s50usTimer.setMode(TIMER_CH1, TIMER_OUTPUT_COMPARE);
1780 s50usTimer.setPrescaleFactor(1);
1782 s50usTimer.attachInterrupt(TIMER_CH1, IRTimerInterruptHandler);
1783 s50usTimer.refresh();
1792 #elif defined(STM32F1xx) || defined(ARDUINO_ARCH_STM32)
1793 #include <HardwareTimer.h>
1794 # if defined(SEND_PWM_BY_TIMER)
1795 #error PWM generation by hardware not implemented for STM32
1803 HardwareTimer s50usTimer(TIM4);
1805 HardwareTimer s50usTimer(TIM2);
1809 s50usTimer.resume();
1819 #define ISR() void IRTimerInterruptHandler(void)
1820 void IRTimerInterruptHandler();
1824 s50usTimer.attachInterrupt(IRTimerInterruptHandler);
1825 s50usTimer.resume();
1832 #elif defined(PARTICLE)
1833 # ifndef __INTERVALTIMER_H__
1834 #include "SparkIntervalTimer.h"
1837 extern IntervalTimer timer;
1838 extern int ir_out_kHz;
1851 #define ISR() void IRTimerInterruptHandler(void)
1856 # if defined(SEND_PWM_BY_TIMER)
1857 # if defined(IR_SEND_PIN)
1880 # if defined(IR_SEND_PIN)
1885 ir_out_kHz = aFrequencyKHz;
1887 # endif // defined(SEND_PWM_BY_TIMER)
1893 #error Internal code configuration error, no timer functions implemented for this CPU / board
1904 #define ISR() void notImplemented(void)
1909 # if defined(SEND_PWM_BY_TIMER)
1917 # if defined(IR_SEND_PIN)
1922 (void) aFrequencyKHz;
1924 # endif // defined(SEND_PWM_BY_TIMER)
1926 #endif // defined(DOXYGEN / CPU_TYPES)
1930 #endif // _IR_TIMER_HPP