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)
1400 #elif defined(ESP8266)
1401 # if defined(SEND_PWM_BY_TIMER)
1402 #error "No support for hardware PWM generation for ESP8266"
1403 # endif // defined(SEND_PWM_BY_TIMER)
1414 timer1_detachInterrupt();
1424 timer1_enable(TIM_DIV16, TIM_EDGE, TIM_LOOP);
1433 #elif defined(ESP32)
1436 hw_timer_t *s50usTimer = NULL;
1438 # if ESP_ARDUINO_VERSION < ESP_ARDUINO_VERSION_VAL(3, 0, 0) && !defined(SEND_AND_RECEIVE_TIMER_LEDC_CHANNEL)
1439 #define SEND_AND_RECEIVE_TIMER_LEDC_CHANNEL 0 // The channel used for PWM 0 to 7 are high speed PWM channels
1443 timerAlarmEnable(s50usTimer);
1446 #if !defined(ESP_ARDUINO_VERSION)
1447 #define ESP_ARDUINO_VERSION 0
1449 #if !defined(ESP_ARDUINO_VERSION_VAL)
1450 #define ESP_ARDUINO_VERSION_VAL(major, minor, patch) 202
1452 #if ESP_ARDUINO_VERSION < ESP_ARDUINO_VERSION_VAL(2, 0, 2)
1454 if (s50usTimer != NULL) {
1455 timerDetachInterrupt(s50usTimer);
1456 timerEnd(s50usTimer);
1461 if (s50usTimer != NULL) {
1462 timerAlarmDisable(s50usTimer);
1472 # if !defined(DISABLE_CODE_FOR_RECEIVER) // &IRReceiveTimerInterruptHandler is referenced, but not available
1477 if(s50usTimer == NULL) {
1478 s50usTimer = timerBegin(1, 80,
true);
1486 # if !defined(IR_SEND_PIN)
1487 uint8_t sLastSendPin = 0;
1490 # if defined(SEND_PWM_BY_TIMER)
1492 # if ESP_ARDUINO_VERSION < ESP_ARDUINO_VERSION_VAL(3, 0, 0)
1499 # if ESP_ARDUINO_VERSION < ESP_ARDUINO_VERSION_VAL(3, 0, 0)
1500 ledcWrite(SEND_AND_RECEIVE_TIMER_LEDC_CHANNEL, 0);
1511 # if ESP_ARDUINO_VERSION < ESP_ARDUINO_VERSION_VAL(3, 0, 0)
1512 ledcSetup(SEND_AND_RECEIVE_TIMER_LEDC_CHANNEL, aFrequencyKHz * 1000, 8);
1513 # if defined(IR_SEND_PIN)
1514 ledcAttachPin(
IR_SEND_PIN, SEND_AND_RECEIVE_TIMER_LEDC_CHANNEL);
1522 # else // New API here
1523 # if defined(IR_SEND_PIN)
1534 # endif // defined(SEND_PWM_BY_TIMER)
1539 #elif defined(ARDUINO_ARCH_SAMD)
1540 # if defined(SEND_PWM_BY_TIMER)
1541 #error PWM generation by hardware is not yet implemented for SAMD
1544 # if !defined(IR_SAMD_TIMER)
1545 # if defined(__SAMD51__)
1546 #define IR_SAMD_TIMER TC5
1547 #define IR_SAMD_TIMER_IRQ TC5_IRQn
1550 #define IR_SAMD_TIMER TC3
1551 #define IR_SAMD_TIMER_ID GCLK_CLKCTRL_ID_TCC2_TC3
1552 #define IR_SAMD_TIMER_IRQ TC3_IRQn
1557 NVIC_EnableIRQ (IR_SAMD_TIMER_IRQ);
1560 NVIC_DisableIRQ (IR_SAMD_TIMER_IRQ);
1578 TcCount16 *TC = (TcCount16*) IR_SAMD_TIMER;
1580 # if defined(__SAMD51__)
1582 GCLK->PCHCTRL[TC5_GCLK_ID].reg = GCLK_PCHCTRL_GEN_GCLK0_Val | (1 << GCLK_PCHCTRL_CHEN_Pos);
1585 TC->CTRLA.reg &= ~TC_CTRLA_ENABLE;
1586 while (TC->SYNCBUSY.bit.ENABLE)
1589 TC->CTRLA.reg = TC_CTRLA_SWRST;
1591 while (TC->SYNCBUSY.bit.SWRST)
1600 TC->CTRLA.reg |= TC_CTRLA_MODE_COUNT16 | TC_WAVE_WAVEGEN_MFRQ | TC_CTRLA_PRESCALER_DIV16 | TC_CTRLA_ENABLE;
1604 REG_GCLK_CLKCTRL = (uint16_t)(GCLK_CLKCTRL_CLKEN | GCLK_CLKCTRL_GEN_GCLK0 | IR_SAMD_TIMER_ID);
1605 while (GCLK->STATUS.bit.SYNCBUSY == 1)
1609 TC->CTRLA.reg &= ~TC_CTRLA_ENABLE;
1611 while (TC->STATUS.bit.SYNCBUSY == 1)
1614 TC->CTRLA.reg = TC_CTRLA_SWRST;
1616 while (TC->CTRLA.bit.SWRST)
1625 TC->CTRLA.reg |= TC_CTRLA_MODE_COUNT16 | TC_CTRLA_WAVEGEN_MFRQ | TC_CTRLA_PRESCALER_DIV16 | TC_CTRLA_ENABLE;
1629 NVIC_DisableIRQ (IR_SAMD_TIMER_IRQ);
1630 NVIC_ClearPendingIRQ(IR_SAMD_TIMER_IRQ);
1631 NVIC_SetPriority(IR_SAMD_TIMER_IRQ, 0);
1632 NVIC_EnableIRQ(IR_SAMD_TIMER_IRQ);
1635 TC->INTENSET.bit.MC0 = 1;
1638 # if !defined(DISABLE_CODE_FOR_RECEIVER)
1639 # if defined(__SAMD51__)
1640 void TC5_Handler(
void) {
1641 TcCount16 *TC = (TcCount16*) IR_SAMD_TIMER;
1643 if (TC->INTFLAG.bit.MC0 == 1) {
1645 TC->INTFLAG.bit.MC0 = 1;
1650 void TC3_Handler(
void) {
1651 TcCount16 *TC = (TcCount16*) IR_SAMD_TIMER;
1653 if (TC->INTFLAG.bit.MC0 == 1) {
1655 TC->INTFLAG.bit.MC0 = 1;
1659 # endif // defined(__SAMD51__)
1660 # endif // !defined(DISABLE_CODE_FOR_RECEIVER)
1665 #elif defined(ARDUINO_ARCH_MBED) // Arduino Nano 33 BLE + Sparkfun Apollo3 + Nano RP2040 Connect
1667 mbed::Ticker s50usTimer;
1678 s50usTimer.detach();
1685 # if defined(SEND_PWM_BY_TIMER)
1686 #include "pins_arduino.h"
1688 # if defined(IR_SEND_PIN)
1689 mbed::PwmOut sPwmOutForSendPWM(digitalPinToPinName(
IR_SEND_PIN));
1691 mbed::PwmOut sPwmOutForSendPWM(digitalPinToPinName(
IrSender.
sendPin));
1693 uint8_t sIROutPuseWidth;
1696 sPwmOutForSendPWM.pulsewidth_us(sIROutPuseWidth);
1702 sPwmOutForSendPWM.pulsewidth_us(0);
1710 sPwmOutForSendPWM.period_us(1000 / aFrequencyKHz);
1713 # endif // defined(SEND_PWM_BY_TIMER)
1721 #elif defined(ARDUINO_ARCH_RP2040) // Raspberry Pi Pico, Adafruit Feather RP2040, etc.
1722 #include "pico/time.h"
1724 repeating_timer_t s50usTimer;
1732 bool IRTimerInterruptHandlerHelper(repeating_timer_t*) {
1738 add_repeating_timer_us(-(
MICROS_PER_TICK), IRTimerInterruptHandlerHelper, NULL, &s50usTimer);
1741 cancel_repeating_timer(&s50usTimer);
1748 # if defined(SEND_PWM_BY_TIMER)
1749 #include "hardware/pwm.h"
1751 uint sSliceNumberForSendPWM;
1752 uint sChannelNumberForSendPWM;
1753 uint sIROutPuseWidth;
1759 pwm_set_counter(sSliceNumberForSendPWM, 0);
1760 pwm_set_chan_level(sSliceNumberForSendPWM, sChannelNumberForSendPWM, sIROutPuseWidth);
1763 pwm_set_chan_level(sSliceNumberForSendPWM, sChannelNumberForSendPWM, 0);
1771 # if defined(IR_SEND_PIN)
1774 sSliceNumberForSendPWM = pwm_gpio_to_slice_num(
IR_SEND_PIN);
1775 sChannelNumberForSendPWM = pwm_gpio_to_channel(
IR_SEND_PIN);
1782 uint16_t tPWMWrapValue = (clock_get_hz(clk_sys)) / (aFrequencyKHz * 1000);
1784 pwm_config tPWMConfig = pwm_get_default_config();
1785 pwm_config_set_wrap(&tPWMConfig, tPWMWrapValue - 1);
1786 pwm_init(sSliceNumberForSendPWM, &tPWMConfig,
false);
1788 pwm_set_chan_level(sSliceNumberForSendPWM, sChannelNumberForSendPWM, 0);
1789 pwm_set_enabled(sSliceNumberForSendPWM,
true);
1791 # endif // defined(SEND_PWM_BY_TIMER)
1796 #elif defined(NRF5) || defined(ARDUINO_ARCH_NRF52840) || defined(ARDUINO_ARCH_NRF52)
1797 # if defined(SEND_PWM_BY_TIMER)
1798 #error PWM generation by hardware not implemented for NRF5
1802 NVIC_EnableIRQ (TIMER2_IRQn);
1805 NVIC_DisableIRQ (TIMER2_IRQn);
1814 NRF_TIMER2->MODE = TIMER_MODE_MODE_Timer;
1815 NRF_TIMER2->TASKS_CLEAR = 1;
1816 NRF_TIMER2->PRESCALER = 4;
1817 NRF_TIMER2->BITMODE = TIMER_BITMODE_BITMODE_16Bit;
1819 NRF_TIMER2->CC[1] = 0;
1822 NRF_TIMER2->INTENSET = (TIMER_INTENSET_COMPARE0_Enabled << TIMER_INTENSET_COMPARE0_Pos);
1823 NRF_TIMER2->TASKS_START = 1;
1828 #if !defined(DISABLE_CODE_FOR_RECEIVER)
1833 void TIMER2_IRQHandler(
void) {
1835 if ((NRF_TIMER2->EVENTS_COMPARE[0] != 0) && ((NRF_TIMER2->INTENSET & TIMER_INTENSET_COMPARE0_Msk) != 0)) {
1836 NRF_TIMER2->EVENTS_COMPARE[0] = 0;
1838 NRF_TIMER2->CC[0] += 50;
1851 #elif defined(__STM32F1__) || defined(ARDUINO_ARCH_STM32F1)
1852 #include <HardwareTimer.h>
1853 # if defined(SEND_PWM_BY_TIMER)
1854 #error PWM generation by hardware not implemented for STM32
1861 HardwareTimer s50usTimer(3);
1864 s50usTimer.resume();
1876 s50usTimer.setMode(TIMER_CH1, TIMER_OUTPUT_COMPARE);
1877 s50usTimer.setPrescaleFactor(1);
1880 s50usTimer.refresh();
1889 #elif defined(STM32F1xx) || defined(ARDUINO_ARCH_STM32)
1890 #include <HardwareTimer.h>
1891 # if defined(SEND_PWM_BY_TIMER)
1892 #error PWM generation by hardware not implemented for STM32
1900 HardwareTimer s50usTimer(TIM4);
1902 HardwareTimer s50usTimer(TIM2);
1906 s50usTimer.resume();
1920 s50usTimer.resume();
1927 #elif defined(PARTICLE)
1928 # ifndef __INTERVALTIMER_H__
1929 #include "SparkIntervalTimer.h"
1932 extern IntervalTimer timer;
1933 extern int ir_out_kHz;
1950 # if defined(SEND_PWM_BY_TIMER)
1951 # if defined(IR_SEND_PIN)
1974 # if defined(IR_SEND_PIN)
1979 ir_out_kHz = aFrequencyKHz;
1981 # endif // defined(SEND_PWM_BY_TIMER)
1987 #error Internal code configuration error, no timer functions implemented for this CPU / board
1998 #define ISR() void notImplemented(void)
2003 # if defined(SEND_PWM_BY_TIMER)
2011 # if defined(IR_SEND_PIN)
2016 (void) aFrequencyKHz;
2018 # endif // defined(SEND_PWM_BY_TIMER)
2020 #endif // defined(DOXYGEN / CPU_TYPES)
2024 #endif // _IR_TIMER_HPP