/* * timer_hw.c * * Created: 25-04-2013 18:44:43 * Author: pf */ #include #include #include "timer_hw.h" #define NUMBER_OF_PRESCALERS (sizeof(prescalers)/sizeof(prescalers[0])) int8_t set_timer(uint32_t frequency) { /* Possible values for counter prescaler */ const uint16_t prescalers[] = {0,1,8,32,64,128,256,1024}; uint32_t divider; uint8_t i=1; /* * Handle special case when frequency is zero. * * A zero value for frequency means stopping the timer */ if(frequency == 0) { /* Stop timer */ TCCR0 = 0; return 0; } /* * Compute overall divider (from oscillator to output) * This divider is defined by * divider = prescaler * max_count * where prescaler is counter0 prescaler and * max_count is the MAX value of the counter. * */ divider = XTAL_FREQ / frequency; /* find a prescaler value */ /* try to find a suitable value, starting from the */ /* first non-zero prescaler value */ while(prescalers[i]< divider/255) { i++; if(i>=NUMBER_OF_PRESCALERS) { /* There is not a large enough prescaler value */ /* Stop the counter */ TCCR0 &= 0xF8; /* Signal error and leave */ return -1; } } /* i holds the index to the selected prescaler value and * it will be the value to write to CS02:0 in TCCR0 */ /* Reset counter0 value */ TCNT0 = 0x00; /* Program Output Control Register */ OCR0 = divider / prescalers[i]; /* Write the CS02:0 bits in TCCR0 (select prescaler) */ /* and WGM01:2=2 (force CTC mode) */ TCCR0 = (1 << WGM01) | i; return 0; }