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

Reply via email to