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