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