avr-equeue

view serial.c @ 1:9cb1db5d0e7c

foo
author John Tsiombikas <nuclear@member.fsf.org>
date Sun, 13 Jul 2014 12:18:14 +0300
parents b1d590a201df
children 9b7983ee2a89
line source
1 #ifdef XTAL
2 #define F_CLK XTAL
3 #define F_CPU XTAL
4 #else
5 #warning "compiled for 1mhz internal rc osc. serial comms won't work"
6 #define F_CLK 1000000
7 #define F_CPU 1000000
8 #endif
10 #include <stdio.h>
11 #include <avr/io.h>
12 #include <avr/interrupt.h>
13 #include <avr/power.h>
15 #define BAUD 9600
16 #define UBRR_VAL (F_CLK / 16 / BAUD - 1)
18 static int uart_send_char(char c, FILE *fp);
19 static int uart_get_char(FILE *fp);
21 #define BUF_SZ 32
22 static char outbuf[BUF_SZ];
23 static volatile int out_rd, out_wr;
25 static char inbuf[BUF_SZ];
26 static volatile int in_rd, in_wr;
28 static FILE std_stream = FDEV_SETUP_STREAM(uart_send_char, uart_get_char, _FDEV_SETUP_RW);
32 void init_serial(void)
33 {
34 power_usart0_enable();
36 /* make RXD (D0) an input and TXD (D1) an output */
37 DDRD = (DDRD & 0xfc) | 2;
39 /* set baud generator timer reset value */
40 UBRR0H = (unsigned char)(UBRR_VAL >> 8);
41 UBRR0L = (unsigned char)UBRR_VAL;
43 /* enable rx/tx and recv interrupt */
44 UCSR0B = (1 << RXEN0) | (1 << TXEN0) | (1 << RXCIE0);
45 /* set frame format: 8n1 */
46 UCSR0C = 3 << UCSZ00;
48 stdin = stdout = stderr = &std_stream;
49 }
51 int have_input(void)
52 {
53 return in_wr != in_rd;
54 }
56 #define NEXT_IDX(x) (((x) + 1) % BUF_SZ)
57 static int uart_send_char(char c, FILE *fp)
58 {
59 int next;
61 if(c == '\n') {
62 uart_send_char('\r', fp);
63 }
65 next = NEXT_IDX(out_wr);
66 while(next == out_rd);
68 outbuf[out_wr] = c;
69 out_wr = next;
71 /* enable the Tx data register empty interrupt */
72 UCSR0B |= 1 << UDRIE0;
73 return 0;
74 }
76 static int uart_get_char(FILE *fp)
77 {
78 char c;
79 int next = NEXT_IDX(in_rd);
81 while(in_rd == in_wr);
83 c = inbuf[in_rd];
84 in_rd = next;
85 return c;
86 }
88 ISR(USART_RX_vect)
89 {
90 char c = UDR0;
92 if(c == '\r') {
93 c = '\n';
94 }
96 inbuf[in_wr] = c;
97 in_wr = NEXT_IDX(in_wr);
98 }
100 /* USART Tx data register empty (can send more data) */
101 ISR(USART_UDRE_vect)
102 {
103 if(out_rd != out_wr) {
104 UDR0 = outbuf[out_rd];
105 out_rd = NEXT_IDX(out_rd);
106 } else {
107 /* no more data to send for now, disable the interrupt */
108 UCSR0B &= ~(1 << UDRIE0);
109 }
110 }