From 36fa7353232068831174ebfb3d4ab6c10a7a49ca Mon Sep 17 00:00:00 2001 From: David Kopf Date: Wed, 17 Aug 2011 13:15:26 -0400 Subject: [PATCH] Calculate best prescaler based on F_CPU and CLOCK_CONF_SECONDS. Inspired by patch from Ivan Delamer. --- cpu/avr/dev/clock-avr.h | 54 ++++++++++++++++++++++++++++++++++++----- 1 file changed, 48 insertions(+), 6 deletions(-) diff --git a/cpu/avr/dev/clock-avr.h b/cpu/avr/dev/clock-avr.h index 95bcfbc8e..02d175020 100644 --- a/cpu/avr/dev/clock-avr.h +++ b/cpu/avr/dev/clock-avr.h @@ -37,6 +37,7 @@ TIMSK = _BV (OCIE0); #elif defined (__AVR_ATmega128RFA1__) && 0 +/* Uses the general routine below at present */ #define AVR_OUTPUT_COMPARE_INT TIMER0_COMPA_vect #define OCRSetup() \ @@ -113,8 +114,49 @@ * counter value in TCNT2 is cleared automatically. \ */ \ TIMSK2 = _BV (OCIE2A); +#else /* !AVR_CONF_USE32KCRYSTAL */ + +/* Determine the largest value that can be used with 8 bit timer0 */ +#ifndef F_CPU +#error "Please define CPU clock speed for your platform. #define F_CPU 8000000UL is typical." +#endif +#if CLOCK_CONF_SECOND == 0 +#error "Please define timer ticks per second for your platform. #define CLOCK_CONF_SECOND 128 is typical." +#endif + +#ifdef AVR_CONF_TMR0_PRESCALE +#elif F_CPU/CLOCK_CONF_SECOND < 256 + #define AVR_CONF_TMR0_PRESCALE 1 +#elif F_CPU/CLOCK_CONF_SECOND < 256 * 8 + #define AVR_CONF_TMR0_PRESCALE 8 +#elif F_CPU/CLOCK_CONF_SECOND < 256 * 64 + #define AVR_CONF_TMR0_PRESCALE 8 +#elif F_CPU/CLOCK_CONF_SECOND < 256 * 256 + #define AVR_CONF_TMR0_PRESCALE 256 #else + #define AVR_CONF_TMR0_PRESCALE 1024 +#endif + +#if F_CPU/CLOCK_CONF_SECOND/AVR_CONF_TMR0_PRESCALE > 255 +#error "Can not prescale CPU clock to get specified ticks per second. F_CPU/CLOCK_CONF_SECOND/1024 must be less than 256." +#endif + +#if AVR_CONF_TMR0_PRESCALE == 1 + #define AVR_TCCR0B_CONF _BV(CS00) +#elif AVR_CONF_TMR0_PRESCALE == 8 + #define AVR_TCCR0B_CONF _BV(CS01) +#elif AVR_CONF_TMR0_PRESCALE == 64 + #define AVR_TCCR0B_CONF _BV(CS01) | _BV(CS00) +#elif AVR_CONF_TMR0_PRESCALE == 256 + #define AVR_TCCR0B_CONF _BV(CS02) +#elif AVR_CONF_TMR0_PRESCALE == 1024 + #define AVR_TCCR0B_CONF _BV(CS02) | _BV(CS00) +#else +#error "Prescale factor not supported. Allowed values are 1,8,64,256,1024." +#endif + #define AVR_OUTPUT_COMPARE_INT TIMER0_COMPA_vect + #define OCRSetup() \ /* Select internal clock */ \ ASSR = 0x00; \ @@ -124,19 +166,19 @@ \ /* \ * Set comparison register: \ - * Crystal freq. is F_CPU,\ - * pre-scale factor is 1024, we want CLOCK_CONF_SECOND ticks / sec: \ - * F_CPU = 1024 * CLOCK_CONF_SECOND * OCR2A, less 1 for CTC mode \ + * Crystal freq. is F_CPU, prescale is given, \ + * We want CLOCK_CONF_SECOND ticks / sec: \ + * F_CPU = AVR_CONF_TMR0_PRESCALE * CLOCK_CONF_SECOND * OCR2A, less 1 for CTC mode \ */ \ - OCR0A = F_CPU/1024UL/CLOCK_CONF_SECOND - 1; \ + OCR0A = F_CPU/AVR_CONF_TMR0_PRESCALE/CLOCK_CONF_SECOND - 1; \ \ /* \ * Set timer control register: \ - * - prescale: 1024 (CS00 - CS02) \ + * - prescale according to AVR_CONF_TMR0_PRESCALE \ * - counter reset via comparison register (WGM01) \ */ \ TCCR0A = _BV(WGM01); \ - TCCR0B = _BV(CS00) | _BV(CS02); \ + TCCR0B = AVR_TCCR0B_CONF; \ \ /* Clear interrupt flag register */ \ TIFR0 = TIFR0; \