cmtmessage.cpp

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
Generated on Sun May 8 08:41:36 2011 for iLab Neuromorphic Vision Toolkit by  doxygen 1.6.3