Cellular module AT Serial interface passthrough to Debug COM port. This program can be used on the C030 boards excluding the C030 N2xx version.
Revision 4:80b2cd2b03f7, committed 2019-08-30
- Comitter:
- fahimalavi
- Date:
- Fri Aug 30 13:54:48 2019 +0500
- Parent:
- 3:924ed55e8397
- Child:
- 5:1d6adbeb8a19
- Commit message:
- Remove gnss folder
Changed in this revision
--- a/gnss/TESTS/unit_tests/default/main.cpp Fri Aug 30 13:05:19 2019 +0500 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,227 +0,0 @@ -#include "mbed.h" -#include "greentea-client/test_env.h" -#include "unity.h" -#include "utest.h" -#include "gnss.h" - -using namespace utest::v1; - -// ---------------------------------------------------------------- -// COMPILE-TIME MACROS -// ---------------------------------------------------------------- - -// How long to wait for a GNSS result -#define GNSS_WAIT_SECONDS 120 - -// ---------------------------------------------------------------- -// PRIVATE VARIABLES -// ---------------------------------------------------------------- - -// ---------------------------------------------------------------- -// PRIVATE FUNCTIONS -// ---------------------------------------------------------------- - -static void printHex (char * pData, uint32_t lenData) -{ - char * pEnd = pData + lenData; - uint8_t x; - - printf (" 0 1 2 3 4 5 6 7 8 9 A B C D E F\n"); - while (pData < pEnd) { - for (x = 1; (x <= 32) && (pData < pEnd); x++) { - if (x % 16 == 8) { - printf ("%02x ", *pData); - } else if (x % 16 == 0) { - printf ("%02x\n", *pData); - } else { - printf ("%02x-", *pData); - } - pData++; - } - - - if (x % 16 != 1) { - printf("\n"); - } - } -} - -// ---------------------------------------------------------------- -// TESTS -// ---------------------------------------------------------------- - -// Test sending a u-blox command over serial -void test_serial_ubx() { - char buffer[64]; - int responseLength = 0; - int returnCode; - bool gotAck = false; - Timer timer; - - GnssSerial *pGnss = new GnssSerial(); - - // Initialise the GNSS chip - pGnss->init(NC); - - // Try this a few times as we might get no response - // if the GNSS chip is busy - for (int x = 0; (x < 3) && !gotAck; x++) { - // See ublox7-V14_ReceiverDescrProtSpec section 30.11.15 (CFG-NAV5) - // Set automotive mode, which should be acknowledged - memset (buffer, 0, sizeof (buffer)); - buffer[0] = 0x00; - buffer[1] = 0x01; // Mask: set dynamic config only - buffer[2] = 0x04; // Dynamic platform model: automotive - // Send length is 32 bytes of payload + 6 bytes header + 2 bytes CRC - TEST_ASSERT_EQUAL_INT (40, pGnss->sendUbx(0x06, 0x24, buffer, 32)); - printf ("CFG_NAV5 command sent, try %d.\n", x); - timer.start(); - while ((!gotAck) && (timer.read_ms() < 1000)) { - // Wait for the required Ack - returnCode = pGnss->getMessage(buffer, sizeof(buffer)); - if ((returnCode != GnssSerial::WAIT) && (returnCode != GnssSerial::NOT_FOUND)) { - responseLength = LENGTH(returnCode); - if ((PROTOCOL(returnCode) == GnssSerial::UBX)) { - printHex(buffer, responseLength); - // Ack is 0xb5-62-05-00-02-00-msgclass-msgid-crcA-crcB - // Nack is 0xb5-62-05-01-02-00-msgclass-msgid-crcA-crcB - TEST_ASSERT_EQUAL_UINT8(0xb5, buffer[0]); - TEST_ASSERT_EQUAL_UINT8(0x62, buffer[1]); - TEST_ASSERT_EQUAL_UINT8(0x05, buffer[2]); - TEST_ASSERT_EQUAL_UINT8(0x00, buffer[3]); - TEST_ASSERT_EQUAL_UINT8(0x02, buffer[4]); - TEST_ASSERT_EQUAL_UINT8(0x00, buffer[5]); - TEST_ASSERT_EQUAL_UINT8(0x06, buffer[6]); - TEST_ASSERT_EQUAL_UINT8(0x24, buffer[7]); - gotAck = true; - } else if ((PROTOCOL(returnCode) == GnssSerial::NMEA)) { - printf ("%.*s", responseLength, buffer); - } else { - printHex(buffer, responseLength); - } - } - wait_ms (100); - } - timer.stop(); - timer.reset(); - } -} - -// Test getting a response from GNSS using the serial interface -void test_serial_time() { - GnssSerial *pGnss = new GnssSerial(); - - bool gotLatLong = false; - bool gotElevation = false; - bool gotSpeed = false; - bool gotTime = false; - char buffer[256]; - int returnCode; - double latitude; - double longitude; - double elevation; - double speed; - - printf("GNSS: powering up and waiting up to %d second(s) for something to happen.\n", GNSS_WAIT_SECONDS); - pGnss->init(); - - memset(buffer, 0, sizeof(buffer)); - for (uint32_t x = 0; (x < GNSS_WAIT_SECONDS) && !gotTime; x++) - { - while (((returnCode = pGnss->getMessage(buffer, sizeof(buffer))) > 0) && - !(gotLatLong && gotElevation && gotSpeed && gotTime)) - { - int32_t length = LENGTH(returnCode); - - if ((PROTOCOL(returnCode) == GnssParser::NMEA) && (length > 6)) - { - printf("."); - - // talker is $GA=Galileo $GB=Beidou $GL=Glonass $GN=Combined $GP=GNSS - if ((buffer[0] == '$') || buffer[1] == 'G') - { -#define _CHECK_TALKER(s) ((buffer[3] == s[0]) && (buffer[4] == s[1]) && (buffer[5] == s[2])) - if (_CHECK_TALKER("GLL")) - { - char ch; - - if (pGnss->getNmeaAngle(1, buffer, length, latitude) && - pGnss->getNmeaAngle(3, buffer, length, longitude) && - pGnss->getNmeaItem(6, buffer, length, ch) && - ch == 'A') - { - gotLatLong = true; - latitude *= 60000; - longitude *= 60000; - printf("\nGNSS: location %.5f %.5f %c.\n", latitude, longitude, ch); - } - } - else if (_CHECK_TALKER("GGA") || _CHECK_TALKER("GNS")) - { - const char *pTimeString = NULL; - - // Retrieve the time - pTimeString = pGnss->findNmeaItemPos(1, buffer, buffer + length); - if (pTimeString != NULL) - { - gotTime = true; - printf("\nGNSS: time is %.6s.", pTimeString); - } - - if (pGnss->getNmeaItem(9, buffer, length, elevation)) // altitude msl [m] - { - gotElevation = true; - printf("\nGNSS: elevation: %.1f.", elevation); - } - } - else if (_CHECK_TALKER("VTG")) - { - if (pGnss->getNmeaItem(7, buffer, length, speed)) // speed [km/h] - { - gotSpeed = true; - printf("\nGNSS: speed: %.1f.", speed); - } - } - } - } - } - - wait_ms(1000); - } - - printf("\n"); - - // Depending on antenna positioning we may not be able to get a GNSS fix but we - // should at least be able to receive the time from a satellite - TEST_ASSERT(gotTime); -} - -// ---------------------------------------------------------------- -// TEST ENVIRONMENT -// ---------------------------------------------------------------- - -// Setup the test environment -utest::v1::status_t test_setup(const size_t number_of_cases) { - // Setup Greentea with a timeout - GREENTEA_SETUP(120, "default_auto"); - return verbose_test_setup_handler(number_of_cases); -} - -// Test cases -Case cases[] = { - Case("Ubx command", test_serial_ubx), - Case("Get time", test_serial_time), -}; - -Specification specification(test_setup, cases); - -// ---------------------------------------------------------------- -// MAIN -// ---------------------------------------------------------------- - -int main() { - - return !Harness::run(specification); -} - -// End Of File
--- a/gnss/gnss.cpp Fri Aug 30 13:05:19 2019 +0500 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,434 +0,0 @@ -/* mbed Microcontroller Library - * Copyright (c) 2017 u-blox - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** - * @file gnss.cpp - * This file defines a class that communicates with a u-blox GNSS chip. - */ - -#include "mbed.h" -#include "ctype.h" -#include "gnss.h" - -GnssParser::GnssParser(void) -{ - // Create the enable pin but set everything to disabled - _gnssEnable = NULL; - -#ifdef TARGET_UBLOX_C030 - _gnssEnable = new DigitalInOut(GNSSEN, PIN_OUTPUT, PushPullNoPull, 0); -#else - _gnssEnable = new DigitalInOut(GNSSEN, PIN_OUTPUT, PullNone, 1); -#endif -} - -GnssParser::~GnssParser(void) -{ - if (_gnssEnable != NULL) { - *_gnssEnable = 0; - delete _gnssEnable; - } -} - -void GnssParser::powerOff(void) -{ - // Set the GNSS into backup mode using the command RMX-LPREQ - struct { unsigned long dur; unsigned long flags; } msg = {0/*endless*/,0/*backup*/}; - sendUbx(0x02, 0x41, &msg, sizeof(msg)); -} - -void GnssParser::_powerOn(void) -{ - if (_gnssEnable != NULL) { - *_gnssEnable = 1; - } - wait_ms (1); -} - -int GnssParser::_getMessage(Pipe<char>* pipe, char* buf, int len) -{ - int unkn = 0; - int sz = pipe->size(); - int fr = pipe->free(); - if (len > sz) - len = sz; - while (len > 0) - { - // NMEA protocol - pipe->set(unkn); - int nmea = _parseNmea(pipe,len); - if ((nmea != NOT_FOUND) && (unkn > 0)) - return UNKNOWN | pipe->get(buf,unkn); - if (nmea == WAIT && fr) - return WAIT; - if (nmea > 0) - return NMEA | pipe->get(buf,nmea); - // UBX protocol - - pipe->set(unkn); - int ubx = _parseUbx(pipe,len); - if ((ubx != NOT_FOUND) && (unkn > 0)) - return UNKNOWN | pipe->get(buf,unkn); - if (ubx == WAIT && fr) - return WAIT; - if (ubx > 0) - return UBX | pipe->get(buf,ubx); - - // UNKNOWN - unkn ++; - len--; - } - if (unkn > 0) - return UNKNOWN | pipe->get(buf,unkn); - return WAIT; -} - -int GnssParser::_parseNmea(Pipe<char>* pipe, int len) -{ - int o = 0; - int c = 0; - char ch; - if (++o > len) return WAIT; - if ('$' != pipe->next()) return NOT_FOUND; - // This needs to be extended by crc checking - for (;;) - { - if (++o > len) return WAIT; - ch = pipe->next(); - if ('*' == ch) break; // crc delimiter - if (!isprint(ch)) return NOT_FOUND; - c ^= ch; - } - if (++o > len) return WAIT; - ch = _toHex[(c >> 4) & 0xF]; // high nibble - if (ch != pipe->next()) return NOT_FOUND; - if (++o > len) return WAIT; - ch = _toHex[(c >> 0) & 0xF]; // low nibble - if (ch != pipe->next()) return NOT_FOUND; - if (++o > len) return WAIT; - if ('\r' != pipe->next()) return NOT_FOUND; - if (++o > len) return WAIT; - if ('\n' != pipe->next()) return NOT_FOUND; - return o; -} - -int GnssParser::_parseUbx(Pipe<char>* pipe, int l) -{ - int o = 0; - 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 GnssParser::send(const char* buf, int len) -{ - return _send(buf, len); -} - -int GnssParser::sendNmea(const char* buf, int len) -{ - char head[1] = { '$' }; - char tail[5] = { '*', 0x00/*crc_high*/, 0x00/*crc_low*/, '\r', '\n' }; - int i; - int crc = 0; - for (i = 0; i < len; i ++) - crc ^= *buf++; - i = _send(head, sizeof(head)); - i += _send(buf, len); - tail[1] = _toHex[(crc > 4) & 0xF0]; - tail[2] = _toHex[(crc > 0) & 0x0F]; - i += _send(tail, sizeof(tail)); - return i; -} - -int GnssParser::sendUbx(unsigned char cls, unsigned char id, const void* buf /*= NULL*/, int len /*= 0*/) -{ - char head[6] = { 0xB5, 0x62, cls, id, (char) len, (char) (len >> 8)}; - char crc[2]; - int i; - int ca = 0; - int cb = 0; - for (i = 2; i < 6; i ++) - { - ca += head[i]; - cb += ca; - } - for (i = 0; i < len; i ++) - { - ca += ((char*)buf)[i]; - cb += ca; - } - i = _send(head, sizeof(head)); - i += _send(buf, len); - crc[0] = ca & 0xFF; - crc[1] = cb & 0xFF; - i += _send(crc, sizeof(crc)); - return i; -} - -const char* GnssParser::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 GnssParser::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 GnssParser::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 GnssParser::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; -} - -bool GnssParser::getNmeaAngle(int ix, char* buf, int len, double& val) -{ - char ch; - if (getNmeaItem(ix,buf,len,val) && getNmeaItem(ix+1,buf,len,ch) && - ((ch == 'S') || (ch == 'N') || (ch == 'E') || (ch == 'W'))) - { - val *= 0.01; - int i = (int)val; - val = (val - i) / 0.6 + i; - if (ch == 'S' || ch == 'W') - val = -val; - return true; - } - return false; -} - -const char GnssParser::_toHex[] = { '0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F' }; - -// ---------------------------------------------------------------- -// Serial Implementation -// ---------------------------------------------------------------- - -GnssSerial::GnssSerial(PinName tx /*= GNSSTXD */, PinName rx /*= GNSSRXD */, int baudrate /*= GNSSBAUD */, - int rxSize /*= 256 */, int txSize /*= 128 */) : - SerialPipe(tx, rx, baudrate, rxSize, txSize) -{ - baud(baudrate); -} - -GnssSerial::~GnssSerial(void) -{ - powerOff(); -} - -bool GnssSerial::init(PinName pn) -{ - Timer timer; - int size; - - // Unused (kept only for compatibility with the I2C version) - (void)pn; - - // Power up and enable the module - _powerOn(); - - // Send a byte to wakup the device again - putc(0xFF); - // Wait until we get some bytes - size = _pipeRx.size(); - timer.start(); - while ((timer.read_ms() < 1000) && (size == _pipeRx.size())) { - /* Nothing, just wait */ - } - timer.stop(); - - return (size != _pipeRx.size()); -} - -int GnssSerial::getMessage(char* buf, int len) -{ - return _getMessage(&_pipeRx, buf, len); -} - -int GnssSerial::_send(const void* buf, int len) -{ - return put((const char*)buf, len, true/*=blocking*/); -} - -// ---------------------------------------------------------------- -// I2C Implementation -// ---------------------------------------------------------------- - -GnssI2C::GnssI2C(PinName sda /*= NC */, PinName scl /*= NC */, - unsigned char i2cAdr /*= (66<<1) */, int rxSize /*= 256 */) : - I2C(sda,scl), - _pipe(rxSize), - _i2cAdr(i2cAdr) -{ - frequency(100000); -} - -GnssI2C::~GnssI2C(void) -{ - powerOff(); -} - -bool GnssI2C::init(PinName pn) -{ - // Power up and enable the module - _powerOn(); - - if (pn != NC) { - DigitalOut pin(pn, 0); - ::wait_us(1); - pin = 1; - ::wait_ms(100); - } - return !I2C::write(_i2cAdr,®STREAM,sizeof(REGSTREAM)); -} - -int GnssI2C::getMessage(char* buf, int len) -{ - // Fill the pipe - int sz = _pipe.free(); - if (sz) - sz = _get(buf, sz); - if (sz) - _pipe.put(buf, sz); - // Now parse it - return _getMessage(&_pipe, buf, len); -} - -int GnssI2C::send(const char* buf, int len) -{ - int sent = 0; - if (len) - { - if (!I2C::write(_i2cAdr,®STREAM,sizeof(REGSTREAM),true)) - sent = send(buf, len); - stop(); - } - return sent; -} - -int GnssI2C::sendNmea(const char* buf, int len) -{ - int sent = 0; - if (!I2C::write(_i2cAdr,®STREAM,sizeof(REGSTREAM),true)) - sent = GnssParser::sendNmea(buf, len); - stop(); - return sent; -} - -int GnssI2C::sendUbx(unsigned char cls, unsigned char id, const void* buf, int len) -{ - int sent = 0; - if (!I2C::write(_i2cAdr,®STREAM,sizeof(REGSTREAM),true)) - sent = GnssParser::sendUbx(cls, id, buf, len); - I2C::stop(); - return sent; -} - -int GnssI2C::_get(char* buf, int len) -{ - int read = 0; - unsigned char sz[2] = {0,0}; - if (!I2C::write(_i2cAdr,®LEN,sizeof(REGLEN),true) && - !I2C::read(_i2cAdr,(char*)sz,sizeof(sz))) - { - int size = 256 * (int)sz[0] + sz[1]; - if (size > len) - size = len; - if (size > 0) - { - if (!I2C::write(_i2cAdr,®STREAM,sizeof(REGSTREAM),true) && - !I2C::read(_i2cAdr,buf,size)) { - read = size; - } - } - } - return read; -} - -int GnssI2C::_send(const void* buf, int len) -{ - return !I2C::write(_i2cAdr,(const char*)buf,len,true) ? len : 0; -} - -const char GnssI2C::REGLEN = 0xFD; -const char GnssI2C::REGSTREAM = 0xFF; - -// End Of File
--- a/gnss/gnss.h Fri Aug 30 13:05:19 2019 +0500 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,342 +0,0 @@ -/* mbed Microcontroller Library - * Copyright (c) 2017 u-blox - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef GNSS_H -#define GNSS_H - -/** - * @file gnss.h - * This file defines a class that communicates with a u-blox GNSS chip. - */ - -#include "mbed.h" -#include "pipe.h" -#include "serial_pipe.h" - -#if defined (TARGET_UBLOX_C030) || defined (TARGET_UBLOX_C027) -# define GNSS_IF(onboard, shield) onboard -#else -# define GNSS_IF(onboard, shield) shield -#endif - -#ifdef TARGET_UBLOX_C027 -# define GNSSEN GPSEN -# define GNSSTXD GPSTXD -# define GNSSRXD GPSRXD -# define GNSSBAUD GPSBAUD -#endif - -/** Basic GNSS parser class. -*/ -class GnssParser -{ -public: - /** Constructor. - */ - GnssParser(); - /** Destructor. - */ - virtual ~GnssParser(void); - - /** Power-on/wake-up the GNSS. - */ - virtual bool init(PinName pn) = 0; - - enum { - // getLine Responses - WAIT = -1, //!< wait for more incoming data (the start of a message was found, or no data available) - NOT_FOUND = 0, //!< a parser concluded the the current offset of the pipe doe not contain a valid message - - #define LENGTH(x) (x & 0x00FFFF) //!< extract/mask the length - #define PROTOCOL(x) (x & 0xFF0000) //!< extract/mask the type - - UNKNOWN = 0x000000, //!< message type is unknown - UBX = 0x100000, //!< message if of protocol NMEA - NMEA = 0x200000 //!< message if of protocol UBX - }; - - /** Get a line from the physical interface. This function - * needs to be implemented in the inherited class. - * @param buf the buffer to store it. - * @param len size of the buffer. - * @return type and length if something was found, - * WAIT if not enough data is available, - * NOT_FOUND if nothing was found - */ - virtual int getMessage(char* buf, int len) = 0; - - /** Send a buffer. - * @param buf the buffer to write. - * @param len size of the buffer to write. - * @return bytes written. - */ - virtual int send(const char* buf, int len); - - /** send a NMEA message, this function just takes the - * payload and calculates and adds checksum. ($ and *XX\r\n will be added). - * @param buf the message payload to write. - * @param len size of the message payload to write. - * @return total bytes written. - */ - virtual int sendNmea(const char* buf, int len); - - /** Send a UBX message, this function just takes the - * payload and calculates and adds checksum. - * @param cls the UBX class id. - * @param id the UBX message id. - * @param buf the message payload to write. - * @param len size of the message payload to write. - * @return total bytes written. - */ - virtual int sendUbx(unsigned char cls, unsigned char id, - const void* buf = NULL, int len = 0); - - /** Power off the GNSS, it can be again woken up by an - * edge on the serial port on the external interrupt pin. - */ - void powerOff(void); - - /** get the first character of a NMEA field. - * @param ix the index of the field to find. - * @param start the start of the buffer. - * @param end the end of the buffer. - * @return the pointer to the first character of the field. - */ - static const char* findNmeaItemPos(int ix, const char* start, const char* end); - - /** Extract a double value from a buffer containing a NMEA message. - * @param ix the index of the field to extract. - * @param buf the NMEA message. - * @param len the size of the NMEA message. - * @param val the extracted value. - * @return true if successful, false otherwise. - */ - static bool getNmeaItem(int ix, char* buf, int len, double& val); - - /** Extract a interger value from a buffer containing a NMEA message. - * @param ix the index of the field to extract. - * @param buf the NMEA message. - * @param len the size of the NMEA message. - * @param val the extracted value. - * @param base the numeric base to be used (e.g. 8, 10 or 16). - * @return true if successful, false otherwise. - */ - static bool getNmeaItem(int ix, char* buf, int len, int& val, int base/*=10*/); - - /** Extract a char value from a buffer containing a NMEA message. - * @param ix the index of the field to extract. - * @param buf the NMEA message. - * @param len the size of the NMEA message. - * @param val the extracted value. - * @return true if successful, false otherwise. - */ - static bool getNmeaItem(int ix, char* buf, int len, char& val); - - /** Extract a latitude/longitude value from a buffer containing a NMEA message. - * @param ix the index of the field to extract (will extract ix and ix + 1), - * @param buf the NMEA message, - * @param len the size of the NMEA message, - * @param val the extracted latitude or longitude, - * @return true if successful, false otherwise. - */ - static bool getNmeaAngle(int ix, char* buf, int len, double& val); - -protected: - /** Power on the GNSS module. - */ - void _powerOn(void); - - /** Get a line from the physical interface. - * @param pipe the receiveing pipe to parse messages . - * @param buf the buffer to store it. - * @param len size of the buffer. - * @return type and length if something was found, - * WAIT if not enough data is available, - * NOT_FOUND if nothing was found. - */ - static int _getMessage(Pipe<char>* pipe, char* buf, int len); - - /** Check if the current offset of the pipe contains a NMEA message. - * @param pipe the receiveing pipe to parse messages. - * @param len numer of bytes to parse at maximum. - * @return length if something was found (including the NMEA frame), - * WAIT if not enough data is available, - * NOT_FOUND if nothing was found. - */ - static int _parseNmea(Pipe<char>* pipe, int len); - - /** Check if the current offset of the pipe contains a UBX message. - * @param pipe the receiveing pipe to parse messages. - * @param len numer of bytes to parse at maximum. - * @return length if something was found (including the UBX frame), - * WAIT if not enough data is available, - * NOT_FOUND if nothing was found. - */ - static int _parseUbx(Pipe<char>* pipe, int len); - - /** Write bytes to the physical interface. This function - * needs to be implemented by the inherited class. - * @param buf the buffer to write. - * @param len size of the buffer to write. - * @return bytes written. - */ - virtual int _send(const void* buf, int len) = 0; - - static const char _toHex[16]; //!< num to hex conversion - DigitalInOut *_gnssEnable; //!< IO pin that enables GNSS -}; - -/** GNSS class which uses a serial port as physical interface. - */ -class GnssSerial : public SerialPipe, public GnssParser -{ -public: - /** Constructor. - * @param tx is the serial ports transmit pin (GNSS to CPU). - * @param rx is the serial ports receive pin (CPU to GNSS). - * @param baudrate the baudrate of the GNSS use 9600. - * @param rxSize the size of the serial rx buffer. - * @param txSize the size of the serial tx buffer. - */ - GnssSerial(PinName tx GNSS_IF( = GNSSTXD, = D8 /* = D8 */), // resistor on shield not populated - PinName rx GNSS_IF( = GNSSRXD, = D9 /* = D9 */), // resistor on shield not populated - int baudrate GNSS_IF( = GNSSBAUD, = 9600 ), - int rxSize = 256 , - int txSize = 128 ); - - /** Destructor. - */ - virtual ~GnssSerial(void); - - /** Initialise the GNSS device. - * @param pn NOT USED. - * @return true if successful, otherwise false. - */ - virtual bool init(PinName pn = NC); - - /** Get a line from the physical interface. - * @param buf the buffer to store it. - * @param len size of the buffer. - * @return type and length if something was found, - * WAIT if not enough data is available, - * NOT_FOUND if nothing was found. - */ - virtual int getMessage(char* buf, int len); - -protected: - /** Write bytes to the physical interface. - * @param buf the buffer to write. - * @param len size of the buffer to write. - * @return bytes written. - */ - virtual int _send(const void* buf, int len); -}; - -/** GNSS class which uses a i2c as physical interface. -*/ -class GnssI2C : public I2C, public GnssParser -{ -public: - /** Constructor. - * @param sda is the I2C SDA pin (between CPU and GNSS). - * @param scl is the I2C SCL pin (CPU to GNSS). - * @param adr the I2C address of the GNSS set to (66<<1). - * @param rxSize the size of the serial rx buffer. - */ - GnssI2C(PinName sda GNSS_IF( = NC, = /* D16 TODO */ NC ), - PinName scl GNSS_IF( = NC, = /* D17 TODO */ NC ), - unsigned char i2cAdr GNSS_IF( = (66<<1), = (66<<1) ), - int rxSize = 256 ); - /** Destructor - */ - virtual ~GnssI2C(void); - - /** Helper function to probe the i2c device. - * @param pn the power-on pin for the chip. - * @return true if successfully detected the GNSS chip. - */ - virtual bool init(PinName pn = GNSS_IF( NC, NC /* D7 resistor R67 on shield not mounted */)); - - /** Get a line from the physical interface. - * @param buf the buffer to store it. - * @param len size of the buffer. - * @return type and length if something was found, - * WAIT if not enough data is available, - * NOT_FOUND if nothing was found. - */ - virtual int getMessage(char* buf, int len); - - /** Send a buffer. - * @param buf the buffer to write. - * @param len size of the buffer to write. - * @return bytes written. - */ - virtual int send(const char* buf, int len); - - /** Send an NMEA message, this function just takes the - * payload and calculates and adds checksum ($ and *XX\r\n will be added). - * @param buf the message payload to write. - * @param len size of the message payload to write. - * @return total bytes written. - */ - virtual int sendNmea(const char* buf, int len); - - /** Send a UBX message, this function just takes the - * payload and calculates and adds checksum. - * @param cls the UBX class id. - * @param id the UBX message id. - * @param buf the message payload to write. - * @param len size of the message payload to write. - * @return total bytes written. - */ - virtual int sendUbx(unsigned char cls, unsigned char id, - const void* buf = NULL, int len = 0); - -protected: - /** Check if the port is writeable (like SerialPipe) - * @return true if writeable - */ - bool writeable(void) {return true;} - - /** Write a character (like SerialPipe). - * @param c the character to write. - * @return true if succesffully written . - */ - bool putc(int c) {char ch = c; return send(&ch, 1);} - - /** Write bytes to the physical interface. - * @param buf the buffer to write. - * @param len size of the buffer to write. - * @return bytes written. - */ - virtual int _send(const void* buf, int len); - - /** Read bytes from the physical interface. - * @param buf the buffer to read into. - * @param len size of the read buffer . - * @return bytes read. - */ - int _get(char* buf, int len); - - Pipe<char> _pipe; //!< the rx pipe. - unsigned char _i2cAdr; //!< the i2c address. - static const char REGLEN; //!< the length i2c register address. - static const char REGSTREAM;//!< the stream i2c register address. -}; - -#endif - -// End Of File
--- a/gnss/pipe.h Fri Aug 30 13:05:19 2019 +0500 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,262 +0,0 @@ -/* Copyright (c) 2017 Michael Ammann - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef PIPE_H -#define PIPE_H - -/** pipe, this class implements a buffered pipe that can be savely - written and read between two context. E.g. Written from a task - and read from a interrupt. -*/ -template <class T> -class Pipe -{ -public: - /* Constructor - \param n size of the pipe/buffer - \param b optional buffer that should be used. - if NULL the constructor will allocate a buffer of size n. - */ - Pipe(int n, T* b = NULL) - { - _a = b ? NULL : n ? new T[n] : NULL; - _r = 0; - _w = 0; - _b = b ? b : _a; - _s = n; - } - /** Destructor - frees a allocated buffer. - */ - ~Pipe(void) - { - if (_a) - delete [] _a; - } - - /* This function can be used during debugging to hexdump the - content of a buffer to the stdout. - */ - void dump(void) - { - int o = _r; - printf("pipe: %d/%d ", size(), _s); - while (o != _w) { - T t = _b[o]; - printf("%0*X", sizeof(T)*2, t); - o = _inc(o); - } - printf("\n"); - } - - // writing thread/context API - //------------------------------------------------------------- - - /** Check if buffer is writeable (=not full) - \return true if writeable - */ - bool writeable(void) - { - return free() > 0; - } - - /** Return the number of free elements in the buffer - \return the number of free elements - */ - int free(void) - { - int s = _r - _w; - if (s <= 0) - s += _s; - return s - 1; - } - - /* Add a single element to the buffer. (blocking) - \param c the element to add. - \return c - */ - T putc(T c) - { - int i = _w; - int j = i; - i = _inc(i); - while (i == _r) // = !writeable() - /* nothing / just wait */; - _b[j] = c; - _w = i; - return c; - } - - /* Add a buffer of elements to the buffer. - \param p the elements to add - \param n the number elements to add from p - \param t set to true if blocking, false otherwise - \return number elements added - */ - int put(const T* p, int n, bool t = false) - { - int c = n; - while (c) - { - int f; - for (;;) // wait for space - { - f = free(); - if (f > 0) break; // data avail - if (!t) return n - c; // no more space and not blocking - /* nothing / just wait */; - } - // check free space - if (c < f) f = c; - int w = _w; - int m = _s - w; - // check wrap - if (f > m) f = m; - memcpy(&_b[w], p, f); - _w = _inc(w, f); - c -= f; - p += f; - } - return n - c; - } - - // reading thread/context API - // -------------------------------------------------------- - - /** Check if there are any emelemnt available (readble / not empty) - \return true if readable/not empty - */ - bool readable(void) - { - return (_r != _w); - } - - /** Get the number of values available in the buffer - return the number of element available - */ - int size(void) - { - int s = _w - _r; - if (s < 0) - s += _s; - return s; - } - - /** get a single value from buffered pipe (this function will block if no values available) - \return the element extracted - */ - T getc(void) - { - int r = _r; - while (r == _w) // = !readable() - /* nothing / just wait */; - T t = _b[r]; - _r = _inc(r); - return t; - } - - /*! get elements from the buffered pipe - \param p the elements extracted - \param n the maximum number elements to extract - \param t set to true if blocking, false otherwise - \return number elements extracted - */ - int get(T* p, int n, bool t = false) - { - int c = n; - while (c) - { - int f; - for (;;) // wait for data - { - f = size(); - if (f) break; // free space - if (!t) return n - c; // no space and not blocking - /* nothing / just wait */; - } - // check available data - if (c < f) f = c; - int r = _r; - int m = _s - r; - // check wrap - if (f > m) f = m; - memcpy(p, &_b[r], f); - _r = _inc(r, f); - c -= f; - p += f; - } - return n - c; - } - - // the following functions are useful if you like to inspect - // or parse the buffer in the reading thread/context - // -------------------------------------------------------- - - /** set the parsing index and return the number of available - elments starting this position. - \param ix the index to set. - \return the number of elements starting at this position - */ - int set(int ix) - { - int sz = size(); - ix = (ix > sz) ? sz : ix; - _o = _inc(_r, ix); - return sz - ix; - } - - /** get the next element from parsing position and increment parsing index - \return the extracted element. - */ - T next(void) - { - int o = _o; - T t = _b[o]; - _o = _inc(o); - return t; - } - - /** commit the index, mark the current parsing index as consumed data. - */ - void done(void) - { - _r = _o; - } - -private: - /** increment the index - \param i index to increment - \param n the step to increment - \return the incremented index. - */ - inline int _inc(int i, int n = 1) - { - i += n; - if (i >= _s) - i -= _s; - return i; - } - - T* _b; //!< buffer - T* _a; //!< allocated buffer - int _s; //!< size of buffer (s - 1) elements can be stored - volatile int _w; //!< write index - volatile int _r; //!< read index - int _o; //!< offest index used by parsing functions -}; - -#endif - -// End Of File
--- a/gnss/serial_pipe.cpp Fri Aug 30 13:05:19 2019 +0500 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,129 +0,0 @@ -/* Copyright (c) 2017 Michael Ammann - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "serial_pipe.h" - -SerialPipe::SerialPipe(PinName tx, PinName rx, int baudrate, int rxSize, int txSize) : - _SerialPipeBase(tx, rx, baudrate), - _pipeRx( (rx!=NC) ? rxSize : 0), - _pipeTx( (tx!=NC) ? txSize : 0) -{ - if (rx!=NC) { - attach(callback(this, &SerialPipe::rxIrqBuf), RxIrq); - } -} - -SerialPipe::~SerialPipe(void) -{ - attach(NULL, RxIrq); - attach(NULL, TxIrq); -} - -// tx channel -int SerialPipe::writeable(void) -{ - return _pipeTx.free(); -} - -int SerialPipe::putc(int c) -{ - c = _pipeTx.putc(c); - txStart(); - return c; -} - -int SerialPipe::put(const void* buffer, int length, bool blocking) -{ - int count = length; - const char* ptr = (const char*)buffer; - if (count) { - do { - int written = _pipeTx.put(ptr, count, false); - if (written) { - ptr += written; - count -= written; - txStart(); - } - else if (!blocking) { - /* nothing / just wait */; - break; - } - } - while (count); - } - - return (length - count); -} - -void SerialPipe::txCopy(void) -{ - while (_SerialPipeBase::writeable() && _pipeTx.readable()) { - char c = _pipeTx.getc(); - _SerialPipeBase::_base_putc(c); - } -} - -void SerialPipe::txIrqBuf(void) -{ - txCopy(); - // detach tx isr if we are done - if (!_pipeTx.readable()) { - attach(NULL, TxIrq); - } -} - -void SerialPipe::txStart(void) -{ - // disable the tx isr to avoid interruption - attach(NULL, TxIrq); - txCopy(); - // attach the tx isr to handle the remaining data - if (_pipeTx.readable()) { - attach(callback(this, &SerialPipe::txIrqBuf), TxIrq); - } -} - -// rx channel -int SerialPipe::readable(void) -{ - return _pipeRx.readable(); -} - -int SerialPipe::getc(void) -{ - if (!_pipeRx.readable()) { - return EOF; - } - - return _pipeRx.getc(); -} - -int SerialPipe::get(void* buffer, int length, bool blocking) -{ - return _pipeRx.get((char*)buffer,length,blocking); -} - -void SerialPipe::rxIrqBuf(void) -{ - while (_SerialPipeBase::readable()) - { - char c = _SerialPipeBase::_base_getc(); - if (_pipeRx.writeable()) { - _pipeRx.putc(c); - } else { - /* overflow */ - } - } -}
--- a/gnss/serial_pipe.h Fri Aug 30 13:05:19 2019 +0500 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,102 +0,0 @@ -/* Copyright (c) 2017 Michael Ammann - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef SERIAL_PIPE_H -#define SERIAL_PIPE_H - -#include "mbed.h" -#include "pipe.h" - -#define _SerialPipeBase SerialBase //!< base class used by this class - -/** Buffered serial interface (rtos capable/interrupt driven) -*/ -class SerialPipe : public _SerialPipeBase -{ -public: - /** Constructor - \param tx the trasmitting pin - \param rx the receiving pin - \param baudate the serial baud rate - \param rxSize the size of the receiving buffer - \param txSize the size of the transmitting buffer - */ - SerialPipe(PinName tx, PinName rx, int baudrate, int rxSize = 128, int txSize = 128); - - /** Destructor - */ - virtual ~SerialPipe(void); - - // tx channel - //---------------------------------------------------- - - /** check if writable - return the number of free bytes - */ - int writeable(void); - - /** send a character (blocking) - \param c the character to send - \return c - */ - int putc(int c); - - /** send a buffer - \param buffer the buffer to send - \param length the size of the buffer to send - \param blocking, if true this function will block - until all bytes placed in the buffer. - \return the number of bytes written - */ - int put(const void* buffer, int length, bool blocking); - - // rx channel - //---------------------------------------------------- - - /** check if readable - * - \return the size available in the buffer. - */ - int readable(void); - - /** receive one character from the serial port (blocking) - \param the character received - */ - int getc(void); - - /** read a buffer from the serial port - \param pointer to the buffer to read. - \param length number of bytes to read - \param blocking true if all bytes shall be read. false if only the available bytes. - \return the number of bytes read. - */ - int get(void* buffer, int length, bool blocking); - -protected: - //! receive interrupt routine - void rxIrqBuf(void); - //! transmit interrupt woutine - void txIrqBuf(void); - //! start transmission helper - void txStart(void); - //! move bytes to hardware - void txCopy(void); - Pipe<char> _pipeRx; //!< receive pipe - Pipe<char> _pipeTx; //!< transmit pipe -}; - -#endif - -// End Of File