avr-equeue

view serial.c @ 0:b1d590a201df

initial commit
author John Tsiombikas <nuclear@member.fsf.org>
date Wed, 09 Jul 2014 08:58:46 +0300
parents
children 9cb1db5d0e7c
line source
1 #define F_CLK XTAL
2 #define F_CPU XTAL
4 #include <stdio.h>
5 #include <avr/io.h>
6 #include <avr/interrupt.h>
7 #include <avr/power.h>
9 #define BAUD 9600
10 #define UBRR_VAL (F_CLK / 16 / BAUD - 1)
12 static int uart_send_char(char c, FILE *fp);
13 static int uart_get_char(FILE *fp);
15 #define BUF_SZ 32
16 static char outbuf[BUF_SZ];
17 static volatile int out_rd, out_wr;
19 static char inbuf[BUF_SZ];
20 static volatile int in_rd, in_wr;
22 static FILE std_stream = FDEV_SETUP_STREAM(uart_send_char, uart_get_char, _FDEV_SETUP_RW);
26 void init_serial(void)
27 {
28 power_usart0_enable();
30 /* make RXD (D0) an input and TXD (D1) an output */
31 DDRD = (DDRD & 0xfc) | 2;
33 /* set baud generator timer reset value */
34 UBRR0H = (unsigned char)(UBRR_VAL >> 8);
35 UBRR0L = (unsigned char)UBRR_VAL;
37 /* enable rx/tx and recv interrupt */
38 UCSR0B = (1 << RXEN0) | (1 << TXEN0) | (1 << RXCIE0);
39 /* set frame format: 8n1 */
40 UCSR0C = 3 << UCSZ00;
42 stdin = stdout = stderr = &std_stream;
43 }
45 int have_input(void)
46 {
47 return in_wr != in_rd;
48 }
50 #define NEXT_IDX(x) (((x) + 1) % BUF_SZ)
51 static int uart_send_char(char c, FILE *fp)
52 {
53 int next;
55 if(c == '\n') {
56 uart_send_char('\r', fp);
57 }
59 next = NEXT_IDX(out_wr);
60 while(next == out_rd);
62 outbuf[out_wr] = c;
63 out_wr = next;
65 /* enable the Tx data register empty interrupt */
66 UCSR0B |= 1 << UDRIE0;
67 return 0;
68 }
70 static int uart_get_char(FILE *fp)
71 {
72 char c;
73 int next = NEXT_IDX(in_rd);
75 while(in_rd == in_wr);
77 c = inbuf[in_rd];
78 in_rd = next;
79 return c;
80 }
82 ISR(USART_RX_vect)
83 {
84 char c = UDR0;
86 if(c == '\r') {
87 c = '\n';
88 }
90 inbuf[in_wr] = c;
91 in_wr = NEXT_IDX(in_wr);
92 }
94 /* USART Tx data register empty (can send more data) */
95 ISR(USART_UDRE_vect)
96 {
97 if(out_rd != out_wr) {
98 UDR0 = outbuf[out_rd];
99 out_rd = NEXT_IDX(out_rd);
100 } else {
101 /* no more data to send for now, disable the interrupt */
102 UCSR0B &= ~(1 << UDRIE0);
103 }
104 }