00001 /** 00002 \file Robots/LoBot/irccm/LoIO.c 00003 \brief Serial I/O API for Robolocust control program running on iRobot 00004 Create Command Module. 00005 00006 This file defines the functions for serial port I/O needed by the 00007 Robolocust iRobot Create Command Module control program. 00008 */ 00009 00010 /* 00011 ************************************************************************ 00012 * The iLab Neuromorphic Vision C++ Toolkit - Copyright (C) 2000-2005 * 00013 * by the University of Southern California (USC) and the iLab at USC. * 00014 * See http://iLab.usc.edu for information about this project. * 00015 * * 00016 * Major portions of the iLab Neuromorphic Vision Toolkit are protected * 00017 * under the U.S. patent ``Computation of Intrinsic Perceptual Saliency * 00018 * in Visual Environments, and Applications'' by Christof Koch and * 00019 * Laurent Itti, California Institute of Technology, 2001 (patent * 00020 * pending; application number 09/912,225 filed July 23, 2001; see * 00021 * http://pair.uspto.gov/cgi-bin/final/home.pl for current status). * 00022 ************************************************************************ 00023 * This file is part of the iLab Neuromorphic Vision C++ Toolkit. * 00024 * * 00025 * The iLab Neuromorphic Vision C++ Toolkit is free software; you can * 00026 * redistribute it and/or modify it under the terms of the GNU General * 00027 * Public License as published by the Free Software Foundation; either * 00028 * version 2 of the License, or (at your option) any later version. * 00029 * * 00030 * The iLab Neuromorphic Vision C++ Toolkit is distributed in the hope * 00031 * that it will be useful, but WITHOUT ANY WARRANTY; without even the * 00032 * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR * 00033 * PURPOSE. See the GNU General Public License for more details. * 00034 * * 00035 * You should have received a copy of the GNU General Public License * 00036 * along with the iLab Neuromorphic Vision C++ Toolkit; if not, write * 00037 * to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, * 00038 * Boston, MA 02111-1307 USA. * 00039 ************************************************************************ 00040 */ 00041 00042 /* 00043 Primary maintainer for this file: mviswana usc edu 00044 $HeadURL: svn://isvn.usc.edu/software/invt/trunk/saliency/src/Robots/LoBot/irccm/LoIO.c $ 00045 $Id: LoIO.c 13744 2010-08-02 02:55:15Z mviswana $ 00046 */ 00047 00048 /*------------------------------ HEADERS ------------------------------*/ 00049 00050 // lobot headers 00051 #include "LoIO.h" 00052 #include "LoTimer.h" 00053 #include "LoOpenInterface.h" 00054 00055 // AVR headers 00056 #include <avr/io.h> 00057 #include <avr/interrupt.h> 00058 00059 /*------------------------------ GLOBALS ------------------------------*/ 00060 00061 // When I/O operations fail, we set a flag to let clients know 00062 static char g_io_error ; 00063 00064 /*-------------------------- INITIALIZATION ---------------------------*/ 00065 00066 // Set up the serial port 00067 void lo_init_comm() 00068 { 00069 UBRR0 = LOBOT_OI_UBRR_57600 ; 00070 UCSR0B = (_BV(TXEN0) | _BV(RXEN0)) ; // enable transmit & receive 00071 UCSR0C = (_BV(UCSZ00) | _BV(UCSZ01)) ; // 8-bit data 00072 } 00073 00074 // Reset communication speed on both Create robot and Command Module 00075 void lo_reset_baud(int baud_rate) 00076 { 00077 if (baud_rate < LOBOT_OI_BAUD_300 || baud_rate > LOBOT_OI_BAUD_115200) 00078 return ; 00079 00080 // Send baud command and new baud rate 00081 lo_tx(LOBOT_OI_CMD_BAUD) ; 00082 UCSR0A |= _BV(TXC0) ; 00083 lo_tx(baud_rate) ; 00084 00085 // Busy wait until transmit is complete 00086 while (! (UCSR0A & _BV(TXC0))) 00087 ; 00088 00089 // Inhibit interrupts while we update the baud rate register 00090 cli() ; 00091 00092 // Update baud rate register 00093 switch (baud_rate) 00094 { 00095 case LOBOT_OI_BAUD_115200: 00096 UBRR0 = LOBOT_OI_UBRR_115200 ; 00097 break ; 00098 case LOBOT_OI_BAUD_57600: 00099 UBRR0 = LOBOT_OI_UBRR_57600 ; 00100 break ; 00101 case LOBOT_OI_BAUD_38400: 00102 UBRR0 = LOBOT_OI_UBRR_38400 ; 00103 break ; 00104 case LOBOT_OI_BAUD_28800: 00105 UBRR0 = LOBOT_OI_UBRR_28800 ; 00106 break ; 00107 case LOBOT_OI_BAUD_19200: 00108 UBRR0 = LOBOT_OI_UBRR_19200 ; 00109 break ; 00110 case LOBOT_OI_BAUD_14400: 00111 UBRR0 = LOBOT_OI_UBRR_14400 ; 00112 break ; 00113 case LOBOT_OI_BAUD_9600: 00114 UBRR0 = LOBOT_OI_UBRR_9600 ; 00115 break ; 00116 case LOBOT_OI_BAUD_4800: 00117 UBRR0 = LOBOT_OI_UBRR_4800 ; 00118 break ; 00119 case LOBOT_OI_BAUD_2400: 00120 UBRR0 = LOBOT_OI_UBRR_2400 ; 00121 break ; 00122 case LOBOT_OI_BAUD_1200: 00123 UBRR0 = LOBOT_OI_UBRR_1200 ; 00124 break ; 00125 case LOBOT_OI_BAUD_600: 00126 UBRR0 = LOBOT_OI_UBRR_600 ; 00127 break ; 00128 case LOBOT_OI_BAUD_300: 00129 UBRR0 = LOBOT_OI_UBRR_300 ; 00130 break ; 00131 default: 00132 UBRR0 = LOBOT_OI_UBRR_57600 ; 00133 break ; 00134 } 00135 00136 // Okay to receive interrupts again 00137 sei(); 00138 00139 // Small delay to let things stabilize 00140 lo_wait(100) ; 00141 } 00142 00143 // Clear TX and RX buffers 00144 void lo_clear_buffers(void) 00145 { 00146 // Wait for TX buffer to empty 00147 while (! (UCSR0A & _BV(UDRE0))) 00148 ; 00149 00150 // Empty the RX buffer 00151 char c ; 00152 while (UCSR0A & 0x80) 00153 c = UDR0 ; 00154 } 00155 00156 /*------------------------- SEND/RECEIVE API --------------------------*/ 00157 00158 // Transmit a byte over the serial port 00159 void lo_tx(char byte) 00160 { 00161 // Clear the communications error flag 00162 g_io_error = LOBOT_IO_OK ; 00163 00164 // Busy wait for transmit buffer to become empty 00165 while (! (UCSR0A & _BV(UDRE0))) 00166 ; 00167 00168 // Transmit buffer now empty ==> place byte in USART data register to send 00169 UDR0 = byte ; 00170 } 00171 00172 // Receive the specified number of bytes over the serial port, waiting a 00173 // maximum number of milliseconds before giving up. If the timeout is 00174 // zero, wait forever for the data to come in. 00175 // 00176 // The function returns the number of bytes successfully read. 00177 // 00178 // Clients should setup a large enough buffer to accommodate the amount 00179 // of data they require and check the return value before using the data 00180 // in the buffer. If the number of bytes read is less than the number 00181 // requested, clients can query the I/O error to see what went wrong. 00182 unsigned char lo_rx(char* buf, unsigned char n, unsigned int timeout) 00183 { 00184 // Clear the communications error flag 00185 g_io_error = LOBOT_IO_OK ; 00186 00187 unsigned char i = 0 ; 00188 if (timeout == 0) // wait forever 00189 { 00190 for (; i < n; ++i) { 00191 while (! (UCSR0A & 0x80)) // serial data not yet available 00192 ; 00193 buf[i] = UDR0 ; 00194 } 00195 } 00196 else // wait for specified amount of time and then give up 00197 { 00198 lo_setup_timer(timeout) ; 00199 while (lo_timer_is_running() && i < n) 00200 if (UCSR0A & 0x80) // serial byte is available 00201 buf[i++] = UDR0 ; 00202 00203 if (i < n) 00204 g_io_error = LOBOT_IO_TIMEOUT ; 00205 } 00206 return i ; 00207 } 00208 00209 // Receive a single byte over the serial port, waiting a maximum number 00210 // of milliseconds before giving up. If the timeout is zero, wait forever 00211 // for the data byte to come in. 00212 // 00213 // Clients should check the I/O error flag before using the byte returned 00214 // by this function. 00215 char lo_rx1(unsigned int timeout) 00216 { 00217 char c = 0 ; 00218 lo_rx(&c, 1, timeout) ; 00219 return c ; 00220 } 00221 00222 /*------------------------- USART REDIRECTION -------------------------*/ 00223 00224 void lo_io_to_usb() 00225 { 00226 lo_wait(10) ; // just in case there are some pending bytes to/from Create 00227 PORTB |= 0x10 ; 00228 lo_wait(10) ; // need to wait at least 10 bit times after switching ports 00229 } 00230 00231 void lo_io_to_create() 00232 { 00233 lo_wait(10) ; // just in case there are some pending bytes to/from USB 00234 PORTB &= ~0x10 ; 00235 lo_wait(10) ; // need to wait at least 10 bit times after switching ports 00236 } 00237 00238 /*-------------------------- ERROR CHECKING ---------------------------*/ 00239 00240 // Retrieve current I/O status 00241 char lo_io_error() 00242 { 00243 return g_io_error ; 00244 }