This class provides an API to communicate with a u-blox GNSS chip. The files here were originally part of the C027_Support library (https://developer.mbed.org/teams/ublox/code/C027_Support/ at revision 138:dafbbf31bf76) but have been separated out, primarily for use on the u-blox C030 board where the cellular interace portion of the C027_Support library will instead be provided through the new mbed Cellular API.

Dependents:   example-ublox-at-cellular-interface-ext example-low-power-sleep example-C030-out-of-box-demo example-C030-out-of-box-demo ... more

Committer:
RobMeades
Date:
Thu Apr 13 14:45:17 2017 +0000
Revision:
2:b10ca4aa2e5e
Parent:
1:ef70a58a6c98
Child:
3:2a1cd49ead85
Remove deprecation warnings and warning about lack of bracing around empty else condition.  Changed bracing style to ARM standard.

Who changed what in which revision?

UserRevisionLine numberNew contents of line
rob.meades@u-blox.com 1:ef70a58a6c98 1 /* mbed Microcontroller Library
rob.meades@u-blox.com 1:ef70a58a6c98 2 * Copyright (c) 2017 u-blox
rob.meades@u-blox.com 1:ef70a58a6c98 3 *
rob.meades@u-blox.com 1:ef70a58a6c98 4 * Licensed under the Apache License, Version 2.0 (the "License");
rob.meades@u-blox.com 1:ef70a58a6c98 5 * you may not use this file except in compliance with the License.
rob.meades@u-blox.com 1:ef70a58a6c98 6 * You may obtain a copy of the License at
rob.meades@u-blox.com 1:ef70a58a6c98 7 *
rob.meades@u-blox.com 1:ef70a58a6c98 8 * http://www.apache.org/licenses/LICENSE-2.0
rob.meades@u-blox.com 1:ef70a58a6c98 9 *
rob.meades@u-blox.com 1:ef70a58a6c98 10 * Unless required by applicable law or agreed to in writing, software
rob.meades@u-blox.com 1:ef70a58a6c98 11 * distributed under the License is distributed on an "AS IS" BASIS,
rob.meades@u-blox.com 1:ef70a58a6c98 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
rob.meades@u-blox.com 1:ef70a58a6c98 13 * See the License for the specific language governing permissions and
rob.meades@u-blox.com 1:ef70a58a6c98 14 * limitations under the License.
rob.meades@u-blox.com 1:ef70a58a6c98 15 */
rob.meades@u-blox.com 1:ef70a58a6c98 16
rob.meades@u-blox.com 1:ef70a58a6c98 17 /**
rob.meades@u-blox.com 1:ef70a58a6c98 18 * @file gnss.cpp
rob.meades@u-blox.com 1:ef70a58a6c98 19 * This file defines a class that communicates with a u-blox GNSS chip.
rob.meades@u-blox.com 1:ef70a58a6c98 20 */
rob.meades@u-blox.com 1:ef70a58a6c98 21
rob.meades@u-blox.com 1:ef70a58a6c98 22 #include "mbed.h"
rob.meades@u-blox.com 1:ef70a58a6c98 23 #include "ctype.h"
rob.meades@u-blox.com 1:ef70a58a6c98 24 #include "gnss.h"
rob.meades@u-blox.com 1:ef70a58a6c98 25
rob.meades@u-blox.com 1:ef70a58a6c98 26 GnssParser::GnssParser(void)
rob.meades@u-blox.com 1:ef70a58a6c98 27 {
rob.meades@u-blox.com 1:ef70a58a6c98 28 // Create the power pins but set everything to disabled
RobMeades 2:b10ca4aa2e5e 29 _gnssPower = NULL;
RobMeades 2:b10ca4aa2e5e 30 _gnssEnable = NULL;
RobMeades 2:b10ca4aa2e5e 31
RobMeades 2:b10ca4aa2e5e 32 #if defined GNSSPWR && defined TARGET_UBLOX_C030 /* TODO */
rob.meades@u-blox.com 1:ef70a58a6c98 33 _gnssPower = new DigitalInOut(GNSSPWR, PIN_OUTPUT, OpenDrain, 0);
RobMeades 2:b10ca4aa2e5e 34 #endif
RobMeades 2:b10ca4aa2e5e 35 #if defined GNSSEN && defined TARGET_UBLOX_C030 /* TODO */
rob.meades@u-blox.com 1:ef70a58a6c98 36 _gnssEnable = new DigitalInOut(GNSSEN, PIN_OUTPUT, PushPullNoPull, 0);
RobMeades 2:b10ca4aa2e5e 37 #endif
rob.meades@u-blox.com 1:ef70a58a6c98 38 }
rob.meades@u-blox.com 1:ef70a58a6c98 39
rob.meades@u-blox.com 1:ef70a58a6c98 40 GnssParser::~GnssParser(void)
rob.meades@u-blox.com 1:ef70a58a6c98 41 {
rob.meades@u-blox.com 1:ef70a58a6c98 42 // Set the power pins to lowest power state before ending
RobMeades 2:b10ca4aa2e5e 43 if (_gnssPower != NULL) {
RobMeades 2:b10ca4aa2e5e 44 *_gnssPower = 0;
RobMeades 2:b10ca4aa2e5e 45 delete _gnssPower;
RobMeades 2:b10ca4aa2e5e 46 }
RobMeades 2:b10ca4aa2e5e 47
RobMeades 2:b10ca4aa2e5e 48 if (_gnssEnable != NULL) {
RobMeades 2:b10ca4aa2e5e 49 *_gnssEnable = 0;
RobMeades 2:b10ca4aa2e5e 50 delete _gnssEnable;
RobMeades 2:b10ca4aa2e5e 51 }
rob.meades@u-blox.com 1:ef70a58a6c98 52 }
rob.meades@u-blox.com 1:ef70a58a6c98 53
rob.meades@u-blox.com 1:ef70a58a6c98 54 void GnssParser::powerOff(void)
rob.meades@u-blox.com 1:ef70a58a6c98 55 {
rob.meades@u-blox.com 1:ef70a58a6c98 56 // set the GNSS into backup mode using the command RMX-LPREQ
rob.meades@u-blox.com 1:ef70a58a6c98 57 struct { unsigned long dur; unsigned long flags; } msg = {0/*endless*/,0/*backup*/};
rob.meades@u-blox.com 1:ef70a58a6c98 58 sendUbx(0x02, 0x41, &msg, sizeof(msg));
rob.meades@u-blox.com 1:ef70a58a6c98 59 }
rob.meades@u-blox.com 1:ef70a58a6c98 60
rob.meades@u-blox.com 1:ef70a58a6c98 61 void GnssParser::_powerOn(void)
rob.meades@u-blox.com 1:ef70a58a6c98 62 {
rob.meades@u-blox.com 1:ef70a58a6c98 63 // Power up and enable the module
RobMeades 2:b10ca4aa2e5e 64 if (_gnssPower != NULL) {
RobMeades 2:b10ca4aa2e5e 65 *_gnssPower = 1;
RobMeades 2:b10ca4aa2e5e 66 }
rob.meades@u-blox.com 1:ef70a58a6c98 67 wait_ms (1);
RobMeades 2:b10ca4aa2e5e 68 if (_gnssEnable != NULL) {
RobMeades 2:b10ca4aa2e5e 69 *_gnssEnable = 1;
RobMeades 2:b10ca4aa2e5e 70 }
rob.meades@u-blox.com 1:ef70a58a6c98 71 wait_ms (1);
rob.meades@u-blox.com 1:ef70a58a6c98 72 }
rob.meades@u-blox.com 1:ef70a58a6c98 73
rob.meades@u-blox.com 1:ef70a58a6c98 74 int GnssParser::_getMessage(Pipe<char>* pipe, char* buf, int len)
rob.meades@u-blox.com 1:ef70a58a6c98 75 {
rob.meades@u-blox.com 1:ef70a58a6c98 76 int unkn = 0;
rob.meades@u-blox.com 1:ef70a58a6c98 77 int sz = pipe->size();
rob.meades@u-blox.com 1:ef70a58a6c98 78 int fr = pipe->free();
rob.meades@u-blox.com 1:ef70a58a6c98 79 if (len > sz)
rob.meades@u-blox.com 1:ef70a58a6c98 80 len = sz;
rob.meades@u-blox.com 1:ef70a58a6c98 81 while (len > 0)
rob.meades@u-blox.com 1:ef70a58a6c98 82 {
rob.meades@u-blox.com 1:ef70a58a6c98 83 // NMEA protocol
rob.meades@u-blox.com 1:ef70a58a6c98 84 pipe->set(unkn);
rob.meades@u-blox.com 1:ef70a58a6c98 85 int nmea = _parseNmea(pipe,len);
rob.meades@u-blox.com 1:ef70a58a6c98 86 if ((nmea != NOT_FOUND) && (unkn > 0))
rob.meades@u-blox.com 1:ef70a58a6c98 87 return UNKNOWN | pipe->get(buf,unkn);
rob.meades@u-blox.com 1:ef70a58a6c98 88 if (nmea == WAIT && fr)
rob.meades@u-blox.com 1:ef70a58a6c98 89 return WAIT;
rob.meades@u-blox.com 1:ef70a58a6c98 90 if (nmea > 0)
rob.meades@u-blox.com 1:ef70a58a6c98 91 return NMEA | pipe->get(buf,nmea);
rob.meades@u-blox.com 1:ef70a58a6c98 92 // UBX protocol
rob.meades@u-blox.com 1:ef70a58a6c98 93
rob.meades@u-blox.com 1:ef70a58a6c98 94 pipe->set(unkn);
rob.meades@u-blox.com 1:ef70a58a6c98 95 int ubx = _parseUbx(pipe,len);
rob.meades@u-blox.com 1:ef70a58a6c98 96 if ((ubx != NOT_FOUND) && (unkn > 0))
rob.meades@u-blox.com 1:ef70a58a6c98 97 return UNKNOWN | pipe->get(buf,unkn);
rob.meades@u-blox.com 1:ef70a58a6c98 98 if (ubx == WAIT && fr)
rob.meades@u-blox.com 1:ef70a58a6c98 99 return WAIT;
rob.meades@u-blox.com 1:ef70a58a6c98 100 if (ubx > 0)
rob.meades@u-blox.com 1:ef70a58a6c98 101 return UBX | pipe->get(buf,ubx);
rob.meades@u-blox.com 1:ef70a58a6c98 102
rob.meades@u-blox.com 1:ef70a58a6c98 103 // UNKNOWN
rob.meades@u-blox.com 1:ef70a58a6c98 104 unkn ++;
rob.meades@u-blox.com 1:ef70a58a6c98 105 len--;
rob.meades@u-blox.com 1:ef70a58a6c98 106 }
rob.meades@u-blox.com 1:ef70a58a6c98 107 if (unkn > 0)
rob.meades@u-blox.com 1:ef70a58a6c98 108 return UNKNOWN | pipe->get(buf,unkn);
rob.meades@u-blox.com 1:ef70a58a6c98 109 return WAIT;
rob.meades@u-blox.com 1:ef70a58a6c98 110 }
rob.meades@u-blox.com 1:ef70a58a6c98 111
rob.meades@u-blox.com 1:ef70a58a6c98 112 int GnssParser::_parseNmea(Pipe<char>* pipe, int len)
rob.meades@u-blox.com 1:ef70a58a6c98 113 {
rob.meades@u-blox.com 1:ef70a58a6c98 114 int o = 0;
rob.meades@u-blox.com 1:ef70a58a6c98 115 int c = 0;
rob.meades@u-blox.com 1:ef70a58a6c98 116 char ch;
rob.meades@u-blox.com 1:ef70a58a6c98 117 if (++o > len) return WAIT;
rob.meades@u-blox.com 1:ef70a58a6c98 118 if ('$' != pipe->next()) return NOT_FOUND;
rob.meades@u-blox.com 1:ef70a58a6c98 119 // this needs to be extended by crc checking
rob.meades@u-blox.com 1:ef70a58a6c98 120 for (;;)
rob.meades@u-blox.com 1:ef70a58a6c98 121 {
rob.meades@u-blox.com 1:ef70a58a6c98 122 if (++o > len) return WAIT;
rob.meades@u-blox.com 1:ef70a58a6c98 123 ch = pipe->next();
rob.meades@u-blox.com 1:ef70a58a6c98 124 if ('*' == ch) break; // crc delimiter
rob.meades@u-blox.com 1:ef70a58a6c98 125 if (!isprint(ch)) return NOT_FOUND;
rob.meades@u-blox.com 1:ef70a58a6c98 126 c ^= ch;
rob.meades@u-blox.com 1:ef70a58a6c98 127 }
rob.meades@u-blox.com 1:ef70a58a6c98 128 if (++o > len) return WAIT;
rob.meades@u-blox.com 1:ef70a58a6c98 129 ch = _toHex[(c >> 4) & 0xF]; // high nibble
rob.meades@u-blox.com 1:ef70a58a6c98 130 if (ch != pipe->next()) return NOT_FOUND;
rob.meades@u-blox.com 1:ef70a58a6c98 131 if (++o > len) return WAIT;
rob.meades@u-blox.com 1:ef70a58a6c98 132 ch = _toHex[(c >> 0) & 0xF]; // low nibble
rob.meades@u-blox.com 1:ef70a58a6c98 133 if (ch != pipe->next()) return NOT_FOUND;
rob.meades@u-blox.com 1:ef70a58a6c98 134 if (++o > len) return WAIT;
rob.meades@u-blox.com 1:ef70a58a6c98 135 if ('\r' != pipe->next()) return NOT_FOUND;
rob.meades@u-blox.com 1:ef70a58a6c98 136 if (++o > len) return WAIT;
rob.meades@u-blox.com 1:ef70a58a6c98 137 if ('\n' != pipe->next()) return NOT_FOUND;
rob.meades@u-blox.com 1:ef70a58a6c98 138 return o;
rob.meades@u-blox.com 1:ef70a58a6c98 139 }
rob.meades@u-blox.com 1:ef70a58a6c98 140
rob.meades@u-blox.com 1:ef70a58a6c98 141 int GnssParser::_parseUbx(Pipe<char>* pipe, int l)
rob.meades@u-blox.com 1:ef70a58a6c98 142 {
rob.meades@u-blox.com 1:ef70a58a6c98 143 int o = 0;
rob.meades@u-blox.com 1:ef70a58a6c98 144 if (++o > l) return WAIT;
rob.meades@u-blox.com 1:ef70a58a6c98 145 if ('\xB5' != pipe->next()) return NOT_FOUND;
rob.meades@u-blox.com 1:ef70a58a6c98 146 if (++o > l) return WAIT;
rob.meades@u-blox.com 1:ef70a58a6c98 147 if ('\x62' != pipe->next()) return NOT_FOUND;
rob.meades@u-blox.com 1:ef70a58a6c98 148 o += 4;
rob.meades@u-blox.com 1:ef70a58a6c98 149 if (o > l) return WAIT;
rob.meades@u-blox.com 1:ef70a58a6c98 150 int i,j,ca,cb;
rob.meades@u-blox.com 1:ef70a58a6c98 151 i = pipe->next(); ca = i; cb = ca; // cls
rob.meades@u-blox.com 1:ef70a58a6c98 152 i = pipe->next(); ca += i; cb += ca; // id
rob.meades@u-blox.com 1:ef70a58a6c98 153 i = pipe->next(); ca += i; cb += ca; // len_lsb
rob.meades@u-blox.com 1:ef70a58a6c98 154 j = pipe->next(); ca += j; cb += ca; // len_msb
rob.meades@u-blox.com 1:ef70a58a6c98 155 j = i + (j << 8);
rob.meades@u-blox.com 1:ef70a58a6c98 156 while (j--)
rob.meades@u-blox.com 1:ef70a58a6c98 157 {
rob.meades@u-blox.com 1:ef70a58a6c98 158 if (++o > l) return WAIT;
rob.meades@u-blox.com 1:ef70a58a6c98 159 i = pipe->next();
rob.meades@u-blox.com 1:ef70a58a6c98 160 ca += i;
rob.meades@u-blox.com 1:ef70a58a6c98 161 cb += ca;
rob.meades@u-blox.com 1:ef70a58a6c98 162 }
rob.meades@u-blox.com 1:ef70a58a6c98 163 ca &= 0xFF; cb &= 0xFF;
rob.meades@u-blox.com 1:ef70a58a6c98 164 if (++o > l) return WAIT;
rob.meades@u-blox.com 1:ef70a58a6c98 165 if (ca != pipe->next()) return NOT_FOUND;
rob.meades@u-blox.com 1:ef70a58a6c98 166 if (++o > l) return WAIT;
rob.meades@u-blox.com 1:ef70a58a6c98 167 if (cb != pipe->next()) return NOT_FOUND;
rob.meades@u-blox.com 1:ef70a58a6c98 168 return o;
rob.meades@u-blox.com 1:ef70a58a6c98 169 }
rob.meades@u-blox.com 1:ef70a58a6c98 170
rob.meades@u-blox.com 1:ef70a58a6c98 171 int GnssParser::send(const char* buf, int len)
rob.meades@u-blox.com 1:ef70a58a6c98 172 {
rob.meades@u-blox.com 1:ef70a58a6c98 173 return _send(buf, len);
rob.meades@u-blox.com 1:ef70a58a6c98 174 }
rob.meades@u-blox.com 1:ef70a58a6c98 175
rob.meades@u-blox.com 1:ef70a58a6c98 176 int GnssParser::sendNmea(const char* buf, int len)
rob.meades@u-blox.com 1:ef70a58a6c98 177 {
rob.meades@u-blox.com 1:ef70a58a6c98 178 char head[1] = { '$' };
rob.meades@u-blox.com 1:ef70a58a6c98 179 char tail[5] = { '*', 0x00/*crc_high*/, 0x00/*crc_low*/, '\r', '\n' };
rob.meades@u-blox.com 1:ef70a58a6c98 180 int i;
rob.meades@u-blox.com 1:ef70a58a6c98 181 int crc = 0;
rob.meades@u-blox.com 1:ef70a58a6c98 182 for (i = 0; i < len; i ++)
rob.meades@u-blox.com 1:ef70a58a6c98 183 crc ^= *buf++;
rob.meades@u-blox.com 1:ef70a58a6c98 184 i = _send(head, sizeof(head));
rob.meades@u-blox.com 1:ef70a58a6c98 185 i += _send(buf, len);
rob.meades@u-blox.com 1:ef70a58a6c98 186 tail[1] = _toHex[(crc > 4) & 0xF0];
rob.meades@u-blox.com 1:ef70a58a6c98 187 tail[2] = _toHex[(crc > 0) & 0x0F];
rob.meades@u-blox.com 1:ef70a58a6c98 188 i += _send(tail, sizeof(tail));
rob.meades@u-blox.com 1:ef70a58a6c98 189 return i;
rob.meades@u-blox.com 1:ef70a58a6c98 190 }
rob.meades@u-blox.com 1:ef70a58a6c98 191
rob.meades@u-blox.com 1:ef70a58a6c98 192 int GnssParser::sendUbx(unsigned char cls, unsigned char id, const void* buf /*= NULL*/, int len /*= 0*/)
rob.meades@u-blox.com 1:ef70a58a6c98 193 {
rob.meades@u-blox.com 1:ef70a58a6c98 194 char head[6] = { 0xB5, 0x62, cls, id, (char) len, (char) (len >> 8)};
rob.meades@u-blox.com 1:ef70a58a6c98 195 char crc[2];
rob.meades@u-blox.com 1:ef70a58a6c98 196 int i;
rob.meades@u-blox.com 1:ef70a58a6c98 197 int ca = 0;
rob.meades@u-blox.com 1:ef70a58a6c98 198 int cb = 0;
rob.meades@u-blox.com 1:ef70a58a6c98 199 for (i = 2; i < 6; i ++)
rob.meades@u-blox.com 1:ef70a58a6c98 200 {
rob.meades@u-blox.com 1:ef70a58a6c98 201 ca += head[i];
rob.meades@u-blox.com 1:ef70a58a6c98 202 cb += ca;
rob.meades@u-blox.com 1:ef70a58a6c98 203 }
rob.meades@u-blox.com 1:ef70a58a6c98 204 for (i = 0; i < len; i ++)
rob.meades@u-blox.com 1:ef70a58a6c98 205 {
rob.meades@u-blox.com 1:ef70a58a6c98 206 ca += ((char*)buf)[i];
rob.meades@u-blox.com 1:ef70a58a6c98 207 cb += ca;
rob.meades@u-blox.com 1:ef70a58a6c98 208 }
rob.meades@u-blox.com 1:ef70a58a6c98 209 i = _send(head, sizeof(head));
rob.meades@u-blox.com 1:ef70a58a6c98 210 i += _send(buf, len);
rob.meades@u-blox.com 1:ef70a58a6c98 211 crc[0] = ca & 0xFF;
rob.meades@u-blox.com 1:ef70a58a6c98 212 crc[1] = cb & 0xFF;
rob.meades@u-blox.com 1:ef70a58a6c98 213 i += _send(crc, sizeof(crc));
rob.meades@u-blox.com 1:ef70a58a6c98 214 return i;
rob.meades@u-blox.com 1:ef70a58a6c98 215 }
rob.meades@u-blox.com 1:ef70a58a6c98 216
rob.meades@u-blox.com 1:ef70a58a6c98 217 const char* GnssParser::findNmeaItemPos(int ix, const char* start, const char* end)
rob.meades@u-blox.com 1:ef70a58a6c98 218 {
rob.meades@u-blox.com 1:ef70a58a6c98 219 // find the start
rob.meades@u-blox.com 1:ef70a58a6c98 220 for (; (start < end) && (ix > 0); start ++)
rob.meades@u-blox.com 1:ef70a58a6c98 221 {
rob.meades@u-blox.com 1:ef70a58a6c98 222 if (*start == ',')
rob.meades@u-blox.com 1:ef70a58a6c98 223 ix --;
rob.meades@u-blox.com 1:ef70a58a6c98 224 }
rob.meades@u-blox.com 1:ef70a58a6c98 225 // found and check bounds
rob.meades@u-blox.com 1:ef70a58a6c98 226 if ((ix == 0) && (start < end) &&
rob.meades@u-blox.com 1:ef70a58a6c98 227 (*start != ',') && (*start != '*') && (*start != '\r') && (*start != '\n'))
rob.meades@u-blox.com 1:ef70a58a6c98 228 return start;
rob.meades@u-blox.com 1:ef70a58a6c98 229 else
rob.meades@u-blox.com 1:ef70a58a6c98 230 return NULL;
rob.meades@u-blox.com 1:ef70a58a6c98 231 }
rob.meades@u-blox.com 1:ef70a58a6c98 232
rob.meades@u-blox.com 1:ef70a58a6c98 233 bool GnssParser::getNmeaItem(int ix, char* buf, int len, double& val)
rob.meades@u-blox.com 1:ef70a58a6c98 234 {
rob.meades@u-blox.com 1:ef70a58a6c98 235 char* end = &buf[len];
rob.meades@u-blox.com 1:ef70a58a6c98 236 const char* pos = findNmeaItemPos(ix, buf, end);
rob.meades@u-blox.com 1:ef70a58a6c98 237 // find the start
rob.meades@u-blox.com 1:ef70a58a6c98 238 if (!pos)
rob.meades@u-blox.com 1:ef70a58a6c98 239 return false;
rob.meades@u-blox.com 1:ef70a58a6c98 240 val = strtod(pos, &end);
rob.meades@u-blox.com 1:ef70a58a6c98 241 // restore the last character
rob.meades@u-blox.com 1:ef70a58a6c98 242 return (end > pos);
rob.meades@u-blox.com 1:ef70a58a6c98 243 }
rob.meades@u-blox.com 1:ef70a58a6c98 244
rob.meades@u-blox.com 1:ef70a58a6c98 245 bool GnssParser::getNmeaItem(int ix, char* buf, int len, int& val, int base /*=10*/)
rob.meades@u-blox.com 1:ef70a58a6c98 246 {
rob.meades@u-blox.com 1:ef70a58a6c98 247 char* end = &buf[len];
rob.meades@u-blox.com 1:ef70a58a6c98 248 const char* pos = findNmeaItemPos(ix, buf, end);
rob.meades@u-blox.com 1:ef70a58a6c98 249 // find the start
rob.meades@u-blox.com 1:ef70a58a6c98 250 if (!pos)
rob.meades@u-blox.com 1:ef70a58a6c98 251 return false;
rob.meades@u-blox.com 1:ef70a58a6c98 252 val = (int)strtol(pos, &end, base);
rob.meades@u-blox.com 1:ef70a58a6c98 253 return (end > pos);
rob.meades@u-blox.com 1:ef70a58a6c98 254 }
rob.meades@u-blox.com 1:ef70a58a6c98 255
rob.meades@u-blox.com 1:ef70a58a6c98 256 bool GnssParser::getNmeaItem(int ix, char* buf, int len, char& val)
rob.meades@u-blox.com 1:ef70a58a6c98 257 {
rob.meades@u-blox.com 1:ef70a58a6c98 258 const char* end = &buf[len];
rob.meades@u-blox.com 1:ef70a58a6c98 259 const char* pos = findNmeaItemPos(ix, buf, end);
rob.meades@u-blox.com 1:ef70a58a6c98 260 // find the start
rob.meades@u-blox.com 1:ef70a58a6c98 261 if (!pos)
rob.meades@u-blox.com 1:ef70a58a6c98 262 return false;
rob.meades@u-blox.com 1:ef70a58a6c98 263 // skip leading spaces
rob.meades@u-blox.com 1:ef70a58a6c98 264 while ((pos < end) && isspace(*pos))
rob.meades@u-blox.com 1:ef70a58a6c98 265 pos++;
rob.meades@u-blox.com 1:ef70a58a6c98 266 // check bound
rob.meades@u-blox.com 1:ef70a58a6c98 267 if ((pos < end) &&
rob.meades@u-blox.com 1:ef70a58a6c98 268 (*pos != ',') && (*pos != '*') && (*pos != '\r') && (*pos != '\n'))
rob.meades@u-blox.com 1:ef70a58a6c98 269 {
rob.meades@u-blox.com 1:ef70a58a6c98 270 val = *pos;
rob.meades@u-blox.com 1:ef70a58a6c98 271 return true;
rob.meades@u-blox.com 1:ef70a58a6c98 272 }
rob.meades@u-blox.com 1:ef70a58a6c98 273 return false;
rob.meades@u-blox.com 1:ef70a58a6c98 274 }
rob.meades@u-blox.com 1:ef70a58a6c98 275
rob.meades@u-blox.com 1:ef70a58a6c98 276 bool GnssParser::getNmeaAngle(int ix, char* buf, int len, double& val)
rob.meades@u-blox.com 1:ef70a58a6c98 277 {
rob.meades@u-blox.com 1:ef70a58a6c98 278 char ch;
rob.meades@u-blox.com 1:ef70a58a6c98 279 if (getNmeaItem(ix,buf,len,val) && getNmeaItem(ix+1,buf,len,ch) &&
rob.meades@u-blox.com 1:ef70a58a6c98 280 ((ch == 'S') || (ch == 'N') || (ch == 'E') || (ch == 'W')))
rob.meades@u-blox.com 1:ef70a58a6c98 281 {
rob.meades@u-blox.com 1:ef70a58a6c98 282 val *= 0.01;
rob.meades@u-blox.com 1:ef70a58a6c98 283 int i = (int)val;
rob.meades@u-blox.com 1:ef70a58a6c98 284 val = (val - i) / 0.6 + i;
rob.meades@u-blox.com 1:ef70a58a6c98 285 if (ch == 'S' || ch == 'W')
rob.meades@u-blox.com 1:ef70a58a6c98 286 val = -val;
rob.meades@u-blox.com 1:ef70a58a6c98 287 return true;
rob.meades@u-blox.com 1:ef70a58a6c98 288 }
rob.meades@u-blox.com 1:ef70a58a6c98 289 return false;
rob.meades@u-blox.com 1:ef70a58a6c98 290 }
rob.meades@u-blox.com 1:ef70a58a6c98 291
rob.meades@u-blox.com 1:ef70a58a6c98 292 const char GnssParser::_toHex[] = { '0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F' };
rob.meades@u-blox.com 1:ef70a58a6c98 293
rob.meades@u-blox.com 1:ef70a58a6c98 294 // ----------------------------------------------------------------
rob.meades@u-blox.com 1:ef70a58a6c98 295 // Serial Implementation
rob.meades@u-blox.com 1:ef70a58a6c98 296 // ----------------------------------------------------------------
rob.meades@u-blox.com 1:ef70a58a6c98 297
rob.meades@u-blox.com 1:ef70a58a6c98 298 GnssSerial::GnssSerial(PinName tx /*= GNSSTXD */, PinName rx /*= GNSSRXD */, int baudrate /*= GNSSBAUD */,
rob.meades@u-blox.com 1:ef70a58a6c98 299 int rxSize /*= 256 */, int txSize /*= 128 */) :
rob.meades@u-blox.com 1:ef70a58a6c98 300 SerialPipe(tx, rx, baudrate, rxSize, txSize)
rob.meades@u-blox.com 1:ef70a58a6c98 301 {
rob.meades@u-blox.com 1:ef70a58a6c98 302 baud(baudrate);
rob.meades@u-blox.com 1:ef70a58a6c98 303 }
rob.meades@u-blox.com 1:ef70a58a6c98 304
rob.meades@u-blox.com 1:ef70a58a6c98 305 GnssSerial::~GnssSerial(void)
rob.meades@u-blox.com 1:ef70a58a6c98 306 {
rob.meades@u-blox.com 1:ef70a58a6c98 307 powerOff();
rob.meades@u-blox.com 1:ef70a58a6c98 308 }
rob.meades@u-blox.com 1:ef70a58a6c98 309
rob.meades@u-blox.com 1:ef70a58a6c98 310 bool GnssSerial::init(PinName pn)
rob.meades@u-blox.com 1:ef70a58a6c98 311 {
rob.meades@u-blox.com 1:ef70a58a6c98 312 // Power up and enable the module
rob.meades@u-blox.com 1:ef70a58a6c98 313 _powerOn();
rob.meades@u-blox.com 1:ef70a58a6c98 314
rob.meades@u-blox.com 1:ef70a58a6c98 315 // send a byte to wakup the device again
rob.meades@u-blox.com 1:ef70a58a6c98 316 putc(0xFF);
rob.meades@u-blox.com 1:ef70a58a6c98 317 // wait until we get some bytes
rob.meades@u-blox.com 1:ef70a58a6c98 318 int size = _pipeRx.size();
rob.meades@u-blox.com 1:ef70a58a6c98 319 Timer timer;
rob.meades@u-blox.com 1:ef70a58a6c98 320 timer.start();
rob.meades@u-blox.com 1:ef70a58a6c98 321 while ((100 > timer.read_ms()) && (size == _pipeRx.size()))
rob.meades@u-blox.com 1:ef70a58a6c98 322 /* nothing / just wait */;
rob.meades@u-blox.com 1:ef70a58a6c98 323 return (size != _pipeRx.size());
rob.meades@u-blox.com 1:ef70a58a6c98 324 }
rob.meades@u-blox.com 1:ef70a58a6c98 325
rob.meades@u-blox.com 1:ef70a58a6c98 326 int GnssSerial::getMessage(char* buf, int len)
rob.meades@u-blox.com 1:ef70a58a6c98 327 {
rob.meades@u-blox.com 1:ef70a58a6c98 328 return _getMessage(&_pipeRx, buf, len);
rob.meades@u-blox.com 1:ef70a58a6c98 329 }
rob.meades@u-blox.com 1:ef70a58a6c98 330
rob.meades@u-blox.com 1:ef70a58a6c98 331 int GnssSerial::_send(const void* buf, int len)
rob.meades@u-blox.com 1:ef70a58a6c98 332 {
rob.meades@u-blox.com 1:ef70a58a6c98 333 return put((const char*)buf, len, true/*=blocking*/);
rob.meades@u-blox.com 1:ef70a58a6c98 334 }
rob.meades@u-blox.com 1:ef70a58a6c98 335
rob.meades@u-blox.com 1:ef70a58a6c98 336 // ----------------------------------------------------------------
rob.meades@u-blox.com 1:ef70a58a6c98 337 // I2C Implementation
rob.meades@u-blox.com 1:ef70a58a6c98 338 // ----------------------------------------------------------------
rob.meades@u-blox.com 1:ef70a58a6c98 339
rob.meades@u-blox.com 1:ef70a58a6c98 340 GnssI2C::GnssI2C(PinName sda /*= NC */, PinName scl /*= NC */,
rob.meades@u-blox.com 1:ef70a58a6c98 341 unsigned char i2cAdr /*= (66<<1) */, int rxSize /*= 256 */) :
rob.meades@u-blox.com 1:ef70a58a6c98 342 I2C(sda,scl),
rob.meades@u-blox.com 1:ef70a58a6c98 343 _pipe(rxSize),
rob.meades@u-blox.com 1:ef70a58a6c98 344 _i2cAdr(i2cAdr)
rob.meades@u-blox.com 1:ef70a58a6c98 345 {
rob.meades@u-blox.com 1:ef70a58a6c98 346 frequency(100000);
rob.meades@u-blox.com 1:ef70a58a6c98 347 }
rob.meades@u-blox.com 1:ef70a58a6c98 348
rob.meades@u-blox.com 1:ef70a58a6c98 349 GnssI2C::~GnssI2C(void)
rob.meades@u-blox.com 1:ef70a58a6c98 350 {
rob.meades@u-blox.com 1:ef70a58a6c98 351 powerOff();
rob.meades@u-blox.com 1:ef70a58a6c98 352 }
rob.meades@u-blox.com 1:ef70a58a6c98 353
rob.meades@u-blox.com 1:ef70a58a6c98 354 bool GnssI2C::init(PinName pn)
rob.meades@u-blox.com 1:ef70a58a6c98 355 {
rob.meades@u-blox.com 1:ef70a58a6c98 356 // Power up and enable the module
rob.meades@u-blox.com 1:ef70a58a6c98 357 _powerOn();
rob.meades@u-blox.com 1:ef70a58a6c98 358
rob.meades@u-blox.com 1:ef70a58a6c98 359 if (pn != NC) {
rob.meades@u-blox.com 1:ef70a58a6c98 360 DigitalOut pin(pn, 0);
rob.meades@u-blox.com 1:ef70a58a6c98 361 ::wait_us(1);
rob.meades@u-blox.com 1:ef70a58a6c98 362 pin = 1;
rob.meades@u-blox.com 1:ef70a58a6c98 363 ::wait_ms(100);
rob.meades@u-blox.com 1:ef70a58a6c98 364 }
rob.meades@u-blox.com 1:ef70a58a6c98 365 return !I2C::write(_i2cAdr,&REGSTREAM,sizeof(REGSTREAM));
rob.meades@u-blox.com 1:ef70a58a6c98 366 }
rob.meades@u-blox.com 1:ef70a58a6c98 367
rob.meades@u-blox.com 1:ef70a58a6c98 368 int GnssI2C::getMessage(char* buf, int len)
rob.meades@u-blox.com 1:ef70a58a6c98 369 {
rob.meades@u-blox.com 1:ef70a58a6c98 370 // fill the pipe
rob.meades@u-blox.com 1:ef70a58a6c98 371 int sz = _pipe.free();
rob.meades@u-blox.com 1:ef70a58a6c98 372 if (sz)
rob.meades@u-blox.com 1:ef70a58a6c98 373 sz = _get(buf, sz);
rob.meades@u-blox.com 1:ef70a58a6c98 374 if (sz)
rob.meades@u-blox.com 1:ef70a58a6c98 375 _pipe.put(buf, sz);
rob.meades@u-blox.com 1:ef70a58a6c98 376 // now parse it
rob.meades@u-blox.com 1:ef70a58a6c98 377 return _getMessage(&_pipe, buf, len);
rob.meades@u-blox.com 1:ef70a58a6c98 378 }
rob.meades@u-blox.com 1:ef70a58a6c98 379
rob.meades@u-blox.com 1:ef70a58a6c98 380 int GnssI2C::send(const char* buf, int len)
rob.meades@u-blox.com 1:ef70a58a6c98 381 {
rob.meades@u-blox.com 1:ef70a58a6c98 382 int sent = 0;
rob.meades@u-blox.com 1:ef70a58a6c98 383 if (len)
rob.meades@u-blox.com 1:ef70a58a6c98 384 {
rob.meades@u-blox.com 1:ef70a58a6c98 385 if (!I2C::write(_i2cAdr,&REGSTREAM,sizeof(REGSTREAM),true))
rob.meades@u-blox.com 1:ef70a58a6c98 386 sent = send(buf, len);
rob.meades@u-blox.com 1:ef70a58a6c98 387 stop();
rob.meades@u-blox.com 1:ef70a58a6c98 388 }
rob.meades@u-blox.com 1:ef70a58a6c98 389 return sent;
rob.meades@u-blox.com 1:ef70a58a6c98 390 }
rob.meades@u-blox.com 1:ef70a58a6c98 391
rob.meades@u-blox.com 1:ef70a58a6c98 392 int GnssI2C::sendNmea(const char* buf, int len)
rob.meades@u-blox.com 1:ef70a58a6c98 393 {
rob.meades@u-blox.com 1:ef70a58a6c98 394 int sent = 0;
rob.meades@u-blox.com 1:ef70a58a6c98 395 if (!I2C::write(_i2cAdr,&REGSTREAM,sizeof(REGSTREAM),true))
rob.meades@u-blox.com 1:ef70a58a6c98 396 sent = GnssParser::sendNmea(buf, len);
rob.meades@u-blox.com 1:ef70a58a6c98 397 stop();
rob.meades@u-blox.com 1:ef70a58a6c98 398 return sent;
rob.meades@u-blox.com 1:ef70a58a6c98 399 }
rob.meades@u-blox.com 1:ef70a58a6c98 400
rob.meades@u-blox.com 1:ef70a58a6c98 401 int GnssI2C::sendUbx(unsigned char cls, unsigned char id, const void* buf, int len)
rob.meades@u-blox.com 1:ef70a58a6c98 402 {
rob.meades@u-blox.com 1:ef70a58a6c98 403 int sent = 0;
rob.meades@u-blox.com 1:ef70a58a6c98 404 if (!I2C::write(_i2cAdr,&REGSTREAM,sizeof(REGSTREAM),true))
rob.meades@u-blox.com 1:ef70a58a6c98 405 sent = GnssParser::sendUbx(cls, id, buf, len);
rob.meades@u-blox.com 1:ef70a58a6c98 406 I2C::stop();
rob.meades@u-blox.com 1:ef70a58a6c98 407 return sent;
rob.meades@u-blox.com 1:ef70a58a6c98 408 }
rob.meades@u-blox.com 1:ef70a58a6c98 409
rob.meades@u-blox.com 1:ef70a58a6c98 410 int GnssI2C::_get(char* buf, int len)
rob.meades@u-blox.com 1:ef70a58a6c98 411 {
rob.meades@u-blox.com 1:ef70a58a6c98 412 int read = 0;
rob.meades@u-blox.com 1:ef70a58a6c98 413 unsigned char sz[2] = {0,0};
rob.meades@u-blox.com 1:ef70a58a6c98 414 if (!I2C::write(_i2cAdr,&REGLEN,sizeof(REGLEN),true) &&
rob.meades@u-blox.com 1:ef70a58a6c98 415 !I2C::read(_i2cAdr,(char*)sz,sizeof(sz)))
rob.meades@u-blox.com 1:ef70a58a6c98 416 {
rob.meades@u-blox.com 1:ef70a58a6c98 417 int size = 256 * (int)sz[0] + sz[1];
rob.meades@u-blox.com 1:ef70a58a6c98 418 if (size > len)
rob.meades@u-blox.com 1:ef70a58a6c98 419 size = len;
rob.meades@u-blox.com 1:ef70a58a6c98 420 if (size > 0)
rob.meades@u-blox.com 1:ef70a58a6c98 421 {
rob.meades@u-blox.com 1:ef70a58a6c98 422 if (!I2C::write(_i2cAdr,&REGSTREAM,sizeof(REGSTREAM),true) &&
rob.meades@u-blox.com 1:ef70a58a6c98 423 !I2C::read(_i2cAdr,buf,size)) {
rob.meades@u-blox.com 1:ef70a58a6c98 424 read = size;
rob.meades@u-blox.com 1:ef70a58a6c98 425 }
rob.meades@u-blox.com 1:ef70a58a6c98 426 }
rob.meades@u-blox.com 1:ef70a58a6c98 427 }
rob.meades@u-blox.com 1:ef70a58a6c98 428 return read;
rob.meades@u-blox.com 1:ef70a58a6c98 429 }
rob.meades@u-blox.com 1:ef70a58a6c98 430
rob.meades@u-blox.com 1:ef70a58a6c98 431 int GnssI2C::_send(const void* buf, int len)
rob.meades@u-blox.com 1:ef70a58a6c98 432 {
rob.meades@u-blox.com 1:ef70a58a6c98 433 return !I2C::write(_i2cAdr,(const char*)buf,len,true) ? len : 0;
rob.meades@u-blox.com 1:ef70a58a6c98 434 }
rob.meades@u-blox.com 1:ef70a58a6c98 435
rob.meades@u-blox.com 1:ef70a58a6c98 436 const char GnssI2C::REGLEN = 0xFD;
rob.meades@u-blox.com 1:ef70a58a6c98 437 const char GnssI2C::REGSTREAM = 0xFF;
rob.meades@u-blox.com 1:ef70a58a6c98 438
rob.meades@u-blox.com 1:ef70a58a6c98 439 // End Of File