From 7bb6e004a6151b0a97cec685963b2b47b8eeb2d0 Mon Sep 17 00:00:00 2001 From: Lady Ada Date: Sat, 16 Nov 2019 19:06:07 -0500 Subject: [PATCH] add SPI support - tested with TitanX1. --- Adafruit_GPS.cpp | 76 ++++++++++++++++--- Adafruit_GPS.h | 9 ++- .../GPS_SPI_EchoTest/GPS_SPI_EchoTest.ino | 41 ++++++++++ 3 files changed, 112 insertions(+), 14 deletions(-) create mode 100644 examples/GPS_SPI_EchoTest/GPS_SPI_EchoTest.ino diff --git a/Adafruit_GPS.cpp b/Adafruit_GPS.cpp index b1551af..62f4b5d 100755 --- a/Adafruit_GPS.cpp +++ b/Adafruit_GPS.cpp @@ -455,8 +455,8 @@ size_t Adafruit_GPS::available(void) { if (gpsHwSerial) { return gpsHwSerial->available(); } - if (gpsI2C) { - return 1; // I2C doesnt have 'availability' so always has a byte at least to read! + if (gpsI2C || gpsSPI) { + return 1; // I2C/SPI doesnt have 'availability' so always has a byte at least to read! } return 0; } @@ -486,6 +486,19 @@ size_t Adafruit_GPS::write(uint8_t c) { return 1; } } + if (gpsSPI) { + gpsSPI->beginTransaction(gpsSPI_settings); + if (gpsSPI_cs >= 0) { + digitalWrite(gpsSPI_cs, LOW); + } + c = gpsSPI->transfer(c); + if (gpsSPI_cs >= 0) { + digitalWrite(gpsSPI_cs, HIGH); + } + gpsSPI->endTransaction(); + return 1; + } + return 0; } @@ -515,14 +528,14 @@ char Adafruit_GPS::read(void) { c = gpsHwSerial->read(); } if (gpsI2C) { - if (_i2cbuff_idx <= _i2cbuff_max) { - c = _i2cbuffer[_i2cbuff_idx]; - _i2cbuff_idx++; + if (_buff_idx <= _buff_max) { + c = _i2cbuffer[_buff_idx]; + _buff_idx++; } else { // refill the buffer! if (Wire.requestFrom(0x10, GPS_MAX_I2C_TRANSFER, true) == GPS_MAX_I2C_TRANSFER) { // got data! - _i2cbuff_max = 0; + _buff_max = 0; char curr_char = 0; for (int i=0; ibeginTransaction(gpsSPI_settings); + if (gpsSPI_cs >= 0) { + digitalWrite(gpsSPI_cs, LOW); + } + c = gpsSPI->transfer(0xFF); + if (gpsSPI_cs >= 0) { + digitalWrite(gpsSPI_cs, HIGH); + } + gpsSPI->endTransaction(); + // skip duplicate 0x0A's - but keep as part of a CRLF + } while (((c == 0x0A) && (last_char != 0x0D)) || (!isprint(c) && !isspace(c)) ); + last_char = c; + } //Serial.print(c); currentline[lineidx++] = c; @@ -612,6 +640,20 @@ Adafruit_GPS::Adafruit_GPS(TwoWire *theWire) { gpsI2C = theWire; // ...override gpsI2C } +/**************************************************************************/ +/*! + @brief Constructor when using SPI + @param theSPI Pointer to an SPI device object + @param cspin The pin connected to the GPS CS, can be -1 if unused +*/ +/**************************************************************************/ +Adafruit_GPS::Adafruit_GPS(SPIClass *theSPI, int8_t cspin) { + common_init(); // Set everything to common state, then... + gpsSPI = theSPI; // ...override gpsSPI + gpsSPI_cs = cspin; +} + + /**************************************************************************/ /*! @brief Initialization code used by all constructor types @@ -623,6 +665,7 @@ void Adafruit_GPS::common_init(void) { #endif gpsHwSerial = NULL; // port pointer in corresponding constructor gpsI2C = NULL; + gpsSPI = NULL; recvdflag = false; paused = false; lineidx = 0; @@ -666,6 +709,15 @@ bool Adafruit_GPS::begin(uint32_t baud_or_i2caddr) gpsI2C->beginTransmission(_i2caddr); return (gpsI2C->endTransmission () == 0); } + if (gpsSPI) { + gpsSPI->begin(); + gpsSPI_settings = SPISettings(baud_or_i2caddr, MSBFIRST, SPI_MODE0); + if (gpsSPI_cs >= 0) { + pinMode(gpsSPI_cs, OUTPUT); + digitalWrite(gpsSPI_cs, HIGH); + } + } + delay(10); return true; } diff --git a/Adafruit_GPS.h b/Adafruit_GPS.h index a65fa59..19bb003 100644 --- a/Adafruit_GPS.h +++ b/Adafruit_GPS.h @@ -35,7 +35,7 @@ #include #endif #include - +#include /**************************************************************************/ /** @@ -112,6 +112,7 @@ class Adafruit_GPS : public Print{ #endif Adafruit_GPS(HardwareSerial *ser); // Constructor when using HardwareSerial Adafruit_GPS(TwoWire *theWire); // Constructor when using I2C + Adafruit_GPS(SPIClass *theSPI, int8_t cspin); // Constructor when using SPI char *lastNMEA(void); boolean newNMEAreceived(); @@ -208,9 +209,13 @@ class Adafruit_GPS : public Print{ #endif HardwareSerial *gpsHwSerial; TwoWire *gpsI2C; + SPIClass *gpsSPI; + int8_t gpsSPI_cs = -1; + SPISettings gpsSPI_settings = SPISettings(1000000, MSBFIRST, SPI_MODE0); // default + char _spibuffer[GPS_MAX_SPI_TRANSFER]; // for when we write data, we need to read it too! uint8_t _i2caddr; char _i2cbuffer[GPS_MAX_I2C_TRANSFER]; - int8_t _i2cbuff_max = -1, _i2cbuff_idx = 0; + int8_t _buff_max = -1, _buff_idx = 0; char last_char = 0; }; /**************************************************************************/ diff --git a/examples/GPS_SPI_EchoTest/GPS_SPI_EchoTest.ino b/examples/GPS_SPI_EchoTest/GPS_SPI_EchoTest.ino new file mode 100644 index 0000000..aae97f6 --- /dev/null +++ b/examples/GPS_SPI_EchoTest/GPS_SPI_EchoTest.ino @@ -0,0 +1,41 @@ +// Test code for Adafruit GPS That Support Using SPI +// +// This code shows how to test a passthru between USB and SPI +// +// Pick one up today at the Adafruit electronics shop +// and help support open source hardware & software! -ada + +#include + +// Connect to the GPS on the hardware SPI port +// with CS on pin #10 +Adafruit_GPS GPS(&SPI, 10); +#define RESET_PIN 9 + +void setup() { + // wait for hardware serial to appear + while (!Serial); + + // make this baud rate fast enough to we aren't waiting on it + Serial.begin(115200); + + Serial.println("Adafruit GPS library basic SPI test!"); + pinMode(RESET_PIN, OUTPUT); + digitalWrite(RESET_PIN, LOW); + delay(10); + digitalWrite(RESET_PIN, HIGH); + delay(100); + GPS.begin(100000); // use 100kHz for SPI data rate +} + + +void loop() { + if (Serial.available()) { + char c = Serial.read(); + GPS.write(c); + } + if (GPS.available()) { + char c = GPS.read(); + Serial.write(c); + } +} \ No newline at end of file