00001 #ifndef _CMT_MONOLITHIC 00002 /*! \file 00003 \brief Contains the CMT Level 1 interface 00004 00005 This level contains OS-dependent implementations of Serial and File 00006 communication, as well as some other functionality like 'sleep'. 00007 00008 \section FileCopyright Copyright Notice 00009 Copyright (C) Xsens Technologies B.V., 2006. All rights reserved. 00010 00011 This source code is intended for use only by Xsens Technologies BV and 00012 those that have explicit written permission to use it from 00013 Xsens Technologies BV. 00014 00015 THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY 00016 KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE 00017 IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A 00018 PARTICULAR PURPOSE. 00019 */ 00020 #endif 00021 #ifndef _CMT1_H_2006_04_12 00022 #define _CMT1_H_2006_04_12 00023 00024 #ifndef _CMTDEF_H_2006_05_01 00025 # include <cmtdef.h> 00026 #endif 00027 00028 #ifdef _WIN32 00029 # include <windows.h> 00030 //# include <sys/types.h> 00031 #else 00032 # include <termios.h> 00033 // these are not required by level 1, but to keep the higher levels platform-independent they are put here 00034 # include <stdlib.h> 00035 # include <string.h> 00036 # include <stddef.h> 00037 #define _strnicmp strncasecmp 00038 #endif 00039 00040 #include <stdio.h> 00041 00042 //! The namespace of all Xsens software since 2006. 00043 namespace xsens { 00044 00045 #ifndef CMTLOG 00046 # if defined(_DEBUG) || defined(_LOG_ALWAYS) 00047 void CMTLOG(const char *str, ...); 00048 # define CMTEXITLOG(str) JanitorFunc2<const char*,XsensResultValue> _cmtExitLog(CMTLOG,str " returns %u",m_lastResult); 00049 # else 00050 # define CMTLOG(...) 00051 # define CMTEXITLOG(...) 00052 # endif 00053 #endif 00054 00055 #ifndef _WIN32 00056 int _wcsnicmp(const wchar_t* s1, const wchar_t* s2,int count); 00057 #endif 00058 00059 ////////////////////////////////////////////////////////////////////////////////////////// 00060 ///////////////////////////////////////// Cmt1s ///////////////////////////////////////// 00061 ////////////////////////////////////////////////////////////////////////////////////////// 00062 00063 /*! \brief The low-level serial communication class. 00064 */ 00065 class Cmt1s { 00066 private: 00067 //! This object cannot be copied, so this function is not implemented. 00068 Cmt1s(const Cmt1s& ref); 00069 00070 #ifdef _LOG_RX_TX 00071 FILE* rx_log; 00072 FILE* tx_log; 00073 #endif 00074 00075 /*! \brief The bytes received function. 00076 00077 This function is automatically called every time binary data is read from the 00078 connected COM port. 00079 */ 00080 CmtCallbackFunction m_onBytesReceived; 00081 //! Custom, user supplied parameter for the OnBytesReceived callback function, passed as the first argument 00082 int32_t m_onBytesReceivedInstance; 00083 //! Custom, user supplied parameter for the OnBytesReceived callback function, passed as the last argument 00084 void* m_onBytesReceivedParam; 00085 protected: 00086 //! The baudrate that was last set to be used by the port 00087 uint32_t m_baudrate; 00088 //! The time at which an operation will end in ms, used by several functions. 00089 uint32_t m_endTime; 00090 //! Indicates if the port is open or not 00091 bool m_isOpen; 00092 //! The last result of an operation 00093 mutable XsensResultValue m_lastResult; 00094 //! The opened COM port nr 00095 uint16_t m_port; 00096 char m_portname[32]; 00097 /*! The default timeout value to use during blocking operations. 00098 A value of 0 means that all operations become non-blocking. 00099 */ 00100 uint32_t m_timeout; 00101 00102 #ifdef _WIN32 00103 DCB m_commState; //!< Stored settings about the serial port 00104 HANDLE m_handle; //!< The serial port handle 00105 #else 00106 termios m_commState; //!< Stored settings about the serial port 00107 int32_t m_handle; //!< The serial port handle 00108 typedef int32_t HANDLE; 00109 #endif 00110 public: 00111 //! Default constructor, initializes all members to their default values. 00112 Cmt1s(); 00113 //! Destructor, de-initializes, frees memory allocated for buffers, etc. 00114 ~Cmt1s(); 00115 //! \brief Close the serial communication port. 00116 XsensResultValue close (void); 00117 /*! \brief Manipulate the Serial control lines 00118 00119 The function manipulates the serial control lines that are indicated by the 00120 mask parameter. Note that only the DTR and RTS lines can be set by win32. 00121 \param mask Indicates which lines are to be manipulated and which should be 00122 left alone. 00123 \param state Contains the new state of the control lines. 00124 */ 00125 XsensResultValue escape (const CmtControlLine mask, const CmtControlLine state); 00126 /*! \brief Flush all data to be transmitted / received. 00127 00128 This function tries to send and receive any remaining data immediately 00129 and does not return until the buffers are empty. 00130 */ 00131 XsensResultValue flushData (void); 00132 //! Return the baudrate that is currently being used by the port 00133 uint32_t getBaudrate(void) const { return m_baudrate; } 00134 //! Return the handle of the port 00135 HANDLE getHandle(void) const { return m_handle; } 00136 //! Retrieve the port number that was last successfully opened. 00137 uint16_t getPortNr (void) const { return m_port; } 00138 //! Retrieve the port name that was last successfully opened. 00139 void getPortName(char *portname) const { sprintf(portname, "%s", m_portname); } 00140 //! Return the error code of the last operation. 00141 XsensResultValue getLastResult(void) const { return m_lastResult; } 00142 //! Return the current timeout value 00143 uint32_t getTimeout (void) const { return m_timeout; } 00144 //! Return whether the communication port is open or not. 00145 bool isOpen (void) const { return m_isOpen; } 00146 00147 /*! \brief Open a communcation channel to the given serial port name. 00148 00149 The port is automatically initialized to the given baudrate. 00150 If the baudrate is set to 0, the baud rate is automatically detected. If possible. 00151 */ 00152 XsensResultValue open ( const char *portName, 00153 const uint32_t baudRate = CMT_DEFAULT_BAUD_RATE, 00154 uint32_t readBufSize = CMT_DEFAULT_READ_BUFFER_SIZE, 00155 uint32_t writeBufSize = CMT_DEFAULT_WRITE_BUFFER_SIZE); 00156 00157 #ifdef _WIN32 00158 /*! \brief Open a communication channel to the given COM port number. 00159 00160 The port is automatically initialized to the given baud rate. 00161 If the baudrate is set to 0, the baud rate is automatically detected. If possible. 00162 */ 00163 XsensResultValue open ( const uint32_t portNumber, 00164 const uint32_t baudRate = CMT_DEFAULT_BAUD_RATE, 00165 uint32_t readBufSize = CMT_DEFAULT_READ_BUFFER_SIZE, 00166 uint32_t writeBufSize = CMT_DEFAULT_WRITE_BUFFER_SIZE); 00167 #endif 00168 /*! \brief Read data from the serial port and put it into the data buffer. 00169 00170 This function reads as much data as possible from the com port (non-blocking) and 00171 put as much data as will fit into the data buffer. Any excess data is stored in 00172 the \c m_readBuffer member variable. If there was enough data in m_readBuffer to 00173 fulfill the request, the data parameter is first filled and the port is polled 00174 afterwards. 00175 \param maxLength The maximum amount of data read. 00176 \param data Pointer to a buffer that will store the received data. 00177 \param length The number of bytes placed into \c data. 00178 */ 00179 XsensResultValue readData (const uint32_t maxLength, uint8_t* data, 00180 uint32_t* length = NULL); 00181 //! Set the callback function for when bytes have been received 00182 XsensResultValue setCallbackFunction(CmtCallbackType tp, int32_t instance, CmtCallbackFunction func, void* param); 00183 /*! \brief Set the default timeout value to use in blocking operations. 00184 00185 This function sets the value of m_timeout. There is no infinity value. The value 0 00186 means that all blocking operations now become polling (non-blocking) operations. 00187 If the value is set to or from 0, the low-level serial port settings may be 00188 changed in addition to the m_timeout value. 00189 */ 00190 XsensResultValue setTimeout (const uint32_t ms = CMT1_DEFAULT_TIMEOUT); 00191 /*! \brief Wait for data to arrive or a timeout to occur. 00192 00193 The function waits until \c maxLength data is available or until a timeout occurs. 00194 The function returns success if data is available or XsensResultValue::TIMEOUT if a 00195 timeout occurred. A timeout value of 0 indicates that the default timeout stored 00196 in the class should be used. 00197 */ 00198 XsensResultValue waitForData (const uint32_t maxLength, uint8_t* data, 00199 uint32_t* length = NULL); 00200 /*! \brief Write the data to the serial port. 00201 00202 The function writes the given data to the connected COM port. 00203 The default timeout is respected in this operation. 00204 */ 00205 XsensResultValue writeData (const uint32_t length, const uint8_t* data, 00206 uint32_t* written); 00207 00208 }; 00209 00210 ////////////////////////////////////////////////////////////////////////////////////////// 00211 ///////////////////////////////////////// Cmt1f ///////////////////////////////////////// 00212 ////////////////////////////////////////////////////////////////////////////////////////// 00213 00214 /*! \brief The low-level file communication class. 00215 */ 00216 class Cmt1f { 00217 private: 00218 //! This object cannot be copied, so this function is not implemented. 00219 Cmt1f(const Cmt1f& ref); 00220 00221 protected: 00222 //! The file handle 00223 FILE* m_handle; 00224 //! Contains the size of the file 00225 CmtFilePos m_fileSize; 00226 //! The last read position in the file 00227 CmtFilePos m_readPos; 00228 //! The last write position in the file 00229 CmtFilePos m_writePos; 00230 //! The last result of an operation 00231 mutable XsensResultValue m_lastResult; 00232 //! Contains the name of the file that was last successfully opened. 00233 char m_filename[CMT_MAX_FILENAME_LENGTH]; 00234 //! Contains the name of the file that was last successfully opened using unicode. 00235 wchar_t m_filename_w[CMT_MAX_FILENAME_LENGTH]; 00236 //! Indicates if the file is open or not. 00237 bool m_isOpen; 00238 //! Indicates if we're using the unicode filename or the regular filename 00239 bool m_unicode; 00240 /*! \brief Indicates whether the last operation was a read or write operation. 00241 00242 This value is used to check whether or not a seek is required to perform a 00243 requested read or write operation. 00244 */ 00245 bool m_reading; 00246 //! Indicates if the file was opened in read-only mode 00247 bool m_readOnly; 00248 //! Change from writing to reading mode 00249 void gotoRead(void); 00250 //! Change from reading to writing mode 00251 void gotoWrite(void); 00252 public: 00253 //! Default constructor, initializes all members to their default values. 00254 Cmt1f(); 00255 //! Destructor. 00256 ~Cmt1f(); 00257 /*! \brief Write data to the end of the file. 00258 00259 The function writes the given data to the file at the end. The current write 00260 position is also moved to the end of the file. 00261 */ 00262 XsensResultValue appendData(const uint32_t length, const void* data); 00263 //! Close the file. 00264 XsensResultValue close(void); 00265 //! Close the file and delete it. 00266 XsensResultValue closeAndDelete(void); 00267 //! Open an empty file. 00268 XsensResultValue create(const char* filename); 00269 //! Open an empty file using a unicode path + filename. 00270 XsensResultValue create(const wchar_t* filename); 00271 /*! \brief Delete the given data from the file. 00272 00273 The function erases the given data from the file at the given write position. This 00274 operation may take a while to complete, but is faster than insertData. 00275 00276 The write position is not changed and the read position is checked for validity. 00277 */ 00278 XsensResultValue deleteData(const CmtFilePos start, const uint32_t length); 00279 /*! \brief Find a string of bytes in the file 00280 00281 The function searches from the current read position until the given \c needle is 00282 found. If the needle is not found, XsensResultValue::NOT_FOUND is returned. The function 00283 will update the seek position to the first character of the found needle. 00284 \param needle The byte string to find. 00285 \param needleLength The length of the byte string. 00286 \param pos Out: The position where the needle was found. This will point 00287 to the first character of the found needle. 00288 */ 00289 XsensResultValue find(const void* needle, const uint32_t needleLength, CmtFilePos& pos); 00290 /*! \brief Flush all data to be written. 00291 This function writes any remaining data immediately and does not return 00292 until this is done. 00293 */ 00294 XsensResultValue flushData(void); 00295 //! Return the size of the file. 00296 CmtFilePos getFileSize(void) const { return m_fileSize; } 00297 //! Return the result code of the last operation. 00298 XsensResultValue getLastResult(void) const { return m_lastResult; } 00299 /*! \brief Retrieve the filename that was last successfully opened. 00300 00301 \param filename A buffer for storing the filename. The buffer should be able 00302 to hold the filename. A safe size is to make it at least 256 bytes. 00303 */ 00304 XsensResultValue getName(char* filename) const; 00305 /*! \brief Retrieve the filename that was last successfully opened in unicode. 00306 00307 \param filename A buffer for storing the filename. The buffer should be able 00308 to hold the filename. A safe size is to make it at least 256 wide characters. 00309 */ 00310 XsensResultValue getName(wchar_t* filename) const; 00311 //! Return the current read position. 00312 CmtFilePos getReadPos(void) const { return m_readPos; } 00313 //! Return the current write position. 00314 CmtFilePos getWritePos(void) const { return m_writePos; } 00315 /*! \brief Insert the given data into the file. 00316 00317 The function writes the given data to the file at the current write position. This 00318 operation may take a while to complete. 00319 00320 The write position is placed at the end of the inserted data. 00321 */ 00322 XsensResultValue insertData(const CmtFilePos start, const uint32_t length, 00323 const void* data); 00324 //! Return whether the file is open or not. 00325 bool isOpen(void) const { return m_isOpen; } 00326 //! Return whether the file is readonly or not. 00327 bool isReadOnly(void) const { return !m_isOpen || m_readOnly; } 00328 //! Open a file. 00329 XsensResultValue open(const char* filename, const bool create, const bool readOnly); 00330 //! Open a file using a unicode filename. 00331 XsensResultValue open(const wchar_t* filename, const bool create, const bool readOnly); 00332 /*! \brief Read data from the file and put it into the data buffer. 00333 00334 This function reads exactly the number of bytes as requested from the file. 00335 \param maxLength The amount of data that will be read. 00336 \param data Pointer to a buffer that will store the read data. 00337 \param length pointer to a variable that will store the number of bytes 00338 that were actually read. The parameter may be NULL. 00339 */ 00340 XsensResultValue readData(const uint32_t maxLength, void* data, uint32_t* length); 00341 /*! \brief Read data from the file and put it into the data buffer. 00342 00343 This function reads upp to the number of bytes as requested from the file. 00344 The function will also stop if the given terminator character is encountered. 00345 The terminator is included in the output buffer. 00346 \param maxLength The amount of data that will be read. 00347 \param data Pointer to a buffer that will store the read data. 00348 \param terminator A character that will end the read operation if encountered. 00349 \param length The actual number of bytes read, including the terminator 00350 character, if encountered. 00351 */ 00352 XsensResultValue readData(const uint32_t maxLength, const char terminator, void* data, uint32_t* length); 00353 /*! \brief Set the new absolute read position 00354 00355 The read position is checked against the filesize before committing. 00356 */ 00357 XsensResultValue setReadPos(const CmtFilePos pos); 00358 /*! \brief Set the new absolute write position 00359 00360 The write position is checked against the filesize before committing. 00361 */ 00362 XsensResultValue setWritePos(const CmtFilePos pos = -1); 00363 00364 /*! \brief Write data to the file. 00365 00366 The function writes the given data to the file at the current write position. 00367 */ 00368 XsensResultValue writeData(const uint32_t length, const void* data); 00369 }; 00370 00371 } // end of xsens namespace 00372 00373 #endif // _CMT1_H_2006_04_12