Basic implementation of Xbus message parsing and generation for embedded processors. The code has no dependencies and should also work for other MCU architectures than ARM provided a C99 compiler is available.

Dependents:   MTi-1_example_LPC1768 MTi-1_rikbeun MTi-1_example MTi-1_example ... more

Important Information

This library is deprecated and no longer maintained. There are new embedded examples available in the MT SDK folder of the MT Software Suite. For more information please visit: https://xsenstechnologies.force.com/knowledgebase/s/article/Introduction-to-the-MT-SDK-programming-examples-for-MTi-devices

For an example of using the Xbus library to communicate with an MTi-1 series device using a full-duplex UART see:

Import programMTi-1_example

Example of using Xbus library to communicate with an MTi-1 series device using a full-duplex UART connection.

Revision:
0:eb25b1785ee4
Child:
1:c24f69a2eff4
diff -r 000000000000 -r eb25b1785ee4 xbusmessage.c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/xbusmessage.c	Tue Jun 16 07:54:23 2015 +0000
@@ -0,0 +1,238 @@
+/*!
+ * \file
+ * \copyright Copyright (C) Xsens Technologies B.V., 2015.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy
+ * of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ */
+
+#include "xbusmessage.h"
+#include "xbusdef.h"
+#include "xbusutility.h"
+
+/*!
+ * \brief Calculate the number of bytes needed for \a message payload.
+ */
+static uint16_t messageLength(struct XbusMessage const* message)
+{
+	switch (message->mid)
+	{
+		case XMID_SetOutputConfig:
+			return message->length * 2 * sizeof(uint16_t);
+
+		default:
+			return message->length;
+	}
+}
+
+/*!
+ * \brief Format a message with a pointer to an array of OutputConfiguration elements.
+ */
+static void formatOutputConfig(uint8_t* raw, struct XbusMessage const* message)
+{
+	struct OutputConfiguration* conf = message->data;
+	for (int i = 0; i < message->length; ++i)
+	{
+		raw = XbusUtility_writeU16(raw, conf->dtype);
+		raw = XbusUtility_writeU16(raw, conf->freq);
+		++conf;
+	}
+}
+
+/*!
+ * \brief Format the payload of a message from a native data type to
+ * raw bytes.
+ */
+static void formatPayload(uint8_t* raw, struct XbusMessage const* message)
+{
+	switch (message->mid)
+	{
+		case XMID_SetOutputConfig:
+			formatOutputConfig(raw, message);
+			break;
+
+		default:
+			for (int i = 0; i < message->length; ++i)
+			{
+				*raw++ = ((uint8_t*)message->data)[i];
+			}
+			break;
+	}
+}
+
+/*!
+ * \brief Format a message into the raw Xbus format ready for transmission to
+ * a motion tracker.
+ */
+size_t XbusMessage_format(uint8_t* raw, struct XbusMessage const* message)
+{
+	uint8_t* dptr = raw;
+	*dptr++ = XBUS_PREAMBLE;
+
+	*dptr = XBUS_MASTERDEVICE;
+	uint8_t checksum = 0;
+	checksum -= *dptr++;
+
+	*dptr = message->mid;
+	checksum -= *dptr++;
+
+	uint16_t length = messageLength(message);
+
+	if (length < XBUS_EXTENDED_LENGTH)
+	{
+		*dptr = length;
+		checksum -= *dptr++;
+	}
+	else
+	{
+		*dptr = XBUS_EXTENDED_LENGTH;
+		checksum -= *dptr++;
+		*dptr = length >> 8;
+		checksum -= *dptr++;
+		*dptr = length & 0xFF;
+		checksum -= *dptr++;
+	}
+
+	formatPayload(dptr, message);
+	for (int i = 0; i < length; ++i)
+	{
+		checksum -= *dptr++;
+	}
+	*dptr++ = checksum;
+
+	return dptr - raw;
+}
+
+/*!
+ * \brief Get a pointer to the data corresponding to \a id.
+ * \param id The data identifier to find in the message.
+ * \param data Pointer to the raw message payload.
+ * \param dataLength The length of the payload in bytes.
+ * \returns Pointer to data item, or NULL if the identifier is not present in
+ * the message.
+ */
+static uint8_t const* getPointerToData(enum XsDataIdentifier id, uint8_t const* data, uint16_t dataLength)
+{
+	uint8_t const* dptr = data;
+	while (dptr < data + dataLength)
+	{
+		uint16_t itemId;
+		uint8_t itemSize;
+		dptr = XbusUtility_readU16(&itemId, dptr);
+		dptr = XbusUtility_readU8(&itemSize, dptr);
+
+		if (id == itemId)
+			return dptr;
+
+		dptr += itemSize;
+	}
+	return NULL;
+}
+
+/*!
+ * \brief Read a number of floats from a message payload.
+ * \param out Pointer to where to output data.
+ * \param raw Pointer to the start of the raw float data.
+ * \param floats The number of floats to read.
+ */
+static void readFloats(float* out, uint8_t const* raw, uint8_t floats)
+{
+	for (int i = 0; i < floats; ++i)
+	{
+		raw = XbusUtility_readU32((uint32_t*)&out[i], raw);
+	}
+}
+
+/*!
+ * \brief Get a data item from an XMID_MtData2 Xbus message.
+ * \param item Pointer to where to store the data.
+ * \param id The data identifier to get.
+ * \param message The message to read the data item from.
+ * \returns true if the data item is found in the message, else false.
+ */
+bool XbusMessage_getDataItem(void* item, enum XsDataIdentifier id, struct XbusMessage const* message)
+{
+	uint8_t const* raw = getPointerToData(id, message->data, message->length);
+	if (raw)
+	{
+		switch (id)
+		{
+			case XDI_PacketCounter:
+				raw = XbusUtility_readU16(item, raw);
+				break;
+
+			case XDI_SampleTimeFine:
+			case XDI_StatusWord:
+				raw = XbusUtility_readU32(item, raw);
+				break;
+
+			case XDI_Quaternion:
+			case XDI_DeltaQ:
+				readFloats(item, raw, 4);
+				break;
+
+			case XDI_DeltaV:
+			case XDI_Acceleration:
+			case XDI_RateOfTurn:
+			case XDI_MagneticField:
+				readFloats(item, raw, 3);
+				break;
+
+			default:
+				return false;
+		}
+		return true;
+	}
+	else
+	{
+		return false;
+	}
+}
+
+/*!
+ * \brief Get a string description for the passed data identifier.
+ */
+char const* XbusMessage_dataDescription(enum XsDataIdentifier id)
+{
+	switch (id)
+	{
+		case XDI_PacketCounter:
+			return "Packet counter";
+
+		case XDI_SampleTimeFine:
+			return "Sample time fine";
+
+		case XDI_Quaternion:
+			return "Quaternion";
+
+		case XDI_DeltaV:
+			return "Velocity increment";
+
+		case XDI_Acceleration:
+			return "Acceleration";
+
+		case XDI_RateOfTurn:
+			return "Rate of turn";
+
+		case XDI_DeltaQ:
+			return "Orientation increment";
+
+		case XDI_MagneticField:
+			return "Magnetic field";
+
+		case XDI_StatusWord:
+			return "Status word";
+
+		default:
+			return "Unknown data type";
+	}
+}