]> cloudbase.mooo.com Git - z180-stamp.git/blame - avr/serial.c
Remove flow control, factor out ring buffer
[z180-stamp.git] / avr / serial.c
CommitLineData
0c5890bb
L
1/*
2 */
3
4#include <avr/io.h>
5#include <avr/interrupt.h>
6#include <util/atomic.h>
7#include <errno.h>
8#include <stdio.h>
9
762a42ef 10#include "ring.h"
0c5890bb
L
11#include "serial.h"
12
13
14static int _write(char c, FILE *stream);
15static FILE mystdout = FDEV_SETUP_STREAM(_write,
16 NULL, _FDEV_SETUP_WRITE);
17
0c5890bb 18
0c5890bb 19
762a42ef 20#define BUFFER_SIZE 64
0c5890bb
L
21
22#if ((BUFFER_SIZE-1) & BUFFER_SIZE)
23# error: BUFFER_SIZE not power of 2
24#endif
25
26#if ((BUFFER_SIZE) > 256)
27# error: BUFFER_SIZE
28#endif
29
30struct ring rx_ring;
31struct ring tx_ring;
32uint8_t rx_ring_buffer[BUFFER_SIZE];
33uint8_t tx_ring_buffer[BUFFER_SIZE];
34
35
0c5890bb
L
36
37/* Initialize UART */
38
39void usart0_setup(void) {
40
41 ATOMIC_BLOCK(ATOMIC_RESTORESTATE) {
42
43 PRR0 &= ~_BV(PRUSART0);
44 UCSR0B = 0;
45
46 /* Initialize ring buffers. */
47 ring_init(&rx_ring, rx_ring_buffer, BUFFER_SIZE);
48 ring_init(&tx_ring, tx_ring_buffer, BUFFER_SIZE);
49
762a42ef
L
50 UCSR0A = 0;
51 UBRR0 = F_CPU / BAUD / 16 - 1;
0c5890bb
L
52 UCSR0B = _BV(RXCIE0) | _BV(RXEN0) | _BV(TXEN0);
53 UCSR0C = 3 << UCSZ00;
54 };
55}
56
762a42ef 57/*--------------------------------------------------------------------------*/
0c5890bb
L
58
59/* UART RXC interrupt */
60
61ISR(USART0_RX_vect)
62{
63 uint8_t d;
64
65 d = UDR0;
762a42ef 66 ring_write_ch(&rx_ring, d);
0c5890bb
L
67}
68
69/* UART UDRE interrupt */
70
71ISR(USART0_UDRE_vect)
72{
762a42ef 73 int d = ring_read_ch(&tx_ring);
0c5890bb 74
762a42ef
L
75 if (d < 0) {
76 /* Disable TX empty interrupt. */
0c5890bb 77 UCSR0B = _BV(RXCIE0) | _BV(RXEN0) | _BV(TXEN0);
0c5890bb 78 } else {
762a42ef 79 UDR0 = d;
0c5890bb
L
80 }
81}
82
0c5890bb
L
83/*--------------------------------------------------------------------------*/
84
85void serial_setup(void)
86{
87 stdout = &mystdout;
88 usart0_setup();
89}
90
91/*--------------------------------------------------------------------------*/
92
93int _write(char c, FILE *stream)
94{
95 (void) stream;
96
97 if (c == '\n')
98 serial_putc('\r');
99 serial_putc(c);
100
101 return 0;
102}
103
104int serial_getc(void)
105{
106 return ring_read_ch(&rx_ring);
107}
108
109void serial_putc(uint8_t data)
110{
111 while (ring_write_ch(&tx_ring, data) < 0)
112 ;
762a42ef
L
113
114 /* Enable the TXE interrupt. */
115 UCSR0B = _BV(RXCIE0) | _BV(RXEN0) | _BV(TXEN0) | _BV(UDRIE0);
0c5890bb
L
116}
117