timer02.c 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139
  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 "io_atmega2560.h"
  10. #define BEEPER 84
  11. void timer0_init(void)
  12. {
  13. //save sreg
  14. uint8_t _sreg = SREG;
  15. //disable interrupts for sure
  16. cli();
  17. TCNT0 = 0;
  18. // Fast PWM duty (0-255).
  19. // Due to invert mode (following rows) the duty is set to 255, which means zero all the time (bed not heating)
  20. OCR0B = 255;
  21. // Set fast PWM mode and inverting mode.
  22. TCCR0A = (1 << WGM01) | (1 << WGM00) | (1 << COM0B1) | (1 << COM0B0);
  23. TCCR0B = (1 << CS01); // CLK/8 prescaling
  24. TIMSK0 |= (1 << TOIE0); // enable timer overflow interrupt
  25. // Everything, that used to be on timer0 was moved to timer2 (delay, beeping, millis etc.)
  26. //setup timer2
  27. TCCR2A = 0x00; //COM_A-B=00, WGM_0-1=00
  28. TCCR2B = (4 << CS20); //WGM_2=0, CS_0-2=011
  29. //mask timer2 interrupts - enable OVF, disable others
  30. TIMSK2 |= (1<<TOIE2);
  31. TIMSK2 &= ~(1<<OCIE2A);
  32. TIMSK2 &= ~(1<<OCIE2B);
  33. //set timer2 OCR registers (OCRB interrupt generated 0.5ms after OVF interrupt)
  34. OCR2A = 0;
  35. OCR2B = 128;
  36. //restore sreg (enable interrupts)
  37. SREG = _sreg;
  38. }
  39. // The following code is OVF handler for timer 2
  40. // it was copy-pasted from wiring.c and modified for timer2
  41. // variables timer0_overflow_count and timer0_millis are declared in wiring.c
  42. // the prescaler is set so that timer0 ticks every 64 clock cycles, and the
  43. // the overflow handler is called every 256 ticks.
  44. #define MICROSECONDS_PER_TIMER0_OVERFLOW (clockCyclesToMicroseconds(64 * 256))
  45. // the whole number of milliseconds per timer0 overflow
  46. #define MILLIS_INC (MICROSECONDS_PER_TIMER0_OVERFLOW / 1000)
  47. // the fractional number of milliseconds per timer0 overflow. we shift right
  48. // by three to fit these numbers into a byte. (for the clock speeds we care
  49. // about - 8 and 16 MHz - this doesn't lose precision.)
  50. #define FRACT_INC ((MICROSECONDS_PER_TIMER0_OVERFLOW % 1000) >> 3)
  51. #define FRACT_MAX (1000 >> 3)
  52. volatile unsigned long timer2_overflow_count;
  53. volatile unsigned long timer2_millis;
  54. unsigned char timer2_fract = 0;
  55. ISR(TIMER2_OVF_vect)
  56. {
  57. // copy these to local variables so they can be stored in registers
  58. // (volatile variables must be read from memory on every access)
  59. unsigned long m = timer2_millis;
  60. unsigned char f = timer2_fract;
  61. m += MILLIS_INC;
  62. f += FRACT_INC;
  63. if (f >= FRACT_MAX)
  64. {
  65. f -= FRACT_MAX;
  66. m += 1;
  67. }
  68. timer2_fract = f;
  69. timer2_millis = m;
  70. timer2_overflow_count++;
  71. }
  72. unsigned long millis2(void)
  73. {
  74. unsigned long m;
  75. uint8_t oldSREG = SREG;
  76. // disable interrupts while we read timer0_millis or we might get an
  77. // inconsistent value (e.g. in the middle of a write to timer0_millis)
  78. cli();
  79. m = timer2_millis;
  80. SREG = oldSREG;
  81. return m;
  82. }
  83. unsigned long micros2(void)
  84. {
  85. unsigned long m;
  86. uint8_t oldSREG = SREG, t;
  87. cli();
  88. m = timer2_overflow_count;
  89. #if defined(TCNT2)
  90. t = TCNT2;
  91. #elif defined(TCNT2L)
  92. t = TCNT2L;
  93. #else
  94. #error TIMER 2 not defined
  95. #endif
  96. #ifdef TIFR2
  97. if ((TIFR2 & _BV(TOV2)) && (t < 255))
  98. m++;
  99. #else
  100. if ((TIFR & _BV(TOV2)) && (t < 255))
  101. m++;
  102. #endif
  103. SREG = oldSREG;
  104. return ((m << 8) + t) * (64 / clockCyclesPerMicrosecond());
  105. }
  106. void delay2(unsigned long ms)
  107. {
  108. uint32_t start = micros2();
  109. while (ms > 0)
  110. {
  111. yield();
  112. while ( ms > 0 && (micros2() - start) >= 1000)
  113. {
  114. ms--;
  115. start += 1000;
  116. }
  117. }
  118. }
  119. #endif //SYSTEM_TIMER_2