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