timer.c (2998B)
1 /* 2 Copyright 2011 Jun Wako <wakojun@gmail.com> 3 4 This program is free software: you can redistribute it and/or modify 5 it under the terms of the GNU General Public License as published by 6 the Free Software Foundation, either version 2 of the License, or 7 (at your option) any later version. 8 9 This program is distributed in the hope that it will be useful, 10 but WITHOUT ANY WARRANTY; without even the implied warranty of 11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 GNU General Public License for more details. 13 14 You should have received a copy of the GNU General Public License 15 along with this program. If not, see <http://www.gnu.org/licenses/>. 16 */ 17 18 #include <avr/io.h> 19 #include <avr/interrupt.h> 20 #include <util/atomic.h> 21 #include <stdint.h> 22 #include "timer_avr.h" 23 #include "timer.h" 24 25 // counter resolution 1ms 26 // NOTE: union { uint32_t timer32; struct { uint16_t dummy; uint16_t timer16; }} 27 volatile uint32_t timer_count; 28 static uint32_t saved_ms; 29 30 /** \brief timer initialization 31 * 32 * FIXME: needs doc 33 */ 34 void timer_init(void) { 35 #if TIMER_PRESCALER == 1 36 uint8_t prescaler = _BV(CS00); 37 #elif TIMER_PRESCALER == 8 38 uint8_t prescaler = _BV(CS01); 39 #elif TIMER_PRESCALER == 64 40 uint8_t prescaler = _BV(CS00) | _BV(CS01); 41 #elif TIMER_PRESCALER == 256 42 uint8_t prescaler = _BV(CS02); 43 #elif TIMER_PRESCALER == 1024 44 uint8_t prescaler = _BV(CS00) | _BV(CS02); 45 #else 46 # error "Timer prescaler value is not valid" 47 #endif 48 49 #if defined(__AVR_ATmega32A__) 50 // Timer0 CTC mode 51 TCCR0 = _BV(WGM01) | prescaler; 52 53 OCR0 = TIMER_RAW_TOP; 54 TIMSK = _BV(OCIE0); 55 #elif defined(__AVR_ATtiny85__) 56 // Timer0 CTC mode 57 TCCR0A = _BV(WGM01); 58 TCCR0B = prescaler; 59 60 OCR0A = TIMER_RAW_TOP; 61 TIMSK = _BV(OCIE0A); 62 #else 63 // Timer0 CTC mode 64 TCCR0A = _BV(WGM01); 65 TCCR0B = prescaler; 66 67 OCR0A = TIMER_RAW_TOP; 68 TIMSK0 = _BV(OCIE0A); 69 #endif 70 } 71 72 /** \brief timer clear 73 * 74 * FIXME: needs doc 75 */ 76 inline void timer_clear(void) { 77 ATOMIC_BLOCK(ATOMIC_RESTORESTATE) { 78 timer_count = 0; 79 } 80 } 81 82 /** \brief timer save 83 * 84 * Set saved_ms to current time. 85 */ 86 void timer_save(void) { 87 saved_ms = timer_read32(); 88 } 89 90 /** \brief timer restore 91 * 92 * Set timer_count to saved_ms 93 */ 94 void timer_restore(void) { 95 ATOMIC_BLOCK(ATOMIC_RESTORESTATE) { 96 timer_count = saved_ms; 97 } 98 } 99 100 /** \brief timer read 101 * 102 * FIXME: needs doc 103 */ 104 inline uint16_t timer_read(void) { 105 uint32_t t; 106 107 ATOMIC_BLOCK(ATOMIC_RESTORESTATE) { 108 t = timer_count; 109 } 110 111 return (t & 0xFFFF); 112 } 113 114 /** \brief timer read32 115 * 116 * FIXME: needs doc 117 */ 118 inline uint32_t timer_read32(void) { 119 uint32_t t; 120 121 ATOMIC_BLOCK(ATOMIC_RESTORESTATE) { 122 t = timer_count; 123 } 124 125 return t; 126 } 127 128 // excecuted once per 1ms.(excess for just timer count?) 129 #ifndef __AVR_ATmega32A__ 130 # define TIMER_INTERRUPT_VECTOR TIMER0_COMPA_vect 131 #else 132 # define TIMER_INTERRUPT_VECTOR TIMER0_COMP_vect 133 #endif 134 ISR(TIMER_INTERRUPT_VECTOR, ISR_NOBLOCK) { 135 timer_count++; 136 }