avr-equeue

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