Add detect macros for AVR XMega MCU.
[bertos.git] / bertos / cpu / avr / drv / ser_avr.c
index 11a6c65c024c7d628f5041056d556d238eeab21e..ce44fd1983c08d7027f4b5b04233bb2ae95fd3f1 100644 (file)
@@ -74,7 +74,7 @@
        /*\}*/
 #endif
 
-#if CPU_AVR_ATMEGA1281 || CPU_AVR_ATMEGA1280
+#if CPU_AVR_ATMEGA1281 || CPU_AVR_ATMEGA1280 || CPU_AVR_ATMEGA2560
        #define BIT_RXCIE0 RXCIE0
        #define BIT_RXEN0  RXEN0
        #define BIT_TXEN0  TXEN0
@@ -84,7 +84,7 @@
        #define BIT_RXEN1  RXEN1
        #define BIT_TXEN1  TXEN1
        #define BIT_UDRIE1 UDRIE1
-       #if CPU_AVR_ATMEGA1280
+       #if CPU_AVR_ATMEGA1280 || CPU_AVR_ATMEGA2560
                #define BIT_RXCIE2 RXCIE2
                #define BIT_RXEN2  RXEN2
                #define BIT_TXEN2  TXEN2
         * - Enable only the RX complete interrupt
         */
        #define SER_UART0_BUS_TXINIT do { \
+               UCSR0A = 0; /* The Arduino Uno bootloader turns on U2X0 */ \
                UCSR0B = BV(BIT_RXCIE0) | BV(BIT_RXEN0) | BV(BIT_TXEN0); \
        } while (0)
 #endif
 
 /* SPI port and pin configuration */
 #if CPU_AVR_ATMEGA64 || CPU_AVR_ATMEGA128 || CPU_AVR_ATMEGA103 || CPU_AVR_ATMEGA1281 \
-    || CPU_AVR_ATMEGA1280
+    || CPU_AVR_ATMEGA1280 || CPU_AVR_ATMEGA2560
        #define SPI_PORT      PORTB
        #define SPI_DDR       DDRB
        #define SPI_SS_BIT    PB0
        #define SPI_SCK_BIT   PB5
        #define SPI_MOSI_BIT  PB3
        #define SPI_MISO_BIT  PB4
+#elif CPU_AVR_ATMEGA32
+       #define SPI_PORT      PORTB
+       #define SPI_DDR       DDRB
+       #define SPI_SS_BIT    PB4
+       #define SPI_SCK_BIT   PB7
+       #define SPI_MOSI_BIT  PB5
+       #define SPI_MISO_BIT  PB6
 #else
        #error Unknown architecture
 #endif
 
 /* USART register definitions */
-#if CPU_AVR_ATMEGA1280
+#if CPU_AVR_ATMEGA1280 || CPU_AVR_ATMEGA2560
        #define AVR_HAS_UART1 1
        #define AVR_HAS_UART2 1
        #define AVR_HAS_UART3 1
        #define USART0_UDRE_vect USART_UDRE_vect
        #define USART0_RX_vect USART_RX_vect
        #define USART0_TX_vect USART_TX_vect
-#elif CPU_AVR_ATMEGA8
+#elif CPU_AVR_ATMEGA8 || CPU_AVR_ATMEGA32
        #define AVR_HAS_UART1 0
        #define AVR_HAS_UART2 0
        #define AVR_HAS_UART3 0
        #define UDR0   UDR
        #define UBRR0L UBRRL
        #define UBRR0H UBRRH
+       #define UPM01  UPM1
+       #define UPM00  UPM0
        #define USART0_UDRE_vect USART_UDRE_vect
-       #define USART0_RX_vect USART_RX_vect
-       #define USART0_TX_vect USART_TX_vect
+       #define USART0_RX_vect USART_RXC_vect
+       #define USART0_TX_vect USART_TXC_vect
 #elif CPU_AVR_ATMEGA103
        #define AVR_HAS_UART1 0
        #define AVR_HAS_UART2 0
@@ -448,7 +458,20 @@ struct AvrSerial
        volatile bool sending;
 };
 
+static uint16_t uart_period(unsigned long bps)
+{
+       uint16_t period = DIV_ROUND(CPU_FREQ / 16UL, bps) - 1;
+
+       #ifdef _DEBUG
+               long skew = bps - (long)(period + 1) * (CPU_FREQ / 16);
+               /* 8N1 is reliable within 3% skew */
+               if ((unsigned long)ABS(skew) > bps / (100 / 3))
+                       kprintf("Baudrate off by %ldbps\n", skew);
+       #endif
 
+       //DB(kprintf("uart_period(bps=%lu): period=%u\n", bps, period);)
+       return period;
+}
 
 /*
  * Callbacks
@@ -485,15 +508,12 @@ static void uart0_enabletxirq(struct SerialHardware *_hw)
 
 static void uart0_setbaudrate(UNUSED_ARG(struct SerialHardware *, _hw), unsigned long rate)
 {
-       /* Compute baud-rate period */
-       uint16_t period = DIV_ROUND(CPU_FREQ / 16UL, rate) - 1;
+       uint16_t period = uart_period(rate);
 
 #if !CPU_AVR_ATMEGA103
-       UBRR0H = (period) >> 8;
+       UBRR0H = period >> 8;
 #endif
-       UBRR0L = (period);
-
-       //DB(kprintf("uart0_setbaudrate(rate=%lu): period=%d\n", rate, period);)
+       UBRR0L = period;
 }
 
 static void uart0_setparity(UNUSED_ARG(struct SerialHardware *, _hw), int parity)
@@ -538,13 +558,9 @@ static void uart1_enabletxirq(struct SerialHardware *_hw)
 
 static void uart1_setbaudrate(UNUSED_ARG(struct SerialHardware *, _hw), unsigned long rate)
 {
-       /* Compute baud-rate period */
-       uint16_t period = DIV_ROUND(CPU_FREQ / 16UL, rate) - 1;
-
-       UBRR1H = (period) >> 8;
-       UBRR1L = (period);
-
-       //DB(kprintf("uart1_setbaudrate(rate=%ld): period=%d\n", rate, period);)
+       uint16_t period = uart_period(rate);
+       UBRR1H = period >> 8;
+       UBRR1L = period;
 }
 
 static void uart1_setparity(UNUSED_ARG(struct SerialHardware *, _hw), int parity)
@@ -589,13 +605,9 @@ static void uart2_enabletxirq(struct SerialHardware *_hw)
 
 static void uart2_setbaudrate(UNUSED_ARG(struct SerialHardware *, _hw), unsigned long rate)
 {
-       /* Compute baud-rate period */
-       uint16_t period = DIV_ROUND(CPU_FREQ / 16UL, rate) - 1;
-
-       UBRR2H = (period) >> 8;
-       UBRR2L = (period);
-
-       //DB(kprintf("uart2_setbaudrate(rate=%ld): period=%d\n", rate, period);)
+       uint16_t period = uart_period(rate);
+       UBRR2H = period >> 8;
+       UBRR2L = period;
 }
 
 static void uart2_setparity(UNUSED_ARG(struct SerialHardware *, _hw), int parity)
@@ -640,13 +652,9 @@ static void uart3_enabletxirq(struct SerialHardware *_hw)
 
 static void uart3_setbaudrate(UNUSED_ARG(struct SerialHardware *, _hw), unsigned long rate)
 {
-       /* Compute baud-rate period */
-       uint16_t period = DIV_ROUND(CPU_FREQ / 16UL, rate) - 1;
-
-       UBRR3H = (period) >> 8;
-       UBRR3L = (period);
-
-       //DB(kprintf("uart3_setbaudrate(rate=%ld): period=%d\n", rate, period);)
+       uint16_t period = uart_period(rate);
+       UBRR3H = period >> 8;
+       UBRR3L = period;
 }
 
 static void uart3_setparity(UNUSED_ARG(struct SerialHardware *, _hw), int parity)
@@ -1080,22 +1088,6 @@ DECLARE_ISR(USART2_UDRE_vect)
                UARTDescs[SER_UART2].sending = false;
 #endif
        }
-
-/**
- * ATMEGA64, 128 and 103 do not have more than 2 USARTs
-
-#if CPU_AVR_ATMEGA64 || CPU_AVR_ATMEGA128 || CPU_AVR_ATMEGA103
-       else if (!IS_CTS_ON)
-       {
-               // Disable rx interrupt and tx, enable CTS interrupt
-               // UNTESTED
-               UCSR1B = BV(BIT_RXCIE1) | BV(BIT_RXEN1) | BV(BIT_TXEN1);
-               EIFR |= EIMSKF_CTS;
-               EIMSK |= EIMSKF_CTS;
-       }
-#endif
-
- */
        else
        {
                char c = fifo_pop(txfifo);
@@ -1148,22 +1140,6 @@ DECLARE_ISR(USART3_UDRE_vect)
                UARTDescs[SER_UART3].sending = false;
 #endif
        }
-
-/**
- * ATMEGA64, 128 and 103 do not have more than 2 USARTs
-
-#if CPU_AVR_ATMEGA64 || CPU_AVR_ATMEGA128 || CPU_AVR_ATMEGA103
-       else if (!IS_CTS_ON)
-       {
-               // Disable rx interrupt and tx, enable CTS interrupt
-               // UNTESTED
-               UCSR1B = BV(BIT_RXCIE1) | BV(BIT_RXEN1) | BV(BIT_TXEN1);
-               EIFR |= EIMSKF_CTS;
-               EIMSK |= EIMSKF_CTS;
-       }
-#endif
-
- */
        else
        {
                char c = fifo_pop(txfifo);