TimerOne.cpp 7.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209
  1. /*
  2. * Interrupt and PWM utilities for 16 bit Timer1 on ATmega168/328
  3. * Original code by Jesse Tane for http://labs.ideo.com August 2008
  4. * Modified March 2009 by Jérôme Despatis and Jesse Tane for ATmega328 support
  5. * Modified June 2009 by Michael Polli and Jesse Tane to fix a bug in setPeriod() which caused the timer to stop
  6. * Modified June 2011 by Lex Talionis to add a function to read the timer
  7. * Modified Oct 2011 by Andrew Richards to avoid certain problems:
  8. * - Add (long) assignments and casts to TimerOne::read() to ensure calculations involving tmp, ICR1 and TCNT1 aren't truncated
  9. * - Ensure 16 bit registers accesses are atomic - run with interrupts disabled when accessing
  10. * - Remove global enable of interrupts (sei())- could be running within an interrupt routine)
  11. * - Disable interrupts whilst TCTN1 == 0. Datasheet vague on this, but experiment shows that overflow interrupt
  12. * flag gets set whilst TCNT1 == 0, resulting in a phantom interrupt. Could just set to 1, but gets inaccurate
  13. * at very short durations
  14. * - startBottom() added to start counter at 0 and handle all interrupt enabling.
  15. * - start() amended to enable interrupts
  16. * - restart() amended to point at startBottom()
  17. * Modiied 7:26 PM Sunday, October 09, 2011 by Lex Talionis
  18. * - renamed start() to resume() to reflect it's actual role
  19. * - renamed startBottom() to start(). This breaks some old code that expects start to continue counting where it left off
  20. *
  21. * This program is free software: you can redistribute it and/or modify
  22. * it under the terms of the GNU General Public License as published by
  23. * the Free Software Foundation, either version 3 of the License, or
  24. * (at your option) any later version.
  25. *
  26. * This program is distributed in the hope that it will be useful,
  27. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  28. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  29. * GNU General Public License for more details.
  30. *
  31. * You should have received a copy of the GNU General Public License
  32. * along with this program. If not, see <http://www.gnu.org/licenses/>.
  33. *
  34. * See Google Code project http://code.google.com/p/arduino-timerone/ for latest
  35. */
  36. #ifndef TIMERONE_cpp
  37. #define TIMERONE_cpp
  38. #include "TimerOne.h"
  39. TimerOne Timer1; // preinstatiate
  40. ISR(TIMER1_OVF_vect) // interrupt service routine that wraps a user defined function supplied by attachInterrupt
  41. {
  42. Timer1.isrCallback();
  43. }
  44. void TimerOne::initialize(long microseconds)
  45. {
  46. TCCR1A = 0; // clear control register A
  47. TCCR1B = _BV(WGM13); // set mode 8: phase and frequency correct pwm, stop the timer
  48. setPeriod(microseconds);
  49. }
  50. void TimerOne::setPeriod(long microseconds) // AR modified for atomic access
  51. {
  52. long cycles = (F_CPU / 2000000) * microseconds; // the counter runs backwards after TOP, interrupt is at BOTTOM so divide microseconds by 2
  53. if(cycles < RESOLUTION) clockSelectBits = _BV(CS10); // no prescale, full xtal
  54. else if((cycles >>= 3) < RESOLUTION) clockSelectBits = _BV(CS11); // prescale by /8
  55. else if((cycles >>= 3) < RESOLUTION) clockSelectBits = _BV(CS11) | _BV(CS10); // prescale by /64
  56. else if((cycles >>= 2) < RESOLUTION) clockSelectBits = _BV(CS12); // prescale by /256
  57. else if((cycles >>= 2) < RESOLUTION) clockSelectBits = _BV(CS12) | _BV(CS10); // prescale by /1024
  58. else cycles = RESOLUTION - 1, clockSelectBits = _BV(CS12) | _BV(CS10); // request was out of bounds, set as maximum
  59. oldSREG = SREG;
  60. cli(); // Disable interrupts for 16 bit register access
  61. ICR1 = pwmPeriod = cycles; // ICR1 is TOP in p & f correct pwm mode
  62. SREG = oldSREG;
  63. TCCR1B &= ~(_BV(CS10) | _BV(CS11) | _BV(CS12));
  64. TCCR1B |= clockSelectBits; // reset clock select register, and starts the clock
  65. }
  66. void TimerOne::setPwmDuty(char pin, int duty)
  67. {
  68. unsigned long dutyCycle = pwmPeriod;
  69. dutyCycle *= duty;
  70. dutyCycle >>= 10;
  71. oldSREG = SREG;
  72. cli();
  73. if(pin == 1 || pin == 9) OCR1A = dutyCycle;
  74. else if(pin == 2 || pin == 10) OCR1B = dutyCycle;
  75. SREG = oldSREG;
  76. }
  77. void TimerOne::pwm(char pin, int duty, long microseconds) // expects duty cycle to be 10 bit (1024)
  78. {
  79. if(microseconds > 0) setPeriod(microseconds);
  80. if(pin == 1 || pin == 9) {
  81. DDRB |= _BV(PORTB1); // sets data direction register for pwm output pin
  82. TCCR1A |= _BV(COM1A1); // activates the output pin
  83. }
  84. else if(pin == 2 || pin == 10) {
  85. DDRB |= _BV(PORTB2);
  86. TCCR1A |= _BV(COM1B1);
  87. }
  88. setPwmDuty(pin, duty);
  89. resume(); // Lex - make sure the clock is running. We don't want to restart the count, in case we are starting the second WGM
  90. // and the first one is in the middle of a cycle
  91. }
  92. void TimerOne::disablePwm(char pin)
  93. {
  94. if(pin == 1 || pin == 9) TCCR1A &= ~_BV(COM1A1); // clear the bit that enables pwm on PB1
  95. else if(pin == 2 || pin == 10) TCCR1A &= ~_BV(COM1B1); // clear the bit that enables pwm on PB2
  96. }
  97. void TimerOne::attachInterrupt(void (*isr)(), long microseconds)
  98. {
  99. if(microseconds > 0) setPeriod(microseconds);
  100. isrCallback = isr; // register the user's callback with the real ISR
  101. TIMSK1 = _BV(TOIE1); // sets the timer overflow interrupt enable bit
  102. // might be running with interrupts disabled (eg inside an ISR), so don't touch the global state
  103. // sei();
  104. resume();
  105. }
  106. void TimerOne::detachInterrupt()
  107. {
  108. TIMSK1 &= ~_BV(TOIE1); // clears the timer overflow interrupt enable bit
  109. // timer continues to count without calling the isr
  110. }
  111. void TimerOne::resume() // AR suggested
  112. {
  113. TCCR1B |= clockSelectBits;
  114. }
  115. void TimerOne::restart() // Depricated - Public interface to start at zero - Lex 10/9/2011
  116. {
  117. start();
  118. }
  119. void TimerOne::start() // AR addition, renamed by Lex to reflect it's actual role
  120. {
  121. unsigned int tcnt1;
  122. TIMSK1 &= ~_BV(TOIE1); // AR added
  123. GTCCR |= _BV(PSRSYNC); // AR added - reset prescaler (NB: shared with all 16 bit timers);
  124. oldSREG = SREG; // AR - save status register
  125. cli(); // AR - Disable interrupts
  126. TCNT1 = 0;
  127. SREG = oldSREG; // AR - Restore status register
  128. resume();
  129. do { // Nothing -- wait until timer moved on from zero - otherwise get a phantom interrupt
  130. oldSREG = SREG;
  131. cli();
  132. tcnt1 = TCNT1;
  133. SREG = oldSREG;
  134. } while (tcnt1==0);
  135. // TIFR1 = 0xff; // AR - Clear interrupt flags
  136. // TIMSK1 = _BV(TOIE1); // sets the timer overflow interrupt enable bit
  137. }
  138. void TimerOne::stop()
  139. {
  140. TCCR1B &= ~(_BV(CS10) | _BV(CS11) | _BV(CS12)); // clears all clock selects bits
  141. }
  142. unsigned long TimerOne::read() //returns the value of the timer in microseconds
  143. { //rember! phase and freq correct mode counts up to then down again
  144. unsigned long tmp; // AR amended to hold more than 65536 (could be nearly double this)
  145. unsigned int tcnt1; // AR added
  146. oldSREG= SREG;
  147. cli();
  148. tmp=TCNT1;
  149. SREG = oldSREG;
  150. char scale=0;
  151. switch (clockSelectBits)
  152. {
  153. case 1:// no prescalse
  154. scale=0;
  155. break;
  156. case 2:// x8 prescale
  157. scale=3;
  158. break;
  159. case 3:// x64
  160. scale=6;
  161. break;
  162. case 4:// x256
  163. scale=8;
  164. break;
  165. case 5:// x1024
  166. scale=10;
  167. break;
  168. }
  169. do { // Nothing -- max delay here is ~1023 cycles. AR modified
  170. oldSREG = SREG;
  171. cli();
  172. tcnt1 = TCNT1;
  173. SREG = oldSREG;
  174. } while (tcnt1==tmp); //if the timer has not ticked yet
  175. //if we are counting down add the top value to how far we have counted down
  176. tmp = ( (tcnt1>tmp) ? (tmp) : (long)(ICR1-tcnt1)+(long)ICR1 ); // AR amended to add casts and reuse previous TCNT1
  177. return ((tmp*1000L)/(F_CPU /1000L))<<scale;
  178. }
  179. #endif