yarf 0.1
Yet Another RepRap Firmware
src/hardware/usart.c
Go to the documentation of this file.
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 
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Defines