first commit

This commit is contained in:
2021-05-11 20:43:42 +03:00
commit 9f3ffaba30
381 changed files with 69596 additions and 0 deletions

View File

@@ -0,0 +1,75 @@
/*
Copyright 2020 - Stuart Robinson
Licensed under a MIT license displayed at the bottom of this document.
Original published 12/05/20
*/
void startAFSKRTTY(int8_t audiopin, uint16_t freq, uint32_t afskleadinmS)
{
tone(audiopin, freq); //lead in is high tone
delay(afskleadinmS);
}
void endAFSKRTTY(int8_t audiopin)
{
delay(500); //500mS seconds of high tone to finish
noTone(audiopin);
}
void sendAFSKRTTY(uint8_t chartosend, int8_t audiopin, int8_t checkpin, uint16_t tonelowHz, uint16_t tonehighHz, uint32_t perioduS)
//send the byte in chartosend as AFSK RTTY, assumes mark condition (idle) is already present
//Format is 7 bits, no parity and 2 stop bits
{
uint8_t numbits;
uint32_t startuS;
startuS = micros();
digitalWrite(checkpin, LOW);
tone(audiopin, tonelowHz);
while ( (uint32_t) (micros() - startuS) < perioduS); //wait for start bit end
for (numbits = 1; numbits <= 7; numbits++) //send 7 bits, LSB first
{
startuS = micros();
if ((chartosend & 0x01) != 0)
{
digitalWrite(checkpin, HIGH);
tone(audiopin, tonehighHz);
}
else
{
digitalWrite(checkpin, LOW);
tone(audiopin, tonelowHz); //start 0 bit low tone
}
chartosend = (chartosend / 2); //get the next bit
while ( (uint32_t) (micros() - startuS) < perioduS); //wait bit period uS
}
perioduS = perioduS * 2;
startuS = micros();
digitalWrite(checkpin, HIGH); //start mark condition
tone(audiopin, tonehighHz); //start high tone
while ( (uint32_t) (micros() - startuS) < perioduS);
}
/*
MIT license
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
documentation files (the "Software"), to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software,
and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions
of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.
*/

View File

@@ -0,0 +1,180 @@
/*
Copyright 2020 - Stuart Robinson
Licensed under a MIT license displayed at the bottom of this document.
Original published 18/12/20
*/
/*
This is the AFSK RTTY send library specifically for microcontrollers that do not have a tone() function
such as Arduino DUE and ESP32. Tones are generated here by manually toggling the selected tone pin with
a suitable delay between toggles.
The baud rate and tone frequecies used can be adjusted by usin the startAFSKRTTY() command.
The library has been tested and will work on an Arduion Pro Mini 8Mhz, Arduino DUE and ESP32 and when
used with this startup command;
startAFSKRTTY(AUDIOOUTpin, CHECKpin, 5, 1000, 7, 714, 0, 1000);
This outputs AFSKRTTY at 100baud, 7bit, no parity, 1stop bit, low tone 1000hz, hightone 1400hz.
The audio comes out of the pin passed via AUDIOOUTpin and the bit timing can be checked by looking at
the CHECKpin on a scope or analyser.
A low pass filter consiting of a 47K resistor and 470nF capacitor was used to redice the output for
feeding into a PC soundcard.
*/
#define AFSKRTTY_UNUSED(v) (void) (v) //add AFSKRTTY_UNUSED(variable); in functions to avoid compiler warnings
int8_t _audiopin, _checkpin, _adjust;
uint8_t _lowcycles, _highcycles;
uint32_t _lowperioduS, _highperioduS;
void startAFSKRTTY(int8_t audiopin, int8_t checkpin, uint8_t lowcycles, uint16_t lowperioduS, uint8_t highcycles, uint16_t highperioduS, int16_t adjust, uint16_t leadinmS);
void sendAFSKRTTY(uint8_t chartosend);
void toneHigh();
void toneLow();
void startAFSKRTTY(int8_t audiopin, int8_t checkpin, uint8_t lowcycles, uint16_t lowperioduS, uint8_t highcycles, uint16_t highperioduS, int16_t adjust, uint16_t leadinmS)
{
uint32_t startmS;
_audiopin = audiopin;
_checkpin = checkpin;
_lowperioduS = (lowperioduS / 2) + adjust; //period passed is equal to frequency, but delays are in two halfs
_highperioduS = (highperioduS / 2) + adjust;
_lowcycles = lowcycles;
_highcycles = highcycles;
_adjust = adjust;
if (audiopin > 0)
{
pinMode(audiopin, OUTPUT);
}
if (checkpin > 0)
{
pinMode(checkpin, OUTPUT);
}
startmS = millis();
while ( (uint32_t) (millis() - startmS) < leadinmS) //allows for millis() overflow
{
digitalWrite(audiopin, HIGH);
delayMicroseconds(_highperioduS);
digitalWrite(audiopin, LOW);
delayMicroseconds(_highperioduS);
}
}
void endAFSKRTTY(int8_t audiopin, int8_t checkpin, uint16_t leadoutmS)
{
uint32_t startmS;
startmS = millis();
while ( (uint32_t) (millis() - startmS) < leadoutmS) //allows for millis() overflow
{
digitalWrite(audiopin, HIGH);
delayMicroseconds(_highperioduS);
digitalWrite(audiopin, LOW);
delayMicroseconds(_highperioduS);
}
if (audiopin > 0)
{
pinMode(audiopin, INPUT);
}
if (checkpin > 0)
{
pinMode(checkpin, INPUT);
}
}
void toneHigh()
{
uint8_t index;
for (index = 1; index <= _highcycles; index++)
{
digitalWrite(_audiopin, HIGH);
delayMicroseconds(_highperioduS);
digitalWrite(_audiopin, LOW);
delayMicroseconds(_highperioduS);
}
}
void toneLow()
{
uint8_t index;
for (index = 1; index <= _lowcycles; index++)
{
digitalWrite(_audiopin, HIGH);
delayMicroseconds(_lowperioduS);
digitalWrite(_audiopin, LOW);
delayMicroseconds(_lowperioduS);
}
}
void sendAFSKRTTY(uint8_t chartosend)
//send the byte in chartosend as AFSK RTTY, assumes mark condition (idle) is already present
//Format is 7 bits, no parity and 2 stop bits
{
uint8_t numbits;
digitalWrite(_checkpin, LOW);
toneLow();
for (numbits = 1; numbits <= 7; numbits++) //send 7 bits, LSB first
{
if ((chartosend & 0x01) != 0)
{
digitalWrite(_checkpin, HIGH);
toneHigh();
}
else
{
digitalWrite(_checkpin, LOW);
toneLow();
}
chartosend = (chartosend / 2); //get the next bit
}
digitalWrite(_checkpin, HIGH); //start mark condition
toneHigh();
toneHigh();
}
/*
MIT license
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
documentation files (the "Software"), to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software,
and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions
of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.
*/

View File

@@ -0,0 +1,101 @@
/*******************************************************************************************************
Programs for Arduino - Copyright of the author Stuart Robinson - 24/04/20
This program is supplied as is, it is up to the user of the program to decide if the program is
suitable for the intended purpose and free from errors.
These are sleep routines for Atmel processors, tested on ATmega328. When calling the sleep routines be
sure there are no pending interrupts such as from Serial.print(), strange things can happen otherwise.
*******************************************************************************************************/
#include <avr/sleep.h> //sleep library for Atmel processor
#include <avr/wdt.h> //watchdog library for Atmel processor
//Atmel watchdog sleep times
#define sleep16mS 0x00
#define sleep32mS 0x01
#define sleep64mS 0x02
#define sleep125mS 0x03
#define sleep250mS 0x04
#define sleep500mS 0x05
#define sleep1000mS 0x06
#define sleep2000mS 0x07
#define sleep4000mS 0x20
#define sleep8000mS 0x21
void SleepSeconds(uint32_t secs);
void SleepmS(uint32_t sleeps, uint8_t numbermS);
void atmelSleepPermanent();
void SleepSeconds(uint32_t secs)
{
//for Atmel processor only
uint16_t sleeps8secs, sleeps1secs;
sleeps8secs = secs >> 3;
sleeps1secs = secs - (sleeps8secs << 3);
SleepmS(sleeps8secs, sleep8000mS);
SleepmS(sleeps1secs, sleep1000mS);
}
void SleepmS(uint32_t sleeps, uint8_t numbermS)
{
//for Atmel processor only
uint32_t index;
for (index = 1; index <= sleeps; index++)
{
ADCSRA = 0; //disable ADC
MCUSR = 0; //clear various "reset" flags
WDTCSR = bit (WDCE) | bit (WDE); //allow changes, disable reset
WDTCSR = bit (WDIE) + numbermS; //set the number of mS for sleep
wdt_reset(); //pat the pet, could be a dog
set_sleep_mode (SLEEP_MODE_PWR_DOWN);
noInterrupts (); //timed sequence follows
sleep_enable();
MCUCR = bit (BODS) | bit (BODSE); //turn off brown-out enable in software
MCUCR = bit (BODS);
interrupts (); //guarantees next instruction executed
sleep_cpu ();
//awake here
sleep_disable(); //cancel sleep as a precaution
}
}
void atmelSleepPermanent()
{
ADCSRA = 0; //disable ADC
set_sleep_mode (SLEEP_MODE_PWR_DOWN);
noInterrupts (); //timed sequence follows
sleep_enable();
// turn off brown-out enable in software
MCUCR = bit (BODS) | bit (BODSE); //turn on brown-out enable select
MCUCR = bit (BODS); //this must be done within 4 clock cycles of above
interrupts (); //guarantees next instruction executed
sleep_cpu (); //sleep within 3 clock cycles of above
/* wake up here */
sleep_disable();
}
ISR (WDT_vect)
{
//watchdog interrupt
wdt_disable(); // disable watchdog
}

View File

@@ -0,0 +1,88 @@
/*
Copyright 2020 - Stuart Robinson
24/04/20
*/
/*******************************************************************************************************
Library Operation - This library is for reading from and writing to the EEPROM. These routines provide
a funtional match to the libraries for FRAM.
*******************************************************************************************************/
#include <EEPROM.h>
#define LTUNUSED(v) (void) (v) //add LTUNUSED(variable); in functions to avoid compiler warnings
void memoryStart(uint16_t addr) //yes I know the EEPROM does not have an address, but the other memory types do
{
//left empty for future use
LTUNUSED(addr); //avoids compliler warning
}
void memoryEnd()
{
//left empty for future use
}
void writeMemoryUint8(uint16_t addr, uint8_t x)
{
//write a byte to the EEPROM
EEPROM.put(addr, x);
}
uint16_t readMemoryUint16(uint16_t addr)
{
uint16_t x;
EEPROM.get(addr, x);
return x;
}
uint32_t readMemoryUint32(uint16_t addr)
{
uint32_t x;
EEPROM.get(addr, x);
return x;
}
void writeMemoryUint32(uint16_t addr, uint32_t x)
{
EEPROM.put(addr, x);
}
void writeMemoryUint16(uint16_t addr, uint16_t x)
{
EEPROM.put(addr, x);
}
float readMemoryFloat(uint16_t addr)
{
float x;
EEPROM.get(addr, x);
return x;
}
void writeMemoryFloat(uint16_t addr, float x)
{
EEPROM.put(addr, x);
}
void fillMemory(uint16_t startaddr, uint16_t endaddr, uint8_t lval)
{
uint32_t i;
for (i = startaddr; i <= endaddr; i++)
{
writeMemoryUint8(i, lval);
}
}

View File

@@ -0,0 +1,462 @@
/*
Copyright 2020 - Stuart Robinson
Licensed under a MIT license displayed at the bottom of this document.
14/04/20
*/
/*******************************************************************************************************
Library Operation - This library is for reading from and writing to the 64kbit (8kbyte) I2C FRAMS.
Take care when writing variables to the end of the address space, the writes and reads may wrap
around back to address 0
*******************************************************************************************************/
#include <Wire.h>
int16_t Memory_I2C_Addr = 0x50; //default I2C address of FM24CL64 FRAM
void memoryStart(int16_t addr)
{
Memory_I2C_Addr = addr;
Wire.begin();
}
void memorySetAddress(int16_t addr)
{
Memory_I2C_Addr = addr;
}
void memoryEnd()
{
//left empty for future use
}
/***************************************************************************
Write Routines
***************************************************************************
*/
void writeMemoryChar(uint16_t addr, char x)
{
uint8_t msb_addr = highByte(addr);
uint8_t lsb_addr = lowByte(addr);
Wire.beginTransmission(Memory_I2C_Addr);
Wire.write(msb_addr);
Wire.write(lsb_addr);
Wire.write(x);
Wire.endTransmission();
}
void writeMemoryInt8(uint16_t addr, int8_t x)
{
uint8_t msb_addr = highByte(addr);
uint8_t lsb_addr = lowByte(addr);
Wire.beginTransmission(Memory_I2C_Addr);
Wire.write(msb_addr);
Wire.write(lsb_addr);
Wire.write(x);
Wire.endTransmission();
}
void writeMemoryUint8(uint16_t addr, uint8_t x)
{
uint8_t msb_addr = highByte(addr);
uint8_t lsb_addr = lowByte(addr);
Wire.beginTransmission(Memory_I2C_Addr);
Wire.write(msb_addr);
Wire.write(lsb_addr);
Wire.write(x);
Wire.endTransmission();
}
void writeMemoryInt16(uint16_t addr, int16_t x)
{
uint8_t msb_addr = highByte(addr);
uint8_t lsb_addr = lowByte(addr);
uint8_t msb_data = highByte(x);
uint8_t lsb_data = lowByte(x);
Wire.beginTransmission(Memory_I2C_Addr);
Wire.write(msb_addr);
Wire.write(lsb_addr);
Wire.write(lsb_data);
Wire.write(msb_data);
Wire.endTransmission();
}
void writeMemoryUint16(uint16_t addr, uint16_t x)
{
uint8_t msb_addr = highByte(addr);
uint8_t lsb_addr = lowByte(addr);
uint8_t msb_data = highByte(x);
uint8_t lsb_data = lowByte(x);
Wire.beginTransmission(Memory_I2C_Addr);
Wire.write(msb_addr);
Wire.write(lsb_addr);
Wire.write(lsb_data);
Wire.write(msb_data);
Wire.endTransmission();
}
void writeMemoryInt32(uint16_t addr, int32_t x)
{
uint8_t index, val;
uint8_t msb_addr = highByte(addr);
uint8_t lsb_addr = lowByte(addr);
union
{
uint8_t b[4];
uint32_t f;
} data;
data.f = x;
Wire.beginTransmission(Memory_I2C_Addr);
Wire.write(msb_addr);
Wire.write(lsb_addr);
for (index = 0; index < 4; index++)
{
val = data.b[index];
Wire.write(val); //write the data
}
Wire.endTransmission();
}
void writeMemoryUint32(uint16_t addr, uint32_t x)
{
uint8_t index, val;
uint8_t msb_addr = highByte(addr);
uint8_t lsb_addr = lowByte(addr);
union
{
uint8_t b[4];
uint32_t f;
} data;
data.f = x;
Wire.beginTransmission(Memory_I2C_Addr);
Wire.write(msb_addr);
Wire.write(lsb_addr);
for (index = 0; index < 4; index++)
{
val = data.b[index];
Wire.write(val); //write the data
}
Wire.endTransmission();
}
void writeMemoryFloat(uint16_t addr, float x)
{
uint8_t index, val;
uint8_t msb_addr = highByte(addr);
uint8_t lsb_addr = lowByte(addr);
union
{
uint8_t b[4];
float f;
} data;
data.f = x;
Wire.beginTransmission(Memory_I2C_Addr);
Wire.write(msb_addr);
Wire.write(lsb_addr);
for (index = 0; index < 4; index++)
{
val = data.b[index];
Wire.write(val); //write the data
}
Wire.endTransmission();
}
/***************************************************************************
Read Routines
**************************************************************************
*/
char readMemoryChar(uint16_t addr)
{
char data;
uint8_t msb_addr = highByte(addr);
uint8_t lsb_addr = lowByte(addr);
Wire.beginTransmission(Memory_I2C_Addr);
Wire.write(msb_addr);
Wire.write(lsb_addr);
Wire.endTransmission();
Wire.requestFrom((Memory_I2C_Addr), 1);
data = Wire.read();
return data;
}
int8_t readMemoryInt8(uint16_t addr)
{
int8_t data;
uint8_t msb_addr = highByte(addr);
uint8_t lsb_addr = lowByte(addr);
Wire.beginTransmission(Memory_I2C_Addr);
Wire.write(msb_addr);
Wire.write(lsb_addr);
Wire.endTransmission();
Wire.requestFrom((Memory_I2C_Addr), 1);
data = Wire.read();
return data;
}
uint8_t readMemoryUint8(uint16_t addr)
{
uint8_t data;
uint8_t msb_addr = highByte(addr);
uint8_t lsb_addr = lowByte(addr);
Wire.beginTransmission(Memory_I2C_Addr);
Wire.write(msb_addr);
Wire.write(lsb_addr);
Wire.endTransmission();
Wire.requestFrom((Memory_I2C_Addr), 1);
data = Wire.read();
return data;
}
int16_t readMemoryInt16(uint16_t addr)
{
uint8_t lsb_data, msb_data;
uint8_t msb_addr = highByte(addr);
uint8_t lsb_addr = lowByte(addr);
Wire.beginTransmission(Memory_I2C_Addr);
Wire.write(msb_addr);
Wire.write(lsb_addr);
Wire.endTransmission();
Wire.requestFrom(Memory_I2C_Addr, 2);
lsb_data = Wire.read();
msb_data = Wire.read();
return (lsb_data + (msb_data * 256));
}
uint16_t readMemoryUint16(uint16_t addr)
{
uint8_t lsb_data, msb_data;
uint8_t msb_addr = highByte(addr);
uint8_t lsb_addr = lowByte(addr);
Wire.beginTransmission(Memory_I2C_Addr);
Wire.write(msb_addr);
Wire.write(lsb_addr);
Wire.endTransmission();
Wire.requestFrom(Memory_I2C_Addr, 2);
lsb_data = Wire.read();
msb_data = Wire.read();
return (lsb_data + (msb_data * 256));
}
int32_t readMemoryInt32(uint16_t addr)
{
uint8_t val;
uint8_t msb_addr = highByte(addr);
uint8_t lsb_addr = lowByte(addr);
Wire.beginTransmission(Memory_I2C_Addr);
Wire.write(msb_addr);
Wire.write(lsb_addr);
Wire.endTransmission();
Wire.requestFrom(Memory_I2C_Addr, 4);
union
{
uint8_t b[4];
unsigned long f;
} readdata;
for (int index = 0; index < 4; index++)
{
val = Wire.read(); // read the uint8_t
readdata.b[index] = val;
}
return readdata.f;
}
uint32_t readMemoryUint32(uint16_t addr)
{
uint8_t val;
uint8_t msb_addr = highByte(addr);
uint8_t lsb_addr = lowByte(addr);
Wire.beginTransmission(Memory_I2C_Addr);
Wire.write(msb_addr);
Wire.write(lsb_addr);
Wire.endTransmission();
Wire.requestFrom(Memory_I2C_Addr, 4);
union
{
uint8_t b[4];
unsigned long f;
} readdata;
for (int index = 0; index < 4; index++)
{
val = Wire.read(); // read the uint8_t
readdata.b[index] = val;
}
return readdata.f;
}
float readMemoryFloat(uint16_t addr)
{
uint8_t val;
uint8_t msb_addr = highByte(addr);
uint8_t lsb_addr = lowByte(addr);
Wire.beginTransmission(Memory_I2C_Addr);
Wire.write(msb_addr);
Wire.write(lsb_addr);
Wire.endTransmission();
Wire.requestFrom(Memory_I2C_Addr, 4);
union
{
uint8_t b[4];
float f;
} readdata;
for (int index = 0; index < 4; index++)
{
val = Wire.read(); // read the uint8_t
readdata.b[index] = val;
}
return readdata.f;
}
/***************************************************************************
Start of general purpose memory routines
***************************************************************************/
uint16_t CRCMemory(uint16_t startaddr, uint16_t endaddr, uint16_t startval)
{
uint16_t i, libraryCRC;
uint8_t j;
libraryCRC = startval; //start value for CRC16, often 0xffff
for (i = startaddr; i <= endaddr; i++) //element 4 is first character after $$$$ at start
{
libraryCRC ^= ((uint16_t)readMemoryUint8(i) << 8);
for (j = 0; j < 8; j++)
{
if (libraryCRC & 0x8000)
libraryCRC = (libraryCRC << 1) ^ 0x1021;
else
libraryCRC <<= 1;
}
}
return libraryCRC;
}
void printMemory(uint16_t start_addr, uint16_t end_addr)
{
//print the contents of Memory
uint8_t value;
for (uint16_t a = start_addr; a <= end_addr; a++)
{
value = readMemoryUint8(a);
if ((a % 16) == 0)
{
Serial.println();
Serial.print(F("0x"));
if (a < 0x10)
{
Serial.print('0');
}
Serial.print(a, HEX);
Serial.print(F(": "));
}
Serial.print(F("0x"));
if (value < 0x10)
Serial.print('0');
Serial.print(value, HEX);
Serial.print(F(" "));
}
Serial.println();
}
void fillMemory(uint16_t startaddr, uint16_t endaddr, uint8_t lval)
{
uint16_t i;
for (i = startaddr; i <= endaddr; i++)
{
writeMemoryUint8(i, lval);
}
}
/*
MIT license
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
documentation files (the "Software"), to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software,
and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions
of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.
*/

View File

@@ -0,0 +1,447 @@
/*
Copyright 2020 - Stuart Robinson
Licensed under a MIT license displayed at the bottom of this document.
14/04/20
*/
/*******************************************************************************************************
Library Operation - This library is for reading from and writing to the 16kbit (2Kbyte) I2C FRAMS.
These FRAMS present as a series of eight 256 byte pages at I2C addresses 0X50 to 0x57. The library
calculates from the passed address which page to write to. For variables that are larger than one
uint8_t take care not to set the address so that a write would cross a page boundary. The library
does not deal with writes or reads that cross the 256 byte pages of the device.
*******************************************************************************************************/
#include <Wire.h>
int16_t Memory_I2C_Addr = 0x50; //default I2C address of MB85RC16PNF FRAM
void memoryStart(int16_t addr)
{
Memory_I2C_Addr = addr;
Wire.begin();
}
void memorySetAddress(int16_t addr)
{
Memory_I2C_Addr = addr;
}
void memoryEnd()
{
//left empty for future use
}
/***************************************************************************
Write Routines
**************************************************************************/
void writeMemoryChar(uint16_t addr, char x)
{
uint8_t msb_addr = (highByte(addr) & 0x07); //get 3 MSB bits of address
uint8_t lsb_addr = lowByte(addr);
Wire.beginTransmission(Memory_I2C_Addr + msb_addr);
Wire.write(lsb_addr);
Wire.write(x);
Wire.endTransmission();
}
void writeMemoryInt8(uint16_t addr, int8_t x)
{
uint8_t msb_addr = (highByte(addr) & 0x07); //get 3 MSB bits of address
uint8_t lsb_addr = lowByte(addr);
Wire.beginTransmission(Memory_I2C_Addr + msb_addr);
Wire.write(lsb_addr);
Wire.write(x);
Wire.endTransmission();
}
void writeMemoryUint8(uint16_t addr, uint8_t x)
{
uint8_t msb_addr = (highByte(addr) & 0x07); //get 3 MSB bits of address
uint8_t lsb_addr = lowByte(addr);
Wire.beginTransmission(Memory_I2C_Addr + msb_addr);
Wire.write(lsb_addr);
Wire.write(x);
Wire.endTransmission();
}
void writeMemoryInt16(uint16_t addr, int16_t x)
{
uint8_t msb_addr = (highByte(addr) & 0x07); //get 3 MSB bits of address
uint8_t lsb_addr = lowByte(addr);
uint8_t msb_data = highByte(x);
uint8_t lsb_data = lowByte(x);
Wire.beginTransmission(Memory_I2C_Addr + msb_addr);
Wire.write(lsb_addr);
Wire.write(lsb_data);
Wire.write(msb_data);
Wire.endTransmission();
}
void writeMemoryUint16(uint16_t addr, uint16_t x)
{
uint8_t msb_addr = (highByte(addr) & 0x07); //get 3 MSB bits of address
uint8_t lsb_addr = lowByte(addr);
uint8_t msb_data = highByte(x);
uint8_t lsb_data = lowByte(x);
Wire.beginTransmission(Memory_I2C_Addr + msb_addr);
Wire.write(lsb_addr);
Wire.write(lsb_data);
Wire.write(msb_data);
Wire.endTransmission();
}
void writeMemoryInt32(uint16_t addr, int32_t x)
{
uint8_t index, val;
uint8_t msb_addr = (highByte(addr) & 0x07); //get 3 MSB bits of address
uint8_t lsb_addr = lowByte(addr);
union
{
uint8_t b[4];
uint32_t f;
} data;
data.f = x;
Wire.beginTransmission(Memory_I2C_Addr + msb_addr);
Wire.write(lsb_addr);
for (index = 0; index < 4; index++)
{
val = data.b[index];
Wire.write(val); //write the data
}
Wire.endTransmission();
}
void writeMemoryUint32(uint16_t addr, uint32_t x)
{
uint8_t index, val;
uint8_t msb_addr = (highByte(addr) & 0x07); //get 3 MSB bits of address
uint8_t lsb_addr = lowByte(addr);
union
{
uint8_t b[4];
uint32_t f;
} data;
data.f = x;
Wire.beginTransmission(Memory_I2C_Addr + msb_addr);
Wire.write(lsb_addr);
for (index = 0; index < 4; index++)
{
val = data.b[index];
Wire.write(val); //write the data
}
Wire.endTransmission();
}
void writeMemoryFloat(uint16_t addr, float x)
{
uint8_t index, val;
uint8_t msb_addr = (highByte(addr) & 0x07); //get 3 MSB bits of address
uint8_t lsb_addr = lowByte(addr);
union
{
uint8_t b[4];
float f;
} data;
data.f = x;
Wire.beginTransmission(Memory_I2C_Addr + msb_addr);
Wire.write(lsb_addr);
for (index = 0; index < 4; index++)
{
val = data.b[index];
Wire.write(val); //write the data
}
Wire.endTransmission();
}
/***************************************************************************
Read Routines
**************************************************************************
*/
char readMemoryChar(uint16_t addr)
{
char data;
uint8_t msb_addr = (highByte(addr) & 0x07); //get 3 MSB bits of address
uint8_t lsb_addr = lowByte(addr);
Wire.beginTransmission(Memory_I2C_Addr + msb_addr);
Wire.write(lsb_addr);
Wire.endTransmission();
Wire.requestFrom((Memory_I2C_Addr + msb_addr), 1);
data = Wire.read();
return data;
}
int8_t readMemoryInt8(uint16_t addr)
{
int8_t data;
uint8_t msb_addr = (highByte(addr) & 0x07); //get 3 MSB bits of address
uint8_t lsb_addr = lowByte(addr);
Wire.beginTransmission(Memory_I2C_Addr + msb_addr);
Wire.write(lsb_addr);
Wire.endTransmission();
Wire.requestFrom((Memory_I2C_Addr + msb_addr), 1);
data = Wire.read();
return data;
}
uint8_t readMemoryUint8(uint16_t addr)
{
uint8_t data;
uint8_t msb_addr = (highByte(addr) & 0x07); //get 3 MSB bits of address
uint8_t lsb_addr = lowByte(addr);
Wire.beginTransmission(Memory_I2C_Addr + msb_addr);
Wire.write(lsb_addr);
Wire.endTransmission();
Wire.requestFrom((Memory_I2C_Addr + msb_addr), 1);
data = Wire.read();
return data;
}
int16_t readMemoryInt16(uint16_t addr)
{
uint8_t lsb_data, msb_data;
uint8_t msb_addr = (highByte(addr) & 0x07); //get 3 MSB bits of address
uint8_t lsb_addr = lowByte(addr);
Wire.beginTransmission(Memory_I2C_Addr + msb_addr);
Wire.write(lsb_addr);
Wire.endTransmission();
Wire.requestFrom(Memory_I2C_Addr + msb_addr, 2);
lsb_data = Wire.read();
msb_data = Wire.read();
return (lsb_data + (msb_data * 256));
}
uint16_t readMemoryUint16(uint16_t addr)
{
uint8_t lsb_data, msb_data;
uint8_t msb_addr = (highByte(addr) & 0x07); //get 3 MSB bits of address
uint8_t lsb_addr = lowByte(addr);
Wire.beginTransmission(Memory_I2C_Addr + msb_addr);
Wire.write(lsb_addr);
Wire.endTransmission();
Wire.requestFrom(Memory_I2C_Addr + msb_addr, 2);
lsb_data = Wire.read();
msb_data = Wire.read();
return (lsb_data + (msb_data * 256));
}
int32_t readMemoryInt32(uint16_t addr)
{
uint8_t val, index;
uint8_t msb_addr = (highByte(addr) & 0x07); //get 3 MSB bits of address
uint8_t lsb_addr = lowByte(addr);
Wire.beginTransmission(Memory_I2C_Addr + msb_addr);
Wire.write(lsb_addr);
Wire.endTransmission();
Wire.requestFrom(Memory_I2C_Addr + msb_addr, 4);
union
{
uint8_t b[4];
uint32_t f;
} readdata;
for (index = 0; index < 4; index++)
{
val = Wire.read(); // read the uint8_t
readdata.b[index] = val;
}
return readdata.f;
}
uint32_t readMemoryUint32(uint16_t addr)
{
uint8_t val, index;
uint8_t msb_addr = (highByte(addr) & 0x07); //get 3 MSB bits of address
uint8_t lsb_addr = lowByte(addr);
Wire.beginTransmission(Memory_I2C_Addr + msb_addr);
Wire.write(lsb_addr);
Wire.endTransmission();
Wire.requestFrom(Memory_I2C_Addr + msb_addr, 4);
union
{
uint8_t b[4];
uint32_t f;
} readdata;
for (index = 0; index < 4; index++)
{
val = Wire.read(); // read the uint8_t
readdata.b[index] = val;
}
return readdata.f;
}
float readMemoryFloat(uint16_t addr)
{
uint8_t val, index;
uint8_t msb_addr = (highByte(addr) & 0x07); //get 3 MSB bits of address
uint8_t lsb_addr = lowByte(addr);
Wire.beginTransmission(Memory_I2C_Addr + msb_addr);
Wire.write(lsb_addr);
Wire.endTransmission();
Wire.requestFrom(Memory_I2C_Addr + msb_addr, 4);
union
{
uint8_t b[4];
float f;
} readdata;
for (index = 0; index < 4; index++)
{
val = Wire.read(); // read the uint8_t
readdata.b[index] = val;
}
return readdata.f;
}
/***************************************************************************
Start of general purpose memory routines
***************************************************************************/
uint16_t CRCMemory(uint16_t startaddr, uint16_t endaddr, uint16_t startval)
{
uint16_t i, libraryCRC;
uint8_t j;
libraryCRC = startval; //start value for CRC16, often 0xffff
for (i = startaddr; i <= endaddr; i++) //element 4 is first character after $$$$ at start
{
libraryCRC ^= ((uint16_t)readMemoryUint8(i) << 8);
for (j = 0; j < 8; j++)
{
if (libraryCRC & 0x8000)
libraryCRC = (libraryCRC << 1) ^ 0x1021;
else
libraryCRC <<= 1;
}
}
return libraryCRC;
}
void printMemory(uint16_t start_addr, uint16_t end_addr)
{
//print the contents of Memory
uint8_t value;
for (uint16_t a = start_addr; a <= end_addr; a++)
{
value = readMemoryUint8(a);
if ((a % 16) == 0)
{
Serial.println();
Serial.print(F("0x"));
if (a < 0x10)
{
Serial.print('0');
}
Serial.print(a, HEX);
Serial.print(F(": "));
}
Serial.print(F("0x"));
if (value < 0x10)
Serial.print('0');
Serial.print(value, HEX);
Serial.print(F(" "));
}
Serial.println();
}
void fillMemory(uint16_t startaddr, uint16_t endaddr, uint8_t lval)
{
uint16_t i;
for (i = startaddr; i <= endaddr; i++)
{
writeMemoryUint8(i, lval);
}
}
/*
MIT license
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
documentation files (the "Software"), to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software,
and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions
of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.
*/

View File

@@ -0,0 +1,25 @@
--- Revised BSD License ---
Copyright (c) 2013, SEMTECH S.A.
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
* Neither the name of the Semtech corporation nor the
names of its contributors may be used to endorse or promote products
derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL SEMTECH S.A. BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

View File

@@ -0,0 +1,123 @@
/*******************************************************************************************************
Programs for Arduino - Copyright of the author Stuart Robinson - 17/12/19
This program is supplied as is, it is up to the user of the program to decide if the program is
suitable for the intended purpose and free from errors.
*******************************************************************************************************/
/*
******************************************************************************************************
Definitions for packet types
******************************************************************************************************
*/
const char Sensor1 = '!'; //Sensor packet1
const char HABPacket = '$'; //HAB style CSV ASCII packet
const char Broadcast = '*'; //Broadcast destination address
const char RControl1 = 'D'; //Remote Control packet
const char TestMode1 = '1'; //used to switch to Testmode1 settings
const char TestPacket = 'T'; //Test packet
const char TXError = 't'; //Transmitter error
const char PowerUp = 'P'; //sent on tracker start
const char LocationPacket = 'L'; //LT library tracker location packet in binary format
const char LocationBinaryPacket = 's'; //short location packet in binary format
const char NoFix = 'F'; //GPS no fix
const char NoGPS = 'G'; //No GPS found, or GPS error.
const char ACK = 'A'; //Acknowledge
const char NACK = 'N'; //Not Acknowledge, error
const char AFC = 'a'; //Packet sent for AFC purposes
const uint8_t Reliable = 0x80; //this packet type indicates reliable data packet
const uint8_t ReliableACK = 0x81; //this packet type indicates reliable data packet acknowledge
const uint8_t FTtype = 0xF0; //FTsubtype file transfer type
const uint8_t FTstart = 0xF1; //FTsubtype file transfer start information, filename etc
const uint8_t FTsegment = 0xF2; //FTsubtype packet contains a numbered segment
const uint8_t FTACK = 0xF3; //FTsubtype ACK response for file transfers
const uint8_t FTNACK = 0xF4; //FTsubtype NACK response for file transfers
const uint8_t FTclose = 0xF5; //FTsubtype request from TX to close file, transfer finished
const uint8_t FTrestart = 0xF6; //FTsubtype request from RX to restart current file transfer
//GPS Tracker Status byte settings
const uint8_t GPSFix = 0; //flag bit set when GPS has a current fix
const uint8_t GPSConfigError = 1; //flag bit set to indicate cannot configure GPS or wrong configuration
const uint8_t CameraError = 2; //flag bit indicating a camera device error
const uint8_t GPSError = 3; //flag bit set to indicate GPS error, response timeout for instance
const uint8_t LORAError = 4; //flag bit indication a lora device error
const uint8_t SDError = 5; //flag bit indication a SD card device error
const uint8_t TrackerLost = 6; //flag bit indication that tracker in lost mode
const uint8_t NoGPSTestMode = 7; //flag bit number to indicate tracker in no GPS test mode
/*********************************************************************
START Stored Program data
**********************************************************************/
const uint16_t addr_StartMemory = 0x00; //the start of memory
const uint16_t addr_StartProgramData = 0x100; //the start of program data in memory
const uint16_t addr_ResetCount = 0x100; //unsigned long int 4 bytes
const uint16_t addr_SequenceNum = 0x104; //unsigned long int 4 bytes
const uint16_t addr_TXErrors = 0x108; //uint16_t 2 bytes
const uint16_t addr_EndMemory = 0x3FF;
/*********************************************************************
START GPS CoordinateData
**********************************************************************/
//for storing last received GPS co-ordinates from local and remote tracker GPS
const uint16_t addr_StartCoordinateData = 0x300;
const uint16_t addr_RemoteLat = 0x300; //float 4 bytes
const uint16_t addr_RemoteLon = 0x304; //float 4 bytes
const uint16_t addr_RemoteAlt = 0x308; //uint16_t 2 bytes
const uint16_t addr_RemoteHour = 0x30C; //byte 1 byte; Note times for last tracker co-ordinates come from local GPS time
const uint16_t addr_RemoteMin = 0x310; //byte 1 byte
const uint16_t addr_RemoteSec = 0x311; //byte 1 byte
const uint16_t addr_RemoteDay = 0x312; //byte 1 byte
const uint16_t addr_RemoteMonth = 0x313; //byte 1 byte
const uint16_t addr_RemoteYear = 0x314; //byte 1 byte
const uint16_t addr_LocalLat = 0x318; //float 4 bytes
const uint16_t addr_LocalLon = 0x31C; //float 4 bytes
const uint16_t addr_LocalAlt = 0x320; //uint16_t 2 bytes
const uint16_t addr_LocalHour = 0x322; //byte 1 byte
const uint16_t addr_LocalMin = 0x323; //byte 1 byte
const uint16_t addr_LocalSec = 0x324; //byte 1 byte
const uint16_t addr_LocalDay = 0x325; //byte 1 byte
const uint16_t addr_LocalMonth = 0x326; //byte 1 byte
const uint16_t addr_LocalYear = 0x327; //byte 1 byte
const uint16_t addr_EndCoordinateData = 0x327;
const uint16_t addr_RemotelocationCRC = 0x340; //the 16 bit CRC of the last tracker location data is saved here
const uint16_t addr_LocallocationCRC = 0x342; //the 16 bit CRC of the last local location data is saved here
const uint16_t addr_TestLocation_page3 = 0x3FF; //used as a location for read\write tests
/*********************************************************************
END GPS CoordinateData
**********************************************************************/
/*
******************************************************************************************************
Bit numbers for current_config byte settings end definitions for packet types
******************************************************************************************************
*/
//Bit numbers for current_config byte settings in transmitter (addr_Default_config1)
const uint8_t SearchEnable = 0; //bit num to set in config byte to enable search mode packet
const uint8_t TXEnable = 1; //bit num to set in config byte to enable transmissions
const uint8_t FSKRTTYEnable = 2; //bit num to set in config byte to enable FSK RTTY
const uint8_t DozeEnable = 4; //bit num to set in config byte to put tracker in Doze mode
const uint8_t GPSHotFix = 7; //bit when set enables GPS Hot Fix mode.
/*
******************************************************************************************************
Values for reliable transmit\receive errors
******************************************************************************************************
*/
const uint16_t packettypeErr = 0x01;
const uint16_t destErr = 0x02;
const uint16_t sourceErr = 0x04;
const uint16_t timeoutErr = 0x08;
const uint16_t IDErr = 0x10;
const uint16_t crcErr = 0x20;
const uint16_t seqErr = 0x40;
const uint16_t packetErr = 0x80;

View File

@@ -0,0 +1,608 @@
/*
Copyright 2020 - Stuart Robinson
Licensed under a MIT license displayed at the bottom of this document.
Original published 12/05/20
*/
/*******************************************************************************************************
Program Operation - This is a library file for the Quectel L70,L76,L80 and L86 GPSs
The routines assume that the GPS has been setup on GPSserial which could be either software serial or
hardware serial. This library file has optimisations that the use of SoftwareSerial requires.
The calling program should include a define for the GPS baud rate as follows
#define GPSBaud 9600
If this define is missing then 9600 baud is assumed
*******************************************************************************************************/
const PROGMEM uint8_t SetBalloonMode[] = {"$PMTK886,3*2B"}; //response should be $PMTK001,886,3*36
const PROGMEM uint8_t ClearConfig[] = {"$PMTK104*37"}; //no response
const PROGMEM uint8_t PMTK_ACK[] = {"$PMTK001,xxx,?"}; //? = 0 = invalid, 1 = unsupported, 2 = valid failed, 3 = valids succeeded
const PROGMEM uint8_t SoftwareBackup[] = {"$PMTK161,0*28"}; //response should be $PMTK001,161,3*36
const PROGMEM uint8_t HotStart[] = {"$PMTK101*32"};
const PROGMEM uint8_t GGARMCOnly[] = {"$PMTK314,0,1,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0*28"};
uint8_t GPS_GetByte();
void GPS_OutputOn();
void GPS_OutputOff();
void GPS_PowerOn(int8_t pin, uint8_t state);
void GPS_PowerOff(int8_t pin, uint8_t state);
bool GPS_Setup();
bool GPS_SendConfig(const uint8_t *Progmem_ptr, uint8_t arraysize, uint8_t replylength, uint8_t attempts);
bool GPS_WaitAck(uint32_t waitms, uint8_t length);
bool GPS_WaitChar(uint8_t waitforchar, uint32_t waitmS);
uint8_t GPS_GetNextChar(uint32_t waitmS);
bool GPS_CheckAck();
bool GPS_SetBalloonMode();
bool GPS_CheckBalloonMode();
bool GPS_ClearConfig();
bool GPS_SetCyclicMode();
bool GPS_SoftwareBackup();
bool GPS_HotStart();
bool GPS_PollNavigation();
bool GPS_SaveConfig();
bool GPS_GLONASSOff(); //not currently implemented on Quectel GPS
bool GPS_GPGLLOff(); //not currently implemented on Quectel GPS
bool GPS_GPGLSOff(); //not currently implemented on Quectel GPS
bool GPS_GPGSAOff(); //not currently implemented on Quectel GPS
bool GPS_GPGSVOff(); //not currently implemented on Quectel GPS
bool GPS_GNSSmode(); //not currently implemented on Quectel GPS
bool GPS_GGARMCOnly();
const uint32_t GPS_WaitAck_mS = 2000; //number of mS to wait for an ACK response from GPS
const uint8_t GPS_attempts = 10; //number of times the sending of GPS config will be attempted.
const uint8_t GPS_Reply_Size = 20; //size of GPS reply buffer
const uint16_t GPS_Clear_DelaymS = 2000; //mS to wait after a GPS Clear command is sent
uint8_t GPS_Reply[GPS_Reply_Size]; //byte array for storing GPS reply to UBX commands
#define QUECTELINUSE //so complier can know which GPS library is used //so complier can know which GPS library is used
//#define GPSDebug
#ifndef GPSBaud
#define GPSBaud 9600
#endif
void GPS_OutputOn()
{
#ifdef GPSDebug
Serial.print(F("GPS_OutputOn() "));
#endif
//turns on serial output from GPS
GPSserial.begin(GPSBaud);
while (GPSserial.available()) GPSserial.read(); //make sure input buffer is empty
}
void GPS_OutputOff()
{
#ifdef GPSDebug
Serial.print(F("GPS_OutputOff() "));
#endif
//turns off serial output from GPS
GPSserial.end();
}
void GPS_PowerOn(int8_t pin, uint8_t state)
{
#ifdef GPSDebug
Serial.print(F("GPS_PowerOn() "));
#endif
if (pin >= 0)
{
digitalWrite(pin, state);
}
}
void GPS_PowerOff(int8_t pin, uint8_t state)
{
#ifdef GPSDebug
Serial.print(F("GPS_PowerOff() "));
#endif
if (pin >= 0)
{
digitalWrite(pin, state);
}
}
bool GPS_Setup()
{
#ifdef GPSDebug
Serial.print(F("GPS_Setup() "));
#endif
if (!GPS_SetBalloonMode())
{
return false;
}
if (!GPS_GGARMCOnly())
{
return false;
}
return true;
}
bool GPS_SendConfig(const uint8_t *Progmem_ptr, uint8_t arraysize, uint8_t replylength, uint8_t attempts)
{
#ifdef GPSDebug
Serial.print(F("GPS_SendConfig() "));
#endif
uint8_t byteread, index;
uint8_t config_attempts = attempts;
memset(GPS_Reply, 0, sizeof(GPS_Reply)); //clear the reply buffer
Serial.flush(); //ensure there are no pending interrupts from serial monitor printing
do
{
if (config_attempts == 0)
{
return false;
}
GPS_OutputOff();
Serial.print(F("GPSSend "));
for (index = 0; index < arraysize; index++)
{
byteread = pgm_read_byte_near(Progmem_ptr++);
Serial.write(byteread);
}
Serial.flush(); //make sure serial out buffer is empty
GPS_OutputOn();
Progmem_ptr = Progmem_ptr - arraysize; //set Progmem_ptr back to start
for (index = 0; index < arraysize; index++)
{
byteread = pgm_read_byte_near(Progmem_ptr++);
GPSserial.write(byteread);
}
Progmem_ptr = Progmem_ptr - arraysize; //set Progmem_ptr back to start, in case config command retried
GPSserial.write(13);
GPSserial.write(10);
if (replylength == 0)
{
break;
}
GPSserial.flush(); //make sure all of config command has been sent
config_attempts--;
}
while (!GPS_WaitAck(GPS_WaitAck_mS, replylength));
delay(100); //GPS can sometimes be a bit slow getting ready for next config
return true;
}
bool GPS_WaitChar(uint8_t waitforchar, uint32_t waitmS)
{
uint8_t GPSchar;
uint32_t startmS;
startmS = millis();
do
{
if (GPSserial.available())
{
GPSchar = GPSserial.read();
if (GPSchar == waitforchar)
{
GPS_Reply[0] = GPSchar;
return true;
}
}
}
while ((uint32_t) (millis() - startmS) < waitmS); //use the timeout to ensure a lack of GPS does not cause the program to hang
return false;
}
uint8_t GPS_GetNextChar(uint32_t waitmS)
{
uint8_t GPSchar;
uint32_t startmS;
startmS = millis();
do
{
if (GPSserial.available())
{
GPSchar = GPSserial.read();
GPS_Reply[1] = GPSchar;
return GPSchar;
}
}
while ((uint32_t) (millis() - startmS) < waitmS); //use the timeout to ensure a lack of GPS does not cause the program to hang
return '*';
}
bool GPS_WaitAck(uint32_t waitmS, uint8_t length)
{
#ifdef GPSDebug
Serial.print(F("GPS_WaitAck() "));
Serial.print(F(" Reply length "));
Serial.print(length);
Serial.print(F(" "));
#endif
uint8_t GPSchar;
uint32_t startmS;
startmS = millis();
uint8_t ptr = 0; //used as pointer to store GPS reply
bool found;
Serial.println();
Serial.print(F("Received "));
Serial.flush();
found = false;
do
{
if (!GPS_WaitChar('$', waitmS))
{
Serial.print(F("Timeout Error"));
found = false;
break;
}
Serial.print(F("$"));
GPSchar = GPS_GetNextChar(waitmS);
Serial.write(GPSchar);
if (GPSchar == 'P')
{
found = true;
break;
}
else
{
Serial.print(F(" "));
found = false;
}
}
while ((uint32_t) (millis() - startmS) < waitmS);
if (found)
{
ptr = 2;
do
{
if (GPSserial.available())
{
GPSchar = GPSserial.read();
GPS_Reply[ptr++] = GPSchar;
}
}
while (((uint32_t) (millis() - startmS) < waitmS) && (ptr < length)); //use the timeout to ensure a lack of GPS does not cause the program to hang
}
GPS_OutputOff();
for (ptr = 2; ptr < length; ptr++)
{
GPSchar = GPS_Reply[ptr];
Serial.write(GPSchar);
}
Serial.println();
if (GPS_CheckAck())
{
return true;
}
return false;
}
bool GPS_CheckBalloonMode()
{
//Reply to set balloon mode ought to be $PMTK886,3*2B, the 3 is for balloon mode
#ifdef GPSDebug
Serial.print(F("GPS_CheckBalloonMode() "));
#endif
if (GPS_SetBalloonMode())
{
return true;
}
return false;
}
bool GPS_PollNavigation()
{
#ifdef GPSDebug
Serial.print(F("GPS_PollNavigation() "));
#endif
//empty function for compatibility reasons with other GPS libraries
return true;
}
bool GPS_SaveConfig()
{
#ifdef GPSDebug
Serial.print(F("GPS_SaveConfig() "));
#endif
//empty function for compatibility reasons with other GPS libraries
return true;
}
bool GPS_CheckAck()
{
#ifdef GPSDebug
Serial.print(F("GPS_CheckAck() "));
#endif
uint8_t response[] = {"$PMTK001,xxx,?"};
uint8_t index;
for (index = 2; index <= 7; index++) //check up to the eighth ([7]) character, which is the ','
{
if ( GPS_Reply[index] != response[index])
{
return false;
}
}
if ((index == 8) && (GPS_Reply[13] == '3') ) //if we got to index 8 there was a match for $PMTK001, so check reply type
{
return true;
}
Serial.print(index);
Serial.print(F(" "));
return false;
}
/*********************************************************************
// GPS configuration commands
*********************************************************************/
bool GPS_SetBalloonMode()
{
#ifdef GPSDebug
Serial.print(F("GPS_SetBalloonMode() "));
#endif
Serial.println(F("SetBalloonMode "));
size_t SIZE = sizeof(SetBalloonMode);
if (GPS_SendConfig(SetBalloonMode, SIZE, 17, GPS_attempts))
{
Serial.println(F("OK"));
Serial.println();
return true;
}
Serial.println(F("Fail"));
Serial.println();
return false;
}
bool GPS_GGARMCOnly()
{
#ifdef GPSDebug
Serial.print(F("GPS_GGARMCOnly() "));
#endif
Serial.println(F("Set GGA and RMC only "));
size_t SIZE = sizeof(GGARMCOnly);
if (GPS_SendConfig(GGARMCOnly, SIZE, 17, GPS_attempts))
{
Serial.println(F("OK"));
Serial.println();
return true;
}
Serial.println(F("Fail"));
Serial.println();
return false;
}
bool GPS_ClearConfig()
{
Serial.println(F("ClearConfig()"));
size_t SIZE = sizeof(ClearConfig);
GPS_SendConfig(ClearConfig, SIZE, 0, GPS_attempts); //full cold start, no response is given, so replylength = 0
#ifdef GPSDebug
Serial.print(F("No Response given for full cold start"));
#endif
Serial.println();
Serial.println(F("Wait clear"));
delay(GPS_Clear_DelaymS);
return true;
}
bool GPS_SetCyclicMode()
{
#ifdef GPSDebug
Serial.print(F("GPS_SetCyclicMode() "));
#endif
//no clyclic mode config for Quectel
return true;
}
bool GPS_SoftwareBackup()
{
#ifdef GPSDebug
Serial.print(F("GPS_SoftwareBackup() "));
#endif
size_t SIZE = sizeof(SoftwareBackup);
Serial.println(F("SoftwareBackup"));
if (GPS_SendConfig(SoftwareBackup, SIZE, 0, GPS_attempts))
{
return true;
}
return false;
}
bool GPS_HotStart()
{
#ifdef GPSDebug
Serial.print(F("GPS_HotStart() "));
#endif
size_t SIZE = sizeof(HotStart);
Serial.println(F("HotStart"));
if (GPS_SendConfig(HotStart, SIZE, 0, GPS_attempts)) //reply is $PMTK010,002*2D, so not receognised by check ack
{
return true;
}
return false;
}
bool GPS_GPGLLOff()
{
#ifdef GPSDebug
Serial.print(F("GPS_GPGLLOff() "));
#endif
//setup to be added later
//function included for compatibility with other GPS library
return true;
}
bool GPS_GPGLSOff()
{
#ifdef GPSDebug
Serial.print(F("GPS_GPGLSOff() "));
#endif
//setup to be added later
//function included for compatibility with other GPS library
return true;
}
bool GPS_GPGSAOff()
{
#ifdef GPSDebug
Serial.print(F("GPS_GPGSAOff() "));
#endif
//setup to be added later
//function included for compatibility with other GPS library
return true;
}
bool GPS_GPGSVOff()
{
#ifdef GPSDebug
Serial.print(F("GPS_GPGSVOff() "));
#endif
//setup to be added later
//function included for compatibility with other GPS library
return true;
}
bool GPS_GLONASSOff()
{
#ifdef GPSDebug
Serial.print(F("GPS_GLONASSOff() "));
#endif
//setup to be added later
//function included for compatibility with other GPS library
return true;
}
bool GPS_GNSSmode()
{
#ifdef GPSDebug
Serial.print(F("GPS_GNSSmode() "));
#endif
//setup to be added later
//function included for compatibility with other GPS library
return true;
}
uint8_t GPS_GetByte() //get a byte for GPS
{
if (GPSserial.available() == 0)
{
return 0xFF; //for compatibility with I2C reading of GPS
}
else
{
return GPSserial.read();
}
}
/*
MIT license
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
documentation files (the "Software"), to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software,
and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions
of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.
*/

View File

@@ -0,0 +1,474 @@
/*
Copyright 2020 - Stuart Robinson
Licensed under a MIT license displayed at the bottom of this document.
Original published 12/05/20
*/
/*******************************************************************************************************
Program Operation - This is a library file for the Quectel L70,L76,L80 and L86 GPSs
The routines assume that the GPS has been setup on GPSserial which could be either software serial or
hardware serial. The calling program should include a define for the GPS baud rate as follows
#define GPSBaud 9600
If this define is missing then 9600 baud is assumed
*******************************************************************************************************/
const PROGMEM uint8_t SetBalloonMode[] = {"$PMTK886,3*2B"}; //response should be $PMTK001,886,3*36
const PROGMEM uint8_t ClearConfig[] = {"$PMTK104*37"}; //no response
const PROGMEM uint8_t PMTK_ACK[] = {"$PMTK001,xxx,?"}; //? = 0 = invalid, 1 = unsupported, 2 = valid failed, 3 = valids succeeded
const PROGMEM uint8_t SoftwareBackup[] = {"$PMTK161,0*28"}; //response should be $PMTK001,161,3*36
const PROGMEM uint8_t HotStart[] = {"$PMTK101*32"};
uint8_t GPS_GetByte();
void GPS_OutputOn();
void GPS_OutputOff();
void GPS_PowerOn(int8_t pin, uint8_t state);
void GPS_PowerOff(int8_t pin, uint8_t state);
bool GPS_Setup();
bool GPS_SendConfig(const uint8_t *Progmem_ptr, uint8_t arraysize, uint8_t replylength, uint8_t attempts);
bool GPS_WaitChar(uint8_t waitforchar, uint32_t waitmS);
uint8_t GPS_GetNextChar(uint32_t waitmS);
bool GPS_WaitAck(uint32_t waitms, uint8_t length);
bool GPS_CheckConfiguration();
bool GPS_CheckAck();
bool GPS_SetBalloonMode();
bool GPS_ClearConfig();
bool GPS_SetCyclicMode();
bool GPS_SoftwareBackup();
bool GPS_HotStart();
const uint32_t GPS_WaitAck_mS = 2000; //number of mS to wait for an ACK response from GPS
const uint8_t GPS_attempts = 5; //number of times the sending of GPS config will be attempted.
const uint8_t GPS_Reply_Size = 20; //size of GPS reply buffer
const uint16_t GPS_Clear_DelaymS = 2000; //mS to wait after a GPS Clear command is sent
uint8_t GPS_Reply[GPS_Reply_Size]; //byte array for storing GPS reply to UBX commands
#define QUECTELINUSE //so complier can know which GPS library is used //so complier can know which GPS library is used
//#define GPSDebug
#ifndef GPSConfigSerial // if GPSDebugSerial is not defined set to Serial as default
#define GPSConfigSerial Serial
#endif
#ifndef GPSDebugSerial // if GPSDebugSerial is not defined set to Serial as default
#define GPSDebugSerial Serial
#endif
#ifndef GPSBaud
#define GPSBaud 9600
#endif
void GPS_OutputOn()
{
#ifdef GPSDebug
Serial.print(F("GPS_OutputOn() "));
#endif
//turns on serial output from GPS
GPSserial.begin(GPSBaud);
}
void GPS_OutputOff()
{
#ifdef GPSDebug
Serial.print(F("GPS_OutputOff() "));
#endif
//turns off serial output from GPS
GPSserial.end();
}
void GPS_PowerOn(int8_t pin, uint8_t state)
{
#ifdef GPSDebug
Serial.print(F("GPS_PowerOn() "));
#endif
if (pin >= 0)
{
digitalWrite(pin, state);
}
}
void GPS_PowerOff(int8_t pin, uint8_t state)
{
#ifdef GPSDebug
Serial.print(F("GPS_PowerOff() "));
#endif
if (pin >= 0)
{
digitalWrite(pin, state);
}
}
bool GPS_Setup()
{
#ifdef GPSDebug
Serial.print(F("GPS_Setup() "));
#endif
if (!GPS_SetBalloonMode())
{
return false;
}
return true;
}
bool GPS_SendConfig(const uint8_t *Progmem_ptr, uint8_t arraysize, uint8_t replylength, uint8_t attempts)
{
#ifdef GPSDebug
Serial.print(F("GPS_SendConfig() "));
#endif
uint8_t byteread, index;
uint8_t config_attempts = attempts;
memset(GPS_Reply, 0, sizeof(GPS_Reply)); //clear the reply buffer
Serial.flush(); //ensure there are no pending interrupts from serial monitor printing
do
{
if (config_attempts == 0)
{
return false;
}
Serial.print(F("GPSSend "));
for (index = 0; index < arraysize; index++)
{
byteread = pgm_read_byte_near(Progmem_ptr++);
Serial.write(byteread);
}
Serial.flush(); //make sure serial out buffer is empty
Progmem_ptr = Progmem_ptr - arraysize; //set Progmem_ptr back to start
for (index = 0; index < arraysize; index++)
{
byteread = pgm_read_byte_near(Progmem_ptr++);
GPSserial.write(byteread);
}
Progmem_ptr = Progmem_ptr - arraysize; //set Progmem_ptr back to start, in case config command retried
GPSserial.write(13);
GPSserial.write(10);
if (replylength == 0)
{
break;
}
config_attempts--;
}
while (!GPS_WaitAck(GPS_WaitAck_mS, replylength));
delay(100); //GPS can sometimes be a bit slow getting ready for next config
return true;
}
bool GPS_WaitChar(uint8_t waitforchar, uint32_t waitmS)
{
uint8_t GPSchar;
do
{
if (GPSserial.available())
{
GPSchar = GPSserial.read();
if (GPSchar == waitforchar)
{
GPS_Reply[0] = GPSchar;
return true;
}
}
}
while ((millis() < waitmS)); //use the timeout to ensure a lack of GPS does not cause the program to hang
return false;
}
uint8_t GPS_GetNextChar(uint32_t waitmS)
{
uint8_t GPSchar;
do
{
if (GPSserial.available())
{
GPSchar = GPSserial.read();
GPS_Reply[1] = GPSchar;
return GPSchar;
}
}
while ((millis() < waitmS)); //use the timeout to ensure a lack of GPS does not cause the program to hang
return '*';
}
bool GPS_WaitAck(uint32_t waitmS, uint8_t length)
{
#ifdef GPSDebug
Serial.print(F("GPS_WaitAck() "));
Serial.print(F(" Reply length "));
Serial.print(length);
Serial.print(F(" "));
#endif
uint8_t GPSchar;
uint32_t endmS;
endmS = millis() + waitmS;
uint8_t ptr = 0; //used as pointer to store GPS reply
bool found;
Serial.println();
Serial.print(F("Received "));
Serial.flush();
endmS = millis() + GPS_WaitAck_mS;
found = false;
do
{
if (!GPS_WaitChar('$', endmS))
{
Serial.print(F("Timeout Error"));
found = false;
break;
}
Serial.print(F("$"));
GPSchar = GPS_GetNextChar(endmS);
Serial.write(GPSchar);
if (GPSchar == 'P')
{
found = true;
break;
}
else
{
Serial.print(F(" "));
found = false;
}
}
while (millis() <= endmS);
if (found)
{
ptr = 2;
do
{
if (GPSserial.available())
{
GPSchar = GPSserial.read();
GPS_Reply[ptr++] = GPSchar;
}
}
while ((millis() < endmS) && (ptr < length)); //use the timeout to ensure a lack of GPS does not cause the program to hang
}
for (ptr = 2; ptr < length; ptr++)
{
GPSchar = GPS_Reply[ptr];
Serial.write(GPSchar);
}
Serial.println();
if (GPS_CheckAck())
{
return true;
}
return false;
}
bool GPS_CheckConfiguration()
{
//Reply to set balloon mode ought to be $PMTK886,3*2B, the 3 is for balloon mode
#ifdef GPSDebug
Serial.print(F("GPS_CheckConfiguration() "));
#endif
if (GPS_SetBalloonMode())
{
return true;
}
return false;
}
bool GPS_CheckAck()
{
#ifdef GPSDebug
Serial.print(F("GPS_CheckAck() "));
#endif
uint8_t response[] = {"$PMTK001,xxx,?"};
uint8_t index;
for (index = 2; index <= 7; index++) //check up to the eighth ([7]) character, which is the ','
{
if ( GPS_Reply[index] != response[index])
{
return false;
}
}
if ((index == 8) && (GPS_Reply[13] == '3') ) //if we got to index 8 there was a match for $PMTK001, so check reply type
{
return true;
}
Serial.print(index);
Serial.print(F(" "));
return false;
}
/*********************************************************************
// GPS configuration commands
*********************************************************************/
bool GPS_SetBalloonMode()
{
#ifdef GPSDebug
Serial.print(F("GPS_SetBalloonMode() "));
#endif
Serial.println(F("SetBalloonMode "));
size_t SIZE = sizeof(SetBalloonMode);
if (GPS_SendConfig(SetBalloonMode, SIZE, 17, GPS_attempts))
{
Serial.println(F("OK"));
Serial.println();
return true;
}
Serial.println(F("Fail"));
Serial.println();
return false;
}
bool GPS_ClearConfig()
{
Serial.println(F("ClearConfig()"));
size_t SIZE = sizeof(ClearConfig);
GPS_SendConfig(ClearConfig, SIZE, 0, GPS_attempts); //full cold start, no response is given, so replylength = 0
#ifdef GPSDebug
Serial.print(F("No Response given for full cold start"));
#endif
Serial.println();
Serial.println(F("Wait clear"));
delay(GPS_Clear_DelaymS);
return true;
}
bool GPS_SetCyclicMode()
{
#ifdef GPSDebug
Serial.print(F("GPS_SetCyclicMode() "));
#endif
//no clyclic mode config for Quectel
return true;
}
bool GPS_SoftwareBackup()
{
#ifdef GPSDebug
Serial.print(F("GPS_SoftwareBackup() "));
#endif
size_t SIZE = sizeof(SoftwareBackup);
if (GPS_SendConfig(SoftwareBackup, SIZE, 0, GPS_attempts))
{
return true;
}
return false;
}
bool GPS_HotStart()
{
#ifdef GPSDebug
Serial.print(F("GPS_HotStart() "));
#endif
size_t SIZE = sizeof(HotStart);
Serial.println(F("HotStart"));
if (GPS_SendConfig(HotStart, SIZE, 0, GPS_attempts)) //reply is $PMTK010,002*2D, so not receognised by check ack
{
return true;
}
return false;
}
uint8_t GPS_GetByte() //get a byte for GPS
{
if (GPSserial.available() == 0)
{
return 0xFF; //for compatibility with I2C reading of GPS
}
else
{
return GPSserial.read();
}
}
/*
MIT license
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
documentation files (the "Software"), to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software,
and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions
of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.
*/

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,229 @@
#ifndef SX126XLT_h
#define SX126XLT_h
#include "Arduino.h"
#include <SX126XLT_Definitions.h>
/**************************************************************************
ToDO
DONE - Check setDIOIRQ is before all setTX SetRX calls
DONE - Check for checkbusy, before all uses of SPI
DONE - Match printlorasettings and printdevice settings with sx127x library
DONE - Check if SX126X has AGCauto_
DONE - Check correct setting of optimisation
DONE - Check in addressed send txpacketL = 3 + size; //we have added 3 header bytes to size
DONE - Investigate use of clearDeviceErrors() - Not used in Semtech sample code
ABANDONED - Investigate if setPacketParams(savedPacketParam1, savedPacketParam2 in send routine can be avoided - TXpacketL
DONE - Test rxEnable and txenable functionality
DONE - Check TX power settings at 17dBm +
Description of how to include RxGain register in the retention memory, see Section 9.6 - manual p58
Add a library function for SetRxDutyCycle ?
Add a library function to allow changing of ramptime from RADIO_RAMP_200_US ?
Check use of RADIO_RAMP_DEFAULT
**************************************************************************/
class SX126XLT {
public:
SX126XLT();
bool begin(int8_t pinNSS, int8_t pinNRESET, int8_t pinRFBUSY, int8_t pinDIO1, int8_t pinDIO2, int8_t pinDIO3, int8_t pinRXEN, int8_t pinTXEN, int8_t pinSW, uint8_t device);
bool begin(int8_t pinNSS, int8_t pinNRESET, int8_t pinRFBUSY, int8_t pinDIO1, uint8_t device);
bool begin(int8_t pinNSS, int8_t pinNRESET, int8_t pinRFBUSY, int8_t pinDIO1, int8_t pinSW, uint8_t device);
bool begin(int8_t pinNSS, int8_t pinNRESET, int8_t pinRFBUSY, int8_t pinDIO1, int8_t pinRXEN, int8_t pinTXEN, uint8_t device);
void checkBusy();
void writeCommand(uint8_t Opcode, uint8_t *buffer, uint16_t size );
void readCommand( uint8_t Opcode, uint8_t *buffer, uint16_t size );
void writeRegisters( uint16_t address, uint8_t *buffer, uint16_t size );
void writeRegister( uint16_t address, uint8_t value );
void readRegisters( uint16_t address, uint8_t *buffer, uint16_t size );
uint8_t readRegister( uint16_t address );
void resetDevice();
bool checkDevice();
void setupLoRa(uint32_t frequency, int32_t offset, uint8_t modParam1, uint8_t modParam2, uint8_t modParam3, uint8_t modParam4);
void setMode(uint8_t modeconfig);
void setRegulatorMode(uint8_t mode);
void setPaConfig(uint8_t dutycycle, uint8_t hpMax, uint8_t device);
void setDIO3AsTCXOCtrl(uint8_t tcxoVoltage);
void calibrateDevice(uint8_t devices);
void calibrateImage(uint32_t freq);
void setDIO2AsRfSwitchCtrl();
void setPacketType(uint8_t PacketType);
void setRfFrequency( uint32_t frequency, int32_t offset );
void setModulationParams(uint8_t modParam1, uint8_t modParam2, uint8_t modParam3, uint8_t modParam4);
uint8_t returnOptimisation(uint8_t SpreadingFactor, uint8_t Bandwidth);
uint32_t returnBandwidth(uint8_t BWregvalue);
float calcSymbolTime(float Bandwidth, uint8_t SpreadingFactor);
void setBufferBaseAddress(uint8_t txBaseAddress, uint8_t rxBaseAddress);
void setPacketParams(uint16_t packetParam1, uint8_t packetParam2, uint8_t packetParam3, uint8_t packetParam4, uint8_t packetParam5);
void setDioIrqParams(uint16_t irqMask, uint16_t dio1Mask, uint16_t dio2Mask, uint16_t dio3Mask );
void setHighSensitivity();
void setLowPowerRX();
void setSyncWord(uint16_t syncword);
void printModemSettings();
void printDevice();
uint32_t getFreqInt(); //this reads the SX126x registers to get the current frequency
uint8_t getLoRaSF();
uint8_t getLoRaCodingRate();
uint8_t getOptimisation();
uint16_t getSyncWord();
uint8_t getInvertIQ();
uint16_t getPreamble();
void printOperatingSettings();
uint8_t getHeaderMode();
uint8_t getLNAgain();
void printRegisters(uint16_t Start, uint16_t End);
void printASCIIPacket(uint8_t *buff, uint8_t tsize);
uint8_t transmit(uint8_t *txbuffer, uint8_t size, uint32_t txtimeout, int8_t txpower, uint8_t wait);
void setTxParams(int8_t TXpower, uint8_t RampTime);
void setTx(uint32_t timeout);
void clearIrqStatus( uint16_t irq );
uint16_t readIrqStatus();
uint16_t CRCCCITT(uint8_t *buffer, uint8_t size, uint16_t start);
uint8_t receive(uint8_t *rxbuffer, uint8_t size, uint32_t rxtimeout, uint8_t wait);
uint8_t readPacketRSSI();
uint8_t readPacketSNR();
uint8_t readRXPacketL();
void setRx(uint32_t timeout);
void printIrqStatus();
void rxEnable();
void txEnable();
bool config();
/***************************************************************************
//Start direct access SX buffer routines
***************************************************************************/
void startWriteSXBuffer(uint8_t ptr);
uint8_t endWriteSXBuffer();
void startReadSXBuffer(uint8_t ptr);
uint8_t endReadSXBuffer();
void writeUint8(uint8_t x);
uint8_t readUint8();
void writeInt8(int8_t x);
int8_t readInt8();
void writeInt16(int16_t x);
int16_t readInt16();
void writeUint16(uint16_t x);
uint16_t readUint16();
void writeInt32(int32_t x);
int32_t readInt32();
void writeUint32(uint32_t x);
uint32_t readUint32();
void writeFloat(float x);
float readFloat();
uint8_t transmitSXBuffer(uint8_t startaddr, uint8_t length, uint32_t txtimeout, int8_t txpower, uint8_t wait);
void writeBuffer(uint8_t *txbuffer, uint8_t size);
uint8_t receiveSXBuffer(uint8_t startaddr, uint32_t rxtimeout, uint8_t wait);
uint8_t readBuffer(uint8_t *rxbuffer);
void setupDirect(uint32_t frequency, int32_t offset);
void toneFM(uint16_t frequency, uint32_t length, uint32_t deviation, float adjust, uint8_t txpower);
void setTXDirect();
uint8_t getByteSXBuffer(uint8_t addr);
void printSXBufferHEX(uint8_t start, uint8_t end);
int32_t getFrequencyErrorHz();
int32_t getFrequencyErrorRegValue();
void printHEXByte(uint8_t temp);
uint8_t transmitAddressed(uint8_t *txbuffer, uint8_t size, char txpackettype, char txdestination, char txsource, uint32_t txtimeout, int8_t txpower, uint8_t wait);
uint8_t readRXPacketType();
uint8_t readRXDestination();
uint8_t readRXSource();
uint8_t receiveAddressed(uint8_t *rxbuffer, uint8_t size, uint32_t rxtimeout, uint8_t wait);
void clearDeviceErrors();
void printDeviceErrors();
void printHEXPacket(uint8_t *buffer, uint8_t size);
void printHEXByte0x(uint8_t temp);
uint8_t readsavedModParam1(); //spreading factor
uint8_t readsavedModParam2(); //bandwidth
uint8_t readsavedModParam3(); //code rate
uint8_t readsavedModParam4(); //optimisation
uint8_t readsavedPower();
uint8_t getPacketMode();
uint8_t readsavedPacketParam1(); //preamble
uint8_t readsavedPacketParam2(); //header type
uint8_t readsavedPacketParam3(); //packet length
uint8_t readsavedPacketParam4(); //CRC
uint8_t readsavedPacketParam5(); //IQ
uint8_t getOpmode();
uint8_t getCRCMode();
void fillSXBuffer(uint8_t startaddress, uint8_t size, uint8_t character);
uint8_t readPacket(uint8_t *rxbuffer, uint8_t size);
void writeByteSXBuffer(uint8_t addr, uint8_t regdata);
void printSXBufferASCII(uint8_t start, uint8_t end);
void startFSKRTTY(uint32_t freqshift, uint8_t pips, uint16_t pipPeriodmS, uint16_t pipDelaymS, uint16_t leadinmS);
void transmitFSKRTTY(uint8_t chartosend, uint8_t databits, uint8_t stopbits, uint8_t parity, uint16_t baudPerioduS, int8_t pin);
void transmitFSKRTTY(uint8_t chartosend, uint16_t baudPerioduS, int8_t pin);
void printRTTYregisters();
void endFSKRTTY();
void getRfFrequencyRegisters(uint8_t *buff);
void setRfFrequencyDirect(uint8_t high, uint8_t midhigh, uint8_t midlow, uint8_t low);
/***************************************************************************
//End direct access SX buffer routines
***************************************************************************/
uint16_t CRCCCITTSX(uint8_t startadd, uint8_t endadd, uint16_t startvalue);
void setSleep(uint8_t sleepconfig);
void wake();
private:
int8_t _NSS, _NRESET, _RFBUSY, _DIO1, _DIO2, _DIO3, _SW;
int8_t _RXEN, _TXEN;
uint8_t _RXPacketL; //length of packet received
uint8_t _RXPacketType; //type number of received packet
uint8_t _RXDestination; //destination address of received packet
uint8_t _RXSource; //source address of received packet
int8_t _PacketRSSI; //RSSI of received packet
int8_t _PacketSNR; //signal to noise ratio of received packet
int8_t _TXPacketL;
uint8_t _RXcount; //used to keep track of the bytes read from SX126X buffer during readFloat() etc
uint8_t _TXcount; //used to keep track of the bytes written to SX126X buffer during writeFloat() etc
uint8_t _RXBufferPointer; //pointer to first byte of packet in buffer
uint8_t _OperatingMode; //current operating mode
bool _rxtxpinmode = false; //set to true if RX and TX enable pin mode is used.
uint8_t _Device; //saved device type
uint8_t _TXDonePin; //the pin that will indicate TX done
uint8_t _RXDonePin; //the pin that will indicate RX done
uint32_t savedFrequency;
int32_t savedOffset;
uint8_t savedPacketType;
uint8_t savedRegulatorMode;
uint8_t savedModParam1, savedModParam2, savedModParam3, savedModParam4;
uint16_t savedPacketParam1;
uint8_t savedPacketParam2, savedPacketParam3, savedPacketParam4, savedPacketParam5;
uint16_t savedIrqMask, savedDio1Mask, savedDio2Mask, savedDio3Mask;
int8_t savedTXPower;
uint32_t savedFrequencyReg;
uint8_t _freqregH, _freqregMH, _freqregML,_freqregL; //the registers values for the set frequency
uint8_t _ShiftfreqregH, _ShiftfreqregMH, _ShiftfreqregML, _ShiftfreqregL; //register values for shifted frequency, used in FSK
};
#endif

View File

@@ -0,0 +1,305 @@
/*
Copyright 2019 - Stuart Robinson
Licensed under a MIT license displayed at the bottom of this document.
17/12/19
*/
#define XTAL_FREQ 32000000
#define FREQ_DIV 33554432
#define FREQ_STEP 0.95367431640625
#define FREQ_ERR 0.47683715820312
#define FREQ_ERROR_CORRECTION 1.55 //this was measured on SX1280 for bandwidth of 400khz
#define AUTO_RX_TX_OFFSET 2
#define CRC_IBM_SEED 0xFFFF
#define CRC_CCITT_SEED 0x1D0F
#define CRC_POLYNOMIAL_IBM 0x8005
#define CRC_POLYNOMIAL_CCITT 0x1021
//Registers - Used, tested
#define REG_LR_PAYLOADLENGTH 0x0702
#define REG_IQ_POLARITY_SETUP 0x0736
#define REG_LR_SYNCWORD 0x0740
#define REG_RX_GAIN 0x08AC
#define REG_TX_MODULATION 0x0889
#define REG_RFFrequency31_24 0x088B
#define REG_RFFrequency23_16 0x088C
#define REG_RFFrequency15_8 0x088D
#define REG_RFFrequency7_0 0x088E
//Registers - Not used, not tested
#define REG_LR_WHITSEEDBASEADDR_MSB 0x06B8
#define REG_LR_WHITSEEDBASEADDR_LSB 0x06B9
#define REG_LR_CRCSEEDBASEADDR 0x06BC
#define REG_LR_CRCPOLYBASEADDR 0x06BE
#define REG_LR_PACKETPARAMS 0x0704
#define REG_LR_SYNCWORDBASEADDRESS 0x06C0
#define REG_FREQUENCY_ERRORBASEADDR 0x076B
#define RANDOM_NUMBER_GENERATORBASEADDR 0x0819
#define REG_OCP 0x08E7
#define REG_XTA_TRIM 0x0911
#define LORA_MAC_PRIVATE_SYNCWORD 0x1424
#define LORA_MAC_PUBLIC_SYNCWORD 0x3444
#define PRINT_LOW_REGISTER 0x680
#define PRINT_HIGH_REGISTER 0x920
#define POWER_SAVE_GAIN 0x94
#define BOOSTED_GAIN 0x96
//radio operatine modes
#define MODE_SLEEP 0x07
#define MODE_STDBY_RC 0x00 //Device running on RC13M, set STDBY_RC mode
#define MODE_STDBY_XOSC 0x01 //Device running on XTAL 32MHz, set STDBY_XOSC mode
#define MODE_FS 0x02 // The radio is in frequency synthesis mode
#define MODE_TX 0x03 //TX mode
#define MODE_RX 0x04 //RX mode
#define MODE_RX_DC 0x05 //RX duty cycle mode
#define MODE_CAD 0x06 //RX CAD mode
//Sleep Mode Definition
#define COLD_START 0x00
#define WARM_START 0x04
#define RTC_TIMEOUT_DISABLE 0x00
#define RTC_TIMEOUT_ENABLE 0x01
#define USE_LDO 0x00 //default
#define USE_DCDC 0x01
#define PACKET_TYPE_GFSK 0x00
#define PACKET_TYPE_LORA 0x01
#define PACKET_TYPE_NONE 0x0F
#define RADIO_RAMP_10_US 0x00
#define RADIO_RAMP_20_US 0x01
#define RADIO_RAMP_40_US 0x02
#define RADIO_RAMP_80_US 0x03
#define RADIO_RAMP_200_US 0x04
#define RADIO_RAMP_800_US 0x05
#define RADIO_RAMP_1700_US 0x06
#define RADIO_RAMP_3400_US 0x07
#define LORA_CAD_01_SYMBOL 0x00
#define LORA_CAD_02_SYMBOL 0x01
#define LORA_CAD_04_SYMBOL 0x02
#define LORA_CAD_08_SYMBOL 0x03
#define LORA_CAD_16_SYMBOL 0x04
#define LORA_CAD_ONLY 0x00
#define LORA_CAD_RX 0x01
#define LORA_CAD_LBT 0x10
#define LORA_SF5 0x05
#define LORA_SF6 0x06
#define LORA_SF7 0x07
#define LORA_SF8 0x08
#define LORA_SF9 0x09
#define LORA_SF10 0x0A
#define LORA_SF11 0x0B
#define LORA_SF12 0x0C
#define LORA_BW_500 6 //actual 500000hz
#define LORA_BW_250 5 //actual 250000hz
#define LORA_BW_125 4 //actual 125000hz
#define LORA_BW_062 3 //actual 62500hz
#define LORA_BW_041 10 //actual 41670hz
#define LORA_BW_031 2 //actual 31250hz
#define LORA_BW_020 9 //actual 20830hz
#define LORA_BW_015 1 //actual 15630hz
#define LORA_BW_010 8 //actual 10420hz
#define LORA_BW_007 0 //actual 7810hz
#define LORA_CR_4_5 0x01
#define LORA_CR_4_6 0x02
#define LORA_CR_4_7 0x03
#define LORA_CR_4_8 0x04
#define WAIT_RX 0x01
#define WAIT_TX 0x01
#define NO_WAIT 0x00
#define RADIO_PREAMBLE_DETECTOR_OFF 0x00 //!< Preamble detection length off
#define RADIO_PREAMBLE_DETECTOR_08_BITS 0x04 //!< Preamble detection length 8 bits
#define RADIO_PREAMBLE_DETECTOR_16_BITS 0x05 //!< Preamble detection length 16 bits
#define RADIO_PREAMBLE_DETECTOR_24_BITS 0x06 //!< Preamble detection length 24 bits
#define RADIO_PREAMBLE_DETECTOR_32_BITS 0x07 //!< Preamble detection length 32 bit
#define RADIO_ADDRESSCOMP_FILT_OFF 0x00 //!< No correlator turned on i.e. do not search for SyncWord
#define RADIO_ADDRESSCOMP_FILT_NODE 0x01
#define RADIO_ADDRESSCOMP_FILT_NODE_BROAD 0x02
#define RADIO_PACKET_FIXED_LENGTH 0x00 //!< The packet is known on both sides no header included in the packet
#define RADIO_PACKET_VARIABLE_LENGTH 0x01 //!< The packet is on variable size header included
#define RADIO_CRC_OFF 0x01 //!< No CRC in use
#define RADIO_CRC_1_BYTES 0x00
#define RADIO_CRC_2_BYTES 0x02
#define RADIO_CRC_1_BYTES_INV 0x04
#define RADIO_CRC_2_BYTES_INV 0x06
#define RADIO_CRC_2_BYTES_IBM 0xF1
#define RADIO_CRC_2_BYTES_CCIT 0xF2
#define RADIO_DC_FREE_OFF 0x00
#define RADIO_DC_FREEWHITENING 0x01
#define LORA_PACKET_VARIABLE_LENGTH 0x00 //!< The packet is on variable size header included
#define LORA_PACKET_FIXED_LENGTH 0x01 //!< The packet is known on both sides no header included in the packet
#define LORA_PACKET_EXPLICIT LORA_PACKET_VARIABLE_LENGTH
#define LORA_PACKET_IMPLICIT LORA_PACKET_FIXED_LENGTH
#define LORA_CRC_ON 0x01 //!< CRC activated
#define LORA_CRC_OFF 0x00 //!< CRC not used
#define LORA_IQ_NORMAL 0x00
#define LORA_IQ_INVERTED 0x01
#define TCXO_CTRL_1_6V 0x00
#define TCXO_CTRL_1_7V 0x01
#define TCXO_CTRL_1_8V 0x02
#define TCXO_CTRL_2_2V 0x03
#define TCXO_CTRL_2_4V 0x04
#define TCXO_CTRL_2_7V 0x05
#define TCXO_CTRL_3_0V 0x06
#define TCXO_CTRL_3_3V 0x07
#define IRQ_RADIO_NONE 0x0000
#define IRQ_TX_DONE 0x0001
#define IRQ_RX_DONE 0x0002
#define IRQ_PREAMBLE_DETECTED 0x0004
#define IRQ_SYNCWORD_VALID 0x0008
#define IRQ_HEADER_VALID 0x0010
#define IRQ_HEADER_ERROR 0x0020
#define IRQ_CRC_ERROR 0x0040
#define IRQ_CAD_DONE 0x0080
#define IRQ_CAD_ACTIVITY_DETECTED 0x0100
#define IRQ_RX_TX_TIMEOUT 0x0200
#define IRQ_TX_TIMEOUT 0x0200
#define IRQ_RX_TIMEOUT 0x0200
#define IRQ_RADIO_ALL 0xFFFF
#define RADIO_GET_STATUS 0xC0
#define RADIO_WRITE_REGISTER 0x0D
#define RADIO_READ_REGISTER 0x1D
#define RADIO_WRITE_BUFFER 0x0E
#define RADIO_READ_BUFFER 0x1E
#define RADIO_SET_SLEEP 0x84
#define RADIO_SET_STANDBY 0x80
#define RADIO_SET_FS 0xC1
#define RADIO_SET_TX 0x83
#define RADIO_SET_RX 0x82
#define RADIO_SET_RXDUTYCYCLE 0x94
#define RADIO_SET_CAD 0xC5
#define RADIO_SET_TXCONTINUOUSWAVE 0xD1
#define RADIO_SET_TXCONTINUOUSPREAMBLE 0xD2
#define RADIO_SET_PACKETTYPE 0x8A
#define RADIO_GET_PACKETTYPE 0x11
#define RADIO_SET_RFFREQUENCY 0x86
#define RADIO_SET_TXPARAMS 0x8E
#define RADIO_SET_PACONFIG 0x95
#define RADIO_SET_CADPARAMS 0x88
#define RADIO_SET_BUFFERBASEADDRESS 0x8F
#define RADIO_SET_MODULATIONPARAMS 0x8B
#define RADIO_SET_PACKETPARAMS 0x8C
#define RADIO_GET_RXBUFFERSTATUS 0x13
#define RADIO_GET_PACKETSTATUS 0x14
#define RADIO_GET_RSSIINST 0x15
#define RADIO_GET_STATS 0x10
#define RADIO_RESET_STATS 0x00
#define RADIO_CFG_DIOIRQ 0x08
#define RADIO_GET_IRQSTATUS 0x12
#define RADIO_CLR_IRQSTATUS 0x02
#define RADIO_CALIBRATE 0x89
#define RADIO_CALIBRATEIMAGE 0x98
#define RADIO_SET_REGULATORMODE 0x96
#define RADIO_GET_ERROR 0x17
#define RADIO_CLEAR_ERRORS 0x07
#define RADIO_SET_TCXOMODE 0x97
#define RADIO_SET_TXFALLBACKMODE 0x93
#define RADIO_SET_RFSWITCHMODE 0x9D
#define RADIO_SET_STOPRXTIMERONPREAMBLE 0x9F
#define RADIO_SET_LORASYMBTIMEOUT 0xA0
//Table 13-2 SX126X Sleep modes
#define CONFIGURATION_RETENTION 0x04
#define RTC_TIMEOUT_ENABLE 0x01
#define LDRO_OFF 0x00
#define LDRO_ON 0x01
#define LDRO_AUTO 0x02 //when used causes LDRO to be automatically calculated
#define DEVICE_SX1261 0x01
#define DEVICE_SX1262 0x00
#define DEVICE_SX1268 0x02
#define PAAUTO 0xFF
#define HPMAXAUTO 0xFF
#ifndef RAMP_TIME
#define RAMP_TIME RADIO_RAMP_40_US
#endif
#define RC64KEnable 0x01 //calibrate RC64K clock
#define RC13MEnable 0x02 //calibrate RC13M clock
#define PLLEnable 0x04 //calibrate PLL
#define ADCPulseEnable 0x08 //calibrate ADC Pulse
#define ADCBulkNEnable 0x10 //calibrate ADC bulkN
#define ADCBulkPEnable 0x20 //calibrate ADC bulkP
#define ImgEnable 0x40 //calibrate image
#define ALLDevices 0x7F //calibrate all devices
#define RC64K_CALIB_ERR 0x0001
#define RC13M_CALIB_ERR 0x0002
#define PLL_CALIB_ERR 0x0004
#define ADC_CALIB_ERR 0x0008
#define IMG_CALIB_ERR 0x0010
#define XOSC_START_ERR 0x0020
#define PLL_LOCK_ERR 0x0040
#define RFU 0x0080
#define PA_RAMP_ERR 0x0100
//SPI settings
#define LTspeedMaximum 8000000
#define LTdataOrder MSBFIRST
#define LTdataMode SPI_MODE0
//FSKRTTY Settings
#define ParityNone 0
#define ParityOdd 1
#define ParityEven 2
#define ParityZero 0xF0
#define ParityOne 0xF1
#define ToneMinuS 52 //timed constant for ATmega328P at 8Mhz with FM Tone delayus at 0, period for half loop
/*
MIT license
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
documentation files (the "Software"), to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software,
and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions
of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.
*/

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,263 @@
/*
Copyright 2020 - Stuart Robinson
Licensed under a MIT license displayed at the bottom of this document.
Original published 17/12/19
New version 23/12/20
*/
#ifndef SX127XLT_h
#define SX127XLT_h
#include <Arduino.h>
#include <SX127XLT_Definitions.h>
class SX127XLT
{
public:
SX127XLT();
bool begin(int8_t pinNSS, int8_t pinNRESET, int8_t pinDIO0, int8_t pinDIO1, int8_t pinDIO2, uint8_t device);
bool begin(int8_t pinNSS, int8_t pinNRESET, int8_t pinDIO0, uint8_t device);
bool begin(int8_t pinNSS, uint8_t device);
void resetDevice();
void setMode(uint8_t modeconfig);
void setSleep(uint8_t sleepconfig);
bool checkDevice();
void wake();
void calibrateImage(uint8_t null);
uint16_t CRCCCITT(uint8_t *buffer, uint16_t size, uint16_t startvalue);
uint16_t CRCCCITTSX(uint8_t startadd, uint8_t endadd, uint16_t startvalue);
void setDevice(uint8_t type);
void printDevice();
uint8_t getOperatingMode();
bool isReceiveDone();
bool isTransmitDone();
void writeRegister( uint8_t address, uint8_t value );
uint8_t readRegister( uint8_t address );
void printRegisters(uint16_t start, uint16_t end);
void printRegister(uint8_t reg);
void printOperatingMode();
void printOperatingSettings();
void setTxParams(int8_t txPower, uint8_t rampTime);
void setPacketParams(uint16_t packetParam1, uint8_t packetParam2, uint8_t packetParam3, uint8_t packetParam4, uint8_t packetParam5);
void setModulationParams(uint8_t modParam1, uint8_t modParam2, uint8_t modParam3, uint8_t modParam4);
void setRfFrequency(uint64_t freq64, int32_t offset);
uint32_t getFreqInt();
int32_t getFrequencyErrorRegValue();
int32_t getFrequencyErrorHz();
void setTx(uint32_t timeout);
void setRx(uint32_t timeout);
bool readTXIRQ();
bool readRXIRQ();
void setLowPowerReceive();
void setHighSensitivity();
void setRXGain(uint8_t config);
uint8_t getAGC();
uint8_t getLNAgain();
uint8_t getCRCMode();
uint8_t getHeaderMode();
uint8_t getLNAboostHF();
uint8_t getLNAboostLF();
uint8_t getOpmode();
uint8_t getPacketMode();
uint8_t readRXPacketL();
uint8_t readTXPacketL();
int16_t readPacketRSSI();
int16_t readCurrentRSSI();
int8_t readPacketSNR();
bool readPacketCRCError();
bool readPacketHeaderValid();
uint8_t packetOK();
uint8_t readRXPacketType();
uint8_t readRXDestination();
uint8_t readRXSource();
void setBufferBaseAddress(uint8_t txBaseAddress, uint8_t rxBaseAddress);
void setPacketType(uint8_t PacketType);
void clearIrqStatus( uint16_t irqMask );
uint16_t readIrqStatus();
void setDioIrqParams(uint16_t irqMask, uint16_t dio0Mask, uint16_t dio1Mask, uint16_t dio2Mask );
void printIrqStatus();
void printASCIIPacket(uint8_t *buff, uint8_t tsize);
void printHEXPacket(uint8_t *buff, uint8_t tsize);
void printASCIIorHEX(uint8_t temp);
void printHEXByte(uint8_t temp);
void printHEXByte0x(uint8_t temp);
bool isRXdone();
bool isTXdone();
bool isRXdoneIRQ();
bool isTXdoneIRQ();
void setTXDonePin(uint8_t pin);
void setRXDonePin(uint8_t pin);
//*******************************************************************************
//Packet Read and Write Routines
//*******************************************************************************
uint8_t receive(uint8_t *rxbuffer, uint8_t size, uint32_t rxtimeout, uint8_t wait);
uint8_t receiveAddressed(uint8_t *rxbuffer, uint8_t size, uint32_t rxtimeout, uint8_t wait);
uint8_t readPacket(uint8_t *rxbuffer, uint8_t size);
uint8_t readPacketAddressed(uint8_t *rxbuffer, uint8_t size);
uint8_t transmit(uint8_t *txbuffer, uint8_t size, uint32_t txtimeout, int8_t txPower, uint8_t wait);
uint8_t transmitAddressed(uint8_t *txbuffer, uint8_t size, char txpackettype, char txdestination, char txsource, uint32_t txtimeout, int8_t txpower, uint8_t wait);
//*******************************************************************************
//LoRa specific routines
//*******************************************************************************
void setupLoRa(uint32_t Frequency, int32_t Offset, uint8_t modParam1, uint8_t modParam2, uint8_t modParam3, uint8_t modParam4);
uint8_t getLoRaSF();
uint8_t getLoRaCodingRate();
uint8_t getOptimisation();
uint8_t getSyncWord();
uint8_t getInvertIQ();
uint8_t getVersion();
uint16_t getPreamble();
uint32_t returnBandwidth(uint8_t BWregvalue);
uint8_t returnOptimisation(uint8_t SpreadingFactor, uint8_t Bandwidth);
float calcSymbolTime(float Bandwidth, uint8_t SpreadingFactor);
void printModemSettings();
void setSyncWord(uint8_t syncword);
void setTXDirect();
void setupDirect(uint32_t frequency, int32_t offset);
void toneFM(uint16_t frequency, uint32_t length, uint32_t deviation, float adjust, int8_t txpower);
int8_t getDeviceTemperature();
void fskCarrierOn(int8_t txpower);
void fskCarrierOff();
void setRfFrequencyDirect(uint8_t high, uint8_t mid, uint8_t low);
void getRfFrequencyRegisters(uint8_t *buff);
void startFSKRTTY(uint32_t freqshift, uint8_t pips, uint16_t pipDelaymS, uint16_t pipPeriodmS, uint16_t leadinmS);
void transmitFSKRTTY(uint8_t chartosend, uint8_t databits, uint8_t stopbits, uint8_t parity, uint16_t baudPerioduS, int8_t pin);
void transmitFSKRTTY(uint8_t chartosend, uint16_t baudPerioduS, int8_t pin);
void printRTTYregisters();
void endFSKRTTY();
void doAFC();
void doAFCPPM();
uint8_t getPPM();
int32_t getOffset();
void printOCPTRIM();
uint8_t readBufferbytes(uint8_t *rxbuffer, uint8_t size);
uint8_t writeBufferbytes(uint8_t *txbuffer, uint8_t size);
void setDevicePABOOST();
void setDeviceRFO();
//*******************************************************************************
//Read Write SX12xxx Buffer commands, this is the buffer internal to the SX12xxxx
//*******************************************************************************
uint8_t receiveSXBuffer(uint8_t startaddr, uint32_t rxtimeout, uint8_t wait);
uint8_t transmitSXBuffer(uint8_t startaddr, uint8_t length, uint32_t txtimeout, int8_t txpower, uint8_t wait);
void printSXBufferHEX(uint8_t start, uint8_t end);
void printSXBufferASCII(uint8_t start, uint8_t end);
void fillSXBuffer(uint8_t startaddress, uint8_t size, uint8_t character);
uint8_t getByteSXBuffer(uint8_t addr);
void writeByteSXBuffer(uint8_t addr, uint8_t regdata);
void startWriteSXBuffer(uint8_t ptr);
uint8_t endWriteSXBuffer();
void startReadSXBuffer(uint8_t ptr);
uint8_t endReadSXBuffer();
void writeUint8(uint8_t x);
uint8_t readUint8();
void writeInt8(int8_t x);
int8_t readInt8();
void writeChar(char x);
char readChar();
void writeUint16(uint16_t x);
uint16_t readUint16();
void writeInt16(int16_t x);
int16_t readInt16();
void writeUint32(uint32_t x);
uint32_t readUint32();
void writeInt32(int32_t x);
int32_t readInt32();
void writeFloat(float x);
float readFloat();
void writeBuffer(uint8_t *txbuffer, uint8_t size);
void writeBufferChar(char *txbuffer, uint8_t size);
void writeBufferChar(char *txbuffer);
uint8_t readBuffer(uint8_t *rxbuffer);
uint8_t readBuffer(uint8_t *rxbuffer, uint8_t size);
uint8_t readBufferChar(char *rxbuffer);
//*******************************************************************************
//RX\TX Enable routines - Not yet tested as of 02/12/19
//*******************************************************************************
void rxtxInit(int8_t pinRXEN, int8_t pinTXEN); //not used on current SX127x modules
void rxEnable(); //not used on current SX127x modules
void txEnable(); //not used on current SX127x modules
//*******************************************************************************
//Library variables
//*******************************************************************************
private:
int8_t _NSS, _NRESET, _DIO0, _DIO1, _DIO2;
uint8_t _RXPacketL; //length of packet received
uint8_t _RXPacketType; //type number of received packet
uint8_t _RXDestination; //destination address of received packet
uint8_t _RXSource; //source address of received packet
uint8_t _TXPacketL; //length of transmitted packet
uint16_t _IRQmsb; //for setting additional flags
uint8_t _Device; //saved device type
int8_t _TXDonePin; //the pin that will indicate TX done
int8_t _RXDonePin; //the pin that will indicate RX done
uint8_t _UseCRC; //when packet parameters are set this flag is set if CRC on packets in use
int8_t _RXEN, _TXEN; //for modules that have RX TX pin switching
uint8_t _PACKET_TYPE; //used to save the set packet type
uint8_t _freqregH, _freqregM, _freqregL; //the registers values for the set frequency
uint8_t _ShiftfreqregH, _ShiftfreqregM, _ShiftfreqregL; //register values for shifted frequency, used in FSK RTTY etc
uint32_t _savedFrequency; //when setRfFrequency() is used the set frequency is saved
int32_t _savedOffset; //when setRfFrequency() is used the set offset is saved
};
#endif
/*
MIT license
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
documentation files (the "Software"), to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software,
and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions
of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.
*/

View File

@@ -0,0 +1,314 @@
/*
Copyright 2019 - Stuart Robinson
Licensed under a MIT license displayed at the bottom of this document.
Original published 17/12/19
*/
#define LORA_MAC_PRIVATE_SYNCWORD 0x12
#define LORA_MAC_PUBLIC_SYNCWORD 0x34
//radio operatine modes - see RegOpMode in register map
#define MODE_SLEEP 0x00
#define MODE_STDBY 0x01
#define MODE_STDBY_RC 0x01
#define MODE_FSTX 0x02 //Frequency synthesis TX mode
#define MODE_TX 0x03 //TX mode
#define MODE_FSRX 0x04 //Frequency synthesis RX mode
#define MODE_RXCONTINUOUS 0x05 //RX continuous mode
#define MODE_RXSINGLE 0x06 //RX single mode
#define MODE_CAD 0xFF //RX CAD mode
#define POWERSAVE 0xC0 //select minimum LNA gain
#define BOOSTED 0x38 //mode for booted, max LNA gain
#define LNAGAING1 0x20 //maximum LNA gain
#define LNAGAING2 0x40
#define LNAGAING3 0x60
#define LNAGAING4 0x80
#define LNAGAING5 0xA0
#define LNAGAING6 0xC0 //minimum LNA gain
#define PACKET_TYPE_GFSK 0x00 //regopmode setting for FSK and direct mode
#define PACKET_TYPE_LORA 0x80 //regopmode setting for LoRa
#define PACKET_TYPE_NONE 0x0F
#define RADIO_RAMP_10_US 0x0F
#define RADIO_RAMP_12_US 0x0E
#define RADIO_RAMP_15_US 0x0D
#define RADIO_RAMP_20_US 0x0C
#define RADIO_RAMP_25_US 0x0B
#define RADIO_RAMP_31_US 0x0A
#define RADIO_RAMP_40_US 0x09
#define RADIO_RAMP_50_US 0x08
#define RADIO_RAMP_62_US 0x07
#define RADIO_RAMP_100_US 0x06
#define RADIO_RAMP_125_US 0x05
#define RADIO_RAMP_250_US 0x04
#define RADIO_RAMP_500_US 0x03
#define RADIO_RAMP_1000_US 0x02
#define RADIO_RAMP_2000_US 0x01
#define RADIO_RAMP_3400_US 0x00
#define RADIO_RAMP_DEFAULT 0x09
#define OCP_TRIM_ON 0x20
#define OCP_TRIM_OFF 0x00
#define OCP_TRIM_45MA 0x00
#define OCP_TRIM_80MA 0x07
#define OCP_TRIM_100MA 0x0B
#define OCP_TRIM_110MA 0x0D
#define OCP_TRIM_120MA 0x0F
#define OCP_TRIM_130MA 0x10
#define OCP_TRIM_140MA 0x11
#define OCP_TRIM_150MA 0x12
//Constant names for bandwidth settings
#define LORA_BW_500 144 //actual 500000hz
#define LORA_BW_250 128 //actual 250000hz
#define LORA_BW_125 112 //actual 125000hz
#define LORA_BW_062 96 //actual 62500hz
#define LORA_BW_041 80 //actual 41670hz
#define LORA_BW_031 64 //actual 31250hz
#define LORA_BW_020 48 //actual 20830hz
#define LORA_BW_015 32 //actual 15630hz
#define LORA_BW_010 16 //actual 10420hz
#define LORA_BW_007 0 //actual 7810hz
//for SX127x
#define LORA_SF6 0x06
#define LORA_SF7 0x07
#define LORA_SF8 0x08
#define LORA_SF9 0x09
#define LORA_SF10 0x0A
#define LORA_SF11 0x0B
#define LORA_SF12 0x0C
#define LORA_CR_4_5 0x02
#define LORA_CR_4_6 0x04
#define LORA_CR_4_7 0x06
#define LORA_CR_4_8 0x08
#define LDRO_OFF 0x00
#define LDRO_ON 0x01
#define LDRO_AUTO 0x02 //when set causes LDRO to be automatically calculated
#define WAIT_RX 0x01
#define WAIT_TX 0x01
#define NO_WAIT 0x00
#define FREQ_STEP 61.03515625
//These are the &/AND values for reading a parameter from a register.
//For example the Bandwidth on a SX1278 is stored in bits 7-4 and those bits are
//in effect numbers from 0 to 9, where 0 = 7800hz and 9 = 500000hz. Thus to read
//the bandwidth value you need to &/AND the contents of the register with a value
//The registers and values are different for SX1272 and the rest, so they are identified
//by _2 and _X respectivly. To read all the bits of a register, appart from the setting
//use the &/AND value with all bits inverted.
#define READ_BW_AND_2 0xC0 //register 0x1D
#define READ_BW_AND_X 0xF0 //register 0x1D
#define READ_CR_AND_2 0x38 //register 0x1D
#define READ_CR_AND_X 0x0E //register 0x1D
#define READ_SF_AND_2 0xF0 //register 0x1E
#define READ_SF_AND_X 0xF0 //register 0x1E
#define READ_HASCRC_AND_2 0x02 //register 0x1D
#define READ_HASCRC_AND_X 0x04 //register 0x1E
#define READ_LDRO_AND_2 0x01 //register 0x1D
#define READ_LDRO_AND_X 0x08 //register 0x26
#define READ_AGCAUTO_AND_2 0x04 //register 0x1E
#define READ_AGCAUTO_AND_X 0x04 //register 0x26
#define READ_IMPLCIT_AND_2 0x04 //register 0x1D
#define READ_IMPLCIT_AND_X 0x01 //register 0x1D
#define READ_LNAGAIN_AND_2 0xE0 //register 0x0C
#define READ_LNAGAIN_AND_X 0xE0 //register 0x0C
#define READ_LNABOOSTHF_AND_2 0x03 //register 0x0C
#define READ_LNABOOSTHF_AND_X 0x03 //register 0x0C
#define READ_LNABOOSTLF_AND_2 0x18 //register 0x0C
#define READ_LNABOOSTLF_AND_X 0x18 //register 0x0C
#define READ_OPMODE_AND_2 0x18 //register 0x01
#define READ_OPMODE_AND_X 0x18 //register 0x01
#define READ_RANGEMODE_AND_2 0x80 //register 0x01
#define READ_RANGEMODE_AND_X 0x80 //register 0x01
#define LORA_PACKET_VARIABLE_LENGTH 0x00
#define LORA_PACKET_FIXED_LENGTH 0x01
#define LORA_PACKET_EXPLICIT LORA_PACKET_VARIABLE_LENGTH
#define LORA_PACKET_IMPLICIT LORA_PACKET_FIXED_LENGTH
//for SX127x
#define LORA_CRC_ON 0x01 //Packet CRC is activated
#define LORA_CRC_OFF 0x00 //Packet CRC not used
#define LORA_IQ_NORMAL 0x00
#define LORA_IQ_INVERTED 0x40
//For SX127x - mapping of these IRQs to the SX126x and SX128x style is not easy
//the values have been fixed to these following DIOs. For instance IRQ_RX_DONE,
//IRQ_TX_DONE and IRQ_CAD_DONE can only be mapped to DIO0.
//For most applications only DIO0, DIO1 and DIO2 are connected.
#define IRQ_RADIO_NONE 0x00
#define IRQ_CAD_ACTIVITY_DETECTED 0x01 //active on DIO1
#define IRQ_FSHS_CHANGE_CHANNEL 0x02 //active on DIO2
#define IRQ_CAD_DONE 0x04 //active on DIO0
#define IRQ_TX_DONE 0x08 //active on DIO0
#define IRQ_HEADER_VALID 0x10 //read from IRQ register only
#define IRQ_CRC_ERROR 0x20 //read from IRQ register only
#define IRQ_RX_DONE 0x40 //active on DIO0
#define IRQ_RADIO_ALL 0xFFFF
#define IRQ_TX_TIMEOUT 0x0100 //so that readIrqstatus can return additional detections
#define IRQ_RX_TIMEOUT 0x0200 //so that readIrqstatus can return additional detections
#define IRQ_NO_PACKET_CRC 0x0400 //so that readIrqstatus can return additional detections
#define CONFIGURATION_RETENTION 0x04 //these have no effect in SX127x, kept for compatibility
#define RTC_TIMEOUT_ENABLE 0x01
//SX127x Register names
const uint8_t REG_FIFO = 0x00;
const uint8_t WREG_FIFO = 0x80; //this is the write address for the FIFO
const uint8_t REG_OPMODE = 0x01;
const uint8_t REG_FDEVLSB = 0x05;
const uint8_t REG_FRMSB = 0x06;
const uint8_t REG_FRMID = 0x07;
const uint8_t REG_FRLSB = 0x08;
const uint8_t REG_PACONFIG = 0x09;
const uint8_t REG_PARAMP = 0x0A;
const uint8_t REG_OCP = 0x0B;
const uint8_t REG_LNA = 0x0C;
const uint8_t REG_FIFOADDRPTR = 0x0D;
const uint8_t REG_FIFOTXBASEADDR = 0x0E;
const uint8_t REG_FIFORXBASEADDR = 0x0F;
const uint8_t REG_FIFORXCURRENTADDR = 0x10;
const uint8_t REG_IRQFLAGSMASK = 0x11;
const uint8_t REG_IRQFLAGS = 0x12;
const uint8_t REG_RXNBBYTES = 0x13;
const uint8_t REG_RXHEADERCNTVALUEMSB = 0x14;
const uint8_t REG_RXHEADERCNTVALUELSB = 0x15;
const uint8_t REG_RXPACKETCNTVALUEMSB = 0x16;
const uint8_t REG_RXPACKETCNTVALUELSB = 0x17;
const uint8_t REG_PKTSNRVALUE = 0x19;
const uint8_t REG_PKTRSSIVALUE = 0x1A;
const uint8_t REG_RSSIVALUE = 0x1B;
const uint8_t REG_CURRENTRSSIVALUE = 0x1B;
const uint8_t REG_HOPCHANNEL = 0x1C;
const uint8_t REG_MODEMCONFIG1 = 0x1D;
const uint8_t REG_MODEMCONFIG2 = 0x1E;
const uint8_t REG_SYMBTIMEOUTLSB = 0x1F;
const uint8_t REG_PREAMBLEMSB = 0x20;
const uint8_t REG_PREAMBLELSB = 0x21;
const uint8_t REG_PAYLOADLENGTH = 0x22;
const uint8_t REG_FIFORXBYTEADDR = 0x25;
const uint8_t REG_MODEMCONFIG3 = 0x26;
const uint8_t REG_PPMCORRECTION = 0x27;
const uint8_t REG_FEIMSB = 0x28;
const uint8_t REG_FEIMID = 0x29;
const uint8_t REG_FEILSB = 0x2A;
const uint8_t REG_LRRSSIWIDEBAND = 0x2C;
const uint8_t REG_LRTEST2F = 0x2F;
const uint8_t REG_LRTEST30 = 0x30;
const uint8_t REG_DETECTOPTIMIZE = 0x31;
const uint8_t REG_INVERTIQ = 0x33;
const uint8_t REG_LRTEST36 = 0x36;
const uint8_t REG_HIGHBWOPTIMIZE1 = 0x36;
const uint8_t REG_LRDETECTIONTHRESHOLD = 0x37;
const uint8_t REG_DETECTIONTHRESHOLD = 0x37;
const uint8_t REG_SYNCWORD = 0x39;
const uint8_t REG_LRTEST3A = 0x3A;
const uint8_t REG_HIGHBWOPTIMIZE2 = 0x3A;
const uint8_t REG_IMAGECAL = 0x3B;
const uint8_t REG_INVERTIQ2 = 0x3B;
const uint8_t REG_TEMP = 0x3C;
const uint8_t REG_DIOMAPPING1 = 0x40;
const uint8_t REG_DIOMAPPING2 = 0x41;
const uint8_t REG_VERSION = 0x42;
const uint8_t REG_PLLHOP = 0x44;
const uint8_t REG_PADAC = 0x4D;
#define PRINT_LOW_REGISTER 0x00
#define PRINT_HIGH_REGISTER 0x4F
#define DEVICE_SX1272 0x10 //for modules that use the PA_BOOST pin for RF output
#define DEVICE_SX1276 0x11 //bit 4 set indicates PA_BOOST in use
#define DEVICE_SX1277 0x12
#define DEVICE_SX1278 0x13
#define DEVICE_SX1279 0x14
#define DEVICE_SX1272_PABOOST 0x10 //for modules that use the RF_BOOST pin for RF output
#define DEVICE_SX1276_PABOOST 0x11 //bit 4 set indicates PA_BOOST in use
#define DEVICE_SX1277_PABOOST 0x12
#define DEVICE_SX1278_PABOOST 0x13
#define DEVICE_SX1279_PABOOST 0x14
//no support for SX1272 modules using RFO output, dont have one to test
#define DEVICE_SX1276_RFO 0x01 //for modules that use the RFO LF_ANT or HF_ANT pin for RF output
#define DEVICE_SX1277_RFO 0x02 //bit 4 clear indicates RFO in use
#define DEVICE_SX1278_RFO 0x03
#define DEVICE_SX1279_RFO 0x04
//power settings
#define MAXPOWER11dBm 0x00 //REG_PACONFIG = x000xxxx
#define MAXPOWER14dBm 0x50 //REG_PACONFIG = x101xxxx
#define MAXPOWER17dBm 0x70 //REG_PACONFIG = x111xxxx
#define PABOOSTON 0x80
#define PABOOSTOFF 0x00
//SPI settings
#define LTspeedMaximum 8000000
#define LTdataOrder MSBFIRST
#define LTdataMode SPI_MODE0
#define Deviation5khz 0x52
//FSKRTTY Settings
#define ParityNone 0
#define ParityOdd 1
#define ParityEven 2
#define ParityZero 0xF0
#define ParityOne 0xF1
/*
MIT license
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
documentation files (the "Software"), to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software,
and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions
of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.
*/

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,197 @@
#ifndef SX128XLT_h
#define SX128XLT_h
#include "Arduino.h"
#include <SX128XLT_Definitions.h>
/**************************************************************************
ToDO
DONE - Why is SX1280LT.setPacketType(PACKET_TYPE_LORA) required before getFreqInt works with FLRC
- The register addresses where the frequency is stored are different for FLRC and LORA
DONE - Checkbusy at end of setmode ? - not needed, Checkbusy before all SPI activity
DONE - Ranging in complement2 - warning: comparison between signed and unsigned integer
DONE - Trap use of devices with RX\TX switching in ranging mode
DONE - Ensure ranging distance is not negative
Add routine to change period_base for RX,TX timeout
Is there a direct register access to packet length for transmit ?
Test RSSI and SNR are realistic for LoRa and FLRC
Review error rate in FLRC mode
Error packets at -99dBm due to noise ?
Add support for printPacketStatus for FLRC
**************************************************************************/
class SX128XLT {
public:
SX128XLT();
bool begin(int8_t pinNSS, int8_t pinNRESET, int8_t pinRFBUSY, int8_t pinDIO1, int8_t pinDIO2, int8_t pinDIO3, int8_t pinRXEN, int8_t pinTXEN, uint8_t device);
bool begin(int8_t pinNSS, int8_t pinNRESET, int8_t pinRFBUSY, int8_t pinDIO1, uint8_t device);
bool begin(int8_t pinNSS, int8_t pinNRESET, int8_t pinRFBUSY, int8_t pinDIO1, int8_t pinRXEN, int8_t pinTXEN, uint8_t device);
void rxEnable();
void txEnable();
void checkBusy();
bool config();
void readRegisters( uint16_t address, uint8_t *buffer, uint16_t size );
uint8_t readRegister( uint16_t address );
void writeRegisters( uint16_t address, uint8_t *buffer, uint16_t size );
void writeRegister( uint16_t address, uint8_t value );
void writeCommand(uint8_t Opcode, uint8_t *buffer, uint16_t size );
void readCommand( uint8_t Opcode, uint8_t *buffer, uint16_t size );
void resetDevice();
bool checkDevice();
void setupLoRa(uint32_t frequency, int32_t offset, uint8_t modParam1, uint8_t modParam2, uint8_t modParam3);
void setMode(uint8_t modeconfig);
void setRegulatorMode(uint8_t mode);
void setPacketType(uint8_t PacketType);
void setRfFrequency( uint32_t frequency, int32_t offset );
void setBufferBaseAddress(uint8_t txBaseAddress, uint8_t rxBaseAddress);
void setModulationParams(uint8_t modParam1, uint8_t modParam2, uint8_t modParam3);
void setPacketParams(uint8_t packetParam1, uint8_t packetParam2, uint8_t packetParam3, uint8_t packetParam4, uint8_t packetParam5, uint8_t packetParam6, uint8_t packetParam7);
void setDioIrqParams(uint16_t irqMask, uint16_t dio1Mask, uint16_t dio2Mask, uint16_t dio3Mask );
void setHighSensitivity();
void setLowPowerRX();
void printModemSettings();
void printDevice();
uint32_t getFreqInt();
uint8_t getLoRaSF();
uint32_t returnBandwidth(uint8_t data);
uint8_t getLoRaCodingRate();
uint8_t getInvertIQ();
uint16_t getPreamble();
void printOperatingSettings();
uint8_t getLNAgain();
void printRegisters(uint16_t Start, uint16_t End);
void printASCIIPacket(uint8_t *buff, uint8_t tsize);
uint8_t transmit(uint8_t *txbuffer, uint8_t size, uint16_t timeout, int8_t txpower, uint8_t wait);
void setTxParams(int8_t TXpower, uint8_t RampTime);
void setTx(uint16_t timeout);
void clearIrqStatus( uint16_t irq );
uint16_t readIrqStatus();
void printIrqStatus();
uint16_t CRCCCITT(uint8_t *buffer, uint8_t size, uint16_t start);
uint8_t receive(uint8_t *rxbuffer, uint8_t size, uint16_t timeout, uint8_t wait);
uint8_t readPacketRSSI();
uint8_t readPacketSNR();
uint8_t readRXPacketL();
void setRx(uint16_t timeout);
void setSyncWord1(uint32_t syncword);
void setSleep(uint8_t sleepconfig);
uint16_t CRCCCITTSX(uint8_t startadd, uint8_t endadd, uint16_t startvalue);
uint8_t getByteSXBuffer(uint8_t addr);
int32_t getFrequencyErrorRegValue();
int32_t getFrequencyErrorHz();
void printHEXByte(uint8_t temp);
void wake() ;
uint8_t transmitAddressed(uint8_t *txbuffer, uint8_t size, char txpackettype, char txdestination, char txsource, uint32_t timeout, int8_t txpower, uint8_t wait);
uint8_t receiveAddressed(uint8_t *rxbuffer, uint8_t size, uint16_t timeout, uint8_t wait);
uint8_t readRXPacketType();
uint8_t readPacket(uint8_t *rxbuffer, uint8_t size);
/**********************************************************
*****************
//Start direct access SX buffer routines
***************************************************************************/
void startWriteSXBuffer(uint8_t ptr);
uint8_t endWriteSXBuffer();
void startReadSXBuffer(uint8_t ptr);
uint8_t endReadSXBuffer();
void writeUint8(uint8_t x);
uint8_t readUint8();
void writeInt8(int8_t x);
int8_t readInt8();
void writeInt16(int16_t x);
int16_t readInt16();
void writeUint16(uint16_t x);
uint16_t readUint16();
void writeInt32(int32_t x);
int32_t readInt32();
void writeUint32(uint32_t x);
uint32_t readUint32();
void writeFloat(float x);
float readFloat();
uint8_t transmitSXBuffer(uint8_t startaddr, uint8_t length, uint16_t timeout, int8_t txpower, uint8_t wait);
void writeBuffer(uint8_t *txbuffer, uint8_t size);
uint8_t receiveSXBuffer(uint8_t startaddr, uint16_t timeout, uint8_t wait);
uint8_t readBuffer(uint8_t *rxbuffer);
void printSXBufferHEX(uint8_t start, uint8_t end);
uint16_t addCRC(uint8_t data, uint16_t libraryCRC);
void writeBufferChar(char *txbuffer, uint8_t size);
uint8_t readBufferChar(char *rxbuffer);
/***************************************************************************
//End direct access SX buffer routines
***************************************************************************/
/***************************************************************************
//Start ranging routines
***************************************************************************/
void setRangingSlaveAddress(uint32_t address);
void setRangingMasterAddress(uint32_t address);
void setRangingCalibration(uint16_t cal);
void setRangingRole(uint8_t role);
double getRangingDistance(uint8_t resultType, int32_t regval, float adjust);
uint32_t getRangingResultRegValue(uint8_t resultType);
int32_t complement2( uint32_t num, uint8_t bitCnt );
bool setupRanging(uint32_t frequency, int32_t offset, uint8_t modParam1, uint8_t modParam2, uint8_t modParam3, uint32_t address, uint8_t role);
bool transmitRanging(uint32_t address, uint16_t timeout, int8_t txpower, uint8_t wait);
uint8_t receiveRanging(uint32_t address, uint16_t timeout, int8_t txpower, uint8_t wait);
uint16_t lookupCalibrationValue(uint8_t spreadingfactor, uint8_t bandwidth);
uint16_t getSetCalibrationValue();
/***************************************************************************
//End ranging routines
***************************************************************************/
private:
int8_t _NSS, _NRESET, _RFBUSY, _DIO1, _DIO2, _DIO3;
int8_t _RXEN, _TXEN;
uint8_t _RXPacketL; //length of packet received
uint8_t _RXPacketType; //type number of received packet
uint8_t _RXDestination; //destination address of received packet
uint8_t _RXSource; //source address of received packet
int8_t _PacketRSSI; //RSSI of received packet
int8_t _PacketSNR; //signal to noise ratio of received packet
int8_t _TXPacketL; //transmitted packet length
uint8_t _RXcount; //used to keep track of the bytes read from SX1280 buffer during readFloat() etc
uint8_t _TXcount; //used to keep track of the bytes written to SX1280 buffer during writeFloat() etc
uint8_t _OperatingMode; //current operating mode
bool _rxtxpinmode = false; //set to true if RX and TX pin mode is used.
uint8_t _Device; //saved device type
uint8_t _TXDonePin; //the pin that will indicate TX done
uint8_t _RXDonePin; //the pin that will indicate RX done
uint8_t _PERIODBASE = PERIODBASE_01_MS;
uint8_t savedRegulatorMode;
uint8_t savedPacketType;
uint32_t savedFrequency;
int32_t savedOffset;
uint8_t savedModParam1, savedModParam2, savedModParam3; //sequence is spreading factor, bandwidth, coding rate
uint8_t savedPacketParam1, savedPacketParam2, savedPacketParam3, savedPacketParam4, savedPacketParam5, savedPacketParam6, savedPacketParam7;
uint16_t savedIrqMask, savedDio1Mask, savedDio2Mask, savedDio3Mask;
int8_t savedTXPower;
uint16_t savedCalibration;
uint32_t savedFrequencyReg;
};
#endif

View File

@@ -0,0 +1,388 @@
//SX1280LT Includes
//*************************************************************
// LoRa Modem Settings
//*************************************************************
//
//LoRa spreading factors
#define LORA_SF5 0x50
#define LORA_SF6 0x60
#define LORA_SF7 0x70
#define LORA_SF8 0x80
#define LORA_SF9 0x90
#define LORA_SF10 0xA0
#define LORA_SF11 0xB0
#define LORA_SF12 0xC0
//LoRa bandwidths
#define LORA_BW_0200 0x34 //actually 203125hz
#define LORA_BW_0400 0x26 //actually 406250hz
#define LORA_BW_0800 0x18 //actually 812500hz
#define LORA_BW_1600 0x0A //actually 1625000hz
//LoRa coding rates
#define LORA_CR_4_5 0x01
#define LORA_CR_4_6 0x02
#define LORA_CR_4_7 0x03
#define LORA_CR_4_8 0x04
//LoRa CAD settings
#define LORA_CAD_01_SYMBOL 0x00
#define LORA_CAD_02_SYMBOL 0x20
#define LORA_CAD_04_SYMBOL 0x40
#define LORA_CAD_08_SYMBOL 0x60
#define LORA_CAD_16_SYMBOL 0x80
//LoRa Header Types
#define LORA_PACKET_VARIABLE_LENGTH 0x00
#define LORA_PACKET_FIXED_LENGTH 0x80
#define LORA_PACKET_EXPLICIT LORA_PACKET_VARIABLE_LENGTH
#define LORA_PACKET_IMPLICIT LORA_PACKET_FIXED_LENGTH
//LoRa packet CRC settings
#define LORA_CRC_ON 0x20
#define LORA_CRC_OFF 0x00
//LoRa IQ Setings
#define LORA_IQ_NORMAL 0x40
#define LORA_IQ_INVERTED 0x00
#define FREQ_STEP 198.364
#define FREQ_ERROR_CORRECTION 1.55
//*************************************************************
// SX1280 Interrupt flags
//*************************************************************
#define IRQ_RADIO_NONE 0x0000
#define IRQ_TX_DONE 0x0001
#define IRQ_RX_DONE 0x0002
#define IRQ_SYNCWORD_VALID 0x0004
#define IRQ_SYNCWORD_ERROR 0x0008
#define IRQ_HEADER_VALID 0x0010
#define IRQ_HEADER_ERROR 0x0020
#define IRQ_CRC_ERROR 0x0040
#define IRQ_RANGING_SLAVE_RESPONSE_DONE 0x0080
#define IRQ_RANGING_SLAVE_REQUEST_DISCARDED 0x0100
#define IRQ_RANGING_MASTER_RESULT_VALID 0x0200
#define IRQ_RANGING_MASTER_RESULT_TIMEOUT 0x0400
#define IRQ_RANGING_SLAVE_REQUEST_VALID 0x0800
#define IRQ_CAD_DONE 0x1000
#define IRQ_CAD_ACTIVITY_DETECTED 0x2000
#define IRQ_RX_TX_TIMEOUT 0x4000
#define IRQ_TX_TIMEOUT 0x4000
#define IRQ_RX_TIMEOUT 0x4000
#define IRQ_PREAMBLE_DETECTED 0x8000
#define IRQ_RADIO_ALL 0xFFFF
//*************************************************************
// SX1280 Commands
//*************************************************************
#define RADIO_GET_PACKETTYPE 0x03
#define RADIO_GET_IRQSTATUS 0x15
#define RADIO_GET_RXBUFFERSTATUS 0x17
#define RADIO_WRITE_REGISTER 0x18
#define RADIO_READ_REGISTER 0x19
#define RADIO_WRITE_BUFFER 0x1A
#define RADIO_READ_BUFFER 0x1B
#define RADIO_GET_PACKETSTATUS 0x1D
#define RADIO_GET_RSSIINST 0x1F
#define RADIO_SET_STANDBY 0x80
#define RADIO_SET_RX 0x82
#define RADIO_SET_TX 0x83
#define RADIO_SET_SLEEP 0x84
#define RADIO_SET_RFFREQUENCY 0x86
#define RADIO_SET_CADPARAMS 0x88
#define RADIO_CALIBRATE 0x89
#define RADIO_SET_PACKETTYPE 0x8A
#define RADIO_SET_MODULATIONPARAMS 0x8B
#define RADIO_SET_PACKETPARAMS 0x8C
#define RADIO_SET_DIOIRQPARAMS 0x8D
#define RADIO_SET_TXPARAMS 0x8E
#define RADIO_SET_BUFFERBASEADDRESS 0x8F
#define RADIO_SET_RXDUTYCYCLE 0x94
#define RADIO_SET_REGULATORMODE 0x96
#define RADIO_CLR_IRQSTATUS 0x97
#define RADIO_SET_AUTOTX 0x98
#define RADIO_SET_LONGPREAMBLE 0x9B
#define RADIO_SET_UARTSPEED 0x9D
#define RADIO_SET_AUTOFS 0x9E
#define RADIO_SET_RANGING_ROLE 0xA3
#define RADIO_GET_STATUS 0xC0
#define RADIO_SET_FS 0xC1
#define RADIO_SET_CAD 0xC5
#define RADIO_SET_TXCONTINUOUSWAVE 0xD1
#define RADIO_SET_TXCONTINUOUSPREAMBLE 0xD2
#define RADIO_SET_SAVECONTEXT 0xD5
//*************************************************************
// SX1280 Registers
//*************************************************************
#define REG_LNA_REGIME 0x0891
#define REG_LR_PAYLOADLENGTH 0x901
#define REG_LR_PACKETPARAMS 0x903
#define REG_RFFrequency23_16 0x906
#define REG_RFFrequency15_8 0x907
#define REG_RFFrequency7_0 0x908
#define REG_FLRC_RFFrequency23_16 0x9A3 //found by experiment
#define REG_FLRC_RFFrequency15_8 0x9A4
#define REG_FLRC_RFFrequency7_0 0x9A5
#define REG_RANGING_FILTER_WINDOW_SIZE 0x091E
#define REG_LR_DEVICERANGINGADDR 0x0916
#define REG_LR_DEVICERANGINGADDR 0x0916
#define REG_LR_RANGINGRESULTCONFIG 0x0924
#define REG_LR_RANGINGRERXTXDELAYCAL 0x092C
#define REG_LR_RANGINGIDCHECKLENGTH 0x0931
#define REG_LR_ESTIMATED_FREQUENCY_ERROR_MSB 0x954
#define REG_LR_ESTIMATED_FREQUENCY_ERROR_MID 0x955
#define REG_LR_ESTIMATED_FREQUENCY_ERROR_LSB 0x956
#define REG_LR_RANGINGRESULTBASEADDR 0x0961
#define REG_LR_SYNCWORDTOLERANCE 0x09CD
#define REG_LR_SYNCWORDBASEADDRESS1 0x09CE
#define REG_FLRCSYNCWORD1_BASEADDR 0x09CF
#define REG_LR_SYNCWORDBASEADDRESS2 0x09D3
#define REG_FLRCSYNCWORD2_BASEADDR 0x09D4
#define REG_LR_SYNCWORDBASEADDRESS3 0x09D8
#define REG_LR_ESTIMATED_FREQUENCY_ERROR_MASK 0x0FFFFF
//SX1280 Packet Types
#define PACKET_TYPE_GFSK 0x00
#define PACKET_TYPE_LORA 0x01
#define PACKET_TYPE_RANGING 0x02
#define PACKET_TYPE_FLRC 0x03
#define PACKET_TYPE_BLE 0x04
//SX1280 Standby modes
#define MODE_STDBY_RC 0x00
#define MODE_STDBY_XOSC 0x01
//TX and RX timeout based periods
#define PERIODBASE_15_US 0x00
#define PERIODBASE_62_US 0x01
#define PERIODBASE_01_MS 0x02
#define PERIODBASE_04_MS 0x03
//TX ramp periods
#define RADIO_RAMP_02_US 0x00
#define RADIO_RAMP_04_US 0x20
#define RADIO_RAMP_06_US 0x40
#define RADIO_RAMP_08_US 0x60
#define RADIO_RAMP_10_US 0x80
#define RADIO_RAMP_12_US 0xA0
#define RADIO_RAMP_16_US 0xC0
#define RADIO_RAMP_20_US 0xE0
//SX1280 Power settings
#define USE_LDO 0x00
#define USE_DCDC 0x01
//*************************************************************
//SX1280 Ranging settings
//*************************************************************
#define RANGING_IDCHECK_LENGTH_08_BITS 0x00
#define RANGING_IDCHECK_LENGTH_16_BITS 0x01
#define RANGING_IDCHECK_LENGTH_24_BITS 0x02
#define RANGING_IDCHECK_LENGTH_32_BITS 0x03
#define RANGING_RESULT_RAW 0x00
#define RANGING_RESULT_AVERAGED 0x01
#define RANGING_RESULT_DEBIASED 0x02
#define RANGING_RESULT_FILTERED 0x03
#define MASK_RANGINGMUXSEL 0xCF
#define RANGING_SLAVE 0x00
#define RANGING_MASTER 0x01
//*************************************************************
//GFSK modem settings
//*************************************************************
#define GFS_BLE_BR_2_000_BW_2_4 0x04
#define GFS_BLE_BR_1_600_BW_2_4 0x28
#define GFS_BLE_BR_1_000_BW_2_4 0x4C
#define GFS_BLE_BR_1_000_BW_1_2 0x45
#define GFS_BLE_BR_0_800_BW_2_4 0x70
#define GFS_BLE_BR_0_800_BW_1_2 0x69
#define GFS_BLE_BR_0_500_BW_1_2 0x8D
#define GFS_BLE_BR_0_500_BW_0_6 0x86
#define GFS_BLE_BR_0_400_BW_1_2 0xB1
#define GFS_BLE_BR_0_400_BW_0_6 0xAA
#define GFS_BLE_BR_0_250_BW_0_6 0xCE
#define GFS_BLE_BR_0_250_BW_0_3 0xC7
#define GFS_BLE_BR_0_125_BW_0_3 0xEF
#define GFS_BLE_MOD_IND_0_35 0
#define GFS_BLE_MOD_IND_0_50 1
#define GFS_BLE_MOD_IND_0_75 2
#define GFS_BLE_MOD_IND_1_00 3
#define GFS_BLE_MOD_IND_1_25 4
#define GFS_BLE_MOD_IND_1_50 5
#define GFS_BLE_MOD_IND_1_75 6
#define GFS_BLE_MOD_IND_2_00 7
#define GFS_BLE_MOD_IND_2_25 8
#define GFS_BLE_MOD_IND_2_50 9
#define GFS_BLE_MOD_IND_2_75 10
#define GFS_BLE_MOD_IND_3_00 11
#define GFS_BLE_MOD_IND_3_25 12
#define GFS_BLE_MOD_IND_3_50 13
#define GFS_BLE_MOD_IND_3_75 14
#define GFS_BLE_MOD_IND_4_00 15
#define PREAMBLE_LENGTH_04_BITS 0x00 //4 bits
#define PREAMBLE_LENGTH_08_BITS 0x10 //8 bits
#define PREAMBLE_LENGTH_12_BITS 0x20 //12 bits
#define PREAMBLE_LENGTH_16_BITS 0x30 //16 bits
#define PREAMBLE_LENGTH_20_BITS 0x40 //20 bits
#define PREAMBLE_LENGTH_24_BITS 0x50 //24 bits
#define PREAMBLE_LENGTH_28_BITS 0x60 //28 bits
#define PREAMBLE_LENGTH_32_BITS 0x70 //32 bits
#define GFS_SYNCWORD_LENGTH_1_BYTE 0x00 //Sync word length 1 byte
#define GFS_SYNCWORD_LENGTH_2_BYTE 0x02 //Sync word length 2 bytes
#define GFS_SYNCWORD_LENGTH_3_BYTE 0x04 //Sync word length 3 bytes
#define GFS_SYNCWORD_LENGTH_4_BYTE 0x06 //Sync word length 4 bytes
#define GFS_SYNCWORD_LENGTH_5_BYTE 0x08 //Sync word length 5 bytes
#define RADIO_RX_MATCH_SYNCWORD_OFF 0x00 //no search for SyncWord
#define RADIO_RX_MATCH_SYNCWORD_1 0x10
#define RADIO_RX_MATCH_SYNCWORD_2 0x20
#define RADIO_RX_MATCH_SYNCWORD_1_2 0x30
#define RADIO_RX_MATCH_SYNCWORD_3 0x40
#define RADIO_RX_MATCH_SYNCWORD_1_3 0x50
#define RADIO_RX_MATCH_SYNCWORD_2_3 0x60
#define RADIO_RX_MATCH_SYNCWORD_1_2_3 0x70
#define RADIO_PACKET_FIXED_LENGTH 0x00 //The packet is fixed length, klnown on both RX and TX, no header
#define RADIO_PACKET_VARIABLE_LENGTH 0x20 //The packet is variable size, header included
#define RADIO_CRC_OFF 0x00
#define RADIO_CRC_1_BYTES 0x10
#define RADIO_CRC_2_BYTES 0x20
#define RADIO_CRC_3_BYTES 0x30
#define RADIO_WHITENING_ON 0x00
#define RADIO_WHITENING_OFF 0x08
//End GFSK ****************************************************
//*************************************************************
//FLRC modem settings
//*************************************************************
#define FLRC_SYNC_NOSYNC 0x00
#define FLRC_SYNC_WORD_LEN_P32S 0x04
#define FLRC_BR_1_300_BW_1_2 0x45 //1.3Mbs
#define FLRC_BR_1_000_BW_1_2 0x69 //1.04Mbs
#define FLRC_BR_0_650_BW_0_6 0x86 //0.65Mbs
#define FLRC_BR_0_520_BW_0_6 0xAA //0.52Mbs
#define FLRC_BR_0_325_BW_0_3 0xC7 //0.325Mbs
#define FLRC_BR_0_260_BW_0_3 0xEB //0.26Mbs
#define FLRC_CR_1_2 0x00 //coding rate 1:2
#define FLRC_CR_3_4 0x02 //coding rate 3:4
#define FLRC_CR_1_0 0x04 //coding rate 1
#define BT_DIS 0x00 //No filtering
#define BT_1 0x10 //1
#define BT_0_5 0x20 //0.5
#define RADIO_MOD_SHAPING_BT_OFF 0x00
#define RADIO_MOD_SHAPING_BT_1_0 0x10
#define RADIO_MOD_SHAPING_BT_0_5 0x20
//Table 13-45: PacketStatus2 in FLRC Packet
#define PacketCtrlBusy 0x01
#define PacketReceived 0x02
#define HeaderReceived 0x04
#define AbortError 0x08
#define CrcError 0x10
#define LengthError 0x20
#define SyncError 0x40
#define Reserved 0x80
//Table 13-46: PacketStatus3 in FLRC Packet
#define PktSent 0x01
#define rxpiderr 0x08
#define rx_no_ack 0x10
//FLRC default packetparamns
#define FLRC_Default_AGCPreambleLength PREAMBLE_LENGTH_32_BITS //packetParam1
#define FLRC_Default_SyncWordLength FLRC_SYNC_WORD_LEN_P32S //packetParam2
#define FLRC_Default_SyncWordMatch RADIO_RX_MATCH_SYNCWORD_1 //packetParam3
#define FLRC_Default_PacketType RADIO_PACKET_VARIABLE_LENGTH //packetParam4
#define FLRC_Default_PayloadLength BUFFER_SIZE_DEFAULT //packetParam5
#define FLRC_Default_CrcLength RADIO_CRC_3_BYTES //packetParam6
#define FLRC_Default_Whitening RADIO_WHITENING_OFF //packetParam7
//Table 11-15 Sleep modes
#define RETAIN_INSTRUCTION_RAM 0x04
#define RETAIN_DATABUFFER 0x02
#define RETAIN_DATA_RAM 0x01
#define CONFIGURATION_RETENTION 0x01 //included for libray compatibility
#define RETAIN_None 0x00
#ifndef RAMP_TIME
#define RAMP_TIME RADIO_RAMP_02_US
#endif
#ifndef PERIODBASE
#define PERIODBASE PERIOBASE_01_MS
#endif
#ifndef PERIODBASE_COUNT_15_8
#define PERIODBASE_COUNT_15_8 0
#endif
#ifndef PERIODBASE_COUNT_7_0
#define PERIODBASE_COUNT_7_0 0
#endif
#define DEVICE_SX1280 0x20
#define DEVICE_SX1281 0x21
//SPI settings
#define LTspeedMaximum 8000000
#define LTdataOrder MSBFIRST
#define LTdataMode SPI_MODE0
#define RANGING_VALID 0x03
#define RANGING_TIMEOUT 0x02
#define WAIT_RX 0x01
#define WAIT_TX 0x01
#define NO_WAIT 0x00
#define CalibrationSF10BW400 10180 //calibration value for ranging, SF10, BW400
#define CalibrationSF5BW1600 13100 //calibration value for ranging, SF5, BW1600
const uint16_t RNG_CALIB_0400[] = { 10260, 10244, 10228, 10212, 10196, 10180 }; //SF5 to SF10
const uint16_t RNG_CALIB_0800[] = { 11380, 11370, 11360, 11350, 11340, 11330 };
const uint16_t RNG_CALIB_1600[] = { 13100, 13160, 13220, 13280, 13340, 13400 };

View File

@@ -0,0 +1,569 @@
/*
Copyright 2020 - Stuart Robinson
Licensed under a MIT license displayed at the bottom of this document.
Original published 27/06/20
*/
/*******************************************************************************************************
Program Operation - This is a library file for the UBLOX 6,7 and 8 series GPSs.
This GPS library file is designed for use with the GPSs I2C interface.
*******************************************************************************************************/
//For use with I2C the configurations sent must be even numbers of bytes, thus the last byte in some cases may be a 0x00 padding byte
const PROGMEM uint8_t ClearConfig[] = {0xB5, 0x62, 0x06, 0x09, 0x0D, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x01, 0x19, 0x98, 0x00}; //22
const PROGMEM uint8_t GLONASSOff[] = {0xB5, 0x62, 0x06, 0x3E, 0x0C, 0x00, 0x00, 0x00, 0x20, 0x01, 0x06, 0x08, 0x0E, 0x00, 0x00, 0x00, 0x01, 0x01, 0x8F, 0xB2}; //20
const PROGMEM uint8_t GPGLLOff[] = {0xB5, 0x62, 0x06, 0x01, 0x08, 0x00, 0xF0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2A}; //16
const PROGMEM uint8_t GPGLSOff[] = {0xB5, 0x62, 0x06, 0x01, 0x08, 0x00, 0xF0, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x46}; //16
const PROGMEM uint8_t GPGSAOff[] = {0xB5, 0x62, 0x06, 0x01, 0x08, 0x00, 0xF0, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x31}; //16
const PROGMEM uint8_t GPGSVOff[] = {0xB5, 0x62, 0x06, 0x01, 0x08, 0x00, 0xF0, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x38}; //16
const PROGMEM uint8_t GNSSmode[] = {0xB5, 0x62, 0x06, 0x3E, 0x2C, 0x00, 0x00, 0x00, 0x20, 0x05, 0x00, 0x08, 0x10, 0x00, 0x01, 0x00, 0x01, 0x01, 0x01, 0x01,
0x03, 0x00, 0x00, 0x00, 0x01, 0x01, 0x03, 0x08, 0x10, 0x00, 0x00, 0x00, 0x01, 0x01, 0x05, 0x00, 0x03, 0x00, 0x00, 0x00, 0x01, 0x01, 0x06, 0x08, 0x0E, 0x00,
0x00, 0x00, 0x01, 0x01, 0xFC, 0x11};
const PROGMEM uint8_t SetBalloonMode[] = {0xB5, 0x62, 0x06, 0x24, 0x24, 0x00, 0xFF, 0xFF, 0x06, 0x03, 0x00, 0x00, 0x00, 0x00, 0x10, 0x27,
0x00, 0x00, 0x05, 0x00, 0xFA, 0x00, 0xFA, 0x00, 0x64, 0x00, 0x2C, 0x01, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x16, 0xDC}; //44
const PROGMEM uint8_t SaveConfig[] = {0xB5, 0x62, 0x06, 0x09, 0x0D, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x1B, 0xA9, 0x00}; //22
const PROGMEM uint8_t PollNavigation[] = {0xB5, 0x62, 0x06, 0x24, 0x00, 0x00, 0x2A, 0x84}; //8
const PROGMEM uint8_t SetCyclicMode[] = {0xB5, 0x62, 0x06, 0x11, 0x02, 0x00, 0x08, 0x01, 0x22, 0x92}; //10
const PROGMEM uint8_t SoftwareBackup[] = {0xB5, 0x62, 0x06, 0x57, 0x08, 0x00, 0x01, 0x00, 0x00, 0x00, 0x50, 0x4B, 0x43, 0x42, 0x86, 0x46}; //16
const PROGMEM uint8_t EnableI2C[] = {0xB5, 0x62, 0x06, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x24, 0x92}; //28
//const PROGMEM uint8_t PMREQBackup[] = {0xB5, 0x62, 0x02, 0x41, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x4D, 0x3B}; //16
uint8_t GPS_GetByte();
void GPS_OutputOn();
void GPS_OutputOff();
void GPS_PowerOn(int8_t pin, uint8_t state);
void GPS_PowerOff(int8_t pin, uint8_t state);
bool GPS_Setup();
bool GPS_SendConfig(unsigned int Progmem_ptr, byte length, byte replylength);
bool GPS_WaitAck(unsigned long waitms, byte length);
//uint8_t GPS_GetNextChar(uint32_t waitmS);
//bool GPS_CheckAck();
bool GPS_SetBalloonMode();
bool GPS_CheckBalloonMode();
bool GPS_ClearConfig();
bool GPS_SetCyclicMode();
bool GPS_SoftwareBackup();
//bool GPS_HotStart();
bool GPS_PollNavigation();
bool GPS_SaveConfig();
bool GPS_GLONASSOff();
bool GPS_GPGLLOff();
bool GPS_GPGLSOff();
bool GPS_GPGSAOff();
bool GPS_GPGSVOff();
bool GPS_GNSSmode();
bool GPS_GGARMCOnly();
//void GPS_PMREQBackup();
//void GPS_StartRead();
//void GPS_SetGPMode();
//void GPS_StopMessages();
const int16_t GPSI2CAddress = 0x42;
const uint32_t GPS_WaitAck_mS = 1000; //number of mS to wait for an ACK response from GPS
const uint8_t GPS_attempts = 5; //number of times the sending of GPS config will be attempted.
const uint8_t GPS_Reply_Size = 16; //size of GPS reply buffer
const uint16_t GPS_Clear_DelaymS = 2000; //mS to wait after a GPS Clear command is sent
uint8_t GPS_Reply[GPS_Reply_Size]; //byte array for storing GPS reply to UBX commands
#define USING_I2CGPS //so the rest of the program knows I2C GPS is in use
#define UBLOX //so the rest of the program knows UBLOX GPS is in use
//#define GPSDEBUG //include define to see some debug messages
uint8_t GPS_GetByte() //get and process output from GPS
{
uint8_t GPSchar;
Wire.requestFrom(GPSI2CAddress, 1);
GPSchar = Wire.read();
return GPSchar;
}
void GPS_OutputOn()
{
//not used function for I2C library, included for compatibility with other libraries
}
void GPS_OutputOff()
{
//not used function for I2C library, included for compatibility with other libraries
}
/*
void GPS_StartRead()
{
Wire.beginTransmission(GPSI2CAddress);
Wire.write(0xFF);
}
*/
void GPS_PowerOn(int8_t pin, uint8_t state)
{
#ifdef GPSDebug
Serial.print(F("GPS_PowerOn() "));
#endif
if (pin >= 0)
{
digitalWrite(pin, state);
}
}
void GPS_PowerOff(int8_t pin, uint8_t state)
{
#ifdef GPSDebug
Serial.print(F("GPS_PowerOff() "));
#endif
if (pin >= 0)
{
digitalWrite(pin, state);
}
}
bool GPS_WaitAck(uint32_t waitmS, uint8_t length)
{
//wait for Ack from GPS
byte i, j;
uint32_t startmS;
startmS = millis();
byte ptr = 0; //used as pointer to store GPS reply
Wire.beginTransmission(GPSI2CAddress);
Wire.write(0xFF);
do
{
Wire.requestFrom(GPSI2CAddress, 1);
i = Wire.read();
}
while ((i != 0xb5) && ((uint32_t) (millis() - startmS) < waitmS));
if (i != 0xb5)
{
Serial.print(F("Timeout "));
return false;
}
else
{
Serial.print(F("Ack "));
Serial.print(i, HEX);
length--;
for (j = 1; j <= length; j++)
{
Serial.print(F(" "));
Wire.requestFrom(GPSI2CAddress, 1);
i = Wire.read();
if (j < 12)
{
GPS_Reply[ptr++] = i; //save reply in buffer, but no more than 10 characters
}
if (i < 0x10)
{
Serial.print(F("0"));
}
Serial.print(i, HEX);
}
}
Serial.println();
return true;
}
bool GPS_SendConfig(const uint8_t *Progmem_ptr, uint8_t arraysize, uint8_t replylength, uint8_t attempts)
{
uint8_t byteread1, byteread2, index, length;
uint8_t config_attempts = attempts;
do
{
if (config_attempts == 0)
{
Serial.println(F("Fail"));
Serial.println();
return false;
}
length = arraysize / 2; //we are sending messages 2 bytes at a time
for (index = 0; index < length; index++)
{
byteread1 = pgm_read_byte_near(Progmem_ptr++); //we will read and write 2 bytes at a time
byteread2 = pgm_read_byte_near(Progmem_ptr++);
Wire.beginTransmission(GPSI2CAddress);
Wire.write(byteread1);
Wire.write(byteread2);
Wire.endTransmission();
if (byteread1 < 0x10)
{
Serial.print(F("0"));
}
Serial.print(byteread1, HEX);
Serial.print(F(" "));
if (byteread2 < 0x10)
{
Serial.print(F("0"));
}
Serial.print(byteread2, HEX);
Serial.print(F(" "));
}
Progmem_ptr = Progmem_ptr - arraysize; //put Progmem_ptr back to start value in case we need to re-send the config
Serial.println();
if (replylength == 0)
{
#ifdef GPSDebug
Serial.println(F("Reply not required"));
#endif
break;
}
config_attempts--;
} while (!GPS_WaitAck(GPS_WaitAck_mS, replylength));
delay(50); //GPS can sometimes be a bit slow getting ready for next config
return true;
}
bool GPS_Setup()
{
#ifdef GPSDebug
Serial.println(F("GPS_Setup()"));
#endif
/*
Wire.begin();
GPS_ClearConfig();
GPS_StopMessages();
GPS_SetBalloonMode();
GPS_SaveConfig();
*/
Wire.begin();
if (!GPS_ClearConfig())
{
return false;
}
if (!GPS_SetBalloonMode())
{
return false;
}
if (!GPS_GNSSmode())
{
return false;
}
if (!GPS_GPGLLOff())
{
return false;
}
if (!GPS_GPGLSOff())
{
return false;
}
if (!GPS_GPGSAOff())
{
return false;
}
if (!GPS_GPGSVOff())
{
return false;
}
if (!GPS_SaveConfig())
{
return false;
}
return true;
}
bool GPS_CheckBalloonMode()
{
#ifdef GPSDebug
Serial.println(F("GPS_CheckBalloonMode()"));
#endif
uint8_t j;
GPS_Reply[7] = 0xff;
GPS_PollNavigation();
j = GPS_Reply[7];
Serial.print(F("Dynamic Model is "));
Serial.println(j);
if (j != 6)
{
Serial.println(F("Dynamic Model 6 not Set !"));
return false;
}
else
{
return true;
}
}
bool GPS_ClearConfig()
{
#ifdef GPSDebug
Serial.println(F("GPS_ClearConfig()"));
#endif
Serial.println(F("ClearConfig"));
size_t SIZE = sizeof(ClearConfig);
if (!GPS_SendConfig(ClearConfig,SIZE,10,GPS_attempts))
{
return false;
}
Serial.println(F("Wait clear"));
delay(GPS_Clear_DelaymS); //wait a while for GPS to clear its settings
return true;
}
/*
void GPS_StopMessages()
{
#ifdef GPSDebug
Serial.print(F("GPS GPGLLOff "));
#endif
size_t SIZE;
SIZE = sizeof(GPGLLOff);
GPS_SendConfig(GPGLLOff, SIZE, 10, GPS_attempts);
#ifdef GPSDebug
Serial.print(F("GPS GPGLSOff "));
#endif
SIZE = sizeof(GPGLSOff);
GPS_SendConfig(GPGLSOff, SIZE, 10, GPS_attempts);
#ifdef GPSDebug
Serial.print(F("GPS GPGSAOff "));
#endif
SIZE = sizeof(GPGSAOff);
GPS_SendConfig(GPGSAOff, SIZE, 10, GPS_attempts);
#ifdef GPSDebug
Serial.print(F("GPS GPGSVOff "));
#endif
SIZE = sizeof(GPGSVOff);
GPS_SendConfig(GPGSVOff, SIZE, 10, GPS_attempts);
}
*/
bool GPS_SetBalloonMode()
{
#ifdef GPSDebug
Serial.print(F("GPS SetBalloonMode "));
#endif
size_t SIZE = sizeof(SetBalloonMode);
return GPS_SendConfig(SetBalloonMode, SIZE, 10, GPS_attempts);
}
bool GPS_SaveConfig()
{
#ifdef GPSDebug
Serial.print(F("GPS_SaveConfig()"));
#endif
size_t SIZE = sizeof(SaveConfig);
return GPS_SendConfig(SaveConfig, SIZE, 10, GPS_attempts);
}
bool GPS_PollNavigation()
{
#ifdef GPSDebug
Serial.print(F("GPS_PollNavigation()"));
#endif
size_t SIZE = sizeof(PollNavigation);
return GPS_SendConfig(PollNavigation, SIZE, 44, GPS_attempts);
}
/*
void GPS_SetGPMode()
{
#ifdef GPSDebug
Serial.print(F("GPS_SetGPMode()"));
#endif
size_t SIZE = sizeof(SetCyclicMode);
GPS_SendConfig(SetCyclicMode, SIZE, 10, GPS_attempts);
}
*/
bool GPS_SetCyclicMode()
{
#ifdef GPSDebug
Serial.print(F("GPS_SetCyclicMode() "));
#endif
Serial.println(F("SetCyclicMode"));
size_t SIZE = sizeof(SetCyclicMode);
return GPS_SendConfig(SetCyclicMode, SIZE, 10, GPS_attempts);
}
bool GPS_SoftwareBackup()
{
#ifdef GPSDebug
Serial.print(F("GPS_SoftwareBackup()"));
#endif
size_t SIZE = sizeof(SoftwareBackup);
return GPS_SendConfig(SoftwareBackup, SIZE, 0, GPS_attempts);
}
/*
void GPS_PMREQBackup()
{
#ifdef GPSDebug
Serial.print(F("GPS_PMREQBackup()"));
#endif
size_t SIZE = sizeof(PMREQBackup);
GPS_SendConfig(PMREQBackup, SIZE, 0, GPS_attempts);
}
*/
bool GPS_GLONASSOff()
{
#ifdef GPSDebug
Serial.print(F("GPS_GLONASSOff() "));
#endif
size_t SIZE = sizeof(GLONASSOff);
return GPS_SendConfig(GLONASSOff, SIZE, 10, GPS_attempts);
}
bool GPS_GPGLLOff()
{
#ifdef GPSDebug
Serial.print(F("GPS_GPGLLOff() "));
#endif
size_t SIZE = sizeof(GPGLLOff);
return GPS_SendConfig(GPGLLOff, SIZE, 10, GPS_attempts);
}
bool GPS_GPGLSOff()
{
#ifdef GPSDebug
Serial.print(F("GPS_GPGLSOff() "));
#endif
size_t SIZE = sizeof(GPGLSOff);
return GPS_SendConfig(GPGLSOff, SIZE, 10, GPS_attempts);
}
bool GPS_GPGSAOff()
{
#ifdef GPSDebug
Serial.print(F("GPS_GPGSAOff() "));
#endif
size_t SIZE = sizeof(GPGSAOff);
return GPS_SendConfig(GPGSAOff, SIZE, 10, GPS_attempts);
}
bool GPS_GPGSVOff()
{
#ifdef GPSDebug
Serial.print(F("GPS_GPGSVOff() "));
#endif
size_t SIZE = sizeof(GPGSVOff);
return GPS_SendConfig(GPGSVOff, SIZE, 10, GPS_attempts);
}
bool GPS_GNSSmode()
{
#ifdef GPSDebug
Serial.print(F("GPS_GNSSmode() "));
#endif
size_t SIZE = sizeof(GNSSmode);
return GPS_SendConfig(GNSSmode, SIZE, 10, GPS_attempts);
}
bool GPS_GGARMCOnly()
{
//null function, not used with Ublox library
return true;
}
/*
MIT license
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
documentation files (the "Software"), to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software,
and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions
of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.
*/

View File

@@ -0,0 +1,690 @@
/*
Copyright 2020 - Stuart Robinson
Licensed under a MIT license displayed at the bottom of this document.
Original published 27/06/20
*/
/*******************************************************************************************************
Program Operation - This is a library file for the UBLOX 6,7 and 8 series GPSs.
The routines assume that the GPS has been setup on GPSserial which could be either software serial or
hardware serial. This library file can be used with both Hardware serial and SoftwareSerial. The
configuration of the GPS prints debug output to the Serial console and mixing thisdebug output with
the use of software serial has required several optimistations, in particular tha the GPS serial
output is turned off at some points in the configuration process to allow prints to the serial monitor
to continue without interruption or missed characters, see the post below for details on the problem;
https://stuartsprojects.github.io/2020/05/05/softwareserial-problems.html
The library assumes that the GPS is connected onto a port named GPSserial, this is achived in software
serial with;
SoftwareSerial GPSserial(RXpin, TXpin);
And for hardware serial, assuming Serila2 is used for the GPS with;
#define GPSserial Serial2
The calling program should also include a define for the GPS baud rate as follows;
#define GPSBaud 9600
If this define is missing then 9600 baud is assumed
*******************************************************************************************************/
const PROGMEM uint8_t ClearConfig[] = {0xB5, 0x62, 0x06, 0x09, 0x0D, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x01, 0x19, 0x98}; //21
const PROGMEM uint8_t SetBalloonMode[] = {0xB5, 0x62, 0x06, 0x24, 0x24, 0x00, 0xFF, 0xFF, 0x06, 0x03, 0x00, 0x00, 0x00, 0x00, 0x10, 0x27, 0x00, 0x00, 0x05,
0x00, 0xFA, 0x00, 0xFA, 0x00, 0x64, 0x00, 0x2C, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x16, 0xDC
}; //44
const PROGMEM uint8_t SaveConfig[] = {0xB5, 0x62, 0x06, 0x09, 0x0D, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x1B, 0xA9}; //22
const PROGMEM uint8_t SetCyclicMode[] = {0xB5, 0x62, 0x06, 0x11, 0x02, 0x00, 0x08, 0x01, 0x22, 0x92}; //10
const PROGMEM uint8_t SoftwareBackup[] = {0xB5, 0x62, 0x02, 0x41, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x4D, 0x3B}; //16
const PROGMEM uint8_t PollNavigation[] = {0xB5, 0x62, 0x06, 0x24, 0x00, 0x00, 0x2A, 0x84}; //8
//B5 62 06 57 08 00 01 00 00 00 50 4B 43 42 86 46
//these are the commands to turn off NMEA sentences
const PROGMEM uint8_t GLONASSOff[] = {0xB5, 0x62, 0x06, 0x3E, 0x0C, 0x00, 0x00, 0x00, 0x20, 0x01, 0x06, 0x08, 0x0E, 0x00, 0x00, 0x00, 0x01, 0x01, 0x8F, 0xB2}; //20
const PROGMEM uint8_t GPGLLOff[] = {0xB5, 0x62, 0x06, 0x01, 0x08, 0x00, 0xF0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2A}; //16
const PROGMEM uint8_t GPGLSOff[] = {0xB5, 0x62, 0x06, 0x01, 0x08, 0x00, 0xF0, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x46}; //16
const PROGMEM uint8_t GPGSAOff[] = {0xB5, 0x62, 0x06, 0x01, 0x08, 0x00, 0xF0, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x31}; //16
const PROGMEM uint8_t GPGSVOff[] = {0xB5, 0x62, 0x06, 0x01, 0x08, 0x00, 0xF0, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x38}; //16
const PROGMEM uint8_t GNSSmode[] = {0xB5, 0x62, 0x06, 0x3E, 0x2C, 0x00, 0x00, 0x00, 0x20, 0x05, 0x00, 0x08, 0x10, 0x00, 0x01, 0x00, 0x01, 0x01, 0x01, 0x01,
0x03, 0x00, 0x00, 0x00, 0x01, 0x01, 0x03, 0x08, 0x10, 0x00, 0x00, 0x00, 0x01, 0x01, 0x05, 0x00, 0x03, 0x00, 0x00, 0x00, 0x01, 0x01, 0x06, 0x08, 0x0E, 0x00,
0x00, 0x00, 0x01, 0x01, 0xFC, 0x11};
//response to PollNavigation should be B5 62 06 24 24 00 FF FF 06 03
//accepted response to configuaration command should be UBX-ACK-ACK B5 62 05 01
//fail response to configuaration command should be UBX-ACK-NAK B5 62 05 00
uint8_t GPS_GetByte();
void GPS_OutputOn();
void GPS_OutputOff();
void GPS_PowerOn(int8_t pin, uint8_t state);
void GPS_PowerOff(int8_t pin, uint8_t state);
bool GPS_Setup();
bool GPS_SendConfig(const uint8_t *Progmem_ptr, uint8_t arraysize, uint8_t replylength, uint8_t attempts);
bool GPS_WaitAck(uint32_t waitms, uint8_t length);
bool GPS_WaitChar(uint8_t waitforchar, uint32_t waitmS);
//uint8_t GPS_GetNextChar(uint32_t waitmS);
bool GPS_CheckAck();
bool GPS_SetBalloonMode();
bool GPS_CheckBalloonMode();
bool GPS_ClearConfig();
bool GPS_SetCyclicMode();
bool GPS_SoftwareBackup();
bool GPS_HotStart();
bool GPS_PollNavigation();
bool GPS_SaveConfig();
bool GPS_GLONASSOff();
bool GPS_GPGLLOff();
bool GPS_GPGLSOff();
bool GPS_GPGSAOff();
bool GPS_GPGSVOff();
bool GPS_GNSSmode();
bool GPS_GGARMCOnly();
const uint32_t GPS_WaitAck_mS = 1000; //number of mS to wait for an ACK response from GPS
const uint8_t GPS_attempts = 10; //number of times the sending of GPS config will be attempted.
const uint8_t GPS_Reply_Size = 16; //size of GPS reply buffer
const uint16_t GPS_Clear_DelaymS = 2000; //mS to wait after a GPS Clear command is sent
uint8_t GPS_Reply[GPS_Reply_Size]; //byte array for storing GPS reply to UBX commands
#define UBLOXINUSE //so complier can know which GPS library is used
//#define GPSDebug
#ifndef GPSBaud
#define GPSBaud 9600
#endif
void GPS_OutputOn()
{
#ifdef GPSDebug
Serial.print(F("GPS_On() "));
#endif
uint8_t GPSchar = 0;
//turns on serial output from GPS
GPSserial.begin(GPSBaud);
GPSserial.write(GPSchar);
}
void GPS_OutputOff()
{
#ifdef GPSDebug
Serial.print(F("GPS_Off() "));
#endif
GPSserial.end(); //turns off serial output from GPS
}
void GPS_PowerOn(int8_t pin, uint8_t state)
{
#ifdef GPSDebug
Serial.print(F("GPS_PowerOn() "));
#endif
if (pin >= 0)
{
digitalWrite(pin, state);
}
}
void GPS_PowerOff(int8_t pin, uint8_t state)
{
#ifdef GPSDebug
Serial.print(F("GPS_PowerOff() "));
#endif
if (pin >= 0)
{
digitalWrite(pin, state);
}
}
bool GPS_Setup()
{
#ifdef GPSDebug
Serial.print(F("GPS_Setup() "));
#endif
if (!GPS_ClearConfig())
{
return false;
}
if (!GPS_SetBalloonMode())
{
return false;
}
if (!GPS_GNSSmode())
{
return false;
}
if (!GPS_GPGLLOff())
{
return false;
}
if (!GPS_GPGLSOff())
{
return false;
}
if (!GPS_GPGSAOff())
{
return false;
}
if (!GPS_GPGSVOff())
{
return false;
}
if (!GPS_SaveConfig())
{
return false;
}
return true;
}
bool GPS_CheckBalloonMode()
{
//navigation model setting for UBLOX is at GPS_Reply[8] of poll request reply.
#ifdef GPSDebug
Serial.print(F("GPS_CheckBalloonMode() "));
#endif
uint8_t j;
GPS_Reply[8] = 0xff;
GPS_PollNavigation();
if ( (GPS_Reply[0] == 0xB5) && (GPS_Reply[1] == 0x62) && (GPS_Reply[2] == 0x06) && (GPS_Reply[3] == 0X24) )
{
j = GPS_Reply[8];
if (j == 6)
{
return true;
}
else
{
return false;
}
}
return false;
}
bool GPS_SendConfig(const uint8_t *Progmem_ptr, uint8_t arraysize, uint8_t replylength, uint8_t attempts)
{
#ifdef GPSDebug
Serial.print(F("GPS_SendConfig() "));
#endif
uint8_t byteread, index;
uint8_t config_attempts = attempts;
Serial.flush(); //ensure there are no pending interrupts from serial monitor printing
do
{
if (config_attempts == 0)
{
Serial.println(F("Fail"));
Serial.println();
return false;
}
GPS_OutputOff();
Serial.print(F("GPSSend "));
for (index = 0; index < arraysize; index++)
{
byteread = pgm_read_byte_near(Progmem_ptr++);
if (byteread < 0x10)
{
Serial.print(F("0"));
}
Serial.print(byteread, HEX);
Serial.print(F(" "));
}
Serial.flush(); //make sure serial out buffer is empty
GPS_OutputOn();
Progmem_ptr = Progmem_ptr - arraysize; //set Progmem_ptr back to start
for (index = 0; index < arraysize; index++)
{
byteread = pgm_read_byte_near(Progmem_ptr++);
GPSserial.write(byteread);
}
Progmem_ptr = Progmem_ptr - arraysize; //set Progmem_ptr back to start
if (replylength == 0)
{
#ifdef GPSDebug
Serial.println(F("Reply not required"));
#endif
break;
}
GPSserial.flush(); //make sure all of config command has been sent
config_attempts--;
}
while (!GPS_WaitAck(GPS_WaitAck_mS, replylength));
Serial.println(F("OK"));
Serial.println();
delay(100); //GPS can sometimes be a bit slow getting ready for next config
return true;
}
bool GPS_WaitAck(uint32_t waitmS, uint8_t length)
{
#ifdef GPSDebug
Serial.print(F("GPS_WaitAck() "));
Serial.print(F(" Reply length "));
Serial.print(length);
Serial.print(F(" "));
#endif
//wait for Ack (UBX-ACK-ACK) response from GPS is 0xb5,0x62, 0x05, 0x01
//Nack (UBX-ACK-NAK) response from GPS is 0xb5,0x62, 0x05, 0x00
uint8_t GPSchar;
uint32_t startmS;
startmS = millis();
uint8_t ptr = 0; //used as pointer to store GPS reply
Serial.println();
Serial.print(F("Received "));
Serial.flush();
do
{
if (GPSserial.available())
{
GPSchar = GPSserial.read();
}
}
while ((GPSchar != 0xb5) && ((uint32_t) (millis() - startmS) < waitmS)); //use the timeout to ensure a lack of GPS does not cause the program to hang
if (GPSchar != 0xb5)
{
Serial.println(F("Timeout Error"));
return false;
}
GPS_Reply[ptr++] = 0xB5; //test if a 0xB5 has been received
startmS = millis();
do
{
if (GPSserial.available())
{
GPS_Reply[ptr++] = GPSserial.read();
}
}
while ((ptr < length) && ((uint32_t) (millis() - startmS) < waitmS)); //fill buffer, stop when either ptr is (length-1) or timeout
if (ptr < length)
{
Serial.print(F("Short Reply Error"));
return false;
}
GPS_OutputOff();
for (ptr = 0; ptr < length; ptr++)
{
GPSchar = GPS_Reply[ptr];
if (GPSchar < 0x10)
{
Serial.print(F("0"));
}
Serial.print(GPSchar , HEX);
Serial.print(F(" "));
}
Serial.println();
if (GPS_CheckAck())
{
return true;
}
return false;
}
bool GPS_WaitChar(uint8_t waitforchar, uint32_t waitmS)
{
uint8_t GPSchar;
uint32_t startmS;
startmS = millis();
do
{
if (GPSserial.available())
{
GPSchar = GPSserial.read();
if (GPSchar == waitforchar)
{
GPS_Reply[0] = GPSchar;
return true;
}
}
}
while ((uint32_t) (millis() - startmS) < waitmS); //use the timeout to ensure a lack of GPS does not cause the program to hang
return false;
}
/*
uint8_t GPS_GetNextChar(uint32_t waitmS)
{
uint8_t GPSchar;
do
{
if (GPSserial.available())
{
GPSchar = GPSserial.read();
GPS_Reply[1] = GPSchar;
return GPSchar;
}
}
while ((millis() < waitmS)); //use the timeout to ensure a lack of GPS does not cause the program to hang
return '*';
}
*/
bool GPS_PollNavigation()
{
#ifdef GPSDebug
Serial.print(F("GPS_PollNavigation() "));
#endif
//Serial.println(F("PollNavigation"));
size_t SIZE = sizeof(PollNavigation);
if (GPS_SendConfig(PollNavigation, SIZE, 10, GPS_attempts))
{
return true;
}
return false;
}
bool GPS_CheckAck()
{
#ifdef GPSDebug
Serial.print(F("GPS_CheckAck() "));
#endif
if ((GPS_Reply[0] == 0xB5) && (GPS_Reply[1] == 0x62))
{
#ifdef GPSDebug
Serial.println(F(" UBX-ACK-ACK"));
#endif
return true; //there has been a UBX-ACK-ACK response
}
else
{
#ifdef GPSDebug
Serial.println(F(" Not UBX-ACK-ACK "));
#endif
return false; //there has been a UBX-ACK-ACK response
}
}
/*********************************************************************
// GPS configuration commands
*********************************************************************/
bool GPS_ClearConfig()
{
#ifdef GPSDebug
Serial.print(F("GPS_ClearConfig() "));
#endif
//Serial.println(F("ClearConfig"));
size_t SIZE = sizeof(ClearConfig);
if (GPS_SendConfig(ClearConfig, SIZE, 10, GPS_attempts))
{
Serial.println(F("Wait clear"));
Serial.println();
delay(GPS_Clear_DelaymS); //wait a while for GPS to clear its settings
return true;
}
return false;
}
bool GPS_SetBalloonMode()
{
#ifdef GPSDebug
Serial.print(F("GPS_SetBalloonMode() "));
#endif
//Serial.println(F("SetBalloonMode"));
size_t SIZE = sizeof(SetBalloonMode);
if (GPS_SendConfig(SetBalloonMode, SIZE, 10, GPS_attempts))
{
return true;
}
return false;
}
bool GPS_SaveConfig()
{
#ifdef GPSDebug
Serial.print(F("GPS_SaveConfig() "));
#endif
//Serial.println(F("SaveConfig"));
size_t SIZE = sizeof(SaveConfig);
if (GPS_SendConfig(SaveConfig, SIZE, 10, GPS_attempts))
{
return true;
}
return false;
}
bool GPS_SetCyclicMode()
{
#ifdef GPSDebug
Serial.print(F("GPS_SetCyclicMode() "));
#endif
//Serial.println(F("SetCyclicMode"));
size_t SIZE = sizeof(SetCyclicMode);
if (GPS_SendConfig(SetCyclicMode, SIZE, 10, GPS_attempts))
{
return true;
}
return false;
}
bool GPS_SoftwareBackup()
{
#ifdef GPSDebug
Serial.print(F("GPS_SoftwareBackup() "));
#endif
//Serial.println(F("SoftwareBackup"));
size_t SIZE = sizeof(SoftwareBackup);
if (GPS_SendConfig(SoftwareBackup, SIZE, 0, GPS_attempts))
{
return true;
}
return false;
}
bool GPS_HotStart()
{
#ifdef GPSDebug
Serial.print(F("GPS_HotStart() "));
#endif
//Serial.println(F("HotStart"));
GPSserial.println();
return true;
}
bool GPS_GLONASSOff()
{
#ifdef GPSDebug
Serial.print(F("GPS_GLONASSOff() "));
#endif
size_t SIZE = sizeof(GLONASSOff);
return GPS_SendConfig(GLONASSOff, SIZE, 10, GPS_attempts);
}
bool GPS_GPGLLOff()
{
#ifdef GPSDebug
Serial.print(F("GPS_GPGLLOff() "));
#endif
size_t SIZE = sizeof(GPGLLOff);
return GPS_SendConfig(GPGLLOff, SIZE, 10, GPS_attempts);
}
bool GPS_GPGLSOff()
{
#ifdef GPSDebug
Serial.print(F("GPS_GPGLSOff() "));
#endif
size_t SIZE = sizeof(GPGLSOff);
return GPS_SendConfig(GPGLSOff, SIZE, 10, GPS_attempts);
}
bool GPS_GPGSAOff()
{
#ifdef GPSDebug
Serial.print(F("GPS_GPGSAOff() "));
#endif
size_t SIZE = sizeof(GPGSAOff);
return GPS_SendConfig(GPGSAOff, SIZE, 10, GPS_attempts);
}
bool GPS_GPGSVOff()
{
#ifdef GPSDebug
Serial.print(F("GPS_GPGSVOff() "));
#endif
size_t SIZE = sizeof(GPGSVOff);
return GPS_SendConfig(GPGSVOff, SIZE, 10, GPS_attempts);
}
bool GPS_GNSSmode()
{
#ifdef GPSDebug
Serial.print(F("GPS_GNSSmode() "));
#endif
size_t SIZE = sizeof(GNSSmode);
return GPS_SendConfig(GNSSmode, SIZE, 10, GPS_attempts);
}
uint8_t GPS_GetByte() //get a byte for GPS
{
if (GPSserial.available() == 0)
{
return 0xFF; //for compatibility with I2C reading of GPS
}
else
{
return GPSserial.read();
}
}
bool GPS_GGARMCOnly()
{
//null function, not used with Ublox library
return true;
}
/*
MIT license
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
documentation files (the "Software"), to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software,
and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions
of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.
*/

View File

@@ -0,0 +1,580 @@
/*
Copyright 2020 - Stuart Robinson
Licensed under a MIT license displayed at the bottom of this document.
Original published 07/08/20
*/
const PROGMEM uint8_t ClearConfig[] = {0xB5, 0x62, 0x06, 0x09, 0x0D, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x01, 0x19, 0x98}; //21
const PROGMEM uint8_t SetBalloonMode[] = {0xB5, 0x62, 0x06, 0x24, 0x24, 0x00, 0xFF, 0xFF, 0x06, 0x03, 0x00, 0x00, 0x00, 0x00, 0x10, 0x27, 0x00, 0x00, 0x05,
0x00, 0xFA, 0x00, 0xFA, 0x00, 0x64, 0x00, 0x2C, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x16, 0xDC
}; //44
const PROGMEM uint8_t SaveConfig[] = {0xB5, 0x62, 0x06, 0x09, 0x0D, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x1B, 0xA9}; //22
const PROGMEM uint8_t SetCyclicMode[] = {0xB5, 0x62, 0x06, 0x11, 0x02, 0x00, 0x08, 0x01, 0x22, 0x92}; //10
const PROGMEM uint8_t SoftwareBackup[] = {0xB5, 0x62, 0x02, 0x41, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x4D, 0x3B}; //16
const PROGMEM uint8_t PollNavigation[] = {0xB5, 0x62, 0x06, 0x24, 0x00, 0x00, 0x2A, 0x84}; //8
//these are the commands to turn off NMEA sentences
const PROGMEM uint8_t GLONASSOff[] = {0xB5, 0x62, 0x06, 0x3E, 0x0C, 0x00, 0x00, 0x00, 0x20, 0x01, 0x06, 0x08, 0x0E, 0x00, 0x00, 0x00, 0x01, 0x01, 0x8F, 0xB2}; //20
const PROGMEM uint8_t GPGLLOff[] = {0xB5, 0x62, 0x06, 0x01, 0x08, 0x00, 0xF0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2A}; //16
const PROGMEM uint8_t GPGLSOff[] = {0xB5, 0x62, 0x06, 0x01, 0x08, 0x00, 0xF0, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x46}; //16
const PROGMEM uint8_t GPGSAOff[] = {0xB5, 0x62, 0x06, 0x01, 0x08, 0x00, 0xF0, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x31}; //16
const PROGMEM uint8_t GPGSVOff[] = {0xB5, 0x62, 0x06, 0x01, 0x08, 0x00, 0xF0, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x38}; //16
const PROGMEM uint8_t GNSSmode[] = {0xB5, 0x62, 0x06, 0x3E, 0x2C, 0x00, 0x00, 0x00, 0x20, 0x05, 0x00, 0x08, 0x10, 0x00, 0x01, 0x00, 0x01, 0x01, 0x01, 0x01,
0x03, 0x00, 0x00, 0x00, 0x01, 0x01, 0x03, 0x08, 0x10, 0x00, 0x00, 0x00, 0x01, 0x01, 0x05, 0x00, 0x03, 0x00, 0x00, 0x00, 0x01, 0x01, 0x06, 0x08, 0x0E, 0x00,
0x00, 0x00, 0x01, 0x01, 0xFC, 0x11};
//response to PollNavigation should be B5 62 06 24 24 00 FF FF 06 03
//accepted response to configuaration command should be UBX-ACK-ACK B5 62 05 01
//fail response to configuaration command should be UBX-ACK-NAK B5 62 05 00
void GPS_OutputOn();
void GPS_OutputOff();
void GPS_PowerOn();
bool GPS_CheckConfiguration();
bool GPS_SendConfig(const uint8_t *Progmem_ptr, uint8_t arraysize, uint8_t replylength, uint8_t attempts);
bool GPS_WaitAck(uint32_t waitms, uint8_t length);
bool GPS_PollNavigation();
bool GPS_ClearConfig();
bool GPS_SaveConfig();
bool GPS_SetBalloonMode();
bool GPS_SetCyclicMode();
bool GPS_SoftwareBackup();
bool GPS_GLONASSOff();
bool GPS_GPGLLOff();
bool GPS_GPGLSOff();
bool GPS_GPGSAOff();
bool GPS_GPGSVOff();
bool GPS_GNSSmode();
bool GPS_CheckAck();
uint8_t GPS_GetByte();
const uint32_t GPS_WaitAck_mS = 1000; //number of mS to wait for an ACK response from GPS
const uint8_t GPS_attempts = 5; //number of times the sending of GPS config will be attempted.
const uint8_t GPS_Reply_Size = 16; //size of GPS reply buffer
const uint16_t GPS_Clear_DelaymS = 2000; //mS to wait after a GPS Clear command is sent
uint8_t GPS_Reply[GPS_Reply_Size]; //byte array for storing GPS reply to UBX commands
#define UBLOXINUSE //so complier can know which GPS library is used
//#define GPSDebug
#ifndef GPSConfigSerial // if GPSDebugSerial is not defined set to Serial as default
#define GPSConfigSerial Serial
#endif
#ifndef GPSDebugSerial // if GPSDebugSerial is not defined set to Serial as default
#define GPSDebugSerial Serial
#endif
#ifndef GPSBaud
#define GPSBaud 9600
#endif
void GPS_OutputOn()
{
#ifdef GPSDebug
Serial.print(F("GPS_On() "));
#endif
uint8_t GPSchar = 0;
//turns on serial output from GPS
GPSserial.begin(GPSBaud);
GPSserial.write(GPSchar);
}
void GPS_OutputOff()
{
#ifdef GPSDebug
Serial.print(F("GPS_Off() "));
#endif
GPSserial.end(); //turns off serial output from GPS
}
void GPS_PowerOn(int8_t pin, uint8_t state)
{
#ifdef GPSDebug
Serial.print(F("GPS_PowerOn() "));
#endif
if (pin >= 0)
{
digitalWrite(pin, state);
}
}
void GPS_PowerOff(int8_t pin, uint8_t state)
{
#ifdef GPSDebug
Serial.print(F("GPS_PowerOff() "));
#endif
if (pin >= 0)
{
digitalWrite(pin, state);
}
}
bool GPS_Setup()
{
#ifdef GPSDebug
Serial.print(F("GPS_Setup() "));
#endif
if (!GPS_ClearConfig())
{
return false;
}
if (!GPS_SetBalloonMode())
{
return false;
}
if (!GPS_CheckConfiguration())
{
return false;
}
if (!GPS_SaveConfig())
{
return false;
}
return true;
}
bool GPS_CheckConfiguration()
{
//navigation model setting for UBLOX is at GPS_Reply[8] of poll request reply.
#ifdef GPSDebug
Serial.print(F("GPS_CheckConfiguration() UBLOX "));
#endif
uint8_t j;
GPS_Reply[8] = 0xff;
GPS_PollNavigation();
if ( (GPS_Reply[0] == 0xB5) && (GPS_Reply[1] == 0x62) && (GPS_Reply[2] == 0x06) && (GPS_Reply[3] == 0X24) )
{
j = GPS_Reply[8];
if (j == 6)
{
return true;
}
else
{
return false;
}
}
return false;
}
bool GPS_SendConfig(const uint8_t *Progmem_ptr, uint8_t arraysize, uint8_t replylength, uint8_t attempts)
{
#ifdef GPSDebug
Serial.print(F("GPS_SendConfig() "));
#endif
uint8_t byteread, index;
uint8_t config_attempts = attempts;
Serial.flush(); //ensure there are no pending interrupts from serial monitor printing
do
{
if (config_attempts == 0)
{
Serial.println(F("Fail"));
Serial.println();
return false;
}
Serial.print(F("GPSSend "));
for (index = 0; index < arraysize; index++)
{
byteread = pgm_read_byte_near(Progmem_ptr++);
Serial.print(byteread, HEX);
Serial.print(F(" "));
}
Serial.flush(); //make sure serial out buffer is empty
Progmem_ptr = Progmem_ptr - arraysize; //set Progmem_ptr back to start
for (index = 0; index < arraysize; index++)
{
byteread = pgm_read_byte_near(Progmem_ptr++);
GPSserial.write(byteread);
}
Progmem_ptr = Progmem_ptr - arraysize; //set Progmem_ptr back to start
if (replylength == 0)
{
#ifdef GPSDebug
Serial.println(F("Reply not required"));
#endif
break;
}
config_attempts--;
}
while (!GPS_WaitAck(GPS_WaitAck_mS, replylength));
Serial.println(F("OK"));
Serial.println();
delay(100); //GPS can sometimes be a bit slow getting ready for next config
return true;
}
bool GPS_WaitAck(uint32_t waitms, uint8_t length)
{
#ifdef GPSDebug
Serial.print(F("GPS_WaitAck() "));
Serial.print(F(" Reply length "));
Serial.print(length);
Serial.print(F(" "));
#endif
//wait for Ack (UBX-ACK-ACK) response from GPS is 0xb5,0x62, 0x05, 0x01
//Nack (UBX-ACK-NAK) response from GPS is 0xb5,0x62, 0x05, 0x00
uint8_t GPSchar;
uint32_t endms;
endms = millis() + waitms;
uint8_t ptr = 0; //used as pointer to store GPS reply
Serial.println();
Serial.print(F("Received "));
Serial.flush();
do
{
if (GPSserial.available())
{
GPSchar = GPSserial.read();
}
}
while ((GPSchar != 0xb5) && (millis() < endms)); //use the timeout to ensure a lack of GPS does not cause the program to hang
if (GPSchar != 0xb5)
{
Serial.println(F("Timeout Error"));
return false;
}
GPS_Reply[ptr++] = 0xB5; //test if a 0xB5 has been received
do
{
if (GPSserial.available())
{
GPS_Reply[ptr++] = GPSserial.read();
}
}
while ((ptr < length) || (millis() >= endms)); //fill buffer, stop when either ptr is (length-1) or timeout
if (millis() >= endms) //check for another timeout
{
Serial.print(F("NoReply Error"));
return false;
}
for (ptr = 0; ptr < length; ptr++)
{
GPSchar = GPS_Reply[ptr];
if (GPSchar < 0x10)
{
Serial.print(F("0"));
}
Serial.print(GPSchar , HEX);
Serial.print(F(" "));
}
Serial.println();
if (GPS_CheckAck())
{
return true;
}
return false;
}
bool GPS_PollNavigation()
{
#ifdef GPSDebug
Serial.print(F("GPS_PollNavigation() "));
#endif
Serial.println(F("PollNavigation"));
size_t SIZE = sizeof(PollNavigation);
if (GPS_SendConfig(PollNavigation, SIZE, 10, GPS_attempts))
{
return true;
}
return false;
}
bool GPS_CheckAck()
{
#ifdef GPSDebug
Serial.print(F("GPS_CheckAck() "));
#endif
if ((GPS_Reply[0] == 0xB5) && (GPS_Reply[1] == 0x62))
{
#ifdef GPSDebug
Serial.println(F(" UBX-ACK-ACK"));
#endif
return true; //there has been a UBX-ACK-ACK response
}
else
{
#ifdef GPSDebug
Serial.println(F(" Not UBX-ACK-ACK "));
#endif
return false; //there has been a UBX-ACK-ACK response
}
}
/*********************************************************************
// GPS configuration commands
*********************************************************************/
bool GPS_ClearConfig()
{
#ifdef GPSDebug
Serial.print(F("GPS_ClearConfig() "));
#endif
Serial.println(F("ClearConfig"));
size_t SIZE = sizeof(ClearConfig);
if (GPS_SendConfig(ClearConfig, SIZE, 10, GPS_attempts))
{
Serial.println(F("Wait clear"));
Serial.println();
delay(GPS_Clear_DelaymS); //wait a while for GPS to clear its settings
return true;
}
return false;
}
bool GPS_SetBalloonMode()
{
#ifdef GPSDebug
Serial.print(F("GPS_SetBalloonMode() "));
#endif
Serial.println(F("SetBalloonMode"));
size_t SIZE = sizeof(SetBalloonMode);
if (GPS_SendConfig(SetBalloonMode, SIZE, 10, GPS_attempts))
{
return true;
}
return false;
}
bool GPS_SaveConfig()
{
#ifdef GPSDebug
Serial.print(F("GPS_SaveConfig() "));
#endif
Serial.println(F("SaveConfig"));
size_t SIZE = sizeof(SaveConfig);
if (GPS_SendConfig(SaveConfig, SIZE, 10, GPS_attempts))
{
return true;
}
return false;
}
bool GPS_SetCyclicMode()
{
#ifdef GPSDebug
Serial.print(F("GPS_SetCyclicMode() "));
#endif
Serial.println(F("SetCyclicMode"));
size_t SIZE = sizeof(SetCyclicMode);
if (GPS_SendConfig(SetCyclicMode, SIZE, 10, GPS_attempts))
{
return true;
}
return false;
}
bool GPS_SoftwareBackup()
{
#ifdef GPSDebug
Serial.print(F("GPS_SoftwareBackup() "));
#endif
Serial.println(F("SoftwareBackup"));
size_t SIZE = sizeof(SoftwareBackup);
if (GPS_SendConfig(SoftwareBackup, SIZE, 0, GPS_attempts))
{
return true;
}
return false;
}
bool GPS_HotStart()
{
#ifdef GPSDebug
Serial.print(F("GPS_HotStart() "));
#endif
Serial.println(F("HotStart"));
GPSserial.println();
return true;
}
bool GPS_GLONASSOff()
{
#ifdef GPSDebug
Serial.print(F("GPS_GLONASSOff() "));
#endif
size_t SIZE = sizeof(GLONASSOff);
return GPS_SendConfig(GLONASSOff, SIZE, 10, GPS_attempts);
}
bool GPS_GPGLLOff()
{
#ifdef GPSDebug
Serial.print(F("GPS_GPGLLOff() "));
#endif
size_t SIZE = sizeof(GPGLLOff);
return GPS_SendConfig(GPGLLOff, SIZE, 10, GPS_attempts);
}
bool GPS_GPGLSOff()
{
#ifdef GPSDebug
Serial.print(F("GPS_GPGLSOff() "));
#endif
size_t SIZE = sizeof(GPGLSOff);
return GPS_SendConfig(GPGLSOff, SIZE, 10, GPS_attempts);
}
bool GPS_GPGSAOff()
{
#ifdef GPSDebug
Serial.print(F("GPS_GPGSAOff() "));
#endif
size_t SIZE = sizeof(GPGSAOff);
return GPS_SendConfig(GPGSAOff, SIZE, 10, GPS_attempts);
}
bool GPS_GPGSVOff()
{
#ifdef GPSDebug
Serial.print(F("GPS_GPGSVOff() "));
#endif
size_t SIZE = sizeof(GPGSVOff);
return GPS_SendConfig(GPGSVOff, SIZE, 10, GPS_attempts);
}
bool GPS_GNSSmode()
{
#ifdef GPSDebug
Serial.print(F("GPS_GNSSmode() "));
#endif
size_t SIZE = sizeof(GNSSmode);
return GPS_SendConfig(GNSSmode, SIZE, 10, GPS_attempts);
}
uint8_t GPS_GetByte() //get a byte for GPS
{
if (GPSserial.available() == 0)
{
return 0xFF; //for compatibility with I2C reading of GPS
}
else
{
return GPSserial.read();
}
}
/*
MIT license
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
documentation files (the "Software"), to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software,
and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions
of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.
*/