Permalink
Browse files

Add UART library.

  • Loading branch information...
1 parent 391a0e6 commit 01261ca1b54c046081d47ecf2fc321ebf2cc94b4 @tuupola committed Dec 17, 2011
Showing with 203 additions and 0 deletions.
  1. +74 −0 tpic6b595_spi/uart/uart.c
  2. +17 −0 tpic6b595_spi/uart/uart.h
  3. +112 −0 tpic6b595_spi/uart/uart_async.c
View
74 tpic6b595_spi/uart/uart.c
@@ -0,0 +1,74 @@
+/*
+ * Copyright 2011 Mika Tuupola
+ *
+ * Licensed under the MIT license:
+ * http://www.opensource.org/licenses/mit-license.php
+ *
+ */
+
+#include <avr/io.h>
+#include <stdio.h>
+
+#ifndef F_CPU
+#define F_CPU 16000000UL
+#endif
+
+#ifndef BAUD
+#define BAUD 9600
+#endif
+#include <util/setbaud.h>
+
+/* http://www.cs.mun.ca/~rod/Winter2007/4723/notes/serial/serial.html */
+
+#if defined (__AVR_ATmega32U4__)
+void uart_init(void) {
+ UBRR1H = UBRRH_VALUE;
+ UBRR1L = UBRRL_VALUE;
+
+#if USE_2X
+ UCSR1A |= _BV(U2X1);
+#else
+ UCSR1A &= ~(_BV(U2X1));
+#endif
+
+ UCSR1C = _BV(UCSZ11) | _BV(UCSZ10); /* 8-bit data */
+ UCSR1B = _BV(RXEN1) | _BV(TXEN1); /* Enable RX and TX */
+}
+#else
+void uart_init(void) {
+ UBRR0H = UBRRH_VALUE;
+ UBRR0L = UBRRL_VALUE;
+
+#if USE_2X
+ UCSR0A |= _BV(U2X0);
+#else
+ UCSR0A &= ~(_BV(U2X0));
+#endif
+
+ UCSR0C = _BV(UCSZ01) | _BV(UCSZ00); /* 8-bit data */
+ UCSR0B = _BV(RXEN0) | _BV(TXEN0); /* Enable RX and TX */
+}
+#endif
+
+void uart_putchar(char c, FILE *stream) {
+ if (c == '\n') {
+ uart_putchar('\r', stream);
+ }
+#if defined (__AVR_ATmega32U4__)
+ loop_until_bit_is_set(UCSR1A, UDRE1);
+ UDR1 = c;
+#else
+ loop_until_bit_is_set(UCSR0A, UDRE0);
+ UDR0 = c;
+#endif
+}
+
+char uart_getchar(FILE *stream) {
+#if defined (__AVR_ATmega32U4__)
+ loop_until_bit_is_set(UCSR1A, RXC1);
+ return UDR1;
+#else
+ loop_until_bit_is_set(UCSR0A, RXC0);
+ return UDR0;
+#endif
+}
View
17 tpic6b595_spi/uart/uart.h
@@ -0,0 +1,17 @@
+/*
+ * Copyright 2011 Mika Tuupola
+ *
+ * Licensed under the MIT license:
+ * http://www.opensource.org/licenses/mit-license.php
+ *
+ */
+
+void uart_putchar(char c, FILE *stream);
+char uart_getchar(FILE *stream);
+
+void uart_init(void);
+
+/* http://www.ermicro.com/blog/?p=325 */
+
+FILE uart_output = FDEV_SETUP_STREAM(uart_putchar, NULL, _FDEV_SETUP_WRITE);
+FILE uart_input = FDEV_SETUP_STREAM(NULL, uart_getchar, _FDEV_SETUP_READ);
View
112 tpic6b595_spi/uart/uart_async.c
@@ -0,0 +1,112 @@
+/*
+ * Copyright 2011 Mika Tuupola
+ *
+ * Licensed under the MIT license:
+ * http://www.opensource.org/licenses/mit-license.php
+ *
+ */
+
+/* Based on Atmel Application Note AVR 306 */
+
+#include <avr/io.h>
+#include <avr/interrupt.h>
+#include <stdio.h>
+
+#ifndef BAUD
+#define BAUD 9600
+#endif
+#include <util/setbaud.h>
+
+#ifndef UART_RX_BUFFER_SIZE
+#define UART_RX_BUFFER_SIZE 64
+#endif
+
+#ifndef UART_TX_BUFFER_SIZE
+#define UART_TX_BUFFER_SIZE 64
+#endif
+
+struct tx_ring {
+ int buffer[UART_TX_BUFFER_SIZE];
+ int start;
+ int end;
+};
+
+struct rx_ring {
+ int buffer[UART_RX_BUFFER_SIZE];
+ int start;
+ int end;
+};
+
+static struct tx_ring tx_buffer;
+static struct rx_ring rx_buffer;
+
+/* http://www.cs.mun.ca/~rod/Winter2007/4723/notes/serial/serial.html */
+
+void uart_init(void) {
+
+ tx_buffer.start = 0;
+ tx_buffer.end = 0;
+
+ rx_buffer.start = 0;
+ rx_buffer.end = 0;
+
+ UBRR0H = UBRRH_VALUE;
+ UBRR0L = UBRRL_VALUE;
+
+ UCSR0C = _BV(UCSZ01) | _BV(UCSZ00); /* 8-bit data */
+ UCSR0B = _BV(RXEN0) | _BV(TXEN0); /* Enable RX and TX */
+
+ sei();
+}
+
+
+//int uart_putchar(char c, FILE *stream) {
+void uart_putchar(char c, FILE *stream) {
+ if (c == '\n') {
+ uart_putchar('\r', stream);
+ }
+
+ int write_pointer = (tx_buffer.end + 1) % UART_TX_BUFFER_SIZE;
+
+ if (write_pointer != tx_buffer.start){
+ tx_buffer.buffer[tx_buffer.end] = c;
+ tx_buffer.end = write_pointer;
+
+ /* Data available. Enable the transmit interrupt for serial port 0. */
+ UCSR0B |= _BV(UDRIE0);
+ }
+
+ //return 0;
+}
+
+char uart_getchar(FILE *stream) {
+ int read_pointer = (rx_buffer.start + 1) % UART_RX_BUFFER_SIZE;
+
+ rx_buffer.start = read_pointer;
+ return rx_buffer.buffer[read_pointer];
+}
+
+ISR(USART_RX_vect) {
+ int write_pointer = (rx_buffer.end + 1) % UART_RX_BUFFER_SIZE;
+
+ /* Add next byte to ringbuffer if it has space available. */
+ if (write_pointer != rx_buffer.start){
+ rx_buffer.buffer[rx_buffer.end] = UDR0;
+ rx_buffer.end = write_pointer;
+ }
+}
+
+ISR(USART_UDRE_vect){
+ int read_pointer = (tx_buffer.start + 1) % UART_TX_BUFFER_SIZE;
+
+ /* Transmit next byte if data available in ringbuffer. */
+ if (read_pointer != tx_buffer.end) {
+ UDR0 = tx_buffer.buffer[read_pointer];
+ tx_buffer.start = read_pointer;
+ } else {
+ /* Nothing to send. Disable the transmit interrupt for serial port 0. */
+ UCSR0B &= ~_BV(UDRIE0);
+ }
+}
+
+

0 comments on commit 01261ca

Please sign in to comment.