avr_test_simm72_dram
view serial.c @ 0:c47d05df0667
initial commit
author | John Tsiombikas <nuclear@member.fsf.org> |
---|---|
date | Tue, 07 Mar 2017 23:50:45 +0200 |
parents | |
children | bd6ad00cb1bc |
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 <util/delay.h>
14 #include <avr/power.h>
16 static int uart_send_char(char c, FILE *fp);
17 static int uart_get_char(FILE *fp);
19 #define BUF_SZ 64
20 #define BUF_IDX_MASK 0x3f
21 #define NEXT_IDX(x) (((x) + 1) & BUF_IDX_MASK)
22 static char outbuf[BUF_SZ];
23 static volatile unsigned char out_rd, out_wr;
24 static char inbuf[BUF_SZ];
25 static volatile unsigned char in_rd, in_wr;
27 static FILE std_stream = FDEV_SETUP_STREAM(uart_send_char, uart_get_char, _FDEV_SETUP_RW);
31 void init_serial(long baud)
32 {
33 unsigned int ubrr_val = F_CLK / 16 / baud - 1;
35 power_usart0_enable();
37 /* set baud generator timer reset value */
38 UBRR0H = (unsigned char)(ubrr_val >> 8);
39 UBRR0L = (unsigned char)ubrr_val;
41 /* enable rx/tx and recv interrupt */
42 UCSR0B = (1 << RXEN0) | (1 << TXEN0) | (1 << RXCIE0);
43 /* set frame format: 8n1 */
44 UCSR0C = 3 << UCSZ00;
46 stdin = stdout = stderr = &std_stream;
47 }
49 int have_input(void)
50 {
51 return in_wr != in_rd;
52 }
54 static int uart_send_char(char c, FILE *fp)
55 {
56 int next;
58 if(c == '\n') {
59 uart_send_char('\r', fp);
60 }
62 next = NEXT_IDX(out_wr);
63 while(next == out_rd);
65 outbuf[out_wr] = c;
66 out_wr = next;
68 /* enable the Tx data register empty interrupt */
69 UCSR0B |= 1 << UDRIE0;
70 return 0;
71 }
73 static int uart_get_char(FILE *fp)
74 {
75 char c;
77 while(in_rd == in_wr);
79 c = inbuf[in_rd];
80 in_rd = NEXT_IDX(in_rd);
81 return c;
82 }
84 ISR(USART0_RX_vect)
85 {
86 char c = UDR0;
88 if(c == '\r') {
89 c = '\n';
90 }
92 inbuf[in_wr] = c;
93 in_wr = NEXT_IDX(in_wr);
94 }
96 /* USART Tx data register empty (can send more data) */
97 ISR(USART0_UDRE_vect)
98 {
99 if(out_rd != out_wr) {
100 UDR0 = outbuf[out_rd];
101 out_rd = NEXT_IDX(out_rd);
102 } else {
103 /* no more data to send for now, disable the interrupt */
104 UCSR0B &= ~(1 << UDRIE0);
105 }
106 }