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 +}