a500kbd

annotate src/serial.c @ 2:a4fd9c5a6655

first working version
author John Tsiombikas <nuclear@member.fsf.org>
date Tue, 17 Oct 2017 15:25:33 +0300
parents 8e8e17a0f88e
children
rev   line source
nuclear@2 1 #ifndef F_CPU
nuclear@0 2 #ifdef 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_CPU 1000000
nuclear@0 7 #endif
nuclear@2 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@2 33 unsigned int ubrr_val = F_CPU / 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 }