diff --git a/externs.h b/externs.h index 1607192..a9a9b0e 100644 --- a/externs.h +++ b/externs.h @@ -1,5 +1,9 @@ #ifndef EXTERNS_H #define EXTERNS_H extern I2C i2c; +#if MBED_MAJOR_VERSION == 6 +extern UnbufferedSerial pc; +#elif MBED_MAJOR_VERSION == 5 extern Serial pc; #endif +#endif diff --git a/main.cpp b/main.cpp index 3c566a8..55791a3 100644 --- a/main.cpp +++ b/main.cpp @@ -2,34 +2,32 @@ #include "src/SparkFun_I2C_GPS_Reading_and_Control/SparkFun_I2C_GPS_Arduino_Library.h" #include "externs.h" -I2C i2c(I2C1_SDA, I2C1_SCL); -Serial pc(USBTX, USBRX, 115200); +I2C i2c(I2C_SDA, I2C_SCL); +//Serial pc(USBTX, USBRX, 115200); //Line not needed in Mbed OS V6, uncomment if using Mbed OS V5 I2CGPS myI2CGPS; string configString; - // main() runs in its own thread in the OS int main() { while (myI2CGPS.begin(i2c, 400000) == false) { - pc.printf("Module failed to respond. Please check wiring.\n"); + printf("Module failed to respond. Please check wiring.\n"); ThisThread::sleep_for(500); } - pc.printf("GPS module found!\n"); + printf("GPS module found!\n"); /* if GPS module is found let us configure it */ // setup PPS LED configString = myI2CGPS.createMTKpacket(285, ",4,25"); myI2CGPS.sendMTKpacket(configString); - while (true) { - while (myI2CGPS.available()) // available() returns the number of new bytes - // available from the GPS module + while (myI2CGPS.available()) // available() returns the number of new bytes available from the GPS module { - uint8_t incoming = myI2CGPS.read(); //Read the latest byte from Qwiic GPS - if(incoming == '$') pc.printf("\n"); //Break the sentences onto new lines - pc.printf("%c", incoming); //Print this character + uint8_t incoming = myI2CGPS.read(); // Read the latest byte from Qwiic GPS + if (incoming == '$') + printf("\n"); // Break the sentences onto new lines + printf("%c", incoming); // Print this character } } return 0; diff --git a/src/SparkFun_I2C_GPS_Arduino_Library.cpp b/src/SparkFun_I2C_GPS_Arduino_Library.cpp index 038c358..3d1a17a 100644 --- a/src/SparkFun_I2C_GPS_Arduino_Library.cpp +++ b/src/SparkFun_I2C_GPS_Arduino_Library.cpp @@ -1,13 +1,14 @@ /* - This is a library written for the MediaTek MT3333 based GPS module with I2C firmware - specially loaded. SparkFun sells these at its website: www.sparkfun.com + This is a library written for the MediaTek MT3333 based GPS module with I2C + firmware specially loaded. SparkFun sells these at its website: + www.sparkfun.com Written by Nathan Seidle @ SparkFun Electronics, April 25th, 2017 This GPS module is special because it can use an I2C interface to communicate. - This library handles the pulling in of data over I2C. We recommend a parsing engine - such as TinyGPS. + This library handles the pulling in of data over I2C. We recommend a parsing + engine such as TinyGPS. https://github.com/sparkfun/SparkFun_I2C_GPS_Arduino_Library @@ -33,12 +34,11 @@ char dummy = 0; #endif -//Sets up the sensor for constant read -//Returns false if sensor does not respond -#if defined (ARDUINO) -boolean I2CGPS::begin(TwoWire &wirePort, uint32_t i2cSpeed) -{ - //Bring in the user's choices +// Sets up the sensor for constant read +// Returns false if sensor does not respond +#if defined(ARDUINO) +boolean I2CGPS::begin(TwoWire &wirePort, uint32_t i2cSpeed) { + // Bring in the user's choices _i2cPort = &wirePort; //Grab which port the user wants us to use _i2cPort->begin(); @@ -47,7 +47,7 @@ boolean I2CGPS::begin(TwoWire &wirePort, uint32_t i2cSpeed) _head = 0; //Reset the location holder _tail = 0; - //Ping the module to see if it responds + // Ping the module to see if it responds _i2cPort->beginTransmission(MT333x_ADDR); _i2cPort->write(0); //Write dummy value _i2cPort->endTransmission(); @@ -59,9 +59,8 @@ boolean I2CGPS::begin(TwoWire &wirePort, uint32_t i2cSpeed) } #elif defined(__MBED__) -bool I2CGPS::begin(I2C &wirePort, uint32_t i2cSpeed) -{ - //Bring in the user's choices +bool I2CGPS::begin(I2C &wirePort, uint32_t i2cSpeed) { + // Bring in the user's choices _i2cPort = &wirePort; //Grab which port the user wants us to use _i2cPort->frequency(i2cSpeed); @@ -69,59 +68,60 @@ bool I2CGPS::begin(I2C &wirePort, uint32_t i2cSpeed) _head = 0; //Reset the location holder _tail = 0; - _i2cPort->write(MT333x_ADDR << 1, (char *) &dummy, sizeof(dummy)); + _i2cPort->write(MT333x_ADDR << 1, (char *)&dummy, sizeof(dummy)); - if (0 == _i2cPort->read(MT333x_ADDR << 1|1, (char *) &dummy, sizeof(dummy))) // might fail if current is unstable on GPIO pins + if (0 == _i2cPort->read(MT333x_ADDR << 1 | 1, (char *)&dummy, sizeof(dummy))) //might fail if current is unstable on GPIO pins return (true); else return (false); } #endif -//Polls the GPS module to see if new data is available -//Reads a 255 byte packet from GPS module -//If new data is there, appends it to the gpsData array -//Function requires 26ms @ 100kHz I2C, 9ms @ 400kHz I2C so call sparingly -void I2CGPS::check() -{ - //TODO: Re-write this function to be less tied to Arduino's 32 byte limit - //Maybe pass a maxRead during .begin() +// Polls the GPS module to see if new data is available +// Reads a 255 byte packet from GPS module +// If new data is there, appends it to the gpsData array +// Function requires 26ms @ 100kHz I2C, 9ms @ 400kHz I2C so call sparingly +void I2CGPS::check() { + // TODO: Re-write this function to be less tied to Arduino's 32 byte limit + // Maybe pass a maxRead during .begin() - for (uint8_t x = 0; x < MAX_PACKET_SIZE; x++) - { - #if defined (ARDUINO) - if (x % 32 == 0) //Arduino can only Wire.read() in 32 byte chunks. Yay. - _i2cPort->requestFrom(MT333x_ADDR, 32); //Request 32 more bytes + for (uint8_t x = 0; x < MAX_PACKET_SIZE; x++) { +#if defined(ARDUINO) + if (x % 32 == 0) //Arduino can only Wire.read() in 32 byte chunks. Yay. + _i2cPort->requestFrom(MT333x_ADDR, 32); // Request 32 more bytes uint8_t incoming = _i2cPort->read(); - #elif defined (__MBED__) +#elif defined(__MBED__) uint8_t incoming; - _i2cPort->read(MT333x_ADDR << 1|1, (char *)&incoming, 1); - #endif + _i2cPort->read(MT333x_ADDR << 1 | 1, (char *)&incoming, 1); +#endif - if (incoming != 0x0A) - { + if (incoming != 0x0A) { //Record this byte gpsData[_head++] = incoming; _head %= MAX_PACKET_SIZE; //Wrap variable - if (_printDebug == true && _head == _tail) - #if defined (ARDUINO) + if (_printDebug == true && _head == _tail) { + #if defined(ARDUINO) _debugSerial->println(F("Buffer overrun")); - #elif defined (__MBED__) - _debugSerial->printf("Buffer overrun\n"); + #elif defined(__MBED__) + const char response[16] = "Buffer overrun\n"; + #if MBED_MAJOR_VERSION == 6 + _debugSerial->write(response, sizeof(response)); + #elif MBED_MAJOR_VERSION == 5 + _debugSerial->printf(response); #endif + #endif + } } } } //Returns # of available bytes that can be read -uint8_t I2CGPS::available() -{ +uint8_t I2CGPS::available() { //If tail=head then no new data is available in the local buffer //So now check to see if the module has anything new in its buffer - if (_tail == _head) - { + if (_tail == _head) { check(); //Check to module to see if new I2C bytes are available } @@ -130,35 +130,38 @@ uint8_t I2CGPS::available() return (_head - _tail); if (_tail > _head) return (MAX_PACKET_SIZE - _tail + _head); - return (0); //No data available + return (0); // No data available } //Returns the next available byte from the gpsData array //Returns 0 if no byte available -uint8_t I2CGPS::read(void) -{ - if (_tail != _head) - { +uint8_t I2CGPS::read(void) { + if (_tail != _head) { uint8_t datum = gpsData[_tail++]; if (_tail == MAX_PACKET_SIZE) _tail = 0; //Wrap variable return (datum); - } - else + } else return (0); //No new data } //Enables serial printing of local error messages -void I2CGPS::enableDebugging(Stream &debugPort) -{ - _debugSerial = &debugPort; //Grab which port the user wants us to use for debugging +#if defined(ARDUINO) +void I2CGPS::enableDebugging(Stream &debugPort) { +#elif MBED_MAJOR_VERSION == 6 +void I2CGPS::enableDebugging(UnbufferedSerial &debugPort) { +#elif MBED_MAJOR_VERSION == 5 +void I2CGPS::enableDebugging(Serial &debugPort) { +#endif + + _debugSerial = + &debugPort; //Grab which port the user wants us to use for debugging _printDebug = true; //Should we print the commands we send? Good for debugging } //Turn off printing of GPS character streams -void I2CGPS::disableDebugging() -{ +void I2CGPS::disableDebugging() { _printDebug = false; //Turn off extra print statements } @@ -166,13 +169,12 @@ void I2CGPS::disableDebugging() //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= //Send a given command or configuration string to the module -//The input buffer on the MTK is 255 bytes. Caller must keep strings shorter than 255 bytes -//Any time you end transmission you must give the module 10ms to process bytes -#if defined (ARDUINO) -boolean I2CGPS::sendMTKpacket(String command) -{ - if (command.length() > 255) - { +//The input buffer on the MTK is 255 bytes. Caller must keep strings shorter +//than 255 bytes Any time you end transmission you must give the module 10ms to +//process bytes +#if defined(ARDUINO) +boolean I2CGPS::sendMTKpacket(String command) { + if (command.length() > 255) { if (_printDebug == true) _debugSerial->println(F("Command message too long!")); @@ -180,13 +182,14 @@ boolean I2CGPS::sendMTKpacket(String command) } //Arduino can only Wire.write() in 32 byte chunks. Yay. - for (uint8_t chunk = 0; chunk < 7; chunk++) //8 chunks * 32 = 256 bytes total so we need to shave one + for (uint8_t chunk = 0; chunk < 7; + chunk++) // 8 chunks * 32 = 256 bytes total so we need to shave one { _i2cPort->beginTransmission(MT333x_ADDR); for (uint8_t x = 0; x < 32; x++) //Send out 32 bytes { if ((chunk * 32 + x) == command.length()) - break; //We're done! + break; // We're done! _i2cPort->write(command[(chunk * 32) + x]); } _i2cPort->endTransmission(); @@ -195,13 +198,14 @@ boolean I2CGPS::sendMTKpacket(String command) } //Send final 31 bytes - if (command.length() > (7 * 32)) //Do we have more than 224 bytes? Then send last 31 + if (command.length() > + (7 * 32)) //Do we have more than 224 bytes? Then send last 31 { _i2cPort->beginTransmission(MT333x_ADDR); for (uint8_t x = 0; x < 31; x++) //Write any remaining bytes up to 255 { if ((7 * 32 + x) == command.length()) - break; //We're done! + break; // We're done! _i2cPort->write(command[(7 * 32) + x]); } _i2cPort->endTransmission(); @@ -210,17 +214,20 @@ boolean I2CGPS::sendMTKpacket(String command) return (true); } -#elif defined (__MBED__) -bool I2CGPS::sendMTKpacket(string command) -{ - if (command.length() > 255) - { - if (_printDebug == true) - _debugSerial->printf("Command message too long!\n"); - +#elif defined(__MBED__) +bool I2CGPS::sendMTKpacket(string command) { + if (command.length() > 255) { + if (_printDebug == true) { + const char response[28] = "Command message too long!\n"; +#if MBED_MAJOR_VERSION == 6 + _debugSerial->write(response, sizeof(response)); +#elif MBED_MAJOR_VERSION == 5 + _debugSerial->printf(response); +#endif + } return (false); } - + _i2cPort->write(MT333x_ADDR << 1, command.c_str(), command.length()); ThisThread::sleep_for(10); @@ -232,14 +239,12 @@ bool I2CGPS::sendMTKpacket(string command) //config sentence complete with CRC and \r \n ending bytes //PMTK uses a different packet numbers to do configure the module. //These vary from 0 to 999. See 'MTK NMEA Packet' datasheet for more info. -#if defined (ARDUINO) -String I2CGPS::createMTKpacket(uint16_t packetType, String dataField) -{ +#if defined(ARDUINO) +String I2CGPS::createMTKpacket(uint16_t packetType, String dataField) { //Build config sentence using packetType String configSentence = ""; -#elif defined (__MBED__) -string I2CGPS::createMTKpacket(uint16_t packetType, string dataField) -{ +#elif defined(__MBED__) +string I2CGPS::createMTKpacket(uint16_t packetType, string dataField) { //Build config sentence using packetType string configSentence = ""; #endif @@ -251,15 +256,14 @@ string I2CGPS::createMTKpacket(uint16_t packetType, string dataField) configSentence += "0"; if (packetType < 10) configSentence += "0"; -#if defined (ARDUINO) +#if defined(ARDUINO) configSentence += String(packetType); -#elif defined (__MBED__) +#elif defined(__MBED__) configSentence += to_string(packetType); #endif //Attach any settings - if (dataField.length() > 0) - { + if (dataField.length() > 0) { configSentence += dataField; //Attach the string of flags } @@ -275,59 +279,54 @@ string I2CGPS::createMTKpacket(uint16_t packetType, string dataField) } //Calculate CRC for MTK messages -//Given a string of characters, XOR them all together and return CRC in string form -#if defined (ARDUINO) -String I2CGPS::calcCRCforMTK(String sentence) -{ -#elif defined (__MBED__) -string I2CGPS::calcCRCforMTK(string sentence) -{ +//Given a string of characters, XOR them all together and return CRC in string +//form +#if defined(ARDUINO) +String I2CGPS::calcCRCforMTK(String sentence) { +#elif defined(__MBED__) +string I2CGPS::calcCRCforMTK(string sentence) { #endif uint8_t crc = 0; //We need to ignore the first character $ //And the last character * for (uint8_t x = 1; x < sentence.length() - 1; x++) - crc ^= sentence[x]; //XOR this byte with all the others + crc ^= sentence[x]; // XOR this byte with all the others - #if defined (ARDUINO) +#if defined(ARDUINO) String output = ""; - #elif defined (__MBED__) +#elif defined(__MBED__) string output = ""; - #endif +#endif if (crc < 10) output += "0"; //Append leading zero if needed - #if defined (ARDUINO) +#if defined(ARDUINO) output += String(crc, HEX); - #elif defined (__MBED__) +#elif defined(__MBED__) static char outhex[4]; sprintf(outhex, "%02X", crc); output += outhex; - #endif +#endif return (output); } -#if defined (ARDUINO) -boolean I2CGPS::sendPGCMDpacket(String command) -{ -#elif defined (__MBED__) -bool I2CGPS::sendPGCMDpacket(string command) -{ +#if defined(ARDUINO) +boolean I2CGPS::sendPGCMDpacket(String command) { +#elif defined(__MBED__) +bool I2CGPS::sendPGCMDpacket(string command) { #endif - return (sendMTKpacket(command)); // Send process is the same, re-named to ease user's minds + return (sendMTKpacket(command)); //Send process is the same, re-named to ease user's minds } -#if defined (ARDUINO) -String I2CGPS::createPGCMDpacket(uint16_t packetType, String dataField) -{ +#if defined(ARDUINO) +String I2CGPS::createPGCMDpacket(uint16_t packetType, String dataField) { //Build config sentence using packetType String configSentence = ""; -#elif defined (__MBED__) -string I2CGPS::createPGCMDpacket(uint16_t packetType, string dataField) -{ +#elif defined(__MBED__) +string I2CGPS::createPGCMDpacket(uint16_t packetType, string dataField) { //Build config sentence using packetType string configSentence = ""; #endif @@ -339,25 +338,24 @@ string I2CGPS::createPGCMDpacket(uint16_t packetType, string dataField) configSentence += "0"; if (packetType < 10) configSentence += "0"; -#if defined (ARDUINO) +#if defined(ARDUINO) configSentence += String(packetType); -#elif defined (__MBED__) +#elif defined(__MBED__) configSentence += to_string(packetType); #endif //Attach any settings - if (dataField.length() > 0) - { - configSentence += dataField; //Attach the string of flags + if (dataField.length() > 0) { + configSentence += dataField; // Attach the string of flags } configSentence += "*"; //Attach end tag - configSentence += calcCRCforMTK(configSentence); //Attach CRC - uses the same crc as PTMK + configSentence += calcCRCforMTK(configSentence); // Attach CRC - uses the same crc as PTMK //Attach ending bytes configSentence += '\r'; //Carriage return configSentence += '\n'; //Line feed return (configSentence); -} +} diff --git a/src/SparkFun_I2C_GPS_Arduino_Library.h b/src/SparkFun_I2C_GPS_Arduino_Library.h index 70d5233..8ee14db 100644 --- a/src/SparkFun_I2C_GPS_Arduino_Library.h +++ b/src/SparkFun_I2C_GPS_Arduino_Library.h @@ -38,7 +38,7 @@ #include "externs.h" #include #include -#include "TinyGPSPlus/TinyGPS++.h" +//#include "TinyGPSPlus/TinyGPS++.h" //uncomment if you also wish to parse the NMEA sentences #endif @@ -69,7 +69,12 @@ class I2CGPS { #if defined(ARDUINO) void enableDebugging(Stream &debugPort = Serial); //Output various extra messages to help with debug #elif defined (__MBED__) - void enableDebugging(Stream &debugPort = pc); + #if MBED_MAJOR_VERSION == 6 + void enableDebugging(UnbufferedSerial &debugPort = pc); + #elif MBED_MAJOR_VERSION == 5 + void enableDebugging(Serial &debugPort = pc); + #endif + #endif void disableDebugging(); @@ -101,16 +106,19 @@ class I2CGPS { #if defined(ARDUINO) TwoWire *_i2cPort; //The generic connection to user's chosen I2C hardware boolean _printDebug = false; //Flag to print the serial commands we are sending to the Serial port for debug + Stream *_debugSerial; //The stream to send debug messages to if enabled + #elif defined (__MBED__) I2C *_i2cPort; //The generic connection to user's chosen I2C hardware bool _printDebug = false; //Flag to print the serial commands we are sending to the Serial port for debug - #endif uint8_t _i2caddr; - - - - Stream *_debugSerial; //The stream to send debug messages to if enabled + #if MBED_MAJOR_VERSION == 6 + UnbufferedSerial *_debugSerial; + #elif MBED_MAJOR_VERSION == 5 + Serial *_debugSerial; //The stream to send debug messages to if enabled + #endif + #endif uint8_t _head; //Location of next available spot in the gpsData array. Limited to 255. uint8_t _tail; //Location of last spot read from gpsData array. Limited to 255. -}; +};