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