Hi folks, For the command clock_prescale_set() and clock_prescale_get(), devices ATmega128/128A & 64/64A are not covered since they seems to be the only ones that make uses of XDIV rather than CLKPR.
Attached patch is for discussion purposes. I'm not much of an assembler guru, so functions are in plain C. Code is working well on a ATmega128(I don't have any 64). Test code is also included. Setup is a STK500 w/atmega...@14.7456mhz with port B connected to leds. I shall make a formal patch file(including Doxygen comments) would people here finds this addition appropriate. Thanks for your comments. Frédéric Nadeau ing. jr
Index: power.h =================================================================== --- power.h (révision 2122) +++ power.h (copie de travail) @@ -1505,7 +1505,51 @@ #define clock_prescale_get() (clock_div_t)(CLKPR & (uint8_t)((1<<CLKPS0)|(1<<CLKPS1)|(1<<CLKPS2)|(1<<CLKPS3))) +#elif defined(XDIV) +//Enum is declared for code compatibility +typedef enum +{ + clock_div_1 = 1, + clock_div_2 = 2, + clock_div_4 = 4, + clock_div_8 = 8, + clock_div_16 = 16, + clock_div_32 = 32, + clock_div_64 = 64, + clock_div_128 = 128 +} clock_div_t; + +//X has to be between 1 and 129 +void clock_prescale_set(uint8 x) +{ + if(x == 0) + { + return; + } + else if(x == 1)//Disable prescaler + { + XDIV = 0; + } + else if(x <= 129) + { + XDIV = (129 - x) | _BV(XDIVEN); + } +} + +uint8_t clock_prescale_get(void) +{ + if(bit_is_clear(XDIV, XDIVEN)) + { + return 1; + } + else + { + return (129 - (XDIV & 0x7F)); + } +} + + #endif Index: power.h =================================================================== --- power.h (révision 2122) +++ power.h (copie de travail) @@ -1505,7 +1505,56 @@ #define clock_prescale_get() (clock_div_t)(CLKPR & (uint8_t)((1<<CLKPS0)|(1<<CLKPS1)|(1<<CLKPS2)|(1<<CLKPS3))) +#elif defined(XDIV) +//Enum is declared for code compatibility +//could also be +//#define clock_div_1 1 +//... +//#define clock_div_128 128 +//but then clock_div_t would not be recognized anymore +typedef enum +{ + clock_div_1 = 1, + clock_div_2 = 2, + clock_div_4 = 4, + clock_div_8 = 8, + clock_div_16 = 16, + clock_div_32 = 32, + clock_div_64 = 64, + clock_div_128 = 128 +} clock_div_t; + +//X has to be between 1 and 129 +void clock_prescale_set(uint8 x) +{ + if(x == 0) + { + return; + } + else if(x == 1)//Disable prescaler + { + XDIV = 0; + } + else if(x <= 129) + { + XDIV &= ~_BV(XDIVEN);//XDIVEN needs to be 0 to change the XDIV value + XDIV = (129 - x) | _BV(XDIVEN); + } +} + +uint8_t clock_prescale_get(void) +{ + if(bit_is_clear(XDIV, XDIVEN)) + { + return 1; + } + else + { + return (129 - (XDIV & 0x7F)); + } +} + #endif
#include <stdint.h> #include <avr/io.h> #include <avr/interrupt.h> #include <util/delay.h> //X has to be between 1 and 129 void clock_prescale_set(uint8_t x) { if(x == 0) { return; } else if(x == 1)//Disable prescaler { XDIV = 0; } else if(x <= 129) { XDIV &= ~_BV(XDIVEN); XDIV = (129 - x) | _BV(XDIVEN); } } uint8_t clock_prescale_get(void) { if(bit_is_clear(XDIV, XDIVEN)) { return 1; } else { return (129 - (XDIV & 0x7F)); } } ISR(TIMER1_OVF_vect) { static int i = 0; static uint8_t prescaler = 1; uint8_t prescalerRead; PORTB ^= 0xFF; i++; if(i > 10) { i = 0; prescaler++; if(prescaler > 129) prescaler = 1; clock_prescale_set(prescaler); prescalerRead = clock_prescale_get(); if(prescalerRead != prescaler) asm("break"); } } int main(void) { DDRB = 0xFF; sei(); //Enable timer 1 TIMSK |= _BV(TOIE1); TCCR1B |= _BV(CS10) | _BV(CS11); for(;;) asm("nop"); return 0; }
_______________________________________________ AVR-libc-dev mailing list AVR-libc-dev@nongnu.org http://lists.nongnu.org/mailman/listinfo/avr-libc-dev