XsensMTiModule.cpp
Go to the documentation of this file.
1/*
2 * Player - One Hell of a Robot Server
3 * Copyright (C) 2006 Radu Bogdan Rusu (rusu@cs.tum.edu)
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 *
19 */
20/*
21 Desc: Driver for XSens MTx/MTi IMU. CMTComm class borrowed from XSens under GPL.
22 Author: Radu Bogdan Rusu
23 Date: 1 Aug 2006
24 */
25// MTComm.cpp: implementation of the CMTComm class.
26//
27// Version 1.2.0
28// Public release
29//
30// v1.2.0
31// 27-02-2006 - Renamed Xbus class to Motion Tracker C++ Communication class, short MTComm
32// - Defines XBRV_* accordingly renamed to MTRV_*
33// - Fixed device length not correct for bid 0 when using Xbus Master and setDeviceMode function
34//
35// v1.1.7
36// 15-02-2006 - Added fixed point signed 12.20 dataformat support
37// Added selective calibrated data output per sensor type support
38// Added outputmode temperature support
39// Fixed warning C4244: '=' : conversion from '' to '', possible loss of data
40// v1.1.6
41// 25-01-2006 - Added escape function for CLRDTR, CLRRTS, SETDTR, SETRTS, SETXOFF, SETXON, SETBREAK, CLRBREAK
42//
43// v1.1.5
44// 14-11-2005 - Made swapEndian a static member function, Job Mulder
45//
46// v1.1.4
47// 08-11-2005 - Changed practically all uses of m_timeOut into uses of the new m_clkEnd
48// - Changed COM timeout in win32 to return immediately if data is available,
49// but wait 1ms otherwise
50//
51// v1.1.3
52// 18-10-2005 - Added MID_REQPRODUCTCODE, MID_REQ/SETTRANSMITDELAY
53// - Added MTRV_TIMEOUTNODATA indicating timeout occurred due to no data read
54//
55// v1.1.2
56// 16-09-2005 - Added eMTS version 0.1->1.0 changes (EMTS_FACTORYMODE)
57// - Added factory output mode defines
58//
59// v1.1.1
60// 01-09-2005 - Added defines for Extended output mode
61// - Added reqSetting (byte array in + out & no param variant)
62//
63// v1.1
64// 08-08-2005 - Added file read and write support
65// - Added functions for data retrieval (getValue etc)
66// for easy data retrieval of acc, gyr, mag etc
67// - ReadMessageRaw:
68// - added a temporary buffer for unprocessed bytes
69// - check for invalid length messages
70// - Changed BID_MT into 1 and added BID_MASTER (=0xFF)
71// - Changed various ....SerialPort functions to .....Port
72// - Changed mtSendMessage functions to mtWriteMessage
73// - Added numerous defines
74// - Deleted obsolete functions
75// - Changed function getLastErrorCode into getLastDeviceError
76// - Changed OpenPort function for compatiblity with Bluetooth ports
77// - Added workaround for lockup of USB driver (close function)
78// - Added workaround for clock() problem with read function of USB driver
79//
80// v1.0.2
81// 29-06-2005 - Inserted initSerialPort with devicename input
82// - Changed return value defines names from X_ to MTRV_
83// - Removed unneeded includes for linux
84//
85// v1.0.1
86// 22-06-2005 - Fixed ReqSetting functions (byte array & param variant)
87// mtSendRawString had wrong length input
88//
89// v1.0.0
90// 20-06-2005 - Initial release
91//
92// ----------------------------------------------------------------------------
93// This file is an Xsens Code Examples.
94//
95// Copyright (C) Xsens Technologies B.V., 2005.
96//
97// This source code is intended only as a example of the implementation
98// of the Xsens MT Communication protocol.
99// It was written for cross platform capabilities.
100//
101// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY
102// KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
103// IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
104// PARTICULAR PURPOSE.
105//////////////////////////////////////////////////////////////////////
106#include "XsensMTiModule.h"
107
108#ifdef _IMU_USE_XSENS_DEVICE_
109
110#ifdef _DEBUG
111#undef THIS_FILE
112static char THIS_FILE[] = __FILE__;
113#define new DEBUG_NEW
114#endif
115
116#ifndef CRTSCTS
117#ifdef IHFLOW
118#ifdef OHFLOW
119#define CRTSCTS ((IHFLOW) | (OHFLOW))
120#endif
121#endif
122#endif
123
124namespace IMU::Xsens
125{
126 //////////////////////////////////////////////////////////////////////
127 // Construction/Destruction
128 //////////////////////////////////////////////////////////////////////
129 //
131 {
132 m_handle = -1;
133 m_portOpen = false;
134 m_fileOpen = false;
135 m_deviceError = 0; // No error
139 m_clkEnd = 0;
140
141 for (int i = 0; i < MAXDEVICES + 1; i++)
142 {
145 m_storedDataLength[i] = 0;
146 }
147 }
148
153
154 ////////////////////////////////////////////////////////////////////
155 // clockms
156 //
157 // Calculates the processor time used by the calling process.
158 // For linux use gettimeofday instead of clock() function
159 // When using read from FTDI serial port in a loop the
160 // clock() function very often keeps returning 0.
161 //
162 // Output
163 // returns processor time in milliseconds
164 //
165 clock_t
167 {
168 clock_t clk;
169#ifdef WIN32
170 clk = clock(); // Get current processor time
171#if (CLOCKS_PER_SEC != 1000)
172 clk /= (CLOCKS_PER_SEC / 1000);
173 // clk = (clk * 1000) / CLOCKS_PER_SEC;
174#endif
175#else
176 struct timeval tv;
177 struct timezone tz;
178 gettimeofday(&tv, &tz);
179 clk = tv.tv_sec * 1000 + (tv.tv_usec / 1000);
180#endif
181 return clk;
182 }
183
184 ////////////////////////////////////////////////////////////////////
185 // openPort (serial port number as input parameter)
186 //
187 // Opens a 'live' connection to a MT or XM
188 //
189 // Input
190 // portNumber : number of serial port to open (1-99)
191 // baudrate : baudrate value (One of the PBR_* defines), default = PBR_115K2
192 // inqueueSize : size of input queue, default = 4096
193 // outqueueSize: size of output queue, default = 1024
194 //
195 // Output
196 // returns MTRV_OK if serial port is successfully opened, else MTRV_INPUTCANNOTBEOPENED
197 //
198 short
199 CXsensMTiModule::openPort(const int portNumber,
200 const unsigned long baudrate,
201 const unsigned long /*inqueueSize*/,
202 const unsigned long /*outqueueSize*/)
203 {
204 m_clkEnd = 0;
205
206 if (m_fileOpen || m_portOpen)
207 {
209 }
210
211#ifdef WIN32
212 char pchFileName[10];
213
214 sprintf(pchFileName, "\\\\.\\COM%d", portNumber); // Create file name
215
216 m_handle =
217 CreateFile(pchFileName, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL);
218
219 if (m_handle == INVALID_HANDLE_VALUE)
220 {
222 }
223
224 // Once here, port is open
225 m_portOpen = true;
226
227 //Get the current state & then change it
228 DCB dcb;
229
230 GetCommState(m_handle, &dcb); // Get current state
231
232 dcb.BaudRate = baudrate; // Setup the baud rate
233 dcb.Parity = NOPARITY; // Setup the Parity
234 dcb.ByteSize = 8; // Setup the data bits
235 dcb.StopBits = TWOSTOPBITS; // Setup the stop bits
236 dcb.fDsrSensitivity = FALSE; // Setup the flow control
237 dcb.fOutxCtsFlow = FALSE; // NoFlowControl:
238 dcb.fOutxDsrFlow = FALSE;
239 dcb.fOutX = FALSE;
240 dcb.fInX = FALSE;
241
242 if (!SetCommState(m_handle, (LPDCB)&dcb))
243 {
244 // Set new state
245 // Bluetooth ports cannot always be opened with 2 stopbits
246 // Now try to open port with 1 stopbit.
247 dcb.StopBits = ONESTOPBIT;
248
249 if (!SetCommState(m_handle, (LPDCB)&dcb))
250 {
251 CloseHandle(m_handle);
252 m_handle = INVALID_HANDLE_VALUE;
253 m_portOpen = false;
255 }
256 }
257
258 // Set COM timeouts
259 COMMTIMEOUTS CommTimeouts;
260
261 GetCommTimeouts(m_handle, &CommTimeouts); // Fill CommTimeouts structure
262
263 // immediate return if data is available, wait 1ms otherwise
264 CommTimeouts.ReadTotalTimeoutConstant = 1;
265 CommTimeouts.ReadIntervalTimeout = MAXDWORD;
266 CommTimeouts.ReadTotalTimeoutMultiplier = MAXDWORD;
267
268 // immediate return whether data is available or not
269 // CommTimeouts.ReadTotalTimeoutConstant = 0;
270 // CommTimeouts.ReadIntervalTimeout = MAXDWORD;
271 // CommTimeouts.ReadTotalTimeoutMultiplier = 0;
272
273 SetCommTimeouts(m_handle, &CommTimeouts); // Set CommTimeouts structure
274
275 // Other initialization functions
276 EscapeCommFunction(m_handle, SETRTS); // Enable RTS (for Xbus Master use)
277 SetupComm(m_handle, inqueueSize, outqueueSize); // Set queue size
278
279 // Remove any 'old' data in buffer
280 PurgeComm(m_handle, PURGE_TXCLEAR | PURGE_RXCLEAR);
281
282 return (m_retVal = MTRV_OK);
283#else
284 char chPort[32];
285 struct termios options;
286
287 /* Open port */
288 sprintf(chPort, "/dev/ttyS%d", (portNumber - 1));
289 m_handle = open(chPort, O_RDWR | O_NOCTTY);
290
291 // O_RDWR: Read+Write
292 // O_NOCTTY: Raw input, no "controlling terminal"
293 // O_NDELAY: Don't care about DCD signal
294
295 if (m_handle < 0)
296 {
297 // Port not open
299 }
300
301 // Once here, port is open
302 m_portOpen = true;
303
304 /* Start configuring of port for non-canonical transfer mode */
305 // Get current options for the port
306 tcgetattr(m_handle, &options);
307
308 // Set baudrate.
309 cfsetispeed(&options, baudrate);
310 cfsetospeed(&options, baudrate);
311
312 // Enable the receiver and set local mode
313 options.c_cflag |= (CLOCAL | CREAD);
314 // Set character size to data bits and set no parity Mask the characte size bits
315 options.c_cflag &= ~(CSIZE | PARENB);
316 options.c_cflag |= CS8; // Select 8 data bits
317 options.c_cflag |= CSTOPB; // send 2 stop bits
318 // Disable hardware flow control
319 options.c_cflag &= ~CRTSCTS;
320 options.c_lflag &= ~(ECHO | ECHONL | ICANON | ISIG | IEXTEN);
321 // Disable software flow control
322 options.c_iflag &= ~(IGNBRK | BRKINT | PARMRK | ISTRIP | INLCR | IGNCR | ICRNL | IXON);
323 // Set Raw output
324 options.c_oflag &= ~OPOST;
325 // Timeout 0.005 sec for first byte, read minimum of 0 bytes
326 options.c_cc[VMIN] = 0;
327 options.c_cc[VTIME] = 5;
328
329 // Set the new options for the port
330 tcsetattr(m_handle, TCSANOW, &options);
331
332 tcflush(m_handle, TCIOFLUSH);
333
334 return (m_retVal = MTRV_OK);
335#endif
336 }
337
338 ////////////////////////////////////////////////////////////////////
339 // openPort (string as input parameter)
340 //
341 // Opens a 'live' connection to a MT or XM
342 //
343 // Input
344 // portName : device name of serial port ("/dev/ttyUSB0" or "\\\\.\\COM1")
345 // baudrate : baudrate value (One of the PBR_* defines), default = PBR_115K2
346 // inqueueSize : size of input queue, default = 4096
347 // outqueueSize: size of output queue, default = 1024
348 //
349 // Output
350 // returns MTRV_OK if serial port is successfully opened, else MTRV_INPUTCANNOTBEOPENED
351 //
352 short
353 CXsensMTiModule::openPort(const char* portName,
354 const unsigned long baudrate,
355 const unsigned long /*inqueueSize*/,
356 const unsigned long /*outqueueSize*/)
357 {
358 m_clkEnd = 0;
359
360 if (m_fileOpen || m_portOpen)
361 {
363 }
364
365#ifdef WIN32
366 m_handle =
367 CreateFile(portName, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL);
368
369 if (m_handle == INVALID_HANDLE_VALUE)
370 {
372 }
373
374 // Once here, port is open
375 m_portOpen = true;
376
377 //Get the current state & then change it
378 DCB dcb;
379
380 GetCommState(m_handle, &dcb); // Get current state
381
382 dcb.BaudRate = baudrate; // Setup the baud rate
383 dcb.Parity = NOPARITY; // Setup the Parity
384 dcb.ByteSize = 8; // Setup the data bits
385 dcb.StopBits = TWOSTOPBITS; // Setup the stop bits
386 dcb.fDsrSensitivity = FALSE; // Setup the flow control
387 dcb.fOutxCtsFlow = FALSE; // NoFlowControl:
388 dcb.fOutxDsrFlow = FALSE;
389 dcb.fOutX = FALSE;
390 dcb.fInX = FALSE;
391
392 if (!SetCommState(m_handle, (LPDCB)&dcb))
393 {
394 // Set new state
395 // Bluetooth ports cannot always be opened with 2 stopbits
396 // Now try to open port with 1 stopbit.
397 dcb.StopBits = ONESTOPBIT;
398
399 if (!SetCommState(m_handle, (LPDCB)&dcb))
400 {
401 CloseHandle(m_handle);
402 m_handle = INVALID_HANDLE_VALUE;
403 m_portOpen = false;
405 }
406 }
407
408 // Set COM timeouts
409 COMMTIMEOUTS CommTimeouts;
410
411 GetCommTimeouts(m_handle, &CommTimeouts); // Fill CommTimeouts structure
412
413 // immediate return if data is available, wait 1ms otherwise
414 CommTimeouts.ReadTotalTimeoutConstant = 1;
415 CommTimeouts.ReadIntervalTimeout = MAXDWORD;
416 CommTimeouts.ReadTotalTimeoutMultiplier = MAXDWORD;
417
418 // immediate return whether data is available or not
419 // CommTimeouts.ReadTotalTimeoutConstant = 0;
420 // CommTimeouts.ReadIntervalTimeout = MAXDWORD;
421 // CommTimeouts.ReadTotalTimeoutMultiplier = 0;
422 SetCommTimeouts(m_handle, &CommTimeouts); // Set CommTimeouts structure
423
424 // Other initialization functions
425 EscapeCommFunction(m_handle, SETRTS); // Enable RTS (for Xbus Master use)
426 SetupComm(m_handle, inqueueSize, outqueueSize); // Set queue size
427
428 // Remove any 'old' data in buffer
429 PurgeComm(m_handle, PURGE_TXCLEAR | PURGE_RXCLEAR);
430
431 return (m_retVal = MTRV_OK);
432#else
433 struct termios options;
434
435 /* Open port */
436
437 m_handle = open(portName, O_RDWR | O_NOCTTY);
438
439 // O_RDWR: Read+Write
440 // O_NOCTTY: Raw input, no "controlling terminal"
441 // O_NDELAY: Don't care about DCD signal
442
443 if (m_handle < 0)
444 {
445 // Port not open
447 }
448
449 // Once here, port is open
450 m_portOpen = true;
451
452 /* Start configuring of port for non-canonical transfer mode */
453 // Get current options for the port
454 tcgetattr(m_handle, &options);
455
456 // Set baudrate.
457 cfsetispeed(&options, baudrate);
458 cfsetospeed(&options, baudrate);
459
460 // Enable the receiver and set local mode
461 options.c_cflag |= (CLOCAL | CREAD);
462 // Set character size to data bits and set no parity Mask the characte size bits
463 options.c_cflag &= ~(CSIZE | PARENB);
464 options.c_cflag |= CS8; // Select 8 data bits
465 options.c_cflag |= CSTOPB; // send 2 stop bits
466 // Disable hardware flow control
467 options.c_cflag &= ~CRTSCTS;
468 options.c_lflag &= ~(ECHO | ECHONL | ICANON | ISIG | IEXTEN);
469 // Disable software flow control
470 options.c_iflag &= ~(IGNBRK | BRKINT | PARMRK | ISTRIP | INLCR | IGNCR | ICRNL | IXON);
471 // Set Raw output
472 options.c_oflag &= ~OPOST;
473 // Timeout 0.005 sec for first byte, read minimum of 0 bytes
474 options.c_cc[VMIN] = 0;
475 options.c_cc[VTIME] = 5;
476
477 // Set the new options for the port
478 tcsetattr(m_handle, TCSANOW, &options);
479
480 tcflush(m_handle, TCIOFLUSH);
481
482 return (m_retVal = MTRV_OK);
483#endif
484 }
485
486 ////////////////////////////////////////////////////////////////////
487 // openFile
488 //
489 // Open file for reading and writing
490 // Filepos is at start of file
491 //
492 // Input
493 // fileName : file name including path
494 // createAlways: empties the log file, if existing
495 //
496 // Output
497 // returns MTRV_OK if the file is opened
498 // returns MTRV_INPUTCANNOTBEOPENED if the file can not be opened
499 // returns MTRV_ANINPUTALREADYOPEN if a serial port / file is already opened
500 //
501 short
502 CXsensMTiModule::openFile(const char* fileName, bool createAlways)
503 {
504 m_clkEnd = 0;
505
506 if (m_portOpen || m_portOpen)
507 {
509 }
510
511#ifdef WIN32
512 DWORD disposition = OPEN_ALWAYS;
513
514 if (createAlways == true)
515 {
516 disposition = CREATE_ALWAYS;
517 }
518
519 m_handle = CreateFile(
520 fileName, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ, NULL, disposition, 0, NULL);
521
522 if (m_handle == INVALID_HANDLE_VALUE)
523 {
525 }
526
527#else
528 int openMode = O_RDWR | O_CREAT;
529
530 if (createAlways == true)
531 {
532 openMode |= O_TRUNC;
533 }
534
535 m_handle = open(fileName, openMode, S_IRWXU);
536
537 if (m_handle < 0)
538 {
540 }
541
542#endif
543 m_timeOut = 0; // No timeout when using file input
544 m_fileOpen = true;
545 return (m_retVal = MTRV_OK);
546 }
547
548 ////////////////////////////////////////////////////////////////////
549 // isPortOpen
550 //
551 // Return if serial port is open or not
552 //
553 bool
555 {
556 return m_portOpen;
557 }
558
559 ////////////////////////////////////////////////////////////////////
560 // isFileOpen
561 //
562 // Return if serial port is open or not
563 //
564 bool
566 {
567 return m_fileOpen;
568 }
569
570 ////////////////////////////////////////////////////////////////////
571 // readData
572 //
573 // Reads bytes from serial port or file
574 //
575 // Input
576 // msgBuffer : pointer to buffer in which next string will be stored
577 // nBytesToRead : number of buffer bytes to read from serial port
578 // retval : return value, either MTRV_OK, MTRV_ENDOFFILE or MTRV_NOINPUTINITIALIZED
579 //
580 // Output
581 // number of bytes actually read
582 int
583 CXsensMTiModule::readData(unsigned char* msgBuffer, const int nBytesToRead)
584 {
585 //if(!m_fileOpen && !m_portOpen)
586 if (!(m_portOpen || m_fileOpen))
587 {
589 return 0;
590 }
591
592#ifdef WIN32
593 DWORD nBytesRead;
594 BOOL retval = ReadFile(m_handle, msgBuffer, nBytesToRead, &nBytesRead, NULL);
595
596 if (retval && nBytesRead == 0 && m_fileOpen)
597 {
599 }
600 else
601 {
603 }
604
605 return nBytesRead;
606#else
607 const int nBytesRead = read(m_handle, msgBuffer, nBytesToRead);
608
610
611 if (nBytesRead)
612 {
613 return nBytesRead;
614 }
615 else if (m_fileOpen)
616 {
618 }
619
620 return nBytesRead;
621 /*
622 if (nBytesRead == 0 && m_fileOpen)
623 {
624 nBytesRead = 0;
625 m_retVal = MTRV_ENDOFFILE;
626 }
627 else
628 m_retVal = MTRV_OK;
629 return nBytesRead;*/
630
631 // In Linux it is sometimes better to read per byte instead of a block of bytes at once
632 // Use this block if experiencing problems with the above code
633 /*
634 int j = 0; // Index in buffer for read data
635 int k = 0; // Timeout factor
636 int nRead = 0; // Bytes read from port, return by read function
637
638 do {
639 nRead = read(m_handle, &msgBuffer[j], 1);
640 if (nRead == 1) { // Byte read
641 k = 0;
642 j++;
643 }
644 else {
645 k++;
646 }
647
648 if (k == 3) { // Timeout, too long no data read from port
649 return nRead;
650 }
651 }
652 while (j < nBytesToRead);
653
654 return j;
655 */
656#endif
657 }
658
659 ////////////////////////////////////////////////////////////////////
660 // writeData
661 //
662 // Writes bytes to serial port (to do: file)
663 //
664 // Input
665 // msgBuffer : a pointer to a char buffer containing
666 // the characters to be written to serial port
667 // nBytesToWrite : number of buffer bytes to write to serial port
668 //
669 // Output
670 // number of bytes actually written
671 //
672 // The MTComm return value is != MTRV_OK if serial port is closed
673 int
674 CXsensMTiModule::writeData(const unsigned char* msgBuffer, const int nBytesToWrite)
675 {
676 if (!m_fileOpen && !m_portOpen)
677 {
679 return 0;
680 }
681
683#ifdef WIN32
684 DWORD nBytesWritten;
685 WriteFile(m_handle, msgBuffer, nBytesToWrite, &nBytesWritten, NULL);
686 return nBytesWritten;
687#else
688 return write(m_handle, msgBuffer, nBytesToWrite);
689#endif
690 }
691
692 ////////////////////////////////////////////////////////////////////
693 // flush
694 //
695 // Remove any 'old' data in COM port buffer and flushes internal
696 // temporary buffer
697 //
698 void
700 {
701 if (m_portOpen)
702 {
703#ifdef WIN32
704 // Remove any 'old' data in buffer
705 PurgeComm(m_handle, PURGE_TXCLEAR | PURGE_RXCLEAR);
706#else
707 tcflush(m_handle, TCIOFLUSH);
708#endif
709 }
710
713 }
714
715 ////////////////////////////////////////////////////////////////////
716 // escape
717 //
718 // Directs a COM port to perform an extended function
719 //
720 // Input
721 // function : Windows define. Can be one of following:
722 // CLRDTR, CLRRTS, SETDTR, SETRTS, SETXOFF, SETXON, SETBREAK, CLRBREAK
723 void
724 CXsensMTiModule::escape(unsigned long /*function*/)
725 {
726#ifdef WIN32
727 EscapeCommFunction(m_handle, function);
728#else
729#endif
730 }
731
732 ////////////////////////////////////////////////////////////////////
733 // setPortQueueSize
734 //
735 // Set input and output buffer size of serial port
736 //
737 void
738 CXsensMTiModule::setPortQueueSize(const unsigned long /*inqueueSize = 4096 */,
739 const unsigned long /*outqueueSize = 1024 */)
740 {
741 if (m_portOpen)
742 {
743#ifdef WIN32
744 SetupComm(m_handle, inqueueSize, outqueueSize); // Set queue size
745#else
746 // Not yet implemented
747#endif
748 }
749
751 }
752
753 ////////////////////////////////////////////////////////////////////
754 // setFilePos
755 //
756 // Sets the current position of the file pointer for file input
757 //
758 // Input
759 // relPos : 32-bit value specifying the relative move in bytes
760 // origin is specified in moveMethod
761 // moveMethod : FILEPOS_BEGIN, FILEPOS_CURRENT or FILEPOS_END
762 // Output
763 //
764 // returns MTRV_OK if file pointer is successfully set
765 //
766 short
767 CXsensMTiModule::setFilePos(long relPos, unsigned long moveMethod)
768 {
769#ifdef WIN32
770
771 if (m_fileOpen)
772 {
773 if (SetFilePointer(m_handle, relPos, NULL, moveMethod) != INVALID_SET_FILE_POINTER)
774 {
775 return (m_retVal = MTRV_OK);
776 }
777 }
778
779#else
780
781 if (m_fileOpen)
782 {
783 if (lseek(m_handle, relPos, moveMethod) != -1)
784 {
785 return (m_retVal = MTRV_OK);
786 }
787 }
788
789#endif
790 return (m_retVal = MTRV_NOTSUCCESSFUL);
791 }
792
793 ////////////////////////////////////////////////////////////////////
794 // getFileSize
795 //
796 // Retrieves the file size of the opened file
797 //
798 // Input
799 // Output
800 // fileSize : Number of bytes of the current file
801 //
802 // returns MTRV_OK if successful
803 //
804 short
805 CXsensMTiModule::getFileSize(unsigned long& fileSize)
806 {
807#ifdef WIN32
808
809 if (m_fileOpen)
810 {
811 if ((fileSize = GetFileSize(m_handle, NULL)) != INVALID_FILE_SIZE)
812 {
813 return (m_retVal = MTRV_OK);
814 }
815 }
816
817#else
818
819 if (m_fileOpen)
820 {
821 struct stat buf;
822
823 if (fstat(m_handle, &buf) == 0)
824 {
825 fileSize = buf.st_size;
826 return (m_retVal = MTRV_OK);
827 }
828 }
829
830#endif
831 return (m_retVal = MTRV_NOTSUCCESSFUL);
832 }
833
834 ////////////////////////////////////////////////////////////////////
835 // close
836 //
837 // Closes handle of file or serial port
838 //
839 short
841 {
842 if (m_portOpen || m_fileOpen)
843 {
844#ifdef WIN32
845
846 if (m_portOpen)
847 {
848 // Because of USB-serial driver bug
849 flush();
850 }
851
852 CloseHandle(m_handle);
853#else
855#endif
856 }
857
858 m_fileOpen = m_portOpen = false;
859 m_timeOut = TO_DEFAULT; // Restore timeout value (file input)
860 m_clkEnd = 0;
862 m_deviceError = 0; // No error
863
864 for (int i = 0; i < MAXDEVICES + 1; i++)
865 {
868 m_storedDataLength[i] = 0;
869 }
870
871 return (m_retVal = MTRV_OK);
872 }
873
874 ////////////////////////////////////////////////////////////////////
875 // readMessage
876 //
877 // Reads the next message from serial port buffer or file.
878 // To be read within current time out period
879 //
880 // Input
881 // Output
882 // mid : MessageID of message received
883 // data : array pointer to data bytes (no header)
884 // dataLen : number of data bytes read
885 // bid : BID or address of message read (optional)
886 //
887 // returns MTRV_OK if a message has been read else <>MTRV_OK
888 //
889 // Remarks
890 // allocate enough memory for message buffer
891 // use setTimeOut for different timeout value
892 short
894 unsigned char data[],
895 short& dataLen,
896 unsigned char* bid)
897 {
898 unsigned char buffer[MAXMSGLEN];
899 short msgLen;
900
901 if (!(m_fileOpen || m_portOpen))
902 {
904 }
905
906 if (readMessageRaw(buffer, &msgLen) == MTRV_OK)
907 {
908 // Message read
909 mid = buffer[IND_MID];
910
911 if (bid != nullptr)
912 {
913 *bid = buffer[IND_BID];
914 }
915
916 if (buffer[IND_LEN] != EXTLENCODE)
917 {
918 dataLen = buffer[IND_LEN];
919 memcpy(data, &buffer[IND_DATA0], dataLen);
920 }
921 else
922 {
923 dataLen = buffer[IND_LENEXTH] * 256 + buffer[IND_LENEXTL];
924 memcpy(data, &buffer[IND_DATAEXT0], dataLen);
925 }
926 }
927
928 return m_retVal;
929 }
930
931 ////////////////////////////////////////////////////////////////////
932 // readDataMessage
933 //
934 // Read a MTData or XMData message from serial port (using TimeOut val)
935 //
936 // Input
937 // data : pointer to buffer in which the DATA field of MTData/XMData is stored
938 // dataLen : number of bytes in buffer (= number bytes in DATA field)
939 // Output
940 // returns MTRV_OK if MTData / XMData message has been read else <>MTRV_OK
941 //
942 // Remarks
943 // allocate enough memory for data buffer
944 // use setTimeOut for different timeout value
945 short
946 CXsensMTiModule::readDataMessage(unsigned char data[], short& dataLen)
947 {
948 if (!(m_portOpen || m_fileOpen))
949 {
951 }
952
953 unsigned char buffer[MAXMSGLEN];
954 short buflen;
955
956 if (readMessageRaw(buffer, &buflen) == MTRV_OK)
957 {
958 if (buffer[IND_MID] == MID_MTDATA)
959 {
960 // MID_XMDATA is same
961 if (buffer[IND_LEN] != EXTLENCODE)
962 {
963 dataLen = buffer[IND_LEN];
964 memcpy(data, &buffer[IND_DATA0], dataLen);
965 }
966 else
967 {
968 dataLen = buffer[IND_LENEXTH] * 256 + buffer[IND_LENEXTL];
969 memcpy(data, &buffer[IND_DATAEXT0], dataLen);
970 }
971
972 return (m_retVal = MTRV_OK);
973 }
974 else if (buffer[IND_MID] == MID_ERROR)
975 {
976 m_deviceError = buffer[IND_DATA0];
977 return (m_retVal = MTRV_RECVERRORMSG); // Error message received
978 }
979 }
980
981 return m_retVal;
982 }
983
984 ////////////////////////////////////////////////////////////////////
985 // readMessageRaw
986 //
987 // Read a message from serial port for a certain period
988 //
989 // Input
990 // msgBuffer : pointer to buffer in which next msg will be stored
991 // msgBufferLength: integer to number of bytes written in buffer (header + data + chksum)
992 // Output
993 // returns MTRV_OK if a message has been read else <>MTRV_OK
994 //
995 // Remarks
996 // allocate enough memory for message buffer
997 // use setTimeOut for different timeout value
998 short
999 CXsensMTiModule::readMessageRaw(unsigned char* msgBuffer, short* msgBufferLength)
1000 {
1001 int state = 0;
1002 int nBytesToRead = 1;
1003 int nBytesRead = 0;
1004 int nOffset = 0;
1005 int nMsgDataLen = 0;
1006 int nMsgLen;
1007 unsigned char chCheckSum;
1008 bool Synced = false;
1009
1010 if (!(m_portOpen || m_fileOpen))
1011 {
1013 }
1014
1015 // Copy previous read bytes if available
1016 if (m_nTempBufferLen > 0)
1017 {
1018 memcpy(msgBuffer, m_tempBuffer, m_nTempBufferLen);
1019 nBytesRead = m_nTempBufferLen;
1020 m_nTempBufferLen = 0;
1021 }
1022
1023 clock_t clkStart = clockms(); // Get current processor time
1024 clock_t clkEnd = m_clkEnd; // check if the end timer is already set
1025
1026 if (clkEnd == 0)
1027 {
1028 clkEnd = clkStart + m_timeOut;
1029 }
1030
1031 while (true)
1032 {
1033 do
1034 {
1035 // First check if we already have some bytes read
1036 if (nBytesRead > 0 && nBytesToRead > 0)
1037 {
1038 if (nBytesToRead > nBytesRead)
1039 {
1040 nOffset += nBytesRead;
1041 nBytesToRead -= nBytesRead;
1042 nBytesRead = 0;
1043 }
1044 else
1045 {
1046 nOffset += nBytesToRead;
1047 nBytesRead -= nBytesToRead;
1048 nBytesToRead = 0;
1049 }
1050 }
1051
1052 // Check if serial port buffer must be read
1053 if (nBytesToRead > 0)
1054 {
1055 nBytesRead = readData(msgBuffer + nOffset, nBytesToRead);
1056
1057 if (m_retVal == MTRV_ENDOFFILE)
1058 {
1059 return (m_retVal = MTRV_ENDOFFILE);
1060 }
1061
1062 nOffset += nBytesRead;
1063 nBytesToRead -= nBytesRead;
1064 nBytesRead = 0;
1065 }
1066
1067 if (!nBytesToRead)
1068 {
1069 switch (state)
1070 {
1071 case 0: // Check preamble
1072 if (msgBuffer[IND_PREAMBLE] == PREAMBLE)
1073 {
1074 state++;
1075 nBytesToRead = 3;
1076 }
1077 else
1078 {
1079 nOffset = 0;
1080 nBytesToRead = 1;
1081 }
1082
1083 break;
1084
1085 case 1: // Check ADDR, MID, LEN
1086 if (msgBuffer[IND_LEN] != 0xFF)
1087 {
1088 state = 3;
1089 nBytesToRead =
1090 (nMsgDataLen = msgBuffer[IND_LEN]) + 1; // Read LEN + 1 (chksum)
1091 }
1092 else
1093 {
1094 state = 2;
1095 nBytesToRead = 2; // Read extended length
1096 }
1097
1098 break;
1099
1100 case 2:
1101 state = 3;
1102 nBytesToRead = (nMsgDataLen = msgBuffer[IND_LENEXTH] * 256 +
1103 msgBuffer[IND_LENEXTL]) +
1104 1; // Read LENEXT + CS
1105
1106 if (nMsgDataLen > MAXMSGLEN - LEN_MSGEXTHEADERCS)
1107 {
1108 // Not synced - check for preamble in the bytes read
1109 for (int i = 1; i < LEN_MSGEXTHEADER; i++)
1110 if (msgBuffer[i] == PREAMBLE)
1111 {
1112 // Found a maybe preamble - 'fill buffer'
1113 nBytesRead = LEN_MSGEXTHEADER - i;
1114 memmove(msgBuffer, msgBuffer + i, nBytesRead);
1115 break;
1116 }
1117
1118 Synced = false;
1119 nOffset = 0;
1120 state = 0;
1121 nBytesToRead = 1; // Start looking for preamble
1122 }
1123
1124 break;
1125
1126 case 3: // Check msg
1127 chCheckSum = 0;
1128 nMsgLen = nMsgDataLen + 5 + (msgBuffer[IND_LEN] == 0xFF ? 2 : 0);
1129
1130 for (int i = 1; i < nMsgLen; i++)
1131 {
1132 chCheckSum += msgBuffer[i];
1133 }
1134
1135 if (chCheckSum == 0)
1136 {
1137 // Checksum ok?
1138 if (nBytesRead > 0)
1139 {
1140 // Store bytes if read too much
1141 memcpy(m_tempBuffer, msgBuffer + nMsgLen, nBytesRead);
1142 m_nTempBufferLen = nBytesRead;
1143 }
1144
1145 *msgBufferLength = nMsgLen;
1146 Synced = true;
1147 return (m_retVal = MTRV_OK);
1148 }
1149 else
1150 {
1151 if (!Synced)
1152 for (
1153 int i = 1; i < nMsgLen;
1154 i++) // Not synced - maybe recheck for preamble in this incorrect message
1155 if (msgBuffer[i] == PREAMBLE)
1156 {
1157 // Found a maybe preamble - 'fill buffer'
1158 nBytesRead = nMsgLen - i;
1159 memmove(msgBuffer, msgBuffer + i, nBytesRead);
1160 break;
1161 }
1162
1163 Synced = false;
1164 nOffset = 0;
1165 state = 0;
1166 nBytesToRead = 1; // Start looking for preamble
1167 }
1168
1169 break;
1170 }
1171 }
1172 } while ((clkEnd >= clockms()) || m_timeOut == 0 || nBytesRead != 0);
1173
1174 // Check if pending message has a valid message
1175 if (state > 0)
1176 {
1177 int i;
1178
1179 // Search for preamble
1180 for (i = 1; i < nOffset; i++)
1181 if (msgBuffer[i] == PREAMBLE)
1182 {
1183 // Found a maybe preamble - 'fill buffer'
1184 nBytesRead = nOffset - i - 1; // no preamble
1185 memmove(msgBuffer + 1, msgBuffer + i + 1, nBytesRead);
1186 break;
1187 }
1188
1189 if (i < nOffset)
1190 {
1191 // Found preamble in message - recheck
1192 nOffset = 1;
1193 state = 1;
1194 nBytesToRead = 3; // Start looking for preamble
1195 continue;
1196 }
1197 }
1198
1199 break;
1200 }
1201
1202 return (m_retVal = MTRV_TIMEOUT);
1203 }
1204
1205 ////////////////////////////////////////////////////////////////////
1206 // writeMessage (optional: integer value)
1207 //
1208 // Sends a message and in case of an serial port interface it checks
1209 // if the return message (ack, error or timeout). See return value
1210 // In case an file is opened the functions returns directly after
1211 // 'sending' the message
1212 //
1213 // Use this function for GotoConfig, Reset, ResetOrientation etc
1214 //
1215 // Input
1216 // mid : MessageID of message to send
1217 // dataValue : A integer value that will be included into the data message field
1218 // can be a 1,2 or 4 bytes values
1219 // dataValueLen : Size of dataValue in bytes
1220 // bid : BID or address to use in message to send (default = 0xFF)
1221 //
1222 // Return value
1223 // = MTRV_OK if an Ack message received / or data successfully written to file
1224 // = MTRV_RECVERRORMSG if an error message received
1225 // = MTRV_TIMEOUT if timeout occurred
1226 // = MTRV_NOINPUTINITIALIZED
1227 //
1228 short
1229 CXsensMTiModule::writeMessage(const unsigned char mid,
1230 const unsigned long dataValue,
1231 const unsigned char dataValueLen,
1232 const unsigned char bid)
1233 {
1234 unsigned char buffer[MAXMSGLEN];
1235 short msgLen;
1236
1237 if (!(m_fileOpen || m_portOpen))
1238 {
1240 }
1241
1242 buffer[IND_PREAMBLE] = PREAMBLE;
1243 buffer[IND_BID] = bid;
1244 buffer[IND_MID] = mid;
1245 buffer[IND_LEN] = dataValueLen;
1246
1247 if (dataValueLen)
1248 {
1249 swapEndian((const unsigned char*)&dataValue, &buffer[IND_DATA0], dataValueLen);
1250 }
1251
1252 calcChecksum(buffer, LEN_MSGHEADER + dataValueLen);
1253
1254 // Send message
1255 writeData(buffer, LEN_MSGHEADERCS + dataValueLen);
1256
1257 // Return if file opened
1258 if (m_fileOpen)
1259 {
1260 return (m_retVal = MTRV_OK);
1261 }
1262
1263 // Keep reading until an Ack or Error message is received (or timeout)
1264 clock_t clkStart, clkOld;
1265 bool msgRead = false;
1266
1267 clkStart = clockms(); // Get current processor time
1268 clkOld = m_clkEnd;
1269
1270 if (clkOld == 0)
1271 {
1272 m_clkEnd = m_timeOut + clkStart;
1273 }
1274
1275 while (m_clkEnd >= clockms() || (m_timeOut == 0))
1276 {
1277 if (readMessageRaw(buffer, &msgLen) == MTRV_OK)
1278 {
1279 // Message received
1280 msgRead = true;
1281
1282 if (buffer[IND_MID] == (mid + 1))
1283 {
1284 m_clkEnd = clkOld;
1285 return (m_retVal = MTRV_OK); // Acknowledge received
1286 }
1287 else if (buffer[IND_MID] == MID_ERROR)
1288 {
1289 m_deviceError = buffer[IND_DATA0];
1290 m_clkEnd = clkOld;
1291 return (m_retVal = MTRV_RECVERRORMSG); // Error message received
1292 }
1293 }
1294 }
1295
1296 m_clkEnd = clkOld;
1297
1298 if (msgRead)
1299 {
1300 return (m_retVal = MTRV_TIMEOUT);
1301 }
1302 else
1303 {
1304 return (m_retVal = MTRV_TIMEOUTNODATA);
1305 }
1306 }
1307
1308 ////////////////////////////////////////////////////////////////////
1309 // writeMessage (data array)
1310 //
1311 // Sends a message and in case of an serial port interface it checks
1312 // if the return message (ack, error or timeout). See return value
1313 // In case an file is opened the functions returns directly after
1314 // 'sending' the message
1315 //
1316 // Input
1317 // mid : MessageID of message to send
1318 // data : array pointer to data bytes
1319 // dataLen : number of bytes to include in message
1320 // bid : BID or address to use in message to send (default = 0xFF)
1321 //
1322 // Output
1323 // = MTRV_OK if an Ack message received
1324 // = MTRV_RECVERRORMSG if an error message received
1325 // = MTRV_TIMEOUT if timeout occurred
1326 // = MTRV_NOINPUTINITIALIZED
1327 //
1328 short
1329 CXsensMTiModule::writeMessage(const unsigned char mid,
1330 const unsigned char data[],
1331 const unsigned short& dataLen,
1332 const unsigned char bid)
1333 {
1334 unsigned char buffer[MAXMSGLEN];
1335 short msgLen;
1336 short headerLength;
1337
1338 if (!(m_fileOpen || m_portOpen))
1339 {
1341 }
1342
1343 // Build message to send
1344 buffer[IND_PREAMBLE] = PREAMBLE;
1345 buffer[IND_BID] = bid;
1346 buffer[IND_MID] = mid;
1347
1348 if (dataLen < EXTLENCODE)
1349 {
1350 buffer[IND_LEN] = (unsigned char)dataLen;
1351 headerLength = LEN_MSGHEADER;
1352 }
1353 else
1354 {
1355 buffer[IND_LEN] = EXTLENCODE;
1356 buffer[IND_LENEXTH] = (unsigned char)(dataLen >> 8);
1357 buffer[IND_LENEXTL] = (unsigned char)(dataLen & 0x00FF);
1358 headerLength = LEN_MSGEXTHEADER;
1359 }
1360
1361 memcpy(&buffer[headerLength], data, dataLen);
1362 calcChecksum(buffer, headerLength + dataLen);
1363
1364 // Send message
1365 writeData(buffer, headerLength + dataLen + LEN_CHECKSUM);
1366
1367 // Return if file opened
1368 if (m_fileOpen)
1369 {
1370 return (m_retVal = MTRV_OK);
1371 }
1372
1373 // Keep reading until an Ack or Error message is received (or timeout)
1374 bool msgRead = false;
1375 clock_t clkStart, clkOld;
1376
1377 clkStart = clockms(); // Get current processor time
1378 clkOld = m_clkEnd;
1379
1380 if (clkOld == 0)
1381 {
1382 m_clkEnd = m_timeOut + clkStart;
1383 }
1384
1385 while (m_clkEnd >= clockms() || (m_timeOut == 0))
1386 {
1387 if (readMessageRaw(buffer, &msgLen) == MTRV_OK)
1388 {
1389 // Message received
1390 msgRead = true;
1391
1392 if (buffer[IND_MID] == (mid + 1))
1393 {
1394 m_clkEnd = clkOld;
1395 return (m_retVal = MTRV_OK); // Acknowledge received
1396 }
1397 else if (buffer[IND_MID] == MID_ERROR)
1398 {
1399 m_deviceError = buffer[IND_DATA0];
1400 m_clkEnd = clkOld;
1401 return (m_retVal = MTRV_RECVERRORMSG); // Error message received
1402 }
1403 }
1404 }
1405
1406 m_clkEnd = clkOld;
1407
1408 if (msgRead)
1409 {
1410 return (m_retVal = MTRV_TIMEOUT);
1411 }
1412 else
1413 {
1414 return (m_retVal = MTRV_TIMEOUTNODATA);
1415 }
1416 }
1417
1418 ////////////////////////////////////////////////////////////////////
1419 // waitForMessage
1420 //
1421 // Read messages from serial port or file using the current timeout period
1422 // until the received message is equal to a specific message identifier
1423 // By default the timeout period by file input is set to infinity (= until
1424 // end of file is reached)
1425 //
1426 // Input/Output
1427 // mid : message identifier of message that should be returned
1428 // data : pointer to buffer in which the data of the requested msg will be stored
1429 // dataLen : integer to number of data bytes
1430 // bid : optional, pointer which holds the bid of the returned message
1431 // Output
1432 // returns MTRV_OK if the message has been read else != MTRV_OK
1433 //
1434 // Remarks
1435 // allocate enough memory for data message buffer
1436 // use setTimeOut for different timeout value
1437 short
1438 CXsensMTiModule::waitForMessage(const unsigned char mid,
1439 unsigned char data[],
1440 short* dataLen,
1441 unsigned char* bid)
1442 {
1443 unsigned char buffer[MAXMSGLEN];
1444 short buflen;
1445
1446 clock_t clkStart, clkOld;
1447
1448 if (!(m_fileOpen || m_portOpen))
1449 {
1451 }
1452
1453 clkStart = clockms(); // Get current processor time
1454 clkOld = m_clkEnd;
1455
1456 if (clkOld == 0)
1457 {
1458 m_clkEnd = m_timeOut + clkStart;
1459 }
1460
1461 while (m_clkEnd >= clockms() || (m_timeOut == 0))
1462 {
1463 if (readMessageRaw(buffer, &buflen) == MTRV_OK)
1464 {
1465 if (buffer[IND_MID] == mid)
1466 {
1467 if (bid != nullptr)
1468 {
1469 *bid = buffer[IND_BID];
1470 }
1471
1472 if (data != nullptr && dataLen != nullptr)
1473 {
1474 if (buffer[IND_LEN] != EXTLENCODE)
1475 {
1476 *dataLen = buffer[IND_LEN];
1477 memcpy(data, &buffer[IND_DATA0], *dataLen);
1478 }
1479 else
1480 {
1481 *dataLen = buffer[IND_LENEXTH] * 256 + buffer[IND_LENEXTL];
1482 memcpy(data, &buffer[IND_DATAEXT0], *dataLen);
1483 }
1484 }
1485 else if (dataLen != nullptr)
1486 {
1487 dataLen = nullptr;
1488 }
1489
1490 m_clkEnd = clkOld;
1491 return (m_retVal = MTRV_OK);
1492 }
1493 }
1494 else if (m_retVal == MTRV_ENDOFFILE)
1495 {
1496 m_clkEnd = clkOld;
1497 return (m_retVal = MTRV_ENDOFFILE);
1498 }
1499 }
1500
1501 m_clkEnd = clkOld;
1502 return (m_retVal = MTRV_TIMEOUT);
1503 }
1504
1505 ////////////////////////////////////////////////////////////////////
1506 // reqSetting (integer & no param variant)
1507 //
1508 // Request a integer setting from the device. This setting
1509 // can be an unsigned 1,2 or 4 bytes setting. Only valid
1510 // for serial port connections
1511 //
1512 // Input
1513 // mid : Message ID of message to send
1514 // bid : Bus ID of message to send (def 0xFF)
1515 //
1516 // Output
1517 // = MTRV_OK if an Ack message is received
1518 // = MTRV_RECVERRORMSG if an error message is received
1519 // = MTRV_TIMEOUT if timeout occurred
1520 //
1521 // value contains the integer value of the data field of the ack message
1522 //
1523 short
1524 CXsensMTiModule::reqSetting(const unsigned char mid,
1525 unsigned long& value,
1526 const unsigned char bid)
1527 {
1528 unsigned char buffer[MAXMSGLEN];
1529 short msgLen;
1530
1531 if (m_fileOpen)
1532 {
1534 }
1535
1536 if (!m_portOpen)
1537 {
1539 }
1540
1541 buffer[IND_PREAMBLE] = PREAMBLE;
1542 buffer[IND_BID] = bid;
1543 buffer[IND_MID] = mid;
1544 buffer[IND_LEN] = 0;
1545 calcChecksum(buffer, LEN_MSGHEADER + buffer[IND_LEN]);
1546
1547 // Send message
1548 writeData(buffer, LEN_MSGHEADERCS + buffer[IND_LEN]);
1549
1550 // Read next message or else timeout
1551 if (readMessageRaw(buffer, &msgLen) == MTRV_OK)
1552 {
1553 // Message received
1554 if (buffer[IND_MID] == (mid + 1))
1555 {
1556 // Acknowledge received
1557 value = 0;
1558 swapEndian(&buffer[IND_DATA0], (unsigned char*)&value, buffer[IND_LEN]);
1559 return (m_retVal = MTRV_OK);
1560 }
1561 else if (buffer[IND_MID] == MID_ERROR)
1562 {
1563 m_deviceError = buffer[IND_DATA0];
1564 return (m_retVal = MTRV_RECVERRORMSG); // Error message received
1565 }
1566 else
1567 {
1568 return (m_retVal = MTRV_UNEXPECTEDMSG); // Unexpected message
1569 }
1570 }
1571
1572 return m_retVal;
1573 }
1574
1575 ////////////////////////////////////////////////////////////////////
1576 // reqSetting (integer & param variant)
1577 //
1578 // Request a integer setting from the device. This setting
1579 // can be an unsigned 1,2 or 4 bytes setting. Only valid
1580 // for serial port connections.
1581 //
1582 // Input
1583 // mid : Message ID of message to send
1584 // param : For messages that need a parameter
1585 // bid : Bus ID of message to send (def 0xFF)
1586 //
1587 // Output
1588 // = MTRV_OK if an Ack message is received
1589 // = MTRV_RECVERRORMSG if an error message is received
1590 // = MTRV_TIMEOUT if timeout occurred
1591 //
1592 // value contains the integer value of the data field of the ack message
1593 //
1594 short
1595 CXsensMTiModule::reqSetting(const unsigned char mid,
1596 const unsigned char param,
1597 unsigned long& value,
1598 const unsigned char bid)
1599 {
1600 unsigned char buffer[MAXMSGLEN];
1601 short msgLen;
1602
1603 if (m_fileOpen)
1604 {
1606 }
1607
1608 if (!m_portOpen)
1609 {
1611 }
1612
1613 buffer[IND_PREAMBLE] = PREAMBLE;
1614 buffer[IND_BID] = bid;
1615 buffer[IND_MID] = mid;
1616
1617 if (param != 0xFF)
1618 {
1619 buffer[IND_LEN] = 1;
1620 buffer[IND_DATA0] = param;
1621 }
1622 else
1623 {
1624 buffer[IND_LEN] = 0;
1625 }
1626
1627 calcChecksum(buffer, LEN_MSGHEADER + buffer[IND_LEN]);
1628
1629 // Send message
1630 writeData(buffer, LEN_MSGHEADERCS + buffer[IND_LEN]);
1631
1632 // Read next message or else timeout
1633 if (readMessageRaw(buffer, &msgLen) == MTRV_OK)
1634 {
1635 // Message received
1636 if (buffer[IND_MID] == (mid + 1))
1637 {
1638 // Acknowledge received
1639 value = 0;
1640
1641 if (param == 0xFF)
1642 {
1643 swapEndian(&buffer[IND_DATA0], (unsigned char*)&value, buffer[IND_LEN]);
1644 }
1645 else
1646 {
1647 swapEndian(&buffer[IND_DATA0] + 1, (unsigned char*)&value, buffer[IND_LEN] - 1);
1648 }
1649
1650 return (m_retVal = MTRV_OK);
1651 }
1652 else if (buffer[IND_MID] == MID_ERROR)
1653 {
1654 m_deviceError = buffer[IND_DATA0];
1655 return (m_retVal = MTRV_RECVERRORMSG); // Error message received
1656 }
1657 else
1658 {
1659 return (m_retVal = MTRV_UNEXPECTEDMSG); // Unexpected message
1660 }
1661 }
1662
1663 return m_retVal;
1664 }
1665
1666 ////////////////////////////////////////////////////////////////////
1667 // reqSetting (float & no param variant)
1668 //
1669 // Request a float setting from the device. Only valid
1670 // for serial port connections.
1671 //
1672 // Input
1673 // mid : Message ID of message to send
1674 // bid : Bus ID of message to send (def 0xFF)
1675 //
1676 // Output
1677 // = MTRV_OK if an Ack message is received
1678 // = MTRV_RECVERRORMSG if an error message is received
1679 // = MTRV_TIMEOUT if timeout occurred
1680 //
1681 // value contains the float value of the acknowledge data field
1682 //
1683 short
1684 CXsensMTiModule::reqSetting(const unsigned char mid, float& value, const unsigned char bid)
1685 {
1686 unsigned char buffer[MAXMSGLEN];
1687 short msgLen;
1688
1689 if (m_fileOpen)
1690 {
1692 }
1693
1694 if (!m_portOpen)
1695 {
1697 }
1698
1699 buffer[IND_PREAMBLE] = PREAMBLE;
1700 buffer[IND_BID] = bid;
1701 buffer[IND_MID] = mid;
1702 buffer[IND_LEN] = 0;
1703 calcChecksum(buffer, LEN_MSGHEADER + buffer[IND_LEN]);
1704
1705 // Send message
1706 writeData(buffer, LEN_MSGHEADERCS + buffer[IND_LEN]);
1707
1708 // Read next message or else timeout
1709 if (readMessageRaw(buffer, &msgLen) == MTRV_OK)
1710 {
1711 // Message received
1712 if (buffer[IND_MID] == (mid + 1))
1713 {
1714 // Acknowledge received
1715 value = 0;
1716 swapEndian(&buffer[IND_DATA0], (unsigned char*)&value, buffer[IND_LEN]);
1717 return (m_retVal = MTRV_OK);
1718 }
1719 else if (buffer[IND_MID] == MID_ERROR)
1720 {
1721 m_deviceError = buffer[IND_DATA0];
1722 return (m_retVal = MTRV_RECVERRORMSG); // Error message received
1723 }
1724 else
1725 {
1726 return (m_retVal = MTRV_UNEXPECTEDMSG); // Unexpected message
1727 }
1728 }
1729
1730 return m_retVal;
1731 }
1732
1733 ////////////////////////////////////////////////////////////////////
1734 // reqSetting (float & param variant)
1735 //
1736 // Request a float setting from the device. Only valid
1737 // for serial port connections.
1738 //
1739 // Input
1740 // mid : Message ID of message to send
1741 // param : For messages that need a parameter (optional)
1742 // bid : Bus ID of message to send (def 0xFF)
1743 //
1744 // Output
1745 // = MTRV_OK if an Ack message is received
1746 // = MTRV_RECVERRORMSG if an error message is received
1747 // = MTRV_TIMEOUT if timeout occurred
1748 //
1749 // value contains the float value of the acknowledge data field
1750 //
1751 short
1752 CXsensMTiModule::reqSetting(const unsigned char mid,
1753 const unsigned char param,
1754 float& value,
1755 const unsigned char bid)
1756 {
1757 unsigned char buffer[MAXMSGLEN];
1758 short msgLen;
1759
1760 if (m_fileOpen)
1761 {
1763 }
1764
1765 if (!m_portOpen)
1766 {
1768 }
1769
1770 buffer[IND_PREAMBLE] = PREAMBLE;
1771 buffer[IND_BID] = bid;
1772 buffer[IND_MID] = mid;
1773
1774 if (param != 0xFF)
1775 {
1776 buffer[IND_LEN] = 1;
1777 buffer[IND_DATA0] = param;
1778 }
1779 else
1780 {
1781 buffer[IND_LEN] = 0;
1782 }
1783
1784 calcChecksum(buffer, LEN_MSGHEADER + buffer[IND_LEN]);
1785
1786 // Send message
1787 writeData(buffer, LEN_MSGHEADERCS + buffer[IND_LEN]);
1788
1789 // Read next message or else timeout
1790 if (readMessageRaw(buffer, &msgLen) == MTRV_OK)
1791 {
1792 // Message received
1793 if (buffer[IND_MID] == (mid + 1))
1794 {
1795 // Acknowledge received
1796 value = 0;
1797
1798 if (param == 0xFF)
1799 {
1800 swapEndian(&buffer[IND_DATA0], (unsigned char*)&value, buffer[IND_LEN]);
1801 }
1802 else
1803 {
1804 swapEndian(&buffer[IND_DATA0] + 1, (unsigned char*)&value, buffer[IND_LEN] - 1);
1805 }
1806
1807 return (m_retVal = MTRV_OK);
1808 }
1809 else if (buffer[IND_MID] == MID_ERROR)
1810 {
1811 m_deviceError = buffer[IND_DATA0];
1812 return (m_retVal = MTRV_RECVERRORMSG); // Error message received
1813 }
1814 else
1815 {
1816 return (m_retVal = MTRV_UNEXPECTEDMSG); // Unexpected message
1817 }
1818 }
1819
1820 return m_retVal;
1821 }
1822
1823 ////////////////////////////////////////////////////////////////////
1824 // reqSetting (byte array & no param variant)
1825 //
1826 // Send a message to the device and the data of acknowledge message
1827 // will be returned. Only valid for serial port connections
1828 //
1829 // Input
1830 // mid : Message ID of message to send
1831 // bid : Bus ID of message to send (def 0xFF)
1832 //
1833 // Output
1834 // = MTRV_OK if an Ack message is received
1835 // = MTRV_RECVERRORMSG if an error message is received
1836 // = MTRV_TIMEOUT if timeout occurred
1837 //
1838 // data[] contains the data of the acknowledge message
1839 // dataLen contains the number bytes returned
1840 //
1841 short
1842 CXsensMTiModule::reqSetting(const unsigned char mid,
1843 unsigned char data[],
1844 short& dataLen,
1845 const unsigned char bid)
1846 {
1847 unsigned char buffer[MAXMSGLEN];
1848 short msgLen;
1849
1850 if (m_fileOpen)
1851 {
1853 }
1854
1855 if (!m_portOpen)
1856 {
1858 }
1859
1860 buffer[IND_PREAMBLE] = PREAMBLE;
1861 buffer[IND_BID] = bid;
1862 buffer[IND_MID] = mid;
1863 buffer[IND_LEN] = 0;
1864 calcChecksum(buffer, LEN_MSGHEADER + buffer[IND_LEN]);
1865
1866 // Send message
1867 writeData(buffer, LEN_MSGHEADERCS + buffer[IND_LEN]);
1868
1869 dataLen = 0;
1870
1871 // Read next message or else timeout
1872 if (readMessageRaw(buffer, &msgLen) == MTRV_OK)
1873 {
1874 // Message received
1875 if (buffer[IND_MID] == (mid + 1))
1876 {
1877 // Acknowledge received
1878 if (buffer[IND_LEN] != EXTLENCODE)
1879 {
1880 dataLen = buffer[IND_LEN];
1881 memcpy(data, &buffer[IND_DATA0], dataLen);
1882 }
1883 else
1884 {
1885 dataLen = buffer[IND_LENEXTH] * 256 + buffer[IND_LENEXTL];
1886 memcpy(data, &buffer[IND_DATAEXT0], dataLen);
1887 }
1888
1889 return (m_retVal = MTRV_OK);
1890 }
1891 else if (buffer[IND_MID] == MID_ERROR)
1892 {
1893 m_deviceError = buffer[IND_DATA0];
1894 return (m_retVal = MTRV_RECVERRORMSG); // Error message received
1895 }
1896 else
1897 {
1898 return (m_retVal = MTRV_UNEXPECTEDMSG); // Unexpected message
1899 }
1900 }
1901
1902 return m_retVal;
1903 }
1904
1905 ////////////////////////////////////////////////////////////////////
1906 // reqSetting (byte array in + out & no param variant)
1907 //
1908 // Send a message to the device and the data of acknowledge message
1909 // will be returned. Only valid for serial port connections
1910 //
1911 // Input
1912 // mid : Message ID of message to send
1913 // bid : Bus ID of message to send (def 0xFF)
1914 // dataIn : Data to be included in request
1915 // dataInLen : Number of bytes in dataIn
1916 //
1917 // Output
1918 // = MTRV_OK if an Ack message is received
1919 // = MTRV_RECVERRORMSG if an error message is received
1920 // = MTRV_TIMEOUT if timeout occurred
1921 //
1922 // dataOut[] contains the data of the acknowledge message
1923 // dataOutLen contains the number bytes returned
1924 //
1925 short
1926 CXsensMTiModule::reqSetting(const unsigned char mid,
1927 unsigned char dataIn[],
1928 short dataInLen,
1929 unsigned char dataOut[],
1930 short& dataOutLen,
1931 const unsigned char bid)
1932 {
1933 unsigned char buffer[MAXMSGLEN];
1934 short headerLength;
1935 short msgLen;
1936
1937 if (m_fileOpen)
1938 {
1940 }
1941
1942 if (!m_portOpen)
1943 {
1945 }
1946
1947 buffer[IND_PREAMBLE] = PREAMBLE;
1948 buffer[IND_BID] = bid;
1949 buffer[IND_MID] = mid;
1950
1951 if (dataInLen < EXTLENCODE)
1952 {
1953 buffer[IND_LEN] = (unsigned char)dataInLen;
1954 headerLength = LEN_MSGHEADER;
1955 }
1956 else
1957 {
1958 buffer[IND_LEN] = EXTLENCODE;
1959 buffer[IND_LENEXTH] = (unsigned char)(dataInLen >> 8);
1960 buffer[IND_LENEXTL] = (unsigned char)(dataInLen & 0x00FF);
1961 headerLength = LEN_MSGEXTHEADER;
1962 }
1963
1964 memcpy(&buffer[headerLength], dataIn, dataInLen);
1965 calcChecksum(buffer, headerLength + dataInLen);
1966
1967 // Send message
1968 writeData(buffer, headerLength + dataInLen + LEN_CHECKSUM);
1969
1970 dataOutLen = 0;
1971
1972 // Read next message or else timeout
1973 if (readMessageRaw(buffer, &msgLen) == MTRV_OK)
1974 {
1975 // Message received
1976 if (buffer[IND_MID] == (mid + 1))
1977 {
1978 // Acknowledge received
1979 if (buffer[IND_LEN] != EXTLENCODE)
1980 {
1981 dataOutLen = buffer[IND_LEN];
1982 memcpy(dataOut, &buffer[IND_DATA0], dataOutLen);
1983 }
1984 else
1985 {
1986 dataOutLen = buffer[IND_LENEXTH] * 256 + buffer[IND_LENEXTL];
1987 memcpy(dataOut, &buffer[IND_DATAEXT0], dataOutLen);
1988 }
1989
1990 return (m_retVal = MTRV_OK);
1991 }
1992 else if (buffer[IND_MID] == MID_ERROR)
1993 {
1994 m_deviceError = buffer[IND_DATA0];
1995 return (m_retVal = MTRV_RECVERRORMSG); // Error message received
1996 }
1997 else
1998 {
1999 return (m_retVal = MTRV_UNEXPECTEDMSG); // Unexpected message
2000 }
2001 }
2002
2003 return m_retVal;
2004 }
2005
2006 ////////////////////////////////////////////////////////////////////
2007 // reqSetting (byte array & param variant)
2008 //
2009 // Send a message to the device and the data of acknowledge message
2010 // will be returned. Only valid for serial port connections
2011 //
2012 // Input
2013 // mid : Message ID of message to send
2014 // param : For messages that need a parameter (optional)
2015 // bid : Bus ID of message to send (def 0xFF)
2016 //
2017 // Output
2018 // = MTRV_OK if an Ack message is received
2019 // = MTRV_RECVERRORMSG if an error message is received
2020 // = MTRV_TIMEOUT if timeout occurred
2021 //
2022 // data[] contains the data of the acknowledge message (including param!!)
2023 // dataLen contains the number bytes returned
2024 //
2025 short
2026 CXsensMTiModule::reqSetting(const unsigned char mid,
2027 const unsigned char param,
2028 unsigned char data[],
2029 short& dataLen,
2030 const unsigned char bid)
2031 {
2032 unsigned char buffer[MAXMSGLEN];
2033 short msgLen;
2034
2035 if (m_fileOpen)
2036 {
2038 }
2039
2040 if (!m_portOpen)
2041 {
2043 }
2044
2045 buffer[IND_PREAMBLE] = PREAMBLE;
2046 buffer[IND_BID] = bid;
2047 buffer[IND_MID] = mid;
2048
2049 if (param != 0xFF)
2050 {
2051 buffer[IND_LEN] = 1;
2052 buffer[IND_DATA0] = param;
2053 }
2054 else
2055 {
2056 buffer[IND_LEN] = 0;
2057 }
2058
2059 calcChecksum(buffer, LEN_MSGHEADER + buffer[IND_LEN]);
2060
2061 // Send message
2062 writeData(buffer, LEN_MSGHEADERCS + buffer[IND_LEN]);
2063
2064 dataLen = 0;
2065
2066 // Read next message or else timeout
2067 if (readMessageRaw(buffer, &msgLen) == MTRV_OK)
2068 {
2069 // Message received
2070 if (buffer[IND_MID] == (mid + 1))
2071 {
2072 // Acknowledge received
2073 if (buffer[IND_LEN] != EXTLENCODE)
2074 {
2075 dataLen = buffer[IND_LEN];
2076 memcpy(data, &buffer[IND_DATA0], dataLen);
2077 }
2078 else
2079 {
2080 dataLen = buffer[IND_LENEXTH] * 256 + buffer[IND_LENEXTL];
2081 memcpy(data, &buffer[IND_DATAEXT0], dataLen);
2082 }
2083
2084 return (m_retVal = MTRV_OK);
2085 }
2086 else if (buffer[IND_MID] == MID_ERROR)
2087 {
2088 m_deviceError = buffer[IND_DATA0];
2089 return (m_retVal = MTRV_RECVERRORMSG); // Error message received
2090 }
2091 else
2092 {
2093 return (m_retVal = MTRV_UNEXPECTEDMSG); // Unexpected message
2094 }
2095 }
2096
2097 return m_retVal;
2098 }
2099
2100 ////////////////////////////////////////////////////////////////////
2101 // setSetting (integer & no param variant)
2102 //
2103 // Sets a integer setting of the device. This setting
2104 // can be an unsigned 1,2 or 4 bytes setting. Only valid
2105 // for serial port connections.
2106 //
2107 // Input
2108 // mid : Message ID of message to send
2109 // bid : Bus ID of message to send (def 0xFF)
2110 // value : Contains the integer value to be used
2111 // valuelen : Length in bytes of the value
2112 //
2113 // Output
2114 // = MTRV_OK if an Ack message is received
2115 // = MTRV_RECVERRORMSG if an error message is received
2116 // = MTRV_TIMEOUT if timeout occurred
2117 //
2118 //
2119 short
2120 CXsensMTiModule::setSetting(const unsigned char mid,
2121 const unsigned long value,
2122 const unsigned short valuelen,
2123 const unsigned char bid)
2124 {
2125 unsigned char buffer[MAXMSGLEN];
2126 short msgLen;
2127
2128 if (m_fileOpen)
2129 {
2131 }
2132
2133 if (!m_portOpen)
2134 {
2136 }
2137
2138 msgLen = LEN_MSGHEADER;
2139 buffer[IND_PREAMBLE] = PREAMBLE;
2140 buffer[IND_BID] = bid;
2141 buffer[IND_MID] = mid;
2142 buffer[IND_LEN] = (unsigned char)valuelen;
2143 swapEndian((unsigned char*)&value, &buffer[msgLen], valuelen);
2144 calcChecksum(buffer, LEN_MSGHEADER + buffer[IND_LEN]);
2145
2146 // Send message
2147 writeData(buffer, LEN_MSGHEADERCS + buffer[IND_LEN]);
2148
2149 // Read next received message
2150 if (readMessageRaw(buffer, &msgLen) == MTRV_OK)
2151 {
2152 // Message received
2153 if (buffer[IND_MID] == (mid + 1))
2154 {
2155 return (m_retVal = MTRV_OK); // Acknowledge received
2156 }
2157 else if (buffer[IND_MID] == MID_ERROR)
2158 {
2159 m_deviceError = buffer[IND_DATA0];
2160 return (m_retVal = MTRV_RECVERRORMSG); // Error message received
2161 }
2162 }
2163
2164 return m_retVal;
2165 }
2166
2167 ////////////////////////////////////////////////////////////////////
2168 // setSetting (integer & param variant)
2169 //
2170 // Sets a integer setting of the device. This setting
2171 // can be an unsigned 1,2 or 4 bytes setting. Only valid
2172 // for serial port connections.
2173 //
2174 // Input
2175 // mid : Message ID of message to send
2176 // param : For messages that need a parameter (optional)
2177 // bid : Bus ID of message to send (def 0xFF)
2178 // value : Contains the integer value to be used
2179 // valuelen : Length in bytes of the value
2180 //
2181 // Output
2182 // = MTRV_OK if an Ack message is received
2183 // = MTRV_RECVERRORMSG if an error message is received
2184 // = MTRV_TIMEOUT if timeout occurred
2185 //
2186 //
2187 short
2188 CXsensMTiModule::setSetting(const unsigned char mid,
2189 const unsigned char param,
2190 const unsigned long value,
2191 const unsigned short valuelen,
2192 const unsigned char bid)
2193 {
2194 unsigned char buffer[MAXMSGLEN];
2195 short msgLen;
2196
2197 if (m_fileOpen)
2198 {
2200 }
2201
2202 if (!m_portOpen)
2203 {
2205 }
2206
2207 msgLen = LEN_MSGHEADER;
2208 buffer[IND_PREAMBLE] = PREAMBLE;
2209 buffer[IND_BID] = bid;
2210 buffer[IND_MID] = mid;
2211
2212 if (param != 0xFF)
2213 {
2214 msgLen++;
2215 buffer[IND_LEN] = valuelen + 1;
2216 buffer[IND_DATA0] = param;
2217 }
2218 else
2219 {
2220 buffer[IND_LEN] = (unsigned char)valuelen;
2221 }
2222
2223 swapEndian((unsigned char*)&value, &buffer[msgLen], valuelen);
2224 calcChecksum(buffer, LEN_MSGHEADER + buffer[IND_LEN]);
2225
2226 // Send message
2227 writeData(buffer, LEN_MSGHEADERCS + buffer[IND_LEN]);
2228
2229 // Read next received message
2230 if (readMessageRaw(buffer, &msgLen) == MTRV_OK)
2231 {
2232 // Message received
2233 if (buffer[IND_MID] == (mid + 1))
2234 {
2235 return (m_retVal = MTRV_OK); // Acknowledge received
2236 }
2237 else if (buffer[IND_MID] == MID_ERROR)
2238 {
2239 m_deviceError = buffer[IND_DATA0];
2240 return (m_retVal = MTRV_RECVERRORMSG); // Error message received
2241 }
2242 }
2243
2244 return m_retVal;
2245 }
2246
2247 ////////////////////////////////////////////////////////////////////
2248 // setSetting (float & no param variant)
2249 //
2250 // Sets a float setting of the device. Only valid
2251 // for serial port connections.
2252 //
2253 // Input
2254 // mid : Message ID of message to send
2255 // bid : Bus ID of message to send (def 0xFF)
2256 // value : Contains the float value to be used
2257 //
2258 // Output
2259 // = MTRV_OK if an Ack message is received
2260 // = MTRV_RECVERRORMSG if an error message is received
2261 // = MTRV_TIMEOUT if timeout occurred
2262 //
2263 short
2264 CXsensMTiModule::setSetting(const unsigned char mid, const float value, const unsigned char bid)
2265 {
2266 unsigned char buffer[MAXMSGLEN];
2267 short msgLen;
2268
2269 if (m_fileOpen)
2270 {
2272 }
2273
2274 if (!m_portOpen)
2275 {
2277 }
2278
2279 msgLen = LEN_MSGHEADER;
2280 buffer[IND_PREAMBLE] = PREAMBLE;
2281 buffer[IND_BID] = bid;
2282 buffer[IND_MID] = mid;
2283 buffer[IND_LEN] = LEN_FLOAT;
2284 swapEndian((unsigned char*)&value, &buffer[msgLen], LEN_FLOAT);
2286
2287 // Send message
2289
2290 // Read next received message
2291 if (readMessageRaw(buffer, &msgLen) == MTRV_OK)
2292 {
2293 // Message received
2294 if (buffer[IND_MID] == (mid + 1))
2295 {
2296 return (m_retVal = MTRV_OK); // Acknowledge received
2297 }
2298 else if (buffer[IND_MID] == MID_ERROR)
2299 {
2300 m_deviceError = buffer[IND_DATA0];
2301 return (m_retVal = MTRV_RECVERRORMSG); // Error message received
2302 }
2303 }
2304
2305 return m_retVal;
2306 }
2307
2308 ////////////////////////////////////////////////////////////////////
2309 // setSetting (float & param variant)
2310 //
2311 // Sets a float setting of the device. Only valid
2312 // for serial port connections.
2313 //
2314 // Input
2315 // mid : Message ID of message to send
2316 // param : For messages that need a parameter (optional)
2317 // bid : Bus ID of message to send (def 0xFF)
2318 // value : Contains the float value to be used
2319 //
2320 // Output
2321 // = MTRV_OK if an Ack message is received
2322 // = MTRV_RECVERRORMSG if an error message is received
2323 // = MTRV_TIMEOUT if timeout occurred
2324 //
2325 //
2326 short
2327 CXsensMTiModule::setSetting(const unsigned char mid,
2328 const unsigned char param,
2329 const float value,
2330 const unsigned char bid)
2331 {
2332 unsigned char buffer[MAXMSGLEN];
2333 short msgLen;
2334
2335 if (m_fileOpen)
2336 {
2338 }
2339
2340 if (!m_portOpen)
2341 {
2343 }
2344
2345 msgLen = LEN_MSGHEADER;
2346 buffer[IND_PREAMBLE] = PREAMBLE;
2347 buffer[IND_BID] = bid;
2348 buffer[IND_MID] = mid;
2349
2350 if (param != 0xFF)
2351 {
2352 msgLen++;
2353 buffer[IND_LEN] = LEN_FLOAT + 1;
2354 buffer[IND_DATA0] = param;
2355 }
2356 else
2357 {
2358 buffer[IND_LEN] = LEN_FLOAT;
2359 }
2360
2361 swapEndian((unsigned char*)&value, &buffer[msgLen], LEN_FLOAT);
2362 calcChecksum(buffer, LEN_MSGHEADER + buffer[IND_LEN]);
2363
2364 // Send message
2365 writeData(buffer, LEN_MSGHEADERCS + buffer[IND_LEN]);
2366
2367 // Read next received message
2368 if (readMessageRaw(buffer, &msgLen) == MTRV_OK)
2369 {
2370 // Message received
2371 if (buffer[IND_MID] == (mid + 1))
2372 {
2373 return (m_retVal = MTRV_OK); // Acknowledge received
2374 }
2375 else if (buffer[IND_MID] == MID_ERROR)
2376 {
2377 m_deviceError = buffer[IND_DATA0];
2378 return (m_retVal = MTRV_RECVERRORMSG); // Error message received
2379 }
2380 }
2381
2382 return m_retVal;
2383 }
2384
2385 ////////////////////////////////////////////////////////////////////
2386 // setSetting (float & param & store variant)
2387 //
2388 // Sets a float setting of the device and with the Store field.
2389 // Only valid for serial port connections
2390 //
2391 // Input
2392 // mid : Message ID of message to send
2393 // param : For messages that need a parameter (optional)
2394 // value : Contains the float value to be used
2395 // store ; Store in non-volatile memory (1) or not (0)
2396 // bid : Bus ID of message to send (def 0xFF)
2397 //
2398 // Output
2399 // = MTRV_OK if an Ack message is received
2400 // = MTRV_RECVERRORMSG if an error message is received
2401 // = MTRV_TIMEOUT if timeout occurred
2402 //
2403 //
2404 short
2405 CXsensMTiModule::setSetting(const unsigned char mid,
2406 const unsigned char param,
2407 const float value,
2408 const bool store,
2409 const unsigned char bid)
2410 {
2411 unsigned char buffer[MAXMSGLEN];
2412 short msgLen;
2413
2414 if (m_fileOpen)
2415 {
2417 }
2418
2419 if (!m_portOpen)
2420 {
2422 }
2423
2424 msgLen = LEN_MSGHEADER;
2425 buffer[IND_PREAMBLE] = PREAMBLE;
2426 buffer[IND_BID] = bid;
2427 buffer[IND_MID] = mid;
2428
2429 if (param != 0xFF)
2430 {
2431 msgLen++;
2432 buffer[IND_LEN] = LEN_FLOAT + 2;
2433 buffer[IND_DATA0] = param;
2434 }
2435 else
2436 {
2437 buffer[IND_LEN] = LEN_FLOAT + 1;
2438 }
2439
2440 swapEndian((unsigned char*)&value, &buffer[msgLen], LEN_FLOAT);
2441 buffer[msgLen + LEN_FLOAT] = store;
2442 calcChecksum(buffer, LEN_MSGHEADER + buffer[IND_LEN]);
2443
2444 // Send message
2445 writeData(buffer, LEN_MSGHEADERCS + buffer[IND_LEN]);
2446
2447 // Read next received message
2448 if (readMessageRaw(buffer, &msgLen) == MTRV_OK)
2449 {
2450 // Message received
2451 if (buffer[IND_MID] == (mid + 1))
2452 {
2453 return (m_retVal = MTRV_OK); // Acknowledge received
2454 }
2455 else if (buffer[IND_MID] == MID_ERROR)
2456 {
2457 m_deviceError = buffer[IND_DATA0];
2458 return (m_retVal = MTRV_RECVERRORMSG); // Error message received
2459 }
2460 }
2461
2462 return m_retVal;
2463 }
2464
2465 ////////////////////////////////////////////////////////////////////
2466 // getDeviceMode
2467 //
2468 // Requests the current output mode/setting of input (file or serialport)
2469 // the Outputmode, Outputsettings, DataLength & number of devices
2470 // are stored in member variables of the MTComm class. These values
2471 // are needed for the GetValue functions.
2472 // The function optionally returns the number of devices
2473 //
2474 // File: expects the Configuration message at the start of the file
2475 // which holds the OutputMode & OutputSettings. File position
2476 // is after the first message
2477 //
2478 // Input
2479 // Output
2480 // numDevices : [optional] number of devices connected to port or
2481 // found in configuration file
2482 //
2483 // returns MTRV_OK if the mode & settings are read
2484 //
2485 short
2486 CXsensMTiModule::getDeviceMode(unsigned short* numDevices)
2487 {
2488 unsigned char mid = 0, data[MAXMSGLEN];
2489 short datalen;
2490
2491 if (numDevices != nullptr)
2492 {
2493 *numDevices = 0;
2494 }
2495
2496 // In case serial port is used (live device / XM or MT)
2497 if (m_portOpen)
2498 {
2499 if (reqSetting(MID_INITBUS, data, datalen) != MTRV_OK)
2500 {
2501 return m_retVal;
2502 }
2503
2504 // Retrieve outputmode + outputsettings
2505 for (int i = 0; i < datalen / LEN_DEVICEID; i++)
2506 {
2508 MTRV_OK)
2509 {
2510 return m_retVal;
2511 }
2512
2515 BID_MT + i) != MTRV_OK)
2516 {
2517 return m_retVal;
2518 }
2519
2521 MTRV_OK)
2522 {
2523 return m_retVal;
2524 }
2525 }
2526
2527 if (numDevices != nullptr)
2528 {
2529 *numDevices = datalen / LEN_DEVICEID;
2530 }
2531
2532 unsigned char masterDID[4];
2533 short DIDlen;
2534
2535 if (reqSetting(MID_REQDID, masterDID, DIDlen) != MTRV_OK)
2536 {
2537 return m_retVal;
2538 }
2539
2540 if (memcmp(masterDID, data, LEN_DEVICEID) != 0)
2541 {
2542 // Using an XbusMaster
2546 }
2547 else
2548 {
2552 }
2553
2554 return (m_retVal = MTRV_OK);
2555 }
2556 else if (m_fileOpen)
2557 {
2558 // Configuration message should be the first message in the file
2559 setFilePos(0);
2560
2561 if (readMessage(mid, data, datalen) == MTRV_OK)
2562 {
2563 if (mid == MID_CONFIGURATION)
2564 {
2565 unsigned short _numDevices = 0;
2566 swapEndian(
2567 data + CONF_NUMDEVICES, (unsigned char*)&_numDevices, CONF_NUMDEVICESLEN);
2568
2569 for (unsigned int i = 0; i < _numDevices; i++)
2570 {
2571 m_storedOutputMode[BID_MT + i] = 0;
2573 (unsigned char*)(m_storedOutputMode + BID_MT + i),
2577 (unsigned char*)(m_storedOutputSettings + BID_MT + i),
2579 m_storedDataLength[BID_MT + i] = 0;
2581 (unsigned char*)(m_storedDataLength + BID_MT + i),
2583 }
2584
2585 if (numDevices != nullptr)
2586 {
2587 *numDevices = _numDevices;
2588 }
2589
2590 if (memcmp(data + CONF_MASTERDID, data + CONF_DID, LEN_DEVICEID) != 0)
2591 {
2592 // Using an XbusMaster
2596 }
2597 else
2598 {
2602 }
2603
2604 return (m_retVal = MTRV_OK);
2605 }
2606 }
2607
2608 return (m_retVal = MTRV_NOTSUCCESSFUL);
2609 }
2610
2612 }
2613
2614 ////////////////////////////////////////////////////////////////////
2615 // setDeviceMode
2616 //
2617 // Sets the current output mode/setting of input (not for file-based
2618 // inputs)
2619 //
2620 // Input
2621 // OutputMode : OutputMode to be set in device & stored in MTComm
2622 // class member variable
2623 // OutputSettings : OutputSettings to be set in device & stored in
2624 // MTComm class member variable
2625 // Output
2626 //
2627 // returns MTRV_OK if the mode & settings are read
2628 //
2629 short
2630 CXsensMTiModule::setDeviceMode(unsigned long OutputMode,
2631 unsigned long OutputSettings,
2632 const unsigned char bid)
2633 {
2634 // In case serial port is used (live XM / MT)
2635 if (m_portOpen)
2636 {
2637 // Set OutputMode
2638 if (setSetting(MID_SETOUTPUTMODE, OutputMode, LEN_OUTPUTMODE, bid) != MTRV_OK)
2639 {
2640 return m_retVal;
2641 }
2642
2643 if (bid == BID_MASTER || (bid == BID_MT && m_storedOutputMode[0] != OUTPUTMODE_XM))
2644 {
2645 m_storedOutputMode[0] = m_storedOutputMode[BID_MT] = OutputMode;
2646 }
2647 else
2648 {
2649 m_storedOutputMode[bid] = OutputMode;
2650 }
2651
2652 // Set OutputSettings
2653 if (setSetting(MID_SETOUTPUTSETTINGS, OutputSettings, LEN_OUTPUTSETTINGS, bid) !=
2654 MTRV_OK)
2655 {
2656 return m_retVal;
2657 }
2658
2659 if (bid == BID_MASTER || (bid == BID_MT && m_storedOutputMode[0] != OUTPUTMODE_XM))
2660 {
2662 }
2663 else
2664 {
2665 m_storedOutputSettings[bid] = OutputSettings;
2666 }
2667
2668 // Get DataLength from device
2669 if (OutputMode != OUTPUTMODE_XM)
2670 {
2671 unsigned long value;
2672
2673 if (reqSetting(MID_REQDATALENGTH, value, bid) == MTRV_OK)
2674 {
2675 if ((bid == BID_MASTER) ||
2676 ((bid == BID_MT) && (m_storedOutputMode[0] != OUTPUTMODE_XM)))
2677 {
2679 }
2680 else
2681 {
2682 m_storedDataLength[bid] = value;
2683 }
2684 }
2685 }
2686 else
2687 {
2689 }
2690
2691 return (m_retVal = MTRV_OK);
2692 }
2693
2695 }
2696
2697 ////////////////////////////////////////////////////////////////////
2698 // getMode
2699 //
2700 // Gets the output mode/setting used in MTComm class and the corresponding
2701 // datalength. These variables are set by the functions GetDeviceMode,
2702 // SetDeviceMode or SetMode
2703 //
2704 // Input
2705 // Output
2706 // OutputMode : OutputMode stored in MTComm class member variable
2707 // OutputSettings : OutputSettings stored in MTComm class member variable
2708 //
2709 // returns always MTRV_OK
2710 //
2711 short
2712 CXsensMTiModule::getMode(unsigned long& OutputMode,
2713 unsigned long& OutputSettings,
2714 unsigned short& dataLength,
2715 const unsigned char bid)
2716 {
2717 unsigned char nbid = (bid == BID_MASTER) ? 0 : bid;
2718 OutputMode = m_storedOutputMode[nbid];
2719 OutputSettings = m_storedOutputSettings[nbid];
2720 dataLength = (unsigned short)m_storedDataLength[nbid];
2721 return (m_retVal = MTRV_OK);
2722 }
2723
2724 ////////////////////////////////////////////////////////////////////
2725 // setMode
2726 //
2727 // Sets the output mode/setting used in MTComm class. Use the function
2728 // GetDeviceMode to retrieve the current values of file/device.
2729 // This function will also calculate the data length field
2730 //
2731 // Input
2732 // OutputMode : OutputMode to be stored in MTComm class member variable
2733 // OutputSettings : OutputSettings to be stored in MTComm class member variable
2734 // Output
2735 //
2736 // returns always MTRV_OK
2737 //
2738 short
2739 CXsensMTiModule::setMode(unsigned long OutputMode,
2740 unsigned long OutputSettings,
2741 const unsigned char bid)
2742 {
2743 unsigned char nbid = bid;
2744
2745 if (nbid == BID_MASTER)
2746 {
2747 nbid = 0;
2748 }
2749
2750 m_storedOutputMode[nbid] = OutputMode;
2751 m_storedOutputSettings[nbid] = OutputSettings;
2752
2753 if (OutputMode == INVALIDSETTINGVALUE || OutputSettings == INVALIDSETTINGVALUE)
2754 {
2755 m_storedDataLength[nbid] = 0;
2756 }
2757 else
2758 {
2759 unsigned short dataLength = 0;
2760
2761 if (OutputMode & OUTPUTMODE_MT9)
2762 {
2763 dataLength = ((OutputSettings & OUTPUTSETTINGS_TIMESTAMP_MASK) ==
2766 : 0 + LEN_RAWDATA;
2767 }
2768 else if (OutputMode == OUTPUTMODE_XM)
2769 {
2770 // XbusMaster concatenates sample counter
2771 dataLength = LEN_SAMPLECNT;
2772 }
2773 else
2774 {
2775 if (OutputMode & OUTPUTMODE_RAW)
2776 {
2777 dataLength = LEN_RAWDATA;
2778 }
2779 else
2780 {
2781 if (OutputMode & OUTPUTMODE_CALIB)
2782 {
2783 dataLength = LEN_CALIBDATA;
2784 }
2785
2786 if (OutputMode & OUTPUTMODE_ORIENT)
2787 {
2788 switch (OutputSettings & OUTPUTSETTINGS_ORIENTMODE_MASK)
2789 {
2791 dataLength += LEN_ORIENT_QUATDATA;
2792 break;
2793
2795 dataLength += LEN_ORIENT_EULERDATA;
2796 break;
2797
2799 dataLength += LEN_ORIENT_MATRIXDATA;
2800 break;
2801
2802 default:
2803 break;
2804 }
2805 }
2806 }
2807
2808 switch (OutputSettings & OUTPUTSETTINGS_TIMESTAMP_MASK)
2809 {
2811 dataLength += LEN_SAMPLECNT;
2812 break;
2813
2814 default:
2815 break;
2816 }
2817 }
2818
2819 m_storedDataLength[nbid] = dataLength;
2820 }
2821
2822 // If not XbusMaster store also in BID_MT
2823 if (bid == BID_MASTER && OutputMode != OUTPUTMODE_XM)
2824 {
2828 }
2829
2830 return (m_retVal = MTRV_OK);
2831 }
2832
2833 ////////////////////////////////////////////////////////////////////
2834 // getValue (unsigned short variant)
2835 //
2836 // Retrieves a unsigned short value from the data input parameter
2837 // This function is valid for the following value specifiers:
2838 // VALUE_RAW_TEMP
2839 // VALUE_SAMPLECNT
2840 //
2841 // Use getDeviceMode or setMode to initialize the Outputmode
2842 // and Outputsettings member variables used to retrieve the correct
2843 // value
2844 //
2845 // Input
2846 // valueSpec : Specifier of the value to be retrieved
2847 // data[] : Data field of a MTData / BusData message
2848 // bid : bus identifier of the device of which the
2849 // value should be returned (default = BID_MT)
2850 // Output
2851 // value : reference to unsigned short in which the retrieved
2852 // value will be returned
2853 //
2854 // Return value
2855 // MTRV_OK : value is successfully retrieved
2856 // != MTRV_OK : not successful
2857 //
2858 short
2859 CXsensMTiModule::getValue(const unsigned long valueSpec,
2860 unsigned short& value,
2861 const unsigned char data[],
2862 const unsigned char bid)
2863 {
2864 short offset = 0;
2865 unsigned char nbid = bid;
2866
2867 if (nbid == BID_MASTER)
2868 {
2869 nbid = 0;
2870 }
2871
2872 // Check for invalid mode/settings
2875 {
2877 }
2878
2879 // Calculate offset for XM input
2881 {
2882 int i = 0;
2883
2884 while (i < nbid)
2885 {
2886 offset += (short)m_storedDataLength[i++];
2887 }
2888 }
2889
2890 // Check if data is unsigned short & available in data
2892
2893 if (valueSpec == VALUE_RAW_TEMP)
2894 {
2896 {
2897 offset += (m_storedOutputMode[nbid] == OUTPUTMODE_MT9 &&
2900 : 0;
2901 swapEndian(data + offset + valueSpec * LEN_UNSIGSHORT * 3,
2902 (unsigned char*)&value,
2903 LEN_RAW_TEMP);
2904 m_retVal = MTRV_OK;
2905 }
2906 }
2907 else if (valueSpec == VALUE_SAMPLECNT)
2908 {
2911 {
2912 if (!(m_storedOutputMode[nbid] == OUTPUTMODE_MT9))
2913 {
2914 offset += (short)m_storedDataLength[nbid] - LEN_SAMPLECNT;
2915 }
2916
2917 swapEndian(data + offset, (unsigned char*)&value, LEN_SAMPLECNT);
2918 m_retVal = MTRV_OK;
2919 }
2920 }
2921
2922 return m_retVal;
2923 }
2924
2925 ////////////////////////////////////////////////////////////////////
2926 // getValue (array of unsigned short variant)
2927 //
2928 // Retrieves an array of unsigned short values from the data input
2929 // parameter. This function is valid for the following value specifiers:
2930 // VALUE_RAW_ACC
2931 // VALUE_RAW_GYR
2932 // VALUE_RAW_MAG
2933 //
2934 // Use getDeviceMode or setMode to initialize the Outputmode
2935 // and Outputsettings member variables used to retrieve the correct
2936 // value
2937 //
2938 // Input
2939 // valueSpec : Specifier of the value to be retrieved
2940 // data[] : Data field of a MTData / BusData message
2941 // bid : bus identifier of the device of which the
2942 // value should be returned (default = BID_MT)
2943 // Output
2944 // value[] : pointer to array of unsigned shorts in which the
2945 // retrieved values will be returned
2946 //
2947 // Return value
2948 // MTRV_OK : value is successfully retrieved
2949 // != MTRV_OK : not successful
2950 //
2951 short
2952 CXsensMTiModule::getValue(const unsigned long valueSpec,
2953 unsigned short value[],
2954 const unsigned char data[],
2955 const unsigned char bid)
2956 {
2957 short offset = 0;
2958 unsigned char nbid = bid;
2959
2960 if (nbid == BID_MASTER)
2961 {
2962 nbid = 0;
2963 }
2964
2965 // Check for invalid mode/settings
2968 {
2970 }
2971
2972 // Calculate offset for XM input
2974 {
2975 int i = 0;
2976
2977 while (i < nbid)
2978 {
2979 offset += (short)m_storedDataLength[i++];
2980 }
2981 }
2982
2983 // Check if data is unsigned short, available in data & retrieve data
2985
2986 //if (valueSpec >= VALUE_RAW_ACC && valueSpec <= VALUE_RAW_MAG)
2987 if (valueSpec <= VALUE_RAW_MAG)
2988 {
2990 {
2991 offset += (short)(valueSpec * LEN_UNSIGSHORT * 3);
2992 offset += (m_storedOutputMode[nbid] == OUTPUTMODE_MT9 &&
2995 : 0;
2996
2997 for (int i = 0; i < 3; i++)
2998 {
2999 swapEndian(data + offset + i * LEN_UNSIGSHORT,
3000 (unsigned char*)value + i * LEN_UNSIGSHORT,
3002 }
3003
3004 m_retVal = MTRV_OK;
3005 }
3006 }
3007
3008 return m_retVal;
3009 }
3010
3011 ////////////////////////////////////////////////////////////////////
3012 // getValue (array of floats variant)
3013 //
3014 // Retrieves an array of float values from the data input parameter.
3015 // This function is valid for the following value specifiers:
3016 // VALUE_TEMP
3017 // VALUE_CALIB_ACC
3018 // VALUE_CALIB_GYR
3019 // VALUE_CALIB_MAG
3020 // VALUE_ORIENT_QUAT
3021 // VALUE_ORIENT_EULER
3022 // VALUE_ORIENT_MATRIX
3023 //
3024 // Use getDeviceMode or setMode to initialize the Outputmode
3025 // and Outputsettings member variables used to retrieve the correct
3026 // value
3027 //
3028 // Input
3029 // valueSpec : Specifier of the value to be retrieved
3030 // data[] : Data field of a MTData / BusData message
3031 // bid : bus identifier of the device of which the
3032 // value should be returned (default = BID_MT)
3033 // Output
3034 // value[] : pointer to array of floats in which the
3035 // retrieved values will be returned
3036 //
3037 // Return value
3038 // MTRV_OK : value is successfully retrieved
3039 // != MTRV_OK : not successful
3040 //
3041 short
3042 CXsensMTiModule::getValue(const unsigned long valueSpec,
3043 float value[],
3044 const unsigned char data[],
3045 const unsigned char bid)
3046 {
3047 short offset = 0;
3048 int nElements = 0;
3049 unsigned char nbid = bid;
3050
3051 if (nbid == BID_MASTER)
3052 {
3053 nbid = 0;
3054 }
3055
3056 // Check for invalid mode/settings
3059 {
3061 }
3062
3063 // Calculate offset for XM input
3065 {
3066 int i = 0;
3067
3068 while (i < nbid)
3069 {
3070 offset += (short)m_storedDataLength[i++];
3071 }
3072 }
3073
3074 // Check if data is float & available in data
3076
3077 if (valueSpec == VALUE_TEMP)
3078 {
3080 {
3081 nElements = LEN_TEMPDATA / LEN_FLOAT;
3082 m_retVal = MTRV_OK;
3083 }
3084 }
3085 else if (valueSpec == VALUE_CALIB_ACC)
3086 {
3087 offset += ((m_storedOutputMode[nbid] & OUTPUTMODE_TEMP) != 0) ? LEN_TEMPDATA : 0;
3088
3089 if ((m_storedOutputMode[nbid] & OUTPUTMODE_CALIB) &&
3091 {
3092 nElements = LEN_CALIB_ACCDATA / LEN_FLOAT;
3093 m_retVal = MTRV_OK;
3094 }
3095 }
3096 else if (valueSpec == VALUE_CALIB_GYR)
3097 {
3098 offset += ((m_storedOutputMode[nbid] & OUTPUTMODE_TEMP) != 0) ? LEN_TEMPDATA : 0;
3099
3100 if ((m_storedOutputMode[nbid] & OUTPUTMODE_CALIB) &&
3102 {
3104 ? LEN_CALIB_ACCX * 3
3105 : 0;
3106 nElements = LEN_CALIB_GYRDATA / LEN_FLOAT;
3107 m_retVal = MTRV_OK;
3108 }
3109 }
3110 else if (valueSpec == VALUE_CALIB_MAG)
3111 {
3112 offset += ((m_storedOutputMode[nbid] & OUTPUTMODE_TEMP) != 0) ? LEN_TEMPDATA : 0;
3113
3114 if ((m_storedOutputMode[nbid] & OUTPUTMODE_CALIB) &&
3116 {
3118 ? LEN_CALIB_ACCX * 3
3119 : 0;
3121 ? LEN_CALIB_GYRX * 3
3122 : 0;
3123 nElements = LEN_CALIB_MAGDATA / LEN_FLOAT;
3124 m_retVal = MTRV_OK;
3125 }
3126 }
3127 else if (valueSpec >= VALUE_ORIENT_QUAT && valueSpec <= VALUE_ORIENT_MATRIX)
3128 {
3129 offset += ((m_storedOutputMode[nbid] & OUTPUTMODE_TEMP) != 0) ? LEN_TEMPDATA : 0;
3130
3132 {
3134 ? LEN_CALIB_ACCX * 3
3135 : 0;
3137 ? LEN_CALIB_GYRX * 3
3138 : 0;
3140 ? LEN_CALIB_MAGX * 3
3141 : 0;
3142 }
3143
3145 {
3146 unsigned long orientmode =
3148
3149 switch (valueSpec)
3150 {
3151 case VALUE_ORIENT_QUAT:
3152 if (orientmode == OUTPUTSETTINGS_ORIENTMODE_QUATERNION)
3153 {
3154 nElements = LEN_ORIENT_QUATDATA / LEN_FLOAT;
3155 m_retVal = MTRV_OK;
3156 }
3157
3158 break;
3159
3160 case VALUE_ORIENT_EULER:
3161 if (orientmode == OUTPUTSETTINGS_ORIENTMODE_EULER)
3162 {
3163 nElements = LEN_ORIENT_EULERDATA / LEN_FLOAT;
3164 m_retVal = MTRV_OK;
3165 }
3166
3167 break;
3168
3170 if (orientmode == OUTPUTSETTINGS_ORIENTMODE_MATRIX)
3171 {
3172 nElements = LEN_ORIENT_MATRIXDATA / LEN_FLOAT;
3173 m_retVal = MTRV_OK;
3174 }
3175
3176 break;
3177
3178 default:
3179 break;
3180 }
3181 }
3182 }
3183
3184 if (m_retVal == MTRV_OK)
3185 {
3187 {
3188 for (int i = 0; i < nElements; i++)
3189 {
3190 swapEndian(data + offset + i * LEN_FLOAT,
3191 (unsigned char*)value + i * LEN_FLOAT,
3192 LEN_FLOAT);
3193 }
3194 }
3195 else
3196 {
3197 int temp;
3198
3199 for (int i = 0; i < nElements; i++)
3200 {
3201 swapEndian(data + offset + i * LEN_FLOAT, (unsigned char*)&temp, 4);
3202 value[i] = (float)temp / 1048576;
3203 }
3204 }
3205 }
3206
3207 return m_retVal;
3208 }
3209
3210 //////////////////////////////////////////////////////////////////////
3211 // getLastDeviceError
3212 //
3213 // Returns the last reported device error of the latest received Error
3214 // message
3215 //
3216 // Output
3217 // Error code
3218 short
3223
3224 //////////////////////////////////////////////////////////////////////
3225 // getLastRetVal
3226 //
3227 // Returns the returned value of the last called function
3228 //
3229 // Output
3230 // Return value
3231 short
3233 {
3234 return m_retVal;
3235 }
3236
3237 //////////////////////////////////////////////////////////////////////
3238 // setTimeOut
3239 //
3240 // Sets the time out value in milliseconds used by the functions
3241 // Use 0 for infinite timeout
3242 //
3243 // Output
3244 // MTRV_OK is set, MTRV_INVALIDTIMEOUT if time value < 0
3245 short
3247 {
3248 if (timeOutMs >= 0)
3249 {
3250 m_timeOut = timeOutMs;
3251 return (m_retVal = MTRV_OK);
3252 }
3253 else
3254 {
3255 return (m_retVal = MTRV_INVALIDTIMEOUT);
3256 }
3257 }
3258
3259 //////////////////////////////////////////////////////////////////////
3260 // swapEndian
3261 //
3262 // Convert 2 or 4 bytes data from little to big endian or back
3263 //
3264 // Input
3265 // input : Pointer to data to be converted
3266 // output : Pointer where converted data is stored
3267 // length : Length of setting (0,2 & 4)
3268 //
3269 // Remarks:
3270 // Allocate enough bytes for output buffer
3271
3272 void
3273 CXsensMTiModule::swapEndian(const unsigned char input[],
3274 unsigned char output[],
3275 const int length)
3276 {
3277 switch (length)
3278 {
3279 case 4:
3280 output[0] = input[3];
3281 output[1] = input[2];
3282 output[2] = input[1];
3283 output[3] = input[0];
3284 break;
3285
3286 case 2:
3287 output[0] = input[1];
3288 output[1] = input[0];
3289 break;
3290
3291 case 1:
3292 output[0] = input[0];
3293 break;
3294
3295 default:
3296 for (int i = 0, j = length - 1; i < length; i++, j--)
3297 {
3298 output[j] = input[i];
3299 }
3300
3301 break;
3302 }
3303 }
3304
3305 //////////////////////////////////////////////////////////////////////
3306 // calcChecksum
3307 //
3308 // Calculate and append checksum to msgBuffer
3309 //
3310 void
3311 CXsensMTiModule::calcChecksum(unsigned char* msgBuffer, const int msgBufferLength)
3312 {
3313 unsigned char checkSum = 0;
3314 int i;
3315
3316 for (i = 1; i < msgBufferLength; i++)
3317 {
3318 checkSum += msgBuffer[i];
3319 }
3320
3321 msgBuffer[msgBufferLength] = -checkSum; // Store chksum
3322 }
3323
3324 //////////////////////////////////////////////////////////////////////
3325 // checkChecksum
3326 //
3327 // Checks if message checksum is valid
3328 //
3329 // Output
3330 // returns true checksum is OK
3331 bool
3332 CXsensMTiModule::checkChecksum(const unsigned char* msgBuffer, const int msgBufferLength)
3333 {
3334 unsigned char checkSum = 0;
3335 int i;
3336
3337 for (i = 1; i < msgBufferLength; i++)
3338 {
3339 checkSum += msgBuffer[i];
3340 }
3341
3342 if (checkSum == 0)
3343 {
3344 return true;
3345 }
3346 else
3347 {
3348 return false;
3349 }
3350 }
3351} // namespace IMU::Xsens
3352
3353#endif
#define float
Definition 16_Level.h:22
uint8_t data[1]
#define ECHO
Definition Scanner.cpp:587
#define VALUE_RAW_TEMP
#define MTRV_INVALIDVALUESPEC
#define VALUE_RAW_MAG
#define LEN_ORIENT_MATRIXDATA
#define TO_DEFAULT
#define MID_REQOUTPUTMODE
#define MTRV_ENDOFFILE
#define IND_LEN
#define EXTLENCODE
#define BID_MASTER
#define VALUE_ORIENT_QUAT
#define CONF_NUMDEVICESLEN
#define CONF_NUMDEVICES
#define MID_REQDID
#define MTRV_TIMEOUTNODATA
#define OUTPUTSETTINGS_CALIBMODE_MAG_MASK
#define MID_SETOUTPUTSETTINGS
#define CONF_MASTERDID
#define INVALID_SET_FILE_POINTER
#define OUTPUTSETTINGS_CALIBMODE_ACC_MASK
#define CONF_DATALENGTHLEN
#define MTRV_OK
#define MID_REQDATALENGTH
#define MID_REQOUTPUTSETTINGS
#define LEN_CALIB_GYRDATA
#define OUTPUTSETTINGS_ORIENTMODE_QUATERNION
#define CONF_OUTPUTMODELEN
#define CONF_OUTPUTMODE
#define IND_LENEXTL
#define MTRV_NOINPUTINITIALIZED
#define MTRV_INVALIDFORFILEINPUT
#define LEN_RAW_TEMP
#define IND_BID
#define OUTPUTMODE_CALIB
#define INVALIDSETTINGVALUE
#define LEN_MSGHEADER
#define MID_CONFIGURATION
#define LEN_MSGEXTHEADER
#define MTRV_INVALIDTIMEOUT
#define MID_SETOUTPUTMODE
#define MID_INITBUS
#define MAXMSGLEN
#define OUTPUTMODE_ORIENT
#define OUTPUTSETTINGS_ORIENTMODE_EULER
#define VALUE_CALIB_GYR
#define LEN_SAMPLECNT
#define MTRV_INPUTCANNOTBEOPENED
#define VALUE_CALIB_ACC
#define OUTPUTSETTINGS_ORIENTMODE_MASK
#define LEN_MSGEXTHEADERCS
#define MAXDEVICES
#define OUTPUTMODE_RAW
#define LEN_CALIB_MAGX
#define OUTPUTSETTINGS_CALIBMODE_GYR_MASK
#define OUTPUTSETTINGS_ORIENTMODE_MATRIX
#define LEN_RAWDATA
#define PREAMBLE
#define IND_MID
#define LEN_TEMPDATA
#define OUTPUTSETTINGS_TIMESTAMP_MASK
#define MTRV_ANINPUTALREADYOPEN
#define CONF_DID
#define VALUE_ORIENT_EULER
#define LEN_ORIENT_EULERDATA
#define IND_PREAMBLE
#define LEN_FLOAT
#define CONF_DATALENGTH
#define LEN_CHECKSUM
#define IND_DATAEXT0
#define OUTPUTSETTINGS_TIMESTAMP_SAMPLECNT
#define MTRV_UNEXPECTEDMSG
#define VALUE_ORIENT_MATRIX
#define LEN_MSGHEADERCS
#define IND_DATA0
#define LEN_ORIENT_QUATDATA
#define LEN_CALIB_ACCDATA
#define MTRV_NOTSUCCESSFUL
#define LEN_CALIB_MAGDATA
#define CONF_OUTPUTSETTINGSLEN
#define MTRV_RECVERRORMSG
#define LEN_OUTPUTSETTINGS
#define VALUE_CALIB_MAG
#define OUTPUTSETTINGS_XM
#define LEN_OUTPUTMODE
#define LEN_CALIB_ACCX
#define OUTPUTMODE_TEMP
#define MTRV_TIMEOUT
#define VALUE_TEMP
#define OUTPUTMODE_XM
#define MTRV_NOVALIDMODESPECIFIED
#define OUTPUTSETTINGS_DATAFORMAT_F1220
#define MID_ERROR
#define LEN_UNSIGSHORT
#define LEN_CALIB_GYRX
#define CONF_BLOCKLEN
#define CONF_OUTPUTSETTINGS
#define IND_LENEXTH
#define BID_MT
#define MID_MTDATA
#define OUTPUTMODE_MT9
#define LEN_DEVICEID
#define LEN_CALIBDATA
#define VALUE_SAMPLECNT
short readMessage(unsigned char &mid, unsigned char data[], short &dataLen, unsigned char *bid=NULL)
short getValue(const unsigned long valueSpec, unsigned short &value, const unsigned char data[], const unsigned char bid=BID_MT)
short getFileSize(unsigned long &fileSize)
short setSetting(const unsigned char mid, const unsigned long value, const unsigned short valuelen, const unsigned char bid=BID_MASTER)
short readDataMessage(unsigned char data[], short &dataLen)
int writeData(const unsigned char *msgBuffer, const int nBytesToWrite)
short setFilePos(long relPos, unsigned long moveMethod=FILEPOS_BEGIN)
int readData(unsigned char *msgBuffer, const int nBytesToRead)
short writeMessage(const unsigned char mid, const unsigned long dataValue=0, const unsigned char dataValueLen=0, const unsigned char bid=BID_MASTER)
unsigned long m_storedDataLength[MAXDEVICES+1]
void setPortQueueSize(const unsigned long inqueueSize=4096, const unsigned long outqueueSize=1024)
bool checkChecksum(const unsigned char *msgBuffer, const int msgBufferLength)
void calcChecksum(unsigned char *msgBuffer, const int msgBufferLength)
short setTimeOut(short timeOutMs)
void escape(unsigned long function)
unsigned long m_storedOutputSettings[MAXDEVICES+1]
short reqSetting(const unsigned char mid, unsigned long &value, const unsigned char bid=BID_MASTER)
short getMode(unsigned long &OutputMode, unsigned long &OutputSettings, unsigned short &dataLength, const unsigned char bid=BID_MASTER)
short openFile(const char *fileName, bool createAlways=false)
short readMessageRaw(unsigned char *msgBuffer, short *msgBufferLength)
short getDeviceMode(unsigned short *numDevices=NULL)
unsigned long m_storedOutputMode[MAXDEVICES+1]
short setMode(unsigned long OutputMode, unsigned long OutputSettings, const unsigned char bid=BID_MASTER)
short waitForMessage(const unsigned char mid, unsigned char data[]=NULL, short *dataLen=NULL, unsigned char *bid=NULL)
static void swapEndian(const unsigned char input[], unsigned char output[], const int length)
short openPort(const int portNumber, const unsigned long baudrate=PBR_115K2, const unsigned long inqueueSize=4096, const unsigned long outqueueSize=1024)
unsigned char m_tempBuffer[MAXMSGLEN]
short setDeviceMode(unsigned long OutputMode, unsigned long OutputSettings, const unsigned char bid=BID_MASTER)