00001 /*!@file Devices/Serial.H class for interfacing with a serial port */ 00002 00003 // //////////////////////////////////////////////////////////////////// // 00004 // The iLab Neuromorphic Vision C++ Toolkit - Copyright (C) 2001 by the // 00005 // University of Southern California (USC) and the iLab at USC. // 00006 // See http://iLab.usc.edu for information about this project. // 00007 // //////////////////////////////////////////////////////////////////// // 00008 // Major portions of the iLab Neuromorphic Vision Toolkit are protected // 00009 // under the U.S. patent ``Computation of Intrinsic Perceptual Saliency // 00010 // in Visual Environments, and Applications'' by Christof Koch and // 00011 // Laurent Itti, California Institute of Technology, 2001 (patent // 00012 // pending; application number 09/912,225 filed July 23, 2001; see // 00013 // http://pair.uspto.gov/cgi-bin/final/home.pl for current status). // 00014 // //////////////////////////////////////////////////////////////////// // 00015 // This file is part of the iLab Neuromorphic Vision C++ Toolkit. // 00016 // // 00017 // The iLab Neuromorphic Vision C++ Toolkit is free software; you can // 00018 // redistribute it and/or modify it under the terms of the GNU General // 00019 // Public License as published by the Free Software Foundation; either // 00020 // version 2 of the License, or (at your option) any later version. // 00021 // // 00022 // The iLab Neuromorphic Vision C++ Toolkit is distributed in the hope // 00023 // that it will be useful, but WITHOUT ANY WARRANTY; without even the // 00024 // implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR // 00025 // PURPOSE. See the GNU General Public License for more details. // 00026 // // 00027 // You should have received a copy of the GNU General Public License // 00028 // along with the iLab Neuromorphic Vision C++ Toolkit; if not, write // 00029 // to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, // 00030 // Boston, MA 02111-1307 USA. // 00031 // //////////////////////////////////////////////////////////////////// // 00032 // 00033 // Primary maintainer for this file: Chin-Kai Chang<chinkaic@usc.edu> 00034 // $HeadURL: svn://isvn.usc.edu/software/invt/trunk/saliency/src/Devices/Serial.H $ 00035 // $Id: Serial.H 12962 2010-03-06 02:13:53Z irock $ 00036 // 00037 00038 #ifndef __SERIAL_H__ 00039 #define __SERIAL_H__ 00040 00041 00042 #include <fcntl.h> 00043 #include <stdio.h> 00044 #include <sys/stat.h> 00045 #include <sys/types.h> 00046 #include <termios.h> 00047 #include <unistd.h> 00048 #include <string> 00049 #include <vector> 00050 //! enum for different serial errors that could occur 00051 enum serialError 00052 { 00053 serialErrSuccess = 0, 00054 serialErrOpenNoTty,//1 00055 serialErrOpenFailed,//2 00056 serialErrSpeedInvalid,//3 00057 serialErrFlowInvalid,//4 00058 serialErrParityInvalid,//5 00059 serialErrCharsizeInvalid,//6 00060 serialErrStopbitsInvalid,//7 00061 serialErrOptionInvalid,//8 00062 serialErrResourceFailure,//9 00063 serialErrOutput,//10 00064 serialErrInput,//11 00065 serialErrTimeout,//12 00066 serialErrExtended,//13 00067 serialErrReadFailed,//14 00068 serialErrReadTimedOut,//15 00069 serialErrWriteFailed,//16 00070 serialErrFcntlFailed,//17 00071 serialErrTcGetAttrFailed,//18 00072 serialErrTcSetAttrFailed//19 00073 }; 00074 00075 //! Interface to a serial port 00076 /*! The port will be open at start() time; see ModelComponent.H for 00077 details. Because typically one may use several serial ports with 00078 different configs, this ModelComponent does not export any 00079 command-line option (there would be too many otherwise if many ports 00080 are used). Typically, thus, the port can be configured either via 00081 config files or using the various access functions provided in this 00082 class. */ 00083 class Serial { 00084 public: 00085 //! Constructor 00086 // Serial( const std::string& descrName, const std::string& tagName); 00087 Serial(); 00088 00089 //! destructor 00090 ~Serial(void); 00091 00092 //! Close the serial port device file 00093 void closePort(); 00094 00095 //! Enable the serial port 00096 /*! enablePort will do all of the work of actually setting the config properties 00097 that have been requested, as well as opening the device file, etc... 00098 */ 00099 void enablePort(std::string DeviceName); 00100 00101 //! Configure the port before it is started. 00102 /*! This will update our internal ModelParam values to the specified 00103 ones; thus this should be called before start(). In contrast, 00104 the setXXX functions below are for reconfiguration at runtime, 00105 once the port is already open and running. This function is 00106 provided as a shortcut to set a bunch of ModelParam values in 00107 one simple call. 00108 @param dev device name (e.g., "/dev/ttyS0") 00109 @param speed speed in bauds. See setSpeed() for valid values 00110 @param format a 3-char string for charbits, parity, and stop bits; for 00111 example "8N1"; parity should be "N", "E" or "O". 00112 @param flowSoft use software flow control if true 00113 @param flowHard use hardware flow control if true 00114 @param tout read timeout in 1/10000s or 0 for no timeout */ 00115 void configure(const char *dev = "", const int speed = 9600, 00116 const char *format = "8N1", 00117 const bool flowSoft = false, const bool flowHard = false, 00118 const int = 0); 00119 00120 //! Configure the serial port to search for a device 00121 void configureSearch(const std::string DeviceDescription, const int speed = 115200, 00122 const std::string SearchPrefix = "ttyUSB", 00123 const char *format = "8N1", 00124 const bool flowSoft = false, const bool flowHard = false, 00125 const int = 0); 00126 00127 00128 //! Set serial port speed for both input and output. 00129 /*! This function is to change the speed while already started. 00130 @param speed to select. 0 signifies modem "hang up" and possible 00131 values are 0, 110, 300, 600, 1200, 2400, 4800, 9600, 00132 19200, 38400, 57600, 115200. 00133 @return 0 or serialErrSuccess on success. The perror() method 00134 can be used to print a longer description of the error. */ 00135 serialError setSpeed(const int speed); 00136 00137 //! Set the serial port flow control on Input as well as Ouput 00138 /*! This function is to change the flow control while already started. 00139 @param useHard use hardware flow control if true 00140 @param useSoft use software flow control if true 00141 @return 0 or serialErrSuccess on success */ 00142 serialError setFlowControl(const bool useHard, const bool useSoft); 00143 00144 //! Set character size. 00145 /*! This function is to change the char size while already started. 00146 @return 0 on success. 00147 @param bits character size to use; valid values are 5, 6, 7, 8. */ 00148 serialError setCharBits(const int bits); 00149 00150 //! Set parity mode. 00151 /*! This function is to change the parity while already started. 00152 @param useParity use some parity if true 00153 @param oddParity parity is odd if true, otherwise even 00154 @return 0 on success. */ 00155 serialError setParity(const bool useParity, const bool oddParity); 00156 00157 //! Set number of stop bits. 00158 /*! This function is to change the stop bits while started. 00159 @return 0 on success. 00160 @param bits stop bits (only values 1 and 2 are valid). */ 00161 serialError setStopBits(const int bits); 00162 00163 //! Set the access to blocking or not 00164 /*! If blocking, a write will block until all data has actually been 00165 sent through; otherwise it will return immediately while the data 00166 is being transmitted. */ 00167 serialError setBlocking(const bool blocking); 00168 00169 //! Set the DTR mode off momentarily. 00170 /*! @param millisec number of milliseconds. */ 00171 void toggleDTR(const time_t millisec); 00172 00173 //! transmit continuous stream of zero-valued bits for specific duration. 00174 void sendBreak(void); 00175 00176 //! attempt to read up to nbytes from serial port into the buffer 00177 /*! @param buffer holds bytes after read 00178 @nbytes number of bytes to attempt to read 00179 @return 0 on a timeout, -1 on error, number of bytes actually read 00180 on a success */ 00181 int read(void* buffer, const int nbytes); 00182 00183 //! Attempt to read a serial frame 00184 /*! The frame returned by the device should have the following format: 00185 [start byte] [optional number of data bytes] [data...] ... [...data] [end byte] 00186 @param frameStart holds the byte signifying the start of the frame 00187 @param frameEnd holds the byte signifying the end of the frame 00188 @param frameLength optionally specifies the number of bytes in the frame. If this is -1, 00189 then the second byte of the frame is assumed to contain the total number of 00190 bytes in the frame. 00191 @param timeout the number of seconds to wait before giving up (default of -1 is no timeout) 00192 @return the data contained in the frame */ 00193 //TODO: Implement parity checking in the stop byte 00194 std::vector<unsigned char> readFrame( 00195 const unsigned char frameStart, 00196 const unsigned char frameEnd = 255, 00197 const int frameLength = -1, 00198 const double timeout = -1 00199 ); 00200 00201 //! attempts to get the next character from the serial port 00202 /*! for comptability with dirk's code */ 00203 char read(void); 00204 00205 //! write bytes to the port 00206 /*! @param buffer begin writing from the location buffer. 00207 @param nbytes number of bytes to write 00208 @return -1 on failure, number of bytes written on success */ 00209 int write(const void* buffer, const int nbytes); 00210 00211 //! write a single byte to the port - a simple wrapper around write(const void* buffer, const int nbytes) 00212 /*! @param character the single byte to write 00213 @return -1 on failure, 1 on successs.*/ 00214 int write(const unsigned char character); 00215 00216 //! print a verbal message indicating the last error. 00217 void perror(void); 00218 00219 void flush(void); 00220 00221 //Accessor Functions 00222 std::string getDeviceDescriptor() { return itsDeviceDescription; }; 00223 std::string getDevName() { return itsCmdDevName; }; 00224 bool isSerialOk() { return (serialErrno==0); }; 00225 int getSerialErrno() { return serialErrno; }; 00226 00227 //! open the port and get started 00228 void start(); 00229 00230 //! close the port and get stopped 00231 void stop(); 00232 protected: 00233 std::string itsCmdDevName; //!< device name passed from cmd line 00234 00235 std::string itsDeviceDescription; //!< device description to seach for 00236 std::string itsSearchPrefix; //!< device name prefix (e.g. ttyUSB) 00237 int itsBaud; //!< Baudrate 00238 int itsCharBits; //!< number of useful bits per char 00239 int itsStopBits; //!< number of stop bits 00240 bool itsUseParity; //!< use parity if true 00241 bool itsParityOdd; //!< parity is odd if true, otherwise even 00242 bool itsFlowHard; //!< use hardware flow control if true 00243 bool itsFlowSoft; //!< use software flow control if true 00244 int itsRdTout; //!< read timeout in 1/10000s 00245 bool itsBlocking; //!< use blocking mode 00246 bool itsSerialOk; //!< Port opened success if true 00247 00248 00249 private: 00250 int dev; // descriptor associated with the device file 00251 std::string itsDevName; //the device name 00252 serialError serialErrno; // error id of the last error 00253 termios savedState; // saved state to restore in the destructor 00254 00255 // set our errno 00256 serialError error(const serialError serialErrorNum); 00257 00258 // open the serial port. This is called from the constructor, so there is 00259 // no need to explicitly call this 00260 // @return -1 on error 00261 int openPort(std::string DeviceName); 00262 }; 00263 00264 #endif 00265 00266 // ###################################################################### 00267 /* So things look consistent in everyone's emacs... */ 00268 /* Local Variables: */ 00269 /* indent-tabs-mode: nil */ 00270 /* End: */