Add a bunch of APNs
Fork of C027_Support by
GPS.cpp
- Committer:
- mazgch
- Date:
- 2013-10-25
- Revision:
- 2:b6012cd91657
- Child:
- 3:c7cd4887560d
File content as of revision 2:b6012cd91657:
#include "mbed.h" #include <ctype.h> #include "GPS.h" int GPSParser::_getMessage(Pipe<char>* pipe, char* buf, int len) { int unkn = 0; int sz = pipe->size(); if (len > sz) len = sz; while (len > 0) { // NMEA protocol int nmea = _parseNmea(pipe,len); if ((nmea != NOT_FOUND) && (unkn > 0)) return unkn; if (nmea == WAIT) return WAIT; if (nmea > 0) return NMEA | pipe->get(buf,nmea); // UBX protocol int ubx = _parseUbx(pipe,len); if ((ubx != NOT_FOUND) && (unkn > 0)) return unkn; if (ubx == WAIT) return WAIT; if (ubx > 0) return UBX | pipe->get(buf,ubx); // UNKNOWN *buf++ = pipe->getc(); unkn ++; len--; } if (unkn != NOT_FOUND) return unkn; return WAIT; } int GPSParser::_parseNmea(Pipe<char>* pipe, int len) { int ix = 0; pipe->start(); if (++ix > len) return WAIT; if ('$' != pipe->next()) return NOT_FOUND; for (;;) { if (++ix > len) return WAIT; char ch = pipe->next(); if ('\n' == ch) return ix; if (!isprint(ch) && '\r'!= ch) return NOT_FOUND; } } int GPSParser::_parseUbx(Pipe<char>* pipe, int l) { int o = 0; pipe->start(); if (++o > l) return WAIT; if ('\xB5' != pipe->next()) return NOT_FOUND; if (++o > l) return WAIT; if ('\x62' != pipe->next()) return NOT_FOUND; o += 4; if (o > l) return WAIT; int i,j,ca,cb; i = pipe->next(); ca = i; cb = ca; // cls i = pipe->next(); ca += i; cb += ca; // id i = pipe->next(); ca += i; cb += ca; // len_lsb j = pipe->next(); ca += j; cb += ca; // len_msb j = i + (j << 8); while (j--) { if (++o > l) return WAIT; i = pipe->next(); ca += i; cb += ca; } ca &= 0xFF; cb &= 0xFF; if (++o > l) return WAIT; if (ca != pipe->next()) return NOT_FOUND; if (++o > l) return WAIT; if (cb != pipe->next()) return NOT_FOUND; return o; } int GPSParser::_putNmea(Stream* stream, const char* buf, int len) { stream->putc('$'); int c = 0; for (int i = 0; i < len; i ++) { int t = *buf++; stream->putc(t); c ^= t; } stream->putc('*'); stream->putc(toHex[(c >> 4) & 0xF]); stream->putc(toHex[(c >> 0) & 0xF]); stream->putc('\r'); stream->putc('\n'); return len + 6; } int GPSParser::_putUbx(Stream* stream, const unsigned char cls, unsigned char id, unsigned char* buf, int len) { stream->putc('\xB5'); // 'µ' stream->putc('\x62'); // 'b' int ca = cls, cb = cls; stream->putc(cls); ca += id; cb += ca; stream->putc(id); int t = (len >> 0) & 0xFF; ca += t; cb += ca; stream->putc(t); t = (len >> 8) & 0xFF; ca += t; cb += ca; stream->putc(t); for (int i = 0; i < len; i ++) { t = *buf++; ca += t; cb += ca; stream->putc(t); } stream->putc(ca & 0xFF); stream->putc(cb & 0xFF); return len + 8; } const char* GPSParser::findNmeaItemPos(int ix, const char* start, const char* end) { // find the start for (; (start < end) && (ix > 0); start ++) { if (*start == ',') ix --; } // found and check bounds if ((ix == 0) && (start < end) && (*start != ',') && (*start != '*') && (*start != '\r') && (*start != '\n')) return start; else return NULL; } bool GPSParser::getNmeaItem(int ix, char* buf, int len, double& val) { char* end = &buf[len]; const char* pos = findNmeaItemPos(ix, buf, end); // find the start if (!pos) return false; val = strtod(pos, &end); // restore the last character return (end > pos); } bool GPSParser::getNmeaItem(int ix, char* buf, int len, int& val, int base /*=10*/) { char* end = &buf[len]; const char* pos = findNmeaItemPos(ix, buf, end); // find the start if (!pos) return false; val = (int)strtol(pos, &end, base); return (end > pos); } bool GPSParser::getNmeaItem(int ix, char* buf, int len, char& val) { const char* end = &buf[len]; const char* pos = findNmeaItemPos(ix, buf, end); // find the start if (!pos) return false; // skip leading spaces while ((pos < end) && isspace(*pos)) pos++; // check bound if ((pos < end) && (*pos != ',') && (*pos != '*') && (*pos != '\r') && (*pos != '\n')) { val = *pos; return true; } return false; } const char GPSParser::toHex[] = { '0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F' }; // ---------------------------------------------------------------- // Serial Implementation // ---------------------------------------------------------------- GPSSerial::GPSSerial(PinName tx /*= GPSTXD*/, PinName rx /*= GPSRXD*/, int baudrate /*= GPSBAUD*/) : Serial(tx, rx, "gps"), _pipe(256) { attach(this, &GPSSerial::serialRxIrq, RxIrq); baud(baudrate); } GPSSerial::~GPSSerial(void) { attach(NULL, RxIrq); } void GPSSerial::serialRxIrq(void) { while (serial_readable(&_serial)) _pipe.putc(serial_getc(&_serial)); } int GPSSerial::getMessage(char* buf, int len) { return _getMessage(&_pipe, buf, len); } // ---------------------------------------------------------------- // I2C Implementation // ---------------------------------------------------------------- GPSI2C::GPSI2C(PinName sda /*= GPSSDA*/, PinName scl /*= GPSSCL*/) : I2C(sda,scl), _pipe(256) { found = false; } bool GPSI2C::detect(void) { if (!found) { int w = I2C::write(GPSADR,®STREAM,sizeof(REGSTREAM)); if (w == 0) found = true; } return found; } int GPSI2C::getMessage(char* buf, int len) { int sz = _get(buf, len); if (sz) _pipe.put(buf, sz); return _getMessage(&_pipe, buf, len); } int GPSI2C::_get(char* buf, int len) { unsigned char sz[2]; if (!I2C::write(GPSADR,®LEN,sizeof(REGLEN),true) && !I2C::read(GPSADR,(char*)sz,sizeof(sz),true)) { int size = 256 * (int)sz[0] + sz[1]; if (size > len) size = len; if (size > 0) { if (!I2C::read(GPSADR,buf,size)) { found = true; return size; } // error reading data found = false; return 0; } else { found = true; // no data -> ok } } else { // error setting address and reading length found = false; } I2C::stop(); return 0; } int GPSI2C::_put(const char* buf, int len) { if (len == 0) return 0; if (!I2C::write(GPSADR,®STREAM,sizeof(REGSTREAM),true) && !I2C::write(GPSADR,buf,len,false)) { found = true; return len; } found = false; return 0; } const char GPSI2C::REGLEN = 0xFD; const char GPSI2C::REGSTREAM = 0xFF;