Skip to content

Add spi aberridg #43

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 6 commits into from
Jun 27, 2021
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
121 changes: 121 additions & 0 deletions src/SparkFun_u-blox_GNSS_Arduino_Library.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -451,6 +451,35 @@ boolean SFE_UBLOX_GNSS::begin(Stream &serialPort)
return (connected);
}

// Initialize for SPI
boolean SFE_UBLOX_GNSS::begin(SPIClass &spiPort, uint8_t ssPin, int spiSpeed)
{
commType = COMM_TYPE_SPI;
_spiPort = &spiPort;
_ssPin = ssPin;
_spiSpeed = spiSpeed;
//New in v2.0: allocate memory for the packetCfg payload here - if required. (The user may have called setPacketCfgPayloadSize already)
if (packetCfgPayloadSize == 0)
setPacketCfgPayloadSize(MAX_PAYLOAD_SIZE);
Serial.println("Creating buffer");
createFileBuffer();
boolean connected = isConnected();
if (!connected)
connected = isConnected();

if (!connected)
connected = isConnected();

// 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
for (uint8_t i = 0; i < 20; i++)
{
spiBuffer[i] = 0xFF;
}

return (connected);
}


// Allow the user to change I2C polling wait (the minimum interval between I2C data requests - to avoid pounding the bus)
// i2cPollingWait defaults to 100ms and is adjusted automatically when setNavigationFrequency()
// or setHNRNavigationRate() are called. But if the user is using callbacks, it might be advantageous
Expand Down Expand Up @@ -598,6 +627,8 @@ boolean SFE_UBLOX_GNSS::checkUbloxInternal(ubxPacket *incomingUBX, uint8_t reque
return (checkUbloxI2C(incomingUBX, requestedClass, requestedID));
else if (commType == COMM_TYPE_SERIAL)
return (checkUbloxSerial(incomingUBX, requestedClass, requestedID));
else if (commType == COMM_TYPE_SPI)
return (checkUbloxSpi(incomingUBX, requestedClass, requestedID));
return false;
}

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

} //end checkUbloxSerial()


//Checks SPI for data, passing any new bytes to process()
boolean SFE_UBLOX_GNSS::checkUbloxSpi(ubxPacket *incomingUBX, uint8_t requestedClass, uint8_t requestedID)
{
// process the contents of the SPI buffer if not empty!
uint8_t bufferByte = spiBuffer[0];
uint8_t bufferIndex = 0;

while (bufferByte != 0xFF) {
process(bufferByte, incomingUBX, requestedClass, requestedID);
bufferIndex++;
bufferByte = spiBuffer[bufferIndex];
}

// reset the contents of the SPI buffer
for(uint8_t i = 0; i < bufferIndex; i++)
{
spiBuffer[i] = 0xFF;
}

SPISettings settingsA(_spiSpeed, MSBFIRST, SPI_MODE0);
_spiPort->beginTransaction(settingsA);
digitalWrite(_ssPin, LOW);
uint8_t byteReturned = _spiPort->transfer(0x0A);
while (byteReturned != 0xFF || currentSentence != NONE)
{
process(byteReturned, incomingUBX, requestedClass, requestedID);
byteReturned = _spiPort->transfer(0x0A);
}
digitalWrite(_ssPin, HIGH);
_spiPort->endTransaction();
return (true);

} //end checkUbloxSpi()


//PRIVATE: Check if we have storage allocated for an incoming "automatic" message
boolean SFE_UBLOX_GNSS::checkAutomatic(uint8_t Class, uint8_t ID)
{
Expand Down Expand Up @@ -2675,6 +2742,10 @@ sfe_ublox_status_e SFE_UBLOX_GNSS::sendCommand(ubxPacket *outgoingUBX, uint16_t
{
sendSerialCommand(outgoingUBX);
}
else if (commType == COMM_TYPE_SPI)
{
sendSpiCommand(outgoingUBX);
}

if (maxWait > 0)
{
Expand Down Expand Up @@ -2781,6 +2852,56 @@ void SFE_UBLOX_GNSS::sendSerialCommand(ubxPacket *outgoingUBX)
_serialPort->write(outgoingUBX->checksumB);
}


// 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
// they can be processed later with process
void SFE_UBLOX_GNSS::spiTransfer(uint8_t byteToTransfer)
{
uint8_t returnedByte = _spiPort->transfer(byteToTransfer);
if (returnedByte != 0xFF)
{
spiBuffer[spiBufferIndex] = returnedByte;
spiBufferIndex++;
}
}

// Send a command via SPI
void SFE_UBLOX_GNSS::sendSpiCommand(ubxPacket *outgoingUBX)
{
SPISettings settingsA(_spiSpeed, MSBFIRST, SPI_MODE0);
_spiPort->beginTransaction(settingsA);
digitalWrite(_ssPin, LOW);
//Write header bytes
spiTransfer(UBX_SYNCH_1); //μ - oh ublox, you're funny. I will call you micro-blox from now on.
if (_printDebug) _debugSerial->printf("%x ", UBX_SYNCH_1);
spiTransfer(UBX_SYNCH_2); //b
if (_printDebug) _debugSerial->printf("%x ", UBX_SYNCH_2);

spiTransfer(outgoingUBX->cls);
if (_printDebug) _debugSerial->printf("%x ", outgoingUBX->cls);
spiTransfer(outgoingUBX->id);
if (_printDebug) _debugSerial->printf("%x ", outgoingUBX->id);
spiTransfer(outgoingUBX->len & 0xFF); //LSB
if (_printDebug) _debugSerial->printf("%x ", outgoingUBX->len & 0xFF);
spiTransfer(outgoingUBX->len >> 8);
if (_printDebug) _debugSerial->printf("%x ", outgoingUBX->len >> 8);

//Write payload.
for (uint16_t i = 0; i < outgoingUBX->len; i++)
{
spiTransfer(outgoingUBX->payload[i]);
if (_printDebug) _debugSerial->printf("%x ", outgoingUBX->payload[i]);
}

//Write checksum
spiTransfer(outgoingUBX->checksumA);
if (_printDebug) _debugSerial->printf("%x ", outgoingUBX->checksumA);
spiTransfer(outgoingUBX->checksumB);
if (_printDebug) _debugSerial->printf("%x \n", outgoingUBX->checksumB);
digitalWrite(_ssPin, HIGH);
_spiPort->endTransaction();
}

//Pretty prints the current ubxPacket
void SFE_UBLOX_GNSS::printPacket(ubxPacket *packet, boolean alwaysPrintPayload)
{
Expand Down
18 changes: 17 additions & 1 deletion src/SparkFun_u-blox_GNSS_Arduino_Library.h
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,8 @@

#include <Wire.h>

#include <SPI.h>

#include "u-blox_config_keys.h"
#include "u-blox_structs.h"

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

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

Expand Down Expand Up @@ -612,6 +616,7 @@ class SFE_UBLOX_GNSS

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

// Process the incoming data

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

// Send I2C/Serial commands to the module
// Send I2C/Serial/SPI commands to the module

void calcChecksum(ubxPacket *msg); //Sets the checksumA and checksumB of a given messages
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
sfe_ublox_status_e sendI2cCommand(ubxPacket *outgoingUBX, uint16_t maxWait = defaultMaxWait);
void sendSerialCommand(ubxPacket *outgoingUBX);
void sendSpiCommand(ubxPacket *outgoingUBX);

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

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

//Do the actual transfer to SPI
void spiTransfer(uint8_t byteToTransfer);

boolean initGeofenceParams(); // Allocate RAM for currentGeofenceParams and initialize it
boolean initModuleSWVersion(); // Allocate RAM for moduleSWVersion and initialize it

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

SPIClass *_spiPort; //The instance of SPIClass
uint8_t _ssPin; //The slave select pin
int _spiSpeed; //The speed to use for SPI (Hz)

uint8_t _gpsI2Caddress = 0x42; //Default 7-bit unshifted address of the ublox 6/7/8/M8/F9 series
//This can be changed using the ublox configuration software

Expand All @@ -1292,6 +1305,9 @@ class SFE_UBLOX_GNSS
uint8_t *payloadCfg = NULL;
uint8_t *payloadAuto = NULL;

uint8_t spiBuffer[20]; // A small buffer to store any bytes being recieved back from the device while we are sending via SPI
uint8_t spiBufferIndex = 0; // The index into the SPI buffer

//Init the packet structures and init them with pointers to the payloadAck, payloadCfg, payloadBuf and payloadAuto arrays
ubxPacket packetAck = {0, 0, 0, 0, 0, payloadAck, 0, 0, SFE_UBLOX_PACKET_VALIDITY_NOT_DEFINED, SFE_UBLOX_PACKET_VALIDITY_NOT_DEFINED};
ubxPacket packetBuf = {0, 0, 0, 0, 0, payloadBuf, 0, 0, SFE_UBLOX_PACKET_VALIDITY_NOT_DEFINED, SFE_UBLOX_PACKET_VALIDITY_NOT_DEFINED};
Expand Down