Skip to content

Commit 48ace0a

Browse files
committed
Add support for SPI interface
1 parent 46340ea commit 48ace0a

File tree

2 files changed

+138
-1
lines changed

2 files changed

+138
-1
lines changed

src/SparkFun_u-blox_GNSS_Arduino_Library.cpp

Lines changed: 121 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -451,6 +451,35 @@ boolean SFE_UBLOX_GNSS::begin(Stream &serialPort)
451451
return (connected);
452452
}
453453

454+
// Initialize for SPI
455+
boolean SFE_UBLOX_GNSS::begin(SPIClass &spiPort, uint8_t ssPin, int spiSpeed)
456+
{
457+
commType = COMM_TYPE_SPI;
458+
_spiPort = &spiPort;
459+
_ssPin = ssPin;
460+
_spiSpeed = spiSpeed;
461+
//New in v2.0: allocate memory for the packetCfg payload here - if required. (The user may have called setPacketCfgPayloadSize already)
462+
if (packetCfgPayloadSize == 0)
463+
setPacketCfgPayloadSize(MAX_PAYLOAD_SIZE);
464+
Serial.println("Creating buffer");
465+
createFileBuffer();
466+
boolean connected = isConnected();
467+
if (!connected)
468+
connected = isConnected();
469+
470+
if (!connected)
471+
connected = isConnected();
472+
473+
// Initialize/clear the SPI buffer - fill it with 0xFF as this is what is received from the UBLOX module if there's no data to be processed
474+
for (uint8_t i = 0; i < 20; i++)
475+
{
476+
spiBuffer[i] = 0xFF;
477+
}
478+
479+
return (connected);
480+
}
481+
482+
454483
// Allow the user to change I2C polling wait (the minimum interval between I2C data requests - to avoid pounding the bus)
455484
// i2cPollingWait defaults to 100ms and is adjusted automatically when setNavigationFrequency()
456485
// or setHNRNavigationRate() are called. But if the user is using callbacks, it might be advantageous
@@ -598,6 +627,8 @@ boolean SFE_UBLOX_GNSS::checkUbloxInternal(ubxPacket *incomingUBX, uint8_t reque
598627
return (checkUbloxI2C(incomingUBX, requestedClass, requestedID));
599628
else if (commType == COMM_TYPE_SERIAL)
600629
return (checkUbloxSerial(incomingUBX, requestedClass, requestedID));
630+
else if (commType == COMM_TYPE_SPI)
631+
return (checkUbloxSpi(incomingUBX, requestedClass, requestedID));
601632
return false;
602633
}
603634

@@ -755,6 +786,42 @@ boolean SFE_UBLOX_GNSS::checkUbloxSerial(ubxPacket *incomingUBX, uint8_t request
755786

756787
} //end checkUbloxSerial()
757788

789+
790+
//Checks SPI for data, passing any new bytes to process()
791+
boolean SFE_UBLOX_GNSS::checkUbloxSpi(ubxPacket *incomingUBX, uint8_t requestedClass, uint8_t requestedID)
792+
{
793+
// process the contents of the SPI buffer if not empty!
794+
uint8_t bufferByte = spiBuffer[0];
795+
uint8_t bufferIndex = 0;
796+
797+
while (bufferByte != 0xFF) {
798+
process(bufferByte, incomingUBX, requestedClass, requestedID);
799+
bufferIndex++;
800+
bufferByte = spiBuffer[bufferIndex];
801+
}
802+
803+
// reset the contents of the SPI buffer
804+
for(uint8_t i = 0; i < bufferIndex; i++)
805+
{
806+
spiBuffer[i] = 0xFF;
807+
}
808+
809+
SPISettings settingsA(_spiSpeed, MSBFIRST, SPI_MODE0);
810+
_spiPort->beginTransaction(settingsA);
811+
digitalWrite(_ssPin, LOW);
812+
uint8_t byteReturned = _spiPort->transfer(0x0A);
813+
while (byteReturned != 0xFF || currentSentence != NONE)
814+
{
815+
process(byteReturned, incomingUBX, requestedClass, requestedID);
816+
byteReturned = _spiPort->transfer(0x0A);
817+
}
818+
digitalWrite(_ssPin, HIGH);
819+
_spiPort->endTransaction();
820+
return (true);
821+
822+
} //end checkUbloxSpi()
823+
824+
758825
//PRIVATE: Check if we have storage allocated for an incoming "automatic" message
759826
boolean SFE_UBLOX_GNSS::checkAutomatic(uint8_t Class, uint8_t ID)
760827
{
@@ -2675,6 +2742,10 @@ sfe_ublox_status_e SFE_UBLOX_GNSS::sendCommand(ubxPacket *outgoingUBX, uint16_t
26752742
{
26762743
sendSerialCommand(outgoingUBX);
26772744
}
2745+
else if (commType == COMM_TYPE_SPI)
2746+
{
2747+
sendSpiCommand(outgoingUBX);
2748+
}
26782749

26792750
if (maxWait > 0)
26802751
{
@@ -2781,6 +2852,56 @@ void SFE_UBLOX_GNSS::sendSerialCommand(ubxPacket *outgoingUBX)
27812852
_serialPort->write(outgoingUBX->checksumB);
27822853
}
27832854

2855+
2856+
// Transfer a byte to SPI. Also capture any bytes received from the UBLOX device during sending and capture them in a small buffer so that
2857+
// they can be processed later with process
2858+
void SFE_UBLOX_GNSS::spiTransfer(uint8_t byteToTransfer)
2859+
{
2860+
uint8_t returnedByte = _spiPort->transfer(byteToTransfer);
2861+
if (returnedByte != 0xFF)
2862+
{
2863+
spiBuffer[spiBufferIndex] = returnedByte;
2864+
spiBufferIndex++;
2865+
}
2866+
}
2867+
2868+
// Send a command via SPI
2869+
void SFE_UBLOX_GNSS::sendSpiCommand(ubxPacket *outgoingUBX)
2870+
{
2871+
SPISettings settingsA(_spiSpeed, MSBFIRST, SPI_MODE0);
2872+
_spiPort->beginTransaction(settingsA);
2873+
digitalWrite(_ssPin, LOW);
2874+
//Write header bytes
2875+
spiTransfer(UBX_SYNCH_1); //μ - oh ublox, you're funny. I will call you micro-blox from now on.
2876+
if (_printDebug) _debugSerial->printf("%x ", UBX_SYNCH_1);
2877+
spiTransfer(UBX_SYNCH_2); //b
2878+
if (_printDebug) _debugSerial->printf("%x ", UBX_SYNCH_2);
2879+
2880+
spiTransfer(outgoingUBX->cls);
2881+
if (_printDebug) _debugSerial->printf("%x ", outgoingUBX->cls);
2882+
spiTransfer(outgoingUBX->id);
2883+
if (_printDebug) _debugSerial->printf("%x ", outgoingUBX->id);
2884+
spiTransfer(outgoingUBX->len & 0xFF); //LSB
2885+
if (_printDebug) _debugSerial->printf("%x ", outgoingUBX->len & 0xFF);
2886+
spiTransfer(outgoingUBX->len >> 8);
2887+
if (_printDebug) _debugSerial->printf("%x ", outgoingUBX->len >> 8);
2888+
2889+
//Write payload.
2890+
for (uint16_t i = 0; i < outgoingUBX->len; i++)
2891+
{
2892+
spiTransfer(outgoingUBX->payload[i]);
2893+
if (_printDebug) _debugSerial->printf("%x ", outgoingUBX->payload[i]);
2894+
}
2895+
2896+
//Write checksum
2897+
spiTransfer(outgoingUBX->checksumA);
2898+
if (_printDebug) _debugSerial->printf("%x ", outgoingUBX->checksumA);
2899+
spiTransfer(outgoingUBX->checksumB);
2900+
if (_printDebug) _debugSerial->printf("%x \n", outgoingUBX->checksumB);
2901+
digitalWrite(_ssPin, HIGH);
2902+
_spiPort->endTransaction();
2903+
}
2904+
27842905
//Pretty prints the current ubxPacket
27852906
void SFE_UBLOX_GNSS::printPacket(ubxPacket *packet, boolean alwaysPrintPayload)
27862907
{

src/SparkFun_u-blox_GNSS_Arduino_Library.h

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,8 @@
5151

5252
#include <Wire.h>
5353

54+
#include <SPI.h>
55+
5456
#include "u-blox_config_keys.h"
5557
#include "u-blox_structs.h"
5658

@@ -560,6 +562,8 @@ class SFE_UBLOX_GNSS
560562
boolean begin(TwoWire &wirePort = Wire, uint8_t deviceAddress = 0x42); //Returns true if module is detected
561563
//serialPort needs to be perviously initialized to correct baud rate
562564
boolean begin(Stream &serialPort); //Returns true if module is detected
565+
//SPI - supply instance of SPIClass, slave select pin and SPI speed (in Hz)
566+
boolean begin(SPIClass &spiPort, uint8_t ssPin, int spiSpeed);
563567

564568
void end(void); //Stop all automatic message processing. Free all used RAM
565569

@@ -612,6 +616,7 @@ class SFE_UBLOX_GNSS
612616

613617
boolean checkUbloxI2C(ubxPacket *incomingUBX, uint8_t requestedClass, uint8_t requestedID); //Method for I2C polling of data, passing any new bytes to process()
614618
boolean checkUbloxSerial(ubxPacket *incomingUBX, uint8_t requestedClass, uint8_t requestedID); //Method for serial polling of data, passing any new bytes to process()
619+
boolean checkUbloxSpi(ubxPacket *incomingUBX, uint8_t requestedClass, uint8_t requestedID); //Method for spi polling of data, passing any new bytes to process()
615620

616621
// Process the incoming data
617622

@@ -622,12 +627,13 @@ class SFE_UBLOX_GNSS
622627
void processUBX(uint8_t incoming, ubxPacket *incomingUBX, uint8_t requestedClass, uint8_t requestedID); //Given a character, file it away into the uxb packet structure
623628
void processUBXpacket(ubxPacket *msg); //Once a packet has been received and validated, identify this packet's class/id and update internal flags
624629

625-
// Send I2C/Serial commands to the module
630+
// Send I2C/Serial/SPI commands to the module
626631

627632
void calcChecksum(ubxPacket *msg); //Sets the checksumA and checksumB of a given messages
628633
sfe_ublox_status_e sendCommand(ubxPacket *outgoingUBX, uint16_t maxWait = defaultMaxWait, boolean expectACKonly = false); //Given a packet and payload, send everything including CRC bytes, return true if we got a response
629634
sfe_ublox_status_e sendI2cCommand(ubxPacket *outgoingUBX, uint16_t maxWait = defaultMaxWait);
630635
void sendSerialCommand(ubxPacket *outgoingUBX);
636+
void sendSpiCommand(ubxPacket *outgoingUBX);
631637

632638
void printPacket(ubxPacket *packet, boolean alwaysPrintPayload = false); //Useful for debugging
633639

@@ -1235,6 +1241,9 @@ class SFE_UBLOX_GNSS
12351241
//Calculate how much RAM is needed to store the payload for a given automatic message
12361242
uint16_t getMaxPayloadSize(uint8_t Class, uint8_t ID);
12371243

1244+
//Do the actual transfer to SPI
1245+
void spiTransfer(uint8_t byteToTransfer);
1246+
12381247
boolean initGeofenceParams(); // Allocate RAM for currentGeofenceParams and initialize it
12391248
boolean initModuleSWVersion(); // Allocate RAM for moduleSWVersion and initialize it
12401249

@@ -1273,6 +1282,10 @@ class SFE_UBLOX_GNSS
12731282
Stream *_nmeaOutputPort = NULL; //The user can assign an output port to print NMEA sentences if they wish
12741283
Stream *_debugSerial; //The stream to send debug messages to if enabled
12751284

1285+
SPIClass *_spiPort; //The instance of SPIClass
1286+
uint8_t _ssPin; //The slave select pin
1287+
int _spiSpeed; //The speed to use for SPI (Hz)
1288+
12761289
uint8_t _gpsI2Caddress = 0x42; //Default 7-bit unshifted address of the ublox 6/7/8/M8/F9 series
12771290
//This can be changed using the ublox configuration software
12781291

@@ -1292,6 +1305,9 @@ class SFE_UBLOX_GNSS
12921305
uint8_t *payloadCfg = NULL;
12931306
uint8_t *payloadAuto = NULL;
12941307

1308+
uint8_t spiBuffer[20]; // A small buffer to store any bytes being recieved back from the device while we are sending via SPI
1309+
uint8_t spiBufferIndex = 0; // The index into the SPI buffer
1310+
12951311
//Init the packet structures and init them with pointers to the payloadAck, payloadCfg, payloadBuf and payloadAuto arrays
12961312
ubxPacket packetAck = {0, 0, 0, 0, 0, payloadAck, 0, 0, SFE_UBLOX_PACKET_VALIDITY_NOT_DEFINED, SFE_UBLOX_PACKET_VALIDITY_NOT_DEFINED};
12971313
ubxPacket packetBuf = {0, 0, 0, 0, 0, payloadBuf, 0, 0, SFE_UBLOX_PACKET_VALIDITY_NOT_DEFINED, SFE_UBLOX_PACKET_VALIDITY_NOT_DEFINED};

0 commit comments

Comments
 (0)