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: Nitin Dhavale <dhavale@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 #include "Component/ModelComponent.H" 00042 #include "Component/ModelParam.H" 00043 00044 #include <fcntl.h> 00045 #include <stdio.h> 00046 #include <sys/stat.h> 00047 #include <sys/types.h> 00048 #include <termios.h> 00049 #include <unistd.h> 00050 #include "Component/ModelParam.H" 00051 #include "Component/ModelOptionDef.H" 00052 00053 //! enum for different serial errors that could occur 00054 enum serialError 00055 { 00056 serialErrSuccess = 0, 00057 serialErrOpenNoTty,//1 00058 serialErrOpenFailed,//2 00059 serialErrSpeedInvalid,//3 00060 serialErrFlowInvalid,//4 00061 serialErrParityInvalid,//5 00062 serialErrCharsizeInvalid,//6 00063 serialErrStopbitsInvalid,//7 00064 serialErrOptionInvalid,//8 00065 serialErrResourceFailure,//9 00066 serialErrOutput,//10 00067 serialErrInput,//11 00068 serialErrTimeout,//12 00069 serialErrExtended,//13 00070 serialErrReadFailed,//14 00071 serialErrReadTimedOut,//15 00072 serialErrWriteFailed,//16 00073 serialErrFcntlFailed,//17 00074 serialErrTcGetAttrFailed,//18 00075 serialErrTcSetAttrFailed//19 00076 }; 00077 00078 //! Interface to a serial port 00079 /*! The port will be open at start() time; see ModelComponent.H for 00080 details. Because typically one may use several serial ports with 00081 different configs, this ModelComponent does not export any 00082 command-line option (there would be too many otherwise if many ports 00083 are used). Typically, thus, the port can be configured either via 00084 config files or using the various access functions provided in this 00085 class. */ 00086 class Serial : public ModelComponent { 00087 public: 00088 //! Constructor 00089 Serial(OptionManager& mgr, const std::string& descrName = "Serial Port", 00090 const std::string& tagName = "SerialPort"); 00091 00092 //! destructor 00093 ~Serial(void); 00094 00095 //! Close the serial port device file 00096 void closePort(); 00097 00098 //! Enable the serial port 00099 /*! enablePort will do all of the work of actually setting the config properties 00100 that have been requested, as well as opening the device file, etc... 00101 */ 00102 void enablePort(std::string DeviceName); 00103 00104 //! Configure the port before it is started. 00105 /*! This will update our internal ModelParam values to the specified 00106 ones; thus this should be called before start(). In contrast, 00107 the setXXX functions below are for reconfiguration at runtime, 00108 once the port is already open and running. This function is 00109 provided as a shortcut to set a bunch of ModelParam values in 00110 one simple call. 00111 @param dev device name (e.g., "/dev/ttyS0") 00112 @param speed speed in bauds. See setSpeed() for valid values 00113 @param format a 3-char string for charbits, parity, and stop bits; for 00114 example "8N1"; parity should be "N", "E" or "O". 00115 @param flowSoft use software flow control if true 00116 @param flowHard use hardware flow control if true 00117 @param tout read timeout in 1/10000s or 0 for no timeout */ 00118 void configure(const char *dev = "", const int speed = 9600, 00119 const char *format = "8N1", 00120 const bool flowSoft = false, const bool flowHard = false, 00121 const int = 0); 00122 00123 //! Configure the serial port to search for a device 00124 void configureSearch(const std::string DeviceDescription, const int speed = 115200, 00125 const std::string SearchPrefix = "ttyUSB", 00126 const char *format = "8N1", 00127 const bool flowSoft = false, const bool flowHard = false, 00128 const int = 0); 00129 00130 00131 //! Set serial port speed for both input and output. 00132 /*! This function is to change the speed while already started. 00133 @param speed to select. 0 signifies modem "hang up" and possible 00134 values are 0, 110, 300, 600, 1200, 2400, 4800, 9600, 00135 19200, 38400, 57600, 115200. 00136 @return 0 or serialErrSuccess on success. The perror() method 00137 can be used to print a longer description of the error. */ 00138 serialError setSpeed(const int speed); 00139 00140 //! Set the serial port flow control on Input as well as Ouput 00141 /*! This function is to change the flow control while already started. 00142 @param useHard use hardware flow control if true 00143 @param useSoft use software flow control if true 00144 @return 0 or serialErrSuccess on success */ 00145 serialError setFlowControl(const bool useHard, const bool useSoft); 00146 00147 //! Set character size. 00148 /*! This function is to change the char size while already started. 00149 @return 0 on success. 00150 @param bits character size to use; valid values are 5, 6, 7, 8. */ 00151 serialError setCharBits(const int bits); 00152 00153 //! Set parity mode. 00154 /*! This function is to change the parity while already started. 00155 @param useParity use some parity if true 00156 @param oddParity parity is odd if true, otherwise even 00157 @return 0 on success. */ 00158 serialError setParity(const bool useParity, const bool oddParity); 00159 00160 //! Set number of stop bits. 00161 /*! This function is to change the stop bits while started. 00162 @return 0 on success. 00163 @param bits stop bits (only values 1 and 2 are valid). */ 00164 serialError setStopBits(const int bits); 00165 00166 //! Set the access to blocking or not 00167 /*! If blocking, a write will block until all data has actually been 00168 sent through; otherwise it will return immediately while the data 00169 is being transmitted. */ 00170 serialError setBlocking(const bool blocking); 00171 00172 //! Set the DTR mode off momentarily. 00173 /*! @param millisec number of milliseconds. */ 00174 void toggleDTR(const time_t millisec); 00175 00176 //! transmit continuous stream of zero-valued bits for specific duration. 00177 void sendBreak(void); 00178 00179 //! attempt to read up to nbytes from serial port into the buffer 00180 /*! @param buffer holds bytes after read 00181 @nbytes number of bytes to attempt to read 00182 @return 0 on a timeout, -1 on error, number of bytes actually read 00183 on a success */ 00184 int read(void* buffer, const int nbytes); 00185 00186 //! Attempt to read a serial frame 00187 /*! The frame returned by the device should have the following format: 00188 [start byte] [optional number of data bytes] [data...] ... [...data] [end byte] 00189 @param frameStart holds the byte signifying the start of the frame 00190 @param frameEnd holds the byte signifying the end of the frame 00191 @param frameLength optionally specifies the number of bytes in the frame. If this is -1, 00192 then the second byte of the frame is assumed to contain the total number of 00193 bytes in the frame. 00194 @param timeout the number of seconds to wait before giving up (default of -1 is no timeout) 00195 @return the data contained in the frame */ 00196 //TODO: Implement parity checking in the stop byte 00197 std::vector<unsigned char> readFrame( 00198 const unsigned char frameStart, 00199 const unsigned char frameEnd = 255, 00200 const int frameLength = -1, 00201 const double timeout = -1 00202 ); 00203 00204 //! attempts to get the next character from the serial port 00205 /*! for comptability with dirk's code */ 00206 char read(void); 00207 00208 //! write bytes to the port 00209 /*! @param buffer begin writing from the location buffer. 00210 @param nbytes number of bytes to write 00211 @return -1 on failure, number of bytes written on success */ 00212 int write(const void* buffer, const int nbytes); 00213 00214 //! write a single byte to the port - a simple wrapper around write(const void* buffer, const int nbytes) 00215 /*! @param character the single byte to write 00216 @return -1 on failure, 1 on successs.*/ 00217 int write(const unsigned char character); 00218 00219 //! print a verbal message indicating the last error. 00220 void perror(void); 00221 00222 void flush(void); 00223 00224 //Accessor Functions 00225 std::string getDeviceDescriptor() { return itsDeviceDescription.getVal(); }; 00226 std::string getDevName() { return itsCmdDevName.getVal(); }; 00227 bool isSerialOk() { return (serialErrno==0); }; 00228 int getSerialErrno() { return serialErrno; }; 00229 00230 protected: 00231 OModelParam<std::string> itsCmdDevName; //!< device name passed from cmd line 00232 00233 NModelParam<std::string> itsDeviceDescription; //!< device description to seach for 00234 NModelParam<std::string> itsSearchPrefix; //!< device name prefix (e.g. ttyUSB) 00235 NModelParam<int> itsBaud; //!< Baudrate 00236 NModelParam<int> itsCharBits; //!< number of useful bits per char 00237 NModelParam<int> itsStopBits; //!< number of stop bits 00238 NModelParam<bool> itsUseParity; //!< use parity if true 00239 NModelParam<bool> itsParityOdd; //!< parity is odd if true, otherwise even 00240 NModelParam<bool> itsFlowHard; //!< use hardware flow control if true 00241 NModelParam<bool> itsFlowSoft; //!< use software flow control if true 00242 NModelParam<int> itsRdTout; //!< read timeout in 1/10000s 00243 NModelParam<bool> itsBlocking; //!< use blocking mode 00244 NModelParam<bool> itsSerialOk; //!< Port opened success if true 00245 00246 //! open the port and get started 00247 void start2(); 00248 00249 //! close the port and get stopped 00250 void stop2(); 00251 00252 private: 00253 int dev; // descriptor associated with the device file 00254 std::string itsDevName; //the device name 00255 serialError serialErrno; // error id of the last error 00256 termios savedState; // saved state to restore in the destructor 00257 00258 // set our errno 00259 serialError error(const serialError serialErrorNum); 00260 00261 // open the serial port. This is called from the constructor, so there is 00262 // no need to explicitly call this 00263 // @return -1 on error 00264 int openPort(std::string DeviceName); 00265 }; 00266 00267 #endif 00268 00269 // ###################################################################### 00270 /* So things look consistent in everyone's emacs... */ 00271 /* Local Variables: */ 00272 /* indent-tabs-mode: nil */ 00273 /* End: */