yarf 0.1
Yet Another RepRap Firmware
|
00001 /* 00002 * usart.c 00003 * 00004 * Copyright 2011 Pieter Agten 00005 * 00006 * This file is part of Yarf. 00007 * 00008 * Yarf is free software: you can redistribute it and/or modify 00009 * it under the terms of the GNU General Public License as published by 00010 * the Free Software Foundation, either version 3 of the License, or 00011 * (at your option) any later version. 00012 * 00013 * Yarf is distributed in the hope that it will be useful, 00014 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00015 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00016 * GNU General Public License for more details. 00017 * 00018 * You should have received a copy of the GNU General Public License 00019 * along with Yarf. If not, see <http://www.gnu.org/licenses/>. 00020 */ 00021 00030 #include "usart.h" 00031 00032 #include "yarf.h" 00033 #include "fastio.h" 00034 00035 #include <stdint.h> 00036 #include <stdio.h> 00037 #include <math.h> 00038 #include <avr/interrupt.h> 00039 00046 #define BAUD HOST_BAUD_RATE 00047 #include <util/setbaud.h> 00048 00054 #define ERROR_CHARACTER ((char)0xFE) 00055 00056 00061 static volatile char rx_buffer[USART0_RECEIVE_BUFFER_SIZE]; 00066 static volatile uint8_t rxbuf_head; 00071 static volatile uint8_t rxbuf_tail; 00072 00079 static inline uint8_t 00080 buf_index_next(uint8_t index) 00081 { 00082 index += 1; 00083 if (index == USART0_RECEIVE_BUFFER_SIZE) { 00084 index = 0; 00085 } 00086 return index; 00087 } 00088 00095 static inline uint8_t 00096 buf_index_prev(uint8_t index) 00097 { 00098 if (index == 0) { 00099 return USART0_RECEIVE_BUFFER_SIZE - 1; 00100 } 00101 00102 return index - 1; 00103 } 00104 00110 static inline bool 00111 buf_full(void) 00112 { 00113 return buf_index_next(rxbuf_head) == rxbuf_tail; 00114 } 00115 00121 static inline bool 00122 buf_empty(void) 00123 { 00124 return rxbuf_head == rxbuf_tail; 00125 } 00126 00130 static inline void 00131 usart0_init(void) 00132 { 00133 /* Set baud rate using the helper macros */ 00134 UBRR0H = UBRRH_VALUE; 00135 UBRR0L = UBRRL_VALUE; 00136 00137 #if USE_2X 00138 UCSR0A |= (1 << U2X0); 00139 #else 00140 UCSR0A &= ~(1 << U2X0); 00141 #endif 00142 00143 /* Set frame format to 8N1 */ 00144 UCSR0C = (3 << UCSZ00); 00145 00146 /* Enable USART0 receiver and transmitter and the receive interrupt flag */ 00147 UCSR0B = _BV(TXEN0) | _BV(RXEN0) | _BV(RXCIE0); 00148 00149 //TODO: clear serial buffer? 00150 } 00151 00152 00153 00154 00165 static int 00166 usart0_putchar(char c, FILE *stream) 00167 { 00168 if (c == '\n') { 00169 /* Add carriage return before line ending */ 00170 usart0_putchar('\r', stream); 00171 } 00172 00173 /* Wait for empty transmit buffer */ 00174 loop_until_bit_is_set(UCSR0A, UDRE0); 00175 00176 /* Put character into buffer, sends the data */ 00177 UDR0 = c; 00178 00179 return 0; 00180 } 00181 00182 00197 static int 00198 usart0_getchar(FILE *stream) 00199 { 00200 while (buf_empty()) { 00201 /* Wait for data to arrive in the buffer */ 00202 } 00203 00204 /* Get and return received data from buffer */ 00205 int c = (int)rx_buffer[rxbuf_tail]; 00206 rxbuf_tail = buf_index_next(rxbuf_tail); 00207 if (c == ERROR_CHARACTER) { 00208 c = _FDEV_ERR; 00209 } 00210 return c; 00211 } 00212 00213 00222 static inline void 00223 read_character(void) 00224 { 00225 if (buf_full() || UCSR0A & (_BV(FE0) | _BV(DOR0) | _BV(UPE0))) { 00226 /* An error has occurred. Insert a special error character into this line 00227 * so the parser will mark it as erroneous. */ 00228 uint8_t last_character_received_index = buf_index_prev(rxbuf_head); //TODO: what if error on first char? 00229 rx_buffer[last_character_received_index] = ERROR_CHARACTER; 00230 00231 /* Read character just to remove it from the hardware FIFO buffer */ 00232 UDR0; 00233 return; 00234 } 00235 00236 rx_buffer[rxbuf_head] = UDR0; 00237 rxbuf_head = buf_index_next(rxbuf_head); 00238 } 00239 00244 ISR(USART0_RX_vect,ISR_BLOCK) 00245 { 00246 read_character(); 00247 } 00248 00249 00250 void 00251 usart_init(void) 00252 { 00253 usart0_init(); 00254 rxbuf_head = 0; 00255 rxbuf_tail = 0; 00256 00257 stdout = stdin = stderr = &usart0_stream; 00258 } 00259 00260 00261 void 00262 usart0_try_read_character(void) 00263 { 00264 if (UCSR0A & _BV(RXC0)) { 00265 read_character(); 00266 } 00267 } 00268 00269 00270 FILE usart0_stream = FDEV_SETUP_STREAM(usart0_putchar, usart0_getchar, _FDEV_SETUP_RW); 00271 00272