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