import sd-reader_source_20120612
[protos/imu.git] / uart.c
diff --git a/uart.c b/uart.c
new file mode 100644 (file)
index 0000000..df5e1fd
--- /dev/null
+++ b/uart.c
@@ -0,0 +1,198 @@
+
+/*
+ * Copyright (c) 2006-2012 by Roland Riegel <feedback@roland-riegel.de>
+ *
+ * This file is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <stdio.h>
+#include <avr/interrupt.h>
+#include <avr/io.h>
+#include <avr/pgmspace.h>
+#include <avr/sfr_defs.h>
+#include <avr/sleep.h>
+
+#include "uart.h"
+
+/* some mcus have multiple uarts */
+#ifdef UDR0
+#define UBRRH UBRR0H
+#define UBRRL UBRR0L
+#define UDR UDR0
+
+#define UCSRA UCSR0A
+#define UDRE UDRE0
+#define RXC RXC0
+
+#define UCSRB UCSR0B
+#define RXEN RXEN0
+#define TXEN TXEN0
+#define RXCIE RXCIE0
+
+#define UCSRC UCSR0C
+#define URSEL 
+#define UCSZ0 UCSZ00
+#define UCSZ1 UCSZ01
+#define UCSRC_SELECT 0
+#else
+#define UCSRC_SELECT (1 << URSEL)
+#endif
+
+#ifndef USART_RXC_vect
+#if defined(UART0_RX_vect)
+#define USART_RXC_vect UART0_RX_vect
+#elif defined(UART_RX_vect)
+#define USART_RXC_vect UART_RX_vect
+#elif defined(USART0_RX_vect)
+#define USART_RXC_vect USART0_RX_vect
+#elif defined(USART_RX_vect)
+#define USART_RXC_vect USART_RX_vect
+#elif defined(USART0_RXC_vect)
+#define USART_RXC_vect USART0_RXC_vect
+#elif defined(USART_RXC_vect)
+#define USART_RXC_vect USART_RXC_vect
+#else
+#error "Uart receive complete interrupt not defined!"
+#endif
+#endif
+
+#define BAUD 9600UL
+#define UBRRVAL (F_CPU/(BAUD*16)-1)
+#define USE_SLEEP 1
+
+void uart_init()
+{
+    /* set baud rate */
+    UBRRH = UBRRVAL >> 8;
+    UBRRL = UBRRVAL & 0xff;
+    /* set frame format: 8 bit, no parity, 1 bit */
+    UCSRC = UCSRC_SELECT | (1 << UCSZ1) | (1 << UCSZ0);
+    /* enable serial receiver and transmitter */
+#if !USE_SLEEP
+    UCSRB = (1 << RXEN) | (1 << TXEN);
+#else
+    UCSRB = (1 << RXEN) | (1 << TXEN) | (1 << RXCIE);
+#endif
+}
+
+void uart_putc(uint8_t c)
+{
+    if(c == '\n')
+        uart_putc('\r');
+
+    /* wait until transmit buffer is empty */
+    while(!(UCSRA & (1 << UDRE)));
+
+    /* send next byte */
+    UDR = c;
+}
+
+void uart_putc_hex(uint8_t b)
+{
+    /* upper nibble */
+    if((b >> 4) < 0x0a)
+        uart_putc((b >> 4) + '0');
+    else
+        uart_putc((b >> 4) - 0x0a + 'a');
+
+    /* lower nibble */
+    if((b & 0x0f) < 0x0a)
+        uart_putc((b & 0x0f) + '0');
+    else
+        uart_putc((b & 0x0f) - 0x0a + 'a');
+}
+
+void uart_putw_hex(uint16_t w)
+{
+    uart_putc_hex((uint8_t) (w >> 8));
+    uart_putc_hex((uint8_t) (w & 0xff));
+}
+
+void uart_putdw_hex(uint32_t dw)
+{
+    uart_putw_hex((uint16_t) (dw >> 16));
+    uart_putw_hex((uint16_t) (dw & 0xffff));
+}
+
+void uart_putw_dec(uint16_t w)
+{
+    uint16_t num = 10000;
+    uint8_t started = 0;
+
+    while(num > 0)
+    {
+        uint8_t b = w / num;
+        if(b > 0 || started || num == 1)
+        {
+            uart_putc('0' + b);
+            started = 1;
+        }
+        w -= b * num;
+
+        num /= 10;
+    }
+}
+
+void uart_putdw_dec(uint32_t dw)
+{
+    uint32_t num = 1000000000;
+    uint8_t started = 0;
+
+    while(num > 0)
+    {
+        uint8_t b = dw / num;
+        if(b > 0 || started || num == 1)
+        {
+            uart_putc('0' + b);
+            started = 1;
+        }
+        dw -= b * num;
+
+        num /= 10;
+    }
+}
+
+void uart_puts(const char* str)
+{
+    while(*str)
+        uart_putc(*str++);
+}
+
+void uart_puts_p(PGM_P str)
+{
+    while(1)
+    {
+        uint8_t b = pgm_read_byte_near(str++);
+        if(!b)
+            break;
+
+        uart_putc(b);
+    }
+}
+
+uint8_t uart_getc()
+{
+    /* wait until receive buffer is full */
+#if USE_SLEEP
+    uint8_t sreg = SREG;
+    sei();
+
+    while(!(UCSRA & (1 << RXC)))
+        sleep_mode();
+
+    SREG = sreg;
+#else
+    while(!(UCSRA & (1 << RXC)));
+#endif
+
+    uint8_t b = UDR;
+    if(b == '\r')
+        b = '\n';
+
+    return b;
+}
+
+EMPTY_INTERRUPT(USART_RXC_vect)
+