56 #if defined(SEND_PWM_BY_TIMER) && ( (defined(ESP32) || defined(ARDUINO_ARCH_RP2040) || defined(PARTICLE)) || defined(ARDUINO_ARCH_MBED) )
57 #define SEND_PWM_DOES_NOT_USE_RECEIVE_TIMER // Receive timer and send generation timer are independent here.
60 #if defined(IR_SEND_PIN) && defined(SEND_PWM_BY_TIMER) && !defined(SEND_PWM_DOES_NOT_USE_RECEIVE_TIMER) // For ESP32 etc. IR_SEND_PIN definition is useful
61 #undef IR_SEND_PIN // To avoid "warning: "IR_SEND_PIN" redefined". The user warning is done at IRremote.hpp line 202.
141 #elif defined(__AVR__)
150 #if defined(__AVR_ATmega328P__) || defined(__AVR_ATmega328PB__) || defined(__AVR_ATmega168__) \
151 || defined(__AVR_ATmega88P__) || defined(__AVR_ATmega88PB__)
152 # if !defined(IR_USE_AVR_TIMER1) && !defined(IR_USE_AVR_TIMER2)
154 #define IR_USE_AVR_TIMER2 // send pin = pin 3
158 #elif defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__)
159 # 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)
161 #define IR_USE_AVR_TIMER2 // send pin = pin 9
168 #elif defined(__AVR_ATmega32U4__) && ! defined(TEENSYDUINO) && ! defined(ARDUINO_AVR_PROMICRO)
169 # if !defined(IR_USE_AVR_TIMER1) && !defined(IR_USE_AVR_TIMER3) && !defined(IR_USE_AVR_TIMER4_HS)
171 #define IR_USE_AVR_TIMER3 // send pin = pin 5
176 #elif defined(__AVR_ATmega808__) || defined(__AVR_ATmega809__) || defined(__AVR_ATmega3208__) || defined(__AVR_ATmega3209__) \
177 || defined(__AVR_ATmega1608__) || defined(__AVR_ATmega1609__) || defined(__AVR_ATmega4808__) || defined(__AVR_ATmega4809__) || defined(__AVR_ATtiny1604__)
178 # if !defined(IR_USE_AVR_TIMER_B)
179 #define IR_USE_AVR_TIMER_B // send pin = pin 6 on ATmega4809 1 on ATmega4809
182 #elif defined(__AVR_ATtiny816__) || defined(__AVR_ATtiny1614__) || defined(__AVR_ATtiny1616__) || defined(__AVR_ATtiny3216__) || defined(__AVR_ATtiny3217__) // e.g. TinyCore boards
183 # if !defined(IR_USE_AVR_TIMER_A) && !defined(IR_USE_AVR_TIMER_D)
184 #define IR_USE_AVR_TIMER_A // use this if you use megaTinyCore, Tone is on TCB and millis() on TCD
189 #elif defined(__AVR_ATmega8U2__) || defined(__AVR_ATmega16U2__) || defined(__AVR_ATmega32U2__) || defined(__AVR_ATmega8__)
190 # if !defined(IR_USE_AVR_TIMER1)
191 #define IR_USE_AVR_TIMER1 // send pin = pin C6
195 #elif defined(__AVR_ATtiny84__) || defined(__AVR_ATtiny88__)
196 # if !defined(IR_USE_AVR_TIMER1)
197 #define IR_USE_AVR_TIMER1 // send pin = pin 6
200 #elif defined(__AVR_ATtiny87__) || defined(__AVR_ATtiny167__)
201 # if !defined(IR_USE_AVR_TIMER1)
202 #define IR_USE_AVR_TIMER1 // send pin = pin PB1 / 8
204 #define USE_TIMER_CHANNEL_B
207 #elif defined(__AVR_ATtiny25__) || defined(__AVR_ATtiny45__) || defined(__AVR_ATtiny85__)
208 # if !defined(IR_USE_AVR_TIMER_TINY0) && !defined(IR_USE_AVR_TIMER_TINY1)
209 # if defined(ARDUINO_AVR_DIGISPARK) // tested with 16 and 8 MHz
210 #define IR_USE_AVR_TIMER_TINY0 // send pin = pin 1
214 #define IR_USE_AVR_TIMER_TINY1 // send pin = pin 4
221 #elif defined(ARDUINO_AVR_PROMICRO)
222 # if !defined(IR_USE_AVR_TIMER1) && !defined(IR_USE_AVR_TIMER3) && !defined(IR_USE_AVR_TIMER4_HS)
224 #define IR_USE_AVR_TIMER3 // send pin = pin 5
232 #elif defined(__AVR_AT90USB162__)
233 # if !defined(IR_USE_AVR_TIMER1)
234 #define IR_USE_AVR_TIMER1 // send pin = pin 17
238 #elif defined(__AVR_AT90USB646__) || defined(__AVR_AT90USB1286__)
239 # if !defined(IR_USE_AVR_TIMER1) && !defined(IR_USE_AVR_TIMER2) && !defined(IR_USE_AVR_TIMER3)
241 #define IR_USE_AVR_TIMER2 // send pin = pin 1
246 #elif defined(__AVR_ATmega32U4__) && defined(TEENSYDUINO)
247 # if !defined(IR_USE_AVR_TIMER1) && !defined(IR_USE_AVR_TIMER3) && !defined(IR_USE_AVR_TIMER4_HS)
250 #define IR_USE_AVR_TIMER4_HS // send pin = pin 10 (Teensy 2.0 - physical pin: C7)
257 #elif defined(__AVR_ATmega64__) || defined(__AVR_ATmega128__) || defined(__AVR_ATmega1281__) || defined(__AVR_ATmega2560__)
258 # if !defined(IR_USE_AVR_TIMER1)
259 #define IR_USE_AVR_TIMER1 // send pin = pin 13
265 #elif defined(__AVR_ATmega8515__) || defined(__AVR_ATmega162__)
266 # if !defined(IR_USE_AVR_TIMER1) && !defined(IR_USE_AVR_TIMER3)
267 #define IR_USE_AVR_TIMER1 // send pin = pin 13
275 #elif defined(__AVR_ATmega1284__) || defined(__AVR_ATmega1284P__)
276 # if !defined(IR_USE_AVR_TIMER1) && !defined(IR_USE_AVR_TIMER2) && !defined(IR_USE_AVR_TIMER3)
278 #define IR_USE_AVR_TIMER2 // send pin = pin 14
283 #elif defined(__AVR_ATmega644__) || defined(__AVR_ATmega644P__) \
284 || defined(__AVR_ATmega324P__) || defined(__AVR_ATmega324A__) \
285 || defined(__AVR_ATmega324PA__) || defined(__AVR_ATmega164A__) \
286 || defined(__AVR_ATmega164P__)
287 # if !defined(IR_USE_AVR_TIMER1) && !defined(IR_USE_AVR_TIMER2)
289 #define IR_USE_AVR_TIMER2 // send pin = pin 14
293 #elif defined(__AVR_ATmega8535__) || defined(__AVR_ATmega16__) || defined(__AVR_ATmega32__)
294 # if !defined(IR_USE_AVR_TIMER1)
295 #define IR_USE_AVR_TIMER1 // send pin = pin 13
305 #if defined(IR_USE_AVR_TIMER1)
308 #define TIMSK TIMSK1 // use the value of TIMSK1 for the statements below
312 TIMSK |= _BV(OCIE1A);
315 TIMSK &= ~_BV(OCIE1A);
318 # if defined(USE_TIMER_CHANNEL_B)
319 # if defined(TIMER1_COMPB_vect)
320 #define TIMER_INTR_NAME TIMER1_COMPB_vect
321 # elif defined(TIM1_COMPB_vect)
322 #define TIMER_INTR_NAME TIM1_COMPB_vect
325 # if defined(TIMER1_COMPA_vect)
326 #define TIMER_INTR_NAME TIMER1_COMPA_vect
327 # elif defined(TIM1_COMPA_vect)
328 #define TIMER_INTR_NAME TIM1_COMPA_vect
334 TCCR1B = _BV(WGM12) | _BV(CS10);
339 # if defined(SEND_PWM_BY_TIMER)
340 # if defined(CORE_OC1A_PIN)
341 #define IR_SEND_PIN CORE_OC1A_PIN // Teensy
343 # elif defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__)
344 #define IR_SEND_PIN 11 // Arduino Mega
347 # elif defined(__AVR_ATmega1284__) || defined(__AVR_ATmega1284P__) \
348 || defined(__AVR_ATmega644__) || defined(__AVR_ATmega644P__) \
349 || defined(__AVR_ATmega324P__) || defined(__AVR_ATmega324A__) \
350 || defined(__AVR_ATmega324PA__) || defined(__AVR_ATmega164A__) \
351 || defined(__AVR_ATmega164P__) || defined(__AVR_ATmega32__) \
352 || defined(__AVR_ATmega16__) || defined(__AVR_ATmega8535__) \
353 || defined(__AVR_ATmega64__) || defined(__AVR_ATmega128__) \
354 || defined(__AVR_ATmega1281__) || defined(__AVR_ATmega2561__) \
355 || defined(__AVR_ATmega8515__) || defined(__AVR_ATmega162__)
356 #define IR_SEND_PIN 13
358 # elif defined(__AVR_ATtiny84__)
359 #define IR_SEND_PIN 6
361 # elif defined(__AVR_ATtiny88__)
362 #define IR_SEND_PIN 8
364 # elif defined(__AVR_ATtiny87__) || defined(__AVR_ATtiny167__)
368 # if defined(USE_TIMER_CHANNEL_B)
369 #define IR_SEND_PIN PIN_PB1 // OC1BU / PB1 / Pin9 at ATTinyCore
374 #define IR_SEND_PIN PIN_PB0 // OC1AU / PB1 / Pin8 at ATTinyCore
381 #define IR_SEND_PIN 9 // OC1A Arduino Duemilanove, Diecimila, LilyPad, Sparkfun Pro Micro, Leonardo, MH-ET Tiny88 etc.
382 # endif // defined(CORE_OC1A_PIN)
384 # if defined(__AVR_ATtiny87__) || defined(__AVR_ATtiny167__)
386 # if defined(USE_TIMER_CHANNEL_B)
389 TCCR1A |= _BV(COM1B1);
390 TCCR1D |= _BV(OC1BU);
398 TCCR1A |= _BV(COM1A1);
399 TCCR1D |= _BV(OC1AU);
410 # if defined(USE_TIMER_CHANNEL_B)
413 TCCR1A |= _BV(COM1B1);
416 TCCR1A &= ~(_BV(COM1B1));
421 TCCR1A |= _BV(COM1A1);
424 TCCR1A &= ~(_BV(COM1A1));
436 # if (((F_CPU / 2000) / 38) < 256)
437 const uint16_t tPWMWrapValue = (F_CPU / 2000) / (aFrequencyKHz);
439 TCCR1B = _BV(WGM13) | _BV(CS10);
440 ICR1 = tPWMWrapValue - 1;
441 # if defined(USE_TIMER_CHANNEL_B)
448 const uint16_t tPWMWrapValue = ((F_CPU / 8) / 2000) / (aFrequencyKHz);
450 TCCR1B = _BV(WGM13) | _BV(CS11);
451 ICR1 = tPWMWrapValue - 1;
452 # if defined(USE_TIMER_CHANNEL_B)
460 # endif // defined(SEND_PWM_BY_TIMER)
465 #elif defined(IR_USE_AVR_TIMER2)
468 TIMSK2 = _BV(OCIE2B);
473 #define TIMER_INTR_NAME TIMER2_COMPB_vect // We use TIMER2_COMPB_vect to be compatible with tone() library
475 #define TIMER_COUNT_TOP (F_CPU * MICROS_PER_TICK / MICROS_IN_ONE_SECOND)
478 # if (TIMER_COUNT_TOP < 256)
481 OCR2A = TIMER_COUNT_TOP;
482 OCR2B = TIMER_COUNT_TOP;
487 OCR2A = TIMER_COUNT_TOP / 8;
488 OCR2B = TIMER_COUNT_TOP / 8;
493 # if defined(SEND_PWM_BY_TIMER)
494 # if defined(CORE_OC2B_PIN)
495 #define IR_SEND_PIN CORE_OC2B_PIN // Teensy
497 # elif defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__)
498 #define IR_SEND_PIN 9 // Arduino Mega
500 # elif defined(__AVR_ATmega1284__) || defined(__AVR_ATmega1284P__) \
501 || defined(__AVR_ATmega644__) || defined(__AVR_ATmega644P__) \
502 || defined(__AVR_ATmega324P__) || defined(__AVR_ATmega324A__) \
503 || defined(__AVR_ATmega324PA__) || defined(__AVR_ATmega164A__) \
504 || defined(__AVR_ATmega164P__)
505 #define IR_SEND_PIN 14 // MightyCore, MegaCore
508 #define IR_SEND_PIN 3 // Arduino Duemilanove, Diecimila, LilyPad, etc
509 # endif // defined(CORE_OC2B_PIN)
513 TCCR2A |= _BV(COM2B1);
516 TCCR2A &= ~(_BV(COM2B1));
526 # if (((F_CPU / 2000) / 38) < 256)
532 const uint16_t tPWMWrapValue = (F_CPU / 2000) / (aFrequencyKHz);
534 TCCR2B = _BV(WGM22) | _BV(CS20);
535 OCR2A = tPWMWrapValue - 1;
539 const uint16_t tPWMWrapValue = ((F_CPU / 8) / 2000) / (aFrequencyKHz);
541 TCCR2B = _BV(WGM22) | _BV(CS21);
542 OCR2A = tPWMWrapValue - 1;
547 # endif // defined(SEND_PWM_BY_TIMER)
552 #elif defined(IR_USE_AVR_TIMER3)
555 TIMSK3 = _BV(OCIE3B);
560 #define TIMER_INTR_NAME TIMER3_COMPB_vect
564 TCCR3B = _BV(WGM32) | _BV(CS30);
570 # if defined(SEND_PWM_BY_TIMER)
571 # if defined(CORE_OC3A_PIN)
572 #define IR_SEND_PIN CORE_OC3A_PIN // Teensy
574 # elif defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__) \
575 || defined(__AVR_ATmega32U4__) || defined(ARDUINO_AVR_PROMICRO)
576 #define IR_SEND_PIN 5 // Arduino Mega, Arduino Leonardo, Sparkfun Pro Micro
578 # elif defined(__AVR_ATmega1284__) || defined(__AVR_ATmega1284P__)
579 #define IR_SEND_PIN 6 // MightyCore, MegaCore
582 #error Please add OC3A pin number here
587 TCCR3A |= _BV(COM3A1);
590 TCCR3A &= ~(_BV(COM3A1));
599 #error "Creating timer PWM with timer 3 is not supported for F_CPU > 16 MHz"
603 const uint16_t tPWMWrapValue = (F_CPU / 2000) / (aFrequencyKHz);
605 TCCR3B = _BV(WGM33) | _BV(CS30);
606 ICR3 = tPWMWrapValue - 1;
610 # endif // defined(SEND_PWM_BY_TIMER)
615 #elif defined(IR_USE_AVR_TIMER4)
617 TIMSK4 = _BV(OCIE4A);
622 #define TIMER_INTR_NAME TIMER4_COMPA_vect
626 TCCR4B = _BV(WGM42) | _BV(CS40);
631 # if defined(SEND_PWM_BY_TIMER)
632 # if defined(CORE_OC4A_PIN)
633 #define IR_SEND_PIN CORE_OC4A_PIN
634 # elif defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__)
635 #define IR_SEND_PIN 6 // Arduino Mega
637 #error Please add OC4A pin number here
642 TCCR4A |= _BV(COM4A1);
645 TCCR4A &= ~(_BV(COM4A1));
650 #error "Creating timer PWM with timer 4 is not supported for F_CPU > 16 MHz"
653 const uint16_t tPWMWrapValue = (F_CPU / 2000) / (aFrequencyKHz);
655 TCCR4B = _BV(WGM43) | _BV(CS40);
656 ICR4 = tPWMWrapValue - 1;
660 # endif // defined(SEND_PWM_BY_TIMER)
665 #elif defined(IR_USE_AVR_TIMER4_HS)
673 #define TIMER_INTR_NAME TIMER4_OVF_vect
687 # if defined(SEND_PWM_BY_TIMER)
688 # if defined(CORE_OC4A_PIN)
689 #define IR_SEND_PIN CORE_OC4A_PIN // Teensy 2.0
690 # elif defined(ARDUINO_AVR_PROMICRO)
691 #define IR_SEND_PIN 5 // Sparkfun Pro Micro
692 # elif defined(__AVR_ATmega32U4__)
693 #define IR_SEND_PIN 13 // Leonardo
695 #error Please add OC4A pin number here
698 # if defined(ARDUINO_AVR_PROMICRO) // Sparkfun Pro Micro
701 TCCR4A |= _BV(COM4A0);
704 TCCR4A &= ~(_BV(COM4A0));
710 TCCR4A |= _BV(COM4A1);
714 TCCR4A &= ~(_BV(COM4A1));
724 #error "Creating timer PWM with timer 4 HS is not supported for F_CPU > 16 MHz"
728 const uint16_t tPWMWrapValue = ((F_CPU / 2000) / (aFrequencyKHz)) - 1;
729 TCCR4A = (1 << PWM4A);
732 TCCR4D = (1 << WGM40);
734 TC4H = tPWMWrapValue >> 8;
735 OCR4C = tPWMWrapValue;
740 # endif // defined(SEND_PWM_BY_TIMER)
745 #elif defined(IR_USE_AVR_TIMER5)
748 TIMSK5 = _BV(OCIE5A);
753 #define TIMER_INTR_NAME TIMER5_COMPA_vect
757 TCCR5B = _BV(WGM52) | _BV(CS50);
762 # if defined(SEND_PWM_BY_TIMER)
763 # if defined(CORE_OC5A_PIN)
764 #define IR_SEND_PIN CORE_OC5A_PIN
765 # elif defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__)
766 #define IR_SEND_PIN 46 // Arduino Mega
768 #error Please add OC5A pin number here
773 TCCR5A |= _BV(COM5A1);
776 TCCR5A &= ~(_BV(COM5A1));
785 #error "Creating timer PWM with timer 5 is not supported for F_CPU > 16 MHz"
789 const uint16_t tPWMWrapValue = (F_CPU / 2000) / (aFrequencyKHz);
791 TCCR5B = _BV(WGM53) | _BV(CS50);
792 ICR5 = tPWMWrapValue - 1;
796 # endif // defined(SEND_PWM_BY_TIMER)
801 #elif defined(IR_USE_AVR_TIMER_TINY0)
804 TIMSK |= _BV(OCIE0A);
807 TIMSK &= ~(_BV(OCIE0A));
809 #define TIMER_INTR_NAME TIMER0_COMPA_vect
811 #define TIMER_COUNT_TOP (F_CPU * MICROS_PER_TICK / MICROS_IN_ONE_SECOND)
814 # if (TIMER_COUNT_TOP < 256)
817 OCR0A = TIMER_COUNT_TOP;
822 OCR0A = TIMER_COUNT_TOP / 8;
827 # if defined(SEND_PWM_BY_TIMER)
828 #define IR_SEND_PIN 1
832 TCCR0A |= _BV(COM0B1);
835 TCCR0A &= ~(_BV(COM0B1));
844 #error "Creating timer PWM with timer TINY0 is not supported for F_CPU > 16 MHz"
848 const uint16_t tPWMWrapValue = (F_CPU / 2000) / (aFrequencyKHz);
850 TCCR0B = _BV(WGM02) | _BV(CS00);
851 OCR0A = tPWMWrapValue - 1;
855 # endif // defined(SEND_PWM_BY_TIMER)
860 #elif defined(IR_USE_AVR_TIMER_TINY1)
863 TIMSK |= _BV(OCIE1B);
866 TIMSK &= ~(_BV(OCIE1B));
868 #define TIMER_INTR_NAME TIMER1_COMPB_vect
870 #define TIMER_COUNT_TOP (F_CPU * MICROS_PER_TICK / MICROS_IN_ONE_SECOND)
873 # if (TIMER_COUNT_TOP < 256)
874 TCCR1 = _BV(CTC1) | _BV(CS10);
876 OCR1C = TIMER_COUNT_TOP;
879 TCCR1 = _BV(CTC1) | _BV(CS12);
881 OCR1C = TIMER_COUNT_TOP / 8;
886 # if defined(SEND_PWM_BY_TIMER)
887 #define IR_SEND_PIN 4
891 GTCCR |= _BV(PWM1B) | _BV(COM1B0);
894 GTCCR &= ~(_BV(PWM1B) | _BV(COM1B0));
904 # if (((F_CPU / 1000) / 38) < 256)
905 const uint16_t tPWMWrapValue = (F_CPU / 1000) / (aFrequencyKHz);
906 TCCR1 = _BV(CTC1) | _BV(CS10);
907 OCR1C = tPWMWrapValue - 1;
910 GTCCR = _BV(PWM1B) | _BV(COM1B0);
912 const uint16_t tPWMWrapValue = ((F_CPU / 2) / 1000) / (aFrequencyKHz);
913 TCCR1 = _BV(CTC1) | _BV(CS11);
914 OCR1C = tPWMWrapValue - 1;
917 GTCCR = _BV(PWM1B) | _BV(COM1B0);
920 # endif // defined(SEND_PWM_BY_TIMER)
925 #elif defined(IR_USE_AVR_TIMER_A)
926 #define TIMER_REQUIRES_RESET_INTR_PENDING
928 TCA0.SINGLE.INTFLAGS = TCA_SINGLE_OVF_bm;
931 TCA0.SINGLE.INTCTRL = TCA_SINGLE_OVF_bm;
934 TCA0.SINGLE.INTCTRL &= ~(TCA_SINGLE_OVF_bm);
936 #define TIMER_INTR_NAME TCA0_OVF_vect
943 TCA0.SINGLE.CTRLD = 0;
944 TCA0.SINGLE.CTRLB = TCA_SINGLE_WGMODE_NORMAL_gc;
946 TCA0.SINGLE.CTRLA = TCA_SINGLE_CLKSEL_DIV1_gc | TCA_SINGLE_ENABLE_bm;
949 # if defined(SEND_PWM_BY_TIMER)
950 #error "No support for hardware PWM generation for ATtiny3216/17 etc."
951 # endif // defined(SEND_PWM_BY_TIMER)
956 #elif defined(IR_USE_AVR_TIMER_B)
959 #define TIMER_REQUIRES_RESET_INTR_PENDING
961 TCB0.INTFLAGS = TCB_CAPT_bm;
964 TCB0.INTCTRL = TCB_CAPT_bm;
967 TCB0.INTCTRL &= ~(TCB_CAPT_bm);
969 #define TIMER_INTR_NAME TCB0_INT_vect
972 TCB0.CTRLB = (TCB_CNTMODE_INT_gc);
974 TCB0.INTFLAGS = TCB_CAPT_bm;
975 TCB0.CTRLA = (TCB_CLKSEL_CLKDIV1_gc) | (TCB_ENABLE_bm);
978 # if defined(SEND_PWM_BY_TIMER)
979 # if defined(__AVR_ATmega4808__) || defined(__AVR_ATmega4809__)
980 #define IR_SEND_PIN 6 // PF4 on ATmega4809 / Nano Every (see pins_arduino.h digital_pin_to_timer)
982 #error SEND_PWM_BY_TIMER not yet supported for this CPU
987 TCB0.CTRLB |= TCB_CCMPEN_bm;
990 TCB0.CTRLB &= ~(TCB_CCMPEN_bm);
1000 #error "Creating timer PWM with timer TCB0 is not possible for F_CPU > 16 MHz"
1004 const uint16_t tPWMWrapValue = (F_CPU / 2000) / (aFrequencyKHz);
1005 TCB0.CTRLB = TCB_CNTMODE_PWM8_gc;
1006 TCB0.CCMPL = tPWMWrapValue - 1;
1008 TCB0.CTRLA = (TCB_CLKSEL_CLKDIV2_gc) | (TCB_ENABLE_bm);
1011 # endif // defined(SEND_PWM_BY_TIMER)
1016 #elif defined(IR_USE_AVR_TIMER_D)
1018 #define TIMER_REQUIRES_RESET_INTR_PENDING
1020 TCD0.INTFLAGS = TCD_OVF_bm;
1023 TCD0.INTCTRL = TCD_OVF_bm;
1028 #define TIMER_INTR_NAME TCD0_OVF_vect
1032 TCD0.CTRLB = TCD_WGMODE_ONERAMP_gc;
1036 _PROTECTED_WRITE(TCD0.FAULTCTRL, 0);
1038 TCD0.INTFLAGS = TCD_OVF_bm;
1042 TCD0.CTRLA = TCD_ENABLE_bm | TCD_CLKSEL_SYSCLK_gc | TCD_CNTPRES_DIV1_gc;
1045 # if defined(SEND_PWM_BY_TIMER)
1046 #define IR_SEND_PIN 13
1048 void timerEnableSendPWM() {
1050 _PROTECTED_WRITE(TCD0.FAULTCTRL, FUSE_CMPAEN_bm);
1052 TCD0.CTRLA = TCD_ENABLE_bm | TCD_CLKSEL_SYSCLK_gc | TCD_CNTPRES_DIV1_gc;
1056 timerEnableSendPWM();
1069 const uint16_t tPWMWrapValue = (F_CPU / 1000) / (aFrequencyKHz);
1073 TCD0.CTRLB = TCD_WGMODE_ONERAMP_gc;
1076 TCD0.CMPBCLR = tPWMWrapValue - 1;
1082 TCD0.INTFLAGS = TCD_OVF_bm;
1083 TCD0.INTCTRL = TCD_OVF_bm;
1086 # endif // defined(SEND_PWM_BY_TIMER)
1089 #error Internal code configuration error, no timer functions implemented for this AVR CPU / board
1090 #endif //defined(IR_USE_AVR_TIMER*)
1098 #elif defined(ARDUINO_ARCH_RENESAS)
1099 #include "FspTimer.h"
1100 FspTimer s50usTimer;
1108 void IRTimerInterruptHandlerHelper(timer_callback_args_t __attribute((unused)) *p_args) {
1121 uint8_t tTimerType = GPT_TIMER;
1122 int8_t tIndex = FspTimer::get_available_timer(tTimerType);
1123 if (tIndex < 0 || tTimerType != GPT_TIMER) {
1125 tIndex = FspTimer::get_available_timer(tTimerType,
true);
1132 IRTimerInterruptHandlerHelper);
1133 s50usTimer.setup_overflow_irq();
1138 # if defined(SEND_PWM_BY_TIMER)
1139 #error PWM generation by hardware not yet implemented for Arduino Uno R4
1150 # if defined(IR_SEND_PIN)
1159 #elif defined(__MK20DX128__) || defined(__MK20DX256__) || defined(__MK64FX512__) || defined(__MK66FX1M0__)
1162 #define TIMER_REQUIRES_RESET_INTR_PENDING
1164 uint8_t tmp __attribute__((unused)) = CMT_MSC;
1168 NVIC_ENABLE_IRQ(IRQ_CMT);
1169 NVIC_SET_PRIORITY(IRQ_CMT, 48);
1172 NVIC_DISABLE_IRQ(IRQ_CMT);
1175 #define TIMER_INTR_NAME cmt_isr
1179 #define ISR(f) void f(void)
1181 #define CMT_PPS_DIV ((F_BUS + 7999999) / 8000000)
1182 # if F_BUS < 8000000
1183 #error IRremote requires at least 8 MHz on Teensy 3.x
1187 SIM_SCGC4 |= SIM_SCGC4_CMT;
1188 CMT_PPS = CMT_PPS_DIV - 1;
1194 CMT_CMD4 = (F_BUS / 160000 + CMT_PPS_DIV / 2) / CMT_PPS_DIV - 31;
1199 # if defined(SEND_PWM_BY_TIMER)
1200 #define IR_SEND_PIN 5
1204 CORE_PIN5_CONFIG = PORT_PCR_MUX(2) | PORT_PCR_DSE | PORT_PCR_SRE;
1209 CORE_PIN5_CONFIG = PORT_PCR_MUX(1) | PORT_PCR_DSE | PORT_PCR_SRE;
1219 # if defined(IR_SEND_PIN)
1225 SIM_SCGC4 |= SIM_SCGC4_CMT;
1226 SIM_SOPT2 |= SIM_SOPT2_PTD7PAD;
1227 CMT_PPS = CMT_PPS_DIV - 1;
1228 CMT_CGH1 = ((F_BUS / CMT_PPS_DIV / 3000) + ((aFrequencyKHz) / 2)) / (aFrequencyKHz);
1229 CMT_CGL1 = ((F_BUS / CMT_PPS_DIV / 1500) + ((aFrequencyKHz) / 2)) / (aFrequencyKHz);
1237 # endif // defined(SEND_PWM_BY_TIMER)
1242 #elif defined(__MKL26Z64__)
1245 #define TIMER_REQUIRES_RESET_INTR_PENDING
1247 FTM1_SC |= FTM_SC_TOF;
1250 NVIC_ENABLE_IRQ(IRQ_FTM1);
1251 NVIC_SET_PRIORITY(IRQ_FTM1, 0);
1254 NVIC_DISABLE_IRQ(IRQ_FTM1);
1256 #define TIMER_INTR_NAME ftm1_isr
1260 #define ISR(f) void f(void)
1263 SIM_SCGC6 |= SIM_SCGC6_TPM1;
1266 FTM1_MOD = (F_PLL / 40000) - 1;
1268 FTM1_SC = FTM_SC_CLKS(1) | FTM_SC_PS(0) | FTM_SC_TOF | FTM_SC_TOIE;
1271 # if defined(SEND_PWM_BY_TIMER)
1272 #define IR_SEND_PIN 16
1276 CORE_PIN16_CONFIG = PORT_PCR_MUX(3) | PORT_PCR_DSE | PORT_PCR_SRE;
1279 CORE_PIN16_CONFIG = PORT_PCR_MUX(1) | PORT_PCR_SRE;
1288 # if defined(IR_SEND_PIN)
1294 SIM_SCGC6 |= SIM_SCGC6_TPM1;
1297 FTM1_MOD = ((F_PLL / 2000) / aFrequencyKHz) - 1;
1298 FTM1_C0V = ((F_PLL / 6000) / aFrequencyKHz) - 1;
1299 FTM1_SC = FTM_SC_CLKS(1) | FTM_SC_PS(0);
1301 # endif // defined(SEND_PWM_BY_TIMER)
1306 #elif defined(__IMXRT1062__)
1311 #define TIMER_REQUIRES_RESET_INTR_PENDING
1313 FLEXPWM1_SM3STS = FLEXPWM_SMSTS_RF;
1316 attachInterruptVector(IRQ_FLEXPWM1_3, pwm1_3_isr);
1317 FLEXPWM1_SM3STS = FLEXPWM_SMSTS_RF;
1318 FLEXPWM1_SM3INTEN = FLEXPWM_SMINTEN_RIE;
1319 NVIC_ENABLE_IRQ (IRQ_FLEXPWM1_3), NVIC_SET_PRIORITY(IRQ_FLEXPWM1_3, 48);
1322 NVIC_DISABLE_IRQ (IRQ_FLEXPWM1_3);
1324 #define TIMER_INTR_NAME pwm1_3_isr
1328 #define ISR(f) void (f)(void)
1331 uint32_t period = (float) F_BUS_ACTUAL * (
float) (
MICROS_PER_TICK) * 0.0000005f;
1332 uint32_t prescale = 0;
1333 while (period > 32767) {
1334 period = period >> 1;
1338 FLEXPWM1_FCTRL0 |= FLEXPWM_FCTRL0_FLVL(8);
1339 FLEXPWM1_FSTS0 = 0x0008;
1340 FLEXPWM1_MCTRL |= FLEXPWM_MCTRL_CLDOK(8);
1341 FLEXPWM1_SM3CTRL2 = FLEXPWM_SMCTRL2_INDEP;
1342 FLEXPWM1_SM3CTRL = FLEXPWM_SMCTRL_HALF | FLEXPWM_SMCTRL_PRSC(prescale);
1343 FLEXPWM1_SM3INIT = -period;
1344 FLEXPWM1_SM3VAL0 = 0;
1345 FLEXPWM1_SM3VAL1 = period;
1346 FLEXPWM1_SM3VAL2 = 0;
1347 FLEXPWM1_SM3VAL3 = 0;
1348 FLEXPWM1_SM3VAL4 = 0;
1349 FLEXPWM1_SM3VAL5 = 0;
1350 FLEXPWM1_MCTRL |= FLEXPWM_MCTRL_LDOK(8) | FLEXPWM_MCTRL_RUN(8);
1353 # if defined(SEND_PWM_BY_TIMER)
1354 #define IR_SEND_PIN 7
1356 FLEXPWM1_OUTEN |= FLEXPWM_OUTEN_PWMA_EN(8);
1357 IOMUXC_SW_MUX_CTL_PAD_GPIO_B1_00 = 6;
1361 IOMUXC_SW_MUX_CTL_PAD_GPIO_B1_00 = 5;
1362 FLEXPWM1_OUTEN &= ~FLEXPWM_OUTEN_PWMA_EN(8);
1371 # if defined(IR_SEND_PIN)
1377 uint32_t period = (float) F_BUS_ACTUAL / (
float) ((aFrequencyKHz) * 2000);
1378 uint32_t prescale = 0;
1379 while (period > 32767) {
1380 period = period >> 1;
1384 FLEXPWM1_FCTRL0 |= FLEXPWM_FCTRL0_FLVL(8);
1385 FLEXPWM1_FSTS0 = 0x0008;
1386 FLEXPWM1_MCTRL |= FLEXPWM_MCTRL_CLDOK(8);
1387 FLEXPWM1_SM3CTRL2 = FLEXPWM_SMCTRL2_INDEP;
1388 FLEXPWM1_SM3CTRL = FLEXPWM_SMCTRL_HALF | FLEXPWM_SMCTRL_PRSC(prescale);
1389 FLEXPWM1_SM3INIT = -period;
1390 FLEXPWM1_SM3VAL0 = 0;
1391 FLEXPWM1_SM3VAL1 = period;
1392 FLEXPWM1_SM3VAL2 = -(period / 3);
1393 FLEXPWM1_SM3VAL3 = period / 3;
1394 FLEXPWM1_SM3VAL4 = 0;
1395 FLEXPWM1_SM3VAL5 = 0;
1396 FLEXPWM1_MCTRL |= FLEXPWM_MCTRL_LDOK(8) | FLEXPWM_MCTRL_RUN(8);
1398 # endif // defined(SEND_PWM_BY_TIMER)
1403 #elif defined(ESP8266)
1404 # if defined(SEND_PWM_BY_TIMER)
1405 #error "No support for hardware PWM generation for ESP8266"
1406 # endif // defined(SEND_PWM_BY_TIMER)
1417 timer1_detachInterrupt();
1427 timer1_enable(TIM_DIV16, TIM_EDGE, TIM_LOOP);
1436 #elif defined(ESP32)
1437 # if ESP_ARDUINO_VERSION >= ESP_ARDUINO_VERSION_VAL(3, 0, 0)
1438 #error This library does not work with ESP32 core 3.x. Please use ESP 2.0.17 core. You are kindly invited to port and document the code to 3.x, to fix this problem!
1443 hw_timer_t *s50usTimer = NULL;
1445 # if ESP_ARDUINO_VERSION < ESP_ARDUINO_VERSION_VAL(3, 0, 0) && !defined(SEND_LEDC_CHANNEL)
1446 #define SEND_LEDC_CHANNEL 0 // The channel used for PWM 0 to 7 are high speed PWM channels
1450 timerAlarmEnable(s50usTimer);
1453 # if !defined(ESP_ARDUINO_VERSION)
1454 #define ESP_ARDUINO_VERSION 0
1456 # if !defined(ESP_ARDUINO_VERSION_VAL)
1457 #define ESP_ARDUINO_VERSION_VAL(major, minor, patch) 202
1459 # if ESP_ARDUINO_VERSION < ESP_ARDUINO_VERSION_VAL(2, 0, 2)
1461 if (s50usTimer != NULL) {
1462 timerDetachInterrupt(s50usTimer);
1463 timerEnd(s50usTimer);
1468 if (s50usTimer != NULL) {
1469 timerAlarmDisable(s50usTimer);
1479 # if !defined(DISABLE_CODE_FOR_RECEIVER) // &IRReceiveTimerInterruptHandler is referenced, but not available
1484 if(s50usTimer == NULL) {
1485 s50usTimer = timerBegin(1, 80,
true);
1493 # if !defined(IR_SEND_PIN)
1494 uint8_t sLastSendPin = 0;
1497 # if defined(SEND_PWM_BY_TIMER)
1499 # if ESP_ARDUINO_VERSION < ESP_ARDUINO_VERSION_VAL(3, 0, 0)
1506 # if ESP_ARDUINO_VERSION < ESP_ARDUINO_VERSION_VAL(3, 0, 0)
1507 ledcWrite(SEND_LEDC_CHANNEL, 0);
1518 # if ESP_ARDUINO_VERSION < ESP_ARDUINO_VERSION_VAL(3, 0, 0)
1519 ledcSetup(SEND_LEDC_CHANNEL, aFrequencyKHz * 1000, 8);
1520 # if defined(IR_SEND_PIN)
1529 # else // New API here
1530 # if defined(IR_SEND_PIN)
1541 # endif // defined(SEND_PWM_BY_TIMER)
1546 #elif defined(ARDUINO_ARCH_SAMD)
1547 # if defined(SEND_PWM_BY_TIMER)
1548 #error PWM generation by hardware is not yet implemented for SAMD
1551 # if !defined(IR_SAMD_TIMER)
1552 # if defined(__SAMD51__)
1553 #define IR_SAMD_TIMER TC5
1554 #define IR_SAMD_TIMER_IRQ TC5_IRQn
1557 #define IR_SAMD_TIMER TC3
1558 #define IR_SAMD_TIMER_ID GCLK_CLKCTRL_ID_TCC2_TC3
1559 #define IR_SAMD_TIMER_IRQ TC3_IRQn
1564 NVIC_EnableIRQ (IR_SAMD_TIMER_IRQ);
1567 NVIC_DisableIRQ (IR_SAMD_TIMER_IRQ);
1585 TcCount16 *TC = (TcCount16*) IR_SAMD_TIMER;
1587 # if defined(__SAMD51__)
1589 GCLK->PCHCTRL[TC5_GCLK_ID].reg = GCLK_PCHCTRL_GEN_GCLK0_Val | (1 << GCLK_PCHCTRL_CHEN_Pos);
1592 TC->CTRLA.reg &= ~TC_CTRLA_ENABLE;
1593 while (TC->SYNCBUSY.bit.ENABLE)
1596 TC->CTRLA.reg = TC_CTRLA_SWRST;
1598 while (TC->SYNCBUSY.bit.SWRST)
1607 TC->CTRLA.reg |= TC_CTRLA_MODE_COUNT16 | TC_WAVE_WAVEGEN_MFRQ | TC_CTRLA_PRESCALER_DIV16 | TC_CTRLA_ENABLE;
1611 REG_GCLK_CLKCTRL = (uint16_t)(GCLK_CLKCTRL_CLKEN | GCLK_CLKCTRL_GEN_GCLK0 | IR_SAMD_TIMER_ID);
1612 while (GCLK->STATUS.bit.SYNCBUSY == 1)
1616 TC->CTRLA.reg &= ~TC_CTRLA_ENABLE;
1618 while (TC->STATUS.bit.SYNCBUSY == 1)
1621 TC->CTRLA.reg = TC_CTRLA_SWRST;
1623 while (TC->CTRLA.bit.SWRST)
1632 TC->CTRLA.reg |= TC_CTRLA_MODE_COUNT16 | TC_CTRLA_WAVEGEN_MFRQ | TC_CTRLA_PRESCALER_DIV16 | TC_CTRLA_ENABLE;
1636 NVIC_DisableIRQ (IR_SAMD_TIMER_IRQ);
1637 NVIC_ClearPendingIRQ(IR_SAMD_TIMER_IRQ);
1638 NVIC_SetPriority(IR_SAMD_TIMER_IRQ, 0);
1639 NVIC_EnableIRQ(IR_SAMD_TIMER_IRQ);
1642 TC->INTENSET.bit.MC0 = 1;
1645 # if !defined(DISABLE_CODE_FOR_RECEIVER)
1646 # if defined(__SAMD51__)
1647 void TC5_Handler(
void) {
1648 TcCount16 *TC = (TcCount16*) IR_SAMD_TIMER;
1650 if (TC->INTFLAG.bit.MC0 == 1) {
1652 TC->INTFLAG.bit.MC0 = 1;
1657 void TC3_Handler(
void) {
1658 TcCount16 *TC = (TcCount16*) IR_SAMD_TIMER;
1660 if (TC->INTFLAG.bit.MC0 == 1) {
1662 TC->INTFLAG.bit.MC0 = 1;
1666 # endif // defined(__SAMD51__)
1667 # endif // !defined(DISABLE_CODE_FOR_RECEIVER)
1672 #elif defined(ARDUINO_ARCH_MBED) // Arduino Nano 33 BLE + Sparkfun Apollo3 + Nano RP2040 Connect
1674 mbed::Ticker s50usTimer;
1685 s50usTimer.detach();
1692 # if defined(SEND_PWM_BY_TIMER)
1693 #include "pins_arduino.h"
1695 # if defined(IR_SEND_PIN)
1696 mbed::PwmOut sPwmOutForSendPWM(digitalPinToPinName(
IR_SEND_PIN));
1698 mbed::PwmOut sPwmOutForSendPWM(digitalPinToPinName(
IrSender.
sendPin));
1700 uint8_t sIROutPuseWidth;
1703 sPwmOutForSendPWM.pulsewidth_us(sIROutPuseWidth);
1709 sPwmOutForSendPWM.pulsewidth_us(0);
1717 sPwmOutForSendPWM.period_us(1000 / aFrequencyKHz);
1720 # endif // defined(SEND_PWM_BY_TIMER)
1728 #elif defined(ARDUINO_ARCH_RP2040) // Raspberry Pi Pico, Adafruit Feather RP2040, etc.
1729 #include "pico/time.h"
1731 repeating_timer_t s50usTimer;
1739 bool IRTimerInterruptHandlerHelper(repeating_timer_t*) {
1745 add_repeating_timer_us(-(
MICROS_PER_TICK), IRTimerInterruptHandlerHelper, NULL, &s50usTimer);
1748 cancel_repeating_timer(&s50usTimer);
1755 # if defined(SEND_PWM_BY_TIMER)
1756 #include "hardware/pwm.h"
1758 uint sSliceNumberForSendPWM;
1759 uint sChannelNumberForSendPWM;
1760 uint sIROutPuseWidth;
1766 pwm_set_counter(sSliceNumberForSendPWM, 0);
1767 pwm_set_chan_level(sSliceNumberForSendPWM, sChannelNumberForSendPWM, sIROutPuseWidth);
1770 pwm_set_chan_level(sSliceNumberForSendPWM, sChannelNumberForSendPWM, 0);
1778 # if defined(IR_SEND_PIN)
1781 sSliceNumberForSendPWM = pwm_gpio_to_slice_num(
IR_SEND_PIN);
1782 sChannelNumberForSendPWM = pwm_gpio_to_channel(
IR_SEND_PIN);
1789 uint16_t tPWMWrapValue = (clock_get_hz(clk_sys)) / (aFrequencyKHz * 1000);
1791 pwm_config tPWMConfig = pwm_get_default_config();
1792 pwm_config_set_wrap(&tPWMConfig, tPWMWrapValue - 1);
1793 pwm_init(sSliceNumberForSendPWM, &tPWMConfig,
false);
1795 pwm_set_chan_level(sSliceNumberForSendPWM, sChannelNumberForSendPWM, 0);
1796 pwm_set_enabled(sSliceNumberForSendPWM,
true);
1798 # endif // defined(SEND_PWM_BY_TIMER)
1803 #elif defined(NRF5) || defined(ARDUINO_ARCH_NRF52840) || defined(ARDUINO_ARCH_NRF52)
1804 # if defined(SEND_PWM_BY_TIMER)
1805 #error PWM generation by hardware not implemented for NRF5
1809 NVIC_EnableIRQ (TIMER2_IRQn);
1812 NVIC_DisableIRQ (TIMER2_IRQn);
1821 NRF_TIMER2->MODE = TIMER_MODE_MODE_Timer;
1822 NRF_TIMER2->TASKS_CLEAR = 1;
1823 NRF_TIMER2->PRESCALER = 4;
1824 NRF_TIMER2->BITMODE = TIMER_BITMODE_BITMODE_16Bit;
1826 NRF_TIMER2->CC[1] = 0;
1829 NRF_TIMER2->INTENSET = (TIMER_INTENSET_COMPARE0_Enabled << TIMER_INTENSET_COMPARE0_Pos);
1830 NRF_TIMER2->TASKS_START = 1;
1835 #if !defined(DISABLE_CODE_FOR_RECEIVER)
1840 void TIMER2_IRQHandler(
void) {
1842 if ((NRF_TIMER2->EVENTS_COMPARE[0] != 0) && ((NRF_TIMER2->INTENSET & TIMER_INTENSET_COMPARE0_Msk) != 0)) {
1843 NRF_TIMER2->EVENTS_COMPARE[0] = 0;
1845 NRF_TIMER2->CC[0] += 50;
1858 #elif defined(__STM32F1__) || defined(ARDUINO_ARCH_STM32F1)
1859 #include <HardwareTimer.h>
1860 # if defined(SEND_PWM_BY_TIMER)
1861 #error PWM generation by hardware not implemented for STM32
1868 HardwareTimer s50usTimer(3);
1871 s50usTimer.resume();
1883 s50usTimer.setMode(TIMER_CH1, TIMER_OUTPUT_COMPARE);
1884 s50usTimer.setPrescaleFactor(1);
1887 s50usTimer.refresh();
1896 #elif defined(STM32F1xx) || defined(ARDUINO_ARCH_STM32)
1897 #include <HardwareTimer.h>
1898 # if defined(SEND_PWM_BY_TIMER)
1899 #error PWM generation by hardware not implemented for STM32
1907 HardwareTimer s50usTimer(TIM4);
1909 HardwareTimer s50usTimer(TIM2);
1913 s50usTimer.resume();
1927 s50usTimer.resume();
1934 #elif defined(PARTICLE)
1935 # ifndef __INTERVALTIMER_H__
1936 #include "SparkIntervalTimer.h"
1939 extern IntervalTimer timer;
1940 extern int ir_out_kHz;
1957 # if defined(SEND_PWM_BY_TIMER)
1958 # if defined(IR_SEND_PIN)
1981 # if defined(IR_SEND_PIN)
1986 ir_out_kHz = aFrequencyKHz;
1988 # endif // defined(SEND_PWM_BY_TIMER)
1994 #error Internal code configuration error, no timer functions implemented for this CPU / board
2005 #define ISR() void notImplemented(void)
2010 # if defined(SEND_PWM_BY_TIMER)
2018 # if defined(IR_SEND_PIN)
2023 (void) aFrequencyKHz;
2025 # endif // defined(SEND_PWM_BY_TIMER)
2027 #endif // defined(DOXYGEN / CPU_TYPES)
2031 #endif // _IR_TIMER_HPP