]>
cloudbase.mooo.com Git - z180-stamp.git/blob - avr/serial.c
4b3cd42c580e0ca95d8f7a136e7878a6f81925b1
5 #include <avr/interrupt.h>
6 #include <util/atomic.h>
13 static int _write(char c
, FILE *stream
);
14 static FILE mystdout
= FDEV_SETUP_STREAM(_write
,
15 NULL
, _FDEV_SETUP_WRITE
);
17 #define CTL_S ('S'-'@') /* DC3 (Stop) */
18 #define CTL_Q ('Q'-'@') /* DC1 (Start) */
29 static volatile uint8_t stat_tx
;
30 static volatile uint8_t stat_rx
;
36 volatile uint_fast8_t begin
;
37 volatile uint_fast8_t end
;
41 #define BUFFER_SIZE 256
43 #if ((BUFFER_SIZE-1) & BUFFER_SIZE)
44 # error: BUFFER_SIZE not power of 2
47 #if ((BUFFER_SIZE) > 256)
53 uint8_t rx_ring_buffer
[BUFFER_SIZE
];
54 uint8_t tx_ring_buffer
[BUFFER_SIZE
];
57 static void ring_init(struct ring
*ring
, uint8_t *buf
, int size
)
60 ring
->mask
= (size
-1) & 0xff;
65 static int ring_write_ch(struct ring
*ring
, uint8_t ch
)
67 uint_fast8_t ep
= (ring
->end
+ 1) & ring
->mask
;
69 if ((ep
) != ring
->begin
) {
70 ring
->data
[ring
->end
] = ch
;
79 static int ring_write(struct ring
*ring
, uint8_t *data
, int size
)
83 for (i
= 0; i
< size
; i
++) {
84 if (ring_write_ch(ring
, data
[i
]) < 0)
92 static int ring_read_ch(struct ring
*ring
)
95 uint_fast8_t i
= ring
->begin
;
99 ring
->begin
= (i
+1) & ring
->mask
;
106 static int_fast8_t ring_is_empty(struct ring
*ring
)
108 return ring
->begin
== ring
->end
;
112 /* Initialize UART */
114 void usart0_setup(void) {
116 ATOMIC_BLOCK(ATOMIC_RESTORESTATE
) {
118 PRR0
&= ~_BV(PRUSART0
);
121 /* Initialize ring buffers. */
122 ring_init(&rx_ring
, rx_ring_buffer
, BUFFER_SIZE
);
123 ring_init(&tx_ring
, tx_ring_buffer
, BUFFER_SIZE
);
129 UBRR0L
= F_CPU
/ BAUD
/ 8 - 1;
130 UCSR0B
= _BV(RXCIE0
) | _BV(RXEN0
) | _BV(TXEN0
);
131 UCSR0C
= 3 << UCSZ00
;
137 /* UART RXC interrupt */
150 if ((stat_tx
== STOPPED
) || stat_tx
== REQ_STOP
) {
151 UCSR0B
= _BV(RXCIE0
) | _BV(RXEN0
) | _BV(TXEN0
) | _BV(UDRIE0
);
156 ring_write_ch(&rx_ring
, d
);
161 /* UART UDRE interrupt */
163 ISR(USART0_UDRE_vect
)
167 s
= !ring_is_empty(&tx_ring
);
168 if ((s
== 0) || (stat_tx
!= ACTIVE
)) {
169 UCSR0B
= _BV(RXCIE0
) | _BV(RXEN0
) | _BV(TXEN0
);
173 UDR0
= ring_read_ch(&tx_ring
);
179 /*--------------------------------------------------------------------------*/
181 void serial_setup(void)
187 /*--------------------------------------------------------------------------*/
189 int _write(char c
, FILE *stream
)
200 int serial_getc(void)
202 return ring_read_ch(&rx_ring
);
205 void serial_putc(uint8_t data
)
207 while (ring_write_ch(&tx_ring
, data
) < 0)
212 /* Enable the TXE interrupt. */
213 UCSR0B
= _BV(RXCIE0
) | _BV(RXEN0
) | _BV(TXEN0
) | _BV(UDRIE0
);