timer02.c 4.0 KB

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