qmk_firmware

QMK firmware for my keyboards (Corne, Sweep Ferris) and trackball (Ploopy Adept)
Log | Files | Refs | Submodules | LICENSE

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 }