23 #if defined(ARDUINO) && (ARDUINO >= 100)
26 # if !defined(IRPRONTO)
27 # include <WProgram.h>
37 # define EXTERN extern
43 #define RAWBUF 101 // Maximum length of raw duration buffer
64 #define STATE_OVERFLOW 6
75 #if defined(CORE_LED0_PIN)
76 # define BLINKLED CORE_LED0_PIN
77 # define BLINKLED_ON() (digitalWrite(CORE_LED0_PIN, HIGH))
78 # define BLINKLED_OFF() (digitalWrite(CORE_LED0_PIN, LOW))
80 #elif defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__)
82 # define BLINKLED_ON() (PORTB |= B10000000)
83 # define BLINKLED_OFF() (PORTB &= B01111111)
85 #elif defined(__AVR_ATmega644P__) || defined(__AVR_ATmega644__)
87 # define BLINKLED_ON() (PORTD |= B00000001)
88 # define BLINKLED_OFF() (PORTD &= B11111110)
92 #define BLINKLED_ON() (PORTB |= B00100000)
93 # define BLINKLED_OFF() (PORTB &= B11011111)
100 # define SYSCLOCK F_CPU // main Arduino clock
102 # define SYSCLOCK 16000000 // main Arduino clock
109 # define cbi(sfr, bit) (_SFR_BYTE(sfr) &= ~_BV(bit))
113 # define sbi(sfr, bit) (_SFR_BYTE(sfr) |= _BV(bit))
124 #define MARK_EXCESS 100
127 #define USECPERTICK 50
131 #define LTOL (1.0 - (TOLERANCE/100.))
132 #define UTOL (1.0 + (TOLERANCE/100.))
136 #define GAP_TICKS (_GAP/USECPERTICK)
138 #define TICKS_LOW(us) ((int)(((us)*LTOL/USECPERTICK)))
139 #define TICKS_HIGH(us) ((int)(((us)*UTOL/USECPERTICK + 1)))
156 #if defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__)
158 #define IR_USE_TIMER2 // tx = pin 9
164 #elif defined(__AVR_AT90USB162__)
165 #define IR_USE_TIMER1 // tx = pin 17
168 #elif defined(__AVR_ATmega32U4__)
173 #define IR_SEND_TIMER4_HS // tx = pin 10
176 #define IR_USE_TIMER1 // tx = pin 9
182 #elif defined(__MK20DX128__) || defined(__MK20DX256__)
183 #define IR_USE_TIMER_CMT // tx = pin 5
186 #elif defined(__MKL26Z64__)
187 #define IR_USE_TIMER_TPM1 // tx = pin 16
190 #elif defined(__AVR_AT90USB646__) || defined(__AVR_AT90USB1286__)
192 #define IR_USE_TIMER2 // tx = pin 1
196 #elif defined(__AVR_ATmega644P__) || defined(__AVR_ATmega644__)
198 #define IR_USE_TIMER2 // tx = pin 14
201 #elif defined(__AVR_ATmega8P__) || defined(__AVR_ATmega8__)
202 #define IR_USE_TIMER1 // tx = pin 9
205 #elif defined(__AVR_ATtiny84__)
206 #define IR_USE_TIMER1 // tx = pin 6
209 #elif defined(__AVR_ATtiny85__)
210 #define IR_USE_TIMER_TINY0 // tx = pin 1
215 #define IR_USE_TIMER2 // tx = pin 3
225 #if defined(IR_USE_TIMER2)
228 #define TIMER_ENABLE_PWM (TCCR2A |= _BV(COM2B1))
229 #define TIMER_DISABLE_PWM (TCCR2A &= ~(_BV(COM2B1)))
230 #define TIMER_ENABLE_INTR (TIMSK2 = _BV(OCIE2A))
231 #define TIMER_DISABLE_INTR (TIMSK2 = 0)
232 #define TIMER_INTR_NAME TIMER2_COMPA_vect
234 #define TIMER_CONFIG_KHZ(val) ({ \
235 const uint8_t pwmval = SYSCLOCK / 2000 / (val); \
236 TCCR2A = _BV(WGM20); \
237 TCCR2B = _BV(WGM22) | _BV(CS20); \
239 OCR2B = pwmval / 3; \
242 #define TIMER_COUNT_TOP (SYSCLOCK * USECPERTICK / 1000000)
245 #if (TIMER_COUNT_TOP < 256)
246 # define TIMER_CONFIG_NORMAL() ({ \
247 TCCR2A = _BV(WGM21); \
248 TCCR2B = _BV(CS20); \
249 OCR2A = TIMER_COUNT_TOP; \
253 # define TIMER_CONFIG_NORMAL() ({ \
254 TCCR2A = _BV(WGM21); \
255 TCCR2B = _BV(CS21); \
256 OCR2A = TIMER_COUNT_TOP / 8; \
262 #if defined(CORE_OC2B_PIN)
263 # define TIMER_PWM_PIN CORE_OC2B_PIN // Teensy
264 #elif defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__)
265 # define TIMER_PWM_PIN 9 // Arduino Mega
266 #elif defined(__AVR_ATmega644P__) || defined(__AVR_ATmega644__)
267 # define TIMER_PWM_PIN 14 // Sanguino
269 # define TIMER_PWM_PIN 3 // Arduino Duemilanove, Diecimila, LilyPad, etc
275 #elif defined(IR_USE_TIMER1)
278 #define TIMER_ENABLE_PWM (TCCR1A |= _BV(COM1A1))
279 #define TIMER_DISABLE_PWM (TCCR1A &= ~(_BV(COM1A1)))
282 #if defined(__AVR_ATmega8P__) || defined(__AVR_ATmega8__)
283 # define TIMER_ENABLE_INTR (TIMSK |= _BV(OCIE1A))
284 # define TIMER_DISABLE_INTR (TIMSK &= ~_BV(OCIE1A))
286 # define TIMER_ENABLE_INTR (TIMSK1 = _BV(OCIE1A))
287 # define TIMER_DISABLE_INTR (TIMSK1 = 0)
291 #define TIMER_INTR_NAME TIMER1_COMPA_vect
293 #define TIMER_CONFIG_KHZ(val) ({ \
294 const uint16_t pwmval = SYSCLOCK / 2000 / (val); \
295 TCCR1A = _BV(WGM11); \
296 TCCR1B = _BV(WGM13) | _BV(CS10); \
298 OCR1A = pwmval / 3; \
301 #define TIMER_CONFIG_NORMAL() ({ \
303 TCCR1B = _BV(WGM12) | _BV(CS10); \
304 OCR1A = SYSCLOCK * USECPERTICK / 1000000; \
309 #if defined(CORE_OC1A_PIN)
310 # define TIMER_PWM_PIN CORE_OC1A_PIN // Teensy
311 #elif defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__)
312 # define TIMER_PWM_PIN 11 // Arduino Mega
313 #elif defined(__AVR_ATmega644P__) || defined(__AVR_ATmega644__)
314 # define TIMER_PWM_PIN 13 // Sanguino
315 #elif defined(__AVR_ATtiny84__)
316 # define TIMER_PWM_PIN 6
318 # define TIMER_PWM_PIN 9 // Arduino Duemilanove, Diecimila, LilyPad, etc
324 #elif defined(IR_USE_TIMER3)
327 #define TIMER_ENABLE_PWM (TCCR3A |= _BV(COM3A1))
328 #define TIMER_DISABLE_PWM (TCCR3A &= ~(_BV(COM3A1)))
329 #define TIMER_ENABLE_INTR (TIMSK3 = _BV(OCIE3A))
330 #define TIMER_DISABLE_INTR (TIMSK3 = 0)
331 #define TIMER_INTR_NAME TIMER3_COMPA_vect
333 #define TIMER_CONFIG_KHZ(val) ({ \
334 const uint16_t pwmval = SYSCLOCK / 2000 / (val); \
335 TCCR3A = _BV(WGM31); \
336 TCCR3B = _BV(WGM33) | _BV(CS30); \
338 OCR3A = pwmval / 3; \
341 #define TIMER_CONFIG_NORMAL() ({ \
343 TCCR3B = _BV(WGM32) | _BV(CS30); \
344 OCR3A = SYSCLOCK * USECPERTICK / 1000000; \
349 #if defined(CORE_OC3A_PIN)
350 # define TIMER_PWM_PIN CORE_OC3A_PIN // Teensy
351 #elif defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__)
352 # define TIMER_PWM_PIN 5 // Arduino Mega
354 # error "Please add OC3A pin number here\n"
360 #elif defined(IR_USE_TIMER4_HS)
363 #define TIMER_ENABLE_PWM (TCCR4A |= _BV(COM4A1))
364 #define TIMER_DISABLE_PWM (TCCR4A &= ~(_BV(COM4A1)))
365 #define TIMER_ENABLE_INTR (TIMSK4 = _BV(TOIE4))
366 #define TIMER_DISABLE_INTR (TIMSK4 = 0)
367 #define TIMER_INTR_NAME TIMER4_OVF_vect
369 #define TIMER_CONFIG_KHZ(val) ({ \
370 const uint16_t pwmval = SYSCLOCK / 2000 / (val); \
371 TCCR4A = (1<<PWM4A); \
372 TCCR4B = _BV(CS40); \
374 TCCR4D = (1<<WGM40); \
376 TC4H = pwmval >> 8; \
378 TC4H = (pwmval / 3) >> 8; \
379 OCR4A = (pwmval / 3) & 255; \
382 #define TIMER_CONFIG_NORMAL() ({ \
384 TCCR4B = _BV(CS40); \
388 TC4H = (SYSCLOCK * USECPERTICK / 1000000) >> 8; \
389 OCR4C = (SYSCLOCK * USECPERTICK / 1000000) & 255; \
395 #if defined(CORE_OC4A_PIN)
396 # define TIMER_PWM_PIN CORE_OC4A_PIN // Teensy
397 #elif defined(__AVR_ATmega32U4__)
398 # define TIMER_PWM_PIN 13 // Leonardo
400 # error "Please add OC4A pin number here\n"
406 #elif defined(IR_USE_TIMER4)
409 #define TIMER_ENABLE_PWM (TCCR4A |= _BV(COM4A1))
410 #define TIMER_DISABLE_PWM (TCCR4A &= ~(_BV(COM4A1)))
411 #define TIMER_ENABLE_INTR (TIMSK4 = _BV(OCIE4A))
412 #define TIMER_DISABLE_INTR (TIMSK4 = 0)
413 #define TIMER_INTR_NAME TIMER4_COMPA_vect
415 #define TIMER_CONFIG_KHZ(val) ({ \
416 const uint16_t pwmval = SYSCLOCK / 2000 / (val); \
417 TCCR4A = _BV(WGM41); \
418 TCCR4B = _BV(WGM43) | _BV(CS40); \
420 OCR4A = pwmval / 3; \
423 #define TIMER_CONFIG_NORMAL() ({ \
425 TCCR4B = _BV(WGM42) | _BV(CS40); \
426 OCR4A = SYSCLOCK * USECPERTICK / 1000000; \
431 #if defined(CORE_OC4A_PIN)
432 # define TIMER_PWM_PIN CORE_OC4A_PIN
433 #elif defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__)
434 # define TIMER_PWM_PIN 6 // Arduino Mega
436 # error "Please add OC4A pin number here\n"
442 #elif defined(IR_USE_TIMER5)
445 #define TIMER_ENABLE_PWM (TCCR5A |= _BV(COM5A1))
446 #define TIMER_DISABLE_PWM (TCCR5A &= ~(_BV(COM5A1)))
447 #define TIMER_ENABLE_INTR (TIMSK5 = _BV(OCIE5A))
448 #define TIMER_DISABLE_INTR (TIMSK5 = 0)
449 #define TIMER_INTR_NAME TIMER5_COMPA_vect
451 #define TIMER_CONFIG_KHZ(val) ({ \
452 const uint16_t pwmval = SYSCLOCK / 2000 / (val); \
453 TCCR5A = _BV(WGM51); \
454 TCCR5B = _BV(WGM53) | _BV(CS50); \
456 OCR5A = pwmval / 3; \
459 #define TIMER_CONFIG_NORMAL() ({ \
461 TCCR5B = _BV(WGM52) | _BV(CS50); \
462 OCR5A = SYSCLOCK * USECPERTICK / 1000000; \
467 #if defined(CORE_OC5A_PIN)
468 # define TIMER_PWM_PIN CORE_OC5A_PIN
469 #elif defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__)
470 # define TIMER_PWM_PIN 46 // Arduino Mega
472 # error "Please add OC5A pin number here\n"
478 #elif defined(IR_USE_TIMER_CMT)
480 #define TIMER_RESET ({ \
481 uint8_t tmp = CMT_MSC; \
485 #define TIMER_ENABLE_PWM do { \
486 CORE_PIN5_CONFIG = PORT_PCR_MUX(2) | PORT_PCR_DSE | PORT_PCR_SRE; \
489 #define TIMER_DISABLE_PWM do { \
490 CORE_PIN5_CONFIG = PORT_PCR_MUX(1) | PORT_PCR_DSE | PORT_PCR_SRE; \
493 #define TIMER_ENABLE_INTR NVIC_ENABLE_IRQ(IRQ_CMT)
494 #define TIMER_DISABLE_INTR NVIC_DISABLE_IRQ(IRQ_CMT)
495 #define TIMER_INTR_NAME cmt_isr
501 #define ISR(f) void f(void)
504 #if (F_BUS == 48000000)
505 # define CMT_PPS_VAL 5
507 # define CMT_PPS_VAL 2
511 #define TIMER_CONFIG_KHZ(val) ({ \
512 SIM_SCGC4 |= SIM_SCGC4_CMT; \
513 SIM_SOPT2 |= SIM_SOPT2_PTD7PAD; \
514 CMT_PPS = CMT_PPS_VAL; \
515 CMT_CGH1 = 2667 / val; \
516 CMT_CGL1 = 5333 / val; \
525 #define TIMER_CONFIG_NORMAL() ({ \
526 SIM_SCGC4 |= SIM_SCGC4_CMT; \
527 CMT_PPS = CMT_PPS_VAL; \
538 #define TIMER_PWM_PIN 5
541 #elif defined(IR_USE_TIMER_TPM1)
542 #define TIMER_RESET FTM1_SC |= FTM_SC_TOF;
543 #define TIMER_ENABLE_PWM CORE_PIN16_CONFIG = PORT_PCR_MUX(3)|PORT_PCR_DSE|PORT_PCR_SRE
544 #define TIMER_DISABLE_PWM CORE_PIN16_CONFIG = PORT_PCR_MUX(1)|PORT_PCR_SRE
545 #define TIMER_ENABLE_INTR NVIC_ENABLE_IRQ(IRQ_FTM1)
546 #define TIMER_DISABLE_INTR NVIC_DISABLE_IRQ(IRQ_FTM1)
547 #define TIMER_INTR_NAME ftm1_isr
551 #define ISR(f) void f(void)
552 #define TIMER_CONFIG_KHZ(val) ({ \
553 SIM_SCGC6 |= SIM_SCGC6_TPM1; \
556 FTM1_MOD = (F_PLL/2000) / val - 1; \
557 FTM1_C0V = (F_PLL/6000) / val - 1; \
558 FTM1_SC = FTM_SC_CLKS(1) | FTM_SC_PS(0); \
560 #define TIMER_CONFIG_NORMAL() ({ \
561 SIM_SCGC6 |= SIM_SCGC6_TPM1; \
564 FTM1_MOD = (F_PLL/40000) - 1; \
566 FTM1_SC = FTM_SC_CLKS(1) | FTM_SC_PS(0) | FTM_SC_TOF | FTM_SC_TOIE; \
568 #define TIMER_PWM_PIN 16
571 #elif defined(IR_USE_TIMER_TINY0)
573 #define TIMER_ENABLE_PWM (TCCR0A |= _BV(COM0B1))
574 #define TIMER_DISABLE_PWM (TCCR0A &= ~(_BV(COM0B1)))
575 #define TIMER_ENABLE_INTR (TIMSK |= _BV(OCIE0A))
576 #define TIMER_DISABLE_INTR (TIMSK &= ~(_BV(OCIE0A)))
577 #define TIMER_INTR_NAME TIMER0_COMPA_vect
578 #define TIMER_CONFIG_KHZ(val) ({ \
579 const uint8_t pwmval = SYSCLOCK / 2000 / (val); \
580 TCCR0A = _BV(WGM00); \
581 TCCR0B = _BV(WGM02) | _BV(CS00); \
583 OCR0B = pwmval / 3; \
585 #define TIMER_COUNT_TOP (SYSCLOCK * USECPERTICK / 1000000)
586 #if (TIMER_COUNT_TOP < 256)
587 #define TIMER_CONFIG_NORMAL() ({ \
588 TCCR0A = _BV(WGM01); \
589 TCCR0B = _BV(CS00); \
590 OCR0A = TIMER_COUNT_TOP; \
594 #define TIMER_CONFIG_NORMAL() ({ \
595 TCCR0A = _BV(WGM01); \
596 TCCR0B = _BV(CS01); \
597 OCR0A = TIMER_COUNT_TOP / 8; \
602 #define TIMER_PWM_PIN 1
608 # error "Internal code configuration error, no known IR_USE_TIMER# defined\n"
EXTERN volatile irparams_t irparams