Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Fork of gnss by
gnss.cpp@6:56eda66d585b, 2017-06-14 (annotated)
- Committer:
- rob.meades@u-blox.com
- Date:
- Wed Jun 14 20:44:42 2017 +0100
- Revision:
- 6:56eda66d585b
- Parent:
- 5:af4baf3c67f3
- Child:
- 7:720841961804
Test passing on C027 and C030 platforms.
Who changed what in which revision?
User | Revision | Line number | New 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 | { |
RobMeades | 3:2a1cd49ead85 | 28 | // Create the enable pin but set everything to disabled |
RobMeades | 2:b10ca4aa2e5e | 29 | _gnssEnable = NULL; |
RobMeades | 2:b10ca4aa2e5e | 30 | |
rob.meades@u-blox.com | 4:82308d600690 | 31 | #ifdef TARGET_UBLOX_C030 |
rob.meades@u-blox.com | 1:ef70a58a6c98 | 32 | _gnssEnable = new DigitalInOut(GNSSEN, PIN_OUTPUT, PushPullNoPull, 0); |
RobMeades | 5:af4baf3c67f3 | 33 | #else |
RobMeades | 5:af4baf3c67f3 | 34 | _gnssEnable = new DigitalInOut(GNSSEN, PIN_OUTPUT, PullNone, 1); |
RobMeades | 2:b10ca4aa2e5e | 35 | #endif |
rob.meades@u-blox.com | 1:ef70a58a6c98 | 36 | } |
rob.meades@u-blox.com | 1:ef70a58a6c98 | 37 | |
rob.meades@u-blox.com | 1:ef70a58a6c98 | 38 | GnssParser::~GnssParser(void) |
rob.meades@u-blox.com | 1:ef70a58a6c98 | 39 | { |
RobMeades | 2:b10ca4aa2e5e | 40 | if (_gnssEnable != NULL) { |
RobMeades | 2:b10ca4aa2e5e | 41 | *_gnssEnable = 0; |
RobMeades | 2:b10ca4aa2e5e | 42 | delete _gnssEnable; |
RobMeades | 2:b10ca4aa2e5e | 43 | } |
rob.meades@u-blox.com | 1:ef70a58a6c98 | 44 | } |
rob.meades@u-blox.com | 1:ef70a58a6c98 | 45 | |
rob.meades@u-blox.com | 1:ef70a58a6c98 | 46 | void GnssParser::powerOff(void) |
rob.meades@u-blox.com | 1:ef70a58a6c98 | 47 | { |
rob.meades@u-blox.com | 6:56eda66d585b | 48 | // Set the GNSS into backup mode using the command RMX-LPREQ |
rob.meades@u-blox.com | 1:ef70a58a6c98 | 49 | struct { unsigned long dur; unsigned long flags; } msg = {0/*endless*/,0/*backup*/}; |
rob.meades@u-blox.com | 1:ef70a58a6c98 | 50 | sendUbx(0x02, 0x41, &msg, sizeof(msg)); |
rob.meades@u-blox.com | 1:ef70a58a6c98 | 51 | } |
rob.meades@u-blox.com | 1:ef70a58a6c98 | 52 | |
rob.meades@u-blox.com | 1:ef70a58a6c98 | 53 | void GnssParser::_powerOn(void) |
rob.meades@u-blox.com | 1:ef70a58a6c98 | 54 | { |
RobMeades | 2:b10ca4aa2e5e | 55 | if (_gnssEnable != NULL) { |
RobMeades | 2:b10ca4aa2e5e | 56 | *_gnssEnable = 1; |
RobMeades | 2:b10ca4aa2e5e | 57 | } |
rob.meades@u-blox.com | 1:ef70a58a6c98 | 58 | wait_ms (1); |
rob.meades@u-blox.com | 1:ef70a58a6c98 | 59 | } |
rob.meades@u-blox.com | 1:ef70a58a6c98 | 60 | |
rob.meades@u-blox.com | 1:ef70a58a6c98 | 61 | int GnssParser::_getMessage(Pipe<char>* pipe, char* buf, int len) |
rob.meades@u-blox.com | 1:ef70a58a6c98 | 62 | { |
rob.meades@u-blox.com | 1:ef70a58a6c98 | 63 | int unkn = 0; |
rob.meades@u-blox.com | 1:ef70a58a6c98 | 64 | int sz = pipe->size(); |
rob.meades@u-blox.com | 1:ef70a58a6c98 | 65 | int fr = pipe->free(); |
rob.meades@u-blox.com | 1:ef70a58a6c98 | 66 | if (len > sz) |
rob.meades@u-blox.com | 1:ef70a58a6c98 | 67 | len = sz; |
rob.meades@u-blox.com | 1:ef70a58a6c98 | 68 | while (len > 0) |
rob.meades@u-blox.com | 1:ef70a58a6c98 | 69 | { |
rob.meades@u-blox.com | 1:ef70a58a6c98 | 70 | // NMEA protocol |
rob.meades@u-blox.com | 1:ef70a58a6c98 | 71 | pipe->set(unkn); |
rob.meades@u-blox.com | 1:ef70a58a6c98 | 72 | int nmea = _parseNmea(pipe,len); |
rob.meades@u-blox.com | 1:ef70a58a6c98 | 73 | if ((nmea != NOT_FOUND) && (unkn > 0)) |
rob.meades@u-blox.com | 1:ef70a58a6c98 | 74 | return UNKNOWN | pipe->get(buf,unkn); |
rob.meades@u-blox.com | 1:ef70a58a6c98 | 75 | if (nmea == WAIT && fr) |
rob.meades@u-blox.com | 1:ef70a58a6c98 | 76 | return WAIT; |
rob.meades@u-blox.com | 1:ef70a58a6c98 | 77 | if (nmea > 0) |
rob.meades@u-blox.com | 1:ef70a58a6c98 | 78 | return NMEA | pipe->get(buf,nmea); |
rob.meades@u-blox.com | 1:ef70a58a6c98 | 79 | // UBX protocol |
rob.meades@u-blox.com | 1:ef70a58a6c98 | 80 | |
rob.meades@u-blox.com | 1:ef70a58a6c98 | 81 | pipe->set(unkn); |
rob.meades@u-blox.com | 1:ef70a58a6c98 | 82 | int ubx = _parseUbx(pipe,len); |
rob.meades@u-blox.com | 1:ef70a58a6c98 | 83 | if ((ubx != NOT_FOUND) && (unkn > 0)) |
rob.meades@u-blox.com | 1:ef70a58a6c98 | 84 | return UNKNOWN | pipe->get(buf,unkn); |
rob.meades@u-blox.com | 1:ef70a58a6c98 | 85 | if (ubx == WAIT && fr) |
rob.meades@u-blox.com | 1:ef70a58a6c98 | 86 | return WAIT; |
rob.meades@u-blox.com | 1:ef70a58a6c98 | 87 | if (ubx > 0) |
rob.meades@u-blox.com | 1:ef70a58a6c98 | 88 | return UBX | pipe->get(buf,ubx); |
rob.meades@u-blox.com | 1:ef70a58a6c98 | 89 | |
rob.meades@u-blox.com | 1:ef70a58a6c98 | 90 | // UNKNOWN |
rob.meades@u-blox.com | 1:ef70a58a6c98 | 91 | unkn ++; |
rob.meades@u-blox.com | 1:ef70a58a6c98 | 92 | len--; |
rob.meades@u-blox.com | 1:ef70a58a6c98 | 93 | } |
rob.meades@u-blox.com | 1:ef70a58a6c98 | 94 | if (unkn > 0) |
rob.meades@u-blox.com | 1:ef70a58a6c98 | 95 | return UNKNOWN | pipe->get(buf,unkn); |
rob.meades@u-blox.com | 1:ef70a58a6c98 | 96 | return WAIT; |
rob.meades@u-blox.com | 1:ef70a58a6c98 | 97 | } |
rob.meades@u-blox.com | 1:ef70a58a6c98 | 98 | |
rob.meades@u-blox.com | 1:ef70a58a6c98 | 99 | int GnssParser::_parseNmea(Pipe<char>* pipe, int len) |
rob.meades@u-blox.com | 1:ef70a58a6c98 | 100 | { |
rob.meades@u-blox.com | 1:ef70a58a6c98 | 101 | int o = 0; |
rob.meades@u-blox.com | 1:ef70a58a6c98 | 102 | int c = 0; |
rob.meades@u-blox.com | 1:ef70a58a6c98 | 103 | char ch; |
rob.meades@u-blox.com | 1:ef70a58a6c98 | 104 | if (++o > len) return WAIT; |
rob.meades@u-blox.com | 1:ef70a58a6c98 | 105 | if ('$' != pipe->next()) return NOT_FOUND; |
rob.meades@u-blox.com | 6:56eda66d585b | 106 | // This needs to be extended by crc checking |
rob.meades@u-blox.com | 1:ef70a58a6c98 | 107 | for (;;) |
rob.meades@u-blox.com | 1:ef70a58a6c98 | 108 | { |
rob.meades@u-blox.com | 1:ef70a58a6c98 | 109 | if (++o > len) return WAIT; |
rob.meades@u-blox.com | 1:ef70a58a6c98 | 110 | ch = pipe->next(); |
rob.meades@u-blox.com | 1:ef70a58a6c98 | 111 | if ('*' == ch) break; // crc delimiter |
rob.meades@u-blox.com | 1:ef70a58a6c98 | 112 | if (!isprint(ch)) return NOT_FOUND; |
rob.meades@u-blox.com | 1:ef70a58a6c98 | 113 | c ^= ch; |
rob.meades@u-blox.com | 1:ef70a58a6c98 | 114 | } |
rob.meades@u-blox.com | 1:ef70a58a6c98 | 115 | if (++o > len) return WAIT; |
rob.meades@u-blox.com | 1:ef70a58a6c98 | 116 | ch = _toHex[(c >> 4) & 0xF]; // high nibble |
rob.meades@u-blox.com | 1:ef70a58a6c98 | 117 | if (ch != pipe->next()) return NOT_FOUND; |
rob.meades@u-blox.com | 1:ef70a58a6c98 | 118 | if (++o > len) return WAIT; |
rob.meades@u-blox.com | 1:ef70a58a6c98 | 119 | ch = _toHex[(c >> 0) & 0xF]; // low nibble |
rob.meades@u-blox.com | 1:ef70a58a6c98 | 120 | if (ch != pipe->next()) return NOT_FOUND; |
rob.meades@u-blox.com | 1:ef70a58a6c98 | 121 | if (++o > len) return WAIT; |
rob.meades@u-blox.com | 1:ef70a58a6c98 | 122 | if ('\r' != pipe->next()) return NOT_FOUND; |
rob.meades@u-blox.com | 1:ef70a58a6c98 | 123 | if (++o > len) return WAIT; |
rob.meades@u-blox.com | 1:ef70a58a6c98 | 124 | if ('\n' != pipe->next()) return NOT_FOUND; |
rob.meades@u-blox.com | 1:ef70a58a6c98 | 125 | return o; |
rob.meades@u-blox.com | 1:ef70a58a6c98 | 126 | } |
rob.meades@u-blox.com | 1:ef70a58a6c98 | 127 | |
rob.meades@u-blox.com | 1:ef70a58a6c98 | 128 | int GnssParser::_parseUbx(Pipe<char>* pipe, int l) |
rob.meades@u-blox.com | 1:ef70a58a6c98 | 129 | { |
rob.meades@u-blox.com | 1:ef70a58a6c98 | 130 | int o = 0; |
rob.meades@u-blox.com | 1:ef70a58a6c98 | 131 | if (++o > l) return WAIT; |
rob.meades@u-blox.com | 1:ef70a58a6c98 | 132 | if ('\xB5' != pipe->next()) return NOT_FOUND; |
rob.meades@u-blox.com | 1:ef70a58a6c98 | 133 | if (++o > l) return WAIT; |
rob.meades@u-blox.com | 1:ef70a58a6c98 | 134 | if ('\x62' != pipe->next()) return NOT_FOUND; |
rob.meades@u-blox.com | 1:ef70a58a6c98 | 135 | o += 4; |
rob.meades@u-blox.com | 1:ef70a58a6c98 | 136 | if (o > l) return WAIT; |
rob.meades@u-blox.com | 1:ef70a58a6c98 | 137 | int i,j,ca,cb; |
rob.meades@u-blox.com | 1:ef70a58a6c98 | 138 | i = pipe->next(); ca = i; cb = ca; // cls |
rob.meades@u-blox.com | 1:ef70a58a6c98 | 139 | i = pipe->next(); ca += i; cb += ca; // id |
rob.meades@u-blox.com | 1:ef70a58a6c98 | 140 | i = pipe->next(); ca += i; cb += ca; // len_lsb |
rob.meades@u-blox.com | 1:ef70a58a6c98 | 141 | j = pipe->next(); ca += j; cb += ca; // len_msb |
rob.meades@u-blox.com | 1:ef70a58a6c98 | 142 | j = i + (j << 8); |
rob.meades@u-blox.com | 1:ef70a58a6c98 | 143 | while (j--) |
rob.meades@u-blox.com | 1:ef70a58a6c98 | 144 | { |
rob.meades@u-blox.com | 1:ef70a58a6c98 | 145 | if (++o > l) return WAIT; |
rob.meades@u-blox.com | 1:ef70a58a6c98 | 146 | i = pipe->next(); |
rob.meades@u-blox.com | 1:ef70a58a6c98 | 147 | ca += i; |
rob.meades@u-blox.com | 1:ef70a58a6c98 | 148 | cb += ca; |
rob.meades@u-blox.com | 1:ef70a58a6c98 | 149 | } |
rob.meades@u-blox.com | 1:ef70a58a6c98 | 150 | ca &= 0xFF; cb &= 0xFF; |
rob.meades@u-blox.com | 1:ef70a58a6c98 | 151 | if (++o > l) return WAIT; |
rob.meades@u-blox.com | 1:ef70a58a6c98 | 152 | if (ca != pipe->next()) return NOT_FOUND; |
rob.meades@u-blox.com | 1:ef70a58a6c98 | 153 | if (++o > l) return WAIT; |
rob.meades@u-blox.com | 1:ef70a58a6c98 | 154 | if (cb != pipe->next()) return NOT_FOUND; |
rob.meades@u-blox.com | 1:ef70a58a6c98 | 155 | return o; |
rob.meades@u-blox.com | 1:ef70a58a6c98 | 156 | } |
rob.meades@u-blox.com | 1:ef70a58a6c98 | 157 | |
rob.meades@u-blox.com | 1:ef70a58a6c98 | 158 | int GnssParser::send(const char* buf, int len) |
rob.meades@u-blox.com | 1:ef70a58a6c98 | 159 | { |
rob.meades@u-blox.com | 1:ef70a58a6c98 | 160 | return _send(buf, len); |
rob.meades@u-blox.com | 1:ef70a58a6c98 | 161 | } |
rob.meades@u-blox.com | 1:ef70a58a6c98 | 162 | |
rob.meades@u-blox.com | 1:ef70a58a6c98 | 163 | int GnssParser::sendNmea(const char* buf, int len) |
rob.meades@u-blox.com | 1:ef70a58a6c98 | 164 | { |
rob.meades@u-blox.com | 1:ef70a58a6c98 | 165 | char head[1] = { '$' }; |
rob.meades@u-blox.com | 1:ef70a58a6c98 | 166 | char tail[5] = { '*', 0x00/*crc_high*/, 0x00/*crc_low*/, '\r', '\n' }; |
rob.meades@u-blox.com | 1:ef70a58a6c98 | 167 | int i; |
rob.meades@u-blox.com | 1:ef70a58a6c98 | 168 | int crc = 0; |
rob.meades@u-blox.com | 1:ef70a58a6c98 | 169 | for (i = 0; i < len; i ++) |
rob.meades@u-blox.com | 1:ef70a58a6c98 | 170 | crc ^= *buf++; |
rob.meades@u-blox.com | 1:ef70a58a6c98 | 171 | i = _send(head, sizeof(head)); |
rob.meades@u-blox.com | 1:ef70a58a6c98 | 172 | i += _send(buf, len); |
rob.meades@u-blox.com | 1:ef70a58a6c98 | 173 | tail[1] = _toHex[(crc > 4) & 0xF0]; |
rob.meades@u-blox.com | 1:ef70a58a6c98 | 174 | tail[2] = _toHex[(crc > 0) & 0x0F]; |
rob.meades@u-blox.com | 1:ef70a58a6c98 | 175 | i += _send(tail, sizeof(tail)); |
rob.meades@u-blox.com | 1:ef70a58a6c98 | 176 | return i; |
rob.meades@u-blox.com | 1:ef70a58a6c98 | 177 | } |
rob.meades@u-blox.com | 1:ef70a58a6c98 | 178 | |
rob.meades@u-blox.com | 1:ef70a58a6c98 | 179 | int GnssParser::sendUbx(unsigned char cls, unsigned char id, const void* buf /*= NULL*/, int len /*= 0*/) |
rob.meades@u-blox.com | 1:ef70a58a6c98 | 180 | { |
rob.meades@u-blox.com | 1:ef70a58a6c98 | 181 | char head[6] = { 0xB5, 0x62, cls, id, (char) len, (char) (len >> 8)}; |
rob.meades@u-blox.com | 1:ef70a58a6c98 | 182 | char crc[2]; |
rob.meades@u-blox.com | 1:ef70a58a6c98 | 183 | int i; |
rob.meades@u-blox.com | 1:ef70a58a6c98 | 184 | int ca = 0; |
rob.meades@u-blox.com | 1:ef70a58a6c98 | 185 | int cb = 0; |
rob.meades@u-blox.com | 1:ef70a58a6c98 | 186 | for (i = 2; i < 6; i ++) |
rob.meades@u-blox.com | 1:ef70a58a6c98 | 187 | { |
rob.meades@u-blox.com | 1:ef70a58a6c98 | 188 | ca += head[i]; |
rob.meades@u-blox.com | 1:ef70a58a6c98 | 189 | cb += ca; |
rob.meades@u-blox.com | 1:ef70a58a6c98 | 190 | } |
rob.meades@u-blox.com | 1:ef70a58a6c98 | 191 | for (i = 0; i < len; i ++) |
rob.meades@u-blox.com | 1:ef70a58a6c98 | 192 | { |
rob.meades@u-blox.com | 1:ef70a58a6c98 | 193 | ca += ((char*)buf)[i]; |
rob.meades@u-blox.com | 1:ef70a58a6c98 | 194 | cb += ca; |
rob.meades@u-blox.com | 1:ef70a58a6c98 | 195 | } |
rob.meades@u-blox.com | 1:ef70a58a6c98 | 196 | i = _send(head, sizeof(head)); |
rob.meades@u-blox.com | 1:ef70a58a6c98 | 197 | i += _send(buf, len); |
rob.meades@u-blox.com | 1:ef70a58a6c98 | 198 | crc[0] = ca & 0xFF; |
rob.meades@u-blox.com | 1:ef70a58a6c98 | 199 | crc[1] = cb & 0xFF; |
rob.meades@u-blox.com | 1:ef70a58a6c98 | 200 | i += _send(crc, sizeof(crc)); |
rob.meades@u-blox.com | 1:ef70a58a6c98 | 201 | return i; |
rob.meades@u-blox.com | 1:ef70a58a6c98 | 202 | } |
rob.meades@u-blox.com | 1:ef70a58a6c98 | 203 | |
rob.meades@u-blox.com | 1:ef70a58a6c98 | 204 | const char* GnssParser::findNmeaItemPos(int ix, const char* start, const char* end) |
rob.meades@u-blox.com | 1:ef70a58a6c98 | 205 | { |
rob.meades@u-blox.com | 6:56eda66d585b | 206 | // Find the start |
rob.meades@u-blox.com | 1:ef70a58a6c98 | 207 | for (; (start < end) && (ix > 0); start ++) |
rob.meades@u-blox.com | 1:ef70a58a6c98 | 208 | { |
rob.meades@u-blox.com | 1:ef70a58a6c98 | 209 | if (*start == ',') |
rob.meades@u-blox.com | 1:ef70a58a6c98 | 210 | ix --; |
rob.meades@u-blox.com | 1:ef70a58a6c98 | 211 | } |
rob.meades@u-blox.com | 6:56eda66d585b | 212 | // Found and check bounds |
rob.meades@u-blox.com | 1:ef70a58a6c98 | 213 | if ((ix == 0) && (start < end) && |
rob.meades@u-blox.com | 1:ef70a58a6c98 | 214 | (*start != ',') && (*start != '*') && (*start != '\r') && (*start != '\n')) |
rob.meades@u-blox.com | 1:ef70a58a6c98 | 215 | return start; |
rob.meades@u-blox.com | 1:ef70a58a6c98 | 216 | else |
rob.meades@u-blox.com | 1:ef70a58a6c98 | 217 | return NULL; |
rob.meades@u-blox.com | 1:ef70a58a6c98 | 218 | } |
rob.meades@u-blox.com | 1:ef70a58a6c98 | 219 | |
rob.meades@u-blox.com | 1:ef70a58a6c98 | 220 | bool GnssParser::getNmeaItem(int ix, char* buf, int len, double& val) |
rob.meades@u-blox.com | 1:ef70a58a6c98 | 221 | { |
rob.meades@u-blox.com | 1:ef70a58a6c98 | 222 | char* end = &buf[len]; |
rob.meades@u-blox.com | 1:ef70a58a6c98 | 223 | const char* pos = findNmeaItemPos(ix, buf, end); |
rob.meades@u-blox.com | 6:56eda66d585b | 224 | // Find the start |
rob.meades@u-blox.com | 1:ef70a58a6c98 | 225 | if (!pos) |
rob.meades@u-blox.com | 1:ef70a58a6c98 | 226 | return false; |
rob.meades@u-blox.com | 1:ef70a58a6c98 | 227 | val = strtod(pos, &end); |
rob.meades@u-blox.com | 6:56eda66d585b | 228 | // Restore the last character |
rob.meades@u-blox.com | 1:ef70a58a6c98 | 229 | return (end > pos); |
rob.meades@u-blox.com | 1:ef70a58a6c98 | 230 | } |
rob.meades@u-blox.com | 1:ef70a58a6c98 | 231 | |
rob.meades@u-blox.com | 1:ef70a58a6c98 | 232 | bool GnssParser::getNmeaItem(int ix, char* buf, int len, int& val, int base /*=10*/) |
rob.meades@u-blox.com | 1:ef70a58a6c98 | 233 | { |
rob.meades@u-blox.com | 1:ef70a58a6c98 | 234 | char* end = &buf[len]; |
rob.meades@u-blox.com | 1:ef70a58a6c98 | 235 | const char* pos = findNmeaItemPos(ix, buf, end); |
rob.meades@u-blox.com | 6:56eda66d585b | 236 | // Find the start |
rob.meades@u-blox.com | 1:ef70a58a6c98 | 237 | if (!pos) |
rob.meades@u-blox.com | 1:ef70a58a6c98 | 238 | return false; |
rob.meades@u-blox.com | 1:ef70a58a6c98 | 239 | val = (int)strtol(pos, &end, base); |
rob.meades@u-blox.com | 1:ef70a58a6c98 | 240 | return (end > pos); |
rob.meades@u-blox.com | 1:ef70a58a6c98 | 241 | } |
rob.meades@u-blox.com | 1:ef70a58a6c98 | 242 | |
rob.meades@u-blox.com | 1:ef70a58a6c98 | 243 | bool GnssParser::getNmeaItem(int ix, char* buf, int len, char& val) |
rob.meades@u-blox.com | 1:ef70a58a6c98 | 244 | { |
rob.meades@u-blox.com | 1:ef70a58a6c98 | 245 | const char* end = &buf[len]; |
rob.meades@u-blox.com | 1:ef70a58a6c98 | 246 | const char* pos = findNmeaItemPos(ix, buf, end); |
rob.meades@u-blox.com | 6:56eda66d585b | 247 | // Find the start |
rob.meades@u-blox.com | 1:ef70a58a6c98 | 248 | if (!pos) |
rob.meades@u-blox.com | 1:ef70a58a6c98 | 249 | return false; |
rob.meades@u-blox.com | 6:56eda66d585b | 250 | // Skip leading spaces |
rob.meades@u-blox.com | 1:ef70a58a6c98 | 251 | while ((pos < end) && isspace(*pos)) |
rob.meades@u-blox.com | 1:ef70a58a6c98 | 252 | pos++; |
rob.meades@u-blox.com | 6:56eda66d585b | 253 | // Check bound |
rob.meades@u-blox.com | 1:ef70a58a6c98 | 254 | if ((pos < end) && |
rob.meades@u-blox.com | 1:ef70a58a6c98 | 255 | (*pos != ',') && (*pos != '*') && (*pos != '\r') && (*pos != '\n')) |
rob.meades@u-blox.com | 1:ef70a58a6c98 | 256 | { |
rob.meades@u-blox.com | 1:ef70a58a6c98 | 257 | val = *pos; |
rob.meades@u-blox.com | 1:ef70a58a6c98 | 258 | return true; |
rob.meades@u-blox.com | 1:ef70a58a6c98 | 259 | } |
rob.meades@u-blox.com | 1:ef70a58a6c98 | 260 | return false; |
rob.meades@u-blox.com | 1:ef70a58a6c98 | 261 | } |
rob.meades@u-blox.com | 1:ef70a58a6c98 | 262 | |
rob.meades@u-blox.com | 1:ef70a58a6c98 | 263 | bool GnssParser::getNmeaAngle(int ix, char* buf, int len, double& val) |
rob.meades@u-blox.com | 1:ef70a58a6c98 | 264 | { |
rob.meades@u-blox.com | 1:ef70a58a6c98 | 265 | char ch; |
rob.meades@u-blox.com | 1:ef70a58a6c98 | 266 | if (getNmeaItem(ix,buf,len,val) && getNmeaItem(ix+1,buf,len,ch) && |
rob.meades@u-blox.com | 1:ef70a58a6c98 | 267 | ((ch == 'S') || (ch == 'N') || (ch == 'E') || (ch == 'W'))) |
rob.meades@u-blox.com | 1:ef70a58a6c98 | 268 | { |
rob.meades@u-blox.com | 1:ef70a58a6c98 | 269 | val *= 0.01; |
rob.meades@u-blox.com | 1:ef70a58a6c98 | 270 | int i = (int)val; |
rob.meades@u-blox.com | 1:ef70a58a6c98 | 271 | val = (val - i) / 0.6 + i; |
rob.meades@u-blox.com | 1:ef70a58a6c98 | 272 | if (ch == 'S' || ch == 'W') |
rob.meades@u-blox.com | 1:ef70a58a6c98 | 273 | val = -val; |
rob.meades@u-blox.com | 1:ef70a58a6c98 | 274 | return true; |
rob.meades@u-blox.com | 1:ef70a58a6c98 | 275 | } |
rob.meades@u-blox.com | 1:ef70a58a6c98 | 276 | return false; |
rob.meades@u-blox.com | 1:ef70a58a6c98 | 277 | } |
rob.meades@u-blox.com | 1:ef70a58a6c98 | 278 | |
rob.meades@u-blox.com | 1:ef70a58a6c98 | 279 | 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 | 280 | |
rob.meades@u-blox.com | 1:ef70a58a6c98 | 281 | // ---------------------------------------------------------------- |
rob.meades@u-blox.com | 1:ef70a58a6c98 | 282 | // Serial Implementation |
rob.meades@u-blox.com | 1:ef70a58a6c98 | 283 | // ---------------------------------------------------------------- |
rob.meades@u-blox.com | 1:ef70a58a6c98 | 284 | |
rob.meades@u-blox.com | 1:ef70a58a6c98 | 285 | GnssSerial::GnssSerial(PinName tx /*= GNSSTXD */, PinName rx /*= GNSSRXD */, int baudrate /*= GNSSBAUD */, |
rob.meades@u-blox.com | 4:82308d600690 | 286 | int rxSize /*= 256 */, int txSize /*= 128 */) : |
rob.meades@u-blox.com | 1:ef70a58a6c98 | 287 | SerialPipe(tx, rx, baudrate, rxSize, txSize) |
rob.meades@u-blox.com | 1:ef70a58a6c98 | 288 | { |
rob.meades@u-blox.com | 1:ef70a58a6c98 | 289 | baud(baudrate); |
rob.meades@u-blox.com | 1:ef70a58a6c98 | 290 | } |
rob.meades@u-blox.com | 1:ef70a58a6c98 | 291 | |
rob.meades@u-blox.com | 1:ef70a58a6c98 | 292 | GnssSerial::~GnssSerial(void) |
rob.meades@u-blox.com | 1:ef70a58a6c98 | 293 | { |
rob.meades@u-blox.com | 1:ef70a58a6c98 | 294 | powerOff(); |
rob.meades@u-blox.com | 1:ef70a58a6c98 | 295 | } |
rob.meades@u-blox.com | 1:ef70a58a6c98 | 296 | |
rob.meades@u-blox.com | 1:ef70a58a6c98 | 297 | bool GnssSerial::init(PinName pn) |
rob.meades@u-blox.com | 1:ef70a58a6c98 | 298 | { |
rob.meades@u-blox.com | 6:56eda66d585b | 299 | Timer timer; |
rob.meades@u-blox.com | 6:56eda66d585b | 300 | int size; |
rob.meades@u-blox.com | 6:56eda66d585b | 301 | |
rob.meades@u-blox.com | 4:82308d600690 | 302 | // Unused (kept only for compatibility with the I2C version) |
rob.meades@u-blox.com | 4:82308d600690 | 303 | (void)pn; |
rob.meades@u-blox.com | 4:82308d600690 | 304 | |
rob.meades@u-blox.com | 1:ef70a58a6c98 | 305 | // Power up and enable the module |
rob.meades@u-blox.com | 1:ef70a58a6c98 | 306 | _powerOn(); |
rob.meades@u-blox.com | 1:ef70a58a6c98 | 307 | |
rob.meades@u-blox.com | 6:56eda66d585b | 308 | // Send a byte to wakup the device again |
rob.meades@u-blox.com | 1:ef70a58a6c98 | 309 | putc(0xFF); |
rob.meades@u-blox.com | 6:56eda66d585b | 310 | // Wait until we get some bytes |
rob.meades@u-blox.com | 6:56eda66d585b | 311 | size = _pipeRx.size(); |
rob.meades@u-blox.com | 1:ef70a58a6c98 | 312 | timer.start(); |
rob.meades@u-blox.com | 6:56eda66d585b | 313 | while ((timer.read_ms() < 1000) && (size == _pipeRx.size())) { |
rob.meades@u-blox.com | 6:56eda66d585b | 314 | /* Nothing, just wait */ |
rob.meades@u-blox.com | 6:56eda66d585b | 315 | } |
rob.meades@u-blox.com | 6:56eda66d585b | 316 | timer.stop(); |
rob.meades@u-blox.com | 6:56eda66d585b | 317 | |
rob.meades@u-blox.com | 1:ef70a58a6c98 | 318 | return (size != _pipeRx.size()); |
rob.meades@u-blox.com | 1:ef70a58a6c98 | 319 | } |
rob.meades@u-blox.com | 1:ef70a58a6c98 | 320 | |
rob.meades@u-blox.com | 1:ef70a58a6c98 | 321 | int GnssSerial::getMessage(char* buf, int len) |
rob.meades@u-blox.com | 1:ef70a58a6c98 | 322 | { |
rob.meades@u-blox.com | 1:ef70a58a6c98 | 323 | return _getMessage(&_pipeRx, buf, len); |
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::_send(const void* buf, int len) |
rob.meades@u-blox.com | 1:ef70a58a6c98 | 327 | { |
rob.meades@u-blox.com | 1:ef70a58a6c98 | 328 | return put((const char*)buf, len, true/*=blocking*/); |
rob.meades@u-blox.com | 1:ef70a58a6c98 | 329 | } |
rob.meades@u-blox.com | 1:ef70a58a6c98 | 330 | |
rob.meades@u-blox.com | 1:ef70a58a6c98 | 331 | // ---------------------------------------------------------------- |
rob.meades@u-blox.com | 1:ef70a58a6c98 | 332 | // I2C Implementation |
rob.meades@u-blox.com | 1:ef70a58a6c98 | 333 | // ---------------------------------------------------------------- |
rob.meades@u-blox.com | 1:ef70a58a6c98 | 334 | |
rob.meades@u-blox.com | 1:ef70a58a6c98 | 335 | GnssI2C::GnssI2C(PinName sda /*= NC */, PinName scl /*= NC */, |
rob.meades@u-blox.com | 1:ef70a58a6c98 | 336 | unsigned char i2cAdr /*= (66<<1) */, int rxSize /*= 256 */) : |
rob.meades@u-blox.com | 1:ef70a58a6c98 | 337 | I2C(sda,scl), |
rob.meades@u-blox.com | 1:ef70a58a6c98 | 338 | _pipe(rxSize), |
rob.meades@u-blox.com | 1:ef70a58a6c98 | 339 | _i2cAdr(i2cAdr) |
rob.meades@u-blox.com | 1:ef70a58a6c98 | 340 | { |
rob.meades@u-blox.com | 1:ef70a58a6c98 | 341 | frequency(100000); |
rob.meades@u-blox.com | 1:ef70a58a6c98 | 342 | } |
rob.meades@u-blox.com | 1:ef70a58a6c98 | 343 | |
rob.meades@u-blox.com | 1:ef70a58a6c98 | 344 | GnssI2C::~GnssI2C(void) |
rob.meades@u-blox.com | 1:ef70a58a6c98 | 345 | { |
rob.meades@u-blox.com | 1:ef70a58a6c98 | 346 | powerOff(); |
rob.meades@u-blox.com | 1:ef70a58a6c98 | 347 | } |
rob.meades@u-blox.com | 1:ef70a58a6c98 | 348 | |
rob.meades@u-blox.com | 1:ef70a58a6c98 | 349 | bool GnssI2C::init(PinName pn) |
rob.meades@u-blox.com | 1:ef70a58a6c98 | 350 | { |
rob.meades@u-blox.com | 1:ef70a58a6c98 | 351 | // Power up and enable the module |
rob.meades@u-blox.com | 1:ef70a58a6c98 | 352 | _powerOn(); |
rob.meades@u-blox.com | 1:ef70a58a6c98 | 353 | |
rob.meades@u-blox.com | 1:ef70a58a6c98 | 354 | if (pn != NC) { |
rob.meades@u-blox.com | 1:ef70a58a6c98 | 355 | DigitalOut pin(pn, 0); |
rob.meades@u-blox.com | 1:ef70a58a6c98 | 356 | ::wait_us(1); |
rob.meades@u-blox.com | 1:ef70a58a6c98 | 357 | pin = 1; |
rob.meades@u-blox.com | 1:ef70a58a6c98 | 358 | ::wait_ms(100); |
rob.meades@u-blox.com | 1:ef70a58a6c98 | 359 | } |
rob.meades@u-blox.com | 1:ef70a58a6c98 | 360 | return !I2C::write(_i2cAdr,®STREAM,sizeof(REGSTREAM)); |
rob.meades@u-blox.com | 1:ef70a58a6c98 | 361 | } |
rob.meades@u-blox.com | 1:ef70a58a6c98 | 362 | |
rob.meades@u-blox.com | 1:ef70a58a6c98 | 363 | int GnssI2C::getMessage(char* buf, int len) |
rob.meades@u-blox.com | 1:ef70a58a6c98 | 364 | { |
rob.meades@u-blox.com | 6:56eda66d585b | 365 | // Fill the pipe |
rob.meades@u-blox.com | 1:ef70a58a6c98 | 366 | int sz = _pipe.free(); |
rob.meades@u-blox.com | 1:ef70a58a6c98 | 367 | if (sz) |
rob.meades@u-blox.com | 1:ef70a58a6c98 | 368 | sz = _get(buf, sz); |
rob.meades@u-blox.com | 1:ef70a58a6c98 | 369 | if (sz) |
rob.meades@u-blox.com | 1:ef70a58a6c98 | 370 | _pipe.put(buf, sz); |
rob.meades@u-blox.com | 6:56eda66d585b | 371 | // Now parse it |
rob.meades@u-blox.com | 1:ef70a58a6c98 | 372 | return _getMessage(&_pipe, buf, len); |
rob.meades@u-blox.com | 1:ef70a58a6c98 | 373 | } |
rob.meades@u-blox.com | 1:ef70a58a6c98 | 374 | |
rob.meades@u-blox.com | 1:ef70a58a6c98 | 375 | int GnssI2C::send(const char* buf, int len) |
rob.meades@u-blox.com | 1:ef70a58a6c98 | 376 | { |
rob.meades@u-blox.com | 1:ef70a58a6c98 | 377 | int sent = 0; |
rob.meades@u-blox.com | 1:ef70a58a6c98 | 378 | if (len) |
rob.meades@u-blox.com | 1:ef70a58a6c98 | 379 | { |
rob.meades@u-blox.com | 1:ef70a58a6c98 | 380 | if (!I2C::write(_i2cAdr,®STREAM,sizeof(REGSTREAM),true)) |
rob.meades@u-blox.com | 1:ef70a58a6c98 | 381 | sent = send(buf, len); |
rob.meades@u-blox.com | 1:ef70a58a6c98 | 382 | stop(); |
rob.meades@u-blox.com | 1:ef70a58a6c98 | 383 | } |
rob.meades@u-blox.com | 1:ef70a58a6c98 | 384 | return sent; |
rob.meades@u-blox.com | 1:ef70a58a6c98 | 385 | } |
rob.meades@u-blox.com | 1:ef70a58a6c98 | 386 | |
rob.meades@u-blox.com | 1:ef70a58a6c98 | 387 | int GnssI2C::sendNmea(const char* buf, int len) |
rob.meades@u-blox.com | 1:ef70a58a6c98 | 388 | { |
rob.meades@u-blox.com | 1:ef70a58a6c98 | 389 | int sent = 0; |
rob.meades@u-blox.com | 1:ef70a58a6c98 | 390 | if (!I2C::write(_i2cAdr,®STREAM,sizeof(REGSTREAM),true)) |
rob.meades@u-blox.com | 1:ef70a58a6c98 | 391 | sent = GnssParser::sendNmea(buf, len); |
rob.meades@u-blox.com | 1:ef70a58a6c98 | 392 | stop(); |
rob.meades@u-blox.com | 1:ef70a58a6c98 | 393 | return sent; |
rob.meades@u-blox.com | 1:ef70a58a6c98 | 394 | } |
rob.meades@u-blox.com | 1:ef70a58a6c98 | 395 | |
rob.meades@u-blox.com | 1:ef70a58a6c98 | 396 | int GnssI2C::sendUbx(unsigned char cls, unsigned char id, const void* buf, int len) |
rob.meades@u-blox.com | 1:ef70a58a6c98 | 397 | { |
rob.meades@u-blox.com | 1:ef70a58a6c98 | 398 | int sent = 0; |
rob.meades@u-blox.com | 1:ef70a58a6c98 | 399 | if (!I2C::write(_i2cAdr,®STREAM,sizeof(REGSTREAM),true)) |
rob.meades@u-blox.com | 1:ef70a58a6c98 | 400 | sent = GnssParser::sendUbx(cls, id, buf, len); |
rob.meades@u-blox.com | 1:ef70a58a6c98 | 401 | I2C::stop(); |
rob.meades@u-blox.com | 1:ef70a58a6c98 | 402 | return sent; |
rob.meades@u-blox.com | 1:ef70a58a6c98 | 403 | } |
rob.meades@u-blox.com | 1:ef70a58a6c98 | 404 | |
rob.meades@u-blox.com | 1:ef70a58a6c98 | 405 | int GnssI2C::_get(char* buf, int len) |
rob.meades@u-blox.com | 1:ef70a58a6c98 | 406 | { |
rob.meades@u-blox.com | 1:ef70a58a6c98 | 407 | int read = 0; |
rob.meades@u-blox.com | 1:ef70a58a6c98 | 408 | unsigned char sz[2] = {0,0}; |
rob.meades@u-blox.com | 1:ef70a58a6c98 | 409 | if (!I2C::write(_i2cAdr,®LEN,sizeof(REGLEN),true) && |
rob.meades@u-blox.com | 1:ef70a58a6c98 | 410 | !I2C::read(_i2cAdr,(char*)sz,sizeof(sz))) |
rob.meades@u-blox.com | 1:ef70a58a6c98 | 411 | { |
rob.meades@u-blox.com | 1:ef70a58a6c98 | 412 | int size = 256 * (int)sz[0] + sz[1]; |
rob.meades@u-blox.com | 1:ef70a58a6c98 | 413 | if (size > len) |
rob.meades@u-blox.com | 1:ef70a58a6c98 | 414 | size = len; |
rob.meades@u-blox.com | 1:ef70a58a6c98 | 415 | if (size > 0) |
rob.meades@u-blox.com | 1:ef70a58a6c98 | 416 | { |
rob.meades@u-blox.com | 1:ef70a58a6c98 | 417 | if (!I2C::write(_i2cAdr,®STREAM,sizeof(REGSTREAM),true) && |
rob.meades@u-blox.com | 1:ef70a58a6c98 | 418 | !I2C::read(_i2cAdr,buf,size)) { |
rob.meades@u-blox.com | 1:ef70a58a6c98 | 419 | read = size; |
rob.meades@u-blox.com | 1:ef70a58a6c98 | 420 | } |
rob.meades@u-blox.com | 1:ef70a58a6c98 | 421 | } |
rob.meades@u-blox.com | 1:ef70a58a6c98 | 422 | } |
rob.meades@u-blox.com | 1:ef70a58a6c98 | 423 | return read; |
rob.meades@u-blox.com | 1:ef70a58a6c98 | 424 | } |
rob.meades@u-blox.com | 1:ef70a58a6c98 | 425 | |
rob.meades@u-blox.com | 1:ef70a58a6c98 | 426 | int GnssI2C::_send(const void* buf, int len) |
rob.meades@u-blox.com | 1:ef70a58a6c98 | 427 | { |
rob.meades@u-blox.com | 1:ef70a58a6c98 | 428 | return !I2C::write(_i2cAdr,(const char*)buf,len,true) ? len : 0; |
rob.meades@u-blox.com | 1:ef70a58a6c98 | 429 | } |
rob.meades@u-blox.com | 1:ef70a58a6c98 | 430 | |
rob.meades@u-blox.com | 1:ef70a58a6c98 | 431 | const char GnssI2C::REGLEN = 0xFD; |
rob.meades@u-blox.com | 1:ef70a58a6c98 | 432 | const char GnssI2C::REGSTREAM = 0xFF; |
rob.meades@u-blox.com | 1:ef70a58a6c98 | 433 | |
rob.meades@u-blox.com | 1:ef70a58a6c98 | 434 | // End Of File |