00001 #ifndef _CMT_MONOLITHIC 00002 /*! \file 00003 \brief Contains the CMT Message interface 00004 00005 This level contains the message interface of Cmt. 00006 All code should be OS-independent. 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 _CMTMESSAGE_H_2006_05_24 00022 #define _CMTMESSAGE_H_2006_05_24 00023 00024 #ifndef _CMT_MONOLITHIC 00025 # include "cmtdef.h" 00026 # include "cmt1.h" 00027 #endif 00028 00029 namespace xsens { 00030 00031 ////////////////////////////////////////////////////////////////////////////////////////// 00032 /*! \brief Compute the checksum of the given byte string. 00033 */ 00034 uint8_t computeChecksum(const uint8_t* buffer, uint32_t length); 00035 00036 ////////////////////////////////////////////////////////////////////////////////////////// 00037 /* different alignment commands for gcc / MSVS, the structure needs to be 1-byte aligned. 00038 */ 00039 #ifdef _MSC_VER 00040 #pragma pack(push, 1) 00041 #endif 00042 /*! \brief A message header. 00043 00044 DO NOT REORDER THE MEMBERS! 00045 */ 00046 struct MessageHeader { 00047 uint8_t m_preamble; 00048 uint8_t m_busId; 00049 uint8_t m_messageId; 00050 uint8_t m_length; 00051 union _mdl { 00052 struct _mextd { 00053 struct _mlen { 00054 uint8_t m_high; 00055 uint8_t m_low; 00056 } m_length; 00057 uint8_t m_data[CMT_MAXDATALEN]; 00058 } m_extended; 00059 uint8_t m_data[254]; 00060 } m_datlen; 00061 } 00062 // different alignment commands for gcc / MSVS 00063 #ifdef _MSC_VER 00064 ; 00065 #pragma pack(pop) 00066 #else 00067 /*! \cond NODOXYGEN */ __attribute__((__packed__)) /*! \endcond */; 00068 #endif 00069 00070 00071 #define swapEndian16(src) (((src) >> 8) | ((src) << 8)) 00072 #define swapEndian32(src) (((src) >> 24) | ((src) >> 8 & 0xFF00) | ((src) << 8 & 0xFF0000) | ((src) << 24)) 00073 00074 ////////////////////////////////////////////////////////////////////////////////////////// 00075 //! \brief Class for storing a single message. 00076 class Message { 00077 protected: 00078 00079 //! The message header is the data buffer with interpretation 00080 MessageHeader* m_buffer; 00081 //! The checksum in the m_data or m_extendedData buffer 00082 uint8_t* m_checksum; 00083 //! The maximum size of the message, including header and footer 00084 uint32_t m_maxLength; 00085 00086 //! Internal checksum computation 00087 uint8_t calcChecksum(void) const 00088 { return computeChecksum(((uint8_t*)m_buffer) + 1, getTotalMessageSize()-2); } 00089 //! Internal function to get the start of the data buffer. 00090 uint8_t* getDataStart(void) const; 00091 00092 public: 00093 bool m_autoUpdateChecksum; 00094 00095 /*! \brief Create a Message object with the given data length and message Id. 00096 00097 The function allocates enough memory to hold an entire message with the given 00098 data length. 00099 \param msgId The message Id that will be assigend to the m_messageId field. 00100 \param length The length of the data in the message. This value is stored in 00101 \c m_createdLength as well as \c m_length or \c m_extendedLength. 00102 \param maxLength The maximum data length that can be stored in the structure. 00103 */ 00104 Message(const uint8_t msgId = 0, const uint16_t length = 0, const uint16_t maxLength = CMT_MAXMSGLEN); 00105 00106 /*! \brief Create a message from the given source string 00107 00108 This is done through a simple memory copy. The number of bytes copied is taken 00109 from the data in the message (so the message is interpreted first). 00110 Note that this does NOT recompute the checksum, nor is it checked. 00111 00112 \param source The source string containing message data 00113 \param size The size of the source string 00114 \param maxLength The maximum data length that can be stored in the structure. 00115 */ 00116 Message(const uint8_t* source, const uint16_t size, const uint16_t maxLength = CMT_MAXMSGLEN); 00117 00118 Message(const Message& src); 00119 00120 //! Destructor 00121 ~Message(); 00122 00123 //! Clear all data in the message 00124 void clear(void); 00125 00126 //! Return the current value of the m_busId field. 00127 uint8_t getBusId(void) const { return m_buffer->m_busId; } 00128 /*! \brief Return a pointer to the data buffer. 00129 00130 \param offset An optional offset in the data buffer from where to start reading. 00131 */ 00132 uint8_t* getDataBuffer(const uint16_t offset = 0) 00133 { return &((getDataStart())[offset]); } 00134 const uint8_t* getDataBuffer(const uint16_t offset = 0) const 00135 { return &((getDataStart())[offset]); } 00136 /*! \brief Return the current value of the data as an unsigned byte (8 bits). 00137 00138 \param offset An optional offset in the data buffer from where to start reading. 00139 */ 00140 uint8_t getDataByte(const uint16_t offset = 0) const 00141 { return (getDataStart()[offset]); } 00142 /*! \brief Return the current value of the data as a double (64 bits). 00143 00144 \param offset An optional offset in the data buffer from where to start reading. 00145 */ 00146 double getDataDouble(const uint16_t offset=0) const; 00147 /*! \brief Return the current value of the data as a float (32 bits). 00148 00149 \param offset An optional offset in the data buffer from where to start reading. 00150 */ 00151 float getDataFloat(const uint16_t offset=0) const; 00152 /*! \brief Return the current value of the data as a double, converting it from FP 12.20 00153 00154 \param offset An optional offset in the data buffer from where to start reading. 00155 */ 00156 double getDataF1220(const uint16_t offset=0) const; 00157 /*! \brief Return the current value of the data as a double, converting it from FP 16.32 00158 00159 \param offset An optional offset in the data buffer from where to start reading. 00160 */ 00161 double getDataFP1632(const uint16_t offset=0) const; 00162 /*! \brief Return current data value as double, conversion depends on outputSettings. 00163 00164 \param outputSettings MT output settings 00165 \param offset An optional offset in the data buffer from where to start reading. 00166 */ 00167 double getDataFPValue(const uint64_t outputSettings, const uint16_t offset = 0) const; 00168 /*! \brief Return current data values as double, conversion depends on outputSetting. 00169 00170 \param dest destination array 00171 \param outputSettings MT output settings 00172 \param offset offset in the data buffer from where to start reading. 00173 \param numValues number of values to be read 00174 */ 00175 void getDataFPValue(double *dest, const uint64_t outputSettings, uint16_t offset, const int16_t numValues) const; 00176 /*! \brief Return the current value of the data as an uint32_t (32 bits). 00177 00178 \param offset An optional offset in the data buffer from where to start reading. 00179 */ 00180 uint32_t getDataLong(const uint16_t offset=0) const; 00181 /*! \brief Return the current value of the data as an uint16_t (16 bits). 00182 00183 \param offset An optional offset in the data buffer from where to start reading. 00184 */ 00185 uint16_t getDataShort(const uint16_t offset=0) const; 00186 //! Return the length of the data part of the message. 00187 uint16_t getDataSize(void) const; 00188 //! Return the current value of the m_messageId field. 00189 uint8_t getMessageId(void) const { return m_buffer->m_messageId; } 00190 /*! \brief Return the start of the message buffer. 00191 00192 The function returns the address of the \c m_preamble member. 00193 */ 00194 const uint8_t* getMessageStart(void) const 00195 { return (uint8_t*) m_buffer; } 00196 /*! \brief Return the length of the message buffer. 00197 00198 The function returns the total size of the message, including the checksum. This 00199 is in effect the number of bytes that would be transferred if the message were to 00200 be sent over a communications channel. 00201 */ 00202 uint16_t getTotalMessageSize(void) const; 00203 //! Compute the checksum and compare it with the stored checksum. Equal is ok. 00204 bool isChecksumOk(void) const; 00205 /*! \brief Read the entire message from the given source string 00206 00207 This is done through a simple memory copy. The number of bytes copied is \c 00208 m_createdLength. 00209 \param source The source string containing message data 00210 \param size The size of the source string 00211 */ 00212 XsensResultValue loadFromString(const uint8_t* source, const uint16_t size); 00213 /*! \brief Compute the checksum field and fill it. 00214 00215 The checksum field should normally be correct at all times, but if you have 00216 somehow managed to mess it up, this function can be used to recompute it. 00217 */ 00218 void recomputeChecksum(void) { m_checksum[0] = calcChecksum(); } 00219 //! Resize the data area to the given size 00220 void resizeData(const uint16_t newSize); 00221 //! Set the new value of the m_busId field and update the checksum. 00222 void setBusId(const uint8_t busId); 00223 /*! \brief Write a string of bytes into the data buffer. 00224 00225 \param data The data to write to the buffer. 00226 \param offset An optional offset in the data buffer from where to start writing. 00227 \param count An optional number of bytes to write, if set to 0 (not set), as 00228 many bytes as will fit into the buffer from the given point will 00229 be written. 00230 */ 00231 void setDataBuffer(const uint8_t* data, const uint16_t offset = 0, 00232 const uint16_t count = 0); 00233 /*! \brief Write an unsigned byte (8 bits) into the data buffer. 00234 00235 \param data The data to write to the buffer. 00236 \param offset An optional offset in the data buffer from where to start writing. 00237 */ 00238 void setDataByte(const uint8_t data, const uint16_t offset = 0); 00239 /*! \brief Write a double (64 bits) into the data buffer. 00240 00241 \param data The data to write to the buffer. 00242 \param offset An optional offset in the data buffer from where to start writing. 00243 */ 00244 void setDataDouble(const double data, const uint16_t offset=0); 00245 /*! \brief Write a float (32 bits) into the data buffer. 00246 00247 \param data The data to write to the buffer. 00248 \param offset An optional offset in the data buffer from where to start writing. 00249 */ 00250 void setDataFloat(const float data, const uint16_t offset = 0); 00251 /*! \brief Write a double (64 bits) into the data buffer, after converting it to F1220. 00252 00253 \param data The data to write to the buffer. 00254 \param offset An optional offset in the data buffer from where to start writing. 00255 */ 00256 void setDataF1220(const double data, const uint16_t offset = 0); 00257 /*! \brief Write a double (64 bits) into the data buffer, after converting it to FP1632. 00258 00259 \param data The data to write to the buffer. 00260 \param offset An optional offset in the data buffer from where to start writing. 00261 */ 00262 void setDataFP1632(const double data, const uint16_t offset = 0); 00263 /*! \brief Write a floating/fixed point value into to the data buffer, conversion depends on outputSettings 00264 00265 \param outputSettings MT output settings 00266 \param data The data to write to the buffer. 00267 \param offset An optional offset in the data buffer from where to start writing. 00268 */ 00269 void setDataFPValue(const uint64_t outputSettings, const double data, const uint16_t offset = 0); 00270 /*! \brief Write a floating/fixed point value into to the data buffer, conversion depends on outputSettings 00271 00272 \param outputSettings MT output settings 00273 \param data The data array to be written to the buffer. 00274 \param offset Offset in the data buffer from where to start writing. 00275 \param numValues number of values to be written 00276 */ 00277 void setDataFPValue(const uint64_t outputSettings, const double *data, uint16_t offset, const uint16_t numValues); 00278 /*! \brief Write an uint32_t (32 bits) into the data buffer. 00279 00280 \param data The data to write to the buffer. 00281 \param offset An optional offset in the data buffer from where to start writing. 00282 */ 00283 void setDataLong(const uint32_t data, const uint16_t offset = 0); 00284 /*! \brief Write an uint16_t (16 bits) into the data buffer. 00285 00286 \param data The data to write to the buffer. 00287 \param offset An optional offset in the data buffer from where to start writing. 00288 */ 00289 void setDataShort(const uint16_t data, const uint16_t offset = 0); 00290 //! Set the new value of the m_messageId field and update the checksum. 00291 void setMessageId(const uint8_t msgId); 00292 00293 //! Copy message src into this 00294 void operator = (const Message& src); 00295 00296 //! Remove a number of bytes from the message (this will reduce the message size) 00297 void deleteData(uint16_t size, uint16_t offset = 0); 00298 //! Insert a number of bytes into the message (this will increase the message size) 00299 void insertData(uint16_t size, uint16_t offset = 0); 00300 }; 00301 00302 }; // end of xsens namespace 00303 00304 #endif // _CMTMESSAGE_H_2006_05_24