avr-equeue
diff 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 diff
1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/serial.c Wed Jul 09 08:58:46 2014 +0300 1.3 @@ -0,0 +1,104 @@ 1.4 +#define F_CLK XTAL 1.5 +#define F_CPU XTAL 1.6 + 1.7 +#include <stdio.h> 1.8 +#include <avr/io.h> 1.9 +#include <avr/interrupt.h> 1.10 +#include <avr/power.h> 1.11 + 1.12 +#define BAUD 9600 1.13 +#define UBRR_VAL (F_CLK / 16 / BAUD - 1) 1.14 + 1.15 +static int uart_send_char(char c, FILE *fp); 1.16 +static int uart_get_char(FILE *fp); 1.17 + 1.18 +#define BUF_SZ 32 1.19 +static char outbuf[BUF_SZ]; 1.20 +static volatile int out_rd, out_wr; 1.21 + 1.22 +static char inbuf[BUF_SZ]; 1.23 +static volatile int in_rd, in_wr; 1.24 + 1.25 +static FILE std_stream = FDEV_SETUP_STREAM(uart_send_char, uart_get_char, _FDEV_SETUP_RW); 1.26 + 1.27 + 1.28 + 1.29 +void init_serial(void) 1.30 +{ 1.31 + power_usart0_enable(); 1.32 + 1.33 + /* make RXD (D0) an input and TXD (D1) an output */ 1.34 + DDRD = (DDRD & 0xfc) | 2; 1.35 + 1.36 + /* set baud generator timer reset value */ 1.37 + UBRR0H = (unsigned char)(UBRR_VAL >> 8); 1.38 + UBRR0L = (unsigned char)UBRR_VAL; 1.39 + 1.40 + /* enable rx/tx and recv interrupt */ 1.41 + UCSR0B = (1 << RXEN0) | (1 << TXEN0) | (1 << RXCIE0); 1.42 + /* set frame format: 8n1 */ 1.43 + UCSR0C = 3 << UCSZ00; 1.44 + 1.45 + stdin = stdout = stderr = &std_stream; 1.46 +} 1.47 + 1.48 +int have_input(void) 1.49 +{ 1.50 + return in_wr != in_rd; 1.51 +} 1.52 + 1.53 +#define NEXT_IDX(x) (((x) + 1) % BUF_SZ) 1.54 +static int uart_send_char(char c, FILE *fp) 1.55 +{ 1.56 + int next; 1.57 + 1.58 + if(c == '\n') { 1.59 + uart_send_char('\r', fp); 1.60 + } 1.61 + 1.62 + next = NEXT_IDX(out_wr); 1.63 + while(next == out_rd); 1.64 + 1.65 + outbuf[out_wr] = c; 1.66 + out_wr = next; 1.67 + 1.68 + /* enable the Tx data register empty interrupt */ 1.69 + UCSR0B |= 1 << UDRIE0; 1.70 + return 0; 1.71 +} 1.72 + 1.73 +static int uart_get_char(FILE *fp) 1.74 +{ 1.75 + char c; 1.76 + int next = NEXT_IDX(in_rd); 1.77 + 1.78 + while(in_rd == in_wr); 1.79 + 1.80 + c = inbuf[in_rd]; 1.81 + in_rd = next; 1.82 + return c; 1.83 +} 1.84 + 1.85 +ISR(USART_RX_vect) 1.86 +{ 1.87 + char c = UDR0; 1.88 + 1.89 + if(c == '\r') { 1.90 + c = '\n'; 1.91 + } 1.92 + 1.93 + inbuf[in_wr] = c; 1.94 + in_wr = NEXT_IDX(in_wr); 1.95 +} 1.96 + 1.97 +/* USART Tx data register empty (can send more data) */ 1.98 +ISR(USART_UDRE_vect) 1.99 +{ 1.100 + if(out_rd != out_wr) { 1.101 + UDR0 = outbuf[out_rd]; 1.102 + out_rd = NEXT_IDX(out_rd); 1.103 + } else { 1.104 + /* no more data to send for now, disable the interrupt */ 1.105 + UCSR0B &= ~(1 << UDRIE0); 1.106 + } 1.107 +}