timer02.c 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159
  1. //timer02.c
  2. // use atmega timer2 as main system timer instead of timer0
  3. // timer0 is used for fast pwm (OC0B output)
  4. // original OVF handler is disabled
  5. #include <avr/io.h>
  6. #include <avr/interrupt.h>
  7. #include "Arduino.h"
  8. #include "io_atmega2560.h"
  9. #define BEEPER 84
  10. uint8_t timer02_pwm0 = 0;
  11. void timer02_set_pwm0(uint8_t pwm0)
  12. {
  13. TCCR0A |= (2 << COM0B0); //switch OC0B to OCR mode
  14. OCR0B = (uint16_t)OCR0A * pwm0 / 255;
  15. timer02_pwm0 = pwm0;
  16. }
  17. void timer02_init(void)
  18. {
  19. //save sreg
  20. uint8_t _sreg = SREG;
  21. //disable interrupts for sure
  22. cli();
  23. //mask timer0 interrupts - disable all
  24. TIMSK0 &= ~(1<<TOIE0);
  25. TIMSK0 &= ~(1<<OCIE0A);
  26. TIMSK0 &= ~(1<<OCIE0B);
  27. //setup timer0
  28. TCCR0A = 0x00; //COM_A-B=00, WGM_0-1=00
  29. OCR0A = 200; //max PWM value (freq = 40kHz)
  30. OCR0B = 0; //current PWM value
  31. //switch timer0 to mode 5 (Phase Correct PWM)
  32. TCCR0A |= (1 << WGM00); //WGM_0-1=01
  33. TCCR0B = (1 << CS00) | (1 << WGM02); //WGM_2=1, CS_0-2=001 (no prescaling)
  34. TCCR0A |= (2 << COM0B0); //switch OC0B to OCR mode
  35. //setup timer2
  36. TCCR2A = 0x00; //COM_A-B=00, WGM_0-1=00
  37. TCCR2B = (4 << CS20); //WGM_2=0, CS_0-2=011
  38. //mask timer2 interrupts - enable OVF, disable others
  39. TIMSK2 |= (1<<TOIE2);
  40. TIMSK2 &= ~(1<<OCIE2A);
  41. TIMSK2 &= ~(1<<OCIE2B);
  42. //set timer2 OCR registers (OCRB interrupt generated 0.5ms after OVF interrupt)
  43. OCR2A = 0;
  44. OCR2B = 128;
  45. //restore sreg (enable interrupts)
  46. SREG = _sreg;
  47. }
  48. //following code is OVF handler for timer 2
  49. //it is copy-paste from wiring.c and modified for timer2
  50. //variables timer0_overflow_count and timer0_millis are declared in wiring.c
  51. // the prescaler is set so that timer0 ticks every 64 clock cycles, and the
  52. // the overflow handler is called every 256 ticks.
  53. #define MICROSECONDS_PER_TIMER0_OVERFLOW (clockCyclesToMicroseconds(64 * 256))
  54. // the whole number of milliseconds per timer0 overflow
  55. #define MILLIS_INC (MICROSECONDS_PER_TIMER0_OVERFLOW / 1000)
  56. // the fractional number of milliseconds per timer0 overflow. we shift right
  57. // by three to fit these numbers into a byte. (for the clock speeds we care
  58. // about - 8 and 16 MHz - this doesn't lose precision.)
  59. #define FRACT_INC ((MICROSECONDS_PER_TIMER0_OVERFLOW % 1000) >> 3)
  60. #define FRACT_MAX (1000 >> 3)
  61. //extern volatile unsigned long timer0_overflow_count;
  62. //extern volatile unsigned long timer0_millis;
  63. //unsigned char timer0_fract = 0;
  64. volatile unsigned long timer2_overflow_count;
  65. volatile unsigned long timer2_millis;
  66. unsigned char timer2_fract = 0;
  67. ISR(TIMER2_OVF_vect)
  68. {
  69. // copy these to local variables so they can be stored in registers
  70. // (volatile variables must be read from memory on every access)
  71. unsigned long m = timer2_millis;
  72. unsigned char f = timer2_fract;
  73. m += MILLIS_INC;
  74. f += FRACT_INC;
  75. if (f >= FRACT_MAX)
  76. {
  77. f -= FRACT_MAX;
  78. m += 1;
  79. }
  80. timer2_fract = f;
  81. timer2_millis = m;
  82. timer2_overflow_count++;
  83. }
  84. unsigned long millis2(void)
  85. {
  86. unsigned long m;
  87. uint8_t oldSREG = SREG;
  88. // disable interrupts while we read timer0_millis or we might get an
  89. // inconsistent value (e.g. in the middle of a write to timer0_millis)
  90. cli();
  91. m = timer2_millis;
  92. SREG = oldSREG;
  93. return m;
  94. }
  95. unsigned long micros2(void)
  96. {
  97. unsigned long m;
  98. uint8_t oldSREG = SREG, t;
  99. cli();
  100. m = timer2_overflow_count;
  101. #if defined(TCNT2)
  102. t = TCNT2;
  103. #elif defined(TCNT2L)
  104. t = TCNT2L;
  105. #else
  106. #error TIMER 2 not defined
  107. #endif
  108. #ifdef TIFR2
  109. if ((TIFR2 & _BV(TOV2)) && (t < 255))
  110. m++;
  111. #else
  112. if ((TIFR & _BV(TOV2)) && (t < 255))
  113. m++;
  114. #endif
  115. SREG = oldSREG;
  116. return ((m << 8) + t) * (64 / clockCyclesPerMicrosecond());
  117. }
  118. void delay2(unsigned long ms)
  119. {
  120. uint32_t start = micros2();
  121. while (ms > 0)
  122. {
  123. yield();
  124. while ( ms > 0 && (micros2() - start) >= 1000)
  125. {
  126. ms--;
  127. start += 1000;
  128. }
  129. }
  130. }
  131. void tone2(__attribute__((unused)) uint8_t _pin, __attribute__((unused)) unsigned int frequency/*, unsigned long duration*/)
  132. {
  133. PIN_SET(BEEPER);
  134. }
  135. void noTone2(__attribute__((unused)) uint8_t _pin)
  136. {
  137. PIN_CLR(BEEPER);
  138. }