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

Dependencies:   mbed-rtos mbed Xbus

Fork of MTi-1_example by Alex Young

Important Information

This example 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

Overview

The example program demonstrates connecting to an MTi-1 series device, restoring communications settings to default if necessary, and configuring the MTi to send data. For an MTi-1 the device is configured to send inertial sensor data, while MTi-2 and MTi-3 devices are configured to output orientation data using the onboard XKF3i filter.

Communication with the MTi-1 series device is implemented using a either a full-duplex UART, I2C or SPI bus. A reset line is used to reset the MTi during initialization. Data is output to a host PC terminal using a second UART.

For more information on the MTi-1 series communication protocol please refer to the datasheet: https://www.xsens.com/download/pdf/documentation/mti-1/mti-1-series_datasheet.pdf

Supported Platforms

The program has been tested on the following mbed platforms:

Using the Example

  1. To use the example program connect one of the supported mbed boards to the host PC and download the application from the mbed online compiler to the target device.
  2. With the mbed board unpowered (USB disconnected) wire the mbed board to the MTi-1 development board. The following connections are required:
    • In all cases:
      • 5V (or 3V3) main supply to VDD (P300-1)
      • MCU IO voltage (IORef) to VDDIO (P300-2)
      • GND to GND (P300-3)
      • MT_NRESET to nRST (P300-5)
    • For I2C communication:
      • MT_SCL to I2C_SCL (P300-9)
      • MT_SDA to I2C_SDA (P300-11)
      • MT_DRDY to DRDY (P300-15)
      • MT_ADD0 to ADD0 (P300-17)
      • MT_ADD1 to ADD1 (P300-19)
      • MT_ADD2 to ADD2 (P300-21)
    • For SPI communication:
      • MT_DRDY to DRDY (P300-15)
      • MT_SCLK to SPI_SCK (P300-17)
      • MT_MISO to SPI_MISO (P300-19)
      • MT_MOSI to SPI_MOSI (P300-21)
      • MT_nCS to SPI_nCS (P300-23)
    • For UART communication:
      • MT_RX to UART_TX (P300-9)
      • MT_TX to UART_RX (P300-11)

For more information on the MTi-1 development board please refer to the MTi-1 series user manual: https://www.xsens.com/download/pdf/documentation/mti-1/mti-1-series_dk_user_manual.pdf

Information

Check the defines at the top of main.cpp to determine which IO pins are used for the MT_xxx connections on each mbed platform.

Information

The active peripheral (I2C, SPI or UART) is selected on the MTi-1 development board through the PSEL0 and PSEL1 switches. Look on the bottom of the development board for the correct settings.

  1. Connect to the target using a serial terminal. The application is configured for:
    • Baudrate = 921600
    • Stop bits = 1
    • No parity bits
    • No flow control
  2. Reset the mbed board.
  3. You should be presented with a simple user interface as shown below:
MTi-1 series embedded example firmware.
Device ready for operation.
Found device with ID: 03880011.
Device is an MTi-3: Attitude Heading Reference System.
Output configuration set to:
        Packet counter: 65535 Hz
        Sample time fine: 65535 Hz
        Quaternion: 100 Hz
        Status word: 65535 Hz

Press 'm' to start measuring and 'c' to return to config mode.
Committer:
Alex Young
Date:
Wed May 20 13:58:34 2015 +0200
Revision:
25:01356fb59467
Parent:
23:8171449f0dc3
Child:
46:f652d199d27e
Use rtos memory pool for message reception

Who changed what in which revision?

UserRevisionLine numberNew contents of line
Alex Young 3:abc451d82b88 1 /*!
Alex Young 3:abc451d82b88 2 * \file
Alex Young 3:abc451d82b88 3 * \copyright
Alex Young 3:abc451d82b88 4 * Copyright (C) Xsens Technologies B.V., 2015. All rights reserved.
Alex Young 3:abc451d82b88 5 *
Alex Young 3:abc451d82b88 6 * This source code is intended for use only by Xsens Technologies BV and
Alex Young 3:abc451d82b88 7 * those that have explicit written permission to use it from
Alex Young 3:abc451d82b88 8 * Xsens Technologies BV.
Alex Young 3:abc451d82b88 9 *
Alex Young 3:abc451d82b88 10 * THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY
Alex Young 3:abc451d82b88 11 * KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
Alex Young 3:abc451d82b88 12 * IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
Alex Young 3:abc451d82b88 13 * PARTICULAR PURPOSE.
Alex Young 3:abc451d82b88 14 */
Alex Young 3:abc451d82b88 15
Alex Young 3:abc451d82b88 16 #include "xbusparser.h"
Alex Young 10:18a6661b7e59 17 #include "xbusdef.h"
Alex Young 19:46e88d37ecef 18 #include "xbusutility.h"
Alex Young 3:abc451d82b88 19 #include <stdlib.h>
Alex Young 19:46e88d37ecef 20 #include <string.h>
Alex Young 3:abc451d82b88 21
Alex Young 3:abc451d82b88 22 enum XbusParserState
Alex Young 3:abc451d82b88 23 {
Alex Young 3:abc451d82b88 24 XBPS_Preamble, /*!< \brief Looking for preamble. */
Alex Young 3:abc451d82b88 25 XBPS_BusId, /*!< \brief Waiting for bus ID. */
Alex Young 3:abc451d82b88 26 XBPS_MessageId, /*!< \brief Waiting for message ID. */
Alex Young 3:abc451d82b88 27 XBPS_Length, /*!< \brief Waiting for length. */
Alex Young 3:abc451d82b88 28 XBPS_ExtendedLengthMsb, /*!< \brief Waiting for extended length MSB*/
Alex Young 3:abc451d82b88 29 XBPS_ExtendedLengthLsb, /*!< \brief Waiting for extended length LSB*/
Alex Young 3:abc451d82b88 30 XBPS_Payload, /*!< \brief Reading payload. */
Alex Young 3:abc451d82b88 31 XBPS_Checksum /*!< \brief Waiting for checksum. */
Alex Young 3:abc451d82b88 32 };
Alex Young 3:abc451d82b88 33
Alex Young 3:abc451d82b88 34 struct XbusParser
Alex Young 3:abc451d82b88 35 {
Alex Young 3:abc451d82b88 36 struct XbusParserCallback callbacks;
Alex Young 14:155f9a55ec51 37 struct XbusMessage currentMessage;
Alex Young 3:abc451d82b88 38 uint16_t payloadReceived;
Alex Young 3:abc451d82b88 39 uint8_t checksum;
Alex Young 3:abc451d82b88 40 enum XbusParserState state;
Alex Young 3:abc451d82b88 41 };
Alex Young 3:abc451d82b88 42
Alex Young 3:abc451d82b88 43 size_t XbusParser_mem(void)
Alex Young 3:abc451d82b88 44 {
Alex Young 3:abc451d82b88 45 return sizeof(struct XbusParser);
Alex Young 3:abc451d82b88 46 }
Alex Young 3:abc451d82b88 47
Alex Young 3:abc451d82b88 48 struct XbusParser* XbusParser_create(struct XbusParserCallback const* callback)
Alex Young 3:abc451d82b88 49 {
Alex Young 3:abc451d82b88 50 void* mem = malloc(XbusParser_mem());
Alex Young 3:abc451d82b88 51 if (mem)
Alex Young 3:abc451d82b88 52 {
Alex Young 3:abc451d82b88 53 return XbusParser_init(mem, callback);
Alex Young 3:abc451d82b88 54 }
Alex Young 3:abc451d82b88 55 return NULL;
Alex Young 3:abc451d82b88 56 }
Alex Young 3:abc451d82b88 57
Alex Young 3:abc451d82b88 58 void XbusParser_destroy(struct XbusParser* parser)
Alex Young 3:abc451d82b88 59 {
Alex Young 3:abc451d82b88 60 free(parser);
Alex Young 3:abc451d82b88 61 }
Alex Young 3:abc451d82b88 62
Alex Young 3:abc451d82b88 63 struct XbusParser* XbusParser_init(void* parserMem, struct XbusParserCallback const* callback)
Alex Young 3:abc451d82b88 64 {
Alex Young 3:abc451d82b88 65 struct XbusParser* parser = (struct XbusParser*)parserMem;
Alex Young 3:abc451d82b88 66 parser->state = XBPS_Preamble;
Alex Young 3:abc451d82b88 67 parser->callbacks.allocateBuffer = callback->allocateBuffer;
Alex Young 25:01356fb59467 68 parser->callbacks.deallocateBuffer = callback->deallocateBuffer;
Alex Young 3:abc451d82b88 69 parser->callbacks.handleMessage = callback->handleMessage;
Alex Young 3:abc451d82b88 70 return parser;
Alex Young 3:abc451d82b88 71 }
Alex Young 3:abc451d82b88 72
Alex Young 25:01356fb59467 73 static void parseDeviceId(struct XbusParser* parser, uint8_t const* rawData)
Alex Young 23:8171449f0dc3 74 {
Alex Young 23:8171449f0dc3 75 uint32_t* deviceId = parser->callbacks.allocateBuffer(sizeof(uint32_t));
Alex Young 23:8171449f0dc3 76 if (deviceId)
Alex Young 23:8171449f0dc3 77 {
Alex Young 25:01356fb59467 78 XbusUtility_readU32(deviceId, rawData);
Alex Young 23:8171449f0dc3 79 parser->currentMessage.data = deviceId;
Alex Young 23:8171449f0dc3 80 parser->currentMessage.length = 1;
Alex Young 23:8171449f0dc3 81 }
Alex Young 23:8171449f0dc3 82 else
Alex Young 23:8171449f0dc3 83 {
Alex Young 23:8171449f0dc3 84 parser->currentMessage.data = NULL;
Alex Young 23:8171449f0dc3 85 }
Alex Young 23:8171449f0dc3 86 }
Alex Young 23:8171449f0dc3 87
Alex Young 25:01356fb59467 88 static void parseOutputConfig(struct XbusParser* parser, uint8_t const* rawData)
Alex Young 23:8171449f0dc3 89 {
Alex Young 23:8171449f0dc3 90 uint8_t fields = parser->currentMessage.length / 4;
Alex Young 23:8171449f0dc3 91 struct OutputConfiguration* conf = parser->callbacks.allocateBuffer(fields * sizeof(struct OutputConfiguration));
Alex Young 23:8171449f0dc3 92 if (conf)
Alex Young 23:8171449f0dc3 93 {
Alex Young 23:8171449f0dc3 94 parser->currentMessage.data = conf;
Alex Young 23:8171449f0dc3 95 parser->currentMessage.length = fields;
Alex Young 23:8171449f0dc3 96
Alex Young 23:8171449f0dc3 97 for (int i = 0; i < fields; ++i)
Alex Young 23:8171449f0dc3 98 {
Alex Young 25:01356fb59467 99 rawData = XbusUtility_readU16((uint16_t*)&conf->dtype, rawData);
Alex Young 25:01356fb59467 100 rawData = XbusUtility_readU16(&conf->freq, rawData);
Alex Young 23:8171449f0dc3 101 ++conf;
Alex Young 23:8171449f0dc3 102 }
Alex Young 23:8171449f0dc3 103 }
Alex Young 23:8171449f0dc3 104 else
Alex Young 23:8171449f0dc3 105 {
Alex Young 23:8171449f0dc3 106 parser->currentMessage.data = NULL;
Alex Young 23:8171449f0dc3 107 }
Alex Young 23:8171449f0dc3 108 }
Alex Young 23:8171449f0dc3 109
Alex Young 19:46e88d37ecef 110 static void parseMessagePayload(struct XbusParser* parser)
Alex Young 3:abc451d82b88 111 {
Alex Young 25:01356fb59467 112 uint8_t const* const rawData = parser->currentMessage.data;
Alex Young 19:46e88d37ecef 113 switch (parser->currentMessage.mid)
Alex Young 19:46e88d37ecef 114 {
Alex Young 25:01356fb59467 115 default:
Alex Young 25:01356fb59467 116 // Leave parsing and memory management to user code
Alex Young 25:01356fb59467 117 return;
Alex Young 25:01356fb59467 118
Alex Young 19:46e88d37ecef 119 case XMID_DeviceId:
Alex Young 25:01356fb59467 120 parseDeviceId(parser, rawData);
Alex Young 19:46e88d37ecef 121 break;
Alex Young 19:46e88d37ecef 122
Alex Young 22:3eab999c5076 123 case XMID_OutputConfig:
Alex Young 25:01356fb59467 124 parseOutputConfig(parser, rawData);
Alex Young 19:46e88d37ecef 125 break;
Alex Young 19:46e88d37ecef 126 }
Alex Young 25:01356fb59467 127
Alex Young 25:01356fb59467 128 if (rawData)
Alex Young 25:01356fb59467 129 parser->callbacks.deallocateBuffer(rawData);
Alex Young 19:46e88d37ecef 130 }
Alex Young 19:46e88d37ecef 131
Alex Young 19:46e88d37ecef 132 void prepareForPayload(struct XbusParser* parser)
Alex Young 19:46e88d37ecef 133 {
Alex Young 3:abc451d82b88 134 parser->payloadReceived = 0;
Alex Young 25:01356fb59467 135 parser->currentMessage.data = parser->callbacks.allocateBuffer(parser->currentMessage.length);
Alex Young 3:abc451d82b88 136 }
Alex Young 3:abc451d82b88 137
Alex Young 3:abc451d82b88 138 void XbusParser_parseByte(struct XbusParser* parser, const uint8_t byte)
Alex Young 3:abc451d82b88 139 {
Alex Young 3:abc451d82b88 140 switch (parser->state)
Alex Young 3:abc451d82b88 141 {
Alex Young 3:abc451d82b88 142 case XBPS_Preamble:
Alex Young 3:abc451d82b88 143 if (byte == XBUS_PREAMBLE)
Alex Young 3:abc451d82b88 144 {
Alex Young 3:abc451d82b88 145 parser->checksum = 0;
Alex Young 3:abc451d82b88 146 parser->state = XBPS_BusId;
Alex Young 3:abc451d82b88 147 }
Alex Young 3:abc451d82b88 148 break;
Alex Young 3:abc451d82b88 149
Alex Young 3:abc451d82b88 150 case XBPS_BusId:
Alex Young 3:abc451d82b88 151 parser->checksum += byte;
Alex Young 3:abc451d82b88 152 parser->state = XBPS_MessageId;
Alex Young 3:abc451d82b88 153 break;
Alex Young 3:abc451d82b88 154
Alex Young 3:abc451d82b88 155 case XBPS_MessageId:
Alex Young 3:abc451d82b88 156 parser->checksum += byte;
Alex Young 14:155f9a55ec51 157 parser->currentMessage.mid = (enum XsMessageId)byte;
Alex Young 3:abc451d82b88 158 parser->state = XBPS_Length;
Alex Young 3:abc451d82b88 159 break;
Alex Young 3:abc451d82b88 160
Alex Young 3:abc451d82b88 161 case XBPS_Length:
Alex Young 3:abc451d82b88 162 parser->checksum += byte;
Alex Young 3:abc451d82b88 163 if (byte == XBUS_NO_PAYLOAD)
Alex Young 3:abc451d82b88 164 {
Alex Young 14:155f9a55ec51 165 parser->currentMessage.length = byte;
Alex Young 17:680f28e00d17 166 parser->currentMessage.data = NULL;
Alex Young 3:abc451d82b88 167 parser->state = XBPS_Checksum;
Alex Young 3:abc451d82b88 168 }
Alex Young 3:abc451d82b88 169 else if (byte < XBUS_EXTENDED_LENGTH)
Alex Young 3:abc451d82b88 170 {
Alex Young 14:155f9a55ec51 171 parser->currentMessage.length = byte;
Alex Young 3:abc451d82b88 172 prepareForPayload(parser);
Alex Young 3:abc451d82b88 173 parser->state = XBPS_Payload;
Alex Young 3:abc451d82b88 174 }
Alex Young 3:abc451d82b88 175 else
Alex Young 3:abc451d82b88 176 {
Alex Young 3:abc451d82b88 177 parser->state = XBPS_ExtendedLengthMsb;
Alex Young 3:abc451d82b88 178 }
Alex Young 3:abc451d82b88 179 break;
Alex Young 3:abc451d82b88 180
Alex Young 3:abc451d82b88 181 case XBPS_ExtendedLengthMsb:
Alex Young 3:abc451d82b88 182 parser->checksum += byte;
Alex Young 14:155f9a55ec51 183 parser->currentMessage.length = ((uint16_t)byte) << 8;
Alex Young 3:abc451d82b88 184 parser->state = XBPS_ExtendedLengthLsb;
Alex Young 3:abc451d82b88 185 break;
Alex Young 3:abc451d82b88 186
Alex Young 3:abc451d82b88 187 case XBPS_ExtendedLengthLsb:
Alex Young 3:abc451d82b88 188 parser->checksum += byte;
Alex Young 14:155f9a55ec51 189 parser->currentMessage.length |= byte;
Alex Young 3:abc451d82b88 190 prepareForPayload(parser);
Alex Young 3:abc451d82b88 191 parser->state = XBPS_Payload;
Alex Young 3:abc451d82b88 192 break;
Alex Young 3:abc451d82b88 193
Alex Young 3:abc451d82b88 194 case XBPS_Payload:
Alex Young 3:abc451d82b88 195 parser->checksum += byte;
Alex Young 14:155f9a55ec51 196 if (parser->currentMessage.data)
Alex Young 3:abc451d82b88 197 {
Alex Young 19:46e88d37ecef 198 ((uint8_t*)parser->currentMessage.data)[parser->payloadReceived] = byte;
Alex Young 3:abc451d82b88 199 }
Alex Young 14:155f9a55ec51 200 if (++parser->payloadReceived == parser->currentMessage.length)
Alex Young 3:abc451d82b88 201 {
Alex Young 3:abc451d82b88 202 parser->state = XBPS_Checksum;
Alex Young 3:abc451d82b88 203 }
Alex Young 3:abc451d82b88 204 break;
Alex Young 3:abc451d82b88 205
Alex Young 3:abc451d82b88 206 case XBPS_Checksum:
Alex Young 3:abc451d82b88 207 parser->checksum += byte;
Alex Young 17:680f28e00d17 208 if ((parser->checksum == 0) &&
Alex Young 17:680f28e00d17 209 ((parser->currentMessage.length == 0) ||
Alex Young 17:680f28e00d17 210 parser->currentMessage.data))
Alex Young 3:abc451d82b88 211 {
Alex Young 19:46e88d37ecef 212 parseMessagePayload(parser);
Alex Young 14:155f9a55ec51 213 parser->callbacks.handleMessage(&parser->currentMessage);
Alex Young 3:abc451d82b88 214 }
Alex Young 25:01356fb59467 215 else if (parser->currentMessage.data)
Alex Young 25:01356fb59467 216 {
Alex Young 25:01356fb59467 217 parser->callbacks.deallocateBuffer(parser->currentMessage.data);
Alex Young 25:01356fb59467 218 }
Alex Young 3:abc451d82b88 219 parser->state = XBPS_Preamble;
Alex Young 3:abc451d82b88 220 break;
Alex Young 3:abc451d82b88 221 }
Alex Young 3:abc451d82b88 222 }
Alex Young 3:abc451d82b88 223
Alex Young 3:abc451d82b88 224 void XbusParser_parseBuffer(struct XbusParser* parser, uint8_t const* buf, size_t bufSize)
Alex Young 3:abc451d82b88 225 {
Alex Young 3:abc451d82b88 226 for (size_t i = 0; i < bufSize; ++i)
Alex Young 3:abc451d82b88 227 {
Alex Young 3:abc451d82b88 228 XbusParser_parseByte(parser, buf[i]);
Alex Young 3:abc451d82b88 229 }
Alex Young 3:abc451d82b88 230 }
Alex Young 3:abc451d82b88 231