00001 /*! \file Cmtmessage.cpp 00002 00003 For information about objects in this file, see the appropriate header: 00004 \ref Cmtmessage.h 00005 00006 \section FileCopyright Copyright Notice 00007 Copyright (C) Xsens Technologies B.V., 2006. All rights reserved. 00008 00009 This source code is intended for use only by Xsens Technologies BV and 00010 those that have explicit written permission to use it from 00011 Xsens Technologies BV. 00012 00013 THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY 00014 KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE 00015 IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A 00016 PARTICULAR PURPOSE. 00017 00018 */ 00019 00020 #include "cmtmessage.h" 00021 00022 namespace xsens { 00023 00024 #ifdef _LOG_CMT_MSG 00025 #define MSGLOG CMTLOG 00026 #else 00027 #define MSGLOG(...) 00028 #endif 00029 00030 #ifndef CMT_OUTPUTSETTINGS_DATAFORMAT_DOUBLE 00031 #define CMT_OUTPUTSETTINGS_DATAFORMAT_DOUBLE 0x00000300 00032 #endif 00033 00034 ////////////////////////////////////////////////////////////////////////////////////////// 00035 // Create a Message object with the given data length and message Id. 00036 Message::Message(const uint8_t msgId, const uint16_t length, const uint16_t maxLength) 00037 { 00038 if (maxLength < CMT_MAXMSGLEN) 00039 m_maxLength = CMT_MAXMSGLEN; 00040 else 00041 m_maxLength = maxLength; 00042 m_buffer = (MessageHeader*) new char[m_maxLength];//(MessageHeader*) malloc(m_maxLength); 00043 MSGLOG("Message(%02x, %hu, %hu): buffer = %p\n",(int32_t) msgId, length, m_maxLength,m_buffer); 00044 memset(m_buffer,0,m_maxLength); 00045 00046 m_buffer->m_preamble = CMT_PREAMBLE; 00047 m_buffer->m_messageId = msgId; 00048 m_buffer->m_busId = CMT_BID_MASTER; 00049 00050 if (length >= 255) 00051 { 00052 m_buffer->m_length = CMT_EXTLENCODE; 00053 00054 m_buffer->m_datlen.m_extended.m_length.m_high = (uint8_t) (length >> 8); 00055 m_buffer->m_datlen.m_extended.m_length.m_low = (uint8_t) length; 00056 00057 m_checksum = &(((uint8_t*) m_buffer)[length + CMT_LEN_MSGEXTHEADER]); 00058 m_checksum[0] = -(msgId + CMT_EXTLENCODE + (uint8_t)length + (length >> 8)); 00059 } 00060 else 00061 { 00062 m_buffer->m_length = (uint8_t) length; 00063 m_checksum = &(((uint8_t*) m_buffer)[length + CMT_LEN_MSGHEADER]); 00064 m_checksum[0] = -(msgId + (uint8_t) length); 00065 } 00066 m_checksum[0] -= CMT_BID_MASTER; 00067 00068 m_autoUpdateChecksum = true; 00069 } 00070 00071 ////////////////////////////////////////////////////////////////////////////////////////// 00072 // Create a message from the given source string 00073 Message::Message(const uint8_t* source, const uint16_t size, const uint16_t maxLength) 00074 { 00075 const MessageHeader* tmp = (MessageHeader*) source; 00076 uint16_t length; 00077 00078 if (maxLength < CMT_MAXMSGLEN) 00079 m_maxLength = CMT_MAXMSGLEN; 00080 else 00081 m_maxLength = maxLength; 00082 00083 if (tmp->m_length == CMT_EXTLENCODE) 00084 length = ((uint16_t) tmp->m_datlen.m_extended.m_length.m_high * 256 + (uint16_t) tmp->m_datlen.m_extended.m_length.m_low) + CMT_LEN_MSGEXTHEADERCS; 00085 else 00086 length = tmp->m_length + CMT_LEN_MSGHEADERCS; 00087 if (size && size < length) 00088 length = size; 00089 00090 if ((uint32_t) length > m_maxLength) 00091 m_maxLength = length; 00092 00093 m_buffer = (MessageHeader*) new char[m_maxLength];//(MessageHeader*) malloc(m_maxLength); 00094 MSGLOG("Message(%02x%02x%02x%02x%02x%02x, %hu, %hu): buffer = %p\n",source[0],source[1],source[2],source[3],source[4],source[5], size, m_maxLength,m_buffer); 00095 if (length < m_maxLength) 00096 memset(&(((uint8_t*) m_buffer)[length]),0,m_maxLength-length); 00097 00098 memcpy(m_buffer,source,length); 00099 00100 m_checksum = &(((uint8_t*) m_buffer)[length-1]); 00101 00102 m_autoUpdateChecksum = true; 00103 } 00104 00105 Message::Message(const Message& src) 00106 { 00107 m_maxLength = src.m_maxLength; 00108 m_buffer = (MessageHeader*) new char[m_maxLength]; 00109 memcpy(m_buffer,src.m_buffer,m_maxLength); 00110 ptrdiff_t add = (uint8_t*) src.m_checksum - (uint8_t*) src.m_buffer; 00111 m_checksum = (uint8_t*) m_buffer + add; 00112 m_autoUpdateChecksum = true; 00113 } 00114 00115 ////////////////////////////////////////////////////////////////////////////////////////// 00116 // Destroy a Message object. 00117 Message::~Message() 00118 { 00119 MSGLOG("~Message(): buffer = %p\n",m_buffer); 00120 LSTCHKDELNUL(m_buffer);//free(m_buffer); 00121 } 00122 00123 ////////////////////////////////////////////////////////////////////////////////////////// 00124 // Clear all data in the message 00125 void Message::clear(void) 00126 { 00127 memset(m_buffer,0,m_maxLength); 00128 m_checksum = &(((uint8_t*) m_buffer)[CMT_LEN_MSGHEADER]); 00129 m_buffer->m_preamble = CMT_PREAMBLE; 00130 m_buffer->m_busId = CMT_BID_MASTER; 00131 m_checksum[0] = (uint8_t) (-CMT_BID_MASTER); 00132 } 00133 00134 ////////////////////////////////////////////////////////////////////////////////////////// 00135 // Return the current value of the data as a double (64 bits). 00136 double Message::getDataDouble(const uint16_t offset) const 00137 { 00138 double ret; 00139 uint8_t* dest = (uint8_t*) &ret; 00140 uint8_t* src = &(getDataStart()[offset]); 00141 dest[0] = src[7]; dest[1] = src[6]; dest[2] = src[5]; dest[3] = src[4]; 00142 dest[4] = src[3]; dest[5] = src[2]; dest[6] = src[1]; dest[7] = src[0]; 00143 00144 return ret; 00145 } 00146 00147 ////////////////////////////////////////////////////////////////////////////////////////// 00148 // Return the current value of the data as a float (32 bits). 00149 float Message::getDataFloat(const uint16_t offset) const 00150 { 00151 float ret; 00152 uint8_t* dest = (uint8_t*) &ret; 00153 uint8_t* src = &(getDataStart()[offset]); 00154 dest[0] = src[3]; 00155 dest[1] = src[2]; 00156 dest[2] = src[1]; 00157 dest[3] = src[0]; 00158 00159 return ret; 00160 } 00161 00162 ////////////////////////////////////////////////////////////////////////////////////////// 00163 // Return the current value of the data as a double(64 bits), after converting it from F1220. 00164 double Message::getDataF1220(const uint16_t offset) const 00165 { 00166 double ret; 00167 int32_t tmp; 00168 uint8_t* dest = (uint8_t*) &tmp; 00169 uint8_t* src = &(getDataStart()[offset]); 00170 dest[0] = src[3]; 00171 dest[1] = src[2]; 00172 dest[2] = src[1]; 00173 dest[3] = src[0]; 00174 00175 ret = ((double) tmp)/1048576.0; 00176 return ret; 00177 } 00178 00179 // little endian 00180 union Itypes { 00181 int64_t i64; 00182 struct { 00183 int32_t i1,i0; 00184 } i32; 00185 struct { 00186 int16_t s3,s2,s1,s0; 00187 } i16; 00188 struct { 00189 signed char b7,b6,b5,b4,b3,b2,b1,b0; 00190 } i8; 00191 00192 double d; 00193 struct { 00194 float f1,f0; 00195 } f32; 00196 }; 00197 00198 ////////////////////////////////////////////////////////////////////////////////////////// 00199 // Return the current value of the data as a double(64 bits), after converting it from FP1632. 00200 double Message::getDataFP1632(const uint16_t offset) const 00201 { 00202 00203 int16_t fpint; 00204 int32_t fpfrac; 00205 00206 uint8_t* dest = (uint8_t*) &fpfrac; 00207 uint8_t* src = &(getDataStart()[offset]); 00208 dest[3] = *(src++); 00209 dest[2] = *(src++); 00210 dest[1] = *(src++); 00211 dest[0] = *(src++); 00212 00213 dest = (uint8_t*) &fpint; 00214 dest[1] = *(src++); 00215 dest[0] = *(src++); 00216 00217 Itypes fp; 00218 fp.i32.i0 = fpint; 00219 fp.i32.i1 = fpfrac; 00220 00221 return (double) fp.i64 / 4294967296.0; 00222 } 00223 00224 ////////////////////////////////////////////////////////////////////////////////////////// 00225 // Return current data value as a double(64 bits), after converting it from 00226 // float, double, FP1632 or FP1220 depending on outputSettings 00227 double Message::getDataFPValue(const uint64_t outputSettings, const uint16_t offset) const 00228 { 00229 switch (outputSettings & CMT_OUTPUTSETTINGS_DATAFORMAT_MASK) 00230 { 00231 case CMT_OUTPUTSETTINGS_DATAFORMAT_FLOAT: 00232 return getDataFloat(offset); 00233 00234 case CMT_OUTPUTSETTINGS_DATAFORMAT_DOUBLE: 00235 return getDataDouble(offset); 00236 00237 case CMT_OUTPUTSETTINGS_DATAFORMAT_FP1632: 00238 return getDataFP1632(offset); 00239 00240 case CMT_OUTPUTSETTINGS_DATAFORMAT_F1220: 00241 return getDataF1220(offset); 00242 } 00243 return 0.0; // should never happen 00244 } 00245 00246 ////////////////////////////////////////////////////////////////////////////////////////// 00247 // Return current data values as a double(64 bits), after converting it from 00248 // float, double, FP1632 or FP1220 depending on outputSettings 00249 void Message::getDataFPValue(double *dest, const uint64_t outputSettings, uint16_t offset, const int16_t numValues) const 00250 { 00251 for (uint16_t i=0; i<numValues; i++) { 00252 switch (outputSettings & CMT_OUTPUTSETTINGS_DATAFORMAT_MASK) 00253 { 00254 case CMT_OUTPUTSETTINGS_DATAFORMAT_FLOAT: 00255 *dest++ = getDataFloat(offset); 00256 offset += 4; 00257 break; 00258 00259 case CMT_OUTPUTSETTINGS_DATAFORMAT_DOUBLE: 00260 *dest++ = getDataDouble(offset); 00261 offset += 8; 00262 break; 00263 00264 case CMT_OUTPUTSETTINGS_DATAFORMAT_FP1632: 00265 *dest++ = getDataFP1632(offset); 00266 offset += 6; 00267 break; 00268 00269 case CMT_OUTPUTSETTINGS_DATAFORMAT_F1220: 00270 *dest++ = getDataF1220(offset); 00271 offset += 4; 00272 } 00273 } 00274 } 00275 00276 ////////////////////////////////////////////////////////////////////////////////////////// 00277 // Return the current value of the data as an uint32_t (32 bits). 00278 uint32_t Message::getDataLong(const uint16_t offset) const 00279 { 00280 uint32_t ret; 00281 uint8_t* dest = (uint8_t*) &ret; 00282 uint8_t* src = &(getDataStart()[offset]); 00283 dest[0] = src[3]; 00284 dest[1] = src[2]; 00285 dest[2] = src[1]; 00286 dest[3] = src[0]; 00287 00288 return ret; 00289 } 00290 00291 ////////////////////////////////////////////////////////////////////////////////////////// 00292 // Return the current value of the data as an uint16_t (16 bits). 00293 uint16_t Message::getDataShort(const uint16_t offset) const 00294 { 00295 uint16_t ret; 00296 uint8_t* dest = (uint8_t*) &ret; 00297 uint8_t* src = &(getDataStart()[offset]); 00298 dest[0] = src[1]; 00299 dest[1] = src[0]; 00300 00301 return ret; 00302 } 00303 00304 ////////////////////////////////////////////////////////////////////////////////////////// 00305 // Return the length of the message buffer. 00306 uint16_t Message::getDataSize(void) const 00307 { 00308 if (m_buffer->m_length == 255) 00309 return ((uint16_t) m_buffer->m_datlen.m_extended.m_length.m_high * 256 + (uint16_t) m_buffer->m_datlen.m_extended.m_length.m_low); 00310 else 00311 return m_buffer->m_length; 00312 } 00313 00314 ////////////////////////////////////////////////////////////////////////////////////////// 00315 // Internal function to get the start of the data buffer. 00316 uint8_t* Message::getDataStart(void) const 00317 { 00318 if (m_buffer->m_length == 255) 00319 { 00320 return const_cast<uint8_t*>(m_buffer->m_datlen.m_extended.m_data); 00321 } 00322 else 00323 return const_cast<uint8_t*>(m_buffer->m_datlen.m_data); 00324 } 00325 00326 ////////////////////////////////////////////////////////////////////////////////////////// 00327 // Return the length of the message buffer. 00328 uint16_t Message::getTotalMessageSize(void) const 00329 { 00330 if (m_buffer->m_length == 255) 00331 return ((uint16_t) m_buffer->m_datlen.m_extended.m_length.m_high * 256 + (uint16_t) m_buffer->m_datlen.m_extended.m_length.m_low) + CMT_LEN_MSGEXTHEADERCS; 00332 else 00333 return m_buffer->m_length + CMT_LEN_MSGHEADERCS; 00334 } 00335 00336 ////////////////////////////////////////////////////////////////////////////////////////// 00337 bool Message::isChecksumOk(void) const 00338 { 00339 if (getTotalMessageSize() > m_maxLength) 00340 return false; 00341 return calcChecksum() == m_checksum[0]; 00342 } 00343 00344 ////////////////////////////////////////////////////////////////////////////////////////// 00345 // Read the entire message from the given source string 00346 XsensResultValue Message::loadFromString(const uint8_t* source, const uint16_t size) 00347 { 00348 MSGLOG(__FUNCTION__ " size=%hu, first 7 bytes: %02x %02x %02x %02x %02x %02x %02x\n",size,source[0],source[1],source[2],source[3],source[4],source[5],source[6]); 00349 if (size > m_maxLength) 00350 { 00351 MSGLOG(__FUNCTION__ " returns XRV_PARAMINVALID\n"); 00352 return XRV_PARAMINVALID; 00353 } 00354 memcpy(m_buffer,source,size); 00355 m_checksum = ((uint8_t*) m_buffer) + size-1; 00356 // check the size 00357 if (m_buffer->m_length == CMT_EXTLENCODE) 00358 { 00359 if (((uint16_t) m_buffer->m_datlen.m_extended.m_length.m_high * 256 + (uint16_t) m_buffer->m_datlen.m_extended.m_length.m_low) > size-CMT_LEN_MSGEXTHEADERCS) 00360 { 00361 MSGLOG(__FUNCTION__ " returns XRV_DATACORRUPT (extended length)\n"); 00362 return XRV_DATACORRUPT; 00363 } 00364 } 00365 else 00366 { 00367 if (m_buffer->m_length > size-CMT_LEN_MSGHEADERCS) 00368 { 00369 MSGLOG(__FUNCTION__ " returns XRV_DATACORRUPT (normal length)\n"); 00370 return XRV_DATACORRUPT; 00371 } 00372 } 00373 00374 if (m_checksum[0] != calcChecksum()) 00375 { 00376 MSGLOG(__FUNCTION__ " returns XRV_CHECKSUMFAULT\n"); 00377 return XRV_CHECKSUMFAULT; 00378 } 00379 00380 MSGLOG(__FUNCTION__ " returns XRV_OK\n"); 00381 return XRV_OK; 00382 } 00383 00384 ////////////////////////////////////////////////////////////////////////////////////////// 00385 void Message::resizeData(const uint16_t newSize) 00386 { 00387 int32_t index, oldLength; 00388 00389 MSGLOG("Message.resizeData(%hu): buffer = %p\n",newSize,m_buffer); 00390 00391 if ((uint32_t) (newSize + CMT_LEN_MSGEXTHEADERCS) > m_maxLength) 00392 { 00393 uint16_t newLen = (uint16_t) (m_maxLength+m_maxLength); 00394 if ((newSize + CMT_LEN_MSGEXTHEADERCS) > newLen) 00395 newLen = newSize + CMT_LEN_MSGEXTHEADERCS; 00396 m_buffer = (MessageHeader*) realloc(m_buffer,newLen); 00397 m_maxLength = newLen; 00398 } 00399 00400 MSGLOG("Message.resizeData after realloc(%hu): buffer = %p\n",m_maxLength,m_buffer); 00401 00402 if (newSize >= CMT_EXTLENCODE) 00403 { 00404 if (m_buffer->m_length < CMT_EXTLENCODE) 00405 { 00406 // make extended, shift all data 2 bytes up 00407 for (index = (int32_t) m_buffer->m_length; index >= 0; --index) 00408 m_buffer->m_datlen.m_extended.m_data[index] = 00409 m_buffer->m_datlen.m_data[index]; 00410 00411 oldLength = m_buffer->m_length; 00412 m_buffer->m_length = CMT_EXTLENCODE; 00413 } 00414 else 00415 { 00416 oldLength = ((uint16_t) m_buffer->m_datlen.m_extended.m_length.m_high * 256 + (uint16_t) m_buffer->m_datlen.m_extended.m_length.m_low); 00417 } 00418 m_buffer->m_datlen.m_extended.m_length.m_high = (uint8_t) (newSize >> 8); 00419 m_buffer->m_datlen.m_extended.m_length.m_low = (uint8_t) newSize; 00420 00421 for (index = oldLength; index < newSize; ++index) 00422 m_buffer->m_datlen.m_extended.m_data[index] = 0; 00423 00424 m_checksum = &m_buffer->m_datlen.m_extended.m_data[newSize]; 00425 } 00426 else 00427 { 00428 if (m_buffer->m_length == CMT_EXTLENCODE) 00429 { 00430 oldLength = ((uint16_t) m_buffer->m_datlen.m_extended.m_length.m_high * 256 + (uint16_t) m_buffer->m_datlen.m_extended.m_length.m_low); 00431 // un-extend, shift all data 2 bytes down 00432 for (index = 0; index < newSize; ++index) 00433 m_buffer->m_datlen.m_data[index] = 00434 m_buffer->m_datlen.m_extended.m_data[index]; 00435 } 00436 else 00437 oldLength = m_buffer->m_length; 00438 m_buffer->m_length = (uint8_t) newSize; 00439 for (index = oldLength; index < newSize; ++index) 00440 m_buffer->m_datlen.m_data[index] = 0; 00441 m_checksum = &m_buffer->m_datlen.m_data[newSize]; 00442 } 00443 if (m_autoUpdateChecksum) 00444 recomputeChecksum(); 00445 MSGLOG("Message.resizeData end(%hu): buffer = %p\n",m_maxLength,m_buffer); 00446 } 00447 00448 ////////////////////////////////////////////////////////////////////////////////////////// 00449 // Set the new value of the m_busId field and update the checksum. 00450 void Message::setBusId(const uint8_t busId) 00451 { 00452 if (m_autoUpdateChecksum) 00453 m_checksum[0] += m_buffer->m_busId - busId; 00454 m_buffer->m_busId = busId; 00455 } 00456 00457 ////////////////////////////////////////////////////////////////////////////////////////// 00458 // Write a string of bytes into the data buffer. 00459 void Message::setDataBuffer(const uint8_t* data, const uint16_t offset, 00460 const uint16_t count) 00461 { 00462 if (getDataSize() < offset+count) 00463 resizeData(offset+count); 00464 00465 if (count > 0) 00466 { 00467 uint8_t * dest = &(getDataStart()[offset]); 00468 for (uint16_t i = 0;i < count;++i) 00469 { 00470 if (m_autoUpdateChecksum) 00471 m_checksum[0] += dest[i] - data[i]; 00472 dest[i] = data[i]; 00473 } 00474 } 00475 } 00476 00477 ////////////////////////////////////////////////////////////////////////////////////////// 00478 void Message::setDataByte(const uint8_t data, const uint16_t offset) 00479 { 00480 if (getDataSize() < offset + 1) 00481 resizeData(offset+1); 00482 00483 uint8_t* dest = &(getDataStart()[offset]); 00484 if (m_autoUpdateChecksum) 00485 m_checksum[0] += dest[0] - data; 00486 dest[0] = data; 00487 } 00488 00489 ////////////////////////////////////////////////////////////////////////////////////////// 00490 void Message::setDataDouble(const double data, const uint16_t offset) 00491 { 00492 if (getDataSize() < offset+8) 00493 resizeData(offset+8); 00494 00495 uint8_t* dest = &(getDataStart()[offset]); 00496 const uint8_t* cdata = (const uint8_t*) &data; 00497 if (m_autoUpdateChecksum) 00498 m_checksum[0] += dest[0] + dest[1] + dest[2] + dest[3] 00499 + dest[4] + dest[5] + dest[6] + dest[7] 00500 - cdata[0] - cdata[1] - cdata[2] - cdata[3] 00501 - cdata[4] - cdata[5] - cdata[6] - cdata[7]; 00502 00503 const uint8_t* src = (const uint8_t*) &data; 00504 dest[0] = src[7]; dest[1] = src[6]; dest[2] = src[5]; dest[3] = src[4]; 00505 dest[4] = src[3]; dest[5] = src[2]; dest[6] = src[1]; dest[7] = src[0]; 00506 } 00507 00508 ////////////////////////////////////////////////////////////////////////////////////////// 00509 void Message::setDataFloat(const float data, const uint16_t offset) 00510 { 00511 if (getDataSize() < offset+4) 00512 resizeData(offset+4); 00513 00514 uint8_t* dest = &(getDataStart()[offset]); 00515 const uint8_t* cdata = (const uint8_t*) &data; 00516 if (m_autoUpdateChecksum) 00517 m_checksum[0] += dest[0] + dest[1] + dest[2] + dest[3] 00518 - cdata[0] - cdata[1] - cdata[2] - cdata[3]; 00519 00520 const uint8_t* src = (const uint8_t*) &data; 00521 dest[0] = src[3]; 00522 dest[1] = src[2]; 00523 dest[2] = src[1]; 00524 dest[3] = src[0]; 00525 } 00526 00527 ////////////////////////////////////////////////////////////////////////////////////////// 00528 void Message::setDataF1220(const double data, const uint16_t offset) 00529 { 00530 int32_t val = (int32_t) (data*1048576.0); 00531 setDataLong(val,offset); 00532 } 00533 00534 ////////////////////////////////////////////////////////////////////////////////////////// 00535 // Return the current value of the data as a double(64 bits), after converting it from F1220. 00536 void Message::setDataFP1632(const double data, const uint16_t offset) 00537 { 00538 if (getDataSize() < offset+6) 00539 resizeData(offset+6); 00540 00541 Itypes fp; 00542 fp.d = data; 00543 int32_t dexp = ((fp.i32.i0 & (0x7fffffffL)) >> 20) - 1023; 00544 00545 int16_t fpint; 00546 int32_t fpfrac; 00547 00548 if (dexp <= 14) 00549 { 00550 fp.i16.s0 = (fp.i16.s0 & 0x000F) | 0x0010; 00551 if (data < 0) 00552 fp.i64 = -fp.i64; 00553 if (dexp > -32) 00554 fp.i64 = fp.i64 >> (20-dexp); // 52-32 - exponent 00555 else 00556 fp.i64 = fp.i64 >> 52; // this could be optimized? 00557 fpint = fp.i16.s1; 00558 fpfrac = fp.i32.i1; 00559 } 00560 else 00561 { 00562 if (data < 0) 00563 { 00564 fpint = ((int16_t) (0x8000)); 00565 fpfrac = 0; 00566 } 00567 else 00568 { 00569 fpint = 0x7fff; 00570 fpfrac = -1; 00571 } 00572 } 00573 00574 uint8_t* src = (uint8_t*) &fpfrac; 00575 uint8_t* dest = &(getDataStart()[offset]); 00576 00577 *(dest++) = src[3]; 00578 *(dest++) = src[2]; 00579 *(dest++) = src[1]; 00580 *(dest++) = src[0]; 00581 00582 src = (uint8_t*) &fpint; 00583 *(dest++) = src[1]; 00584 *(dest++) = src[0]; 00585 } 00586 00587 ////////////////////////////////////////////////////////////////////////////////////////// 00588 void Message::setDataFPValue(const uint64_t outputSettings, const double data, const uint16_t offset) 00589 { 00590 switch (outputSettings & CMT_OUTPUTSETTINGS_DATAFORMAT_MASK) 00591 { 00592 case CMT_OUTPUTSETTINGS_DATAFORMAT_FLOAT: 00593 return setDataFloat((const float)data, offset); 00594 00595 case CMT_OUTPUTSETTINGS_DATAFORMAT_DOUBLE: 00596 return setDataDouble(data, offset); 00597 00598 case CMT_OUTPUTSETTINGS_DATAFORMAT_FP1632: 00599 return setDataFP1632(data, offset); 00600 00601 case CMT_OUTPUTSETTINGS_DATAFORMAT_F1220: 00602 return setDataF1220(data, offset); 00603 } 00604 } 00605 00606 ////////////////////////////////////////////////////////////////////////////////////////// 00607 void Message::setDataFPValue(const uint64_t outputSettings, const double *data, uint16_t offset, const uint16_t numValues) 00608 { 00609 for (uint16_t i=0; i<numValues; i++) { 00610 switch (outputSettings & CMT_OUTPUTSETTINGS_DATAFORMAT_MASK) 00611 { 00612 case CMT_OUTPUTSETTINGS_DATAFORMAT_FLOAT: 00613 setDataFloat((float)data[i], offset); 00614 offset += 4; 00615 break; 00616 00617 case CMT_OUTPUTSETTINGS_DATAFORMAT_DOUBLE: 00618 setDataDouble(data[i], offset); 00619 offset += 8; 00620 break; 00621 00622 case CMT_OUTPUTSETTINGS_DATAFORMAT_FP1632: 00623 setDataFP1632(data[i], offset); 00624 offset += 6; 00625 break; 00626 00627 case CMT_OUTPUTSETTINGS_DATAFORMAT_F1220: 00628 setDataF1220(data[i], offset); 00629 offset += 4; 00630 } 00631 } 00632 } 00633 00634 ////////////////////////////////////////////////////////////////////////////////////////// 00635 void Message::setDataLong(const uint32_t data, const uint16_t offset) 00636 { 00637 if (getDataSize() < offset+4) 00638 resizeData(offset+4); 00639 00640 uint8_t* dest = &(getDataStart()[offset]); 00641 if (m_autoUpdateChecksum) 00642 m_checksum[0] +=(uint8_t)(dest[0] + dest[1] + dest[2] + dest[3] - (data & 0xFF)- 00643 ((data >> 8) & 0xFF) - ((data >> 16) & 0xFF) - ((data >> 24) & 0xFF)); 00644 00645 const uint8_t* src = (const uint8_t*) &data; 00646 dest[0] = src[3]; 00647 dest[1] = src[2]; 00648 dest[2] = src[1]; 00649 dest[3] = src[0]; 00650 } 00651 00652 ////////////////////////////////////////////////////////////////////////////////////////// 00653 void Message::setDataShort(const uint16_t data, const uint16_t offset) 00654 { 00655 if (getDataSize() < offset+2) 00656 resizeData(offset+2); 00657 00658 uint8_t* dest = &(getDataStart()[offset]); 00659 if (m_autoUpdateChecksum) 00660 m_checksum[0] += dest[0] + dest[1] - (data & 255) - (data >> 8); 00661 00662 const uint8_t* src = (const uint8_t*) &data; 00663 dest[0] = src[1]; 00664 dest[1] = src[0]; 00665 } 00666 00667 ////////////////////////////////////////////////////////////////////////////////////////// 00668 // Set the new value of the m_messageId field and update the checksum. 00669 void Message::setMessageId(const uint8_t msgId) 00670 { 00671 if (m_autoUpdateChecksum) 00672 m_checksum[0] += m_buffer->m_messageId - msgId; 00673 m_buffer->m_messageId =msgId; 00674 } 00675 00676 ////////////////////////////////////////////////////////////////////////////////////////// 00677 // Copy message src into this 00678 void Message::operator = (const Message& src) 00679 { 00680 if (m_maxLength != src.m_maxLength) 00681 { 00682 LSTCHKDELNUL(m_buffer); 00683 m_maxLength = src.m_maxLength; 00684 m_buffer = (MessageHeader*) new char[m_maxLength]; 00685 } 00686 memcpy(m_buffer,src.m_buffer,m_maxLength); 00687 ptrdiff_t add = (uint8_t*) src.m_checksum - (uint8_t*) src.m_buffer; 00688 m_checksum = (uint8_t*) m_buffer + add; 00689 } 00690 00691 ////////////////////////////////////////////////////////////////////////////////////////// 00692 // Remove a number of bytes from the message (this will reduce the message size) 00693 void Message::deleteData(uint16_t size, uint16_t offset) 00694 { 00695 if (size == 0) 00696 return; 00697 uint16_t oldSize = getDataSize(); 00698 uint16_t newSize; 00699 if (offset >= oldSize) 00700 return; 00701 00702 if (oldSize > offset + size) 00703 newSize = oldSize - size; 00704 else 00705 newSize = offset; 00706 00707 // shift all bytes after the offset down by size positions 00708 uint8_t* address = getDataBuffer(); 00709 for (uint16_t i = offset; i < newSize; ++i) 00710 address[i] = address[i+size]; 00711 00712 // reduce the message length 00713 resizeData(newSize); 00714 } 00715 00716 ////////////////////////////////////////////////////////////////////////////////////////// 00717 // Insert a number of bytes into the message (this will increase the message size) 00718 void Message::insertData(uint16_t size, uint16_t offset) 00719 { 00720 if (size == 0) 00721 return; 00722 // stretch the message 00723 uint16_t oldSize = getDataSize(); 00724 resizeData(oldSize + size); 00725 // shift the bytes after the offset up by size positions 00726 uint8_t* address = getDataBuffer(); 00727 for (uint16_t i = oldSize-1; i >= offset && i < oldSize; --i) 00728 address[i+size] = address[i]; 00729 } 00730 00731 ////////////////////////////////////////////////////////////////////////////////////////// 00732 // Compute the checksum of the given byte string. 00733 uint8_t computeChecksum(const uint8_t* buffer, uint32_t length) 00734 { 00735 uint8_t cs = 0; 00736 while (length--) 00737 cs -= *(buffer++); 00738 00739 return cs; 00740 } 00741 00742 } // end of xsens namespace