A driver for the MAX8U GPS by uBlox. Provides core functionality. Communicates through I2C.

MAX8U Driver

This driver supports a wide range of functions provided by the MAX8U chip. Most of the essential features are supported. It lays a framework to add more commands easily, with only a little extra work.

Driver was originally made for the USC Rocket Propulsion Lab by Adhyyan Sekhsaria and Jamie Smith

Features

Currently supports:

  • Getting coordinates in latitude, longitude, accuracy...
  • Velocity measurements in each axis
  • Individual satellite information
  • Time of last message
  • Antenna Power Status
  • GPS Fix Quality
  • Save configuration in memory

Documentation

Full documentation is available here

Usage

Code Structure:

In factory settings, the module is not configured to send any messages. For the GPS to give updates, we need to configure it by sending messages using setMessageEnabled() which internally calls sendMessage() and waitForAck().

calling configure() once will enable a few useful messages, and save this configuration in the MAX8U non-volatile memory.

update() to be called periodically by the user. Processes and reads all the messages currently stored in the GPS. Calls processMessage() on every message. processMessage(): processes the message currently in the buffer by calling the respective functions. Each message is read, and its relevant information is then stored in the public variables.

By default, the GPS sends messages in NMEA format (but we reconfigure it to UBX format), so readNextMessage() has to determine which format the message is.

define the macro MAX8U_DEBUG to enable printing out to message information to the debug port. If not defined, will only print error messages to the debug port.

Example

Outputting Coordinates, Velocity and Time from GPS

#include "MAX8U.h"

int main(){
    MAX8U gps(&pc, PIN_I2C_SDA, PIN_I2C_SCL, p25);
    bool booted = gps.begin();

    if(!booted){
        //handle error
    }
    booted = gps.configure();
    if(!booted){
        //handle error
    }

    while(true){
        bool newMessageRcvd = gps.update();
        pc.printf(">Position: %.06f %c, %.06f %c, Height %.02f m\r\n",
                  std::abs(gps.latitude), gps.latitude > 0 ? 'N' : 'S',
                  std::abs(gps.longitude), gps.longitude > 0 ? 'E' : 'W',
                  gps.height);

        // velocity
        pc.printf(">Velocity: %.02f m/s N, %.02f m/s E, %.02f m/s Down\r\n",
                  gps.northVel * .02f,
                  gps.eastVel * .02f,
                  gps.downVel * .02f);

        // accuracy
        pc.printf(">Fix: Quality: %" PRIu8 ", Num Satellites: %" PRIu8 ", Position Accuracy: %.02f m\r\n",
                static_cast<uint8_t>(gps.fixQuality), gps.numSatellites, gps.posAccuracy);

        // time
        pc.printf(">Time: %" PRIu8 "/%" PRIu8"/%" PRIu16" %" PRIu8":%" PRIu8 ":%" PRIu8 "\r\n",
                gps.month,
                gps.day,
                gps.year,
                gps.hour,
                gps.minute,
                gps.second);
    }
}

Committer:
adhyyan
Date:
Tue Jan 07 10:49:40 2020 +0000
Revision:
3:b51460af3259
Parent:
0:7f603f221713
Added Example Code

Who changed what in which revision?

UserRevisionLine numberNew contents of line
adhyyan 0:7f603f221713 1 //MAX 8U GPS Driver
adhyyan 0:7f603f221713 2
adhyyan 0:7f603f221713 3 //Author: Adhyyan Sekhsaria, Jamie Smith
adhyyan 0:7f603f221713 4
adhyyan 0:7f603f221713 5 //Written with the help of the following data sheets:
adhyyan 0:7f603f221713 6 //https://www.u-blox.com/sites/default/files/MAX-8-M8-FW3_HardwareIntegrationManual_%28UBX-15030059%29.pdf
adhyyan 0:7f603f221713 7 //https://www.u-blox.com/en/docs/UBX-13003221
adhyyan 0:7f603f221713 8
adhyyan 0:7f603f221713 9 #include "MAX8U.h"
adhyyan 0:7f603f221713 10
adhyyan 0:7f603f221713 11 #include <cinttypes>
adhyyan 0:7f603f221713 12 #include <algorithm>
adhyyan 0:7f603f221713 13
adhyyan 0:7f603f221713 14 #define MAX8U_DEBUG 1
adhyyan 0:7f603f221713 15
adhyyan 0:7f603f221713 16 const char* GNSSNames[] = {"GPS", "SBAS", "Galileo", "BeiDou", "IMES", "QZSS", "GLONASS"};
adhyyan 0:7f603f221713 17
adhyyan 0:7f603f221713 18 const char *MAX8U::SatelliteInfo::getGNSSName()
adhyyan 0:7f603f221713 19 {
adhyyan 0:7f603f221713 20 return GNSSNames[static_cast<uint8_t>(gnss)];
adhyyan 0:7f603f221713 21 }
adhyyan 0:7f603f221713 22
adhyyan 0:7f603f221713 23
adhyyan 0:7f603f221713 24 MAX8U::MAX8U(Serial *debugPort, PinName user_SDApin, PinName user_SCLpin, PinName user_RSTPin,
adhyyan 0:7f603f221713 25 uint8_t i2cAddress, int i2cPortSpeed) :
adhyyan 0:7f603f221713 26 _debugPort(debugPort),
adhyyan 0:7f603f221713 27 _i2cPort(user_SDApin, user_SCLpin),
adhyyan 0:7f603f221713 28 _i2cAddress(i2cAddress),
adhyyan 0:7f603f221713 29 _rst(user_RSTPin, 1)
adhyyan 0:7f603f221713 30
adhyyan 0:7f603f221713 31 {
adhyyan 0:7f603f221713 32
adhyyan 0:7f603f221713 33 //Get user settings
adhyyan 0:7f603f221713 34 _i2cPortSpeed = i2cPortSpeed;
adhyyan 0:7f603f221713 35
adhyyan 0:7f603f221713 36 #define MAX8U_MAX_SPEED 4000000 // 400 kHz
adhyyan 0:7f603f221713 37 if(_i2cPortSpeed > MAX8U_MAX_SPEED)
adhyyan 0:7f603f221713 38 {
adhyyan 0:7f603f221713 39 _i2cPortSpeed = MAX8U_MAX_SPEED;
adhyyan 0:7f603f221713 40 }
adhyyan 0:7f603f221713 41 _i2cPort.frequency(_i2cPortSpeed);
adhyyan 0:7f603f221713 42 }
adhyyan 0:7f603f221713 43
adhyyan 0:7f603f221713 44
adhyyan 0:7f603f221713 45 bool MAX8U::begin(){
adhyyan 0:7f603f221713 46 //Configure the MAX8U for I2C communication
adhyyan 0:7f603f221713 47
adhyyan 0:7f603f221713 48 _rst = 0; // Reset BNO080
adhyyan 0:7f603f221713 49 wait(.002f); // Min length not specified in datasheet?
adhyyan 0:7f603f221713 50 _rst = 1; // Bring out of reset
adhyyan 0:7f603f221713 51
adhyyan 0:7f603f221713 52 //TODO: wait for the GPS to boot. Couldnt find any pin in the data sheet which would be useful
adhyyan 0:7f603f221713 53 wait(0.1f); //for now, just wait for some time
adhyyan 0:7f603f221713 54
adhyyan 0:7f603f221713 55 if(checkVersion())
adhyyan 0:7f603f221713 56 {
adhyyan 0:7f603f221713 57 #ifdef MAX8U_DEBUG
adhyyan 0:7f603f221713 58 _debugPort->printf("MAX8U booted up");
adhyyan 0:7f603f221713 59 #endif
adhyyan 0:7f603f221713 60 return true;
adhyyan 0:7f603f221713 61 }
adhyyan 0:7f603f221713 62 else
adhyyan 0:7f603f221713 63 {
adhyyan 0:7f603f221713 64 _debugPort->printf("MAX8U not detected!");
adhyyan 0:7f603f221713 65 return false;
adhyyan 0:7f603f221713 66 }
adhyyan 0:7f603f221713 67 }
adhyyan 0:7f603f221713 68
adhyyan 0:7f603f221713 69 bool MAX8U::update()
adhyyan 0:7f603f221713 70 {
adhyyan 0:7f603f221713 71 bool gotAnyMessages = false;
adhyyan 0:7f603f221713 72
adhyyan 0:7f603f221713 73 while(readNextMessage())
adhyyan 0:7f603f221713 74 {
adhyyan 0:7f603f221713 75 processMessage();
adhyyan 0:7f603f221713 76
adhyyan 0:7f603f221713 77 gotAnyMessages = true;
adhyyan 0:7f603f221713 78 }
adhyyan 0:7f603f221713 79
adhyyan 0:7f603f221713 80
adhyyan 0:7f603f221713 81 return gotAnyMessages;
adhyyan 0:7f603f221713 82 }
adhyyan 0:7f603f221713 83
adhyyan 0:7f603f221713 84 bool MAX8U::configure()
adhyyan 0:7f603f221713 85 {
adhyyan 0:7f603f221713 86 // switch to UBX mode
adhyyan 0:7f603f221713 87 if(!configureCommSettings())
adhyyan 0:7f603f221713 88 {
adhyyan 0:7f603f221713 89 return false;
adhyyan 0:7f603f221713 90 }
adhyyan 0:7f603f221713 91
adhyyan 0:7f603f221713 92 // enable NAV messages
adhyyan 0:7f603f221713 93 // latitude, longitude, and height
adhyyan 0:7f603f221713 94 if(!setMessageEnabled(UBX_CLASS_NAV, UBX_NAV_POSLLH, true))
adhyyan 0:7f603f221713 95 {
adhyyan 0:7f603f221713 96 return false;
adhyyan 0:7f603f221713 97 }
adhyyan 0:7f603f221713 98
adhyyan 0:7f603f221713 99 if(!setMessageEnabled(UBX_CLASS_NAV, UBX_NAV_SOL, true))
adhyyan 0:7f603f221713 100 {
adhyyan 0:7f603f221713 101 return false;
adhyyan 0:7f603f221713 102 }
adhyyan 0:7f603f221713 103
adhyyan 0:7f603f221713 104 if(!setMessageEnabled(UBX_CLASS_NAV, UBX_NAV_TIMEUTC, true))
adhyyan 0:7f603f221713 105 {
adhyyan 0:7f603f221713 106 return false;
adhyyan 0:7f603f221713 107 }
adhyyan 0:7f603f221713 108
adhyyan 0:7f603f221713 109
adhyyan 0:7f603f221713 110 if(!setMessageEnabled(UBX_CLASS_NAV, UBX_NAV_VELNED, true))
adhyyan 0:7f603f221713 111 {
adhyyan 0:7f603f221713 112 return false;
adhyyan 0:7f603f221713 113 }
adhyyan 0:7f603f221713 114
adhyyan 0:7f603f221713 115 return saveSettings();
adhyyan 0:7f603f221713 116
adhyyan 0:7f603f221713 117 }
adhyyan 0:7f603f221713 118
adhyyan 0:7f603f221713 119 bool MAX8U::setMessageEnabled(uint8_t messageClass, uint8_t messageID, bool enabled)
adhyyan 0:7f603f221713 120 {
adhyyan 0:7f603f221713 121 uint8_t data[3];
adhyyan 0:7f603f221713 122
adhyyan 0:7f603f221713 123 data[0] = messageClass; // byte 0: class
adhyyan 0:7f603f221713 124 data[1] = messageID; // byte 1: ID
adhyyan 0:7f603f221713 125 data[2] = static_cast<uint8_t>(enabled ? 1 : 0); // byte 2: rate
adhyyan 0:7f603f221713 126
adhyyan 0:7f603f221713 127 if(!sendCommand(UBX_CLASS_CFG, UBX_CFG_MSG, data, sizeof(data)))
adhyyan 0:7f603f221713 128 {
adhyyan 0:7f603f221713 129 return false;
adhyyan 0:7f603f221713 130 }
adhyyan 0:7f603f221713 131
adhyyan 0:7f603f221713 132 return waitForACK(UBX_CLASS_CFG, UBX_CFG_MSG);
adhyyan 0:7f603f221713 133 }
adhyyan 0:7f603f221713 134
adhyyan 0:7f603f221713 135 MAX8U::AntennaPowerStatus MAX8U::antennaPowerStatus() {
adhyyan 0:7f603f221713 136 sendCommand(UBX_CLASS_MON, UBX_MON_HW, nullptr, 0);
adhyyan 0:7f603f221713 137
adhyyan 0:7f603f221713 138 if(!waitForMessage(UBX_CLASS_MON, UBX_MON_HW))
adhyyan 0:7f603f221713 139 {
adhyyan 0:7f603f221713 140 return MAX8U::AntennaPowerStatus::NO_MESSAGE_RCVD;
adhyyan 0:7f603f221713 141 }
adhyyan 0:7f603f221713 142
adhyyan 0:7f603f221713 143 //else print out whether its on or off
adhyyan 0:7f603f221713 144 MAX8U::AntennaPowerStatus powerStatus = AntennaPowerStatus (static_cast<uint8_t >(buffer[UBX_DATA_OFFSET + 21]));
adhyyan 0:7f603f221713 145 return powerStatus;
adhyyan 0:7f603f221713 146 }
adhyyan 0:7f603f221713 147
adhyyan 0:7f603f221713 148 ssize_t MAX8U::readSatelliteInfo(MAX8U::SatelliteInfo *satelliteInfos, size_t infoLen)
adhyyan 0:7f603f221713 149 {
adhyyan 0:7f603f221713 150 sendCommand(UBX_CLASS_NAV, UBX_NAV_SAT, nullptr, 0);
adhyyan 0:7f603f221713 151
adhyyan 0:7f603f221713 152 if(!waitForMessage(UBX_CLASS_NAV, UBX_NAV_SAT))
adhyyan 0:7f603f221713 153 {
adhyyan 0:7f603f221713 154 return -1;
adhyyan 0:7f603f221713 155 }
adhyyan 0:7f603f221713 156
adhyyan 0:7f603f221713 157 uint8_t satellitesReturned = static_cast<uint8_t>(buffer[UBX_DATA_OFFSET + 5]);
adhyyan 0:7f603f221713 158
adhyyan 0:7f603f221713 159 for(size_t i = 0; i < std::min(static_cast<size_t>(satellitesReturned), infoLen); i++)
adhyyan 0:7f603f221713 160 {
adhyyan 0:7f603f221713 161 // detect a buffer overrun in the case where more satellites were returned than could
adhyyan 0:7f603f221713 162 // fit in the buffer
adhyyan 0:7f603f221713 163 size_t flagOffset = UBX_DATA_OFFSET + 16 + 12*i;
adhyyan 0:7f603f221713 164 if(flagOffset >= bufferMaxLen)
adhyyan 0:7f603f221713 165 {
adhyyan 0:7f603f221713 166 _debugPort->printf("Error: NAV-SAT message truncated by receive buffer size!\r\n");
adhyyan 0:7f603f221713 167
adhyyan 0:7f603f221713 168 // keep the part that was valid
adhyyan 0:7f603f221713 169 return i;
adhyyan 0:7f603f221713 170 }
adhyyan 0:7f603f221713 171
adhyyan 0:7f603f221713 172 satelliteInfos[i].gnss = static_cast<GNSSID>(static_cast<uint8_t>(buffer[UBX_DATA_OFFSET + 8 + 12 * i]));
adhyyan 0:7f603f221713 173 satelliteInfos[i].satelliteID = static_cast<uint8_t>(buffer[UBX_DATA_OFFSET + 9 + 12*i]);
adhyyan 0:7f603f221713 174 satelliteInfos[i].signalStrength = static_cast<uint8_t>(buffer[UBX_DATA_OFFSET + 10 + 12*i]);
adhyyan 0:7f603f221713 175
adhyyan 0:7f603f221713 176 uint32_t flag = readUnalignedValue<uint32_t>(buffer, flagOffset);
adhyyan 0:7f603f221713 177
adhyyan 0:7f603f221713 178 satelliteInfos[i].signalQuality = (flag & 0x0007);
adhyyan 0:7f603f221713 179 satelliteInfos[i].svUsed = (flag & (1<<3));
adhyyan 0:7f603f221713 180
adhyyan 0:7f603f221713 181 //satelliteInfos[i].elevation = static_cast<int8_t >(buffer[UBX_DATA_OFFSET])
adhyyan 0:7f603f221713 182
adhyyan 0:7f603f221713 183 #if MAX8U_DEBUG
adhyyan 0:7f603f221713 184 _debugPort->printf("NAV_SAT Strength for %s %" PRIu8 ":: %" PRIu8 " dBHz; Quality: %" PRIu8 "\r\n",
adhyyan 0:7f603f221713 185 satelliteInfos[i].getGNSSName(), satelliteInfos[i].satelliteID,
adhyyan 0:7f603f221713 186 satelliteInfos[i].signalStrength, satelliteInfos[i].signalQuality);
adhyyan 0:7f603f221713 187 #endif
adhyyan 0:7f603f221713 188 }
adhyyan 0:7f603f221713 189
adhyyan 0:7f603f221713 190 return satellitesReturned;
adhyyan 0:7f603f221713 191 }
adhyyan 0:7f603f221713 192
adhyyan 0:7f603f221713 193
adhyyan 0:7f603f221713 194 void MAX8U::processMessage()
adhyyan 0:7f603f221713 195 {
adhyyan 0:7f603f221713 196 if(buffer[UBX_BYTE_CLASS] == UBX_CLASS_NAV)
adhyyan 0:7f603f221713 197 {
adhyyan 0:7f603f221713 198 switch(buffer[UBX_BYTE_ID])
adhyyan 0:7f603f221713 199 {
adhyyan 0:7f603f221713 200 case UBX_NAV_POSLLH:
adhyyan 0:7f603f221713 201 processNAV_POSLLH();
adhyyan 0:7f603f221713 202 break;
adhyyan 0:7f603f221713 203 case UBX_NAV_SOL:
adhyyan 0:7f603f221713 204 processNAV_SOL();
adhyyan 0:7f603f221713 205 break;
adhyyan 0:7f603f221713 206 case UBX_NAV_TIMEUTC:
adhyyan 0:7f603f221713 207 processNAV_TIMEUTC();
adhyyan 0:7f603f221713 208 break;
adhyyan 0:7f603f221713 209 case UBX_NAV_VELNED:
adhyyan 0:7f603f221713 210 processNAV_VELNED();
adhyyan 0:7f603f221713 211 break;
adhyyan 0:7f603f221713 212 }
adhyyan 0:7f603f221713 213
adhyyan 0:7f603f221713 214 }
adhyyan 0:7f603f221713 215 }
adhyyan 0:7f603f221713 216 void MAX8U::processNAV_VELNED() {
adhyyan 0:7f603f221713 217 northVel = readUnalignedValue<int32_t>(buffer, UBX_DATA_OFFSET + 4);
adhyyan 0:7f603f221713 218 eastVel = readUnalignedValue<int32_t>(buffer, UBX_DATA_OFFSET + 8);
adhyyan 0:7f603f221713 219 downVel = readUnalignedValue<int32_t>(buffer, UBX_DATA_OFFSET + 12);
adhyyan 0:7f603f221713 220 speed3D = readUnalignedValue<uint32_t>(buffer, UBX_DATA_OFFSET + 16);
adhyyan 0:7f603f221713 221
adhyyan 0:7f603f221713 222 #if MAX8U_DEBUG
adhyyan 0:7f603f221713 223 _debugPort->printf("Got NAV_VELNED message. North Vel=%" PRIi32 ", East Vel=%" PRIi32 ", Down Vel=%" PRIi32 ", 3D Speed=%" PRIu32 "\r\n",
adhyyan 0:7f603f221713 224 northVel, eastVel, downVel, speed3D);
adhyyan 0:7f603f221713 225 #endif
adhyyan 0:7f603f221713 226 }
adhyyan 0:7f603f221713 227
adhyyan 0:7f603f221713 228
adhyyan 0:7f603f221713 229 void MAX8U::processNAV_POSLLH()
adhyyan 0:7f603f221713 230 {
adhyyan 0:7f603f221713 231 // read latitude and longitude
adhyyan 0:7f603f221713 232 int32_t longitudeInt = readUnalignedValue<int32_t>(buffer, UBX_DATA_OFFSET + 4);
adhyyan 0:7f603f221713 233 longitude = longitudeInt * 1e-7;
adhyyan 0:7f603f221713 234
adhyyan 0:7f603f221713 235 int32_t latitudeInt = readUnalignedValue<int32_t>(buffer, UBX_DATA_OFFSET + 8);
adhyyan 0:7f603f221713 236 latitude = latitudeInt * 1e-7;
adhyyan 0:7f603f221713 237
adhyyan 0:7f603f221713 238 height = readUnalignedValue<int32_t>(buffer, UBX_DATA_OFFSET + 12)/(1000.0f); //height above ellipsoid
adhyyan 0:7f603f221713 239
adhyyan 0:7f603f221713 240 #if MAX8U_DEBUG
adhyyan 0:7f603f221713 241 _debugPort->printf("Got NAV_POSLLH message. Longitude=%.06f deg, Latitude=%.06f deg, Height=%.02f m\r\n", longitude, latitude, height);
adhyyan 0:7f603f221713 242 #endif
adhyyan 0:7f603f221713 243 }
adhyyan 0:7f603f221713 244
adhyyan 0:7f603f221713 245
adhyyan 0:7f603f221713 246 void MAX8U::processNAV_SOL()
adhyyan 0:7f603f221713 247 {
adhyyan 0:7f603f221713 248 fixQuality = static_cast<GPSFix>(buffer[UBX_DATA_OFFSET + 10]);
adhyyan 0:7f603f221713 249
adhyyan 0:7f603f221713 250 posAccuracy = readUnalignedValue<uint32_t>(buffer, UBX_DATA_OFFSET + 24) / 100.0f;
adhyyan 0:7f603f221713 251
adhyyan 0:7f603f221713 252 numSatellites = static_cast<uint8_t>(buffer[UBX_DATA_OFFSET + 47]);
adhyyan 0:7f603f221713 253
adhyyan 0:7f603f221713 254 #if MAX8U_DEBUG
adhyyan 0:7f603f221713 255 _debugPort->printf("Got NAV_SOL message. Fix quality=%" PRIu8 ", Pos accuracy=%.02f m, Num satellites=%" PRIu8 "\r\n",
adhyyan 0:7f603f221713 256 static_cast<uint8_t>(fixQuality), posAccuracy, numSatellites);
adhyyan 0:7f603f221713 257 #endif
adhyyan 0:7f603f221713 258 }
adhyyan 0:7f603f221713 259
adhyyan 0:7f603f221713 260 void MAX8U::processNAV_TIMEUTC()
adhyyan 0:7f603f221713 261 {
adhyyan 0:7f603f221713 262 year = readUnalignedValue<uint16_t>(buffer, UBX_DATA_OFFSET + 12);
adhyyan 0:7f603f221713 263
adhyyan 0:7f603f221713 264 month = static_cast<uint8_t>(buffer[UBX_DATA_OFFSET + 14]);
adhyyan 0:7f603f221713 265
adhyyan 0:7f603f221713 266 day = static_cast<uint8_t>(buffer[UBX_DATA_OFFSET + 15]);
adhyyan 0:7f603f221713 267
adhyyan 0:7f603f221713 268 hour = static_cast<uint8_t>(buffer[UBX_DATA_OFFSET + 16]);
adhyyan 0:7f603f221713 269
adhyyan 0:7f603f221713 270 minute = static_cast<uint8_t>(buffer[UBX_DATA_OFFSET + 17]);
adhyyan 0:7f603f221713 271
adhyyan 0:7f603f221713 272 second = static_cast<uint8_t>(buffer[UBX_DATA_OFFSET + 18]);
adhyyan 0:7f603f221713 273
adhyyan 0:7f603f221713 274 #if MAX8U_DEBUG
adhyyan 0:7f603f221713 275 _debugPort->printf("Got NAV_TIMEUTC message. year=%" PRIu16 ", month =%" PRIu8 ", day=%" PRIu8
adhyyan 0:7f603f221713 276 ", hour = %" PRIu8 ", min = %" PRIu8 ", sec = %" PRIu8 "\r\n",
adhyyan 0:7f603f221713 277 year, month, day, hour, minute, second);
adhyyan 0:7f603f221713 278 #endif
adhyyan 0:7f603f221713 279
adhyyan 0:7f603f221713 280 }
adhyyan 0:7f603f221713 281
adhyyan 0:7f603f221713 282 bool MAX8U::waitForMessage(uint8_t messageClass, uint8_t messageID, float timeout)
adhyyan 0:7f603f221713 283 {
adhyyan 0:7f603f221713 284 Timer timeoutTimer;
adhyyan 0:7f603f221713 285 timeoutTimer.start();
adhyyan 0:7f603f221713 286
adhyyan 0:7f603f221713 287 while(timeoutTimer.read() <= timeout)
adhyyan 0:7f603f221713 288 {
adhyyan 0:7f603f221713 289 bool newMessageReceived = readNextMessage();
adhyyan 0:7f603f221713 290
adhyyan 0:7f603f221713 291 //We dont use TX Ready pin here, because it isn't configured when the GPS is first set up.
adhyyan 0:7f603f221713 292
adhyyan 0:7f603f221713 293 if(!newMessageReceived){
adhyyan 0:7f603f221713 294 wait(0.001f);
adhyyan 0:7f603f221713 295 continue;
adhyyan 0:7f603f221713 296 }
adhyyan 0:7f603f221713 297
adhyyan 0:7f603f221713 298 if(messageClass == buffer[UBX_BYTE_CLASS] && messageID == buffer[UBX_BYTE_ID])
adhyyan 0:7f603f221713 299 {
adhyyan 0:7f603f221713 300 // found correct packet!
adhyyan 0:7f603f221713 301 return true;
adhyyan 0:7f603f221713 302 }
adhyyan 0:7f603f221713 303 else
adhyyan 0:7f603f221713 304 {
adhyyan 0:7f603f221713 305 // other data message, send to proper channels
adhyyan 0:7f603f221713 306 processMessage();
adhyyan 0:7f603f221713 307 }
adhyyan 0:7f603f221713 308
adhyyan 0:7f603f221713 309 }
adhyyan 0:7f603f221713 310
adhyyan 0:7f603f221713 311 _debugPort->printf("Timeout waiting for message 0x%02" PRIx8 " 0x%02" PRIx8 ".\r\n", messageClass, messageID);
adhyyan 0:7f603f221713 312 return false;
adhyyan 0:7f603f221713 313 }
adhyyan 0:7f603f221713 314
adhyyan 0:7f603f221713 315 bool MAX8U::waitForACK(uint8_t sentMessageClass, uint8_t sentMessageID, float timeout)
adhyyan 0:7f603f221713 316 {
adhyyan 0:7f603f221713 317 // NOTE: we assume that we wait for an ACK before sending another message, so
adhyyan 0:7f603f221713 318 // there will never be two ACKs in play at once
adhyyan 0:7f603f221713 319
adhyyan 0:7f603f221713 320 if(!waitForMessage(UBX_CLASS_ACK, UBX_ACK_ACK))
adhyyan 0:7f603f221713 321 {
adhyyan 0:7f603f221713 322 _debugPort->printf("Timeout waiting for ACK for message 0x%02" PRIx8 " 0x%02" PRIx8 "\r\n",
adhyyan 0:7f603f221713 323 sentMessageClass, sentMessageID);
adhyyan 0:7f603f221713 324 return false;
adhyyan 0:7f603f221713 325 }
adhyyan 0:7f603f221713 326
adhyyan 0:7f603f221713 327 // check the byte IDs
adhyyan 0:7f603f221713 328 if(buffer[UBX_DATA_OFFSET] != sentMessageClass || buffer[UBX_DATA_OFFSET+1] != sentMessageID)
adhyyan 0:7f603f221713 329 {
adhyyan 0:7f603f221713 330 _debugPort->printf("Ack rcvd for wrong message\r\n");
adhyyan 0:7f603f221713 331 return false;
adhyyan 0:7f603f221713 332 }
adhyyan 0:7f603f221713 333
adhyyan 0:7f603f221713 334
adhyyan 0:7f603f221713 335 return true;
adhyyan 0:7f603f221713 336 }
adhyyan 0:7f603f221713 337
adhyyan 0:7f603f221713 338 bool MAX8U::configureCommSettings(){
adhyyan 0:7f603f221713 339 //Configure DDC(I2C) by writing
adhyyan 0:7f603f221713 340
adhyyan 0:7f603f221713 341 //Configures the MAX8 to output in UBX format instead of NMEA format.
adhyyan 0:7f603f221713 342
adhyyan 0:7f603f221713 343 /*
adhyyan 0:7f603f221713 344 UBX-CFG-PRT Payload
adhyyan 0:7f603f221713 345 1 PortId = 0
adhyyan 0:7f603f221713 346 1 reserved1
adhyyan 0:7f603f221713 347 2 txReady
adhyyan 0:7f603f221713 348 4 mode - 7 address and 0 for write
adhyyan 0:7f603f221713 349 4 reserved - all 0s
adhyyan 0:7f603f221713 350 2 inProtoMask - keep 0th bit on, rest off
adhyyan 0:7f603f221713 351 2 outProtoMask - keep 0th bit on, rest off
adhyyan 0:7f603f221713 352 2 flags - all 0
adhyyan 0:7f603f221713 353 2 reserved - all 0
adhyyan 0:7f603f221713 354 */
adhyyan 0:7f603f221713 355
adhyyan 0:7f603f221713 356 uint16_t dataLen = 20;
adhyyan 0:7f603f221713 357 uint8_t data[20];
adhyyan 0:7f603f221713 358 data[0] = 0; //Port Id
adhyyan 0:7f603f221713 359 data[1] = 0; //Reserved
adhyyan 0:7f603f221713 360
adhyyan 0:7f603f221713 361 // disable TX ready
adhyyan 0:7f603f221713 362 data[2] = 0;
adhyyan 0:7f603f221713 363 data[3] = 0;
adhyyan 0:7f603f221713 364
adhyyan 0:7f603f221713 365 data[4] = (_i2cAddress<<1);
adhyyan 0:7f603f221713 366 data[5] = 0;
adhyyan 0:7f603f221713 367 data[6] = 0;
adhyyan 0:7f603f221713 368 data[7] = 0;
adhyyan 0:7f603f221713 369
adhyyan 0:7f603f221713 370 data[8] = 0;
adhyyan 0:7f603f221713 371 data[9] = 0;
adhyyan 0:7f603f221713 372 data[10] = 0;
adhyyan 0:7f603f221713 373 data[11] = 0;
adhyyan 0:7f603f221713 374
adhyyan 0:7f603f221713 375 data[12] = 0x01; //enabling UBX mode for input
adhyyan 0:7f603f221713 376 data[13] = 0;
adhyyan 0:7f603f221713 377
adhyyan 0:7f603f221713 378 data[14] = 0x01; //enabling UBX mode for output
adhyyan 0:7f603f221713 379 data[15] = 0;
adhyyan 0:7f603f221713 380
adhyyan 0:7f603f221713 381 data[16] = 0;
adhyyan 0:7f603f221713 382 data[17] = 0;
adhyyan 0:7f603f221713 383 data[18] = 0;
adhyyan 0:7f603f221713 384 data[19] = 0;
adhyyan 0:7f603f221713 385
adhyyan 0:7f603f221713 386
adhyyan 0:7f603f221713 387 if(!sendCommand(UBX_CLASS_CFG, UBX_CFG_PRT, data, dataLen))
adhyyan 0:7f603f221713 388 {
adhyyan 0:7f603f221713 389 return false;
adhyyan 0:7f603f221713 390 }
adhyyan 0:7f603f221713 391
adhyyan 0:7f603f221713 392 return waitForACK(UBX_CLASS_CFG, UBX_CFG_PRT);
adhyyan 0:7f603f221713 393 }
adhyyan 0:7f603f221713 394
adhyyan 0:7f603f221713 395 //send the header then the data to the Max8 on the default address 0x42
adhyyan 0:7f603f221713 396 //Returns false if sensor does not ACK
adhyyan 0:7f603f221713 397 bool MAX8U::sendCommand(uint8_t messageClass, uint8_t messageID, uint8_t *data, uint16_t dataLen)
adhyyan 0:7f603f221713 398 {
adhyyan 0:7f603f221713 399
adhyyan 0:7f603f221713 400 //using UBX protocol
adhyyan 0:7f603f221713 401
adhyyan 0:7f603f221713 402 // start the transaction and contact the IMU
adhyyan 0:7f603f221713 403 _i2cPort.start();
adhyyan 0:7f603f221713 404
adhyyan 0:7f603f221713 405 // to indicate an i2c read, shift the 7 bit address up 1 bit and keep bit 0 as a 0
adhyyan 0:7f603f221713 406 int writeResult = _i2cPort.write(_i2cAddress << 1);
adhyyan 0:7f603f221713 407
adhyyan 0:7f603f221713 408 if(writeResult != 1)
adhyyan 0:7f603f221713 409 {
adhyyan 0:7f603f221713 410 _debugPort->printf("MAX8U I2C write failed!\r\n");
adhyyan 0:7f603f221713 411 _i2cPort.stop();
adhyyan 0:7f603f221713 412 return false;
adhyyan 0:7f603f221713 413 }
adhyyan 0:7f603f221713 414
adhyyan 0:7f603f221713 415 #if MAX8U_DEBUG
adhyyan 0:7f603f221713 416 _debugPort->printf("MAX8U I2C write acked!\r\n");
adhyyan 0:7f603f221713 417 #endif
adhyyan 0:7f603f221713 418
adhyyan 0:7f603f221713 419 //compute checksum on header and data. Refer to datasheet
adhyyan 0:7f603f221713 420 uint8_t chka = 0, chkb = 0;
adhyyan 0:7f603f221713 421
adhyyan 0:7f603f221713 422 // add header portions to checksum;
adhyyan 0:7f603f221713 423 chka += messageClass;
adhyyan 0:7f603f221713 424 chkb += chka;
adhyyan 0:7f603f221713 425
adhyyan 0:7f603f221713 426 chka += messageID;
adhyyan 0:7f603f221713 427 chkb += chka;
adhyyan 0:7f603f221713 428
adhyyan 0:7f603f221713 429 chka += dataLen & 0xFF;
adhyyan 0:7f603f221713 430 chkb += chka;
adhyyan 0:7f603f221713 431
adhyyan 0:7f603f221713 432 chka += dataLen >> 8;
adhyyan 0:7f603f221713 433 chkb += chka;
adhyyan 0:7f603f221713 434
adhyyan 0:7f603f221713 435 // add data to checksum
adhyyan 0:7f603f221713 436 for(int i = 0; i < dataLen; i++){
adhyyan 0:7f603f221713 437 chka = chka + data[i];
adhyyan 0:7f603f221713 438 chkb = chkb + chka;
adhyyan 0:7f603f221713 439 }
adhyyan 0:7f603f221713 440
adhyyan 0:7f603f221713 441 //send the sync chars
adhyyan 0:7f603f221713 442 _i2cPort.write(UBX_SYNC_CHAR_1);
adhyyan 0:7f603f221713 443 _i2cPort.write(UBX_SYNC_CHAR_2);
adhyyan 0:7f603f221713 444
adhyyan 0:7f603f221713 445 // send the header
adhyyan 0:7f603f221713 446 _i2cPort.write(messageClass);
adhyyan 0:7f603f221713 447 _i2cPort.write(messageID);
adhyyan 0:7f603f221713 448 _i2cPort.write(dataLen & 0xFF);
adhyyan 0:7f603f221713 449 _i2cPort.write(dataLen >> 8);
adhyyan 0:7f603f221713 450
adhyyan 0:7f603f221713 451
adhyyan 0:7f603f221713 452 for(uint8_t i = 0; i < dataLen; i++){
adhyyan 0:7f603f221713 453 _i2cPort.write(data[i]);
adhyyan 0:7f603f221713 454 }
adhyyan 0:7f603f221713 455
adhyyan 0:7f603f221713 456 _i2cPort.write(chka);
adhyyan 0:7f603f221713 457 _i2cPort.write(chkb);
adhyyan 0:7f603f221713 458
adhyyan 0:7f603f221713 459 _i2cPort.stop();
adhyyan 0:7f603f221713 460
adhyyan 0:7f603f221713 461 #if MAX8U_DEBUG
adhyyan 0:7f603f221713 462 _debugPort->printf("Sending: %02" PRIx8 " %02" PRIx8 " %02" PRIx8 " %02" PRIx8 " %02" PRIx8 " %02" PRIx8,
adhyyan 0:7f603f221713 463 UBX_SYNC_CHAR_1, UBX_SYNC_CHAR_2, messageClass, messageID, dataLen & 0xFF, dataLen >> 8);
adhyyan 0:7f603f221713 464
adhyyan 0:7f603f221713 465 for(uint16_t i = 0; i < dataLen; i++){
adhyyan 0:7f603f221713 466 _debugPort->printf(" %02" PRIx8, data[i]);
adhyyan 0:7f603f221713 467 }
adhyyan 0:7f603f221713 468 _debugPort->printf(" %02" PRIx8 " %02" PRIx8 "\r\n", chka, chkb);
adhyyan 0:7f603f221713 469 #endif
adhyyan 0:7f603f221713 470
adhyyan 0:7f603f221713 471 return true;
adhyyan 0:7f603f221713 472 }
adhyyan 0:7f603f221713 473
adhyyan 0:7f603f221713 474 bool MAX8U::saveSettings()
adhyyan 0:7f603f221713 475 {
adhyyan 0:7f603f221713 476 const size_t dataLen = 12;
adhyyan 0:7f603f221713 477 uint8_t data[dataLen];
adhyyan 0:7f603f221713 478
adhyyan 0:7f603f221713 479 // don't clear any settings
adhyyan 0:7f603f221713 480 memset(data, 0, 4);
adhyyan 0:7f603f221713 481
adhyyan 0:7f603f221713 482 // save all settings
adhyyan 0:7f603f221713 483 data[4] = 0b00011111;
adhyyan 0:7f603f221713 484 data[5] = 0b00011111;
adhyyan 0:7f603f221713 485 data[6] = 0;
adhyyan 0:7f603f221713 486 data[7] = 0;
adhyyan 0:7f603f221713 487
adhyyan 0:7f603f221713 488 memset(data + 8, 0, 4);
adhyyan 0:7f603f221713 489
adhyyan 0:7f603f221713 490 if(!sendCommand(UBX_CLASS_CFG, UBX_CFG_CFG, data, dataLen))
adhyyan 0:7f603f221713 491 {
adhyyan 0:7f603f221713 492 return false;
adhyyan 0:7f603f221713 493 }
adhyyan 0:7f603f221713 494
adhyyan 0:7f603f221713 495 return waitForACK(UBX_CLASS_CFG, UBX_CFG_CFG);
adhyyan 0:7f603f221713 496
adhyyan 0:7f603f221713 497 }
adhyyan 0:7f603f221713 498
adhyyan 0:7f603f221713 499 bool MAX8U::checkVersion()
adhyyan 0:7f603f221713 500 {
adhyyan 0:7f603f221713 501 sendCommand(UBX_CLASS_MON, UBX_MON_VER, nullptr, 0);
adhyyan 0:7f603f221713 502
adhyyan 0:7f603f221713 503 if(!waitForMessage(UBX_CLASS_MON, UBX_MON_VER))
adhyyan 0:7f603f221713 504 {
adhyyan 0:7f603f221713 505 return false;
adhyyan 0:7f603f221713 506 }
adhyyan 0:7f603f221713 507
adhyyan 0:7f603f221713 508 #if MAX8U_DEBUG
adhyyan 0:7f603f221713 509 _debugPort->printf("MAXU8 Software Version: %s\r\n", buffer + UBX_DATA_OFFSET);
adhyyan 0:7f603f221713 510 _debugPort->printf("MAXU8 Software Version: %s\r\n", buffer + UBX_DATA_OFFSET + 30);
adhyyan 0:7f603f221713 511
adhyyan 0:7f603f221713 512 // print additional data
adhyyan 0:7f603f221713 513 size_t numAdditionalLines = (currMessageLength - UBX_HEADER_FOOTER_LENGTH - 40) / 30;
adhyyan 0:7f603f221713 514
adhyyan 0:7f603f221713 515 for(size_t line = 0; line < numAdditionalLines; line++)
adhyyan 0:7f603f221713 516 {
adhyyan 0:7f603f221713 517 _debugPort->printf("Extra Info: %s\r\n", buffer + UBX_DATA_OFFSET + 40 + 30*line);
adhyyan 0:7f603f221713 518 }
adhyyan 0:7f603f221713 519
adhyyan 0:7f603f221713 520 #endif
adhyyan 0:7f603f221713 521
adhyyan 0:7f603f221713 522 return true;
adhyyan 0:7f603f221713 523 }
adhyyan 0:7f603f221713 524
adhyyan 0:7f603f221713 525
adhyyan 0:7f603f221713 526 void MAX8U::readGNSSConfig() {
adhyyan 0:7f603f221713 527 sendCommand(UBX_CLASS_CFG, UBX_CFG_GNSS, nullptr, 0);
adhyyan 0:7f603f221713 528
adhyyan 0:7f603f221713 529 if(!waitForMessage(UBX_CLASS_CFG, UBX_CFG_GNSS)){
adhyyan 0:7f603f221713 530 _debugPort->printf("NO MESSAGE RCVD for GNSS CFG message");
adhyyan 0:7f603f221713 531 return;
adhyyan 0:7f603f221713 532 }
adhyyan 0:7f603f221713 533
adhyyan 0:7f603f221713 534 uint8_t numTrkChHw = static_cast<uint8_t >(buffer[UBX_DATA_OFFSET + 1]);
adhyyan 0:7f603f221713 535 uint8_t usedTracks = static_cast<uint8_t >(buffer[UBX_DATA_OFFSET + 2]);
adhyyan 0:7f603f221713 536 uint8_t blocks = static_cast<uint8_t >(buffer[UBX_DATA_OFFSET + 3]);
adhyyan 0:7f603f221713 537 _debugPort->printf("CHANNELS: %" PRIx8 " , USED: %" PRIx8 " , LEN: %" PRIx8 "\r\n", numTrkChHw, usedTracks, blocks);
adhyyan 0:7f603f221713 538 for(int i = 0; i < blocks; i++){
adhyyan 0:7f603f221713 539 uint8_t gnssID = static_cast<uint8_t >(buffer[UBX_DATA_OFFSET + 4 + 8*i]);
adhyyan 0:7f603f221713 540 uint32_t flag = static_cast<uint32_t >(buffer[UBX_DATA_OFFSET + 8 + 8*i]);
adhyyan 0:7f603f221713 541 bool enabled = flag&1;
adhyyan 0:7f603f221713 542 _debugPort->printf("GNSS ID: %" PRIx8 ", NAME: %s, ENABLED: %d \r\n", gnssID, GNSSNames[gnssID], enabled);
adhyyan 0:7f603f221713 543 }
adhyyan 0:7f603f221713 544
adhyyan 0:7f603f221713 545 }
adhyyan 0:7f603f221713 546
adhyyan 0:7f603f221713 547 bool MAX8U::readNextMessage(){
adhyyan 0:7f603f221713 548 //keep reading the 0xff register until the buffer is ove
adhyyan 0:7f603f221713 549
adhyyan 0:7f603f221713 550 int msgLen = readLen();
adhyyan 0:7f603f221713 551 if(msgLen == -1){
adhyyan 0:7f603f221713 552 _debugPort->printf("Didn't rcv ack from MAX8 when reading length\r\n");
adhyyan 0:7f603f221713 553 return false;
adhyyan 0:7f603f221713 554 }
adhyyan 0:7f603f221713 555
adhyyan 0:7f603f221713 556 if(msgLen == 0)
adhyyan 0:7f603f221713 557 {
adhyyan 0:7f603f221713 558 //nothing to do
adhyyan 0:7f603f221713 559 return false;
adhyyan 0:7f603f221713 560 }
adhyyan 0:7f603f221713 561
adhyyan 0:7f603f221713 562 _i2cPort.start();
adhyyan 0:7f603f221713 563 int readResult = _i2cPort.write((_i2cAddress << 1) | 0x01);
adhyyan 0:7f603f221713 564
adhyyan 0:7f603f221713 565 if(readResult != 1){
adhyyan 0:7f603f221713 566 _debugPort->printf("Didn't receive ack from MAX8\r\n");
adhyyan 0:7f603f221713 567 return false;
adhyyan 0:7f603f221713 568 }
adhyyan 0:7f603f221713 569
adhyyan 0:7f603f221713 570 // whether this is an NMEA or UBX sentence
adhyyan 0:7f603f221713 571 bool isLastByte = false;
adhyyan 0:7f603f221713 572 currMessageLength = 0;
adhyyan 0:7f603f221713 573 int ubxMsgLen = 100000; // large value to stop loop exit condition, will read real value later
adhyyan 0:7f603f221713 574 for(int i = 0; i < msgLen; i++) // for loop in case there's a data error and we don't detect the last byte
adhyyan 0:7f603f221713 575 {
adhyyan 0:7f603f221713 576 uint8_t incoming = static_cast<uint8_t >(_i2cPort.read(!isLastByte));
adhyyan 0:7f603f221713 577 if(i == 5 && !isNMEASentence){
adhyyan 0:7f603f221713 578 //read length and change that to msg length
adhyyan 0:7f603f221713 579 ubxMsgLen = (static_cast<uint16_t>(buffer[i] << 8) | buffer[i-1]) + 8;
adhyyan 0:7f603f221713 580 //non-payload body of a ubx message is 8
adhyyan 0:7f603f221713 581
adhyyan 0:7f603f221713 582 }
adhyyan 0:7f603f221713 583
adhyyan 0:7f603f221713 584 if(i == 0)
adhyyan 0:7f603f221713 585 {
adhyyan 0:7f603f221713 586 if(incoming == NMEA_MESSAGE_START_CHAR)
adhyyan 0:7f603f221713 587 {
adhyyan 0:7f603f221713 588 // NMEA sentences start with a dollars sign
adhyyan 0:7f603f221713 589 isNMEASentence = true;
adhyyan 0:7f603f221713 590 }
adhyyan 0:7f603f221713 591 else if(incoming == UBX_MESSAGE_START_CHAR)
adhyyan 0:7f603f221713 592 {
adhyyan 0:7f603f221713 593 // UBX sentences start with a 0xB5
adhyyan 0:7f603f221713 594 isNMEASentence = false;
adhyyan 0:7f603f221713 595 }
adhyyan 0:7f603f221713 596 else if(incoming == 0xFF)
adhyyan 0:7f603f221713 597 {
adhyyan 0:7f603f221713 598 _debugPort->printf("Message Length > 0, although buffer is empty\r\n");
adhyyan 0:7f603f221713 599 }else{
adhyyan 0:7f603f221713 600 _debugPort->printf("Unknown first character \r\n");
adhyyan 0:7f603f221713 601 }
adhyyan 0:7f603f221713 602
adhyyan 0:7f603f221713 603 }
adhyyan 0:7f603f221713 604
adhyyan 0:7f603f221713 605 if(i < bufferMaxLen){
adhyyan 0:7f603f221713 606 buffer[i] = incoming;
adhyyan 0:7f603f221713 607 ++currMessageLength;
adhyyan 0:7f603f221713 608 }
adhyyan 0:7f603f221713 609
adhyyan 0:7f603f221713 610 if(isLastByte)
adhyyan 0:7f603f221713 611 {
adhyyan 0:7f603f221713 612 break;
adhyyan 0:7f603f221713 613 }
adhyyan 0:7f603f221713 614
adhyyan 0:7f603f221713 615 // post-receive actions
adhyyan 0:7f603f221713 616
adhyyan 0:7f603f221713 617 // if it's an NMEA sentence, there is a CRLF at the end
adhyyan 0:7f603f221713 618 // if it's an UBX sentence, there is a length passed before the payload
adhyyan 0:7f603f221713 619 if((isNMEASentence && incoming == '\r') || (!isNMEASentence && i == ubxMsgLen-2))
adhyyan 0:7f603f221713 620 {
adhyyan 0:7f603f221713 621 isLastByte = true;
adhyyan 0:7f603f221713 622 }
adhyyan 0:7f603f221713 623 }
adhyyan 0:7f603f221713 624
adhyyan 0:7f603f221713 625 // add null terminator
adhyyan 0:7f603f221713 626 buffer[currMessageLength] = 0;
adhyyan 0:7f603f221713 627
adhyyan 0:7f603f221713 628 _i2cPort.stop();
adhyyan 0:7f603f221713 629
adhyyan 0:7f603f221713 630
adhyyan 0:7f603f221713 631 #if MAX8U_DEBUG
adhyyan 0:7f603f221713 632 _debugPort->printf("Read stream of MAX8U: ");
adhyyan 0:7f603f221713 633 for(uint16_t i = 0; i < currMessageLength; i++){
adhyyan 0:7f603f221713 634 _debugPort->printf("%02" PRIx8, buffer[i]);
adhyyan 0:7f603f221713 635 }
adhyyan 0:7f603f221713 636 _debugPort->printf(";\r\n");
adhyyan 0:7f603f221713 637 #endif
adhyyan 0:7f603f221713 638
adhyyan 0:7f603f221713 639 if(!isNMEASentence)
adhyyan 0:7f603f221713 640 {
adhyyan 0:7f603f221713 641 uint8_t chka = 0, chkb = 0;
adhyyan 0:7f603f221713 642 for(uint16_t i = 2; i < currMessageLength-2; i++)
adhyyan 0:7f603f221713 643 {
adhyyan 0:7f603f221713 644 chka += buffer[i];
adhyyan 0:7f603f221713 645 chkb += chka;
adhyyan 0:7f603f221713 646 }
adhyyan 0:7f603f221713 647
adhyyan 0:7f603f221713 648 if((chka != buffer[currMessageLength-2]) || (chkb != buffer[currMessageLength-1]))
adhyyan 0:7f603f221713 649 {
adhyyan 0:7f603f221713 650 _debugPort->printf("Checksums for UBX message don't match!\r\n");
adhyyan 0:7f603f221713 651 return false;
adhyyan 0:7f603f221713 652 }
adhyyan 0:7f603f221713 653 }
adhyyan 0:7f603f221713 654
adhyyan 0:7f603f221713 655 return true;
adhyyan 0:7f603f221713 656
adhyyan 0:7f603f221713 657 }
adhyyan 0:7f603f221713 658
adhyyan 0:7f603f221713 659
adhyyan 0:7f603f221713 660 int32_t MAX8U::readLen(){
adhyyan 0:7f603f221713 661
adhyyan 0:7f603f221713 662 _i2cPort.start();
adhyyan 0:7f603f221713 663 int i2cStatus = _i2cPort.write((_i2cAddress << 1) | 0x00);
adhyyan 0:7f603f221713 664 if(i2cStatus != 1)
adhyyan 0:7f603f221713 665 return -1;
adhyyan 0:7f603f221713 666 _i2cPort.write(0xFD);
adhyyan 0:7f603f221713 667
adhyyan 0:7f603f221713 668
adhyyan 0:7f603f221713 669 _i2cPort.start();
adhyyan 0:7f603f221713 670 i2cStatus = _i2cPort.write((_i2cAddress << 1) | 0x01);
adhyyan 0:7f603f221713 671 if(i2cStatus != 1)
adhyyan 0:7f603f221713 672 return -1;
adhyyan 0:7f603f221713 673
adhyyan 0:7f603f221713 674 uint8_t highByte = static_cast<uint8_t>(_i2cPort.read(true));
adhyyan 0:7f603f221713 675 uint8_t lowByte = static_cast<uint8_t>(_i2cPort.read(false));
adhyyan 0:7f603f221713 676
adhyyan 0:7f603f221713 677 _i2cPort.stop();
adhyyan 0:7f603f221713 678
adhyyan 0:7f603f221713 679 return (static_cast<uint16_t>(highByte << 8) | lowByte);
adhyyan 0:7f603f221713 680 }
adhyyan 0:7f603f221713 681
adhyyan 0:7f603f221713 682