/* * c't-Bot * * This program is free software; you can redistribute it * and/or modify it under the terms of the GNU General * Public License as published by the Free Software * Foundation; either version 2 of the License, or (at your * option) any later version. * This program is distributed in the hope that it will be * useful, but WITHOUT ANY WARRANTY; without even the implied * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR * PURPOSE. See the GNU General Public License for more details. * You should have received a copy of the GNU General Public * License along with this program; if not, write to the Free * Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, * MA 02111-1307, USA. * */ /*! @file uart.c * @brief Routinen zur seriellen Kommunikation * @author Benjamin Benz (bbe@heise.de) * @date 26.12.05 */ #ifdef MCU #include "ct-Bot.h" #include #include #ifndef NEW_AVR_LIB #include #endif #include "ct-Bot.h" #include "uart.h" #include "command.h" #include "log.h" #ifdef UART_AVAILABLE #define BAUDRATE 57600 #define UART_RX_BUFFER_SIZE 16 /*!< Größe des UART-Puffers */ #define UART_RX_BUFFER_MASK ( UART_RX_BUFFER_SIZE - 1 ) #if ( UART_RX_BUFFER_SIZE & UART_RX_BUFFER_MASK ) #error RX buffer size is not a power of 2 #endif //#define UART_TIMEOUT 20000 /*!< Timeout. Wartet UART_TIMEOUT CPU-Takte */ static uint8 UART_RxBuf[UART_RX_BUFFER_SIZE]; /*!< UART-Puffer */ static volatile uint8 UART_RxHead; /*!< Zeiger für UART-Puffer */ static volatile uint8 UART_RxTail; /*!< Zeiger für UART-Puffer */ //char uart_timeout; /*!< 0, wenn uart_read/uart_send erfolgreich 1, wenn timeout erreicht */ /*! * Initialisiere UART */ void uart_init(void){ #ifdef __AVR_ATmega644__ /* Senden und Empfangen ermöglichen + RX Interrupt an */ UCSR0B= (1<> 8); #else UBRRL = (uint8) (( ((uint32)F_CPU) / 16 / ((uint32)BAUDRATE) - 1) & 0xFF); UBRRH = (uint8) (( ((uint32)F_CPU) / 16 / ((uint32)BAUDRATE) - 1) >> 8); #endif /* Puffer leeren */ UART_RxTail = 0; UART_RxHead = 0; } /*! * Interrupt Handler fuer den Datenempfang per UART */ #ifdef __AVR_ATmega644__ SIGNAL (USART0_RX_vect){ #else SIGNAL (SIG_UART_RECV){ #endif /* Pufferindex berechnen */ UART_RxHead++; /* erhoehen */ UART_RxHead %= UART_RX_BUFFER_MASK; /* Und bei Bedarf umklappen, da Ringpuffer */ if (UART_RxHead == UART_RxTail){ /* TODO Fehler behandeln !! * ERROR! Receive buffer overflow */ } #ifdef __AVR_ATmega644__ UART_RxBuf[UART_RxHead] = UDR0; /* Daten lesen und sichern*/ #else UART_RxBuf[UART_RxHead] = UDR; /* Daten lesen und sichern*/ #endif } /*! * Prüft, ob daten verfügbar * @return Anzahl der verfuegbaren Bytes */ uint8 uart_data_available(void){ if (UART_RxHead == UART_RxTail) /* Puffer leer */ return 0; else if (UART_RxHead > UART_RxTail) /* Schreibzeiger vor Lesezeiger */ return UART_RxHead - UART_RxTail; else /* Schreibzeiger ist schon umgelaufen */ return UART_RxHead - UART_RxTail + UART_RX_BUFFER_SIZE; } /*! * Überträgt ein Zeichen per UART * Achtung ist noch blockierend!!!! * TODO: umstellen auf nicht blockierend und mehr als ein Zeichen * @param data Das Zeichen */ void uart_send_byte(uint8 data){ // Achtung ist noch blockierend!!!! #ifdef __AVR_ATmega644__ while ((UCSR0A & _BV(UDRE0)) ==0){asm volatile("nop"); } // warten bis UART sendebereit UDR0= data; #else while ((UCSRA & _BV(UDRE)) ==0){asm volatile("nop"); } // warten bis UART sendebereit UDR= data; #endif } /*! * Sende Kommando per UART im Little Endian * @param cmd Zeiger auf das Kommando * @return Anzahl der gesendete Bytes */ //#define uart_send_cmd(cmd) uart_write(cmd,sizeof(command_t)); /* int uart_send_cmd(command_t *cmd){ int i; char * ptr = (char*) cmd; for (i=0; i length) count=length; for (i=0; i