a500kbd
annotate src/serial.c @ 0:8e8e17a0f88e
initial commit: serial comms up, kbd doesn't respond
author | John Tsiombikas <nuclear@member.fsf.org> |
---|---|
date | Thu, 12 Oct 2017 04:08:48 +0300 |
parents | |
children | a4fd9c5a6655 |
rev | line source |
---|---|
nuclear@0 | 1 #ifdef XTAL |
nuclear@0 | 2 #define F_CLK XTAL |
nuclear@0 | 3 #define F_CPU XTAL |
nuclear@0 | 4 #else |
nuclear@0 | 5 #warning "compiled for 1mhz internal rc osc. serial comms won't work" |
nuclear@0 | 6 #define F_CLK 1000000 |
nuclear@0 | 7 #define F_CPU 1000000 |
nuclear@0 | 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 <util/delay.h> |
nuclear@0 | 14 #include <avr/power.h> |
nuclear@0 | 15 |
nuclear@0 | 16 static int uart_send_char(char c, FILE *fp); |
nuclear@0 | 17 static int uart_get_char(FILE *fp); |
nuclear@0 | 18 |
nuclear@0 | 19 #define BUF_SZ 16 |
nuclear@0 | 20 #define BUF_IDX_MASK (BUF_SZ - 1) |
nuclear@0 | 21 #define NEXT_IDX(x) (((x) + 1) & BUF_IDX_MASK) |
nuclear@0 | 22 static char outbuf[BUF_SZ]; |
nuclear@0 | 23 static volatile unsigned char out_rd, out_wr; |
nuclear@0 | 24 static char inbuf[BUF_SZ]; |
nuclear@0 | 25 static volatile unsigned char in_rd, in_wr; |
nuclear@0 | 26 |
nuclear@0 | 27 static FILE std_stream = FDEV_SETUP_STREAM(uart_send_char, uart_get_char, _FDEV_SETUP_RW); |
nuclear@0 | 28 |
nuclear@0 | 29 |
nuclear@0 | 30 |
nuclear@0 | 31 void init_serial(long baud) |
nuclear@0 | 32 { |
nuclear@0 | 33 unsigned int ubrr_val = F_CLK / 16 / baud - 1; |
nuclear@0 | 34 |
nuclear@0 | 35 power_usart0_enable(); |
nuclear@0 | 36 |
nuclear@0 | 37 /* set baud generator timer reset value */ |
nuclear@0 | 38 UBRR0H = (unsigned char)(ubrr_val >> 8); |
nuclear@0 | 39 UBRR0L = (unsigned char)ubrr_val; |
nuclear@0 | 40 |
nuclear@0 | 41 /* enable rx/tx and recv interrupt */ |
nuclear@0 | 42 UCSR0B = (1 << RXEN0) | (1 << TXEN0) | (1 << RXCIE0); |
nuclear@0 | 43 /* set frame format: 8n1 */ |
nuclear@0 | 44 UCSR0C = 3 << UCSZ00; |
nuclear@0 | 45 |
nuclear@0 | 46 stdin = stdout = stderr = &std_stream; |
nuclear@0 | 47 } |
nuclear@0 | 48 |
nuclear@0 | 49 int have_input(void) |
nuclear@0 | 50 { |
nuclear@0 | 51 return in_wr != in_rd; |
nuclear@0 | 52 } |
nuclear@0 | 53 |
nuclear@0 | 54 static int uart_send_char(char c, FILE *fp) |
nuclear@0 | 55 { |
nuclear@0 | 56 /*int next;*/ |
nuclear@0 | 57 |
nuclear@0 | 58 while((UCSR0A & (1 << UDRE0)) == 0); |
nuclear@0 | 59 UDR0 = (unsigned char)c; |
nuclear@0 | 60 #if 0 |
nuclear@0 | 61 next = NEXT_IDX(out_wr); |
nuclear@0 | 62 while(next == out_rd); |
nuclear@0 | 63 |
nuclear@0 | 64 outbuf[out_wr] = c; |
nuclear@0 | 65 out_wr = next; |
nuclear@0 | 66 |
nuclear@0 | 67 /* enable the Tx data register empty interrupt */ |
nuclear@0 | 68 UCSR0B |= 1 << UDRIE0; |
nuclear@0 | 69 #endif |
nuclear@0 | 70 return 0; |
nuclear@0 | 71 } |
nuclear@0 | 72 |
nuclear@0 | 73 static int uart_get_char(FILE *fp) |
nuclear@0 | 74 { |
nuclear@0 | 75 char c; |
nuclear@0 | 76 |
nuclear@0 | 77 while(in_rd == in_wr); |
nuclear@0 | 78 |
nuclear@0 | 79 c = inbuf[in_rd]; |
nuclear@0 | 80 in_rd = NEXT_IDX(in_rd); |
nuclear@0 | 81 return c; |
nuclear@0 | 82 } |
nuclear@0 | 83 |
nuclear@0 | 84 ISR(USART_RX_vect) |
nuclear@0 | 85 { |
nuclear@0 | 86 char c = UDR0; |
nuclear@0 | 87 |
nuclear@0 | 88 inbuf[in_wr] = c; |
nuclear@0 | 89 in_wr = NEXT_IDX(in_wr); |
nuclear@0 | 90 } |
nuclear@0 | 91 |
nuclear@0 | 92 /* USART Tx data register empty (can send more data) */ |
nuclear@0 | 93 ISR(USART_UDRE_vect) |
nuclear@0 | 94 { |
nuclear@0 | 95 if(out_rd != out_wr) { |
nuclear@0 | 96 UDR0 = outbuf[out_rd]; |
nuclear@0 | 97 out_rd = NEXT_IDX(out_rd); |
nuclear@0 | 98 } else { |
nuclear@0 | 99 /* no more data to send for now, disable the interrupt */ |
nuclear@0 | 100 UCSR0B &= ~(1 << UDRIE0); |
nuclear@0 | 101 } |
nuclear@0 | 102 } |