Subversion Repositories HomeAutomation

Rev

Rev 1468 | Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | SVN | RSS feed

  1. /**
  2.  * Timebase software module. Utilizes timer0 to provide a 32bit timebase with
  3.  * millisecond-granularity to the application.
  4.  *
  5.  * @author  Martin Thomas
  6.  * @author  Jimmy Myhrman
  7.  *
  8.  * @date    2006-11-19
  9.  */
  10.  
  11. /*-----------------------------------------------------------------------------
  12.  * Includes
  13.  *---------------------------------------------------------------------------*/
  14. #include <inttypes.h>
  15. #include <avr/io.h>
  16. #include <avr/interrupt.h>
  17.  
  18. #include <config.h>
  19. #include <drivers/timer/timebase.h>
  20.  
  21.  
  22. /*-----------------------------------------------------------------------------
  23.  * Globals
  24.  *---------------------------------------------------------------------------*/
  25. volatile uint32_t gMilliSecTick;
  26.  
  27.  
  28. /*-----------------------------------------------------------------------------
  29.  * Interrupt Service Routines
  30.  *---------------------------------------------------------------------------*/
  31. #if defined(TIMEBASE_NEW_IMPLEMENTATION)
  32.  
  33. #if defined(__AVR_ATmega88__) || defined(__AVR_ATmega168__) || defined(__AVR_ATmega168P__) || defined(__AVR_ATmega328P__)
  34. #if defined(TIMER2)
  35. ISR(TIMER2_COMPA_vect) {
  36. #else //!defined(TIMER2)
  37. ISR(TIMER0_COMPA_vect) {
  38. #endif //defined(TIMER2)
  39. #else //!defined(__AVR_ATmega88__) || defined(__AVR_ATmega168__) || defined(__AVR_ATmega168P__) || defined(__AVR_ATmega328P__)
  40. ISR(TIMER2_COMP_vect) {
  41. #endif //defined(__AVR_ATmega88__) || defined(__AVR_ATmega168__) || defined(__AVR_ATmega168P__) || defined(__AVR_ATmega328P__)
  42.     gMilliSecTick++;
  43. }
  44.  
  45. #else //!defined(TIMEBASE_NEW_IMPLEMENTATION)
  46.  
  47. #if defined(TIMER2)
  48. ISR(TIMER2_OVF_vect) {
  49.     TCNT2 = TIMEBASE_RELOAD;
  50.     gMilliSecTick++;
  51. }
  52. #else
  53. ISR(TIMER0_OVF_vect) {
  54.     TCNT0 = TIMEBASE_RELOAD;
  55.     gMilliSecTick++;
  56. }
  57. #endif
  58.  
  59. #endif //defined(TIMEBASE_NEW_IMPLEMENTATION)
  60.  
  61.  
  62. /*-----------------------------------------------------------------------------
  63.  * Public Functions
  64.  *---------------------------------------------------------------------------*/
  65.  
  66. /**
  67.  * Initializes the timebase. The hardware timer interrupt source will be
  68.  * enabled, but global interrupts need to be enabled by the application.
  69.  */
  70. void Timebase_Init() {
  71. #if defined(TIMEBASE_NEW_IMPLEMENTATION)
  72.  
  73. #if defined(TIMER2)
  74.     #if defined(__AVR_ATmega8__)
  75.     TCCR2 = (1<<WGM21); // CTC mode
  76.     #if TIMEBASE_PRESCALE == 64
  77.     TCCR2 = (1<<CS22);  // prescaler: 64
  78.     #elif TIMEBASE_PRESCALE == 256
  79.     TCCR2 = (1<<CS22) | (1<<CS21); // prescaler: 256
  80.     #endif
  81.     OCR2 = TIMEBASE_HITS_PER_1MS; // set timer period
  82.     TIFR  |= (1<<OCF2);  // clear ouput compare match flag
  83.     TIMSK |= (1<<OCIE2); // enable output compare match interrupt
  84.     #endif
  85.    
  86.     #if defined(__AVR_ATmega88__) || defined(__AVR_ATmega168__) || defined(__AVR_ATmega168P__) || defined(__AVR_ATmega328P__)
  87.     TCCR2A = (1<<WGM21); // CTC mode
  88.     #if TIMEBASE_PRESCALE == 64
  89.     TCCR2B = (1<<CS22); // prescaler: 64
  90.     #elif TIMEBASE_PRESCALE == 256
  91.     TCCR2B = (1<<CS22)|(1<<CS21);               // prescaler: 256
  92.     #endif
  93.     OCR2A = TIMEBASE_HITS_PER_1MS; // set timer period
  94.     TIFR2  |= (1<<OCF2A);  // clear ouput compare match flag
  95.     TIMSK2 |= (1<<OCIE2A); // enable output compare match interrupt
  96.     #endif
  97. #else /* Use timer0 */
  98.     #if defined(__AVR_ATmega8__)
  99.     #error TIMER0 not supported in ATmega8 with TIMEBASE_NEW_IMPLEMENTATION set!
  100.     #endif
  101.    
  102.     #if defined(__AVR_ATmega88__) || defined(__AVR_ATmega168__) || defined(__AVR_ATmega168P__) || defined(__AVR_ATmega328P__)
  103.     TCCR0A = (1<<WGM01); // CTC mode
  104.     #if TIMEBASE_PRESCALE == 64
  105.     TCCR0B = (1<<CS01) | (1<<CS00); // prescaler: 64
  106.     #elif TIMEBASE_PRESCALE == 256
  107.     TCCR0B = (1<<CS02);             // prescaler: 256
  108.     #endif
  109.     OCR0A = TIMEBASE_HITS_PER_1MS; // set timer period
  110.     TIFR0  |= (1<<OCF0A);  // clear ouput compare match flag
  111.     TIMSK0 |= (1<<OCIE0A); // enable output compare match interrupt
  112.     #endif
  113. #endif
  114.  
  115.  
  116. #else //!defined(TIMEBASE_NEW_IMPLEMENTATION)
  117.  
  118. #if defined(TIMER2)
  119.     #if defined(__AVR_ATmega8__)
  120.     #if TIMEBASE_PRESCALE == 64
  121.     TCCR2 = (1<<CS22);  // prescaler: 64
  122.     #elif TIMEBASE_PRESCALE == 256
  123.     TCCR2 = (1<<CS22) | (1<<CS21); // prescaler: 256
  124.     #endif
  125.     TCNT2 = TIMEBASE_RELOAD; // set initial reload-value
  126.     TIFR  |= (1<<TOV2);  // clear overflow int.
  127.     TIMSK |= (1<<TOIE2); // enable overflow-interrupt
  128.     #endif
  129.    
  130.     #if defined(__AVR_ATmega88__) || defined(__AVR_ATmega168__) || defined(__AVR_ATmega168P__) || defined(__AVR_ATmega328P__)
  131.     #if TIMEBASE_PRESCALE == 64
  132.     TCCR2B = (1<<CS22); // prescaler: 64
  133.     #elif TIMEBASE_PRESCALE == 256
  134.     TCCR2B = (1<<CS22)|(1<<CS21);               // prescaler: 256
  135.     #endif
  136.     TCNT2 = TIMEBASE_RELOAD; // set initial reload-value
  137.     TIFR2  |= (1<<TOV2);  // clear overflow int.
  138.     TIMSK2 |= (1<<TOIE2); // enable overflow-interrupt
  139.     #endif
  140. #else /* Use timer0 */
  141.     #if defined(__AVR_ATmega8__)
  142.     #if TIMEBASE_PRESCALE == 64
  143.     TCCR0 = (1<<CS01) | (1<<CS00);  // prescaler: 64
  144.     #elif TIMEBASE_PRESCALE == 256
  145.     TCCR0 = (1<<CS02);              // prescaler: 256
  146.     #endif
  147.     TCNT0 = TIMEBASE_RELOAD; // set initial reload-value
  148.     TIFR  |= (1<<TOV0);  // clear overflow int.
  149.     TIMSK |= (1<<TOIE0); // enable overflow-interrupt
  150.     #endif
  151.    
  152.     #if defined(__AVR_ATmega88__) || defined(__AVR_ATmega168__) || defined(__AVR_ATmega168P__) || defined(__AVR_ATmega328P__)
  153.     #if TIMEBASE_PRESCALE == 64
  154.     TCCR0B = (1<<CS01) | (1<<CS00); // prescaler: 64
  155.     #elif TIMEBASE_PRESCALE == 256
  156.     TCCR0B = (1<<CS02);             // prescaler: 256
  157.     #endif
  158.     TCNT0 = TIMEBASE_RELOAD; // set initial reload-value
  159.     TIFR0  |= (1<<TOV0);  // clear overflow int.
  160.     TIMSK0 |= (1<<TOIE0); // enable overflow-interrupt
  161.     #endif
  162. #endif
  163.  
  164. #endif //defined(TIMEBASE_NEW_IMPLEMENTATION)
  165. }
  166.  
  167.  
  168. /**
  169.  * Reads the current time.
  170.  *
  171.  * @return
  172.  *      The current time in milliseconds (32bit value).
  173.  */
  174. uint32_t Timebase_CurrentTime(void) {
  175.     uint8_t sreg;
  176.     uint32_t res;
  177.     sreg=SREG;
  178.     cli();
  179.     res = gMilliSecTick;
  180.     SREG=sreg;
  181.     return res;
  182. }
  183.  
  184.  
  185. /**
  186.  * Checks how much time has passed since a given timestamp.
  187.  *
  188.  * @param t0
  189.  *      The timestamp.
  190.  * @return
  191.  *      Number of milliseconds that have passed since t0.
  192.  */
  193. uint32_t Timebase_PassedTimeMillis(uint32_t t0) {
  194.     uint8_t sreg;
  195.     uint32_t res;
  196.     sreg=SREG;
  197.     cli();
  198.     res = (uint32_t)(gMilliSecTick-t0);
  199.     SREG=sreg;
  200.     return res;
  201. }
  202.