IRremote
IRTimer.hpp
Go to the documentation of this file.
1 
35 #ifndef _IR_TIMER_HPP
36 #define _IR_TIMER_HPP
37 
44 /*
45  * Functions declared here
46  */
47 void timerConfigForReceive(); // Initialization of 50 us timer, interrupts are still disabled
48 void timerEnableReceiveInterrupt(); // Enable interrupts of an initialized timer
49 void timerDisableReceiveInterrupt(); // Disable interrupts of an initialized timer
50 void timerResetInterruptPending(); // ISR helper function for some architectures, which require a manual reset
51 // of the pending interrupt (TIMER_REQUIRES_RESET_INTR_PENDING is defined). Otherwise empty.
52 
53 void timerConfigForSend(uint16_t aFrequencyKHz); // Initialization of timer hardware generated PWM, if defined(SEND_PWM_BY_TIMER)
54 void enableSendPWMByTimer(); // Switch on PWM generation
55 void disableSendPWMByTimer(); // Switch off PWM generation
56 
57 // SEND_PWM_BY_TIMER for different architectures is enabled / defined at IRremote.hpp line 195.
58 #if defined(SEND_PWM_BY_TIMER) && ( (defined(ESP32) || defined(ARDUINO_ARCH_RP2040) || defined(PARTICLE)) || defined(ARDUINO_ARCH_MBED) )
59 #define SEND_PWM_DOES_NOT_USE_RECEIVE_TIMER // Receive timer and send generation timer are independent here.
60 #endif
61 
62 #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
63 #undef IR_SEND_PIN // To avoid "warning: "IR_SEND_PIN" redefined". The user warning is done at IRremote.hpp line 202.
64 #endif
65 
66 // Macros for enabling timers for development
67 //#define SEND_PWM_BY_TIMER
68 //#define IR_USE_AVR_TIMER1
69 //#define IR_USE_AVR_TIMER2
70 //#define IR_USE_AVR_TIMER3
71 //#define IR_USE_AVR_TIMER4
72 //#define IR_USE_AVR_TIMER4_HS
73 //#define IR_USE_AVR_TIMER5
74 //#define IR_USE_AVR_TIMER_TINY0
75 //#define IR_USE_AVR_TIMER_TINY1
76 //#define IR_USE_AVR_TIMER_A
77 //#define IR_USE_AVR_TIMER_B
78 //#define IR_USE_AVR_TIMER_D
79 //#define __MK20DX128__
80 //#define __MKL26Z64__
81 //#define __IMXRT1062__
82 //#define ESP8266
83 //#define ESP32
84 //#define ARDUINO_ARCH_SAMD
85 //#define ARDUINO_ARCH_MBED
86 //#define ARDUINO_ARCH_RP2040
87 //#define NRF5
88 //#define __STM32F1__
89 //#define STM32F1xx
90 //#define PARTICLE
91 //#define ARDUINO_ARCH_RENESAS
92 
93 #if defined (DOXYGEN)
94 
97 #define IR_SEND_PIN
98 
106 }
111 }
112 
118 }
119 
129 void timerConfigForSend(uint16_t aFrequencyKHz) {
130 }
131 
136 }
141 }
142 
143 #elif defined(__AVR__)
144 /**********************************************************************************************************************
145  * Mapping of AVR boards to AVR timers
146  * For some CPU's you have the option to switch the timer and the hardware send pin
147  **********************************************************************************************************************/
148 /***************************************
149  * Plain AVR CPU's, no boards
150  ***************************************/
151 // Arduino Duemilanove, Diecimila, LilyPad, Mini, Fio, Nano, etc
152 #if defined(__AVR_ATmega328P__) || defined(__AVR_ATmega328PB__) || defined(__AVR_ATmega168__) \
153  || defined(__AVR_ATmega88P__) || defined(__AVR_ATmega88PB__)
154 # if !defined(IR_USE_AVR_TIMER1) && !defined(IR_USE_AVR_TIMER2)
155 //#define IR_USE_AVR_TIMER1 // send pin = pin 9
156 #define IR_USE_AVR_TIMER2 // send pin = pin 3
157 # endif
158 
159 // Arduino Mega
160 #elif defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__)
161 # 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)
162 //#define IR_USE_AVR_TIMER1 // send pin = pin 11
163 #define IR_USE_AVR_TIMER2 // send pin = pin 9
164 //#define IR_USE_AVR_TIMER3 // send pin = pin 5
165 //#define IR_USE_AVR_TIMER4 // send pin = pin 6
166 //#define IR_USE_AVR_TIMER5 // send pin = pin 46
167 # endif
168 
169 // Leonardo
170 #elif defined(__AVR_ATmega32U4__) && ! defined(TEENSYDUINO) && ! defined(ARDUINO_AVR_PROMICRO)
171 # if !defined(IR_USE_AVR_TIMER1) && !defined(IR_USE_AVR_TIMER3) && !defined(IR_USE_AVR_TIMER4_HS)
172 //#define IR_USE_AVR_TIMER1 // send pin = pin 9
173 #define IR_USE_AVR_TIMER3 // send pin = pin 5
174 //#define IR_USE_AVR_TIMER4_HS // send pin = pin 13
175 # endif
176 
177 // Nano Every, Uno WiFi Rev2 and similar
178 #elif defined(__AVR_ATmega808__) || defined(__AVR_ATmega809__) || defined(__AVR_ATmega3208__) || defined(__AVR_ATmega3209__) \
179  || defined(__AVR_ATmega1608__) || defined(__AVR_ATmega1609__) || defined(__AVR_ATmega4808__) || defined(__AVR_ATmega4809__) || defined(__AVR_ATtiny1604__)
180 # if !defined(IR_USE_AVR_TIMER_B)
181 #define IR_USE_AVR_TIMER_B // send pin = pin 6 on ATmega4809 1 on ATmega4809
182 # endif
183 
184 #elif defined(__AVR_ATtiny816__) || defined(__AVR_ATtiny1614__) || defined(__AVR_ATtiny1616__) || defined(__AVR_ATtiny3216__) || defined(__AVR_ATtiny3217__) // e.g. TinyCore boards
185 # if !defined(IR_USE_AVR_TIMER_A) && !defined(IR_USE_AVR_TIMER_D)
186 #define IR_USE_AVR_TIMER_A // use this if you use megaTinyCore, Tone is on TCB and millis() on TCD
187 //#define IR_USE_AVR_TIMER_D // use this if you use TinyCore
188 # endif
189 
190 // ATmega8u2, ATmega16U2, ATmega32U2, ATmega8 - Timer 2 does not work with existing code below
191 #elif defined(__AVR_ATmega8U2__) || defined(__AVR_ATmega16U2__) || defined(__AVR_ATmega32U2__) || defined(__AVR_ATmega8__)
192 # if !defined(IR_USE_AVR_TIMER1)
193 #define IR_USE_AVR_TIMER1 // send pin = pin C6
194 # endif
195 
196 // ATtiny84
197 #elif defined(__AVR_ATtiny84__) || defined(__AVR_ATtiny88__)
198 # if !defined(IR_USE_AVR_TIMER1)
199 #define IR_USE_AVR_TIMER1 // send pin = pin 6, no tone() available when using ATTinyCore
200 # endif
201 
202 #elif defined(__AVR_ATtiny87__) || defined(__AVR_ATtiny167__)
203 # if !defined(IR_USE_AVR_TIMER1)
204 #define IR_USE_AVR_TIMER1 // send pin = pin PB1 / 8
205 # endif
206 #define USE_TIMER_CHANNEL_B
207 
208 //ATtiny85, 45, 25
209 #elif defined(__AVR_ATtiny25__) || defined(__AVR_ATtiny45__) || defined(__AVR_ATtiny85__)
210 # if !defined(IR_USE_AVR_TIMER_TINY0) && !defined(IR_USE_AVR_TIMER_TINY1)
211 # if defined(ARDUINO_AVR_DIGISPARK) // tested with 16 and 8 MHz
212 #define IR_USE_AVR_TIMER_TINY0 // send pin = pin 1
213 // standard Digispark settings use timer 1 for millis() and micros()
214 # else
215 // standard ATTinyCore settings use timer 0 for millis() and micros()
216 #define IR_USE_AVR_TIMER_TINY1 // send pin = pin 4
217 # endif
218 # endif
219 
220 /***************************************
221  * SPARKFUN Pro Micro board
222  ***************************************/
223 #elif defined(ARDUINO_AVR_PROMICRO)
224 # if !defined(IR_USE_AVR_TIMER1) && !defined(IR_USE_AVR_TIMER3) && !defined(IR_USE_AVR_TIMER4_HS)
225 //#define IR_USE_AVR_TIMER1 // send pin = pin 9
226 #define IR_USE_AVR_TIMER3 // send pin = pin 5
227 //#define IR_USE_AVR_TIMER4_HS // send pin = pin 13
228 # endif
229 
230 /***************************************
231  * TEENSY Boards
232  ***************************************/
233 // Teensy 1.0
234 #elif defined(__AVR_AT90USB162__)
235 # if !defined(IR_USE_AVR_TIMER1)
236 #define IR_USE_AVR_TIMER1 // send pin = pin 17
237 # endif
238 
239 // Teensy++ 1.0 & 2.0
240 #elif defined(__AVR_AT90USB646__) || defined(__AVR_AT90USB1286__)
241 # if !defined(IR_USE_AVR_TIMER1) && !defined(IR_USE_AVR_TIMER2) && !defined(IR_USE_AVR_TIMER3)
242 //#define IR_USE_AVR_TIMER1 // send pin = pin 25
243 #define IR_USE_AVR_TIMER2 // send pin = pin 1
244 //#define IR_USE_AVR_TIMER3 // send pin = pin 16
245 # endif
246 
247 // Teensy 2.0
248 #elif defined(__AVR_ATmega32U4__) && defined(TEENSYDUINO)
249 # if !defined(IR_USE_AVR_TIMER1) && !defined(IR_USE_AVR_TIMER3) && !defined(IR_USE_AVR_TIMER4_HS)
250 //#define IR_USE_AVR_TIMER1 // send pin = pin 14 (Teensy 2.0 - physical pin: B5)
251 //#define IR_USE_AVR_TIMER3 // send pin = pin 9 (Teensy 2.0 - physical pin: C6)
252 #define IR_USE_AVR_TIMER4_HS // send pin = pin 10 (Teensy 2.0 - physical pin: C7)
253 # endif
254 
255 /***************************************
256  * CPU's with MegaCore
257  ***************************************/
258 // MegaCore - ATmega64, ATmega128
259 #elif defined(__AVR_ATmega64__) || defined(__AVR_ATmega128__) || defined(__AVR_ATmega1281__) || defined(__AVR_ATmega2560__)
260 # if !defined(IR_USE_AVR_TIMER1)
261 #define IR_USE_AVR_TIMER1 // send pin = pin 13
262 # endif
263 
264 /***************************************
265  * CPU's with MajorCore
266  ***************************************/
267 #elif defined(__AVR_ATmega8515__) || defined(__AVR_ATmega162__)
268 # if !defined(IR_USE_AVR_TIMER1) && !defined(IR_USE_AVR_TIMER3)
269 #define IR_USE_AVR_TIMER1 // send pin = pin 13
270 //#define IR_USE_AVR_TIMER3 // send pin = pin 12 - ATmega162 only
271 # endif
272 
273 /***************************************
274  * CPU's with MightyCore
275  ***************************************/
276 // MightyCore - ATmega1284
277 #elif defined(__AVR_ATmega1284__) || defined(__AVR_ATmega1284P__)
278 # if !defined(IR_USE_AVR_TIMER1) && !defined(IR_USE_AVR_TIMER2) && !defined(IR_USE_AVR_TIMER3)
279 //#define IR_USE_AVR_TIMER1 // send pin = pin 13
280 #define IR_USE_AVR_TIMER2 // send pin = pin 14
281 //#define IR_USE_AVR_TIMER3 // send pin = pin 6
282 # endif
283 
284 // MightyCore - ATmega164, ATmega324, ATmega644
285 #elif defined(__AVR_ATmega644__) || defined(__AVR_ATmega644P__) \
286 || defined(__AVR_ATmega324P__) || defined(__AVR_ATmega324A__) \
287 || defined(__AVR_ATmega324PA__) || defined(__AVR_ATmega164A__) \
288 || defined(__AVR_ATmega164P__)
289 # if !defined(IR_USE_AVR_TIMER1) && !defined(IR_USE_AVR_TIMER2)
290 //#define IR_USE_AVR_TIMER1 // send pin = pin 13
291 #define IR_USE_AVR_TIMER2 // send pin = pin 14
292 # endif
293 
294 // MightyCore - ATmega8535, ATmega16, ATmega32
295 #elif defined(__AVR_ATmega8535__) || defined(__AVR_ATmega16__) || defined(__AVR_ATmega32__)
296 # if !defined(IR_USE_AVR_TIMER1)
297 #define IR_USE_AVR_TIMER1 // send pin = pin 13
298 # endif
299 
300 #endif // AVR CPU's
301 /**********************************************************************************************************************
302  * End of AVR mapping, start of AVR timers
303  **********************************************************************************************************************/
304 /*
305  * AVR Timer1 (16 bits)
306  */
307 #if defined(IR_USE_AVR_TIMER1)
308 
309 # if defined(TIMSK1)
310 #define TIMSK TIMSK1 // use the value of TIMSK1 for the statements below
311 # endif
312 
314  TIMSK |= _BV(OCIE1A);
315 }
317  TIMSK &= ~_BV(OCIE1A);
318 }
319 
320 # if defined(USE_TIMER_CHANNEL_B)
321 # if defined(TIMER1_COMPB_vect)
322 #define TIMER_INTR_NAME TIMER1_COMPB_vect
323 # elif defined(TIM1_COMPB_vect)
324 #define TIMER_INTR_NAME TIM1_COMPB_vect
325 # endif
326 #else
327 # if defined(TIMER1_COMPA_vect)
328 #define TIMER_INTR_NAME TIMER1_COMPA_vect
329 # elif defined(TIM1_COMPA_vect)
330 #define TIMER_INTR_NAME TIM1_COMPA_vect
331 # endif
332 # endif
333 
334 void timerConfigForReceive() {
335  TCCR1A = 0;
336  TCCR1B = _BV(WGM12) | _BV(CS10); // CTC mode, no prescaling
337  OCR1A = (F_CPU * MICROS_PER_TICK) / MICROS_IN_ONE_SECOND; // 16 * 50 = 800
338  TCNT1 = 0;
339 }
340 
341 # if defined(SEND_PWM_BY_TIMER)
342 # if defined(CORE_OC1A_PIN)
343 #define IR_SEND_PIN CORE_OC1A_PIN // Teensy
344 
345 # elif defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__)
346 #define IR_SEND_PIN 11 // Arduino Mega
347 
348 // MightyCore, MegaCore, MajorCore
349 # elif defined(__AVR_ATmega1284__) || defined(__AVR_ATmega1284P__) \
350 || defined(__AVR_ATmega644__) || defined(__AVR_ATmega644P__) \
351 || defined(__AVR_ATmega324P__) || defined(__AVR_ATmega324A__) \
352 || defined(__AVR_ATmega324PA__) || defined(__AVR_ATmega164A__) \
353 || defined(__AVR_ATmega164P__) || defined(__AVR_ATmega32__) \
354 || defined(__AVR_ATmega16__) || defined(__AVR_ATmega8535__) \
355 || defined(__AVR_ATmega64__) || defined(__AVR_ATmega128__) \
356 || defined(__AVR_ATmega1281__) || defined(__AVR_ATmega2561__) \
357 || defined(__AVR_ATmega8515__) || defined(__AVR_ATmega162__)
358 #define IR_SEND_PIN 13
359 
360 # elif defined(__AVR_ATtiny84__)
361 #define IR_SEND_PIN 6
362 
363 # elif defined(__AVR_ATtiny88__)
364 #define IR_SEND_PIN 8
365 
366 # elif defined(__AVR_ATtiny87__) || defined(__AVR_ATtiny167__)
367 /*
368  * !!! IR_SEND_PIN value must correspond to ENABLE_SEND_PWM_BY_TIMER below !!!
369  */
370 # if defined(USE_TIMER_CHANNEL_B)
371 #define IR_SEND_PIN PIN_PB1 // OC1BU / PB1 / Pin9 at ATTinyCore
372 //#define IR_SEND_PIN PIN_PB3 // OC1BV / PB3 / Pin11 at ATTinyCore
373 //#define IR_SEND_PIN PIN_PB5 // OC1BW / PB5 / Pin13 at ATTinyCore
374 //#define IR_SEND_PIN PIN_PB7 // OC1BX / PB7 / Pin15 at ATTinyCore
375 # else
376 #define IR_SEND_PIN PIN_PB0 // OC1AU / PB1 / Pin8 at ATTinyCore
377 //#define IR_SEND_PIN PIN_PB2 // OC1AV / PB3 / Pin10 at ATTinyCore
378 //#define IR_SEND_PIN PIN_PB4 // OC1AW / PB5 / Pin12 at ATTinyCore
379 //#define IR_SEND_PIN PIN_PB6 // OC1AX / PB6 / Pin14 at ATTinyCore
380 # endif
381 
382 # else
383 #define IR_SEND_PIN 9 // OC1A Arduino Duemilanove, Diecimila, LilyPad, Sparkfun Pro Micro, Leonardo, MH-ET Tiny88 etc.
384 # endif // defined(CORE_OC1A_PIN)
385 
386 # if defined(__AVR_ATtiny87__) || defined(__AVR_ATtiny167__)
387 // Clear OC1A/OC1B on Compare Match when up-counting. Set OC1A/OC1B on Compare Match when down counting.
388 # if defined(USE_TIMER_CHANNEL_B)
389 void enableSendPWMByTimer() {
390  TCNT1 = 0;
391  TCCR1A |= _BV(COM1B1);
392  TCCR1D |= _BV(OC1BU); // + enable OC1BU as output
393  //TCNT1 = 0; TCCR1A |= _BV(COM1B1); TCCR1D |= _BV(OC1BV); // + enable OC1BV as output
394  //TCNT1 = 0; TCCR1A |= _BV(COM1B1); TCCR1D |= _BV(OC1BW); // + enable OC1BW as output
395  //TCNT1 = 0; TCCR1A |= _BV(COM1B1); TCCR1D |= _BV(OC1BX); // + enable OC1BX as output
396 }
397 # else
398 void disableSendPWMByTimer() {
399  TCNT1 = 0;
400  TCCR1A |= _BV(COM1A1);
401  TCCR1D |= _BV(OC1AU); // + enable OC1BU as output
402  //TCNT1 = 0; TCCR1A |= _BV(COM1A1); TCCR1D |= _BV(OC1AV); // + enable OC1BV as output
403  //TCNT1 = 0; TCCR1A |= _BV(COM1A1); TCCR1D |= _BV(OC1AW); // + enable OC1BW as output
404  //TCNT1 = 0; TCCR1A |= _BV(COM1A1); TCCR1D |= _BV(OC1AX); // + enable OC1BX as output
405 }
406 
407 # endif
408 void disableSendPWMByTimer() {
409  TCCR1D = 0;
410 }
411 # else
412 # if defined(USE_TIMER_CHANNEL_B)
413 void enableSendPWMByTimer() {
414  TCNT1 = 0;
415  TCCR1A |= _BV(COM1B1); // Clear OC1A/OC1B on Compare Match when up-counting. Set OC1A/OC1B on Compare Match when counting down.
416 }
417 void disableSendPWMByTimer() {
418  TCCR1A &= ~(_BV(COM1B1));
419 }
420 # else
421 void enableSendPWMByTimer() {
422  TCNT1 = 0;
423  TCCR1A |= _BV(COM1A1); // Clear OC1A/OC1B on Compare Match when up-counting. Set OC1A/OC1B on Compare Match when downcounting.
424 }
425 void disableSendPWMByTimer() {
426  TCCR1A &= ~(_BV(COM1A1));
427 }
428 # endif
429 # endif
430 
431 /*
432  * timerConfigForSend() is used exclusively by IRsend::enableIROut()
433  * Set output pin mode and disable receive interrupt if it uses the same resource
434  */
435 void timerConfigForSend(uint16_t aFrequencyKHz) {
437 
438 # if (((F_CPU / 2000) / 38) < 256)
439  const uint16_t tPWMWrapValue = (F_CPU / 2000) / (aFrequencyKHz); // 210,52 for 38 kHz @16 MHz clock, 2000 instead of 1000 because of Phase Correct PWM
440  TCCR1A = _BV(WGM11); // PWM, Phase Correct, Top is ICR1
441  TCCR1B = _BV(WGM13) | _BV(CS10); // CS10 -> no prescaling
442  ICR1 = tPWMWrapValue - 1;
443 # if defined(USE_TIMER_CHANNEL_B)
444  OCR1B = ((tPWMWrapValue * IR_SEND_DUTY_CYCLE_PERCENT) / 100) - 1;
445 # else
446  OCR1A = ((tPWMWrapValue * IR_SEND_DUTY_CYCLE_PERCENT) / 100) - 1;
447 # endif
448  TCNT1 = 0; // not really required, since we have an 8 bit counter, but makes the signal more reproducible
449 # else
450  const uint16_t tPWMWrapValue = ((F_CPU / 8) / 2000) / (aFrequencyKHz); // 2000 instead of 1000 because of Phase Correct PWM
451  TCCR1A = _BV(WGM11);// PWM, Phase Correct, Top is ICR1
452  TCCR1B = _BV(WGM13) | _BV(CS11);// CS11 -> Prescaling by 8
453  ICR1 = tPWMWrapValue - 1;
454 # if defined(USE_TIMER_CHANNEL_B)
455  OCR1A = ((tPWMWrapValue * IR_SEND_DUTY_CYCLE_PERCENT) / 100) - 1;
456 # else
457  OCR1A = ((tPWMWrapValue * IR_SEND_DUTY_CYCLE_PERCENT) / 100) - 1;
458 # endif
459  TCNT1 = 0; // not really required, since we have an 8 bit counter, but makes the signal more reproducible
460 # endif
461 }
462 # endif // defined(SEND_PWM_BY_TIMER)
463 
464 /*
465  * AVR Timer2 (8 bits) // Tone timer on Uno
466  */
467 #elif defined(IR_USE_AVR_TIMER2)
468 
470  TIMSK2 = _BV(OCIE2B); // Output Compare Match A Interrupt Enable
471 }
473  TIMSK2 = 0;
474 }
475 #define TIMER_INTR_NAME TIMER2_COMPB_vect // We use TIMER2_COMPB_vect to be compatible with tone() library
476 
477 #define TIMER_COUNT_TOP (F_CPU * MICROS_PER_TICK / MICROS_IN_ONE_SECOND)
478 
479 void timerConfigForReceive() {
480 # if (TIMER_COUNT_TOP < 256)
481  TCCR2A = _BV(WGM21);
482  TCCR2B = _BV(CS20);
483  OCR2A = TIMER_COUNT_TOP;
484  OCR2B = TIMER_COUNT_TOP;
485  TCNT2 = 0;
486 # else
487  TCCR2A = _BV(WGM21);
488  TCCR2B = _BV(CS21);
489  OCR2A = TIMER_COUNT_TOP / 8;
490  OCR2B = TIMER_COUNT_TOP / 8;
491  TCNT2 = 0;
492 # endif
493 }
494 
495 # if defined(SEND_PWM_BY_TIMER)
496 # if defined(CORE_OC2B_PIN)
497 #define IR_SEND_PIN CORE_OC2B_PIN // Teensy
498 
499 # elif defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__)
500 #define IR_SEND_PIN 9 // Arduino Mega
501 
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
508 
509 # else
510 #define IR_SEND_PIN 3 // Arduino Duemilanove, Diecimila, LilyPad, etc
511 # endif // defined(CORE_OC2B_PIN)
512 
513 void enableSendPWMByTimer() {
514  TCNT2 = 0;
515  TCCR2A |= _BV(COM2B1); // Clear OC2B on Compare Match
516 }
517 void disableSendPWMByTimer() {
518  TCCR2A &= ~(_BV(COM2B1)); // Normal port operation, OC2B disconnected.
519 }
520 
521 /*
522  * timerConfigForSend() is used exclusively by IRsend::enableIROut()
523  * Set output pin mode and disable receive interrupt if it uses the same resource
524  */
525 void timerConfigForSend(uint16_t aFrequencyKHz) {
527 
528 # if (((F_CPU / 2000) / 38) < 256)
529  /*
530  * tPWMWrapValue is 210.52 for 38 kHz, 17.58 for 455 kHz @16 MHz clock.
531  * 210 -> 38.095 kHz, 17 -> 470.588 kHz @16 MHz clock.
532  * We use 2000 instead of 1000 in the formula, because of Phase Correct PWM.
533  */
534  const uint16_t tPWMWrapValue = (F_CPU / 2000) / (aFrequencyKHz);
535  TCCR2A = _BV(WGM20); // PWM, Phase Correct, Top is OCR2A
536  TCCR2B = _BV(WGM22) | _BV(CS20); // CS20 -> no prescaling
537  OCR2A = tPWMWrapValue - 1; // The top value for the timer. The modulation frequency will be F_CPU / 2 / (OCR2A + 1).
538  OCR2B = ((tPWMWrapValue * IR_SEND_DUTY_CYCLE_PERCENT) / 100) - 1;
539  TCNT2 = 0; // not really required, since we have an 8 bit counter, but makes the signal more reproducible
540 # else
541  const uint16_t tPWMWrapValue = ((F_CPU / 8) / 2000) / (aFrequencyKHz); // 2000 instead of 1000 because of Phase Correct PWM
542  TCCR2A = _BV(WGM20);// PWM, Phase Correct, Top is OCR2A
543  TCCR2B = _BV(WGM22) | _BV(CS21);// CS21 -> Prescaling by 8
544  OCR2A = tPWMWrapValue - 1;
545  OCR2B = ((tPWMWrapValue * IR_SEND_DUTY_CYCLE_PERCENT) / 100) - 1;
546  TCNT2 = 0;// not really required, since we have an 8 bit counter, but makes the signal more reproducible
547 # endif
548 }
549 # endif // defined(SEND_PWM_BY_TIMER)
550 
551 /*
552  * AVR Timer3 (16 bits)
553  */
554 #elif defined(IR_USE_AVR_TIMER3)
555 
557  TIMSK3 = _BV(OCIE3B);
558 }
560  TIMSK3 = 0;
561 }
562 #define TIMER_INTR_NAME TIMER3_COMPB_vect
563 
564 void timerConfigForReceive() {
565  TCCR3A = 0;
566  TCCR3B = _BV(WGM32) | _BV(CS30);
567  OCR3A = F_CPU * MICROS_PER_TICK / MICROS_IN_ONE_SECOND;
568  OCR3B = F_CPU * MICROS_PER_TICK / MICROS_IN_ONE_SECOND;
569  TCNT3 = 0;
570 }
571 
572 # if defined(SEND_PWM_BY_TIMER)
573 # if defined(CORE_OC3A_PIN)
574 #define IR_SEND_PIN CORE_OC3A_PIN // Teensy
575 
576 # elif defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__) \
577 || defined(__AVR_ATmega32U4__) || defined(ARDUINO_AVR_PROMICRO)
578 #define IR_SEND_PIN 5 // Arduino Mega, Arduino Leonardo, Sparkfun Pro Micro
579 
580 # elif defined(__AVR_ATmega1284__) || defined(__AVR_ATmega1284P__)
581 #define IR_SEND_PIN 6 // MightyCore, MegaCore
582 
583 # else
584 #error Please add OC3A pin number here
585 # endif
586 
587 void enableSendPWMByTimer() {
588  TCNT3 = 0;
589  TCCR3A |= _BV(COM3A1);
590 }
591 void disableSendPWMByTimer() {
592  TCCR3A &= ~(_BV(COM3A1));
593 }
594 
595 /*
596  * timerConfigForSend() is used exclusively by IRsend::enableIROut()
597  * Set output pin mode and disable receive interrupt if it uses the same resource
598  */
599 void timerConfigForSend(uint16_t aFrequencyKHz) {
600 #if F_CPU > 16000000
601 #error "Creating timer PWM with timer 3 is not supported for F_CPU > 16 MHz"
602 #endif
604 
605  const uint16_t tPWMWrapValue = (F_CPU / 2000) / (aFrequencyKHz); // 210,52 for 38 kHz @16 MHz clock, 2000 instead of 1000 because of Phase Correct PWM
606  TCCR3A = _BV(WGM31);
607  TCCR3B = _BV(WGM33) | _BV(CS30); // PWM, Phase Correct, ICRn as TOP, complete period is double of tPWMWrapValue
608  ICR3 = tPWMWrapValue - 1;
609  OCR3A = ((tPWMWrapValue * IR_SEND_DUTY_CYCLE_PERCENT) / 100) - 1;
610  TCNT3 = 0; // required, since we have an 16 bit counter
611 }
612 # endif // defined(SEND_PWM_BY_TIMER)
613 
614 /*
615  * AVR Timer4 (16 bits)
616  */
617 #elif defined(IR_USE_AVR_TIMER4)
619  TIMSK4 = _BV(OCIE4A);
620 }
622  TIMSK4 = 0;
623 }
624 #define TIMER_INTR_NAME TIMER4_COMPA_vect
625 
626 void timerConfigForReceive() {
627  TCCR4A = 0;
628  TCCR4B = _BV(WGM42) | _BV(CS40);
629  OCR4A = F_CPU * MICROS_PER_TICK / MICROS_IN_ONE_SECOND;
630  TCNT4 = 0;
631 }
632 
633 # if defined(SEND_PWM_BY_TIMER)
634 # if defined(CORE_OC4A_PIN)
635 #define IR_SEND_PIN CORE_OC4A_PIN
636 # elif defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__)
637 #define IR_SEND_PIN 6 // Arduino Mega
638 # else
639 #error Please add OC4A pin number here
640 # endif
641 
642 void enableSendPWMByTimer() {
643  TCNT4 = 0;
644  TCCR4A |= _BV(COM4A1);
645 }
646 void disableSendPWMByTimer() {
647  TCCR4A &= ~(_BV(COM4A1));
648 }
649 
650 void timerConfigForSend(uint16_t aFrequencyKHz) {
651 #if F_CPU > 16000000
652 #error "Creating timer PWM with timer 4 is not supported for F_CPU > 16 MHz"
653 #endif
655  const uint16_t tPWMWrapValue = (F_CPU / 2000) / (aFrequencyKHz); // 210,52 for 38 kHz @16 MHz clock, 2000 instead of 1000 because of Phase Correct PWM
656  TCCR4A = _BV(WGM41);
657  TCCR4B = _BV(WGM43) | _BV(CS40);
658  ICR4 = tPWMWrapValue - 1;
659  OCR4A = ((tPWMWrapValue * IR_SEND_DUTY_CYCLE_PERCENT) / 100) - 1;
660  TCNT4 = 0; // required, since we have an 16 bit counter
661 }
662 # endif // defined(SEND_PWM_BY_TIMER)
663 
664 /*
665  * AVR Timer4 (10 bits, high speed option)
666  */
667 #elif defined(IR_USE_AVR_TIMER4_HS)
668 
670  TIMSK4 = _BV(TOIE4);
671 }
673  TIMSK4 = 0;
674 }
675 #define TIMER_INTR_NAME TIMER4_OVF_vect
676 
677 void timerConfigForReceive() {
678  TCCR4A = 0;
679  TCCR4B = _BV(CS40);
680  TCCR4C = 0;
681  TCCR4D = 0;
682  TCCR4E = 0;
683  TC4H = (F_CPU * MICROS_PER_TICK / MICROS_IN_ONE_SECOND) >> 8;
684  OCR4C = (F_CPU * MICROS_PER_TICK / MICROS_IN_ONE_SECOND) & 255;
685  TC4H = 0;
686  TCNT4 = 0;
687 }
688 
689 # if defined(SEND_PWM_BY_TIMER)
690 # if defined(CORE_OC4A_PIN)
691 #define IR_SEND_PIN CORE_OC4A_PIN // Teensy 2.0
692 # elif defined(ARDUINO_AVR_PROMICRO)
693 #define IR_SEND_PIN 5 // Sparkfun Pro Micro
694 # elif defined(__AVR_ATmega32U4__)
695 #define IR_SEND_PIN 13 // Leonardo
696 # else
697 #error Please add OC4A pin number here
698 # endif
699 
700 # if defined(ARDUINO_AVR_PROMICRO) // Sparkfun Pro Micro
701 void enableSendPWMByTimer() {
702  TCNT4 = 0;
703  TCCR4A |= _BV(COM4A0); // Use complementary OC4A output on pin 5
704 }
705 void disableSendPWMByTimer() {
706  TCCR4A &= ~(_BV(COM4A0)); // (Pro Micro does not map PC7 (32/ICP3/CLK0/OC4A)
707 }
708 // of ATmega32U4 )
709 # else
710 void enableSendPWMByTimer() {
711  TCNT4 = 0;
712  TCCR4A |= _BV(COM4A1);
713  DDRC |= 1 << 7;
714 }
715 void disableSendPWMByTimer() {
716  TCCR4A &= ~(_BV(COM4A1));
717 }
718 # endif
719 
720 /*
721  * timerConfigForSend() is used exclusively by IRsend::enableIROut()
722  * Set output pin mode and disable receive interrupt if it uses the same resource
723  */
724 void timerConfigForSend(uint16_t aFrequencyKHz) {
725 #if F_CPU > 16000000
726 #error "Creating timer PWM with timer 4 HS is not supported for F_CPU > 16 MHz"
727 #endif
729 
730  const uint16_t tPWMWrapValue = ((F_CPU / 2000) / (aFrequencyKHz)) - 1; // 210,52 for 38 kHz @16 MHz clock, 2000 instead of 1000 because of Phase Correct PWM
731  TCCR4A = (1 << PWM4A);
732  TCCR4B = _BV(CS40);
733  TCCR4C = 0;
734  TCCR4D = (1 << WGM40);
735  TCCR4E = 0;
736  TC4H = tPWMWrapValue >> 8;
737  OCR4C = tPWMWrapValue;
738  TC4H = (tPWMWrapValue * IR_SEND_DUTY_CYCLE_PERCENT / 100) >> 8;
739  OCR4A = (tPWMWrapValue * IR_SEND_DUTY_CYCLE_PERCENT / 100) & 255;
740  TCNT4 = 0; // not really required, since we have an 8 bit counter, but makes the signal more reproducible
741 }
742 # endif // defined(SEND_PWM_BY_TIMER)
743 
744 /*
745  * AVR Timer5 (16 bits)
746  */
747 #elif defined(IR_USE_AVR_TIMER5)
748 
750  TIMSK5 = _BV(OCIE5A);
751 }
753  TIMSK5 = 0;
754 }
755 #define TIMER_INTR_NAME TIMER5_COMPA_vect
756 
757 void timerConfigForReceive() {
758  TCCR5A = 0;
759  TCCR5B = _BV(WGM52) | _BV(CS50);
760  OCR5A = F_CPU * MICROS_PER_TICK / MICROS_IN_ONE_SECOND;
761  TCNT5 = 0;
762 }
763 
764 # if defined(SEND_PWM_BY_TIMER)
765 # if defined(CORE_OC5A_PIN)
766 #define IR_SEND_PIN CORE_OC5A_PIN
767 # elif defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__)
768 #define IR_SEND_PIN 46 // Arduino Mega
769 # else
770 #error Please add OC5A pin number here
771 # endif
772 
773 void enableSendPWMByTimer() {
774  TCNT5 = 0;
775  TCCR5A |= _BV(COM5A1);
776 }
777 void disableSendPWMByTimer() {
778  TCCR5A &= ~(_BV(COM5A1));
779 }
780 
781 /*
782  * timerConfigForSend() is used exclusively by IRsend::enableIROut()
783  * Set output pin mode and disable receive interrupt if it uses the same resource
784  */
785 void timerConfigForSend(uint16_t aFrequencyKHz) {
786 #if F_CPU > 16000000
787 #error "Creating timer PWM with timer 5 is not supported for F_CPU > 16 MHz"
788 #endif
790 
791  const uint16_t tPWMWrapValue = (F_CPU / 2000) / (aFrequencyKHz); // 210,52 for 38 kHz @16 MHz clock, 2000 instead of 1000 because of Phase Correct PWM
792  TCCR5A = _BV(WGM51);
793  TCCR5B = _BV(WGM53) | _BV(CS50);
794  ICR5 = tPWMWrapValue - 1;
795  OCR5A = ((tPWMWrapValue * IR_SEND_DUTY_CYCLE_PERCENT) / 100) - 1;
796  TCNT5 = 0; // required, since we have an 16 bit counter
797 }
798 # endif // defined(SEND_PWM_BY_TIMER)
799 
800 /*
801  * AVR Timer0 for ATtinies (8 bits)
802  */
803 #elif defined(IR_USE_AVR_TIMER_TINY0)
804 
806  TIMSK |= _BV(OCIE0A);
807 }
809  TIMSK &= ~(_BV(OCIE0A));
810 }
811 #define TIMER_INTR_NAME TIMER0_COMPA_vect
812 
813 #define TIMER_COUNT_TOP (F_CPU * MICROS_PER_TICK / MICROS_IN_ONE_SECOND)
814 
815 void timerConfigForReceive() {
816 # if (TIMER_COUNT_TOP < 256)
817  TCCR0A = _BV(WGM01); // CTC, Top is OCR0A
818  TCCR0B = _BV(CS00);// No prescaling
819  OCR0A = TIMER_COUNT_TOP;
820  TCNT0 = 0;
821 # else
822  TCCR0A = _BV(WGM01);
823  TCCR0B = _BV(CS01); // prescaling by 8
824  OCR0A = TIMER_COUNT_TOP / 8;
825  TCNT0 = 0;
826 # endif
827 }
828 
829 # if defined(SEND_PWM_BY_TIMER)
830 #define IR_SEND_PIN 1
831 
832 void enableSendPWMByTimer() {
833  TCNT0 = 0;
834  TCCR0A |= _BV(COM0B1);
835 }
836 void disableSendPWMByTimer() {
837  TCCR0A &= ~(_BV(COM0B1));
838 }
839 
840 /*
841  * timerConfigForSend() is used exclusively by IRsend::enableIROut()
842  * Set output pin mode and disable receive interrupt if it uses the same resource
843  */
844 void timerConfigForSend(uint16_t aFrequencyKHz) {
845 #if F_CPU > 16000000
846 #error "Creating timer PWM with timer TINY0 is not supported for F_CPU > 16 MHz"
847 #endif
849 
850  const uint16_t tPWMWrapValue = (F_CPU / 2000) / (aFrequencyKHz); // 210,52 for 38 kHz @16 MHz clock, 2000 instead of 1000 because of Phase Correct PWM
851  TCCR0A = _BV(WGM00); // PWM, Phase Correct, Top is OCR0A
852  TCCR0B = _BV(WGM02) | _BV(CS00); // CS00 -> no prescaling
853  OCR0A = tPWMWrapValue - 1;
854  OCR0B = ((tPWMWrapValue * IR_SEND_DUTY_CYCLE_PERCENT) / 100) - 1;
855  TCNT0 = 0; // not really required, since we have an 8 bit counter, but makes the signal more reproducible
856 }
857 # endif // defined(SEND_PWM_BY_TIMER)
858 
859 /*
860  * AVR Timer1 for ATtinies (8 bits)
861  */
862 #elif defined(IR_USE_AVR_TIMER_TINY1)
863 
865  TIMSK |= _BV(OCIE1B);
866 }
868  TIMSK &= ~(_BV(OCIE1B));
869 }
870 #define TIMER_INTR_NAME TIMER1_COMPB_vect
871 
872 #define TIMER_COUNT_TOP (F_CPU * MICROS_PER_TICK / MICROS_IN_ONE_SECOND)
873 
874 void timerConfigForReceive() {
875 # if (TIMER_COUNT_TOP < 256)
876  TCCR1 = _BV(CTC1) | _BV(CS10); // Clear Timer/Counter on Compare Match, Top is OCR1C, No prescaling
877  GTCCR = 0;// normal, non-PWM mode
878  OCR1C = TIMER_COUNT_TOP;
879  TCNT1 = 0;
880 # else
881  TCCR1 = _BV(CTC1) | _BV(CS12); // Clear Timer/Counter on Compare Match, Top is OCR1C, prescaling by 8
882  GTCCR = 0; // normal, non-PWM mode
883  OCR1C = TIMER_COUNT_TOP / 8;
884  TCNT1 = 0;
885 # endif
886 }
887 
888 # if defined(SEND_PWM_BY_TIMER)
889 #define IR_SEND_PIN 4
890 
891 void enableSendPWMByTimer() {
892  TCNT1 = 0;
893  GTCCR |= _BV(PWM1B) | _BV(COM1B0); // Enable pin 4 PWM output (PB4 - Arduino D4)
894 }
895 void disableSendPWMByTimer() {
896  GTCCR &= ~(_BV(PWM1B) | _BV(COM1B0));
897 }
898 
899 /*
900  * timerConfigForSend() is used exclusively by IRsend::enableIROut()
901  * Set output pin mode and disable receive interrupt if it uses the same resource
902  */
903 void timerConfigForSend(uint16_t aFrequencyKHz) {
905 
906 # if (((F_CPU / 1000) / 38) < 256)
907  const uint16_t tPWMWrapValue = (F_CPU / 1000) / (aFrequencyKHz); // 421 @16 MHz, 26 @1 MHz and 38 kHz
908  TCCR1 = _BV(CTC1) | _BV(CS10);// CTC1 = 1: TOP value set to OCR1C, CS10 No Prescaling
909  OCR1C = tPWMWrapValue - 1;
910  OCR1B = ((tPWMWrapValue * IR_SEND_DUTY_CYCLE_PERCENT) / 100) - 1;
911  TCNT1 = 0;// not really required, since we have an 8 bit counter, but makes the signal more reproducible
912  GTCCR = _BV(PWM1B) | _BV(COM1B0);// PWM1B = 1: Enable PWM for OCR1B, COM1B0 Clear on compare match
913 # else
914  const uint16_t tPWMWrapValue = ((F_CPU / 2) / 1000) / (aFrequencyKHz); // 210 for 16 MHz and 38 kHz
915  TCCR1 = _BV(CTC1) | _BV(CS11); // CTC1 = 1: TOP value set to OCR1C, CS11 Prescaling by 2
916  OCR1C = tPWMWrapValue - 1;
917  OCR1B = ((tPWMWrapValue * IR_SEND_DUTY_CYCLE_PERCENT) / 100) - 1;
918  TCNT1 = 0; // not really required, since we have an 8 bit counter, but makes the signal more reproducible
919  GTCCR = _BV(PWM1B) | _BV(COM1B0); // PWM1B = 1: Enable PWM for OCR1B, COM1B0 Clear on compare match
920 # endif
921 }
922 # endif // defined(SEND_PWM_BY_TIMER)
923 
924 /*
925  * AVR TimerA for TinyCore 32 (16 bits)
926  */
927 #elif defined(IR_USE_AVR_TIMER_A)
928 #define TIMER_REQUIRES_RESET_INTR_PENDING
930  TCA0.SINGLE.INTFLAGS = TCA_SINGLE_OVF_bm;
931 }
933  TCA0.SINGLE.INTCTRL = TCA_SINGLE_OVF_bm;
934 }
936  TCA0.SINGLE.INTCTRL &= ~(TCA_SINGLE_OVF_bm);
937 }
938 #define TIMER_INTR_NAME TCA0_OVF_vect
939 // For MegaTinyCore:
940 // TCB1 is used by Tone()
941 // TCB2 is used by Servo, but we cannot hijack the ISR, so we must use a dedicated timer for the 20 ms interrupt
942 // TCB3 is used by millis()
943 // Must use TCA0, since TCBx have only prescaler %2. Use single (16bit) mode, because it seems to be easier :-)
944 void timerConfigForReceive() {
945  TCA0.SINGLE.CTRLD = 0; // Single mode - required at least for MegaTinyCore
946  TCA0.SINGLE.CTRLB = TCA_SINGLE_WGMODE_NORMAL_gc; // Normal mode, top = PER
947  TCA0.SINGLE.PER = (F_CPU / MICROS_IN_ONE_SECOND) * MICROS_PER_TICK; // 800 at 16 MHz
948  TCA0.SINGLE.CTRLA = TCA_SINGLE_CLKSEL_DIV1_gc | TCA_SINGLE_ENABLE_bm; // set prescaler to 1 and enable timer
949 }
950 
951 # if defined(SEND_PWM_BY_TIMER)
952 #error "No support for hardware PWM generation for ATtiny3216/17 etc."
953 # endif // defined(SEND_PWM_BY_TIMER)
954 
955 /*
956  * AVR TimerB (8 bits) for ATmega4809 (Nano Every, Uno WiFi Rev2)
957  */
958 #elif defined(IR_USE_AVR_TIMER_B)
959 
960 // ATmega4809 TCB0
961 #define TIMER_REQUIRES_RESET_INTR_PENDING
963  TCB0.INTFLAGS = TCB_CAPT_bm;
964 }
966  TCB0.INTCTRL = TCB_CAPT_bm;
967 }
969  TCB0.INTCTRL &= ~(TCB_CAPT_bm);
970 }
971 #define TIMER_INTR_NAME TCB0_INT_vect
972 
973 void timerConfigForReceive() {
974  TCB0.CTRLB = (TCB_CNTMODE_INT_gc); // Periodic interrupt mode
975  TCB0.CCMP = ((F_CPU * MICROS_PER_TICK) / MICROS_IN_ONE_SECOND);
976  TCB0.INTFLAGS = TCB_CAPT_bm; // reset interrupt flags
977  TCB0.CTRLA = (TCB_CLKSEL_CLKDIV1_gc) | (TCB_ENABLE_bm);
978 }
979 
980 # if defined(SEND_PWM_BY_TIMER)
981 # if defined(__AVR_ATmega4808__) || defined(__AVR_ATmega4809__)
982 #define IR_SEND_PIN 6 // PF4 on ATmega4809 / Nano Every (see pins_arduino.h digital_pin_to_timer)
983 # else
984 #error SEND_PWM_BY_TIMER not yet supported for this CPU
985 # endif
986 
987 void enableSendPWMByTimer() {
988  TCB0.CNT = 0;
989  TCB0.CTRLB |= TCB_CCMPEN_bm; // set Compare/Capture Output Enable
990 }
991 void disableSendPWMByTimer() {
992  TCB0.CTRLB &= ~(TCB_CCMPEN_bm);
993 }
994 
995 /*
996  * timerConfigForSend() is used exclusively by IRsend::enableIROut()
997  * Set output pin mode and disable receive interrupt if it uses the same resource
998  */
999 void timerConfigForSend(uint16_t aFrequencyKHz) {
1000 #if F_CPU > 16000000
1001  // we have only prescaler 2 or must take clock of timer A (which is non deterministic)
1002 #error "Creating timer PWM with timer TCB0 is not possible for F_CPU > 16 MHz"
1003 #endif
1005 
1006  const uint16_t tPWMWrapValue = (F_CPU / 2000) / (aFrequencyKHz); // 210,52 for 38 kHz @16 MHz clock, 2000 instead of 1000 because of using CLK / 2
1007  TCB0.CTRLB = TCB_CNTMODE_PWM8_gc; // 8 bit PWM mode
1008  TCB0.CCMPL = tPWMWrapValue - 1; // Period of 8 bit PWM
1009  TCB0.CCMPH = ((tPWMWrapValue * IR_SEND_DUTY_CYCLE_PERCENT) / 100) - 1; // Duty cycle of waveform of 8 bit PWM
1010  TCB0.CTRLA = (TCB_CLKSEL_CLKDIV2_gc) | (TCB_ENABLE_bm); // use CLK / 2
1011  TCB0.CNT = 0; // not really required, since we have an 8 bit counter, but makes the signal more reproducible
1012 }
1013 # endif // defined(SEND_PWM_BY_TIMER)
1014 
1015 /*
1016  * AVR TimerD for TinyCore 32 (16 bits)
1017  */
1018 #elif defined(IR_USE_AVR_TIMER_D)
1019 
1020 #define TIMER_REQUIRES_RESET_INTR_PENDING
1022  TCD0.INTFLAGS = TCD_OVF_bm;
1023 }
1025  TCD0.INTCTRL = TCD_OVF_bm;
1026 }
1028  TCD0.INTCTRL = 0;
1029 }
1030 #define TIMER_INTR_NAME TCD0_OVF_vect
1031 
1032 void timerConfigForReceive() {
1033  TCD0.CTRLA = 0; // reset enable bit in order to unprotect the other bits
1034  TCD0.CTRLB = TCD_WGMODE_ONERAMP_gc; // must be set since it is used by PWM
1035 // TCD0.CMPBSET = 80;
1036  TCD0.CMPBCLR = ((F_CPU * MICROS_PER_TICK) / MICROS_IN_ONE_SECOND) - 1;
1037 
1038  _PROTECTED_WRITE(TCD0.FAULTCTRL, 0); // must disable WOA output at pin 13/PA4
1039 
1040  TCD0.INTFLAGS = TCD_OVF_bm; // reset interrupt flags
1041  // check enable ready
1042 // while ((TCD0.STATUS & TCD_ENRDY_bm) == 0); // Wait for Enable Ready to be high - I guess it is not required
1043  // enable timer - this locks the other bits and static registers and activates values in double buffered registers
1044  TCD0.CTRLA = TCD_ENABLE_bm | TCD_CLKSEL_SYSCLK_gc | TCD_CNTPRES_DIV1_gc; // System clock, no prescale, no synchronization prescaler
1045 }
1046 
1047 # if defined(SEND_PWM_BY_TIMER)
1048 #define IR_SEND_PIN 13
1049 
1050 void timerEnableSendPWM() {
1051  TCD0.CTRLA = 0; // reset enable bit in order to unprotect the other bits
1052  _PROTECTED_WRITE(TCD0.FAULTCTRL, FUSE_CMPAEN_bm); // enable WOA output at pin 13/PA4
1053 // _PROTECTED_WRITE(TCD0.FAULTCTRL, FUSE_CMPAEN_bm | FUSE_CMPBEN_bm); // enable WOA + WOB output pins at 13/PA4 + 14/PA5
1054  TCD0.CTRLA = TCD_ENABLE_bm | TCD_CLKSEL_SYSCLK_gc | TCD_CNTPRES_DIV1_gc; // System clock, no prescale, no synchronization prescaler
1055 }
1056 
1057 void enableSendPWMByTimer() {
1058  timerEnableSendPWM();
1059 }
1060 void disableSendPWMByTimer() {
1061  TCD0.CTRLA = 0; // do not disable output, disable complete timer
1062 }
1063 
1064 /*
1065  * timerConfigForSend() is used exclusively by IRsend::enableIROut()
1066  * Set output pin mode and disable receive interrupt if it uses the same resource
1067  */
1068 void timerConfigForSend(uint16_t aFrequencyKHz) {
1070 
1071  const uint16_t tPWMWrapValue = (F_CPU / 1000) / (aFrequencyKHz); // 526,31 for 38 kHz @20 MHz clock
1072  // use one ramp mode and overflow interrupt
1073  TCD0.CTRLA = 0; // reset enable bit in order to unprotect the other bits
1074 // while ((TCD0.STATUS & TCD_ENRDY_bm) == 0); // Wait for Enable Ready to be high - I guess it is not required
1075  TCD0.CTRLB = TCD_WGMODE_ONERAMP_gc; // must be set since it is used by PWM
1076  TCD0.CTRLC = 0; // reset WOx output settings
1077 // TCD0.CMPBSET = 80;
1078  TCD0.CMPBCLR = tPWMWrapValue - 1;
1079 
1080  // Generate duty cycle signal for debugging etc.
1081  TCD0.CMPASET = 0;
1082  TCD0.CMPACLR = (tPWMWrapValue * IR_SEND_DUTY_CYCLE_PERCENT / 100) - 1; // duty cycle for WOA
1083 
1084  TCD0.INTFLAGS = TCD_OVF_bm; // reset interrupt flags
1085  TCD0.INTCTRL = TCD_OVF_bm; // overflow interrupt
1086  // Do not enable timer, this is done at timerEnablSendPWM()
1087 }
1088 # endif // defined(SEND_PWM_BY_TIMER)
1089 
1090 #else
1091 #error Internal code configuration error, no timer functions implemented for this AVR CPU / board
1092 #endif //defined(IR_USE_AVR_TIMER*)
1093 /**********************************************************************************************************************
1094  * End of AVR timers
1095  **********************************************************************************************************************/
1096 
1097 /**********************************************
1098  * Uno R4 boards
1099  **********************************************/
1100 #elif defined(ARDUINO_ARCH_RENESAS)
1101 #include "FspTimer.h"
1102 FspTimer s50usTimer;
1103 
1104 // Undefine ISR, because we register/call the plain function IRReceiveTimerInterruptHandler()
1105 # if defined(ISR)
1106 #undef ISR
1107 # endif
1108 
1109 // callback method used by timer
1110 void IRTimerInterruptHandlerHelper(timer_callback_args_t __attribute((unused)) *p_args) {
1112 }
1114 // s50usTimer.enable_overflow_irq();
1115  s50usTimer.start();
1116 }
1118 // s50usTimer.disable_overflow_irq();
1119  s50usTimer.stop(); // May save power
1120 }
1121 
1122 void timerConfigForReceive() {
1123  uint8_t tTimerType = GPT_TIMER;
1124  int8_t tIndex = FspTimer::get_available_timer(tTimerType); // Get first unused channel. Here we need the address of tTimerType
1125  if (tIndex < 0 || tTimerType != GPT_TIMER) {
1126  // here we found no unused GPT channel
1127  tIndex = FspTimer::get_available_timer(tTimerType, true); // true to force use of already used PWM channel. Sets "force_pwm_reserved" if timer found
1128  if (tIndex < 0) {
1129  // If we already get an tIndex < 0 we have an error, but do not know how to handle :-(
1130  return;
1131  }
1132  }
1133  s50usTimer.begin(TIMER_MODE_PERIODIC, tTimerType, tIndex, MICROS_IN_ONE_SECOND / MICROS_PER_TICK, 0.0,
1134  IRTimerInterruptHandlerHelper);
1135  s50usTimer.setup_overflow_irq();
1136  s50usTimer.open(); // In turn calls R_GPT_Enable()
1137  s50usTimer.stop(); // May save power
1138 }
1139 
1140 # if defined(SEND_PWM_BY_TIMER)
1141 #error PWM generation by hardware not yet implemented for Arduino Uno R4
1142 // Not yet implemented
1143 void enableSendPWMByTimer() {
1144 }
1145 void disableSendPWMByTimer() {
1146 }
1147 
1148 /*
1149  * timerConfigForSend() is used exclusively by IRsend::enableIROut()
1150  */
1151 void timerConfigForSend(uint16_t aFrequencyKHz) {
1152 # if defined(IR_SEND_PIN)
1153 # else
1154 # endif
1155 }
1156 # endif
1157 
1158 /**********************************************
1159  * Teensy 3.0 / Teensy 3.1 / Teensy 3.2 boards
1160  **********************************************/
1161 #elif defined(__MK20DX128__) || defined(__MK20DX256__) || defined(__MK64FX512__) || defined(__MK66FX1M0__)
1162 
1163 // Special carrier modulator timer for Teensy 3.0 / Teensy 3.1 / Teensy 3.2
1164 #define TIMER_REQUIRES_RESET_INTR_PENDING
1166  uint8_t tmp __attribute__((unused)) = CMT_MSC;
1167  CMT_CMD2 = 30;
1168 }
1170  NVIC_ENABLE_IRQ(IRQ_CMT);
1171  NVIC_SET_PRIORITY(IRQ_CMT, 48);
1172 }
1174  NVIC_DISABLE_IRQ(IRQ_CMT);
1175 }
1176 
1177 #define TIMER_INTR_NAME cmt_isr
1178 # if defined(ISR)
1179 #undef ISR
1180 # endif
1181 #define ISR(f) void f(void)
1182 
1183 #define CMT_PPS_DIV ((F_BUS + 7999999) / 8000000)
1184 # if F_BUS < 8000000
1185 #error IRremote requires at least 8 MHz on Teensy 3.x
1186 # endif
1187 
1188 void timerConfigForReceive() {
1189  SIM_SCGC4 |= SIM_SCGC4_CMT;
1190  CMT_PPS = CMT_PPS_DIV - 1;
1191  CMT_CGH1 = 1;
1192  CMT_CGL1 = 1;
1193  CMT_CMD1 = 0;
1194  CMT_CMD2 = 30;
1195  CMT_CMD3 = 0;
1196  CMT_CMD4 = (F_BUS / 160000 + CMT_PPS_DIV / 2) / CMT_PPS_DIV - 31;
1197  CMT_OC = 0;
1198  CMT_MSC = 0x03;
1199 }
1200 
1201 # if defined(SEND_PWM_BY_TIMER)
1202 #define IR_SEND_PIN 5
1203 
1204 void enableSendPWMByTimer() {
1205  do {
1206  CORE_PIN5_CONFIG = PORT_PCR_MUX(2) | PORT_PCR_DSE | PORT_PCR_SRE;
1207  } while (0);
1208 }
1209 void disableSendPWMByTimer() {
1210  do {
1211  CORE_PIN5_CONFIG = PORT_PCR_MUX(1) | PORT_PCR_DSE | PORT_PCR_SRE;
1212  } while (0);
1213 }
1214 
1215 /*
1216  * timerConfigForSend() is used exclusively by IRsend::enableIROut()
1217  * Set output pin mode and disable receive interrupt if it uses the same resource
1218  */
1219 void timerConfigForSend(uint16_t aFrequencyKHz) {
1220  timerDisableReceiveInterrupt(); // TODO really required here? Do we have a common resource for Teensy3.0, 3.1
1221 # if defined(IR_SEND_PIN)
1222  pinMode(IR_SEND_PIN, OUTPUT);
1223 # else
1224  pinMode(IrSender.sendPin, OUTPUT);
1225 # endif
1226 
1227  SIM_SCGC4 |= SIM_SCGC4_CMT;
1228  SIM_SOPT2 |= SIM_SOPT2_PTD7PAD;
1229  CMT_PPS = CMT_PPS_DIV - 1;
1230  CMT_CGH1 = ((F_BUS / CMT_PPS_DIV / 3000) + ((aFrequencyKHz) / 2)) / (aFrequencyKHz);
1231  CMT_CGL1 = ((F_BUS / CMT_PPS_DIV / 1500) + ((aFrequencyKHz) / 2)) / (aFrequencyKHz);
1232  CMT_CMD1 = 0;
1233  CMT_CMD2 = 30;
1234  CMT_CMD3 = 0;
1235  CMT_CMD4 = 0;
1236  CMT_OC = 0x60;
1237  CMT_MSC = 0x01;
1238 }
1239 # endif // defined(SEND_PWM_BY_TIMER)
1240 
1241 /***************************************
1242  * Teensy-LC board
1243  ***************************************/
1244 #elif defined(__MKL26Z64__)
1245 
1246 // defines for TPM1 timer on Teensy-LC
1247 #define TIMER_REQUIRES_RESET_INTR_PENDING
1249  FTM1_SC |= FTM_SC_TOF;
1250 }
1252  NVIC_ENABLE_IRQ(IRQ_FTM1);
1253  NVIC_SET_PRIORITY(IRQ_FTM1, 0);
1254 }
1256  NVIC_DISABLE_IRQ(IRQ_FTM1);
1257 }
1258 #define TIMER_INTR_NAME ftm1_isr
1259 # if defined(ISR)
1260 #undef ISR
1261 # endif
1262 #define ISR(f) void f(void)
1263 
1264 void timerConfigForReceive() {
1265  SIM_SCGC6 |= SIM_SCGC6_TPM1;
1266  FTM1_SC = 0;
1267  FTM1_CNT = 0;
1268  FTM1_MOD = (F_PLL / 40000) - 1;
1269  FTM1_C0V = 0;
1270  FTM1_SC = FTM_SC_CLKS(1) | FTM_SC_PS(0) | FTM_SC_TOF | FTM_SC_TOIE;
1271 }
1272 
1273 # if defined(SEND_PWM_BY_TIMER)
1274 #define IR_SEND_PIN 16
1275 
1276 void enableSendPWMByTimer() {
1277  FTM1_CNT = 0;
1278  CORE_PIN16_CONFIG = PORT_PCR_MUX(3) | PORT_PCR_DSE | PORT_PCR_SRE;
1279 }
1280 void disableSendPWMByTimer() {
1281  CORE_PIN16_CONFIG = PORT_PCR_MUX(1) | PORT_PCR_SRE;
1282 }
1283 
1284 /*
1285  * timerConfigForSend() is used exclusively by IRsend::enableIROut()
1286  * Set output pin mode and disable receive interrupt if it uses the same resource
1287  */
1288 void timerConfigForSend(uint16_t aFrequencyKHz) {
1290 # if defined(IR_SEND_PIN)
1291  pinMode(IR_SEND_PIN, OUTPUT);
1292 # else
1293  pinMode(IrSender.sendPin, OUTPUT);
1294 # endif
1295 
1296  SIM_SCGC6 |= SIM_SCGC6_TPM1;
1297  FTM1_SC = 0;
1298  FTM1_CNT = 0;
1299  FTM1_MOD = ((F_PLL / 2000) / aFrequencyKHz) - 1;
1300  FTM1_C0V = ((F_PLL / 6000) / aFrequencyKHz) - 1;
1301  FTM1_SC = FTM_SC_CLKS(1) | FTM_SC_PS(0);
1302 }
1303 # endif // defined(SEND_PWM_BY_TIMER)
1304 
1305 /***************************************
1306  * Teensy 4.0, 4.1, MicroMod boards
1307  ***************************************/
1308 #elif defined(__IMXRT1062__)
1309 // forward declare ISR function (will be implemented by IRReceive.hpp)
1310 void pwm1_3_isr();
1311 
1312 // defines for FlexPWM1 timer on Teensy 4
1313 #define TIMER_REQUIRES_RESET_INTR_PENDING
1315  FLEXPWM1_SM3STS = FLEXPWM_SMSTS_RF;
1316 }
1318  attachInterruptVector(IRQ_FLEXPWM1_3, pwm1_3_isr);
1319  FLEXPWM1_SM3STS = FLEXPWM_SMSTS_RF;
1320  FLEXPWM1_SM3INTEN = FLEXPWM_SMINTEN_RIE;
1321  NVIC_ENABLE_IRQ (IRQ_FLEXPWM1_3), NVIC_SET_PRIORITY(IRQ_FLEXPWM1_3, 48);
1322 }
1324  NVIC_DISABLE_IRQ (IRQ_FLEXPWM1_3);
1325 }
1326 #define TIMER_INTR_NAME pwm1_3_isr
1327 # if defined(ISR)
1328 #undef ISR
1329 # endif
1330 #define ISR(f) void (f)(void)
1331 
1332 void timerConfigForReceive() {
1333  uint32_t period = (float) F_BUS_ACTUAL * (float) (MICROS_PER_TICK) * 0.0000005f;
1334  uint32_t prescale = 0;
1335  while (period > 32767) {
1336  period = period >> 1;
1337  if (prescale < 7)
1338  prescale++;
1339  }
1340  FLEXPWM1_FCTRL0 |= FLEXPWM_FCTRL0_FLVL(8);
1341  FLEXPWM1_FSTS0 = 0x0008;
1342  FLEXPWM1_MCTRL |= FLEXPWM_MCTRL_CLDOK(8);
1343  FLEXPWM1_SM3CTRL2 = FLEXPWM_SMCTRL2_INDEP;
1344  FLEXPWM1_SM3CTRL = FLEXPWM_SMCTRL_HALF | FLEXPWM_SMCTRL_PRSC(prescale);
1345  FLEXPWM1_SM3INIT = -period;
1346  FLEXPWM1_SM3VAL0 = 0;
1347  FLEXPWM1_SM3VAL1 = period;
1348  FLEXPWM1_SM3VAL2 = 0;
1349  FLEXPWM1_SM3VAL3 = 0;
1350  FLEXPWM1_SM3VAL4 = 0;
1351  FLEXPWM1_SM3VAL5 = 0;
1352  FLEXPWM1_MCTRL |= FLEXPWM_MCTRL_LDOK(8) | FLEXPWM_MCTRL_RUN(8);
1353 }
1354 
1355 # if defined(SEND_PWM_BY_TIMER)
1356 #define IR_SEND_PIN 7
1357 void enableSendPWMByTimer() {
1358  FLEXPWM1_OUTEN |= FLEXPWM_OUTEN_PWMA_EN(8);
1359  IOMUXC_SW_MUX_CTL_PAD_GPIO_B1_00 = 6;
1360 }
1361 
1362 void disableSendPWMByTimer() {
1363  IOMUXC_SW_MUX_CTL_PAD_GPIO_B1_00 = 5;
1364  FLEXPWM1_OUTEN &= ~FLEXPWM_OUTEN_PWMA_EN(8);
1365 }
1366 
1367 /*
1368  * timerConfigForSend() is used exclusively by IRsend::enableIROut()
1369  * Set output pin mode and disable receive interrupt if it uses the same resource
1370  */
1371 void timerConfigForSend(uint16_t aFrequencyKHz) {
1373 # if defined(IR_SEND_PIN)
1374  pinMode(IR_SEND_PIN, OUTPUT);
1375 # else
1376  pinMode(IrSender.sendPin, OUTPUT);
1377 # endif
1378 
1379  uint32_t period = (float) F_BUS_ACTUAL / (float) ((aFrequencyKHz) * 2000);
1380  uint32_t prescale = 0;
1381  while (period > 32767) {
1382  period = period >> 1;
1383  if (prescale < 7)
1384  prescale++;
1385  }
1386  FLEXPWM1_FCTRL0 |= FLEXPWM_FCTRL0_FLVL(8);
1387  FLEXPWM1_FSTS0 = 0x0008;
1388  FLEXPWM1_MCTRL |= FLEXPWM_MCTRL_CLDOK(8);
1389  FLEXPWM1_SM3CTRL2 = FLEXPWM_SMCTRL2_INDEP;
1390  FLEXPWM1_SM3CTRL = FLEXPWM_SMCTRL_HALF | FLEXPWM_SMCTRL_PRSC(prescale);
1391  FLEXPWM1_SM3INIT = -period;
1392  FLEXPWM1_SM3VAL0 = 0;
1393  FLEXPWM1_SM3VAL1 = period;
1394  FLEXPWM1_SM3VAL2 = -(period / 3);
1395  FLEXPWM1_SM3VAL3 = period / 3;
1396  FLEXPWM1_SM3VAL4 = 0;
1397  FLEXPWM1_SM3VAL5 = 0;
1398  FLEXPWM1_MCTRL |= FLEXPWM_MCTRL_LDOK(8) | FLEXPWM_MCTRL_RUN(8);
1399 }
1400 # endif // defined(SEND_PWM_BY_TIMER)
1401 
1402 /**********************************************************
1403  * ESP8266 boards
1404  **********************************************************/
1405 #elif defined(ESP8266)
1406 # if defined(SEND_PWM_BY_TIMER)
1407 #error "No support for hardware PWM generation for ESP8266"
1408 # endif // defined(SEND_PWM_BY_TIMER)
1409 
1410 // Undefine ISR, because we register/call the plain function IRReceiveTimerInterruptHandler()
1411 # if defined(ISR)
1412 #undef ISR
1413 # endif
1414 
1416  timer1_attachInterrupt(&IRReceiveTimerInterruptHandler); // enables interrupt too
1417 }
1419  timer1_detachInterrupt(); // disables interrupt too
1420 }
1421 
1422 void timerConfigForReceive() {
1423  timer1_isr_init();
1424  /*
1425  * TIM_DIV1 = 0, //80MHz (80 ticks/us - 104857.588 us max)
1426  * TIM_DIV16 = 1, //5MHz (5 ticks/us - 1677721.4 us max)
1427  * TIM_DIV256 = 3 //312.5Khz (1 tick = 3.2us - 26843542.4 us max)
1428  */
1429  timer1_enable(TIM_DIV16, TIM_EDGE, TIM_LOOP);
1430  timer1_write((80 / 16) * MICROS_PER_TICK); // 80 for 80 and 160! MHz clock, 16 for TIM_DIV16 above
1431 }
1432 
1433 /**********************************************************
1434  * ESP32 boards - can use any pin for send PWM
1435  * Receive timer and send generation are independent,
1436  * so it is recommended to always define SEND_PWM_BY_TIMER
1437  **********************************************************/
1438 #elif defined(ESP32)
1439 # if !defined(ESP_ARDUINO_VERSION)
1440 #define ESP_ARDUINO_VERSION 0x010101 // Version 1.1.1
1441 # endif
1442 # if !defined(ESP_ARDUINO_VERSION_VAL)
1443 #define ESP_ARDUINO_VERSION_VAL(major, minor, patch) ((major << 16) | (minor << 8) | (patch))
1444 # endif
1445 
1446 // Variables specific to the ESP32.
1447 // the ledc functions behave like hardware timers for us :-), so we do not require our own soft PWM generation code.
1448 hw_timer_t *s50usTimer = nullptr; // set by timerConfigForReceive()
1449 
1450 # if ESP_ARDUINO_VERSION < ESP_ARDUINO_VERSION_VAL(3, 0, 0) && !defined(SEND_LEDC_CHANNEL)
1451 #define SEND_LEDC_CHANNEL 0 // The channel used for PWM 0 to 7 are high speed PWM channels
1452 # endif
1453 
1455 # if ESP_ARDUINO_VERSION >= ESP_ARDUINO_VERSION_VAL(3, 0, 0)
1456  timerStart(s50usTimer);
1457 # else
1458  timerAlarmEnable(s50usTimer);
1459 # endif
1460 }
1461 
1462 # if ESP_ARDUINO_VERSION < ESP_ARDUINO_VERSION_VAL(2, 0, 2)
1463 /*
1464  * Special support for ESP core < 202
1465  */
1467  if (s50usTimer != nullptr) {
1468  timerDetachInterrupt(s50usTimer);
1469  timerEnd(s50usTimer);
1470  }
1471 }
1472 # else
1473 
1475  if (s50usTimer != nullptr) {
1476 # if ESP_ARDUINO_VERSION >= ESP_ARDUINO_VERSION_VAL(3, 0, 0)
1477  timerStop(s50usTimer);
1478 # else
1479  timerAlarmDisable(s50usTimer);
1480 # endif
1481  }
1482 }
1483 # endif
1484 
1485 // Undefine ISR, because we register/call the plain function IRReceiveTimerInterruptHandler()
1486 # if defined(ISR)
1487 #undef ISR
1488 # endif
1489 
1490 # if !defined(DISABLE_CODE_FOR_RECEIVER) // Otherwise the &IRReceiveTimerInterruptHandler is referenced, but not available
1491 void timerConfigForReceive() {
1492  // ESP32 has a proper API to setup timers, no weird chip macros needed
1493  // simply call the readable API versions :)
1494  // 3 timers, choose #1, 80 divider for microsecond precision @80MHz clock, count_up = true
1495  if(s50usTimer == nullptr) {
1496 # if ESP_ARDUINO_VERSION >= ESP_ARDUINO_VERSION_VAL(3, 0, 0)
1497  s50usTimer = timerBegin(1000000); // Only 1 parameter is required. 1000000 corresponds to 1 MHz / 1 uSec. After successful setup the timer will automatically start.
1498  timerStop(s50usTimer); // Stop it here, to avoid "error E (3447) gptimer: gptimer_start(348): timer is not enabled yet" at timerEnableReceiveInterrupt()
1499  timerAttachInterrupt(s50usTimer, &IRReceiveTimerInterruptHandler);
1500  timerAlarm(s50usTimer, MICROS_PER_TICK, true, 0); // 0 in the last parameter is repeat forever
1501 # else
1502  s50usTimer = timerBegin(1, 80, true);
1503  timerAttachInterrupt(s50usTimer, &IRReceiveTimerInterruptHandler, false); // false -> level interrupt, true -> edge interrupt, but this is not supported :-(
1504  timerAlarmWrite(s50usTimer, MICROS_PER_TICK, true);
1505 # endif
1506  }
1507  // every 50 us, autoreload = true
1508 }
1509 # endif
1510 
1511 
1512 uint8_t sLastSendPin = 0; // Avoid multiple attach() or if pin changes, detach before attach
1513 
1514 # if defined(SEND_PWM_BY_TIMER)
1515 void enableSendPWMByTimer() {
1516 # if ESP_ARDUINO_VERSION >= ESP_ARDUINO_VERSION_VAL(3, 0, 0)
1517 # if defined(IR_SEND_PIN)
1518  ledcWrite(IR_SEND_PIN, (IR_SEND_DUTY_CYCLE_PERCENT * 256) / 100); // 3.x API
1519 # else
1520  ledcWrite(IrSender.sendPin, (IR_SEND_DUTY_CYCLE_PERCENT * 256) / 100); // 3.x API
1521 # endif
1522 # else
1523  // ESP version < 3.0
1524  ledcWrite(SEND_LEDC_CHANNEL, (IR_SEND_DUTY_CYCLE_PERCENT * 256) / 100); // * 256 since we have 8 bit resolution
1525 # endif
1526 }
1527 void disableSendPWMByTimer() {
1528 # if ESP_ARDUINO_VERSION >= ESP_ARDUINO_VERSION_VAL(3, 0, 0)
1529 # if defined(IR_SEND_PIN)
1530  ledcWrite(IR_SEND_PIN, 0); // 3.x API
1531 # else
1532  ledcWrite(IrSender.sendPin, 0); // 3.x API
1533 # endif
1534 # else
1535  // ESP version < 3.0
1536  ledcWrite(SEND_LEDC_CHANNEL, 0);
1537 # endif
1538 }
1539 
1540 /*
1541  * timerConfigForSend() is used exclusively by IRsend::enableIROut() (or enableHighFrequencyIROut())
1542  * ledcWrite since ESP 2.0.2 does not work if pin mode is set.
1543  */
1544 void timerConfigForSend(uint16_t aFrequencyKHz) {
1545 # if ESP_ARDUINO_VERSION >= ESP_ARDUINO_VERSION_VAL(3, 0, 0)
1546 # if defined(IR_SEND_PIN)
1547  if(sLastSendPin == 0){
1548  ledcAttach(IR_SEND_PIN, aFrequencyKHz * 1000, 8); // 3.x API
1549  sLastSendPin = IR_SEND_PIN;
1550  }
1551 # else
1552  if(sLastSendPin != 0 && sLastSendPin != IrSender.sendPin){
1553  ledcDetach(IrSender.sendPin); // detach pin before new attaching see #1194
1554  }
1555  ledcAttach(IrSender.sendPin, aFrequencyKHz * 1000, 8); // 3.x API
1556  sLastSendPin = IrSender.sendPin;
1557 # endif
1558 # else
1559  // ESP version < 3.0
1560  ledcSetup(SEND_LEDC_CHANNEL, aFrequencyKHz * 1000, 8); // 8 bit PWM resolution
1561 # if defined(IR_SEND_PIN)
1562  ledcAttachPin(IR_SEND_PIN, SEND_LEDC_CHANNEL); // attach pin to channel
1563 # else
1564  if(sLastSendPin != 0 && sLastSendPin != IrSender.sendPin){
1565  ledcDetachPin(IrSender.sendPin); // detach pin before new attaching see #1194
1566  }
1567  ledcAttachPin(IrSender.sendPin, SEND_LEDC_CHANNEL); // attach pin to channel
1568  sLastSendPin = IrSender.sendPin;
1569 # endif
1570 # endif
1571 }
1572 # endif // defined(SEND_PWM_BY_TIMER)
1573 
1574 /***************************************
1575  * SAMD boards like DUE and Zero
1576  ***************************************/
1577 #elif defined(ARDUINO_ARCH_SAMD)
1578 # if defined(SEND_PWM_BY_TIMER)
1579 #error PWM generation by hardware is not yet implemented for SAMD
1580 # endif
1581 
1582 # if !defined(IR_SAMD_TIMER)
1583 # if defined(__SAMD51__)
1584 # if defined(TC5)
1585 #define IR_SAMD_TIMER TC5
1586 #define IR_SAMD_TIMER_IRQ TC5_IRQn
1587 # else
1588 #define IR_SAMD_TIMER TC3
1589 #define IR_SAMD_TIMER_IRQ TC3_IRQn
1590 # endif
1591 # else
1592 // SAMD21
1593 #define IR_SAMD_TIMER TC3
1594 #define IR_SAMD_TIMER_ID GCLK_CLKCTRL_ID_TCC2_TC3
1595 #define IR_SAMD_TIMER_IRQ TC3_IRQn
1596 # endif
1597 # endif
1598 
1600  NVIC_EnableIRQ (IR_SAMD_TIMER_IRQ);
1601 }
1603  NVIC_DisableIRQ (IR_SAMD_TIMER_IRQ); // or TC5->INTENCLR.bit.MC0 = 1; or TC5->COUNT16.CTRLA.reg &= ~TC_CTRLA_ENABLE;
1604 
1605 }
1606 // Undefine ISR, because we call the plain function IRReceiveTimerInterruptHandler()
1607 // The ISR is now TC3_Handler() or TC5_Handler() below
1608 # if defined(ISR)
1609 #undef ISR
1610 # endif
1611 
1620 void timerConfigForReceive() {
1621  TcCount16 *TC = (TcCount16*) IR_SAMD_TIMER;
1622 
1623 # if defined(__SAMD51__)
1624  // Enable the TC5 clock, use generic clock generator 0 (F_CPU) for TC5
1625 # if defined(TC5_GCLK_ID)
1626  GCLK->PCHCTRL[TC5_GCLK_ID].reg = GCLK_PCHCTRL_GEN_GCLK0_Val | (1 << GCLK_PCHCTRL_CHEN_Pos);
1627 # else
1628  GCLK->PCHCTRL[TC3_GCLK_ID].reg = GCLK_PCHCTRL_GEN_GCLK0_Val | (1 << GCLK_PCHCTRL_CHEN_Pos);
1629 # endif
1630 
1631  // The TC should be disabled before the TC is reset in order to avoid undefined behavior.
1632  TC->CTRLA.reg &= ~TC_CTRLA_ENABLE; // Disable the Timer
1633  while (TC->SYNCBUSY.bit.ENABLE)
1634  ; // Wait for disabled
1635  // Reset TCx
1636  TC->CTRLA.reg = TC_CTRLA_SWRST;
1637  // When writing a '1' to the CTRLA.SWRST bit it will immediately read as '1'.
1638  while (TC->SYNCBUSY.bit.SWRST)
1639  ; // CTRL.SWRST will be cleared by hardware when the peripheral has been reset.
1640 
1641  // SAMD51 has F_CPU = 120 MHz
1642  TC->CC[0].reg = ((MICROS_PER_TICK * (F_CPU / MICROS_IN_ONE_SECOND)) / 16) - 1; // (375 - 1);
1643 
1644  /*
1645  * Set timer counter mode to 16 bits, set mode as match frequency, prescaler is DIV16 => 7.5 MHz clock, start counter
1646  */
1647  TC->CTRLA.reg |= TC_CTRLA_MODE_COUNT16 | TC_WAVE_WAVEGEN_MFRQ | TC_CTRLA_PRESCALER_DIV16 | TC_CTRLA_ENABLE;
1648 // while (TC5->COUNT16.STATUS.bit.SYNCBUSY == 1); // The next commands do an implicit wait :-)
1649 # else
1650  // Enable GCLK and select GCLK0 (F_CPU) as clock for TC4 and TC5
1651  REG_GCLK_CLKCTRL = (uint16_t)(GCLK_CLKCTRL_CLKEN | GCLK_CLKCTRL_GEN_GCLK0 | IR_SAMD_TIMER_ID);
1652  while (GCLK->STATUS.bit.SYNCBUSY == 1)
1653  ;
1654 
1655  // The TC should be disabled before the TC is reset in order to avoid undefined behavior.
1656  TC->CTRLA.reg &= ~TC_CTRLA_ENABLE;
1657  // When write-synchronization is ongoing for a register, any subsequent write attempts to this register will be discarded, and an error will be reported.
1658  while (TC->STATUS.bit.SYNCBUSY == 1)
1659  ; // wait for sync to ensure that we can write again to COUNT16.CTRLA.reg
1660  // Reset TCx
1661  TC->CTRLA.reg = TC_CTRLA_SWRST;
1662  // When writing a 1 to the CTRLA.SWRST bit it will immediately read as 1.
1663  while (TC->CTRLA.bit.SWRST)
1664  ; // CTRL.SWRST will be cleared by hardware when the peripheral has been reset.
1665 
1666  // SAMD51 has F_CPU = 48 MHz
1667  TC->CC[0].reg = ((MICROS_PER_TICK * (F_CPU / MICROS_IN_ONE_SECOND)) / 16) - 1; // (150 - 1);
1668 
1669  /*
1670  * Set timer counter mode to 16 bits, set mode as match frequency, prescaler is DIV16 => 3 MHz clock, start counter
1671  */
1672  TC->CTRLA.reg |= TC_CTRLA_MODE_COUNT16 | TC_CTRLA_WAVEGEN_MFRQ | TC_CTRLA_PRESCALER_DIV16 | TC_CTRLA_ENABLE;
1673 
1674 # endif
1675  // Configure interrupt request
1676  NVIC_DisableIRQ (IR_SAMD_TIMER_IRQ);
1677  NVIC_ClearPendingIRQ(IR_SAMD_TIMER_IRQ);
1678  NVIC_SetPriority(IR_SAMD_TIMER_IRQ, 0);
1679  NVIC_EnableIRQ(IR_SAMD_TIMER_IRQ);
1680 
1681  // Enable the compare interrupt
1682  TC->INTENSET.bit.MC0 = 1;
1683 }
1684 
1685 # if !defined(DISABLE_CODE_FOR_RECEIVER)
1686 # if defined(__SAMD51__) && defined(TC5)
1687 void TC5_Handler(void)
1688 # else
1689 void TC3_Handler(void)
1690 # endif // defined(__SAMD51__)
1691 {
1692  TcCount16 *TC = (TcCount16*) IR_SAMD_TIMER;
1693  // Check for right interrupt bit
1694  if (TC->INTFLAG.bit.MC0 == 1) {
1695  // reset bit for next turn
1696  TC->INTFLAG.bit.MC0 = 1;
1698  }
1699 }
1700 # endif // !defined(DISABLE_CODE_FOR_RECEIVER)
1701 
1702 /***************************************
1703  * Mbed based boards
1704  ***************************************/
1705 #elif defined(ARDUINO_ARCH_MBED) // Arduino Nano 33 BLE + Sparkfun Apollo3 + Nano RP2040 Connect
1706 #include "mbed.h"
1707 mbed::Ticker s50usTimer;
1708 
1709 // Undefine ISR, because we register/call the plain function IRReceiveTimerInterruptHandler()
1710 # if defined(ISR)
1711 #undef ISR
1712 # endif
1713 
1715  s50usTimer.attach(IRReceiveTimerInterruptHandler, std::chrono::microseconds(MICROS_PER_TICK));
1716 }
1718  s50usTimer.detach();
1719 }
1720 
1721 void timerConfigForReceive() {
1722  s50usTimer.attach(IRReceiveTimerInterruptHandler, std::chrono::microseconds(MICROS_PER_TICK));
1723 }
1724 
1725 # if defined(SEND_PWM_BY_TIMER)
1726 #include "pins_arduino.h" // for digitalPinToPinName()
1727 
1728 # if defined(IR_SEND_PIN)
1729 mbed::PwmOut sPwmOutForSendPWM(digitalPinToPinName(IR_SEND_PIN));
1730 # else
1731 mbed::PwmOut sPwmOutForSendPWM(digitalPinToPinName(IrSender.sendPin));
1732 # endif
1733 uint8_t sIROutPuseWidth;
1734 
1735 void enableSendPWMByTimer() {
1736  sPwmOutForSendPWM.pulsewidth_us(sIROutPuseWidth);
1737 }
1738 //void enableSendPWMByTimer() { sPwmOutForSendPWM.resume(); sPwmOutForSendPWM.pulsewidth_us(sIROutPuseWidth);}
1739 //void disableSendPWMByTimer() { sPwmOutForSendPWM.suspend();} // this kills pulsewidth_us value and does not set output level to LOW
1740 
1741 void disableSendPWMByTimer() {
1742  sPwmOutForSendPWM.pulsewidth_us(0); // this also sets output level to LOW :-)
1743 }
1744 
1745 /*
1746  * timerConfigForSend() is used exclusively by IRsend::enableIROut()
1747  * Set output pin mode and disable receive interrupt if it uses the same resource
1748  */
1749 void timerConfigForSend(uint16_t aFrequencyKHz) {
1750  sPwmOutForSendPWM.period_us(1000 / aFrequencyKHz); // 26.315 for 38 kHz
1751  sIROutPuseWidth = (1000 * IR_SEND_DUTY_CYCLE_PERCENT) / (aFrequencyKHz * 100);
1752 }
1753 # endif // defined(SEND_PWM_BY_TIMER)
1754 
1755 /*************************************************************************************************************************************
1756  * RP2040 based boards for pico core
1757  * https://github.com/earlephilhower/arduino-pico
1758  * https://github.com/earlephilhower/arduino-pico/releases/download/global/package_rp2040_index.json
1759  * Can use any pin for PWM, no timer restrictions
1760  *************************************************************************************************************************************/
1761 #elif defined(ARDUINO_ARCH_RP2040) // Raspberry Pi Pico, Adafruit Feather RP2040, etc.
1762 #include "pico/time.h"
1763 
1764 repeating_timer_t s50usTimer;
1765 
1766 // Undefine ISR, because we register/call the plain function IRReceiveTimerInterruptHandler()
1767 # if defined(ISR)
1768 #undef ISR
1769 # endif
1770 
1771 // The timer callback has a parameter and a return value
1772 bool IRTimerInterruptHandlerHelper(repeating_timer_t*) {
1774  return true;
1775 }
1776 
1778  add_repeating_timer_us(-(MICROS_PER_TICK), IRTimerInterruptHandlerHelper, nullptr, &s50usTimer);
1779 }
1781  cancel_repeating_timer(&s50usTimer);
1782 }
1783 
1784 void timerConfigForReceive() {
1785  // no need for initializing timer at setup()
1786 }
1787 
1788 # if defined(SEND_PWM_BY_TIMER)
1789 #include "hardware/pwm.h"
1790 
1791 uint sSliceNumberForSendPWM;
1792 uint sChannelNumberForSendPWM;
1793 uint sIROutPuseWidth;
1794 
1795 /*
1796  * If we just disable the PWM, the counter stops and the output stays at the state is currently has
1797  */
1798 void enableSendPWMByTimer() {
1799  pwm_set_counter(sSliceNumberForSendPWM, 0);
1800  pwm_set_chan_level(sSliceNumberForSendPWM, sChannelNumberForSendPWM, sIROutPuseWidth);
1801 }
1802 void disableSendPWMByTimer() {
1803  pwm_set_chan_level(sSliceNumberForSendPWM, sChannelNumberForSendPWM, 0); // this sets output also to LOW
1804 }
1805 
1806 /*
1807  * timerConfigForSend() is used exclusively by IRsend::enableIROut()
1808  * Set output pin mode and disable receive interrupt if it uses the same resource
1809  */
1810 void timerConfigForSend(uint16_t aFrequencyKHz) {
1811 # if defined(IR_SEND_PIN)
1812  gpio_set_function(IR_SEND_PIN, GPIO_FUNC_PWM);
1813  // Find out which PWM slice is connected to IR_SEND_PIN
1814  sSliceNumberForSendPWM = pwm_gpio_to_slice_num(IR_SEND_PIN);
1815  sChannelNumberForSendPWM = pwm_gpio_to_channel(IR_SEND_PIN);
1816 # else
1817  gpio_set_function(IrSender.sendPin, GPIO_FUNC_PWM);
1818  // Find out which PWM slice is connected to IR_SEND_PIN
1819  sSliceNumberForSendPWM = pwm_gpio_to_slice_num(IrSender.sendPin);
1820  sChannelNumberForSendPWM = pwm_gpio_to_channel(IrSender.sendPin);
1821 # endif
1822  uint16_t tPWMWrapValue = (clock_get_hz(clk_sys)) / (aFrequencyKHz * 1000); // 3289.473 for 38 kHz @125 MHz clock. We have a 16 bit counter and use system clock (125 MHz)
1823 
1824  pwm_config tPWMConfig = pwm_get_default_config();
1825  pwm_config_set_wrap(&tPWMConfig, tPWMWrapValue - 1);
1826  pwm_init(sSliceNumberForSendPWM, &tPWMConfig, false); // we do not want to send now
1827  sIROutPuseWidth = ((tPWMWrapValue * IR_SEND_DUTY_CYCLE_PERCENT) / 100) - 1; // 985.84 for 38 kHz
1828  pwm_set_chan_level(sSliceNumberForSendPWM, sChannelNumberForSendPWM, 0);
1829  pwm_set_enabled(sSliceNumberForSendPWM, true);
1830 }
1831 # endif // defined(SEND_PWM_BY_TIMER)
1832 
1833 /***************************************
1834  * NRF5 boards like the BBC:Micro
1835  ***************************************/
1836 #elif defined(NRF5) || defined(ARDUINO_ARCH_NRF52840) || defined(ARDUINO_ARCH_NRF52)
1837 # if defined(SEND_PWM_BY_TIMER)
1838 #error PWM generation by hardware not implemented for NRF5
1839 # endif
1840 
1842  NVIC_EnableIRQ (TIMER2_IRQn);
1843 }
1845  NVIC_DisableIRQ (TIMER2_IRQn);
1846 }
1847 
1848 // Undefine ISR, because we call the plain function IRReceiveTimerInterruptHandler()
1849 # if defined(ISR)
1850 #undef ISR
1851 # endif
1852 
1853 void timerConfigForReceive() {
1854  NRF_TIMER2->MODE = TIMER_MODE_MODE_Timer; // Set the timer in Timer Mode
1855  NRF_TIMER2->TASKS_CLEAR = 1; // clear the task first to be usable for later
1856  NRF_TIMER2->PRESCALER = 4; // f TIMER = 16 MHz / (2 ^ PRESCALER ) : 4 -> 1 MHz, 1 uS
1857  NRF_TIMER2->BITMODE = TIMER_BITMODE_BITMODE_16Bit; //Set counter to 16 bit resolution
1858  NRF_TIMER2->CC[0] = MICROS_PER_TICK; //Set value for TIMER2 compare register 0, to trigger every 50 uS
1859  NRF_TIMER2->CC[1] = 0; //Set value for TIMER2 compare register 1
1860 
1861  // Enable interrupt on Timer 2, for CC[0] compare match events
1862  NRF_TIMER2->INTENSET = (TIMER_INTENSET_COMPARE0_Enabled << TIMER_INTENSET_COMPARE0_Pos);
1863  NRF_TIMER2->TASKS_START = 1; // Start TIMER2
1864 
1865  // timerAttachInterrupt(timer, &IRTimerInterruptHandler, 1);
1866 }
1867 
1868 #if !defined(DISABLE_CODE_FOR_RECEIVER)
1869 
1872 extern "C" {
1873 void TIMER2_IRQHandler(void) {
1874  // Interrupt Service Routine - Fires every 50uS
1875  if ((NRF_TIMER2->EVENTS_COMPARE[0] != 0) && ((NRF_TIMER2->INTENSET & TIMER_INTENSET_COMPARE0_Msk) != 0)) {
1876  NRF_TIMER2->EVENTS_COMPARE[0] = 0; //Clear compare register 0 event
1877  IRReceiveTimerInterruptHandler(); // call the IR-receive function
1878  NRF_TIMER2->CC[0] += 50;
1879  }
1880 }
1881 }
1882 #endif
1883 
1884 /**********************************************************************************************************************
1885  * BluePill in 2 flavors see https://samuelpinches.com.au/3d-printer/cutting-through-some-confusion-on-stm32-and-arduino/
1886  *
1887  * Recommended original Arduino_STM32 by Roger Clark.
1888  * http://dan.drown.org/stm32duino/package_STM32duino_index.json
1889  * STM32F1 architecture for "Generic STM32F103C series" from "STM32F1 Boards (Arduino_STM32)" of Arduino Board manager
1890  **********************************************************************************************************************/
1891 #elif defined(__STM32F1__) || defined(ARDUINO_ARCH_STM32F1)
1892 #include <HardwareTimer.h> // 4 timers and 4. timer (4.channel) is used for tone()
1893 # if defined(SEND_PWM_BY_TIMER)
1894 #error PWM generation by hardware not implemented for STM32
1895 # endif
1896 
1897 /*
1898  * Use timer 3 as IR timer.
1899  * Timer 3 blocks PA6, PA7, PB0, PB1, so if you require one of them as tone() or Servo output, you must choose another timer.
1900  */
1901 HardwareTimer s50usTimer(3);
1902 
1904  s50usTimer.resume();
1905 }
1907  s50usTimer.pause();
1908 }
1909 
1910 // Undefine ISR, because we register/call the plain function IRReceiveTimerInterruptHandler()
1911 # if defined(ISR)
1912 #undef ISR
1913 # endif
1914 
1915 void timerConfigForReceive() {
1916  s50usTimer.setMode(TIMER_CH1, TIMER_OUTPUT_COMPARE);
1917  s50usTimer.setPrescaleFactor(1);
1918  s50usTimer.setOverflow((F_CPU / MICROS_IN_ONE_SECOND) * MICROS_PER_TICK);
1919  s50usTimer.attachInterrupt(TIMER_CH1, IRReceiveTimerInterruptHandler);
1920  s50usTimer.refresh();
1921 }
1922 
1923 /**********************************************************************************************************************
1924  * STM32duino by ST Microsystems.
1925  * https://github.com/stm32duino/Arduino_Core_STM32
1926  * https://github.com/stm32duino/BoardManagerFiles/raw/master/STM32/package_stm_index.json
1927  * stm32 architecture for "Generic STM32F1 series" from "STM32 Boards (selected from submenu)" of Arduino Board manager
1928  **********************************************************************************************************************/
1929 #elif defined(STM32F1xx) || defined(ARDUINO_ARCH_STM32)
1930 #include <HardwareTimer.h> // 4 timers and 3. timer is used for tone(), 2. for Servo
1931 # if defined(SEND_PWM_BY_TIMER)
1932 #error PWM generation by hardware not implemented for STM32
1933 # endif
1934 
1935 /*
1936  * Use timer 4 as IR timer.
1937  * Timer 4 blocks PB6, PB7, PB8, PB9, so if you need one them as tone() or Servo output, you must choose another timer.
1938  */
1939 # if defined(TIM4)
1940 HardwareTimer s50usTimer(TIM4);
1941 # else
1942 HardwareTimer s50usTimer(TIM2);
1943 # endif
1944 
1946  s50usTimer.resume();
1947 }
1949  s50usTimer.pause();
1950 }
1951 
1952 // Undefine ISR, because we register/call the plain function IRReceiveTimerInterruptHandler()
1953 # if defined(ISR)
1954 #undef ISR
1955 # endif
1956 
1957 void timerConfigForReceive() {
1958  s50usTimer.setOverflow(MICROS_PER_TICK, MICROSEC_FORMAT); // 50 uS
1959  s50usTimer.attachInterrupt(IRReceiveTimerInterruptHandler);
1960  s50usTimer.resume();
1961 }
1962 
1963 /***************************************
1964  * Particle special IntervalTimer
1965  * !!!UNTESTED!!!
1966  ***************************************/
1967 #elif defined(PARTICLE)
1968 # ifndef __INTERVALTIMER_H__
1969 #include "SparkIntervalTimer.h" // SparkIntervalTimer.h is required if PARTICLE is defined.
1970 # endif
1971 
1972 extern IntervalTimer timer;
1973 extern int ir_out_kHz;
1974 
1976  timer.begin(IRReceiveTimerInterruptHandler, MICROS_PER_TICK, uSec);
1977 }
1979  timer.end();
1980 }
1981 
1982 // Undefine ISR, because we register/call the plain function IRReceiveTimerInterruptHandler()
1983 # if defined(ISR)
1984 #undef ISR
1985 # endif
1986 
1987 void timerConfigForReceive() {
1988 }
1989 
1990 # if defined(SEND_PWM_BY_TIMER)
1991 # if defined(IR_SEND_PIN)
1992 void enableSendPWMByTimer() {
1993  analogWrite(IR_SEND_PIN, ((256L * 100) / IR_SEND_DUTY_CYCLE_PERCENT)), ir_out_kHz*1000);
1994 }
1995 void disableSendPWMByTimer() {
1996  analogWrite(IR_SEND_PIN, 0, ir_out_kHz*1000);
1997 }
1998 # else
1999 void enableSendPWMByTimer() {
2000  analogWrite(IrSender.sendPin, ((256L * 100) / IR_SEND_DUTY_CYCLE_PERCENT), ir_out_kHz * 1000);
2001 }
2002 void disableSendPWMByTimer() {
2003  analogWrite(IrSender.sendPin, 0, ir_out_kHz * 1000);
2004 }
2005 # endif
2006 
2007 
2008 /*
2009  * timerConfigForSend() is used exclusively by IRsend::enableIROut()
2010  * Set output pin mode and disable receive interrupt if it uses the same resource
2011  */
2012 void timerConfigForSend(uint16_t aFrequencyKHz) {
2014 # if defined(IR_SEND_PIN)
2015  pinMode(IR_SEND_PIN, OUTPUT);
2016 # else
2017  pinMode(IrSender.sendPin, OUTPUT);
2018 # endif
2019  ir_out_kHz = aFrequencyKHz;
2020 }
2021 # endif // defined(SEND_PWM_BY_TIMER)
2022 
2023 /***************************************
2024  * Unknown CPU board
2025  ***************************************/
2026 #else
2027 #error Internal code configuration error, no timer functions implemented for this CPU / board
2028 /*
2029  * Dummy definitions to avoid more irritating compile errors
2030  */
2031 
2032 void timerEnableReceiveInterrupt() {};
2034 
2035 # if defined(ISR)
2036 #undef ISR
2037 # endif
2038 #define ISR() void notImplemented(void)
2039 
2040 void timerConfigForReceive() {
2041 }
2042 
2043 # if defined(SEND_PWM_BY_TIMER)
2044 void enableSendPWMByTimer() {
2045 }
2046 void disableSendPWMByTimer() {
2047 }
2048 
2049 void timerConfigForSend(uint16_t aFrequencyKHz) {
2051 # if defined(IR_SEND_PIN)
2052  pinMode(IR_SEND_PIN, OUTPUT);
2053 # else
2054  pinMode(IrSender.sendPin, OUTPUT);
2055 # endif
2056  (void) aFrequencyKHz;
2057 }
2058 # endif // defined(SEND_PWM_BY_TIMER)
2059 
2060 #endif // defined(DOXYGEN / CPU_TYPES)
2061 
2064 #endif // _IR_TIMER_HPP
timerConfigForReceive
void timerConfigForReceive()
Configures the timer to be able to generate the receive sample interrupt, which consumes a small amou...
Definition: IRTimer.hpp:105
MICROS_PER_TICK
#define MICROS_PER_TICK
microseconds per clock interrupt tick
Definition: IRremote.hpp:250
IRsend::sendPin
uint8_t sendPin
Definition: IRremoteInt.h:681
IR_SEND_PIN
#define IR_SEND_PIN
Hardware / timer dependent pin number for sending IR if SEND_PWM_BY_TIMER is defined.
Definition: IRTimer.hpp:97
timerDisableReceiveInterrupt
void timerDisableReceiveInterrupt()
Disables the receive sample timer interrupt.
Definition: IRTimer.hpp:117
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
IRReceiveTimerInterruptHandler
void IRReceiveTimerInterruptHandler()
Definition: IRReceive.hpp:125
MICROS_IN_ONE_SECOND
#define MICROS_IN_ONE_SECOND
Definition: IRremote.hpp:254
timerResetInterruptPending
void timerResetInterruptPending()
timerEnableReceiveInterrupt
void timerEnableReceiveInterrupt()
Enables the receive sample timer interrupt, which consumes a small amount of CPU every 50 us.
Definition: IRTimer.hpp:110
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
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