Subversion Repositories HomeAutomation

Rev

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