misc avr fixes
[ros_wild_thumper.git] / avr / nano / uart.c
1 #include <stdlib.h>
2 #include "uart.h"
3 #include <avr/interrupt.h>
4
5 #define UART_UBRR_CALC(BAUD_,FREQ_) ((FREQ_)/((BAUD_)*16L)-1)
6
7 static volatile char read[RINGBUFFER_LEN];
8 static volatile char *in_read_ptr;
9 static volatile char *out_read_ptr;
10
11 ISR(USART_RX_vect) {
12         // update read from uart
13         if (UCSR0A & (1<<RXC0)) {
14                 *in_read_ptr = UDR0;
15
16                 if (in_read_ptr < read + RINGBUFFER_LEN - 1) in_read_ptr++;
17                 else in_read_ptr = (char *)read;
18         }
19 }
20
21
22 void setup_uart(unsigned int rate) {
23         UCSR0B = (1<<TXEN0) | (1<<RXEN0); // UART TX & RX
24         UCSR0B |= (1<<RXCIE0);          // RX Interrupt
25         UCSR0C = (3<<UCSZ00); // Asynchron 8N1
26
27         UBRR0H = (uint8_t)(UART_UBRR_CALC(rate, F_CPU) >> 8);
28         UBRR0L = (uint8_t)UART_UBRR_CALC(rate, F_CPU);
29
30         in_read_ptr = out_read_ptr = read;
31 }
32
33
34 void uart_putc(char *c) {
35         while (!(UCSR0A & (1<<UDRE0)));
36         UDR0 = *c;
37 }
38
39
40 int uart_putchar(char c, FILE *stream)
41 {
42         uart_putc(&c);
43         return 0;
44 }
45
46
47 void uart_puts(char *s) {
48         char *c;
49
50         for (c = s; *c != '\0'; c++)
51                 uart_putc(c);
52 }
53
54
55 int uart_getchar(FILE *stream)
56 {
57         return uart_getc();
58 }
59
60
61 int uart_getc() {
62         while (!(UCSR0A & (1<<RXC0)));
63         return UDR0;
64 }
65
66
67 void uart_setup_stdout() {
68         fdevopen(uart_putchar, uart_getchar);
69 }
70
71
72 void uart_stream_update(ringbuffer_t *buffer) {
73         // update write to uart
74         if (buffer->out_write_ptr != buffer->in_write_ptr) {
75                 if (UCSR0A & (1<<UDRE0)) {
76                         UDR0 = *buffer->out_write_ptr;
77                         if (buffer->out_write_ptr < buffer->write + RINGBUFFER_LEN - 1) buffer->out_write_ptr++;
78                         else buffer->out_write_ptr = buffer->write;
79                 }
80         }
81
82         // update read from uart        
83         if (in_read_ptr != out_read_ptr) {
84                 *buffer->in_read_ptr = *out_read_ptr;
85
86                 // update newline chars
87                 if (buffer->block_read == *buffer->in_read_ptr) buffer->newlines++;
88
89                 if (buffer->in_read_ptr < buffer->read + RINGBUFFER_LEN - 1) buffer->in_read_ptr++;
90                 else buffer->in_read_ptr = buffer->read;
91
92                 // move pointer
93                 if (out_read_ptr < read + RINGBUFFER_LEN - 1) out_read_ptr++;
94                 else out_read_ptr = read;
95         }
96 }
97