Merge branch 'master' into development
This commit is contained in:
commit
43eefd4703
75 changed files with 2229 additions and 826 deletions
|
@ -5,9 +5,10 @@ env:
|
|||
# see https://github.com/arduino/Arduino/blob/master/build/shared/manpage.adoc#options
|
||||
# and https://github.com/arduino/Arduino/wiki/Arduino-IDE-1.5-3rd-party-Hardware-specification#boardstxt
|
||||
- BOARD="esp32:esp32:esp32"
|
||||
- BOARD="STM32:stm32:GenF1:pnum=BLUEPILL_F103C6"
|
||||
- BOARD="STM32:stm32:GenF3:pnum=BLACKPILL_F303CC"
|
||||
- BOARD="esp8266:esp8266:generic:xtal=80,ResetMethod=ck,CrystalFreq=26,FlashFreq=40,FlashMode=qio,eesz=512K"
|
||||
- BOARD="arduino:samd:arduino_zero_native"
|
||||
- BOARD="arduino:sam:arduino_due_x"
|
||||
- BOARD="arduino:avr:uno"
|
||||
- BOARD="arduino:avr:leonardo"
|
||||
- BOARD="arduino:avr:mega:cpu=atmega2560"
|
||||
|
@ -28,7 +29,7 @@ before_install:
|
|||
- sudo iptables -A INPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT
|
||||
|
||||
# install 3rd party boards
|
||||
- arduino --pref "boardsmanager.additional.urls=http://arduino.esp8266.com/stable/package_esp8266com_index.json,https://dl.espressif.com/dl/package_esp32_index.json,https://github.com/stm32duino/BoardManagerFiles/raw/master/STM32/package_stm_index.json" --save-prefs 2>&1
|
||||
- arduino --pref "boardsmanager.additional.urls=http://arduino.esp8266.com/stable/package_esp8266com_index.json,https://raw.githubusercontent.com/espressif/arduino-esp32/gh-pages/package_esp32_index.json,https://github.com/stm32duino/BoardManagerFiles/raw/master/STM32/package_stm_index.json" --save-prefs 2>&1
|
||||
- if [[ "$BOARD" =~ "esp8266:esp8266:" ]]; then
|
||||
arduino --install-boards esp8266:esp8266;
|
||||
export SKIP_PAT='(HTTP|MQTT).*ino';
|
||||
|
@ -38,6 +39,8 @@ before_install:
|
|||
arduino --install-boards STM32:stm32;
|
||||
elif [[ "$BOARD" =~ "arduino:samd:" ]]; then
|
||||
arduino --install-boards arduino:samd;
|
||||
elif [[ "$BOARD" =~ "arduino:sam:" ]]; then
|
||||
arduino --install-boards arduino:sam;
|
||||
fi
|
||||
|
||||
# create directory to save the library and create symbolic link
|
||||
|
|
|
@ -15,6 +15,8 @@ To report bugs or suggest new features, use the provided issue templates. Use th
|
|||
Issues with generic titles (e.g. "not working", "lora", etc.) will be **CLOSED** until the title is fixed, since the title is supposed to categorize the issue. The same applies for issues with very little information and extensive grammatical or formatting errors that make it difficult to find out what is the actual issue.
|
||||
4. **Issues deserve some attention too.**
|
||||
Issues that are left for 2 weeks without response by the original author when asked for further information will be closed due to inactivity. This is to keep track of important issues, the author is encouraged to reopen the issue at a later date.
|
||||
5. **LoRaLib is a separate project.**
|
||||
RadioLib was created as an extension of LoRaLib for radios other than SX127x. However, LoRaLib project is still active and RadioLib is reusing its code. **Because of that, please open issues/PRs related to SX127x in [LoRaLib](https://github.com/jgromes/LoRaLib)**.
|
||||
|
||||
## Code style guidelines
|
||||
|
||||
|
@ -22,6 +24,7 @@ I like pretty code! Or at least, I like *consistent* code style. When creating p
|
|||
|
||||
1. **Bracket style**
|
||||
This library uses the following style of bracket indentation (1TBS, or "javascript" style):
|
||||
|
||||
```c++
|
||||
if (foo) {
|
||||
bar();
|
||||
|
@ -35,6 +38,7 @@ Use 2 space characters for tabs.
|
|||
|
||||
3. **Single-line comments**
|
||||
Comments can be very useful - and they can become the bane of readability. Every single-line comment should start at new line, have one space between comment delimiter `//` and the start of the comment itself. The comment should also start with a lower-case letter.
|
||||
|
||||
```c++
|
||||
// this function does something
|
||||
foo("bar");
|
||||
|
@ -45,6 +49,7 @@ foo(12345);
|
|||
|
||||
4. **Split code into blocks**
|
||||
It is very easy to write code that machine can read. It is much harder to write one that humans can read. That's why it's a great idea to split code into blocks - even if the block is just a single line!
|
||||
|
||||
```c++
|
||||
// build a temporary buffer (first block)
|
||||
uint8_t* data = new uint8_t[len + 1];
|
||||
|
@ -63,4 +68,4 @@ data[len] = 0;
|
|||
If you're adding a new method, make sure to add appropriate Doxygen comments, so that the documentation is always complete.
|
||||
|
||||
6. **Keywords**
|
||||
This is an Arduino library, so it needs to comply with the Arduino library specification. To add a new keyword to the Arduino IDE syntax highlighting, add it to the keywords.txt file. **Use true tabs in keywords.txt! No spaces there!"
|
||||
This is an Arduino library, so it needs to comply with the Arduino library specification. To add a new keyword to the Arduino IDE syntax highlighting, add it to the keywords.txt file. **Use true tabs in keywords.txt! No spaces there!**
|
||||
|
|
|
@ -32,8 +32,9 @@ RadioLib was originally created as a driver for [__RadioShield__](https://github
|
|||
* __Arduino AVR boards__ - tested on Uno, Mega and Leonardo
|
||||
* __ESP8266 boards__ - NodeMCU, Wemos D1, etc.
|
||||
* __ESP32 boards__ - tested on ESP-WROOM-32
|
||||
* __STM32 boards__ - tested on BluePill F103C6
|
||||
* __STM32 boards__ - tested on Nucleo L452RE-P
|
||||
* __SAMD boards__ - Arduino Zero
|
||||
* __SAM boards__ - Arduino Due
|
||||
|
||||
### In development:
|
||||
* __SIM800C__ GSM module
|
||||
|
|
|
@ -70,6 +70,7 @@ void setup() {
|
|||
// cc.sleep()
|
||||
// cc.transmit();
|
||||
// cc.receive();
|
||||
// cc.readData();
|
||||
}
|
||||
|
||||
// flag to indicate that a packet was received
|
||||
|
@ -142,6 +143,9 @@ void loop() {
|
|||
|
||||
}
|
||||
|
||||
// put module back to listen mode
|
||||
cc.startReceive();
|
||||
|
||||
// we're ready to receive more packets,
|
||||
// enable interrupt service routine
|
||||
enableInterrupt = true;
|
||||
|
|
|
@ -64,6 +64,7 @@ void setup() {
|
|||
// rf.sleep()
|
||||
// rf.transmit();
|
||||
// rf.receive();
|
||||
// rf.readData();
|
||||
}
|
||||
|
||||
// flag to indicate that a packet was received
|
||||
|
@ -125,6 +126,9 @@ void loop() {
|
|||
|
||||
}
|
||||
|
||||
// put module back to listen mode
|
||||
rf.startReceive();
|
||||
|
||||
// we're ready to receive more packets,
|
||||
// enable interrupt service routine
|
||||
enableInterrupt = true;
|
||||
|
|
|
@ -53,6 +53,28 @@ void setup() {
|
|||
Serial.println(state);
|
||||
while (true);
|
||||
}
|
||||
|
||||
// NOTE: Some SX126x modules use TCXO
|
||||
// (Temprature-Compensated Crystal Oscillator).
|
||||
// To be able to use these modules, TCXO
|
||||
// control must be enabled by calling
|
||||
// setTCXO() and specifying the reference
|
||||
// voltage.
|
||||
|
||||
/*
|
||||
Serial.print(F("[SX1262] Setting TCXO reference ... "));
|
||||
// enable TCXO
|
||||
// reference voltage: 1.6 V
|
||||
// timeout: 5000 us
|
||||
state = lora.setTCXO(1.6);
|
||||
if (state == ERR_NONE) {
|
||||
Serial.println(F("success!"));
|
||||
} else {
|
||||
Serial.print(F("failed, code "));
|
||||
Serial.println(state);
|
||||
while (true);
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
void loop() {
|
||||
|
@ -89,7 +111,7 @@ void loop() {
|
|||
// of the last received packet
|
||||
Serial.print(F("[SX1262] SNR:\t\t"));
|
||||
Serial.print(lora.getSNR());
|
||||
Serial.println(F(" dBm"));
|
||||
Serial.println(F(" dB"));
|
||||
|
||||
} else if (state == ERR_RX_TIMEOUT) {
|
||||
// timeout occurred while waiting for a packet
|
||||
|
|
|
@ -77,6 +77,7 @@ void setup() {
|
|||
// lora.sleep()
|
||||
// lora.transmit();
|
||||
// lora.receive();
|
||||
// lora.readData();
|
||||
// lora.scanChannel();
|
||||
}
|
||||
|
||||
|
@ -136,7 +137,7 @@ void loop() {
|
|||
// print SNR (Signal-to-Noise Ratio)
|
||||
Serial.print(F("[SX1262] SNR:\t\t"));
|
||||
Serial.print(lora.getSNR());
|
||||
Serial.println(F(" dBm"));
|
||||
Serial.println(F(" dB"));
|
||||
|
||||
} else if (state == ERR_CRC_MISMATCH) {
|
||||
// packet was received, but is malformed
|
||||
|
@ -149,6 +150,9 @@ void loop() {
|
|||
|
||||
}
|
||||
|
||||
// put module back to listen mode
|
||||
lora.startReceive();
|
||||
|
||||
// we're ready to receive more packets,
|
||||
// enable interrupt service routine
|
||||
enableInterrupt = true;
|
||||
|
|
|
@ -88,7 +88,7 @@ void loop() {
|
|||
// of the last received packet
|
||||
Serial.print(F("[SX1278] SNR:\t\t\t"));
|
||||
Serial.print(lora.getSNR());
|
||||
Serial.println(F(" dBm"));
|
||||
Serial.println(F(" dB"));
|
||||
|
||||
// print frequency error
|
||||
// of the last received packet
|
||||
|
|
|
@ -76,6 +76,7 @@ void setup() {
|
|||
// lora.sleep()
|
||||
// lora.transmit();
|
||||
// lora.receive();
|
||||
// lora.readData();
|
||||
// lora.scanChannel();
|
||||
}
|
||||
|
||||
|
@ -135,7 +136,7 @@ void loop() {
|
|||
// print SNR (Signal-to-Noise Ratio)
|
||||
Serial.print(F("[SX1278] SNR:\t\t"));
|
||||
Serial.print(lora.getSNR());
|
||||
Serial.println(F(" dBm"));
|
||||
Serial.println(F(" dB"));
|
||||
|
||||
// print frequency error
|
||||
Serial.print(F("[SX1278] Frequency error:\t"));
|
||||
|
@ -153,6 +154,9 @@ void loop() {
|
|||
|
||||
}
|
||||
|
||||
// put module back to listen mode
|
||||
lora.startReceive();
|
||||
|
||||
// we're ready to receive more packets,
|
||||
// enable interrupt service routine
|
||||
enableInterrupt = true;
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
/*
|
||||
RadioLib Module Template header file
|
||||
|
||||
|
||||
Before opening pull request, please make sure that:
|
||||
1. All files MUST be compiled without errors using default Arduino IDE settings.
|
||||
2. All files SHOULD be compiled without warnings with compiler warnings set to "All".
|
||||
|
@ -8,7 +8,7 @@
|
|||
4. Writing style SHOULD be consistent.
|
||||
5. Comments SHOULD be in place for the most important chunks of code and SHOULD be free of typos.
|
||||
6. To indent, 2 spaces MUST be used.
|
||||
|
||||
|
||||
If at any point you are unsure about the required style, please refer to the rest of the modules.
|
||||
*/
|
||||
|
||||
|
@ -21,33 +21,33 @@
|
|||
*/
|
||||
#include "Module.h"
|
||||
|
||||
/*
|
||||
/*
|
||||
Only use the following include if the module implements methods for OSI transport layer control.
|
||||
This concerns only modules similar to e.g. ESP8266.
|
||||
|
||||
This concerns only modules similar to e.g. ESP8266.
|
||||
|
||||
In this case, your class MUST implement all virtual methods of TransportLayer class.
|
||||
You also MUST provide crystal oscillator frequency and frequency configuration divisor step resolution
|
||||
to the TransportLayer constructor.
|
||||
*/
|
||||
//#include "../protocols/TransportLayer.h"
|
||||
|
||||
/*
|
||||
/*
|
||||
Only use the following include if the module implements methods for OSI physical layer control.
|
||||
This concerns only modules similar to SX127x/RF69/CC1101 etc.
|
||||
|
||||
In this case, your class MUST implement all virtual methods of PhysicalLayer class.
|
||||
|
||||
In this case, your class MUST implement all virtual methods of PhysicalLayer class.
|
||||
*/
|
||||
//#include "../protocols/PhysicalLayer.h"
|
||||
|
||||
/*
|
||||
/*
|
||||
Register map
|
||||
Definition of SPI/I2C register map SHOULD be placed here. The register map SHOULD have two parts:
|
||||
|
||||
|
||||
1 - Address map: only defines register names and addresses. Register names MUST match names in
|
||||
official documentation (datasheets etc.).
|
||||
2 - Variable map: defines variables inside register. This functions as a bit range map for a specific register.
|
||||
Bit range (MSB and LSB) as well as short description for each variable MUST be provided in a comment.
|
||||
|
||||
|
||||
See RF69 and SX127x header files for examples of register maps.
|
||||
*/
|
||||
// <module_name> register map | spaces up to this point
|
||||
|
@ -59,9 +59,9 @@
|
|||
|
||||
/*
|
||||
Module class definition
|
||||
|
||||
|
||||
The module class MAY inherit from the following classes:
|
||||
|
||||
|
||||
1 - ISerial: Interface for Arduino Serial class, intended as a thin wrapper for modules that directly take
|
||||
Serial input (e.g. HC-05).
|
||||
2 - TransportLayer: In case the module implements methods for OSI transport layer control (e.g. ESP8266).
|
||||
|
@ -75,29 +75,31 @@ class <module_name> {
|
|||
*/
|
||||
// constructor
|
||||
<module_name>(Module* module);
|
||||
|
||||
|
||||
/*
|
||||
The class MUST implement at least one basic method called "begin".
|
||||
The "begin" method MUST initialize the module and return the status as int16_t type.
|
||||
*/
|
||||
// basic methods
|
||||
int16_t begin();
|
||||
|
||||
|
||||
/*
|
||||
The class MAY implement additional methods.
|
||||
All implemented methods SHOULD return the status as int16_t type.
|
||||
*/
|
||||
|
||||
|
||||
#ifndef RADIOLIB_GODMODE
|
||||
private:
|
||||
#endif
|
||||
/*
|
||||
The class MUST contain private member "Module* _mod"
|
||||
*/
|
||||
Module* _mod;
|
||||
|
||||
|
||||
/*
|
||||
The class MAY contain additional private variables and/or methods.
|
||||
Private member variables MUST have a name prefixed with "_" (underscore, ASCII 0x5F)
|
||||
|
||||
|
||||
Usually, these are variables for saving module configuration, or methods that do not have to be exposed to the end user.
|
||||
*/
|
||||
};
|
||||
|
|
12
keywords.txt
12
keywords.txt
|
@ -88,6 +88,14 @@ setDataShaping KEYWORD2
|
|||
setOOK KEYWORD2
|
||||
setDataShapingOOK KEYWORD2
|
||||
setCRC KEYWORD2
|
||||
variablePacketLengthMode KEYWORD2
|
||||
fixedPacketLengthMode KEYWORD2
|
||||
setCrcFiltering KEYWORD2
|
||||
enableSyncWordFiltering KEYWORD2
|
||||
disableSyncWordFiltering KEYWORD2
|
||||
setPromiscuous KEYWORD2
|
||||
setRSSIConfig KEYWORD2
|
||||
setEncoding KEYWORD2
|
||||
|
||||
# RF69-specific
|
||||
setAESKey KEYWORD2
|
||||
|
@ -107,6 +115,7 @@ setTCXO KEYWORD2
|
|||
setDio2AsRfSwitch KEYWORD2
|
||||
getTimeOnAir KEYWORD2
|
||||
setSyncBits KEYWORD2
|
||||
setWhitening KEYWORD2
|
||||
|
||||
# ESP8266
|
||||
join KEYWORD2
|
||||
|
@ -182,6 +191,9 @@ ERR_INVALID_CURRENT_LIMIT LITERAL1
|
|||
ERR_INVALID_PREAMBLE_LENGTH LITERAL1
|
||||
ERR_INVALID_GAIN LITERAL1
|
||||
ERR_WRONG_MODEM LITERAL1
|
||||
ERR_INVALID_NUM_SAMPLES LITERAL1
|
||||
ERR_INVALID_RSSI_OFFSET LITERAL1
|
||||
ERR_INVALID_ENCODING LITERAL1
|
||||
|
||||
ERR_INVALID_BIT_RATE LITERAL1
|
||||
ERR_INVALID_FREQUENCY_DEVIATION LITERAL1
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
name=RadioLib
|
||||
version=1.6.1
|
||||
version=1.8.0
|
||||
author=Jan Gromes <gromes.jan@gmail.com>
|
||||
maintainer=Jan Gromes <gromes.jan@gmail.com>
|
||||
sentence=Universal wireless communication library for Arduino
|
||||
|
|
|
@ -9,7 +9,7 @@ void ISerial::begin(long speed) {
|
|||
}
|
||||
|
||||
bool ISerial::listen() {
|
||||
#if defined ( ESP32 ) || defined (SAMD_SERIES) || defined (ARDUINO_ARCH_STM32)
|
||||
#ifdef RADIOLIB_SOFTWARE_SERIAL_UNSUPPORTED
|
||||
return true;
|
||||
#else
|
||||
return(_mod->ModuleSerial->listen());
|
||||
|
@ -21,7 +21,7 @@ void ISerial::end() {
|
|||
}
|
||||
|
||||
bool ISerial::isListening() {
|
||||
#if defined( ESP32 ) || defined ( SAMD_SERIES ) || defined (ARDUINO_ARCH_STM32)
|
||||
#ifdef RADIOLIB_SOFTWARE_SERIAL_UNSUPPORTED
|
||||
return true;
|
||||
#else
|
||||
return(_mod->ModuleSerial->isListening());
|
||||
|
@ -29,7 +29,7 @@ bool ISerial::isListening() {
|
|||
}
|
||||
|
||||
bool ISerial::stopListening() {
|
||||
#if defined( ESP32 ) || defined ( SAMD_SERIES ) || defined (ARDUINO_ARCH_STM32)
|
||||
#ifdef RADIOLIB_SOFTWARE_SERIAL_UNSUPPORTED
|
||||
return true;
|
||||
#else
|
||||
return(_mod->ModuleSerial->stopListening());
|
||||
|
@ -37,7 +37,7 @@ bool ISerial::stopListening() {
|
|||
}
|
||||
|
||||
bool ISerial::overflow() {
|
||||
#if defined( ESP32 ) || defined ( SAMD_SERIES ) || defined (ARDUINO_ARCH_STM32)
|
||||
#ifdef RADIOLIB_SOFTWARE_SERIAL_UNSUPPORTED
|
||||
return false;
|
||||
#else
|
||||
return(_mod->ModuleSerial->overflow());
|
||||
|
|
|
@ -54,7 +54,9 @@ class ISerial {
|
|||
size_t println(const Printable&);
|
||||
size_t println(void);
|
||||
|
||||
#ifndef RADIOLIB_GODMODE
|
||||
protected:
|
||||
#endif
|
||||
Module* _mod;
|
||||
};
|
||||
|
||||
|
|
|
@ -7,10 +7,11 @@ Module::Module(int rx, int tx, HardwareSerial* useSer) {
|
|||
_int0 = -1;
|
||||
_int1 = -1;
|
||||
|
||||
#if defined(ESP32) || defined(SAMD_SERIES) || defined (ARDUINO_ARCH_STM32)
|
||||
ModuleSerial = useSer;
|
||||
#ifdef RADIOLIB_SOFTWARE_SERIAL_UNSUPPORTED
|
||||
ModuleSerial = useSer;
|
||||
#else
|
||||
ModuleSerial = new SoftwareSerial(_rx, _tx);
|
||||
(void)useSer;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -33,10 +34,11 @@ Module::Module(int cs, int int0, int int1, int rx, int tx, SPIClass& spi, SPISet
|
|||
_spi = &spi;
|
||||
_spiSettings = spiSettings;
|
||||
|
||||
#if defined(ESP32) || defined(SAMD_SERIES) || defined (ARDUINO_ARCH_STM32)
|
||||
#ifdef RADIOLIB_SOFTWARE_SERIAL_UNSUPPORTED
|
||||
ModuleSerial = useSer;
|
||||
#else
|
||||
ModuleSerial = new SoftwareSerial(_rx, _tx);
|
||||
(void)useSer;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -53,33 +55,33 @@ Module::Module(int cs, int int0, int int1, int int2, SPIClass& spi, SPISettings
|
|||
void Module::init(uint8_t interface, uint8_t gpio) {
|
||||
// select interface
|
||||
switch(interface) {
|
||||
case USE_SPI:
|
||||
case RADIOLIB_USE_SPI:
|
||||
pinMode(_cs, OUTPUT);
|
||||
digitalWrite(_cs, HIGH);
|
||||
_spi->begin();
|
||||
break;
|
||||
case USE_UART:
|
||||
case RADIOLIB_USE_UART:
|
||||
#if defined(ESP32)
|
||||
ModuleSerial->begin(baudrate, SERIAL_8N1, _rx, _tx);
|
||||
#else
|
||||
ModuleSerial->begin(baudrate);
|
||||
#endif
|
||||
break;
|
||||
case USE_I2C:
|
||||
case RADIOLIB_USE_I2C:
|
||||
break;
|
||||
}
|
||||
|
||||
// select GPIO
|
||||
switch(gpio) {
|
||||
case INT_NONE:
|
||||
case RADIOLIB_INT_NONE:
|
||||
break;
|
||||
case INT_0:
|
||||
case RADIOLIB_INT_0:
|
||||
pinMode(_int0, INPUT);
|
||||
break;
|
||||
case INT_1:
|
||||
case RADIOLIB_INT_1:
|
||||
pinMode(_int1, INPUT);
|
||||
break;
|
||||
case INT_BOTH:
|
||||
case RADIOLIB_INT_BOTH:
|
||||
pinMode(_int0, INPUT);
|
||||
pinMode(_int1, INPUT);
|
||||
break;
|
||||
|
@ -120,20 +122,20 @@ bool Module::ATgetResponse() {
|
|||
while (millis() - start < _ATtimeout) {
|
||||
while(ModuleSerial->available() > 0) {
|
||||
char c = ModuleSerial->read();
|
||||
DEBUG_PRINT(c);
|
||||
RADIOLIB_VERBOSE_PRINT(c);
|
||||
data += c;
|
||||
}
|
||||
|
||||
if(data.indexOf("OK") != -1) {
|
||||
DEBUG_PRINTLN();
|
||||
RADIOLIB_VERBOSE_PRINTLN();
|
||||
return(true);
|
||||
} else if (data.indexOf("ERROR") != -1) {
|
||||
DEBUG_PRINTLN();
|
||||
RADIOLIB_VERBOSE_PRINTLN();
|
||||
return(false);
|
||||
}
|
||||
|
||||
}
|
||||
DEBUG_PRINTLN();
|
||||
RADIOLIB_VERBOSE_PRINTLN();
|
||||
return(false);
|
||||
}
|
||||
|
||||
|
@ -170,24 +172,24 @@ int16_t Module::SPIsetRegValue(uint8_t reg, uint8_t value, uint8_t msb, uint8_t
|
|||
}
|
||||
|
||||
// check failed, print debug info
|
||||
DEBUG_PRINTLN();
|
||||
DEBUG_PRINT(F("address:\t0x"));
|
||||
DEBUG_PRINTLN(reg, HEX);
|
||||
DEBUG_PRINT(F("bits:\t\t"));
|
||||
DEBUG_PRINT(msb);
|
||||
DEBUG_PRINT(' ');
|
||||
DEBUG_PRINTLN(lsb);
|
||||
DEBUG_PRINT(F("value:\t\t0b"));
|
||||
DEBUG_PRINTLN(value, BIN);
|
||||
DEBUG_PRINT(F("current:\t0b"));
|
||||
DEBUG_PRINTLN(currentValue, BIN);
|
||||
DEBUG_PRINT(F("mask:\t\t0b"));
|
||||
DEBUG_PRINTLN(mask, BIN);
|
||||
DEBUG_PRINT(F("new:\t\t0b"));
|
||||
DEBUG_PRINTLN(newValue, BIN);
|
||||
DEBUG_PRINT(F("read:\t\t0b"));
|
||||
DEBUG_PRINTLN(readValue, BIN);
|
||||
DEBUG_PRINTLN();
|
||||
RADIOLIB_DEBUG_PRINTLN();
|
||||
RADIOLIB_DEBUG_PRINT(F("address:\t0x"));
|
||||
RADIOLIB_DEBUG_PRINTLN(reg, HEX);
|
||||
RADIOLIB_DEBUG_PRINT(F("bits:\t\t"));
|
||||
RADIOLIB_DEBUG_PRINT(msb);
|
||||
RADIOLIB_DEBUG_PRINT(' ');
|
||||
RADIOLIB_DEBUG_PRINTLN(lsb);
|
||||
RADIOLIB_DEBUG_PRINT(F("value:\t\t0b"));
|
||||
RADIOLIB_DEBUG_PRINTLN(value, BIN);
|
||||
RADIOLIB_DEBUG_PRINT(F("current:\t0b"));
|
||||
RADIOLIB_DEBUG_PRINTLN(currentValue, BIN);
|
||||
RADIOLIB_DEBUG_PRINT(F("mask:\t\t0b"));
|
||||
RADIOLIB_DEBUG_PRINTLN(mask, BIN);
|
||||
RADIOLIB_DEBUG_PRINT(F("new:\t\t0b"));
|
||||
RADIOLIB_DEBUG_PRINTLN(newValue, BIN);
|
||||
RADIOLIB_DEBUG_PRINT(F("read:\t\t0b"));
|
||||
RADIOLIB_DEBUG_PRINTLN(readValue, BIN);
|
||||
RADIOLIB_DEBUG_PRINTLN();
|
||||
|
||||
return(ERR_SPI_WRITE_FAILED);
|
||||
}
|
||||
|
@ -219,30 +221,30 @@ void Module::SPItransfer(uint8_t cmd, uint8_t reg, uint8_t* dataOut, uint8_t* da
|
|||
|
||||
// send SPI register address with access command
|
||||
_spi->transfer(reg | cmd);
|
||||
DEBUG_PRINT(reg | cmd, HEX);
|
||||
DEBUG_PRINT('\t');
|
||||
DEBUG_PRINT(reg | cmd, BIN);
|
||||
DEBUG_PRINT('\t');
|
||||
RADIOLIB_VERBOSE_PRINT(reg | cmd, HEX);
|
||||
RADIOLIB_VERBOSE_PRINT('\t');
|
||||
RADIOLIB_VERBOSE_PRINT(reg | cmd, BIN);
|
||||
RADIOLIB_VERBOSE_PRINT('\t');
|
||||
|
||||
// send data or get response
|
||||
if(cmd == SPIwriteCommand) {
|
||||
for(size_t n = 0; n < numBytes; n++) {
|
||||
_spi->transfer(dataOut[n]);
|
||||
DEBUG_PRINT(dataOut[n], HEX);
|
||||
DEBUG_PRINT('\t');
|
||||
DEBUG_PRINT(dataOut[n], BIN);
|
||||
DEBUG_PRINT('\t');
|
||||
RADIOLIB_VERBOSE_PRINT(dataOut[n], HEX);
|
||||
RADIOLIB_VERBOSE_PRINT('\t');
|
||||
RADIOLIB_VERBOSE_PRINT(dataOut[n], BIN);
|
||||
RADIOLIB_VERBOSE_PRINT('\t');
|
||||
}
|
||||
} else if (cmd == SPIreadCommand) {
|
||||
for(size_t n = 0; n < numBytes; n++) {
|
||||
dataIn[n] = _spi->transfer(0x00);
|
||||
DEBUG_PRINT(dataIn[n], HEX);
|
||||
DEBUG_PRINT('\t');
|
||||
DEBUG_PRINT(dataIn[n], BIN);
|
||||
DEBUG_PRINT('\t');
|
||||
RADIOLIB_VERBOSE_PRINT(dataIn[n], HEX);
|
||||
RADIOLIB_VERBOSE_PRINT('\t');
|
||||
RADIOLIB_VERBOSE_PRINT(dataIn[n], BIN);
|
||||
RADIOLIB_VERBOSE_PRINT('\t');
|
||||
}
|
||||
}
|
||||
DEBUG_PRINTLN();
|
||||
RADIOLIB_VERBOSE_PRINTLN();
|
||||
|
||||
// release CS
|
||||
digitalWrite(_cs, HIGH);
|
||||
|
|
15
src/Module.h
15
src/Module.h
|
@ -1,15 +1,14 @@
|
|||
#ifndef _RADIOLIB_MODULE_H
|
||||
#define _RADIOLIB_MODULE_H
|
||||
|
||||
#include "TypeDef.h"
|
||||
|
||||
#include <SPI.h>
|
||||
//#include <Wire.h>
|
||||
#if defined(ESP32) || defined(SAMD_SERIES) || defined (ARDUINO_ARCH_STM32)
|
||||
#else
|
||||
#ifndef RADIOLIB_SOFTWARE_SERIAL_UNSUPPORTED
|
||||
#include <SoftwareSerial.h>
|
||||
#endif
|
||||
|
||||
#include "TypeDef.h"
|
||||
|
||||
/*!
|
||||
\class Module
|
||||
|
||||
|
@ -28,7 +27,7 @@ class Module {
|
|||
|
||||
\param serial HardwareSerial to be used on ESP32 and SAMD. Defaults to 1
|
||||
*/
|
||||
#if defined(ESP32) || defined(SAMD_SERIES) || defined (ARDUINO_ARCH_STM32)
|
||||
#ifdef RADIOLIB_SOFTWARE_SERIAL_UNSUPPORTED
|
||||
Module(int tx, int rx, HardwareSerial* useSer = &Serial1);
|
||||
#else
|
||||
Module(int tx, int rx, HardwareSerial* useSer = nullptr);
|
||||
|
@ -85,7 +84,7 @@ class Module {
|
|||
|
||||
\param serial HardwareSerial to be used on ESP32 and SAMD. Defaults to 1
|
||||
*/
|
||||
#if defined(ESP32) || defined(SAMD_SERIES) || defined (ARDUINO_ARCH_STM32)
|
||||
#ifdef RADIOLIB_SOFTWARE_SERIAL_UNSUPPORTED
|
||||
Module(int cs, int int0, int int1, int rx, int tx, SPIClass& spi = SPI, SPISettings spiSettings = SPISettings(2000000, MSBFIRST, SPI_MODE0), HardwareSerial* useSer = &Serial1);
|
||||
#else
|
||||
Module(int cs, int int0, int int1, int rx, int tx, SPIClass& spi = SPI, SPISettings spiSettings = SPISettings(2000000, MSBFIRST, SPI_MODE0), HardwareSerial* useSer = nullptr);
|
||||
|
@ -97,7 +96,7 @@ class Module {
|
|||
/*!
|
||||
\brief Internal SoftwareSerial instance.
|
||||
*/
|
||||
#if defined(ESP32) || defined(SAMD_SERIES) || defined (ARDUINO_ARCH_STM32)
|
||||
#ifdef RADIOLIB_SOFTWARE_SERIAL_UNSUPPORTED
|
||||
HardwareSerial* ModuleSerial;
|
||||
#else
|
||||
SoftwareSerial* ModuleSerial;
|
||||
|
@ -311,7 +310,9 @@ class Module {
|
|||
*/
|
||||
SPISettings getSpiSettings() const { return(_spiSettings); }
|
||||
|
||||
#ifndef RADIOLIB_GODMODE
|
||||
private:
|
||||
#endif
|
||||
int _cs;
|
||||
int _tx;
|
||||
int _rx;
|
||||
|
|
|
@ -1,8 +0,0 @@
|
|||
#include "RadioLib.h"
|
||||
|
||||
Radio::Radio() {
|
||||
ModuleA = new Module(RADIOSHIELD_CS_A, RADIOSHIELD_INT_0, RADIOSHIELD_INT_1, RADIOSHIELD_RX_A, RADIOSHIELD_TX_A);
|
||||
ModuleB = new Module(RADIOSHIELD_CS_B, RADIOSHIELD_INT_0, RADIOSHIELD_INT_1, RADIOSHIELD_RX_B, RADIOSHIELD_TX_B);
|
||||
}
|
||||
|
||||
Radio RadioShield;
|
|
@ -38,42 +38,43 @@
|
|||
#include "TypeDef.h"
|
||||
#include "Module.h"
|
||||
|
||||
#include "modules/CC1101.h"
|
||||
#ifndef ESP8266
|
||||
#include "modules/ESP8266.h"
|
||||
#ifdef RADIOLIB_GODMODE
|
||||
#warning "God mode active, I hope it was intentional. Buckle up, lads."
|
||||
#endif
|
||||
#include "modules/HC05.h"
|
||||
#include "modules/JDY08.h"
|
||||
#include "modules/nRF24.h"
|
||||
#include "modules/RF69.h"
|
||||
#include "modules/RFM95.h"
|
||||
#include "modules/RFM96.h"
|
||||
#include "modules/RFM97.h"
|
||||
#include "modules/SIM800.h"
|
||||
#include "modules/SX1231.h"
|
||||
#include "modules/SX1261.h"
|
||||
#include "modules/SX1262.h"
|
||||
#include "modules/SX1268.h"
|
||||
#include "modules/SX1272.h"
|
||||
#include "modules/SX1273.h"
|
||||
#include "modules/SX1276.h"
|
||||
#include "modules/SX1277.h"
|
||||
#include "modules/SX1278.h"
|
||||
#include "modules/SX1279.h"
|
||||
#include "modules/XBee.h"
|
||||
|
||||
#include "modules/CC1101/CC1101.h"
|
||||
#ifndef ESP8266
|
||||
#include "modules/ESP8266/ESP8266.h"
|
||||
#endif
|
||||
#include "modules/HC05/HC05.h"
|
||||
#include "modules/JDY08/JDY08.h"
|
||||
#include "modules/nRF24/nRF24.h"
|
||||
#include "modules/RF69/RF69.h"
|
||||
#include "modules/RFM9x/RFM95.h"
|
||||
#include "modules/RFM9x/RFM96.h"
|
||||
#include "modules/RFM9x/RFM97.h"
|
||||
#include "modules/SX1231/SX1231.h"
|
||||
#include "modules/SX126x/SX1261.h"
|
||||
#include "modules/SX126x/SX1262.h"
|
||||
#include "modules/SX126x/SX1268.h"
|
||||
#include "modules/SX127x/SX1272.h"
|
||||
#include "modules/SX127x/SX1273.h"
|
||||
#include "modules/SX127x/SX1276.h"
|
||||
#include "modules/SX127x/SX1277.h"
|
||||
#include "modules/SX127x/SX1278.h"
|
||||
#include "modules/SX127x/SX1279.h"
|
||||
#include "modules/XBee/XBee.h"
|
||||
|
||||
// physical layer protocols
|
||||
#include "protocols/PhysicalLayer.h"
|
||||
#include "protocols/Morse.h"
|
||||
#include "protocols/RTTY.h"
|
||||
#include "protocols/Pager.h"
|
||||
#include "protocols/PSK.h"
|
||||
#include "protocols/PhysicalLayer/PhysicalLayer.h"
|
||||
#include "protocols/Morse/Morse.h"
|
||||
#include "protocols/RTTY/RTTY.h"
|
||||
|
||||
// transport layer protocols
|
||||
#ifndef ESP8266
|
||||
#include "protocols/TransportLayer.h"
|
||||
#include "protocols/HTTP.h"
|
||||
#include "protocols/MQTT.h"
|
||||
#include "protocols/TransportLayer/TransportLayer.h"
|
||||
#include "protocols/HTTP/HTTP.h"
|
||||
#include "protocols/MQTT/MQTT.h"
|
||||
#endif
|
||||
|
||||
// RadioShield pin definitions
|
||||
|
@ -96,18 +97,23 @@
|
|||
class Radio {
|
||||
public:
|
||||
|
||||
/*!
|
||||
\brief Default constructor. Only used to set ModuleA and ModuleB configuration.
|
||||
*/
|
||||
Radio();
|
||||
|
||||
Module* ModuleA;
|
||||
Module* ModuleB;
|
||||
|
||||
/*!
|
||||
\brief Default constructor. Only used to set ModuleA and ModuleB configuration.
|
||||
*/
|
||||
Radio() {
|
||||
ModuleA = new Module(RADIOSHIELD_CS_A, RADIOSHIELD_INT_0, RADIOSHIELD_INT_1, RADIOSHIELD_RX_A, RADIOSHIELD_TX_A, SPI, SPISettings(2000000, MSBFIRST, SPI_MODE0), nullptr);
|
||||
ModuleB = new Module(RADIOSHIELD_CS_B, RADIOSHIELD_INT_0, RADIOSHIELD_INT_1, RADIOSHIELD_RX_B, RADIOSHIELD_TX_B, SPI, SPISettings(2000000, MSBFIRST, SPI_MODE0), nullptr);
|
||||
}
|
||||
|
||||
#ifndef RADIOLIB_GODMODE
|
||||
private:
|
||||
#endif
|
||||
|
||||
};
|
||||
|
||||
extern Radio RadioShield;
|
||||
Radio RadioShield;
|
||||
|
||||
#endif
|
||||
|
|
|
@ -1,20 +1,63 @@
|
|||
#ifndef _RADIOLIB_TYPES_H
|
||||
#define _RADIOLIB_TYPES_H
|
||||
|
||||
#if ARDUINO >= 100
|
||||
#include "Arduino.h"
|
||||
#else
|
||||
#error "Unsupported Arduino version (< 1.0.0)"
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Uncomment to enable static-only memory management: no dynamic allocation will be performed.
|
||||
* Warning: Large static arrays will be created in some methods. It is not advised to send large packets in this mode.
|
||||
*/
|
||||
|
||||
//#define RADIOLIB_STATIC_ONLY
|
||||
|
||||
// set the size of static arrays to use
|
||||
#define RADIOLIB_STATIC_ARRAY_SIZE 256
|
||||
|
||||
/*
|
||||
* Uncomment to enable debug output.
|
||||
* Warning: Debug output will slow down the whole system significantly.
|
||||
* Also, it will result in larger compiled binary.
|
||||
* Levels: debug - only main info
|
||||
* verbose - full transcript of all SPI/UART communication
|
||||
*/
|
||||
|
||||
//#define RADIOLIB_DEBUG
|
||||
//#define RADIOLIB_VERBOSE
|
||||
|
||||
// set which Serial port should be used for debug output
|
||||
#define RADIOLIB_DEBUG_PORT Serial
|
||||
|
||||
#ifdef RADIOLIB_DEBUG
|
||||
#define DEBUG_PRINT(...) { Serial.print(__VA_ARGS__); }
|
||||
#define DEBUG_PRINTLN(...) { Serial.println(__VA_ARGS__); }
|
||||
#define RADIOLIB_DEBUG_PRINT(...) { RADIOLIB_DEBUG_PORT.print(__VA_ARGS__); }
|
||||
#define RADIOLIB_DEBUG_PRINTLN(...) { RADIOLIB_DEBUG_PORT.println(__VA_ARGS__); }
|
||||
#else
|
||||
#define DEBUG_PRINT(...) {}
|
||||
#define DEBUG_PRINTLN(...) {}
|
||||
#define RADIOLIB_DEBUG_PRINT(...) {}
|
||||
#define RADIOLIB_DEBUG_PRINTLN(...) {}
|
||||
#endif
|
||||
|
||||
#ifdef RADIOLIB_VERBOSE
|
||||
#define RADIOLIB_VERBOSE_PRINT(...) { RADIOLIB_DEBUG_PORT.print(__VA_ARGS__); }
|
||||
#define RADIOLIB_VERBOSE_PRINTLN(...) { RADIOLIB_DEBUG_PORT.println(__VA_ARGS__); }
|
||||
#else
|
||||
#define RADIOLIB_VERBOSE_PRINT(...) {}
|
||||
#define RADIOLIB_VERBOSE_PRINTLN(...) {}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Uncomment to enable god mode - all methods and member variables in all classes will be made public, thus making them accessible from Arduino code.
|
||||
* Warning: Come on, it's called GOD mode - obviously only use this if you know what you're doing.
|
||||
* Failure to heed the above warning may result in bricked module.
|
||||
*/
|
||||
//#define RADIOLIB_GODMODE
|
||||
|
||||
/*
|
||||
* The following platforms do not support SoftwareSerial library.
|
||||
*/
|
||||
#if defined(ESP32) || defined(SAMD_SERIES) || defined(ARDUINO_ARCH_STM32) || defined(__SAM3X8E__)
|
||||
#define RADIOLIB_SOFTWARE_SERIAL_UNSUPPORTED
|
||||
#endif
|
||||
|
||||
/*!
|
||||
|
@ -26,37 +69,37 @@
|
|||
/*!
|
||||
\brief Use SPI interface.
|
||||
*/
|
||||
#define USE_SPI 0x00
|
||||
#define RADIOLIB_USE_SPI 0x00
|
||||
|
||||
/*!
|
||||
\brief Use UART interface.
|
||||
*/
|
||||
#define USE_UART 0x01
|
||||
#define RADIOLIB_USE_UART 0x01
|
||||
|
||||
/*!
|
||||
\brief Use I2C interface.
|
||||
*/
|
||||
#define USE_I2C 0x02
|
||||
#define RADIOLIB_USE_I2C 0x02
|
||||
|
||||
/*!
|
||||
\brief Do not use any interrupts/GPIOs.
|
||||
*/
|
||||
#define INT_NONE 0x00
|
||||
#define RADIOLIB_INT_NONE 0x00
|
||||
|
||||
/*!
|
||||
\brief Use interrupt/GPIO 0.
|
||||
*/
|
||||
#define INT_0 0x01
|
||||
#define RADIOLIB_INT_0 0x01
|
||||
|
||||
/*!
|
||||
\brief Use interrupt/GPIO 1.
|
||||
*/
|
||||
#define INT_1 0x02
|
||||
#define RADIOLIB_INT_1 0x02
|
||||
|
||||
/*!
|
||||
\brief Use both interrupts/GPIOs.
|
||||
*/
|
||||
#define INT_BOTH 0x03
|
||||
#define RADIOLIB_INT_BOTH 0x03
|
||||
|
||||
/*!
|
||||
\}
|
||||
|
@ -242,6 +285,21 @@
|
|||
*/
|
||||
#define ERR_WRONG_MODEM -20
|
||||
|
||||
/*!
|
||||
\brief The supplied number of RSSI samples is invalid.
|
||||
*/
|
||||
#define ERR_INVALID_NUM_SAMPLES -21
|
||||
|
||||
/*!
|
||||
\brief The supplied RSSI offset is invalid.
|
||||
*/
|
||||
#define ERR_INVALID_RSSI_OFFSET -22
|
||||
|
||||
/*!
|
||||
\brief The supplied encoding is invalid.
|
||||
*/
|
||||
#define ERR_INVALID_ENCODING -23
|
||||
|
||||
// RF69-specific status codes
|
||||
|
||||
/*!
|
||||
|
|
|
@ -3,13 +3,16 @@
|
|||
CC1101::CC1101(Module* module) : PhysicalLayer(CC1101_CRYSTAL_FREQ, CC1101_DIV_EXPONENT, CC1101_MAX_PACKET_LENGTH) {
|
||||
_mod = module;
|
||||
_packetLengthQueried = false;
|
||||
_packetLengthConfig = CC1101_LENGTH_CONFIG_VARIABLE;
|
||||
|
||||
_syncWordLength = 2;
|
||||
}
|
||||
|
||||
int16_t CC1101::begin(float freq, float br, float rxBw, float freqDev, int8_t power) {
|
||||
int16_t CC1101::begin(float freq, float br, float rxBw, float freqDev, int8_t power, uint8_t preambleLength) {
|
||||
// set module properties
|
||||
_mod->SPIreadCommand = CC1101_CMD_READ;
|
||||
_mod->SPIwriteCommand = CC1101_CMD_WRITE;
|
||||
_mod->init(USE_SPI, INT_0);
|
||||
_mod->init(RADIOLIB_USE_SPI, RADIOLIB_INT_0);
|
||||
|
||||
// try to find the CC1101 chip
|
||||
uint8_t i = 0;
|
||||
|
@ -20,15 +23,15 @@ int16_t CC1101::begin(float freq, float br, float rxBw, float freqDev, int8_t po
|
|||
flagFound = true;
|
||||
} else {
|
||||
#ifdef RADIOLIB_DEBUG
|
||||
Serial.print(F("CC1101 not found! ("));
|
||||
Serial.print(i + 1);
|
||||
Serial.print(F(" of 10 tries) CC1101_REG_VERSION == "));
|
||||
RADIOLIB_DEBUG_PRINT(F("CC1101 not found! ("));
|
||||
RADIOLIB_DEBUG_PRINT(i + 1);
|
||||
RADIOLIB_DEBUG_PRINT(F(" of 10 tries) CC1101_REG_VERSION == "));
|
||||
|
||||
char buffHex[7];
|
||||
sprintf(buffHex, "0x%04X", version);
|
||||
Serial.print(buffHex);
|
||||
Serial.print(F(", expected 0x0014"));
|
||||
Serial.println();
|
||||
RADIOLIB_DEBUG_PRINT(buffHex);
|
||||
RADIOLIB_DEBUG_PRINT(F(", expected 0x0014"));
|
||||
RADIOLIB_DEBUG_PRINTLN();
|
||||
#endif
|
||||
delay(1000);
|
||||
i++;
|
||||
|
@ -36,11 +39,11 @@ int16_t CC1101::begin(float freq, float br, float rxBw, float freqDev, int8_t po
|
|||
}
|
||||
|
||||
if(!flagFound) {
|
||||
DEBUG_PRINTLN(F("No CC1101 found!"));
|
||||
RADIOLIB_DEBUG_PRINTLN(F("No CC1101 found!"));
|
||||
SPI.end();
|
||||
return(ERR_CHIP_NOT_FOUND);
|
||||
} else {
|
||||
DEBUG_PRINTLN(F("Found CC1101! (match by CC1101_REG_VERSION == 0x14)"));
|
||||
RADIOLIB_DEBUG_PRINTLN(F("Found CC1101! (match by CC1101_REG_VERSION == 0x14)"));
|
||||
}
|
||||
|
||||
// configure settings not accessible by API
|
||||
|
@ -55,26 +58,42 @@ int16_t CC1101::begin(float freq, float br, float rxBw, float freqDev, int8_t po
|
|||
return(state);
|
||||
}
|
||||
|
||||
// configure bitrate
|
||||
state = setBitRate(br);
|
||||
if(state != ERR_NONE) {
|
||||
return(state);
|
||||
}
|
||||
|
||||
// configure default RX bandwidth
|
||||
state = setRxBandwidth(rxBw);
|
||||
if(state != ERR_NONE) {
|
||||
return(state);
|
||||
}
|
||||
|
||||
// configure default frequency deviation
|
||||
state = setFrequencyDeviation(freqDev);
|
||||
if(state != ERR_NONE) {
|
||||
return(state);
|
||||
}
|
||||
|
||||
// configure default TX output power
|
||||
state = setOutputPower(power);
|
||||
if(state != ERR_NONE) {
|
||||
return(state);
|
||||
}
|
||||
|
||||
// set default packet length mode
|
||||
state = variablePacketLengthMode();
|
||||
if (state != ERR_NONE) {
|
||||
return(state);
|
||||
}
|
||||
|
||||
// configure default preamble lenght
|
||||
state = setPreambleLength(preambleLength);
|
||||
if (state != ERR_NONE) {
|
||||
return(state);
|
||||
}
|
||||
|
||||
// flush FIFOs
|
||||
SPIsendCommand(CC1101_CMD_FLUSH_RX);
|
||||
SPIsendCommand(CC1101_CMD_FLUSH_TX);
|
||||
|
@ -162,7 +181,7 @@ int16_t CC1101::receiveDirect() {
|
|||
int16_t CC1101::packetMode() {
|
||||
int16_t state = SPIsetRegValue(CC1101_REG_PKTCTRL1, CC1101_CRC_AUTOFLUSH_OFF | CC1101_APPEND_STATUS_ON | CC1101_ADR_CHK_NONE, 3, 0);
|
||||
state |= SPIsetRegValue(CC1101_REG_PKTCTRL0, CC1101_WHITE_DATA_OFF | CC1101_PKT_FORMAT_NORMAL, 6, 4);
|
||||
state |= SPIsetRegValue(CC1101_REG_PKTCTRL0, CC1101_CRC_ON | CC1101_LENGTH_CONFIG_VARIABLE, 2, 0);
|
||||
state |= SPIsetRegValue(CC1101_REG_PKTCTRL0, CC1101_CRC_ON | _packetLengthConfig, 2, 0);
|
||||
return(state);
|
||||
}
|
||||
|
||||
|
@ -192,8 +211,10 @@ int16_t CC1101::startTransmit(uint8_t* data, size_t len, uint8_t addr) {
|
|||
return(state);
|
||||
}
|
||||
|
||||
// write packet length
|
||||
SPIwriteRegister(CC1101_REG_FIFO, len);
|
||||
// optionally write packet length
|
||||
if (_packetLengthConfig == CC1101_LENGTH_CONFIG_VARIABLE) {
|
||||
SPIwriteRegister(CC1101_REG_FIFO, len);
|
||||
}
|
||||
|
||||
// check address filtering
|
||||
uint8_t filter = SPIgetRegValue(CC1101_REG_PKTCTRL1, 1, 0);
|
||||
|
@ -428,13 +449,74 @@ int16_t CC1101::setOutputPower(int8_t power) {
|
|||
return(SPIsetRegValue(CC1101_REG_PATABLE, powerRaw));
|
||||
}
|
||||
|
||||
int16_t CC1101::setSyncWord(uint8_t syncH, uint8_t syncL) {
|
||||
// set sync word
|
||||
int16_t state = SPIsetRegValue(CC1101_REG_SYNC1, syncH);
|
||||
state |= SPIsetRegValue(CC1101_REG_SYNC0, syncL);
|
||||
return(state);
|
||||
int16_t CC1101::setSyncWord(uint8_t* syncWord, uint8_t len, uint8_t maxErrBits) {
|
||||
if((maxErrBits > 1) || (len > 2)) {
|
||||
return(ERR_INVALID_SYNC_WORD);
|
||||
}
|
||||
|
||||
// sync word must not contain value 0x00
|
||||
for(uint8_t i = 0; i < len; i++) {
|
||||
if(syncWord[i] == 0x00) {
|
||||
return(ERR_INVALID_SYNC_WORD);
|
||||
}
|
||||
}
|
||||
|
||||
_syncWordLength = len;
|
||||
|
||||
// enable sync word filtering
|
||||
int16_t state = enableSyncWordFiltering(maxErrBits);
|
||||
if (state != ERR_NONE) {
|
||||
return(state);
|
||||
}
|
||||
|
||||
// set sync word register
|
||||
_mod->SPIwriteRegisterBurst(CC1101_REG_SYNC1, syncWord, len);
|
||||
|
||||
return(ERR_NONE);
|
||||
}
|
||||
|
||||
int16_t CC1101::setSyncWord(uint8_t syncH, uint8_t syncL, uint8_t maxErrBits) {
|
||||
uint8_t syncWord[] = { syncH, syncL };
|
||||
return(setSyncWord(syncWord, sizeof(syncWord), maxErrBits));
|
||||
}
|
||||
|
||||
int16_t CC1101::setPreambleLength(uint8_t preambleLength) {
|
||||
// check allowed values
|
||||
uint8_t value;
|
||||
switch(preambleLength){
|
||||
case 2:
|
||||
value = CC1101_NUM_PREAMBLE_2;
|
||||
break;
|
||||
case 3:
|
||||
value = CC1101_NUM_PREAMBLE_3;
|
||||
break;
|
||||
case 4:
|
||||
value = CC1101_NUM_PREAMBLE_4;
|
||||
break;
|
||||
case 6:
|
||||
value = CC1101_NUM_PREAMBLE_6;
|
||||
break;
|
||||
case 8:
|
||||
value = CC1101_NUM_PREAMBLE_8;
|
||||
break;
|
||||
case 12:
|
||||
value = CC1101_NUM_PREAMBLE_12;
|
||||
break;
|
||||
case 16:
|
||||
value = CC1101_NUM_PREAMBLE_16;
|
||||
break;
|
||||
case 24:
|
||||
value = CC1101_NUM_PREAMBLE_24;
|
||||
break;
|
||||
default:
|
||||
return(ERR_INVALID_PREAMBLE_LENGTH);
|
||||
}
|
||||
|
||||
|
||||
return SPIsetRegValue(CC1101_REG_MDMCFG1, value, 6, 4);
|
||||
}
|
||||
|
||||
|
||||
int16_t CC1101::setNodeAddress(uint8_t nodeAddr, uint8_t numBroadcastAddrs) {
|
||||
if(!(numBroadcastAddrs > 0) && (numBroadcastAddrs <= 2)) {
|
||||
return(ERR_INVALID_NUM_BROAD_ADDRS);
|
||||
|
@ -477,13 +559,96 @@ uint8_t CC1101::getLQI() {
|
|||
|
||||
size_t CC1101::getPacketLength(bool update) {
|
||||
if(!_packetLengthQueried && update) {
|
||||
_packetLength = _mod->SPIreadRegister(CC1101_REG_FIFO);
|
||||
if (_packetLengthConfig == CC1101_LENGTH_CONFIG_VARIABLE) {
|
||||
_packetLength = _mod->SPIreadRegister(CC1101_REG_FIFO);
|
||||
} else {
|
||||
_packetLength = _mod->SPIreadRegister(CC1101_REG_PKTLEN);
|
||||
}
|
||||
|
||||
_packetLengthQueried = true;
|
||||
}
|
||||
|
||||
return(_packetLength);
|
||||
}
|
||||
|
||||
int16_t CC1101::fixedPacketLengthMode(uint8_t len) {
|
||||
return(setPacketMode(CC1101_LENGTH_CONFIG_FIXED, len));
|
||||
}
|
||||
|
||||
int16_t CC1101::variablePacketLengthMode(uint8_t maxLen) {
|
||||
return(setPacketMode(CC1101_LENGTH_CONFIG_VARIABLE, maxLen));
|
||||
}
|
||||
|
||||
int16_t CC1101::enableSyncWordFiltering(uint8_t maxErrBits) {
|
||||
if (maxErrBits > 1) {
|
||||
return(ERR_INVALID_SYNC_WORD);
|
||||
}
|
||||
|
||||
if (maxErrBits == 0) {
|
||||
if (_syncWordLength == 1) {
|
||||
// in 16 bit sync word, expect all 16 bits
|
||||
return(SPIsetRegValue(CC1101_REG_MDMCFG2, CC1101_SYNC_MODE_16_16, 2, 0));
|
||||
} else {
|
||||
// there's no 32 of 32 case, so we resort to 30 of 32 bits required
|
||||
return(SPIsetRegValue(CC1101_REG_MDMCFG2, CC1101_SYNC_MODE_30_32, 2, 0));
|
||||
}
|
||||
}
|
||||
|
||||
if (maxErrBits == 1) {
|
||||
if (_syncWordLength == 1) {
|
||||
// in 16 bit sync word, expect at least 15 bits
|
||||
return(SPIsetRegValue(CC1101_REG_MDMCFG2, CC1101_SYNC_MODE_15_16, 2, 0));
|
||||
} else {
|
||||
// in 32 bits sync word (16 + 16), expect 30 of 32 to match
|
||||
return(SPIsetRegValue(CC1101_REG_MDMCFG2, CC1101_SYNC_MODE_30_32, 2, 0));
|
||||
}
|
||||
}
|
||||
|
||||
return(ERR_UNKNOWN);
|
||||
}
|
||||
|
||||
int16_t CC1101::disableSyncWordFiltering() {
|
||||
return(SPIsetRegValue(CC1101_REG_MDMCFG2, CC1101_SYNC_MODE_NONE, 2, 0));
|
||||
}
|
||||
|
||||
int16_t CC1101::setCrcFiltering(bool crcOn) {
|
||||
if (crcOn == true) {
|
||||
return(SPIsetRegValue(CC1101_REG_PKTCTRL0, CC1101_CRC_ON, 2, 2));
|
||||
} else {
|
||||
return(SPIsetRegValue(CC1101_REG_PKTCTRL0, CC1101_CRC_OFF, 2, 2));
|
||||
}
|
||||
}
|
||||
|
||||
int16_t CC1101::setPromiscuousMode(bool promiscuous) {
|
||||
int16_t state = ERR_NONE;
|
||||
|
||||
if (_promiscuous == promiscuous) {
|
||||
return(state);
|
||||
}
|
||||
|
||||
if (promiscuous == true) {
|
||||
// disable preamble and sync word filtering and insertion
|
||||
state = disableSyncWordFiltering();
|
||||
if (state != ERR_NONE) {
|
||||
return(state);
|
||||
}
|
||||
|
||||
// disable CRC filtering
|
||||
state = setCrcFiltering(false);
|
||||
} else {
|
||||
// enable preamble and sync word filtering and insertion
|
||||
state = enableSyncWordFiltering();
|
||||
if (state != ERR_NONE) {
|
||||
return(state);
|
||||
}
|
||||
|
||||
// enable CRC filtering
|
||||
state = setCrcFiltering(true);
|
||||
}
|
||||
|
||||
return(state);
|
||||
}
|
||||
|
||||
int16_t CC1101::config() {
|
||||
// enable automatic frequency synthesizer calibration
|
||||
int16_t state = SPIsetRegValue(CC1101_REG_MCSM0, CC1101_FS_AUTOCAL_IDLE_TO_RXTX, 5, 4);
|
||||
|
@ -536,6 +701,29 @@ void CC1101::getExpMant(float target, uint16_t mantOffset, uint8_t divExp, uint8
|
|||
}
|
||||
}
|
||||
|
||||
int16_t CC1101::setPacketMode(uint8_t mode, uint8_t len) {
|
||||
// check length
|
||||
if (len > CC1101_MAX_PACKET_LENGTH) {
|
||||
return(ERR_PACKET_TOO_LONG);
|
||||
}
|
||||
|
||||
// set to fixed packet length
|
||||
int16_t state = _mod->SPIsetRegValue(CC1101_REG_PKTCTRL0, mode, 7, 7);
|
||||
if (state != ERR_NONE) {
|
||||
return(state);
|
||||
}
|
||||
|
||||
// set length to register
|
||||
state = _mod->SPIsetRegValue(CC1101_REG_PKTLEN, len);
|
||||
if (state != ERR_NONE) {
|
||||
return(state);
|
||||
}
|
||||
|
||||
// update the cached value
|
||||
_packetLengthConfig = mode;
|
||||
return(state);
|
||||
}
|
||||
|
||||
int16_t CC1101::SPIgetRegValue(uint8_t reg, uint8_t msb, uint8_t lsb) {
|
||||
// status registers require special command
|
||||
if(reg > CC1101_REG_TEST0) {
|
|
@ -1,10 +1,10 @@
|
|||
#ifndef _RADIOLIB_CC1101_H
|
||||
#define _RADIOLIB_CC1101_H
|
||||
|
||||
#include "TypeDef.h"
|
||||
#include "Module.h"
|
||||
#include "../../TypeDef.h"
|
||||
#include "../../Module.h"
|
||||
|
||||
#include "../protocols/PhysicalLayer.h"
|
||||
#include "../../protocols/PhysicalLayer/PhysicalLayer.h"
|
||||
|
||||
// CC1101 physical layer properties
|
||||
#define CC1101_CRYSTAL_FREQ 26.0
|
||||
|
@ -237,7 +237,7 @@
|
|||
#define CC1101_MOD_FORMAT_MFSK 0b01110000 // 6 4 MFSK - only for data rates above 26 kBaud
|
||||
#define CC1101_MANCHESTER_EN_OFF 0b00000000 // 3 3 Manchester encoding: disabled (default)
|
||||
#define CC1101_MANCHESTER_EN_ON 0b00001000 // 3 3 enabled
|
||||
#define CC1101_SYNC_MODE_NONE 0b00000000 // 2 0 synchronization: no preamble sync
|
||||
#define CC1101_SYNC_MODE_NONE 0b00000000 // 2 0 synchronization: no preamble/sync
|
||||
#define CC1101_SYNC_MODE_15_16 0b00000001 // 2 0 15/16 sync word bits
|
||||
#define CC1101_SYNC_MODE_16_16 0b00000010 // 2 0 16/16 sync word bits (default)
|
||||
#define CC1101_SYNC_MODE_30_32 0b00000011 // 2 0 30/32 sync word bits
|
||||
|
@ -530,9 +530,11 @@ class CC1101: public PhysicalLayer {
|
|||
|
||||
\param power Output power in dBm. Defaults to 0 dBm.
|
||||
|
||||
\param preambleLength Preamble Length in bytes. Defaults to 4 bytes.
|
||||
|
||||
\returns \ref status_codes
|
||||
*/
|
||||
int16_t begin(float freq = 868.0, float br = 4.8, float rxBw = 325.0, float freqDev = 48.0, int8_t power = 0);
|
||||
int16_t begin(float freq = 868.0, float br = 4.8, float rxBw = 325.0, float freqDev = 48.0, int8_t power = 0, uint8_t preambleLength = 4);
|
||||
|
||||
/*!
|
||||
\brief Blocking binary transmit method.
|
||||
|
@ -694,9 +696,33 @@ class CC1101: public PhysicalLayer {
|
|||
|
||||
\param syncL LSB of the sync word.
|
||||
|
||||
\param maxErrBits Maximum allowed number of bit errors in received sync word. Defaults to 0.
|
||||
|
||||
\returns \ref status_codes
|
||||
*/
|
||||
int16_t setSyncWord(uint8_t syncH, uint8_t syncL);
|
||||
int16_t setSyncWord(uint8_t syncH, uint8_t syncL, uint8_t maxErrBits = 0);
|
||||
|
||||
/*!
|
||||
\brief Sets 1 or 2 bytes of sync word.
|
||||
|
||||
\param syncWord Pointer to the array of sync word bytes.
|
||||
|
||||
\param len Sync word length in bytes.
|
||||
|
||||
\param maxErrBits Maximum allowed number of bit errors in received sync word. Defaults to 0.
|
||||
|
||||
\returns \ref status_codes
|
||||
*/
|
||||
int16_t setSyncWord(uint8_t* syncWord, uint8_t len, uint8_t maxErrBits = 0);
|
||||
|
||||
/*!
|
||||
\brief Sets preamble length.
|
||||
|
||||
\param preambleLength Preamble length to be set (in bytes), allowed values: 2, 3, 4, 6, 8, 12, 16, 24
|
||||
|
||||
\returns \ref status_codes
|
||||
*/
|
||||
int16_t setPreambleLength(uint8_t preambleLength);
|
||||
|
||||
/*!
|
||||
\brief Sets node and broadcast addresses. Calling this method will also enable address filtering.
|
||||
|
@ -739,7 +765,61 @@ class CC1101: public PhysicalLayer {
|
|||
*/
|
||||
size_t getPacketLength(bool update = true);
|
||||
|
||||
/*!
|
||||
\brief Set modem in fixed packet length mode.
|
||||
|
||||
\param len Packet length.
|
||||
|
||||
\returns \ref status_codes
|
||||
*/
|
||||
int16_t fixedPacketLengthMode(uint8_t len = CC1101_MAX_PACKET_LENGTH);
|
||||
|
||||
/*!
|
||||
\brief Set modem in variable packet length mode.
|
||||
|
||||
\param len Maximum packet length.
|
||||
|
||||
\returns \ref status_codes
|
||||
*/
|
||||
int16_t variablePacketLengthMode(uint8_t maxLen = CC1101_MAX_PACKET_LENGTH);
|
||||
|
||||
/*!
|
||||
\brief Enable sync word filtering and generation.
|
||||
|
||||
\param numBits Sync word length in bits.
|
||||
|
||||
\returns \ref status_codes
|
||||
*/
|
||||
int16_t enableSyncWordFiltering(uint8_t maxErrBits = 0);
|
||||
|
||||
/*!
|
||||
\brief Disable preamble and sync word filtering and generation.
|
||||
|
||||
\returns \ref status_codes
|
||||
*/
|
||||
int16_t disableSyncWordFiltering();
|
||||
|
||||
/*!
|
||||
\brief Enable CRC filtering and generation.
|
||||
|
||||
\param crcOn Set or unset promiscuous mode.
|
||||
|
||||
\returns \ref status_codes
|
||||
*/
|
||||
int16_t setCrcFiltering(bool crcOn = true);
|
||||
|
||||
/*!
|
||||
\brief Set modem in "sniff" mode: no packet filtering (e.g., no preamble, sync word, address, CRC).
|
||||
|
||||
\param promiscuous Set or unset promiscuous mode.
|
||||
|
||||
\returns \ref status_codes
|
||||
*/
|
||||
int16_t setPromiscuousMode(bool promiscuous = true);
|
||||
|
||||
#ifndef RADIOLIB_GODMODE
|
||||
private:
|
||||
#endif
|
||||
Module* _mod;
|
||||
|
||||
float _freq;
|
||||
|
@ -748,10 +828,16 @@ class CC1101: public PhysicalLayer {
|
|||
|
||||
size_t _packetLength;
|
||||
bool _packetLengthQueried;
|
||||
uint8_t _packetLengthConfig;
|
||||
|
||||
bool _promiscuous;
|
||||
|
||||
uint8_t _syncWordLength;
|
||||
|
||||
int16_t config();
|
||||
int16_t directMode();
|
||||
void getExpMant(float target, uint16_t mantOffset, uint8_t divExp, uint8_t expMax, uint8_t& exp, uint8_t& mant);
|
||||
int16_t setPacketMode(uint8_t mode, uint8_t len);
|
||||
|
||||
// SPI read overrides to set bit for burst write and status registers access
|
||||
int16_t SPIgetRegValue(uint8_t reg, uint8_t msb = 7, uint8_t lsb = 0);
|
|
@ -9,7 +9,7 @@ int16_t ESP8266::begin(long speed) {
|
|||
// set module properties
|
||||
_mod->AtLineFeed = "\r\n";
|
||||
_mod->baudrate = speed;
|
||||
_mod->init(USE_UART, INT_NONE);
|
||||
_mod->init(RADIOLIB_USE_UART, RADIOLIB_INT_NONE);
|
||||
|
||||
// empty UART buffer (garbage data)
|
||||
_mod->ATemptyBuffer();
|
||||
|
@ -52,8 +52,12 @@ int16_t ESP8266::join(const char* ssid, const char* password) {
|
|||
|
||||
// build AT command
|
||||
const char* atStr = "AT+CWJAP_CUR=\"";
|
||||
uint8_t cmdLen = strlen(atStr) + strlen(ssid) + strlen(password) + 4;
|
||||
char* cmd = new char[cmdLen + 1];
|
||||
#ifdef RADIOLIB_STATIC_ONLY
|
||||
char cmd[RADIOLIB_STATIC_ARRAY_SIZE];
|
||||
#else
|
||||
uint8_t cmdLen = strlen(atStr) + strlen(ssid) + strlen(password) + 4;
|
||||
char* cmd = new char[cmdLen + 1];
|
||||
#endif
|
||||
strcpy(cmd, atStr);
|
||||
strcat(cmd, ssid);
|
||||
strcat(cmd, "\",\"");
|
||||
|
@ -62,7 +66,9 @@ int16_t ESP8266::join(const char* ssid, const char* password) {
|
|||
|
||||
// send command
|
||||
bool res = _mod->ATsendCommand(cmd);
|
||||
delete[] cmd;
|
||||
#ifndef RADIOLIB_STATIC_ONLY
|
||||
delete[] cmd;
|
||||
#endif
|
||||
if(!res) {
|
||||
return(ERR_AT_FAILED);
|
||||
}
|
||||
|
@ -87,7 +93,11 @@ int16_t ESP8266::openTransportConnection(const char* host, const char* protocol,
|
|||
if((strcmp(protocol, "TCP") == 0) && (tcpKeepAlive > 0)) {
|
||||
cmdLen += strlen(tcpKeepAliveStr) + 1;
|
||||
}
|
||||
char* cmd = new char[cmdLen + 1];
|
||||
#ifdef RADIOLIB_STATIC_ONLY
|
||||
char cmd[RADIOLIB_STATIC_ARRAY_SIZE];
|
||||
#else
|
||||
char* cmd = new char[cmdLen + 1];
|
||||
#endif
|
||||
strcpy(cmd, atStr);
|
||||
strcat(cmd, protocol);
|
||||
strcat(cmd, "\",\"");
|
||||
|
@ -101,7 +111,9 @@ int16_t ESP8266::openTransportConnection(const char* host, const char* protocol,
|
|||
|
||||
// send command
|
||||
bool res = _mod->ATsendCommand(cmd);
|
||||
delete[] cmd;
|
||||
#ifndef RADIOLIB_STATIC_ONLY
|
||||
delete[] cmd;
|
||||
#endif
|
||||
if(!res) {
|
||||
return(ERR_AT_FAILED);
|
||||
}
|
||||
|
@ -122,13 +134,19 @@ int16_t ESP8266::send(const char* data) {
|
|||
char lenStr[8];
|
||||
itoa(strlen(data), lenStr, 10);
|
||||
const char* atStr = "AT+CIPSEND=";
|
||||
char* cmd = new char[strlen(atStr) + strlen(lenStr) + 1];
|
||||
#ifdef RADIOLIB_STATIC_ONLY
|
||||
char cmd[RADIOLIB_STATIC_ARRAY_SIZE];
|
||||
#else
|
||||
char* cmd = new char[strlen(atStr) + strlen(lenStr) + 1];
|
||||
#endif
|
||||
strcpy(cmd, atStr);
|
||||
strcat(cmd, lenStr);
|
||||
|
||||
// send command
|
||||
bool res = _mod->ATsendCommand(cmd);
|
||||
delete[] cmd;
|
||||
#ifndef RADIOLIB_STATIC_ONLY
|
||||
delete[] cmd;
|
||||
#endif
|
||||
if(!res) {
|
||||
return(ERR_AT_FAILED);
|
||||
}
|
||||
|
@ -146,13 +164,19 @@ int16_t ESP8266::send(uint8_t* data, uint32_t len) {
|
|||
char lenStr[8];
|
||||
itoa(len, lenStr, 10);
|
||||
const char atStr[] = "AT+CIPSEND=";
|
||||
char* cmd = new char[strlen(atStr) + strlen(lenStr) + 1];
|
||||
#ifdef RADIOLIB_STATIC_ONLY
|
||||
char cmd[RADIOLIB_STATIC_ARRAY_SIZE];
|
||||
#else
|
||||
char* cmd = new char[strlen(atStr) + strlen(lenStr) + 1];
|
||||
#endif
|
||||
strcpy(cmd, atStr);
|
||||
strcat(cmd, lenStr);
|
||||
|
||||
// send command
|
||||
bool res = _mod->ATsendCommand(cmd);
|
||||
delete[] cmd;
|
||||
#ifndef RADIOLIB_STATIC_ONLY
|
||||
delete[] cmd;
|
||||
#endif
|
||||
if(!res) {
|
||||
return(ERR_AT_FAILED);
|
||||
}
|
||||
|
@ -173,7 +197,7 @@ size_t ESP8266::receive(uint8_t* data, size_t len, uint32_t timeout) {
|
|||
while((millis() - start < timeout) && (i < len)) {
|
||||
while(_mod->ModuleSerial->available() > 0) {
|
||||
uint8_t b = _mod->ModuleSerial->read();
|
||||
DEBUG_PRINT(b);
|
||||
RADIOLIB_DEBUG_PRINT(b);
|
||||
data[i] = b;
|
||||
i++;
|
||||
}
|
|
@ -1,9 +1,9 @@
|
|||
#if !defined(_RADIOLIB_ESP8266_H) && !defined(ESP8266)
|
||||
#define _RADIOLIB_ESP8266_H
|
||||
|
||||
#include "Module.h"
|
||||
#include "../../Module.h"
|
||||
|
||||
#include "../protocols/TransportLayer.h"
|
||||
#include "../../protocols/TransportLayer/TransportLayer.h"
|
||||
|
||||
/*!
|
||||
\class ESP8266
|
||||
|
@ -54,7 +54,9 @@ class ESP8266: public TransportLayer {
|
|||
size_t receive(uint8_t* data, size_t len, uint32_t timeout = 10000);
|
||||
size_t getNumBytes(uint32_t timeout = 10000, size_t minBytes = 10);
|
||||
|
||||
#ifndef RADIOLIB_GODMODE
|
||||
private:
|
||||
#endif
|
||||
Module* _mod;
|
||||
};
|
||||
|
|
@ -7,5 +7,5 @@ HC05::HC05(Module* mod) : ISerial(mod) {
|
|||
void HC05::begin(long speed) {
|
||||
// set module properties
|
||||
_mod->baudrate = speed;
|
||||
_mod->init(USE_UART, INT_NONE);
|
||||
_mod->init(RADIOLIB_USE_UART, RADIOLIB_INT_NONE);
|
||||
}
|
|
@ -1,7 +1,7 @@
|
|||
#ifndef _RADIOLIB_HC05_H
|
||||
#define _RADIOLIB_HC05_H
|
||||
|
||||
#include "ISerial.h"
|
||||
#include "../../ISerial.h"
|
||||
|
||||
/*!
|
||||
\class HC05
|
|
@ -8,5 +8,5 @@ void JDY08::begin(long speed) {
|
|||
// set module properties
|
||||
_mod->AtLineFeed = "";
|
||||
_mod->baudrate = speed;
|
||||
_mod->init(USE_UART, INT_NONE);
|
||||
_mod->init(RADIOLIB_USE_UART, RADIOLIB_INT_NONE);
|
||||
}
|
|
@ -1,7 +1,7 @@
|
|||
#ifndef _RADIOLIB_JDY08_H
|
||||
#define _RADIOLIB_JDY08_H
|
||||
|
||||
#include "ISerial.h"
|
||||
#include "../../ISerial.h"
|
||||
|
||||
/*!
|
||||
\class JDY08
|
|
@ -3,12 +3,18 @@
|
|||
RF69::RF69(Module* module) : PhysicalLayer(RF69_CRYSTAL_FREQ, RF69_DIV_EXPONENT, RF69_MAX_PACKET_LENGTH) {
|
||||
_mod = module;
|
||||
_tempOffset = 0;
|
||||
|
||||
_packetLengthQueried = false;
|
||||
_packetLengthConfig = RF69_PACKET_FORMAT_VARIABLE;
|
||||
|
||||
_promiscuous = false;
|
||||
|
||||
_syncWordLength = 2;
|
||||
}
|
||||
|
||||
int16_t RF69::begin(float freq, float br, float rxBw, float freqDev, int8_t power) {
|
||||
// set module properties
|
||||
_mod->init(USE_SPI, INT_0);
|
||||
_mod->init(RADIOLIB_USE_SPI, RADIOLIB_INT_0);
|
||||
|
||||
// try to find the RF69 chip
|
||||
uint8_t i = 0;
|
||||
|
@ -19,15 +25,15 @@ int16_t RF69::begin(float freq, float br, float rxBw, float freqDev, int8_t powe
|
|||
flagFound = true;
|
||||
} else {
|
||||
#ifdef RADIOLIB_DEBUG
|
||||
Serial.print(F("RF69 not found! ("));
|
||||
Serial.print(i + 1);
|
||||
Serial.print(F(" of 10 tries) RF69_REG_VERSION == "));
|
||||
RADIOLIB_DEBUG_PRINT(F("RF69 not found! ("));
|
||||
RADIOLIB_DEBUG_PRINT(i + 1);
|
||||
RADIOLIB_DEBUG_PRINT(F(" of 10 tries) RF69_REG_VERSION == "));
|
||||
|
||||
char buffHex[7];
|
||||
sprintf(buffHex, "0x%04X", version);
|
||||
Serial.print(buffHex);
|
||||
Serial.print(F(", expected 0x0024"));
|
||||
Serial.println();
|
||||
RADIOLIB_DEBUG_PRINT(buffHex);
|
||||
RADIOLIB_DEBUG_PRINT(F(", expected 0x0024"));
|
||||
RADIOLIB_DEBUG_PRINTLN();
|
||||
#endif
|
||||
delay(1000);
|
||||
i++;
|
||||
|
@ -35,11 +41,11 @@ int16_t RF69::begin(float freq, float br, float rxBw, float freqDev, int8_t powe
|
|||
}
|
||||
|
||||
if(!flagFound) {
|
||||
DEBUG_PRINTLN(F("No RF69 found!"));
|
||||
RADIOLIB_DEBUG_PRINTLN(F("No RF69 found!"));
|
||||
SPI.end();
|
||||
return(ERR_CHIP_NOT_FOUND);
|
||||
} else {
|
||||
DEBUG_PRINTLN(F("Found RF69! (match by RF69_REG_VERSION == 0x24)"));
|
||||
RADIOLIB_DEBUG_PRINTLN(F("Found RF69! (match by RF69_REG_VERSION == 0x24)"));
|
||||
}
|
||||
|
||||
// configure settings not accessible by API
|
||||
|
@ -54,30 +60,40 @@ int16_t RF69::begin(float freq, float br, float rxBw, float freqDev, int8_t powe
|
|||
return(state);
|
||||
}
|
||||
|
||||
// configure bitrate
|
||||
_rxBw = 125.0;
|
||||
state = setBitRate(br);
|
||||
if(state != ERR_NONE) {
|
||||
return(state);
|
||||
}
|
||||
|
||||
// configure default RX bandwidth
|
||||
state = setRxBandwidth(rxBw);
|
||||
if(state != ERR_NONE) {
|
||||
return(state);
|
||||
}
|
||||
|
||||
// configure default frequency deviation
|
||||
state = setFrequencyDeviation(freqDev);
|
||||
if(state != ERR_NONE) {
|
||||
return(state);
|
||||
}
|
||||
|
||||
// configure default TX output power
|
||||
state = setOutputPower(power);
|
||||
if(state != ERR_NONE) {
|
||||
return(state);
|
||||
}
|
||||
|
||||
// set default packet length mode
|
||||
state = variablePacketLengthMode();
|
||||
if (state != ERR_NONE) {
|
||||
return(state);
|
||||
}
|
||||
|
||||
// default sync word values 0x2D01 is the same as the default in LowPowerLab RFM69 library
|
||||
uint8_t syncWord[] = {0x2D, 0x01};
|
||||
state = setSyncWord(syncWord, 2);
|
||||
state = setSyncWord(syncWord, sizeof(syncWord));
|
||||
if(state != ERR_NONE) {
|
||||
return(state);
|
||||
}
|
||||
|
@ -250,6 +266,11 @@ int16_t RF69::startTransmit(uint8_t* data, size_t len, uint8_t addr) {
|
|||
// set packet length
|
||||
_mod->SPIwriteRegister(RF69_REG_FIFO, len);
|
||||
|
||||
// optionally write packet length
|
||||
if (_packetLengthConfig == RF69_PACKET_FORMAT_VARIABLE) {
|
||||
_mod->SPIwriteRegister(RF69_REG_FIFO, len);
|
||||
}
|
||||
|
||||
// check address filtering
|
||||
uint8_t filter = _mod->SPIgetRegValue(RF69_REG_PACKET_CONFIG_1, 2, 1);
|
||||
if((filter == RF69_ADDRESS_FILTERING_NODE) || (filter == RF69_ADDRESS_FILTERING_NODE_BROADCAST)) {
|
||||
|
@ -268,6 +289,12 @@ int16_t RF69::startTransmit(uint8_t* data, size_t len, uint8_t addr) {
|
|||
}
|
||||
|
||||
int16_t RF69::readData(uint8_t* data, size_t len) {
|
||||
// set mdoe to standby
|
||||
int16_t state = standby();
|
||||
if(state != ERR_NONE) {
|
||||
return(state);
|
||||
}
|
||||
|
||||
// get packet length
|
||||
size_t length = len;
|
||||
if(len == RF69_MAX_PACKET_LENGTH) {
|
||||
|
@ -490,13 +517,14 @@ int16_t RF69::setSyncWord(uint8_t* syncWord, size_t len, uint8_t maxErrBits) {
|
|||
}
|
||||
}
|
||||
|
||||
// enable sync word recognition
|
||||
int16_t state = _mod->SPIsetRegValue(RF69_REG_SYNC_CONFIG, RF69_SYNC_ON | RF69_FIFO_FILL_CONDITION_SYNC | (len - 1) << 3 | maxErrBits, 7, 0);
|
||||
if(state != ERR_NONE) {
|
||||
_syncWordLength = len;
|
||||
|
||||
int16_t state = enableSyncWordFiltering(maxErrBits);
|
||||
if (state != ERR_NONE) {
|
||||
return(state);
|
||||
}
|
||||
|
||||
// set sync word
|
||||
// set sync word register
|
||||
_mod->SPIwriteRegisterBurst(RF69_REG_SYNC_VALUE_1, syncWord, len);
|
||||
return(ERR_NONE);
|
||||
}
|
||||
|
@ -563,13 +591,90 @@ int16_t RF69::getTemperature() {
|
|||
|
||||
size_t RF69::getPacketLength(bool update) {
|
||||
if(!_packetLengthQueried && update) {
|
||||
_packetLength = _mod->SPIreadRegister(RF69_REG_FIFO);
|
||||
if (_packetLengthConfig == RF69_PACKET_FORMAT_VARIABLE) {
|
||||
_packetLength = _mod->SPIreadRegister(RF69_REG_FIFO);
|
||||
} else {
|
||||
_packetLength = _mod->SPIreadRegister(RF69_REG_PAYLOAD_LENGTH);
|
||||
}
|
||||
_packetLengthQueried = true;
|
||||
}
|
||||
|
||||
return(_packetLength);
|
||||
}
|
||||
|
||||
int16_t RF69::fixedPacketLengthMode(uint8_t len) {
|
||||
return(setPacketMode(RF69_PACKET_FORMAT_FIXED, len));
|
||||
}
|
||||
|
||||
int16_t RF69::variablePacketLengthMode(uint8_t maxLen) {
|
||||
return(setPacketMode(RF69_PACKET_FORMAT_VARIABLE, maxLen));
|
||||
}
|
||||
|
||||
int16_t RF69::enableSyncWordFiltering(uint8_t maxErrBits) {
|
||||
// enable sync word recognition
|
||||
int16_t state = _mod->SPIsetRegValue(RF69_REG_SYNC_CONFIG, RF69_SYNC_ON | RF69_FIFO_FILL_CONDITION_SYNC | (_syncWordLength - 1) << 3 | maxErrBits, 7, 0);
|
||||
if(state != ERR_NONE) {
|
||||
return(state);
|
||||
}
|
||||
|
||||
return(state);
|
||||
}
|
||||
|
||||
int16_t RF69::disableSyncWordFiltering() {
|
||||
// disable preamble detection and generation
|
||||
int16_t state = _mod->SPIsetRegValue(RF69_REG_PREAMBLE_LSB, 0, 7, 0);
|
||||
state |= _mod->SPIsetRegValue(RF69_REG_PREAMBLE_MSB, 0, 7, 0);
|
||||
if (state != ERR_NONE) {
|
||||
return(state);
|
||||
}
|
||||
|
||||
// disable sync word detection and generation
|
||||
state = _mod->SPIsetRegValue(RF69_REG_SYNC_CONFIG, RF69_SYNC_OFF | RF69_FIFO_FILL_CONDITION, 7, 6);
|
||||
if (state != ERR_NONE) {
|
||||
return(state);
|
||||
}
|
||||
|
||||
return(state);
|
||||
}
|
||||
|
||||
int16_t RF69::setCrcFiltering(bool crcOn) {
|
||||
if (crcOn == true) {
|
||||
return(_mod->SPIsetRegValue(RF69_REG_PACKET_CONFIG_1, RF69_CRC_ON, 4, 4));
|
||||
} else {
|
||||
return(_mod->SPIsetRegValue(RF69_REG_PACKET_CONFIG_1, RF69_CRC_OFF, 4, 4));
|
||||
}
|
||||
}
|
||||
|
||||
int16_t RF69::setPromiscuousMode(bool promiscuous) {
|
||||
int16_t state = ERR_NONE;
|
||||
|
||||
if (_promiscuous == promiscuous) {
|
||||
return(state);
|
||||
}
|
||||
|
||||
if (promiscuous == true) {
|
||||
// disable preamble and sync word filtering and insertion
|
||||
state = disableSyncWordFiltering();
|
||||
if (state != ERR_NONE) {
|
||||
return(state);
|
||||
}
|
||||
|
||||
// disable CRC filtering
|
||||
state = setCrcFiltering(false);
|
||||
} else {
|
||||
// enable preamble and sync word filtering and insertion
|
||||
state = enableSyncWordFiltering();
|
||||
if (state != ERR_NONE) {
|
||||
return(state);
|
||||
}
|
||||
|
||||
// enable CRC filtering
|
||||
state = setCrcFiltering(true);
|
||||
}
|
||||
|
||||
return(state);
|
||||
}
|
||||
|
||||
int16_t RF69::config() {
|
||||
int16_t state = ERR_NONE;
|
||||
|
||||
|
@ -649,6 +754,29 @@ int16_t RF69::config() {
|
|||
return(ERR_NONE);
|
||||
}
|
||||
|
||||
int16_t RF69::setPacketMode(uint8_t mode, uint8_t len) {
|
||||
// check length
|
||||
if (len > RF69_MAX_PACKET_LENGTH) {
|
||||
return(ERR_PACKET_TOO_LONG);
|
||||
}
|
||||
|
||||
// set to fixed packet length
|
||||
int16_t state = _mod->SPIsetRegValue(RF69_REG_PACKET_CONFIG_1, mode, 7, 7);
|
||||
if (state != ERR_NONE) {
|
||||
return(state);
|
||||
}
|
||||
|
||||
// set length to register
|
||||
state = _mod->SPIsetRegValue(RF69_REG_PAYLOAD_LENGTH, len);
|
||||
if (state != ERR_NONE) {
|
||||
return(state);
|
||||
}
|
||||
|
||||
// update the cached value
|
||||
_packetLengthConfig = mode;
|
||||
return(state);
|
||||
}
|
||||
|
||||
int16_t RF69::setMode(uint8_t mode) {
|
||||
return(_mod->SPIsetRegValue(RF69_REG_OP_MODE, mode, 4, 2));
|
||||
}
|
|
@ -1,10 +1,10 @@
|
|||
#ifndef _RADIOLIB_RF69_H
|
||||
#define _RADIOLIB_RF69_H
|
||||
|
||||
#include "TypeDef.h"
|
||||
#include "Module.h"
|
||||
#include "../../TypeDef.h"
|
||||
#include "../../Module.h"
|
||||
|
||||
#include "../protocols/PhysicalLayer.h"
|
||||
#include "../../protocols/PhysicalLayer/PhysicalLayer.h"
|
||||
|
||||
// RF69 physical layer properties
|
||||
#define RF69_CRYSTAL_FREQ 32.0
|
||||
|
@ -646,7 +646,7 @@ class RF69: public PhysicalLayer {
|
|||
int16_t setOutputPower(int8_t power);
|
||||
|
||||
/*!
|
||||
\brief Sets sync word. Up to 8 bytes can be set as snyc word.
|
||||
\brief Sets sync word. Up to 8 bytes can be set as sync word.
|
||||
|
||||
\param syncWord Pointer to the array of sync word bytes.
|
||||
|
||||
|
@ -697,7 +697,7 @@ class RF69: public PhysicalLayer {
|
|||
*/
|
||||
int16_t getTemperature();
|
||||
|
||||
/*!
|
||||
/*!
|
||||
\brief Query modem for the packet length of received payload.
|
||||
|
||||
\param update Update received packet length. Will return cached value when set to false.
|
||||
|
@ -706,7 +706,61 @@ class RF69: public PhysicalLayer {
|
|||
*/
|
||||
size_t getPacketLength(bool update = true);
|
||||
|
||||
/*!
|
||||
\brief Set modem in fixed packet length mode.
|
||||
|
||||
\param len Packet length.
|
||||
|
||||
\returns \ref status_codes
|
||||
*/
|
||||
int16_t fixedPacketLengthMode(uint8_t len = RF69_MAX_PACKET_LENGTH);
|
||||
|
||||
/*!
|
||||
\brief Set modem in variable packet length mode.
|
||||
|
||||
\param len Maximum packet length.
|
||||
|
||||
\returns \ref status_codes
|
||||
*/
|
||||
int16_t variablePacketLengthMode(uint8_t maxLen = RF69_MAX_PACKET_LENGTH);
|
||||
|
||||
/*!
|
||||
\brief Enable sync word filtering and generation.
|
||||
|
||||
\param numBits Sync word length in bits.
|
||||
|
||||
\returns \ref status_codes
|
||||
*/
|
||||
int16_t enableSyncWordFiltering(uint8_t maxErrBits = 0);
|
||||
|
||||
/*!
|
||||
\brief Disable preamble and sync word filtering and generation.
|
||||
|
||||
\returns \ref status_codes
|
||||
*/
|
||||
int16_t disableSyncWordFiltering();
|
||||
|
||||
/*!
|
||||
\brief Enable CRC filtering and generation.
|
||||
|
||||
\param crcOn Set or unset promiscuous mode.
|
||||
|
||||
\returns \ref status_codes
|
||||
*/
|
||||
int16_t setCrcFiltering(bool crcOn = true);
|
||||
|
||||
/*!
|
||||
\brief Set modem in "sniff" mode: no packet filtering (e.g., no preamble, sync word, address, CRC).
|
||||
|
||||
\param promiscuous Set or unset promiscuous mode.
|
||||
|
||||
\returns \ref status_codes
|
||||
*/
|
||||
int16_t setPromiscuousMode(bool promiscuous = true);
|
||||
|
||||
#ifndef RADIOLIB_GODMODE
|
||||
protected:
|
||||
#endif
|
||||
Module* _mod;
|
||||
|
||||
float _br;
|
||||
|
@ -715,11 +769,19 @@ class RF69: public PhysicalLayer {
|
|||
|
||||
size_t _packetLength;
|
||||
bool _packetLengthQueried;
|
||||
uint8_t _packetLengthConfig;
|
||||
|
||||
bool _promiscuous;
|
||||
|
||||
uint8_t _syncWordLength;
|
||||
|
||||
int16_t config();
|
||||
int16_t directMode();
|
||||
int16_t setPacketMode(uint8_t mode, uint8_t len);
|
||||
|
||||
#ifndef RADIOLIB_GODMODE
|
||||
private:
|
||||
#endif
|
||||
int16_t setMode(uint8_t mode);
|
||||
void clearIRQFlags();
|
||||
};
|
|
@ -1,10 +1,10 @@
|
|||
#ifndef _RADIOLIB_RFM95_H
|
||||
#define _RADIOLIB_RFM95_H
|
||||
|
||||
#include "TypeDef.h"
|
||||
#include "Module.h"
|
||||
#include "SX127x.h"
|
||||
#include "SX1278.h"
|
||||
#include "../../TypeDef.h"
|
||||
#include "../../Module.h"
|
||||
#include "../SX127x/SX127x.h"
|
||||
#include "../SX127x/SX1278.h"
|
||||
|
||||
// SX127X_REG_VERSION
|
||||
#define RFM95_CHIP_VERSION 0x11
|
||||
|
@ -16,59 +16,61 @@
|
|||
*/
|
||||
class RFM95: public SX1278 {
|
||||
public:
|
||||
|
||||
|
||||
// constructor
|
||||
|
||||
|
||||
/*!
|
||||
\brief Default constructor. Called from Arduino sketch when creating new LoRa instance.
|
||||
|
||||
|
||||
\param mod Instance of Module that will be used to communicate with the %LoRa chip.
|
||||
*/
|
||||
RFM95(Module* mod);
|
||||
|
||||
|
||||
// basic methods
|
||||
|
||||
|
||||
/*!
|
||||
\brief %LoRa modem initialization method. Must be called at least once from Arduino sketch to initialize the module.
|
||||
|
||||
|
||||
\param freq Carrier frequency in MHz. Allowed values range from 868.0 MHz to 915.0 MHz.
|
||||
|
||||
|
||||
\param bw %LoRa link bandwidth in kHz. Allowed values are 10.4, 15.6, 20.8, 31.25, 41.7, 62.5, 125, 250 and 500 kHz.
|
||||
|
||||
|
||||
\param sf %LoRa link spreading factor. Allowed values range from 6 to 12.
|
||||
|
||||
|
||||
\param cr %LoRa link coding rate denominator. Allowed values range from 5 to 8.
|
||||
|
||||
|
||||
\param syncWord %LoRa sync word. Can be used to distinguish different networks. Note that value 0x34 is reserved for LoRaWAN networks.
|
||||
|
||||
|
||||
\param power Transmission output power in dBm. Allowed values range from 2 to 17 dBm.
|
||||
|
||||
\param currentLimit Trim value for OCP (over current protection) in mA. Can be set to multiplies of 5 in range 45 to 120 mA and to multiples of 10 in range 120 to 240 mA.
|
||||
|
||||
\param currentLimit Trim value for OCP (over current protection) in mA. Can be set to multiplies of 5 in range 45 to 120 mA and to multiples of 10 in range 120 to 240 mA.
|
||||
Set to 0 to disable OCP (not recommended).
|
||||
|
||||
\param preambleLength Length of %LoRa transmission preamble in symbols. The actual preamble length is 4.25 symbols longer than the set number.
|
||||
|
||||
\param preambleLength Length of %LoRa transmission preamble in symbols. The actual preamble length is 4.25 symbols longer than the set number.
|
||||
Allowed values range from 6 to 65535.
|
||||
|
||||
|
||||
\param gain Gain of receiver LNA (low-noise amplifier). Can be set to any integer in range 1 to 6 where 1 is the highest gain.
|
||||
Set to 0 to enable automatic gain control (recommended).
|
||||
|
||||
|
||||
\returns \ref status_codes
|
||||
*/
|
||||
int16_t begin(float freq = 915.0, float bw = 125.0, uint8_t sf = 9, uint8_t cr = 7, uint8_t syncWord = SX127X_SYNC_WORD, int8_t power = 17, uint8_t currentLimit = 100, uint16_t preambleLength = 8, uint8_t gain = 0);
|
||||
|
||||
|
||||
// configuration methods
|
||||
|
||||
|
||||
/*!
|
||||
\brief Sets carrier frequency. Allowed values range from 868.0 MHz to 915.0 MHz.
|
||||
|
||||
|
||||
\param freq Carrier frequency to be set in MHz.
|
||||
|
||||
|
||||
\returns \ref status_codes
|
||||
*/
|
||||
int16_t setFrequency(float freq);
|
||||
|
||||
|
||||
#ifndef RADIOLIB_GODMODE
|
||||
private:
|
||||
|
||||
#endif
|
||||
|
||||
};
|
||||
|
||||
#endif
|
|
@ -1,10 +1,10 @@
|
|||
#ifndef _RADIOLIB_RFM96_H
|
||||
#define _RADIOLIB_RFM96_H
|
||||
|
||||
#include "TypeDef.h"
|
||||
#include "Module.h"
|
||||
#include "SX127x.h"
|
||||
#include "SX1278.h"
|
||||
#include "../../TypeDef.h"
|
||||
#include "../../Module.h"
|
||||
#include "../SX127x/SX127x.h"
|
||||
#include "../SX127x/SX1278.h"
|
||||
|
||||
// SX127X_REG_VERSION
|
||||
#define RFM9X_CHIP_VERSION 0x12 // according to datasheet, this should be 0x11, but all modules seem to have 0x12
|
||||
|
@ -16,59 +16,61 @@
|
|||
*/
|
||||
class RFM96: public SX1278 {
|
||||
public:
|
||||
|
||||
|
||||
// constructor
|
||||
|
||||
|
||||
/*!
|
||||
\brief Default constructor. Called from Arduino sketch when creating new LoRa instance.
|
||||
|
||||
|
||||
\param mod Instance of Module that will be used to communicate with the %LoRa chip.
|
||||
*/
|
||||
RFM96(Module* mod);
|
||||
|
||||
|
||||
// basic methods
|
||||
|
||||
|
||||
/*!
|
||||
\brief %LoRa modem initialization method. Must be called at least once from Arduino sketch to initialize the module.
|
||||
|
||||
|
||||
\param freq Carrier frequency in MHz. Allowed values range from 433.0 MHz to 470.0 MHz.
|
||||
|
||||
|
||||
\param bw %LoRa link bandwidth in kHz. Allowed values are 10.4, 15.6, 20.8, 31.25, 41.7, 62.5, 125, 250 and 500 kHz.
|
||||
|
||||
|
||||
\param sf %LoRa link spreading factor. Allowed values range from 6 to 12.
|
||||
|
||||
|
||||
\param cr %LoRa link coding rate denominator. Allowed values range from 5 to 8.
|
||||
|
||||
|
||||
\param syncWord %LoRa sync word. Can be used to distinguish different networks. Note that value 0x34 is reserved for LoRaWAN networks.
|
||||
|
||||
|
||||
\param power Transmission output power in dBm. Allowed values range from 2 to 17 dBm.
|
||||
|
||||
\param currentLimit Trim value for OCP (over current protection) in mA. Can be set to multiplies of 5 in range 45 to 120 mA and to multiples of 10 in range 120 to 240 mA.
|
||||
|
||||
\param currentLimit Trim value for OCP (over current protection) in mA. Can be set to multiplies of 5 in range 45 to 120 mA and to multiples of 10 in range 120 to 240 mA.
|
||||
Set to 0 to disable OCP (not recommended).
|
||||
|
||||
\param preambleLength Length of %LoRa transmission preamble in symbols. The actual preamble length is 4.25 symbols longer than the set number.
|
||||
|
||||
\param preambleLength Length of %LoRa transmission preamble in symbols. The actual preamble length is 4.25 symbols longer than the set number.
|
||||
Allowed values range from 6 to 65535.
|
||||
|
||||
|
||||
\param gain Gain of receiver LNA (low-noise amplifier). Can be set to any integer in range 1 to 6 where 1 is the highest gain.
|
||||
Set to 0 to enable automatic gain control (recommended).
|
||||
|
||||
|
||||
\returns \ref status_codes
|
||||
*/
|
||||
int16_t begin(float freq = 434.0, float bw = 125.0, uint8_t sf = 9, uint8_t cr = 7, uint8_t syncWord = SX127X_SYNC_WORD, int8_t power = 17, uint8_t currentLimit = 100, uint16_t preambleLength = 8, uint8_t gain = 0);
|
||||
|
||||
|
||||
// configuration methods
|
||||
|
||||
|
||||
/*!
|
||||
\brief Sets carrier frequency. Allowed values range from 433.0 MHz to 470.0 MHz.
|
||||
|
||||
|
||||
\param freq Carrier frequency to be set in MHz.
|
||||
|
||||
|
||||
\returns \ref status_codes
|
||||
*/
|
||||
int16_t setFrequency(float freq);
|
||||
|
||||
|
||||
#ifndef RADIOLIB_GODMODE
|
||||
private:
|
||||
|
||||
#endif
|
||||
|
||||
};
|
||||
|
||||
/*!
|
|
@ -1,10 +1,10 @@
|
|||
#ifndef _RADIOLIB_RFM97_H
|
||||
#define _RADIOLIB_RFM97_H
|
||||
|
||||
#include "TypeDef.h"
|
||||
#include "Module.h"
|
||||
#include "SX127x.h"
|
||||
#include "SX1278.h"
|
||||
#include "../../TypeDef.h"
|
||||
#include "../../Module.h"
|
||||
#include "../SX127x/SX127x.h"
|
||||
#include "../SX127x/SX1278.h"
|
||||
#include "RFM95.h"
|
||||
|
||||
/*!
|
||||
|
@ -14,28 +14,31 @@
|
|||
*/
|
||||
class RFM97: public RFM95 {
|
||||
public:
|
||||
|
||||
|
||||
// constructor
|
||||
|
||||
|
||||
/*!
|
||||
\brief Default constructor. Called from Arduino sketch when creating new LoRa instance.
|
||||
|
||||
|
||||
\param mod Instance of Module that will be used to communicate with the %LoRa chip.
|
||||
*/
|
||||
RFM97(Module* mod);
|
||||
|
||||
|
||||
// configuration methods
|
||||
|
||||
|
||||
/*!
|
||||
\brief Sets %LoRa link spreading factor. Allowed values range from 6 to 9. Only available in %LoRa mode.
|
||||
|
||||
|
||||
\param sf %LoRa link spreading factor to be set.
|
||||
|
||||
|
||||
\returns \ref status_codes
|
||||
*/
|
||||
int16_t setSpreadingFactor(uint8_t sf);
|
||||
|
||||
|
||||
#ifndef RADIOLIB_GODMODE
|
||||
private:
|
||||
#endif
|
||||
|
||||
};
|
||||
|
||||
#endif
|
|
@ -6,8 +6,8 @@ SX1231::SX1231(Module* mod) : RF69(mod) {
|
|||
|
||||
int16_t SX1231::begin(float freq, float br, float rxBw, float freqDev, int8_t power) {
|
||||
// set module properties
|
||||
_mod->init(USE_SPI, INT_BOTH);
|
||||
|
||||
_mod->init(RADIOLIB_USE_SPI, RADIOLIB_INT_BOTH);
|
||||
|
||||
// try to find the SX1231 chip
|
||||
uint8_t i = 0;
|
||||
bool flagFound = false;
|
||||
|
@ -18,69 +18,79 @@ int16_t SX1231::begin(float freq, float br, float rxBw, float freqDev, int8_t po
|
|||
_chipRevision = version;
|
||||
} else {
|
||||
#ifdef RADIOLIB_DEBUG
|
||||
Serial.print(F("SX127x not found! ("));
|
||||
Serial.print(i + 1);
|
||||
Serial.print(F(" of 10 tries) SX127X_REG_VERSION == "));
|
||||
|
||||
RADIOLIB_DEBUG_PRINT(F("SX127x not found! ("));
|
||||
RADIOLIB_DEBUG_PRINT(i + 1);
|
||||
RADIOLIB_DEBUG_PRINT(F(" of 10 tries) SX127X_REG_VERSION == "));
|
||||
|
||||
char buffHex[7];
|
||||
sprintf(buffHex, "0x%04X", version);
|
||||
Serial.print(buffHex);
|
||||
Serial.print(F(", expected 0x0021 / 0x0022 / 0x0023"));
|
||||
Serial.println();
|
||||
RADIOLIB_DEBUG_PRINT(buffHex);
|
||||
RADIOLIB_DEBUG_PRINT(F(", expected 0x0021 / 0x0022 / 0x0023"));
|
||||
RADIOLIB_DEBUG_PRINTLN();
|
||||
#endif
|
||||
delay(1000);
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if(!flagFound) {
|
||||
DEBUG_PRINTLN(F("No SX1231 found!"));
|
||||
RADIOLIB_DEBUG_PRINTLN(F("No SX1231 found!"));
|
||||
SPI.end();
|
||||
return(ERR_CHIP_NOT_FOUND);
|
||||
} else {
|
||||
DEBUG_PRINTLN(F("Found SX1231!"));
|
||||
RADIOLIB_DEBUG_PRINTLN(F("Found SX1231!"));
|
||||
}
|
||||
|
||||
|
||||
// configure settings not accessible by API
|
||||
int16_t state = config();
|
||||
if(state != ERR_NONE) {
|
||||
return(state);
|
||||
}
|
||||
|
||||
|
||||
// configure publicly accessible settings
|
||||
state = setFrequency(freq);
|
||||
if(state != ERR_NONE) {
|
||||
return(state);
|
||||
}
|
||||
|
||||
|
||||
// configure bitrate
|
||||
_rxBw = 125.0;
|
||||
state = setBitRate(br);
|
||||
if(state != ERR_NONE) {
|
||||
return(state);
|
||||
}
|
||||
|
||||
|
||||
// configure default RX bandwidth
|
||||
state = setRxBandwidth(rxBw);
|
||||
if(state != ERR_NONE) {
|
||||
return(state);
|
||||
}
|
||||
|
||||
|
||||
// configure default frequency deviation
|
||||
state = setFrequencyDeviation(freqDev);
|
||||
if(state != ERR_NONE) {
|
||||
return(state);
|
||||
}
|
||||
|
||||
|
||||
// configure default TX output power
|
||||
state = setOutputPower(power);
|
||||
if(state != ERR_NONE) {
|
||||
return(state);
|
||||
}
|
||||
|
||||
|
||||
// default sync word values 0x2D01 is the same as the default in LowPowerLab RFM69 library
|
||||
uint8_t syncWord[] = {0x2D, 0x01};
|
||||
state = setSyncWord(syncWord, 2);
|
||||
if(state != ERR_NONE) {
|
||||
return(state);
|
||||
}
|
||||
|
||||
|
||||
// set default packet length mode
|
||||
state = variablePacketLengthMode();
|
||||
if (state != ERR_NONE) {
|
||||
return(state);
|
||||
}
|
||||
|
||||
// SX1231 V2a only
|
||||
if(_chipRevision == SX1231_CHIP_REVISION_2_A) {
|
||||
// modify default OOK threshold value
|
||||
|
@ -88,13 +98,13 @@ int16_t SX1231::begin(float freq, float br, float rxBw, float freqDev, int8_t po
|
|||
if(state != ERR_NONE) {
|
||||
return(state);
|
||||
}
|
||||
|
||||
|
||||
// enable OCP with 95 mA limit
|
||||
state = _mod->SPIsetRegValue(RF69_REG_OCP, RF69_OCP_ON | RF69_OCP_TRIM, 4, 0);
|
||||
if(state != ERR_NONE) {
|
||||
return(state);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return(ERR_NONE);
|
||||
}
|
|
@ -1,9 +1,9 @@
|
|||
#ifndef _RADIOLIB_SX1231_H
|
||||
#define _RADIOLIB_SX1231_H
|
||||
|
||||
#include "TypeDef.h"
|
||||
#include "Module.h"
|
||||
#include "RF69.h"
|
||||
#include "../../TypeDef.h"
|
||||
#include "../../Module.h"
|
||||
#include "../RF69/RF69.h"
|
||||
|
||||
#define SX1231_CHIP_REVISION_2_A 0x21
|
||||
#define SX1231_CHIP_REVISION_2_B 0x22
|
||||
|
@ -46,7 +46,9 @@ class SX1231: public RF69 {
|
|||
*/
|
||||
int16_t begin(float freq = 434.0, float br = 48.0, float rxBw = 125.0, float freqDev = 50.0, int8_t power = 13);
|
||||
|
||||
#ifndef RADIOLIB_GODMODE
|
||||
private:
|
||||
#endif
|
||||
uint8_t _chipRevision;
|
||||
};
|
||||
|
|
@ -1,16 +0,0 @@
|
|||
#ifndef _RADIOLIB_SX1261_H
|
||||
#define _RADIOLIB_SX1261_H
|
||||
|
||||
#include "TypeDef.h"
|
||||
#include "Module.h"
|
||||
#include "SX126x.h"
|
||||
#include "SX1262.h"
|
||||
|
||||
//SX126X_CMD_SET_PA_CONFIG
|
||||
#define SX126X_PA_CONFIG_SX1261 0x01
|
||||
#define SX126X_PA_CONFIG_SX1262 0x00
|
||||
|
||||
// TODO: implement SX1261 class
|
||||
using SX1261 = SX1262;
|
||||
|
||||
#endif
|
50
src/modules/SX126x/SX1261.cpp
Normal file
50
src/modules/SX126x/SX1261.cpp
Normal file
|
@ -0,0 +1,50 @@
|
|||
#include "SX1261.h"
|
||||
|
||||
SX1261::SX1261(Module* mod)
|
||||
: SX1262(mod) {
|
||||
|
||||
}
|
||||
|
||||
int16_t SX1261::setOutputPower(int8_t power) {
|
||||
// check allowed power range
|
||||
if (!((power >= -17) && (power <= 14))) {
|
||||
return(ERR_INVALID_OUTPUT_POWER);
|
||||
}
|
||||
|
||||
// get current OCP configuration
|
||||
uint8_t ocp = 0;
|
||||
int16_t state = readRegister(SX126X_REG_OCP_CONFIGURATION, &ocp, 1);
|
||||
if (state != ERR_NONE) {
|
||||
return(state);
|
||||
}
|
||||
|
||||
state = setOptimalLowPowerPaConfig(&power);
|
||||
if (state != ERR_NONE) {
|
||||
return(state);
|
||||
}
|
||||
|
||||
// set output power
|
||||
// TODO power ramp time configuration
|
||||
state = SX126x::setTxParams(power);
|
||||
if (state != ERR_NONE) {
|
||||
return(state);
|
||||
}
|
||||
|
||||
// restore OCP configuration
|
||||
return writeRegister(SX126X_REG_OCP_CONFIGURATION, &ocp, 1);
|
||||
}
|
||||
|
||||
int16_t SX1261::setOptimalLowPowerPaConfig(int8_t* inOutPower)
|
||||
{
|
||||
int16_t state;
|
||||
if (*inOutPower > 10) {
|
||||
state = SX126x::setPaConfig(0x04, SX126X_PA_CONFIG_SX1261, 0x00);
|
||||
}
|
||||
else {
|
||||
state = SX126x::setPaConfig(0x01, SX126X_PA_CONFIG_SX1261, 0x00);
|
||||
// changing the PaConfig means output power is now scaled so we get 3 dB less than requested.
|
||||
// see datasheet table 13-21 and comments in setOptimalHiPowerPaConfig.
|
||||
*inOutPower -= 3;
|
||||
}
|
||||
return state;
|
||||
}
|
42
src/modules/SX126x/SX1261.h
Normal file
42
src/modules/SX126x/SX1261.h
Normal file
|
@ -0,0 +1,42 @@
|
|||
#ifndef _RADIOLIB_SX1261_H
|
||||
#define _RADIOLIB_SX1261_H
|
||||
|
||||
#include "../../TypeDef.h"
|
||||
#include "../../Module.h"
|
||||
#include "SX126x.h"
|
||||
#include "SX1262.h"
|
||||
|
||||
//SX126X_CMD_SET_PA_CONFIG
|
||||
#define SX126X_PA_CONFIG_SX1261 0x01
|
||||
|
||||
/*!
|
||||
\class SX1261
|
||||
|
||||
\brief Derived class for %SX1261 modules.
|
||||
*/
|
||||
class SX1261 : public SX1262 {
|
||||
public:
|
||||
/*!
|
||||
\brief Default constructor.
|
||||
|
||||
\param mod Instance of Module that will be used to communicate with the radio.
|
||||
*/
|
||||
SX1261(Module* mod);
|
||||
|
||||
/*!
|
||||
\brief Sets output power. Allowed values are in range from -17 to 14 dBm.
|
||||
|
||||
\param power Output power to be set in dBm.
|
||||
|
||||
\returns \ref status_codes
|
||||
*/
|
||||
int16_t setOutputPower(int8_t power);
|
||||
|
||||
#ifndef RADIOLIB_GODMODE
|
||||
private:
|
||||
#endif
|
||||
int16_t setOptimalLowPowerPaConfig(int8_t* inOutPower);
|
||||
};
|
||||
|
||||
|
||||
#endif
|
|
@ -22,6 +22,11 @@ int16_t SX1262::begin(float freq, float bw, uint8_t sf, uint8_t cr, uint16_t syn
|
|||
return(state);
|
||||
}
|
||||
|
||||
state = SX126x::fixPaClamping();
|
||||
if (state != ERR_NONE) {
|
||||
return state;
|
||||
}
|
||||
|
||||
return(state);
|
||||
}
|
||||
|
||||
|
@ -43,6 +48,11 @@ int16_t SX1262::beginFSK(float freq, float br, float freqDev, float rxBw, int8_t
|
|||
return(state);
|
||||
}
|
||||
|
||||
state = SX126x::fixPaClamping();
|
||||
if (state != ERR_NONE) {
|
||||
return state;
|
||||
}
|
||||
|
||||
return(state);
|
||||
}
|
||||
|
||||
|
@ -85,28 +95,32 @@ int16_t SX1262::setFrequency(float freq, bool calibrate) {
|
|||
|
||||
int16_t SX1262::setOutputPower(int8_t power) {
|
||||
// check allowed power range
|
||||
if(!((power >= -17) && (power <= 22))) {
|
||||
if (!((power >= -17) && (power <= 22))) {
|
||||
return(ERR_INVALID_OUTPUT_POWER);
|
||||
}
|
||||
|
||||
// get current OCP configuration
|
||||
uint8_t ocp = 0;
|
||||
int16_t state = readRegister(SX126X_REG_OCP_CONFIGURATION, &ocp, 1);
|
||||
if(state != ERR_NONE) {
|
||||
if (state != ERR_NONE) {
|
||||
return(state);
|
||||
}
|
||||
|
||||
// enable high power PA for output power higher than 14 dBm
|
||||
if(power > 13) {
|
||||
SX126x::setPaConfig(0x04, SX126X_PA_CONFIG_SX1262);
|
||||
} else {
|
||||
SX126x::setPaConfig(0x04, SX126X_PA_CONFIG_SX1261);
|
||||
// this function sets the optimal PA settings
|
||||
// and adjusts power based on the PA settings chosen
|
||||
// so that output power matches requested power.
|
||||
state = SX126x::setOptimalHiPowerPaConfig(&power);
|
||||
if (state != ERR_NONE) {
|
||||
return(state);
|
||||
}
|
||||
|
||||
// set output power
|
||||
// TODO power ramp time configuration
|
||||
SX126x::setTxParams(power);
|
||||
state = SX126x::setTxParams(power);
|
||||
if (state != ERR_NONE) {
|
||||
return(state);
|
||||
}
|
||||
|
||||
// restore OCP configuration
|
||||
return(writeRegister(SX126X_REG_OCP_CONFIGURATION, &ocp, 1));
|
||||
return writeRegister(SX126X_REG_OCP_CONFIGURATION, &ocp, 1);
|
||||
}
|
|
@ -1,14 +1,10 @@
|
|||
#ifndef _RADIOLIB_SX1262_H
|
||||
#define _RADIOLIB_SX1262_H
|
||||
|
||||
#include "TypeDef.h"
|
||||
#include "Module.h"
|
||||
#include "../../TypeDef.h"
|
||||
#include "../../Module.h"
|
||||
#include "SX126x.h"
|
||||
|
||||
//SX126X_CMD_SET_PA_CONFIG
|
||||
#define SX126X_PA_CONFIG_SX1261 0x01
|
||||
#define SX126X_PA_CONFIG_SX1262 0x00
|
||||
|
||||
/*!
|
||||
\class SX1262
|
||||
|
||||
|
@ -93,8 +89,9 @@ class SX1262: public SX126x {
|
|||
*/
|
||||
int16_t setOutputPower(int8_t power);
|
||||
|
||||
#ifndef RADIOLIB_GODMODE
|
||||
private:
|
||||
|
||||
#endif
|
||||
|
||||
};
|
||||
|
|
@ -22,6 +22,11 @@ int16_t SX1268::begin(float freq, float bw, uint8_t sf, uint8_t cr, uint16_t syn
|
|||
return(state);
|
||||
}
|
||||
|
||||
state = SX126x::fixPaClamping();
|
||||
if (state != ERR_NONE) {
|
||||
return state;
|
||||
}
|
||||
|
||||
return(state);
|
||||
}
|
||||
int16_t SX1268::beginFSK(float freq, float br, float freqDev, float rxBw, int8_t power, float currentLimit, uint16_t preambleLength, float dataShaping) {
|
||||
|
@ -42,6 +47,11 @@ int16_t SX1268::beginFSK(float freq, float br, float freqDev, float rxBw, int8_t
|
|||
return(state);
|
||||
}
|
||||
|
||||
state = SX126x::fixPaClamping();
|
||||
if (state != ERR_NONE) {
|
||||
return state;
|
||||
}
|
||||
|
||||
return(state);
|
||||
}
|
||||
|
||||
|
@ -89,13 +99,19 @@ int16_t SX1268::setOutputPower(int8_t power) {
|
|||
return(state);
|
||||
}
|
||||
|
||||
// enable high power PA
|
||||
SX126x::setPaConfig(0x04, SX126X_PA_CONFIG_SX1268);
|
||||
// enable optimal PA - this changes the value of power.
|
||||
state = SX126x::setOptimalHiPowerPaConfig(&power);
|
||||
if (state != ERR_NONE) {
|
||||
return(state);
|
||||
}
|
||||
|
||||
// set output power
|
||||
// TODO power ramp time configuration
|
||||
SX126x::setTxParams(power);
|
||||
state = SX126x::setTxParams(power);
|
||||
if (state != ERR_NONE) {
|
||||
return(state);
|
||||
}
|
||||
|
||||
// restore OCP configuration
|
||||
return(writeRegister(SX126X_REG_OCP_CONFIGURATION, &ocp, 1));
|
||||
return writeRegister(SX126X_REG_OCP_CONFIGURATION, &ocp, 1);
|
||||
}
|
|
@ -1,8 +1,8 @@
|
|||
#ifndef _RADIOLIB_SX1268_H
|
||||
#define _RADIOLIB_SX1268_H
|
||||
|
||||
#include "TypeDef.h"
|
||||
#include "Module.h"
|
||||
#include "../../TypeDef.h"
|
||||
#include "../../Module.h"
|
||||
#include "SX126x.h"
|
||||
|
||||
//SX126X_CMD_SET_PA_CONFIG
|
||||
|
@ -91,6 +91,11 @@ class SX1268: public SX126x {
|
|||
\returns \ref status_codes
|
||||
*/
|
||||
int16_t setOutputPower(int8_t power);
|
||||
|
||||
#ifndef RADIOLIB_GODMODE
|
||||
private:
|
||||
#endif
|
||||
|
||||
};
|
||||
|
||||
#endif
|
|
@ -6,7 +6,7 @@ SX126x::SX126x(Module* mod) : PhysicalLayer(SX126X_CRYSTAL_FREQ, SX126X_DIV_EXPO
|
|||
|
||||
int16_t SX126x::begin(float bw, uint8_t sf, uint8_t cr, uint16_t syncWord, float currentLimit, uint16_t preambleLength) {
|
||||
// set module properties
|
||||
_mod->init(USE_SPI, INT_BOTH);
|
||||
_mod->init(RADIOLIB_USE_SPI, RADIOLIB_INT_BOTH);
|
||||
pinMode(_mod->getRx(), INPUT);
|
||||
|
||||
// BW in kHz and SF are required in order to calculate LDRO for setModulationParams
|
||||
|
@ -71,7 +71,7 @@ int16_t SX126x::begin(float bw, uint8_t sf, uint8_t cr, uint16_t syncWord, float
|
|||
|
||||
int16_t SX126x::beginFSK(float br, float freqDev, float rxBw, float currentLimit, uint16_t preambleLength, float dataShaping) {
|
||||
// set module properties
|
||||
_mod->init(USE_SPI, INT_BOTH);
|
||||
_mod->init(RADIOLIB_USE_SPI, RADIOLIB_INT_BOTH);
|
||||
pinMode(_mod->getRx(), INPUT);
|
||||
|
||||
// initialize configuration variables (will be overwritten during public settings configuration)
|
||||
|
@ -134,6 +134,11 @@ int16_t SX126x::beginFSK(float br, float freqDev, float rxBw, float currentLimit
|
|||
return(state);
|
||||
}
|
||||
|
||||
state = setWhitening(true, 0x0100);
|
||||
if(state != ERR_NONE) {
|
||||
return(state);
|
||||
}
|
||||
|
||||
state = setDio2AsRfSwitch(false);
|
||||
|
||||
return(state);
|
||||
|
@ -167,9 +172,9 @@ int16_t SX126x::transmit(uint8_t* data, size_t len, uint8_t addr) {
|
|||
return(ERR_UNKNOWN);
|
||||
}
|
||||
|
||||
DEBUG_PRINT(F("Timeout in "));
|
||||
DEBUG_PRINT(timeout);
|
||||
DEBUG_PRINTLN(F(" us"));
|
||||
RADIOLIB_DEBUG_PRINT(F("Timeout in "));
|
||||
RADIOLIB_DEBUG_PRINT(timeout);
|
||||
RADIOLIB_DEBUG_PRINTLN(F(" us"));
|
||||
|
||||
// start transmission
|
||||
state = startTransmit(data, len, addr);
|
||||
|
@ -231,9 +236,9 @@ int16_t SX126x::receive(uint8_t* data, size_t len) {
|
|||
return(ERR_UNKNOWN);
|
||||
}
|
||||
|
||||
DEBUG_PRINT(F("Timeout in "));
|
||||
DEBUG_PRINT(timeout);
|
||||
DEBUG_PRINTLN(F(" us"));
|
||||
RADIOLIB_DEBUG_PRINT(F("Timeout in "));
|
||||
RADIOLIB_DEBUG_PRINT(timeout);
|
||||
RADIOLIB_DEBUG_PRINTLN(F(" us"));
|
||||
|
||||
// start reception
|
||||
uint32_t timeoutValue = (uint32_t)((float)timeout / 15.625);
|
||||
|
@ -246,11 +251,18 @@ int16_t SX126x::receive(uint8_t* data, size_t len) {
|
|||
uint32_t start = micros();
|
||||
while(!digitalRead(_mod->getInt0())) {
|
||||
if(micros() - start > timeout) {
|
||||
fixImplicitTimeout();
|
||||
clearIrqStatus();
|
||||
return(ERR_RX_TIMEOUT);
|
||||
}
|
||||
}
|
||||
|
||||
// timeout fix is recommended after any reception with active timeout
|
||||
state = fixImplicitTimeout();
|
||||
if(state != ERR_NONE) {
|
||||
return(state);
|
||||
}
|
||||
|
||||
// read the received data
|
||||
return(readData(data, len));
|
||||
}
|
||||
|
@ -359,13 +371,18 @@ int16_t SX126x::startTransmit(uint8_t* data, size_t len, uint8_t addr) {
|
|||
return(ERR_PACKET_TOO_LONG);
|
||||
}
|
||||
|
||||
// maximum packet length is decreased by 1 when address filtering is active
|
||||
if((_addrComp != SX126X_GFSK_ADDRESS_FILT_OFF) && (len > SX126X_MAX_PACKET_LENGTH - 1)) {
|
||||
return(ERR_PACKET_TOO_LONG);
|
||||
}
|
||||
|
||||
// set packet Length
|
||||
int16_t state = ERR_NONE;
|
||||
uint8_t modem = getPacketType();
|
||||
if(modem == SX126X_PACKET_TYPE_LORA) {
|
||||
state = setPacketParams(_preambleLength, _crcType, len);
|
||||
} else if(modem == SX126X_PACKET_TYPE_GFSK) {
|
||||
state = setPacketParamsFSK(_preambleLengthFSK, _crcTypeFSK, _syncWordLength, _addrComp, len);
|
||||
state = setPacketParamsFSK(_preambleLengthFSK, _crcTypeFSK, _syncWordLength, _addrComp, _whitening, _packetType, len);
|
||||
} else {
|
||||
return(ERR_UNKNOWN);
|
||||
}
|
||||
|
@ -397,6 +414,12 @@ int16_t SX126x::startTransmit(uint8_t* data, size_t len, uint8_t addr) {
|
|||
return(state);
|
||||
}
|
||||
|
||||
// fix sensitivity
|
||||
state = fixSensitivity();
|
||||
if(state != ERR_NONE) {
|
||||
return(state);
|
||||
}
|
||||
|
||||
// start transmission
|
||||
state = setTx(SX126X_TX_TIMEOUT_NONE);
|
||||
if(state != ERR_NONE) {
|
||||
|
@ -435,6 +458,12 @@ int16_t SX126x::startReceive(uint32_t timeout) {
|
|||
}
|
||||
|
||||
int16_t SX126x::readData(uint8_t* data, size_t len) {
|
||||
// set mode to standby
|
||||
int16_t state = standby();
|
||||
if(state != ERR_NONE) {
|
||||
return(state);
|
||||
}
|
||||
|
||||
// check integrity CRC
|
||||
uint16_t irq = getIrqStatus();
|
||||
if((irq & SX126X_IRQ_CRC_ERR) || (irq & SX126X_IRQ_HEADER_ERR)) {
|
||||
|
@ -449,7 +478,7 @@ int16_t SX126x::readData(uint8_t* data, size_t len) {
|
|||
}
|
||||
|
||||
// read packet data
|
||||
int16_t state = readBuffer(data, length);
|
||||
state = readBuffer(data, length);
|
||||
if(state != ERR_NONE) {
|
||||
return(state);
|
||||
}
|
||||
|
@ -554,7 +583,7 @@ int16_t SX126x::setPreambleLength(uint16_t preambleLength) {
|
|||
return(setPacketParams(_preambleLength, _crcType));
|
||||
} else if(modem == SX126X_PACKET_TYPE_GFSK) {
|
||||
_preambleLengthFSK = preambleLength;
|
||||
return(setPacketParamsFSK(_preambleLengthFSK, _crcTypeFSK, _syncWordLength, _addrComp));
|
||||
return(setPacketParamsFSK(_preambleLengthFSK, _crcTypeFSK, _syncWordLength, _addrComp, _whitening, _packetType));
|
||||
}
|
||||
|
||||
return(ERR_UNKNOWN);
|
||||
|
@ -716,7 +745,7 @@ int16_t SX126x::setSyncWord(uint8_t* syncWord, uint8_t len) {
|
|||
|
||||
// update packet parameters
|
||||
_syncWordLength = len * 8;
|
||||
state = setPacketParamsFSK(_preambleLengthFSK, _crcTypeFSK, _syncWordLength, _addrComp);
|
||||
state = setPacketParamsFSK(_preambleLengthFSK, _crcTypeFSK, _syncWordLength, _addrComp, _whitening, _packetType);
|
||||
|
||||
return(state);
|
||||
}
|
||||
|
@ -745,7 +774,7 @@ int16_t SX126x::setSyncBits(uint8_t *syncWord, uint8_t bitsLen) {
|
|||
|
||||
// update packet parameters
|
||||
_syncWordLength = bitsLen;
|
||||
state = setPacketParamsFSK(_preambleLengthFSK, _crcTypeFSK, _syncWordLength, _addrComp);
|
||||
state = setPacketParamsFSK(_preambleLengthFSK, _crcTypeFSK, _syncWordLength, _addrComp, _whitening, _packetType);
|
||||
|
||||
return(state);
|
||||
}
|
||||
|
@ -758,7 +787,7 @@ int16_t SX126x::setNodeAddress(uint8_t nodeAddr) {
|
|||
|
||||
// enable address filtering (node only)
|
||||
_addrComp = SX126X_GFSK_ADDRESS_FILT_NODE;
|
||||
int16_t state = setPacketParamsFSK(_preambleLengthFSK, _crcTypeFSK, _syncWordLength, _addrComp);
|
||||
int16_t state = setPacketParamsFSK(_preambleLengthFSK, _crcTypeFSK, _syncWordLength, _addrComp, _whitening, _packetType);
|
||||
if(state != ERR_NONE) {
|
||||
return(state);
|
||||
}
|
||||
|
@ -777,7 +806,7 @@ int16_t SX126x::setBroadcastAddress(uint8_t broadAddr) {
|
|||
|
||||
// enable address filtering (node and broadcast)
|
||||
_addrComp = SX126X_GFSK_ADDRESS_FILT_NODE_BROADCAST;
|
||||
int16_t state = setPacketParamsFSK(_preambleLengthFSK, _crcTypeFSK, _syncWordLength, _addrComp);
|
||||
int16_t state = setPacketParamsFSK(_preambleLengthFSK, _crcTypeFSK, _syncWordLength, _addrComp, _whitening, _packetType);
|
||||
if(state != ERR_NONE) {
|
||||
return(state);
|
||||
}
|
||||
|
@ -796,7 +825,7 @@ int16_t SX126x::disableAddressFiltering() {
|
|||
|
||||
// disable address filtering
|
||||
_addrComp = SX126X_GFSK_ADDRESS_FILT_OFF;
|
||||
return(setPacketParamsFSK(_preambleLengthFSK, _crcTypeFSK, _syncWordLength, _addrComp));
|
||||
return(setPacketParamsFSK(_preambleLengthFSK, _crcTypeFSK, _syncWordLength, _addrComp, _whitening));
|
||||
}
|
||||
|
||||
int16_t SX126x::setCRC(uint8_t len, uint16_t initial, uint16_t polynomial, bool inverted) {
|
||||
|
@ -827,7 +856,7 @@ int16_t SX126x::setCRC(uint8_t len, uint16_t initial, uint16_t polynomial, bool
|
|||
return(ERR_INVALID_CRC_CONFIGURATION);
|
||||
}
|
||||
|
||||
int16_t state = setPacketParamsFSK(_preambleLengthFSK, _crcTypeFSK, _syncWordLength, _addrComp);
|
||||
int16_t state = setPacketParamsFSK(_preambleLengthFSK, _crcTypeFSK, _syncWordLength, _addrComp, _whitening, _packetType);
|
||||
if(state != ERR_NONE) {
|
||||
return(state);
|
||||
}
|
||||
|
@ -862,6 +891,50 @@ int16_t SX126x::setCRC(uint8_t len, uint16_t initial, uint16_t polynomial, bool
|
|||
return(ERR_UNKNOWN);
|
||||
}
|
||||
|
||||
int16_t SX126x::setWhitening(bool enabled, uint16_t initial) {
|
||||
// check active modem
|
||||
if(getPacketType() != SX126X_PACKET_TYPE_GFSK) {
|
||||
return(ERR_WRONG_MODEM);
|
||||
}
|
||||
|
||||
int16_t state = ERR_NONE;
|
||||
if(enabled != true) {
|
||||
// disable whitening
|
||||
_whitening = SX126X_GFSK_WHITENING_OFF;
|
||||
|
||||
state = setPacketParamsFSK(_preambleLengthFSK, _crcTypeFSK, _syncWordLength, _addrComp, _whitening, _packetType);
|
||||
if(state != ERR_NONE) {
|
||||
return(state);
|
||||
}
|
||||
} else {
|
||||
// enable whitening
|
||||
_whitening = SX126X_GFSK_WHITENING_ON;
|
||||
|
||||
// write initial whitening value
|
||||
// as per note on pg. 65 of datasheet v1.2: "The user should not change the value of the 7 MSB's of this register"
|
||||
uint8_t data[2];
|
||||
// first read the actual value and mask 7 MSB which we can not change
|
||||
// if different value is written in 7 MSB, the Rx won't even work (tested on HW)
|
||||
state = readRegister(SX126X_REG_WHITENING_INITIAL_MSB, data, 1);
|
||||
if(state != ERR_NONE) {
|
||||
return(state);
|
||||
}
|
||||
data[0] = (data[0] & 0xFE) | (uint8_t)((initial >> 8) & 0x01);
|
||||
data[1] = (uint8_t)(initial & 0xFF);
|
||||
state = writeRegister(SX126X_REG_WHITENING_INITIAL_MSB, data, 2);
|
||||
|
||||
if(state != ERR_NONE) {
|
||||
return(state);
|
||||
}
|
||||
|
||||
state = setPacketParamsFSK(_preambleLengthFSK, _crcTypeFSK, _syncWordLength, _addrComp, _whitening, _packetType);
|
||||
if(state != ERR_NONE) {
|
||||
return(state);
|
||||
}
|
||||
}
|
||||
return(state);
|
||||
}
|
||||
|
||||
float SX126x::getDataRate() {
|
||||
return(_dataRate);
|
||||
}
|
||||
|
@ -892,6 +965,14 @@ size_t SX126x::getPacketLength(bool update) {
|
|||
return((size_t)rxBufStatus[0]);
|
||||
}
|
||||
|
||||
int16_t SX126x::fixedPacketLengthMode(uint8_t len) {
|
||||
return(setPacketMode(SX126X_GFSK_PACKET_FIXED, len));
|
||||
}
|
||||
|
||||
int16_t SX126x::variablePacketLengthMode(uint8_t maxLen) {
|
||||
return(setPacketMode(SX126X_GFSK_PACKET_VARIABLE, maxLen));
|
||||
}
|
||||
|
||||
uint32_t SX126x::getTimeOnAir(size_t len) {
|
||||
if(getPacketType() == SX126X_PACKET_TYPE_LORA) {
|
||||
float symbolLength = (float)((uint32_t)(1) << _sf) / (float)_bwKhz;
|
||||
|
@ -913,10 +994,15 @@ uint32_t SX126x::getTimeOnAir(size_t len) {
|
|||
}
|
||||
}
|
||||
|
||||
int16_t SX126x::setTCXO(float voltage, uint32_t timeout) {
|
||||
int16_t SX126x::setTCXO(float voltage, uint32_t delay) {
|
||||
// set mode to standby
|
||||
standby();
|
||||
|
||||
// check SX126X_XOSC_START_ERR flag and clear it
|
||||
if(getDeviceErrors() & SX126X_XOSC_START_ERR) {
|
||||
clearDeviceErrors();
|
||||
}
|
||||
|
||||
// check alowed voltage values
|
||||
uint8_t data[4];
|
||||
if(abs(voltage - 1.6) <= 0.001) {
|
||||
|
@ -939,11 +1025,11 @@ int16_t SX126x::setTCXO(float voltage, uint32_t timeout) {
|
|||
return(ERR_INVALID_TCXO_VOLTAGE);
|
||||
}
|
||||
|
||||
// calculate timeout
|
||||
uint32_t timeoutValue = (float)timeout / 15.625;
|
||||
data[1] = (uint8_t)((timeoutValue >> 16) & 0xFF);
|
||||
data[2] = (uint8_t)((timeoutValue >> 8) & 0xFF);
|
||||
data[3] = (uint8_t)(timeoutValue & 0xFF);
|
||||
// calculate delay
|
||||
uint32_t delayValue = (float)delay / 15.625;
|
||||
data[1] = (uint8_t)((delayValue >> 16) & 0xFF);
|
||||
data[2] = (uint8_t)((delayValue >> 8) & 0xFF);
|
||||
data[3] = (uint8_t)(delayValue & 0xFF);
|
||||
|
||||
// enable TCXO control on DIO3
|
||||
SPIwriteCommand(SX126X_CMD_SET_DIO3_AS_TCXO_CTRL, data, 4);
|
||||
|
@ -981,12 +1067,8 @@ int16_t SX126x::setPaConfig(uint8_t paDutyCycle, uint8_t deviceSel, uint8_t hpMa
|
|||
}
|
||||
|
||||
int16_t SX126x::writeRegister(uint16_t addr, uint8_t* data, uint8_t numBytes) {
|
||||
uint8_t* dat = new uint8_t[2 + numBytes];
|
||||
dat[0] = (uint8_t)((addr >> 8) & 0xFF);
|
||||
dat[1] = (uint8_t)(addr & 0xFF);
|
||||
memcpy(dat + 2, data, numBytes);
|
||||
int16_t state = SPIwriteCommand(SX126X_CMD_WRITE_REGISTER, dat, 2 + numBytes);
|
||||
delete[] dat;
|
||||
uint8_t cmd[] = { SX126X_CMD_WRITE_REGISTER, (uint8_t)((addr >> 8) & 0xFF), (uint8_t)(addr & 0xFF) };
|
||||
int16_t state = SPIwriteCommand(cmd, 3, data, numBytes);
|
||||
return(state);
|
||||
}
|
||||
|
||||
|
@ -996,22 +1078,15 @@ int16_t SX126x::readRegister(uint16_t addr, uint8_t* data, uint8_t numBytes) {
|
|||
}
|
||||
|
||||
int16_t SX126x::writeBuffer(uint8_t* data, uint8_t numBytes, uint8_t offset) {
|
||||
uint8_t* dat = new uint8_t[1 + numBytes];
|
||||
dat[0] = offset;
|
||||
memcpy(dat + 1, data, numBytes);
|
||||
int16_t state = SPIwriteCommand(SX126X_CMD_WRITE_BUFFER, dat, 1 + numBytes);
|
||||
delete[] dat;
|
||||
uint8_t cmd[] = { SX126X_CMD_WRITE_BUFFER, offset };
|
||||
int16_t state = SPIwriteCommand(cmd, 2, data, numBytes);
|
||||
|
||||
return(state);
|
||||
}
|
||||
|
||||
int16_t SX126x::readBuffer(uint8_t* data, uint8_t numBytes) {
|
||||
// offset will be always set to 0 (one extra NOP is sent)
|
||||
uint8_t* dat = new uint8_t[1 + numBytes];
|
||||
dat[0] = SX126X_CMD_NOP;
|
||||
memcpy(dat + 1, data, numBytes);
|
||||
int16_t state = SPIreadCommand(SX126X_CMD_READ_BUFFER, dat, 1 + numBytes);
|
||||
memcpy(data, dat + 1, numBytes);
|
||||
delete[] dat;
|
||||
uint8_t cmd[] = { SX126X_CMD_READ_BUFFER, SX126X_CMD_NOP };
|
||||
int16_t state = SPIreadCommand(cmd, 2, data, numBytes);
|
||||
return(state);
|
||||
}
|
||||
|
||||
|
@ -1054,13 +1129,54 @@ int16_t SX126x::setTxParams(uint8_t power, uint8_t rampTime) {
|
|||
return(SPIwriteCommand(SX126X_CMD_SET_TX_PARAMS, data, 2));
|
||||
}
|
||||
|
||||
int16_t SX126x::setOptimalHiPowerPaConfig(int8_t * inOutPower) {
|
||||
// set PA config for optimal consumption as described in section 13-21 of SX1268 datasheet v1.1
|
||||
// the final column of Table 13-21 suggests that the value passed in SetTxParams
|
||||
// is actually scaled depending on the parameters of setPaConfig
|
||||
int16_t state;
|
||||
if (*inOutPower >= 21) {
|
||||
state = SX126x::setPaConfig(0x04, SX126X_PA_CONFIG_SX1262_8, SX126X_PA_CONFIG_HP_MAX/*0x07*/);
|
||||
}
|
||||
else if (*inOutPower >= 18) {
|
||||
state = SX126x::setPaConfig(0x03, SX126X_PA_CONFIG_SX1262_8, 0x05);
|
||||
// datasheet instructs request 22 dBm for 20 dBm actual output power
|
||||
*inOutPower += 2;
|
||||
} else if (*inOutPower >= 15) {
|
||||
state = SX126x::setPaConfig(0x02, SX126X_PA_CONFIG_SX1262_8, 0x03);
|
||||
// datasheet instructs request 22 dBm for 17 dBm actual output power
|
||||
*inOutPower += 5;
|
||||
} else {
|
||||
state = SX126x::setPaConfig(0x02, SX126X_PA_CONFIG_SX1262_8, 0x02);
|
||||
// datasheet instructs request 22 dBm for 14 dBm actual output power.
|
||||
*inOutPower += 8;
|
||||
}
|
||||
return state;
|
||||
}
|
||||
|
||||
int16_t SX126x::setPacketMode(uint8_t mode, uint8_t len) {
|
||||
// check active modem
|
||||
if(getPacketType() != SX126X_PACKET_TYPE_GFSK) {
|
||||
return(ERR_WRONG_MODEM);
|
||||
}
|
||||
|
||||
// set requested packet mode
|
||||
int16_t state = setPacketParamsFSK(_preambleLengthFSK, _crcTypeFSK, _syncWordLength, _addrComp, _whitening, mode, len);
|
||||
if(state != ERR_NONE) {
|
||||
return(state);
|
||||
}
|
||||
|
||||
// update cached value
|
||||
_packetType = mode;
|
||||
return(state);
|
||||
}
|
||||
|
||||
int16_t SX126x::setModulationParams(uint8_t sf, uint8_t bw, uint8_t cr, uint8_t ldro) {
|
||||
// calculate symbol length and enable low data rate optimization, if needed
|
||||
if(ldro == 0xFF) {
|
||||
float symbolLength = (float)(uint32_t(1) << _sf) / (float)_bwKhz;
|
||||
DEBUG_PRINT("Symbol length: ");
|
||||
DEBUG_PRINT(symbolLength);
|
||||
DEBUG_PRINTLN(" ms");
|
||||
RADIOLIB_DEBUG_PRINT("Symbol length: ");
|
||||
RADIOLIB_DEBUG_PRINT(symbolLength);
|
||||
RADIOLIB_DEBUG_PRINTLN(" ms");
|
||||
if(symbolLength >= 16.0) {
|
||||
_ldro = SX126X_LORA_LOW_DATA_RATE_OPTIMIZE_ON;
|
||||
} else {
|
||||
|
@ -1082,11 +1198,12 @@ int16_t SX126x::setModulationParamsFSK(uint32_t br, uint8_t pulseShape, uint8_t
|
|||
}
|
||||
|
||||
int16_t SX126x::setPacketParams(uint16_t preambleLength, uint8_t crcType, uint8_t payloadLength, uint8_t headerType, uint8_t invertIQ) {
|
||||
fixInvertedIQ(invertIQ);
|
||||
uint8_t data[6] = {(uint8_t)((preambleLength >> 8) & 0xFF), (uint8_t)(preambleLength & 0xFF), headerType, payloadLength, crcType, invertIQ};
|
||||
return(SPIwriteCommand(SX126X_CMD_SET_PACKET_PARAMS, data, 6));
|
||||
}
|
||||
|
||||
int16_t SX126x::setPacketParamsFSK(uint16_t preambleLength, uint8_t crcType, uint8_t syncWordLength, uint8_t addrComp, uint8_t payloadLength, uint8_t packetType, uint8_t preambleDetectorLength, uint8_t whitening) {
|
||||
int16_t SX126x::setPacketParamsFSK(uint16_t preambleLength, uint8_t crcType, uint8_t syncWordLength, uint8_t addrComp, uint8_t whitening, uint8_t packetType, uint8_t payloadLength, uint8_t preambleDetectorLength) {
|
||||
uint8_t data[9] = {(uint8_t)((preambleLength >> 8) & 0xFF), (uint8_t)(preambleLength & 0xFF),
|
||||
preambleDetectorLength, syncWordLength, addrComp,
|
||||
packetType, payloadLength, crcType, whitening};
|
||||
|
@ -1118,8 +1235,8 @@ uint16_t SX126x::getDeviceErrors() {
|
|||
}
|
||||
|
||||
int16_t SX126x::clearDeviceErrors() {
|
||||
uint8_t data[1] = {SX126X_CMD_NOP};
|
||||
return(SPIwriteCommand(SX126X_CMD_CLEAR_DEVICE_ERRORS, data, 1));
|
||||
uint8_t data[2] = {SX126X_CMD_NOP, SX126X_CMD_NOP};
|
||||
return(SPIwriteCommand(SX126X_CMD_CLEAR_DEVICE_ERRORS, data, 2));
|
||||
}
|
||||
|
||||
int16_t SX126x::setFrequencyRaw(float freq) {
|
||||
|
@ -1129,9 +1246,90 @@ int16_t SX126x::setFrequencyRaw(float freq) {
|
|||
return(ERR_NONE);
|
||||
}
|
||||
|
||||
int16_t SX126x::fixSensitivity() {
|
||||
// fix receiver sensitivity for 500 kHz LoRa
|
||||
// see SX1262/SX1268 datasheet, chapter 15 Known Limitations, section 15.1 for details
|
||||
|
||||
// read current sensitivity configuration
|
||||
uint8_t sensitivityConfig = 0;
|
||||
int16_t state = readRegister(SX126X_REG_SENSITIVITY_CONFIG, &sensitivityConfig, 1);
|
||||
if(state != ERR_NONE) {
|
||||
return(state);
|
||||
}
|
||||
|
||||
// fix the value for LoRa with 500 kHz bandwidth
|
||||
if((getPacketType() == SX126X_PACKET_TYPE_LORA) && (abs(_bwKhz - 500.0) <= 0.001)) {
|
||||
sensitivityConfig &= 0xFB;
|
||||
} else {
|
||||
sensitivityConfig |= 0x04;
|
||||
}
|
||||
return(writeRegister(SX126X_REG_SENSITIVITY_CONFIG, &sensitivityConfig, 1));
|
||||
}
|
||||
|
||||
int16_t SX126x::fixPaClamping() {
|
||||
// fixes overly eager PA clamping
|
||||
// see SX1262/SX1268 datasheet, chapter 15 Known Limitations, section 15.2 for details
|
||||
|
||||
// read current clamping configuration
|
||||
uint8_t clampConfig = 0;
|
||||
int16_t state = readRegister(SX126X_REG_TX_CLAMP_CONFIG, &clampConfig, 1);
|
||||
if (state != ERR_NONE) {
|
||||
return state;
|
||||
}
|
||||
|
||||
// update with the new value
|
||||
clampConfig |= 0x1E;
|
||||
return(writeRegister(SX126X_REG_TX_CLAMP_CONFIG, &clampConfig, 1));
|
||||
}
|
||||
|
||||
int16_t SX126x::fixImplicitTimeout() {
|
||||
// fixes timeout in implicit header mode
|
||||
// see SX1262/SX1268 datasheet, chapter 15 Known Limitations, section 15.3 for details
|
||||
|
||||
// stop RTC counter
|
||||
uint8_t rtcStop = 0x00;
|
||||
int16_t state = writeRegister(SX126X_REG_RTC_STOP, &rtcStop, 1);
|
||||
if(state != ERR_NONE) {
|
||||
return(state);
|
||||
}
|
||||
|
||||
// read currently active event
|
||||
uint8_t rtcEvent = 0;
|
||||
state = readRegister(SX126X_REG_RTC_EVENT, &rtcEvent, 1);
|
||||
if(state != ERR_NONE) {
|
||||
return(state);
|
||||
}
|
||||
|
||||
// clear events
|
||||
rtcEvent |= 0x02;
|
||||
return(writeRegister(SX126X_REG_RTC_EVENT, &rtcEvent, 1));
|
||||
}
|
||||
|
||||
int16_t SX126x::fixInvertedIQ(uint8_t iqConfig) {
|
||||
// fixes IQ configuration for inverted IQ
|
||||
// see SX1262/SX1268 datasheet, chapter 15 Known Limitations, section 15.4 for details
|
||||
|
||||
// read current IQ configuration
|
||||
uint8_t iqConfigCurrent = 0;
|
||||
int16_t state = readRegister(SX126X_REG_IQ_CONFIG, &iqConfigCurrent, 1);
|
||||
if(state != ERR_NONE) {
|
||||
return(state);
|
||||
}
|
||||
|
||||
// set correct IQ configuration
|
||||
if(iqConfig == SX126X_LORA_IQ_STANDARD) {
|
||||
iqConfigCurrent &= 0xFB;
|
||||
} else {
|
||||
iqConfigCurrent |= 0x04;
|
||||
}
|
||||
|
||||
// update with the new value
|
||||
return(writeRegister(SX126X_REG_IQ_CONFIG, &iqConfigCurrent, 1));
|
||||
}
|
||||
|
||||
int16_t SX126x::config(uint8_t modem) {
|
||||
// set regulator mode
|
||||
uint8_t* data = new uint8_t[1];
|
||||
uint8_t data[7];
|
||||
data[0] = SX126X_REGULATOR_DC_DC;
|
||||
int16_t state = SPIwriteCommand(SX126X_CMD_SET_REGULATOR_MODE, data, 1);
|
||||
if(state != ERR_NONE) {
|
||||
|
@ -1159,8 +1357,6 @@ int16_t SX126x::config(uint8_t modem) {
|
|||
}
|
||||
|
||||
// set CAD parameters
|
||||
delete[] data;
|
||||
data = new uint8_t[7];
|
||||
data[0] = SX126X_CAD_ON_8_SYMB;
|
||||
data[1] = _sf + 13;
|
||||
data[2] = 10;
|
||||
|
@ -1181,8 +1377,6 @@ int16_t SX126x::config(uint8_t modem) {
|
|||
}
|
||||
|
||||
// calibrate all blocks
|
||||
delete[] data;
|
||||
data = new uint8_t[1];
|
||||
data[0] = SX126X_CALIBRATE_ALL;
|
||||
state = SPIwriteCommand(SX126X_CMD_CALIBRATE, data, 1);
|
||||
if(state != ERR_NONE) {
|
||||
|
@ -1193,19 +1387,23 @@ int16_t SX126x::config(uint8_t modem) {
|
|||
delayMicroseconds(1);
|
||||
while(digitalRead(_mod->getRx()));
|
||||
|
||||
delete[] data;
|
||||
|
||||
return(ERR_NONE);
|
||||
}
|
||||
|
||||
int16_t SX126x::SPIwriteCommand(uint8_t* cmd, uint8_t cmdLen, uint8_t* data, uint8_t numBytes, bool waitForBusy) {
|
||||
return(SX126x::SPItransfer(cmd, cmdLen, true, data, NULL, numBytes, waitForBusy));
|
||||
}
|
||||
|
||||
int16_t SX126x::SPIwriteCommand(uint8_t cmd, uint8_t* data, uint8_t numBytes, bool waitForBusy) {
|
||||
uint8_t cmdBuffer[] = {cmd};
|
||||
return(SX126x::SPItransfer(cmdBuffer, 1, true, data, NULL, numBytes, waitForBusy));
|
||||
return(SX126x::SPItransfer(&cmd, 1, true, data, NULL, numBytes, waitForBusy));
|
||||
}
|
||||
|
||||
int16_t SX126x::SPIreadCommand(uint8_t* cmd, uint8_t cmdLen, uint8_t* data, uint8_t numBytes, bool waitForBusy) {
|
||||
return(SX126x::SPItransfer(cmd, cmdLen, false, NULL, data, numBytes, waitForBusy));
|
||||
}
|
||||
|
||||
int16_t SX126x::SPIreadCommand(uint8_t cmd, uint8_t* data, uint8_t numBytes, bool waitForBusy) {
|
||||
uint8_t cmdBuffer[] = {cmd};
|
||||
return(SX126x::SPItransfer(cmdBuffer, 1, false, NULL, data, numBytes, waitForBusy));
|
||||
return(SX126x::SPItransfer(&cmd, 1, false, NULL, data, numBytes, waitForBusy));
|
||||
}
|
||||
|
||||
int16_t SX126x::SPItransfer(uint8_t* cmd, uint8_t cmdLen, bool write, uint8_t* dataOut, uint8_t* dataIn, uint8_t numBytes, bool waitForBusy, uint32_t timeout) {
|
||||
|
@ -1213,7 +1411,15 @@ int16_t SX126x::SPItransfer(uint8_t* cmd, uint8_t cmdLen, bool write, uint8_t* d
|
|||
SPIClass* spi = _mod->getSpi();
|
||||
SPISettings spiSettings = _mod->getSpiSettings();
|
||||
|
||||
#ifdef RADIOLIB_VERBOSE
|
||||
uint8_t debugBuff[256];
|
||||
#endif
|
||||
|
||||
// pull NSS low
|
||||
digitalWrite(_mod->getCs(), LOW);
|
||||
|
||||
// ensure BUSY is low (state meachine ready)
|
||||
RADIOLIB_VERBOSE_PRINTLN(F("Wait for BUSY ... "));
|
||||
uint32_t start = millis();
|
||||
while(digitalRead(_mod->getRx())) {
|
||||
if(millis() - start >= timeout) {
|
||||
|
@ -1222,14 +1428,11 @@ int16_t SX126x::SPItransfer(uint8_t* cmd, uint8_t cmdLen, bool write, uint8_t* d
|
|||
}
|
||||
|
||||
// start transfer
|
||||
digitalWrite(_mod->getCs(), LOW);
|
||||
spi->beginTransaction(spiSettings);
|
||||
|
||||
// send command byte(s)
|
||||
for(uint8_t n = 0; n < cmdLen; n++) {
|
||||
spi->transfer(cmd[n]);
|
||||
DEBUG_PRINT(cmd[n], HEX);
|
||||
DEBUG_PRINT('\t');
|
||||
}
|
||||
|
||||
// variable to save error during SPI transfer
|
||||
|
@ -1240,41 +1443,41 @@ int16_t SX126x::SPItransfer(uint8_t* cmd, uint8_t cmdLen, bool write, uint8_t* d
|
|||
for(uint8_t n = 0; n < numBytes; n++) {
|
||||
// send byte
|
||||
uint8_t in = spi->transfer(dataOut[n]);
|
||||
DEBUG_PRINT(dataOut[n], HEX);
|
||||
DEBUG_PRINT('\t');
|
||||
DEBUG_PRINT(in, HEX);
|
||||
DEBUG_PRINT('\t');
|
||||
#ifdef RADIOLIB_VERBOSE
|
||||
debugBuff[n] = in;
|
||||
#endif
|
||||
|
||||
// check status
|
||||
if(((in & 0b00001110) == SX126X_STATUS_CMD_TIMEOUT) ||
|
||||
((in & 0b00001110) == SX126X_STATUS_CMD_INVALID) ||
|
||||
((in & 0b00001110) == SX126X_STATUS_CMD_FAILED)) {
|
||||
status = in;
|
||||
status = in & 0b00001110;
|
||||
break;
|
||||
} else if(in == 0x00 || in == 0xFF) {
|
||||
status = SX126X_STATUS_SPI_FAILED;
|
||||
break;
|
||||
}
|
||||
}
|
||||
DEBUG_PRINTLN();
|
||||
|
||||
} else {
|
||||
// skip the first byte for read-type commands (status-only)
|
||||
uint8_t in = spi->transfer(SX126X_CMD_NOP);
|
||||
DEBUG_PRINT(SX126X_CMD_NOP, HEX);
|
||||
DEBUG_PRINT('\t');
|
||||
DEBUG_PRINT(in, HEX);
|
||||
DEBUG_PRINT('\t')
|
||||
#ifdef RADIOLIB_VERBOSE
|
||||
debugBuff[0] = in;
|
||||
#endif
|
||||
|
||||
// check status
|
||||
if(((in & 0b00001110) == SX126X_STATUS_CMD_TIMEOUT) ||
|
||||
((in & 0b00001110) == SX126X_STATUS_CMD_INVALID) ||
|
||||
((in & 0b00001110) == SX126X_STATUS_CMD_FAILED)) {
|
||||
status = in;
|
||||
status = in & 0b00001110;
|
||||
} else if(in == 0x00 || in == 0xFF) {
|
||||
status = SX126X_STATUS_SPI_FAILED;
|
||||
} else {
|
||||
for(uint8_t n = 0; n < numBytes; n++) {
|
||||
dataIn[n] = spi->transfer(SX126X_CMD_NOP);
|
||||
}
|
||||
}
|
||||
for(uint8_t n = 0; n < numBytes; n++) {
|
||||
dataIn[n] = spi->transfer(SX126X_CMD_NOP);
|
||||
DEBUG_PRINT(SX126X_CMD_NOP, HEX);
|
||||
DEBUG_PRINT('\t');
|
||||
DEBUG_PRINT(dataIn[n], HEX);
|
||||
DEBUG_PRINT('\t');
|
||||
}
|
||||
DEBUG_PRINTLN();
|
||||
}
|
||||
|
||||
// stop transfer
|
||||
|
@ -1287,11 +1490,52 @@ int16_t SX126x::SPItransfer(uint8_t* cmd, uint8_t cmdLen, bool write, uint8_t* d
|
|||
start = millis();
|
||||
while(digitalRead(_mod->getRx())) {
|
||||
if(millis() - start >= timeout) {
|
||||
return(ERR_SPI_CMD_TIMEOUT);
|
||||
status = SX126X_STATUS_CMD_TIMEOUT;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// print debug output
|
||||
#ifdef RADIOLIB_VERBOSE
|
||||
// print command byte(s)
|
||||
RADIOLIB_VERBOSE_PRINT("CMD\t");
|
||||
for(uint8_t n = 0; n < cmdLen; n++) {
|
||||
RADIOLIB_VERBOSE_PRINT(cmd[n], HEX);
|
||||
RADIOLIB_VERBOSE_PRINT('\t');
|
||||
}
|
||||
RADIOLIB_VERBOSE_PRINTLN();
|
||||
|
||||
// print data bytes
|
||||
RADIOLIB_VERBOSE_PRINT("DAT");
|
||||
if(write) {
|
||||
RADIOLIB_VERBOSE_PRINT("W\t");
|
||||
for(uint8_t n = 0; n < numBytes; n++) {
|
||||
RADIOLIB_VERBOSE_PRINT(dataOut[n], HEX);
|
||||
RADIOLIB_VERBOSE_PRINT('\t');
|
||||
RADIOLIB_VERBOSE_PRINT(debugBuff[n], HEX);
|
||||
RADIOLIB_VERBOSE_PRINT('\t');
|
||||
}
|
||||
RADIOLIB_VERBOSE_PRINTLN();
|
||||
} else {
|
||||
RADIOLIB_VERBOSE_PRINT("R\t");
|
||||
// skip the first byte for read-type commands (status-only)
|
||||
RADIOLIB_VERBOSE_PRINT(SX126X_CMD_NOP, HEX);
|
||||
RADIOLIB_VERBOSE_PRINT('\t');
|
||||
RADIOLIB_VERBOSE_PRINT(debugBuff[0], HEX);
|
||||
RADIOLIB_VERBOSE_PRINT('\t')
|
||||
|
||||
for(uint8_t n = 0; n < numBytes; n++) {
|
||||
RADIOLIB_VERBOSE_PRINT(SX126X_CMD_NOP, HEX);
|
||||
RADIOLIB_VERBOSE_PRINT('\t');
|
||||
RADIOLIB_VERBOSE_PRINT(dataIn[n], HEX);
|
||||
RADIOLIB_VERBOSE_PRINT('\t');
|
||||
}
|
||||
RADIOLIB_VERBOSE_PRINTLN();
|
||||
}
|
||||
RADIOLIB_VERBOSE_PRINTLN();
|
||||
#endif
|
||||
|
||||
// parse status
|
||||
switch(status) {
|
||||
case SX126X_STATUS_CMD_TIMEOUT:
|
||||
|
@ -1300,6 +1544,8 @@ int16_t SX126x::SPItransfer(uint8_t* cmd, uint8_t cmdLen, bool write, uint8_t* d
|
|||
return(ERR_SPI_CMD_INVALID);
|
||||
case SX126X_STATUS_CMD_FAILED:
|
||||
return(ERR_SPI_CMD_FAILED);
|
||||
case SX126X_STATUS_SPI_FAILED:
|
||||
return(ERR_CHIP_NOT_FOUND);
|
||||
default:
|
||||
return(ERR_NONE);
|
||||
}
|
|
@ -1,10 +1,10 @@
|
|||
#ifndef _RADIOLIB_SX126X_H
|
||||
#define _RADIOLIB_SX126X_H
|
||||
|
||||
#include "TypeDef.h"
|
||||
#include "Module.h"
|
||||
#include "../../TypeDef.h"
|
||||
#include "../../Module.h"
|
||||
|
||||
#include "../protocols/PhysicalLayer.h"
|
||||
#include "../../protocols/PhysicalLayer/PhysicalLayer.h"
|
||||
|
||||
// SX126X physical layer properties
|
||||
#define SX126X_CRYSTAL_FREQ 32.0
|
||||
|
@ -93,6 +93,16 @@
|
|||
#define SX126X_REG_XTA_TRIM 0x0911
|
||||
#define SX126X_REG_XTB_TRIM 0x0912
|
||||
|
||||
// undocumented registers
|
||||
#define SX126X_REG_SENSITIVITY_CONFIG 0x0889 // SX1268 datasheet v1.1, section 15.1
|
||||
#define SX126X_REG_TX_CLAMP_CONFIG 0x08D8 // SX1268 datasheet v1.1, section 15.2
|
||||
#define SX126X_REG_RTC_STOP 0x0920 // SX1268 datasheet v1.1, section 15.3
|
||||
#define SX126X_REG_RTC_EVENT 0x0944 // SX1268 datasheet v1.1, section 15.3
|
||||
#define SX126X_REG_IQ_CONFIG 0x0736 // SX1268 datasheet v1.1, section 15.4
|
||||
#define SX126X_REG_RX_GAIN_RETENTION_0 0x029F // SX1268 datasheet v1.1, section 9.6
|
||||
#define SX126X_REG_RX_GAIN_RETENTION_1 0x02A0 // SX1268 datasheet v1.1, section 9.6
|
||||
#define SX126X_REG_RX_GAIN_RETENTION_2 0x02A1 // SX1268 datasheet v1.1, section 9.6
|
||||
|
||||
|
||||
// SX126X SPI command variables
|
||||
//SX126X_CMD_SET_SLEEP
|
||||
|
@ -152,6 +162,7 @@
|
|||
//SX126X_CMD_SET_PA_CONFIG
|
||||
#define SX126X_PA_CONFIG_HP_MAX 0x07
|
||||
#define SX126X_PA_CONFIG_PA_LUT 0x01
|
||||
#define SX126X_PA_CONFIG_SX1262_8 0x00
|
||||
|
||||
//SX126X_CMD_SET_RX_TX_FALLBACK_MODE
|
||||
#define SX126X_RX_TX_FALLBACK_MODE_FS 0x40 // 7 0 after Rx/Tx go to: FS mode
|
||||
|
@ -289,6 +300,7 @@
|
|||
#define SX126X_STATUS_CMD_INVALID 0b00001000 // 3 1 invalid SPI command
|
||||
#define SX126X_STATUS_CMD_FAILED 0b00001010 // 3 1 SPI command failed to execute
|
||||
#define SX126X_STATUS_TX_DONE 0b00001100 // 3 1 packet transmission done
|
||||
#define SX126X_STATUS_SPI_FAILED 0b11111111 // 7 0 SPI transaction failed
|
||||
|
||||
//SX126X_CMD_GET_PACKET_STATUS
|
||||
#define SX126X_GFSK_RX_STATUS_PREAMBLE_ERR 0b10000000 // 7 7 GFSK Rx status: preamble error
|
||||
|
@ -655,6 +667,17 @@ class SX126x: public PhysicalLayer {
|
|||
*/
|
||||
int16_t setCRC(uint8_t len, uint16_t initial = 0x1D0F, uint16_t polynomial = 0x1021, bool inverted = true);
|
||||
|
||||
/*!
|
||||
\brief Sets FSK whitening parameters.
|
||||
|
||||
\param enabled True = Whitening enabled
|
||||
|
||||
\param initial Initial value used for the whitening LFSR in FSK mode.
|
||||
|
||||
\returns \ref status_codes
|
||||
*/
|
||||
int16_t setWhitening(bool enabled, uint16_t initial = 0x0100);
|
||||
|
||||
/*!
|
||||
\brief Sets TCXO (Temperature Compensated Crystal Oscillator) configuration.
|
||||
|
||||
|
@ -662,7 +685,7 @@ class SX126x: public PhysicalLayer {
|
|||
|
||||
\param TCXO timeout in us. Defaults to 5000 us.
|
||||
*/
|
||||
int16_t setTCXO(float voltage, uint32_t timeout = 5000);
|
||||
int16_t setTCXO(float voltage, uint32_t delay = 5000);
|
||||
|
||||
/*!
|
||||
\brief Set DIO2 to function as RF switch (default in Semtech example designs).
|
||||
|
@ -701,6 +724,24 @@ class SX126x: public PhysicalLayer {
|
|||
*/
|
||||
size_t getPacketLength(bool update = true);
|
||||
|
||||
/*!
|
||||
\brief Set modem in fixed packet length mode. Available in FSK mode only.
|
||||
|
||||
\param len Packet length.
|
||||
|
||||
\returns \ref status_codes
|
||||
*/
|
||||
int16_t fixedPacketLengthMode(uint8_t len = SX126X_MAX_PACKET_LENGTH);
|
||||
|
||||
/*!
|
||||
\brief Set modem in variable packet length mode. Available in FSK mode only.
|
||||
|
||||
\param len Maximum packet length.
|
||||
|
||||
\returns \ref status_codes
|
||||
*/
|
||||
int16_t variablePacketLengthMode(uint8_t maxLen = SX126X_MAX_PACKET_LENGTH);
|
||||
|
||||
/*!
|
||||
\brief Get expected time-on-air for a given size of payload
|
||||
|
||||
|
@ -710,7 +751,9 @@ class SX126x: public PhysicalLayer {
|
|||
*/
|
||||
uint32_t getTimeOnAir(size_t len);
|
||||
|
||||
#ifndef RADIOLIB_GODMODE
|
||||
protected:
|
||||
#endif
|
||||
// SX1276x SPI command implementations
|
||||
int16_t setTx(uint32_t timeout = 0);
|
||||
int16_t setRx(uint32_t timeout);
|
||||
|
@ -730,7 +773,7 @@ class SX126x: public PhysicalLayer {
|
|||
int16_t setModulationParams(uint8_t sf, uint8_t bw, uint8_t cr, uint8_t ldro = 0xFF);
|
||||
int16_t setModulationParamsFSK(uint32_t br, uint8_t pulseShape, uint8_t rxBw, uint32_t freqDev);
|
||||
int16_t setPacketParams(uint16_t preambleLength, uint8_t crcType, uint8_t payloadLength = 0xFF, uint8_t headerType = SX126X_LORA_HEADER_EXPLICIT, uint8_t invertIQ = SX126X_LORA_IQ_STANDARD);
|
||||
int16_t setPacketParamsFSK(uint16_t preambleLength, uint8_t crcType, uint8_t syncWordLength, uint8_t addrComp, uint8_t payloadLength = 0xFF, uint8_t packetType = SX126X_GFSK_PACKET_VARIABLE, uint8_t preambleDetectorLength = SX126X_GFSK_PREAMBLE_DETECT_16, uint8_t whitening = SX126X_GFSK_WHITENING_ON);
|
||||
int16_t setPacketParamsFSK(uint16_t preambleLength, uint8_t crcType, uint8_t syncWordLength, uint8_t addrComp, uint8_t whitening, uint8_t packetType = SX126X_GFSK_PACKET_VARIABLE, uint8_t payloadLength = 0xFF, uint8_t preambleDetectorLength = SX126X_GFSK_PREAMBLE_DETECT_16);
|
||||
int16_t setBufferBaseAddress(uint8_t txBaseAddress = 0x00, uint8_t rxBaseAddress = 0x00);
|
||||
uint8_t getStatus();
|
||||
uint32_t getPacketStatus();
|
||||
|
@ -738,8 +781,18 @@ class SX126x: public PhysicalLayer {
|
|||
int16_t clearDeviceErrors();
|
||||
|
||||
int16_t setFrequencyRaw(float freq);
|
||||
int16_t setOptimalHiPowerPaConfig(int8_t* inOutPower);
|
||||
int16_t setPacketMode(uint8_t mode, uint8_t len);
|
||||
|
||||
// fixes to errata
|
||||
int16_t fixSensitivity();
|
||||
int16_t fixPaClamping();
|
||||
int16_t fixImplicitTimeout();
|
||||
int16_t fixInvertedIQ(uint8_t iqConfig);
|
||||
|
||||
#ifndef RADIOLIB_GODMODE
|
||||
private:
|
||||
#endif
|
||||
Module* _mod;
|
||||
|
||||
uint8_t _bw, _sf, _cr, _ldro, _crcType;
|
||||
|
@ -747,7 +800,7 @@ class SX126x: public PhysicalLayer {
|
|||
float _bwKhz;
|
||||
|
||||
uint32_t _br, _freqDev;
|
||||
uint8_t _rxBw, _pulseShape, _crcTypeFSK, _syncWordLength, _addrComp;
|
||||
uint8_t _rxBw, _pulseShape, _crcTypeFSK, _syncWordLength, _addrComp, _whitening, _packetType;
|
||||
uint16_t _preambleLengthFSK;
|
||||
float _rxBwKhz;
|
||||
|
||||
|
@ -757,7 +810,9 @@ class SX126x: public PhysicalLayer {
|
|||
|
||||
// common low-level SPI interface
|
||||
int16_t SPIwriteCommand(uint8_t cmd, uint8_t* data, uint8_t numBytes, bool waitForBusy = true);
|
||||
int16_t SPIwriteCommand(uint8_t* cmd, uint8_t cmdLen, uint8_t* data, uint8_t numBytes, bool waitForBusy = true);
|
||||
int16_t SPIreadCommand(uint8_t cmd, uint8_t* data, uint8_t numBytes, bool waitForBusy = true);
|
||||
int16_t SPIreadCommand(uint8_t* cmd, uint8_t cmdLen, uint8_t* data, uint8_t numBytes, bool waitForBusy = true);
|
||||
int16_t SPItransfer(uint8_t* cmd, uint8_t cmdLen, bool write, uint8_t* dataOut, uint8_t* dataIn, uint8_t numBytes, bool waitForBusy, uint32_t timeout = 5000);
|
||||
};
|
||||
|
|
@ -125,9 +125,9 @@ int16_t SX1272::setBandwidth(float bw) {
|
|||
|
||||
// calculate symbol length and set low data rate optimization, if needed
|
||||
float symbolLength = (float)(uint32_t(1) << SX127x::_sf) / (float)SX127x::_bw;
|
||||
DEBUG_PRINT("Symbol length: ");
|
||||
DEBUG_PRINT(symbolLength);
|
||||
DEBUG_PRINTLN(" ms");
|
||||
RADIOLIB_DEBUG_PRINT("Symbol length: ");
|
||||
RADIOLIB_DEBUG_PRINT(symbolLength);
|
||||
RADIOLIB_DEBUG_PRINTLN(" ms");
|
||||
if(symbolLength >= 16.0) {
|
||||
state = _mod->SPIsetRegValue(SX127X_REG_MODEM_CONFIG_1, SX1272_LOW_DATA_RATE_OPT_ON, 0, 0);
|
||||
} else {
|
||||
|
@ -179,9 +179,9 @@ int16_t SX1272::setSpreadingFactor(uint8_t sf) {
|
|||
|
||||
// calculate symbol length and set low data rate optimization, if needed
|
||||
float symbolLength = (float)(uint32_t(1) << SX127x::_sf) / (float)SX127x::_bw;
|
||||
DEBUG_PRINT("Symbol length: ");
|
||||
DEBUG_PRINT(symbolLength);
|
||||
DEBUG_PRINTLN(" ms");
|
||||
RADIOLIB_DEBUG_PRINT("Symbol length: ");
|
||||
RADIOLIB_DEBUG_PRINT(symbolLength);
|
||||
RADIOLIB_DEBUG_PRINTLN(" ms");
|
||||
if(symbolLength >= 16.0) {
|
||||
state = _mod->SPIsetRegValue(SX127X_REG_MODEM_CONFIG_1, SX1272_LOW_DATA_RATE_OPT_ON, 0, 0);
|
||||
} else {
|
||||
|
@ -342,22 +342,33 @@ int16_t SX1272::setDataShapingOOK(uint8_t sh) {
|
|||
return(state);
|
||||
}
|
||||
|
||||
int8_t SX1272::getRSSI() {
|
||||
// check active modem
|
||||
if(getActiveModem() != SX127X_LORA) {
|
||||
return(0);
|
||||
float SX1272::getRSSI() {
|
||||
if(getActiveModem() == SX127X_LORA) {
|
||||
// RSSI calculation uses different constant for low-frequency and high-frequency ports
|
||||
float lastPacketRSSI = -139 + _mod->SPIgetRegValue(SX127X_REG_PKT_RSSI_VALUE);
|
||||
|
||||
// spread-spectrum modulation signal can be received below noise floor
|
||||
// check last packet SNR and if it's less than 0, add it to reported RSSI to get the correct value
|
||||
float lastPacketSNR = SX127x::getSNR();
|
||||
if(lastPacketSNR < 0.0) {
|
||||
lastPacketRSSI += lastPacketSNR;
|
||||
}
|
||||
|
||||
return(lastPacketRSSI);
|
||||
|
||||
} else {
|
||||
// enable listen mode
|
||||
startReceive();
|
||||
|
||||
// read the value for FSK
|
||||
float rssi = (float)_mod->SPIgetRegValue(SX127X_REG_RSSI_VALUE_FSK) / -2.0;
|
||||
|
||||
// set mode back to standby
|
||||
standby();
|
||||
|
||||
// return the value
|
||||
return(rssi);
|
||||
}
|
||||
|
||||
int8_t lastPacketRSSI = -139 + _mod->SPIgetRegValue(SX127X_REG_PKT_RSSI_VALUE);
|
||||
|
||||
// spread-spectrum modulation signal can be received below noise floor
|
||||
// check last packet SNR and if it's less than 0, add it to reported RSSI to get the correct value
|
||||
float lastPacketSNR = SX127x::getSNR();
|
||||
if(lastPacketSNR < 0.0) {
|
||||
lastPacketRSSI += lastPacketSNR;
|
||||
}
|
||||
|
||||
return(lastPacketRSSI);
|
||||
}
|
||||
|
||||
int16_t SX1272::setCRC(bool enableCRC) {
|
|
@ -1,8 +1,8 @@
|
|||
#ifndef _RADIOLIB_SX1272_H
|
||||
#define _RADIOLIB_SX1272_H
|
||||
|
||||
#include "TypeDef.h"
|
||||
#include "Module.h"
|
||||
#include "../../TypeDef.h"
|
||||
#include "../../Module.h"
|
||||
#include "SX127x.h"
|
||||
|
||||
// SX1272 specific register map
|
||||
|
@ -235,11 +235,11 @@ class SX1272: public SX127x {
|
|||
int16_t setDataShapingOOK(uint8_t sh);
|
||||
|
||||
/*!
|
||||
\brief Gets recorded signal strength indicator of the latest received packet.
|
||||
\brief Gets recorded signal strength indicator of the latest received packet for LoRa modem, or current RSSI level for FSK modem.
|
||||
|
||||
\returns Last packet recorded signal strength indicator (RSSI).
|
||||
\returns Last packet RSSI for LoRa modem, or current RSSI level for FSK modem.
|
||||
*/
|
||||
int8_t getRSSI();
|
||||
float getRSSI();
|
||||
|
||||
/*!
|
||||
\brief Enables/disables CRC check of received packets.
|
||||
|
@ -250,14 +250,18 @@ class SX1272: public SX127x {
|
|||
*/
|
||||
int16_t setCRC(bool enableCRC);
|
||||
|
||||
#ifndef RADIOLIB_GODMODE
|
||||
protected:
|
||||
#endif
|
||||
int16_t setBandwidthRaw(uint8_t newBandwidth);
|
||||
int16_t setSpreadingFactorRaw(uint8_t newSpreadingFactor);
|
||||
int16_t setCodingRateRaw(uint8_t newCodingRate);
|
||||
|
||||
int16_t configFSK();
|
||||
|
||||
#ifndef RADIOLIB_GODMODE
|
||||
private:
|
||||
#endif
|
||||
|
||||
};
|
||||
|
|
@ -1,7 +1,7 @@
|
|||
#ifndef _RADIOLIB_SX1273_H
|
||||
#define _RADIOLIB_SX1273_H
|
||||
|
||||
#include "TypeDef.h"
|
||||
#include "../../TypeDef.h"
|
||||
#include "SX1272.h"
|
||||
|
||||
/*!
|
||||
|
@ -11,56 +11,61 @@
|
|||
*/
|
||||
class SX1273: public SX1272 {
|
||||
public:
|
||||
|
||||
|
||||
// constructor
|
||||
|
||||
|
||||
/*!
|
||||
\brief Default constructor. Called from Arduino sketch when creating new LoRa instance.
|
||||
|
||||
|
||||
\param mod Instance of Module that will be used to communicate with the %LoRa chip.
|
||||
*/
|
||||
SX1273(Module* mod);
|
||||
|
||||
|
||||
// basic methods
|
||||
|
||||
|
||||
/*!
|
||||
\brief %LoRa modem initialization method. Must be called at least once from Arduino sketch to initialize the module.
|
||||
|
||||
|
||||
\param freq Carrier frequency in MHz. Allowed values range from 860.0 MHz to 1020.0 MHz.
|
||||
|
||||
|
||||
\param bw %LoRa link bandwidth in kHz. Allowed values are 125, 250 and 500 kHz.
|
||||
|
||||
|
||||
\param sf %LoRa link spreading factor. Allowed values range from 6 to 9.
|
||||
|
||||
|
||||
\param cr %LoRa link coding rate denominator. Allowed values range from 5 to 8.
|
||||
|
||||
|
||||
\param syncWord %LoRa sync word. Can be used to distinguish different networks. Note that value 0x34 is reserved for LoRaWAN networks.
|
||||
|
||||
|
||||
\param power Transmission output power in dBm. Allowed values range from 2 to 17 dBm.
|
||||
|
||||
\param currentLimit Trim value for OCP (over current protection) in mA. Can be set to multiplies of 5 in range 45 to 120 mA and to multiples of 10 in range 120 to 240 mA.
|
||||
|
||||
\param currentLimit Trim value for OCP (over current protection) in mA. Can be set to multiplies of 5 in range 45 to 120 mA and to multiples of 10 in range 120 to 240 mA.
|
||||
Set to 0 to disable OCP (not recommended).
|
||||
|
||||
\param preambleLength Length of %LoRa transmission preamble in symbols. The actual preamble length is 4.25 symbols longer than the set number.
|
||||
|
||||
\param preambleLength Length of %LoRa transmission preamble in symbols. The actual preamble length is 4.25 symbols longer than the set number.
|
||||
Allowed values range from 6 to 65535.
|
||||
|
||||
|
||||
\param gain Gain of receiver LNA (low-noise amplifier). Can be set to any integer in range 1 to 6 where 1 is the highest gain.
|
||||
Set to 0 to enable automatic gain control (recommended).
|
||||
|
||||
|
||||
\returns \ref status_codes
|
||||
*/
|
||||
int16_t begin(float freq = 915.0, float bw = 125.0, uint8_t sf = 9, uint8_t cr = 7, uint8_t syncWord = SX127X_SYNC_WORD, int8_t power = 17, uint8_t currentLimit = 100, uint16_t preambleLength = 8, uint8_t gain = 0);
|
||||
|
||||
|
||||
// configuration methods
|
||||
|
||||
|
||||
/*!
|
||||
\brief Sets %LoRa link spreading factor. Allowed values range from 6 to 9. Only available in %LoRa mode.
|
||||
|
||||
|
||||
\param sf %LoRa link spreading factor to be set.
|
||||
|
||||
|
||||
\returns \ref status_codes
|
||||
*/
|
||||
int16_t setSpreadingFactor(uint8_t sf);
|
||||
|
||||
#ifndef RADIOLIB_GODMODE
|
||||
private:
|
||||
#endif
|
||||
|
||||
};
|
||||
|
||||
#endif
|
|
@ -1,7 +1,7 @@
|
|||
#ifndef _RADIOLIB_SX1276_H
|
||||
#define _RADIOLIB_SX1276_H
|
||||
|
||||
#include "TypeDef.h"
|
||||
#include "../../TypeDef.h"
|
||||
#include "SX1278.h"
|
||||
|
||||
/*!
|
||||
|
@ -11,56 +11,61 @@
|
|||
*/
|
||||
class SX1276: public SX1278 {
|
||||
public:
|
||||
|
||||
|
||||
// constructor
|
||||
|
||||
|
||||
/*!
|
||||
\brief Default constructor. Called from Arduino sketch when creating new LoRa instance.
|
||||
|
||||
|
||||
\param mod Instance of Module that will be used to communicate with the %LoRa chip.
|
||||
*/
|
||||
SX1276(Module* mod);
|
||||
|
||||
|
||||
// basic methods
|
||||
|
||||
|
||||
/*!
|
||||
\brief %LoRa modem initialization method. Must be called at least once from Arduino sketch to initialize the module.
|
||||
|
||||
|
||||
\param freq Carrier frequency in MHz. Allowed values range from 137.0 MHz to 1020.0 MHz.
|
||||
|
||||
|
||||
\param bw %LoRa link bandwidth in kHz. Allowed values are 10.4, 15.6, 20.8, 31.25, 41.7, 62.5, 125, 250 and 500 kHz.
|
||||
|
||||
|
||||
\param sf %LoRa link spreading factor. Allowed values range from 6 to 12.
|
||||
|
||||
|
||||
\param cr %LoRa link coding rate denominator. Allowed values range from 5 to 8.
|
||||
|
||||
|
||||
\param syncWord %LoRa sync word. Can be used to distinguish different networks. Note that value 0x34 is reserved for LoRaWAN networks.
|
||||
|
||||
|
||||
\param power Transmission output power in dBm. Allowed values range from 2 to 17 dBm.
|
||||
|
||||
\param currentLimit Trim value for OCP (over current protection) in mA. Can be set to multiplies of 5 in range 45 to 120 mA and to multiples of 10 in range 120 to 240 mA.
|
||||
|
||||
\param currentLimit Trim value for OCP (over current protection) in mA. Can be set to multiplies of 5 in range 45 to 120 mA and to multiples of 10 in range 120 to 240 mA.
|
||||
Set to 0 to disable OCP (not recommended).
|
||||
|
||||
\param preambleLength Length of %LoRa transmission preamble in symbols. The actual preamble length is 4.25 symbols longer than the set number.
|
||||
|
||||
\param preambleLength Length of %LoRa transmission preamble in symbols. The actual preamble length is 4.25 symbols longer than the set number.
|
||||
Allowed values range from 6 to 65535.
|
||||
|
||||
|
||||
\param gain Gain of receiver LNA (low-noise amplifier). Can be set to any integer in range 1 to 6 where 1 is the highest gain.
|
||||
Set to 0 to enable automatic gain control (recommended).
|
||||
|
||||
|
||||
\returns \ref status_codes
|
||||
*/
|
||||
int16_t begin(float freq = 434.0, float bw = 125.0, uint8_t sf = 9, uint8_t cr = 7, uint8_t syncWord = SX127X_SYNC_WORD, int8_t power = 17, uint8_t currentLimit = 100, uint16_t preambleLength = 8, uint8_t gain = 0);
|
||||
|
||||
|
||||
// configuration methods
|
||||
|
||||
|
||||
/*!
|
||||
\brief Sets carrier frequency. Allowed values range from 137.0 MHz to 1020.0 MHz.
|
||||
|
||||
|
||||
\param freq Carrier frequency to be set in MHz.
|
||||
|
||||
|
||||
\returns \ref status_codes
|
||||
*/
|
||||
int16_t setFrequency(float freq);
|
||||
|
||||
#ifndef RADIOLIB_GODMODE
|
||||
private:
|
||||
#endif
|
||||
|
||||
};
|
||||
|
||||
#endif
|
|
@ -1,7 +1,7 @@
|
|||
#ifndef _RADIOLIB_SX1277_H
|
||||
#define _RADIOLIB_SX1277_H
|
||||
|
||||
#include "TypeDef.h"
|
||||
#include "../../TypeDef.h"
|
||||
#include "SX1278.h"
|
||||
|
||||
/*!
|
||||
|
@ -11,65 +11,70 @@
|
|||
*/
|
||||
class SX1277: public SX1278 {
|
||||
public:
|
||||
|
||||
|
||||
// constructor
|
||||
|
||||
|
||||
/*!
|
||||
\brief Default constructor. Called from Arduino sketch when creating new LoRa instance.
|
||||
|
||||
|
||||
\param mod Instance of Module that will be used to communicate with the %LoRa chip.
|
||||
*/
|
||||
SX1277(Module* mod);
|
||||
|
||||
|
||||
// basic methods
|
||||
|
||||
|
||||
/*!
|
||||
\brief %LoRa modem initialization method. Must be called at least once from Arduino sketch to initialize the module.
|
||||
|
||||
|
||||
\param freq Carrier frequency in MHz. Allowed values range from 137.0 MHz to 1020.0 MHz.
|
||||
|
||||
|
||||
\param bw %LoRa link bandwidth in kHz. Allowed values are 10.4, 15.6, 20.8, 31.25, 41.7, 62.5, 125, 250 and 500 kHz.
|
||||
|
||||
|
||||
\param sf %LoRa link spreading factor. Allowed values range from 6 to 9.
|
||||
|
||||
|
||||
\param cr %LoRa link coding rate denominator. Allowed values range from 5 to 8.
|
||||
|
||||
|
||||
\param syncWord %LoRa sync word. Can be used to distinguish different networks. Note that value 0x34 is reserved for LoRaWAN networks.
|
||||
|
||||
|
||||
\param power Transmission output power in dBm. Allowed values range from 2 to 17 dBm.
|
||||
|
||||
\param currentLimit Trim value for OCP (over current protection) in mA. Can be set to multiplies of 5 in range 45 to 120 mA and to multiples of 10 in range 120 to 240 mA.
|
||||
|
||||
\param currentLimit Trim value for OCP (over current protection) in mA. Can be set to multiplies of 5 in range 45 to 120 mA and to multiples of 10 in range 120 to 240 mA.
|
||||
Set to 0 to disable OCP (not recommended).
|
||||
|
||||
\param preambleLength Length of %LoRa transmission preamble in symbols. The actual preamble length is 4.25 symbols longer than the set number.
|
||||
|
||||
\param preambleLength Length of %LoRa transmission preamble in symbols. The actual preamble length is 4.25 symbols longer than the set number.
|
||||
Allowed values range from 6 to 65535.
|
||||
|
||||
|
||||
\param gain Gain of receiver LNA (low-noise amplifier). Can be set to any integer in range 1 to 6 where 1 is the highest gain.
|
||||
Set to 0 to enable automatic gain control (recommended).
|
||||
|
||||
|
||||
\returns \ref status_codes
|
||||
*/
|
||||
int16_t begin(float freq = 434.0, float bw = 125.0, uint8_t sf = 9, uint8_t cr = 7, uint8_t syncWord = SX127X_SYNC_WORD, int8_t power = 17, uint8_t currentLimit = 100, uint16_t preambleLength = 8, uint8_t gain = 0);
|
||||
|
||||
|
||||
// configuration methods
|
||||
|
||||
|
||||
/*!
|
||||
\brief Sets carrier frequency. Allowed values range from 137.0 MHz to 1020.0 MHz.
|
||||
|
||||
|
||||
\param freq Carrier frequency to be set in MHz.
|
||||
|
||||
|
||||
\returns \ref status_codes
|
||||
*/
|
||||
int16_t setFrequency(float freq);
|
||||
|
||||
|
||||
/*!
|
||||
\brief Sets %LoRa link spreading factor. Allowed values range from 6 to 9. Only available in %LoRa mode.
|
||||
|
||||
|
||||
\param sf %LoRa link spreading factor to be set.
|
||||
|
||||
|
||||
\returns \ref status_codes
|
||||
*/
|
||||
int16_t setSpreadingFactor(uint8_t sf);
|
||||
|
||||
#ifndef RADIOLIB_GODMODE
|
||||
private:
|
||||
#endif
|
||||
|
||||
};
|
||||
|
||||
#endif
|
|
@ -195,9 +195,9 @@ int16_t SX1278::setBandwidth(float bw) {
|
|||
|
||||
// calculate symbol length and set low data rate optimization, if needed
|
||||
float symbolLength = (float)(uint32_t(1) << SX127x::_sf) / (float)SX127x::_bw;
|
||||
DEBUG_PRINT("Symbol length: ");
|
||||
DEBUG_PRINT(symbolLength);
|
||||
DEBUG_PRINTLN(" ms");
|
||||
RADIOLIB_DEBUG_PRINT("Symbol length: ");
|
||||
RADIOLIB_DEBUG_PRINT(symbolLength);
|
||||
RADIOLIB_DEBUG_PRINTLN(" ms");
|
||||
if(symbolLength >= 16.0) {
|
||||
state = _mod->SPIsetRegValue(SX1278_REG_MODEM_CONFIG_3, SX1278_LOW_DATA_RATE_OPT_ON, 3, 3);
|
||||
} else {
|
||||
|
@ -249,9 +249,9 @@ int16_t SX1278::setSpreadingFactor(uint8_t sf) {
|
|||
|
||||
// calculate symbol length and set low data rate optimization, if needed
|
||||
float symbolLength = (float)(uint32_t(1) << SX127x::_sf) / (float)SX127x::_bw;
|
||||
DEBUG_PRINT("Symbol length: ");
|
||||
DEBUG_PRINT(symbolLength);
|
||||
DEBUG_PRINTLN(" ms");
|
||||
RADIOLIB_DEBUG_PRINT("Symbol length: ");
|
||||
RADIOLIB_DEBUG_PRINT(symbolLength);
|
||||
RADIOLIB_DEBUG_PRINTLN(" ms");
|
||||
if(symbolLength >= 16.0) {
|
||||
state = _mod->SPIsetRegValue(SX1278_REG_MODEM_CONFIG_3, SX1278_LOW_DATA_RATE_OPT_ON, 3, 3);
|
||||
} else {
|
||||
|
@ -411,29 +411,40 @@ int16_t SX1278::setDataShapingOOK(uint8_t sh) {
|
|||
return(state);
|
||||
}
|
||||
|
||||
int8_t SX1278::getRSSI() {
|
||||
// check active modem
|
||||
if(getActiveModem() != SX127X_LORA) {
|
||||
return(0);
|
||||
}
|
||||
float SX1278::getRSSI() {
|
||||
if(getActiveModem() == SX127X_LORA) {
|
||||
// for LoRa, get RSSI of the last packet
|
||||
float lastPacketRSSI;
|
||||
|
||||
int8_t lastPacketRSSI;
|
||||
// RSSI calculation uses different constant for low-frequency and high-frequency ports
|
||||
if(_freq < 868.0) {
|
||||
lastPacketRSSI = -164 + _mod->SPIgetRegValue(SX127X_REG_PKT_RSSI_VALUE);
|
||||
} else {
|
||||
lastPacketRSSI = -157 + _mod->SPIgetRegValue(SX127X_REG_PKT_RSSI_VALUE);
|
||||
}
|
||||
|
||||
// spread-spectrum modulation signal can be received below noise floor
|
||||
// check last packet SNR and if it's less than 0, add it to reported RSSI to get the correct value
|
||||
float lastPacketSNR = SX127x::getSNR();
|
||||
if(lastPacketSNR < 0.0) {
|
||||
lastPacketRSSI += lastPacketSNR;
|
||||
}
|
||||
|
||||
return(lastPacketRSSI);
|
||||
|
||||
// RSSI calculation uses different constant for low-frequency and high-frequency ports
|
||||
if(_freq < 868.0) {
|
||||
lastPacketRSSI = -164 + _mod->SPIgetRegValue(SX127X_REG_PKT_RSSI_VALUE);
|
||||
} else {
|
||||
lastPacketRSSI = -157 + _mod->SPIgetRegValue(SX127X_REG_PKT_RSSI_VALUE);
|
||||
}
|
||||
// enable listen mode
|
||||
startReceive();
|
||||
|
||||
// spread-spectrum modulation signal can be received below noise floor
|
||||
// check last packet SNR and if it's less than 0, add it to reported RSSI to get the correct value
|
||||
float lastPacketSNR = SX127x::getSNR();
|
||||
if(lastPacketSNR < 0.0) {
|
||||
lastPacketRSSI += lastPacketSNR;
|
||||
}
|
||||
// read the value for FSK
|
||||
float rssi = (float)_mod->SPIgetRegValue(SX127X_REG_RSSI_VALUE_FSK) / -2.0;
|
||||
|
||||
return(lastPacketRSSI);
|
||||
// set mode back to standby
|
||||
standby();
|
||||
|
||||
// return the value
|
||||
return(rssi);
|
||||
}
|
||||
}
|
||||
|
||||
int16_t SX1278::setCRC(bool enableCRC) {
|
|
@ -1,8 +1,8 @@
|
|||
#ifndef _RADIOLIB_SX1278_H
|
||||
#define _RADIOLIB_SX1278_H
|
||||
|
||||
#include "TypeDef.h"
|
||||
#include "Module.h"
|
||||
#include "../../TypeDef.h"
|
||||
#include "../../Module.h"
|
||||
#include "SX127x.h"
|
||||
|
||||
// SX1278 specific register map
|
||||
|
@ -244,11 +244,11 @@ class SX1278: public SX127x {
|
|||
int16_t setDataShapingOOK(uint8_t sh);
|
||||
|
||||
/*!
|
||||
\brief Gets recorded signal strength indicator of the latest received packet.
|
||||
\brief Gets recorded signal strength indicator of the latest received packet for LoRa modem, or current RSSI level for FSK modem.
|
||||
|
||||
\returns Last packet recorded signal strength indicator (RSSI).
|
||||
\returns Last packet RSSI for LoRa modem, or current RSSI level for FSK modem.
|
||||
*/
|
||||
int8_t getRSSI();
|
||||
float getRSSI();
|
||||
|
||||
/*!
|
||||
\brief Enables/disables CRC check of received packets.
|
||||
|
@ -259,14 +259,18 @@ class SX1278: public SX127x {
|
|||
*/
|
||||
int16_t setCRC(bool enableCRC);
|
||||
|
||||
#ifndef RADIOLIB_GODMODE
|
||||
protected:
|
||||
#endif
|
||||
int16_t setBandwidthRaw(uint8_t newBandwidth);
|
||||
int16_t setSpreadingFactorRaw(uint8_t newSpreadingFactor);
|
||||
int16_t setCodingRateRaw(uint8_t newCodingRate);
|
||||
|
||||
int16_t configFSK();
|
||||
|
||||
#ifndef RADIOLIB_GODMODE
|
||||
private:
|
||||
#endif
|
||||
|
||||
};
|
||||
|
|
@ -1,7 +1,7 @@
|
|||
#ifndef _RADIOLIB_SX1279_H
|
||||
#define _RADIOLIB_SX1279_H
|
||||
|
||||
#include "TypeDef.h"
|
||||
#include "../../TypeDef.h"
|
||||
#include "SX1278.h"
|
||||
|
||||
/*!
|
||||
|
@ -11,56 +11,61 @@
|
|||
*/
|
||||
class SX1279: public SX1278 {
|
||||
public:
|
||||
|
||||
|
||||
// constructor
|
||||
|
||||
|
||||
/*!
|
||||
\brief Default constructor. Called from Arduino sketch when creating new LoRa instance.
|
||||
|
||||
|
||||
\param mod Instance of Module that will be used to communicate with the %LoRa chip.
|
||||
*/
|
||||
SX1279(Module* mod);
|
||||
|
||||
|
||||
// basic methods
|
||||
|
||||
|
||||
/*!
|
||||
\brief %LoRa modem initialization method. Must be called at least once from Arduino sketch to initialize the module.
|
||||
|
||||
|
||||
\param freq Carrier frequency in MHz. Allowed values range from 137.0 MHz to 960.0 MHz.
|
||||
|
||||
|
||||
\param bw %LoRa link bandwidth in kHz. Allowed values are 10.4, 15.6, 20.8, 31.25, 41.7, 62.5, 125, 250 and 500 kHz.
|
||||
|
||||
|
||||
\param sf %LoRa link spreading factor. Allowed values range from 6 to 12.
|
||||
|
||||
|
||||
\param cr %LoRa link coding rate denominator. Allowed values range from 5 to 8.
|
||||
|
||||
|
||||
\param syncWord %LoRa sync word. Can be used to distinguish different networks. Note that value 0x34 is reserved for LoRaWAN networks.
|
||||
|
||||
|
||||
\param power Transmission output power in dBm. Allowed values range from 2 to 17 dBm.
|
||||
|
||||
\param currentLimit Trim value for OCP (over current protection) in mA. Can be set to multiplies of 5 in range 45 to 120 mA and to multiples of 10 in range 120 to 240 mA.
|
||||
|
||||
\param currentLimit Trim value for OCP (over current protection) in mA. Can be set to multiplies of 5 in range 45 to 120 mA and to multiples of 10 in range 120 to 240 mA.
|
||||
Set to 0 to disable OCP (not recommended).
|
||||
|
||||
\param preambleLength Length of %LoRa transmission preamble in symbols. The actual preamble length is 4.25 symbols longer than the set number.
|
||||
|
||||
\param preambleLength Length of %LoRa transmission preamble in symbols. The actual preamble length is 4.25 symbols longer than the set number.
|
||||
Allowed values range from 6 to 65535.
|
||||
|
||||
|
||||
\param gain Gain of receiver LNA (low-noise amplifier). Can be set to any integer in range 1 to 6 where 1 is the highest gain.
|
||||
Set to 0 to enable automatic gain control (recommended).
|
||||
|
||||
|
||||
\returns \ref status_codes
|
||||
*/
|
||||
int16_t begin(float freq = 434.0, float bw = 125.0, uint8_t sf = 9, uint8_t cr = 7, uint8_t syncWord = SX127X_SYNC_WORD, int8_t power = 17, uint8_t currentLimit = 100, uint16_t preambleLength = 8, uint8_t gain = 0);
|
||||
|
||||
|
||||
// configuration methods
|
||||
|
||||
|
||||
/*!
|
||||
\brief Sets carrier frequency. Allowed values range from 137.0 MHz to 960.0 MHz.
|
||||
|
||||
|
||||
\param freq Carrier frequency to be set in MHz.
|
||||
|
||||
|
||||
\returns \ref status_codes
|
||||
*/
|
||||
int16_t setFrequency(float freq);
|
||||
|
||||
#ifndef RADIOLIB_GODMODE
|
||||
private:
|
||||
#endif
|
||||
|
||||
};
|
||||
|
||||
#endif
|
|
@ -7,15 +7,15 @@ SX127x::SX127x(Module* mod) : PhysicalLayer(SX127X_CRYSTAL_FREQ, SX127X_DIV_EXPO
|
|||
|
||||
int16_t SX127x::begin(uint8_t chipVersion, uint8_t syncWord, uint8_t currentLimit, uint16_t preambleLength) {
|
||||
// set module properties
|
||||
_mod->init(USE_SPI, INT_BOTH);
|
||||
_mod->init(RADIOLIB_USE_SPI, RADIOLIB_INT_BOTH);
|
||||
|
||||
// try to find the SX127x chip
|
||||
if(!SX127x::findChip(chipVersion)) {
|
||||
DEBUG_PRINTLN(F("No SX127x found!"));
|
||||
RADIOLIB_DEBUG_PRINTLN(F("No SX127x found!"));
|
||||
_mod->term();
|
||||
return(ERR_CHIP_NOT_FOUND);
|
||||
} else {
|
||||
DEBUG_PRINTLN(F("Found SX127x!"));
|
||||
RADIOLIB_DEBUG_PRINTLN(F("Found SX127x!"));
|
||||
}
|
||||
|
||||
// check active modem
|
||||
|
@ -42,6 +42,9 @@ int16_t SX127x::begin(uint8_t chipVersion, uint8_t syncWord, uint8_t currentLimi
|
|||
|
||||
// set preamble length
|
||||
state = SX127x::setPreambleLength(preambleLength);
|
||||
if(state != ERR_NONE) {
|
||||
return(state);
|
||||
}
|
||||
|
||||
// initalize internal variables
|
||||
_dataRate = 0.0;
|
||||
|
@ -51,15 +54,15 @@ int16_t SX127x::begin(uint8_t chipVersion, uint8_t syncWord, uint8_t currentLimi
|
|||
|
||||
int16_t SX127x::beginFSK(uint8_t chipVersion, float br, float freqDev, float rxBw, uint8_t currentLimit, uint16_t preambleLength, bool enableOOK) {
|
||||
// set module properties
|
||||
_mod->init(USE_SPI, INT_BOTH);
|
||||
_mod->init(RADIOLIB_USE_SPI, RADIOLIB_INT_BOTH);
|
||||
|
||||
// try to find the SX127x chip
|
||||
if(!SX127x::findChip(chipVersion)) {
|
||||
DEBUG_PRINTLN(F("No SX127x found!"));
|
||||
RADIOLIB_DEBUG_PRINTLN(F("No SX127x found!"));
|
||||
_mod->term();
|
||||
return(ERR_CHIP_NOT_FOUND);
|
||||
} else {
|
||||
DEBUG_PRINTLN(F("Found SX127x!"));
|
||||
RADIOLIB_DEBUG_PRINTLN(F("Found SX127x!"));
|
||||
}
|
||||
|
||||
// check currently active modem
|
||||
|
@ -117,6 +120,27 @@ int16_t SX127x::beginFSK(uint8_t chipVersion, float br, float freqDev, float rxB
|
|||
|
||||
// enable/disable OOK
|
||||
state = setOOK(enableOOK);
|
||||
if(state != ERR_NONE) {
|
||||
return(state);
|
||||
}
|
||||
|
||||
// set default RSSI measurement config
|
||||
state = setRSSIConfig(2);
|
||||
if(state != ERR_NONE) {
|
||||
return(state);
|
||||
}
|
||||
|
||||
// set default encoding
|
||||
state = setEncoding(0);
|
||||
if(state != ERR_NONE) {
|
||||
return(state);
|
||||
}
|
||||
|
||||
// set default packet length mode
|
||||
state = variablePacketLengthMode();
|
||||
if (state != ERR_NONE) {
|
||||
return(state);
|
||||
}
|
||||
|
||||
return(state);
|
||||
}
|
||||
|
@ -174,6 +198,8 @@ int16_t SX127x::transmit(uint8_t* data, size_t len, uint8_t addr) {
|
|||
return(ERR_TX_TIMEOUT);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
return(ERR_UNKNOWN);
|
||||
}
|
||||
|
||||
// update data rate
|
||||
|
@ -399,7 +425,7 @@ int16_t SX127x::startTransmit(uint8_t* data, size_t len, uint8_t addr) {
|
|||
int16_t modem = getActiveModem();
|
||||
if(modem == SX127X_LORA) {
|
||||
// check packet length
|
||||
if(len >= 256) {
|
||||
if(len >= SX127X_MAX_PACKET_LENGTH) {
|
||||
return(ERR_PACKET_TOO_LONG);
|
||||
}
|
||||
|
||||
|
@ -429,7 +455,7 @@ int16_t SX127x::startTransmit(uint8_t* data, size_t len, uint8_t addr) {
|
|||
|
||||
} else if(modem == SX127X_FSK_OOK) {
|
||||
// check packet length
|
||||
if(len >= 64) {
|
||||
if(len >= SX127X_MAX_PACKET_LENGTH_FSK) {
|
||||
return(ERR_PACKET_TOO_LONG);
|
||||
}
|
||||
|
||||
|
@ -467,6 +493,9 @@ int16_t SX127x::readData(uint8_t* data, size_t len) {
|
|||
int16_t modem = getActiveModem();
|
||||
size_t length = len;
|
||||
|
||||
// put module to standby
|
||||
standby();
|
||||
|
||||
if(modem == SX127X_LORA) {
|
||||
// len set to maximum indicates unknown packet length, read the number of actually received bytes
|
||||
if(len == SX127X_MAX_PACKET_LENGTH) {
|
||||
|
@ -888,6 +917,60 @@ size_t SX127x::getPacketLength(bool update) {
|
|||
return(_packetLength);
|
||||
}
|
||||
|
||||
int16_t SX127x::fixedPacketLengthMode(uint8_t len) {
|
||||
return(SX127x::setPacketMode(SX127X_PACKET_FIXED, len));
|
||||
}
|
||||
|
||||
int16_t SX127x::variablePacketLengthMode(uint8_t maxLen) {
|
||||
return(SX127x::setPacketMode(SX127X_PACKET_VARIABLE, maxLen));
|
||||
}
|
||||
|
||||
int16_t SX127x::setRSSIConfig(uint8_t smoothingSamples, int8_t offset) {
|
||||
// check active modem
|
||||
if(getActiveModem() != SX127X_FSK_OOK) {
|
||||
return(ERR_WRONG_MODEM);
|
||||
}
|
||||
|
||||
// set mode to standby
|
||||
int16_t state = standby();
|
||||
if(state != ERR_NONE) {
|
||||
return(state);
|
||||
}
|
||||
|
||||
// check provided values
|
||||
if(!(smoothingSamples <= 7)) {
|
||||
return(ERR_INVALID_NUM_SAMPLES);
|
||||
}
|
||||
|
||||
if(!((offset >= -16) && (offset <= 15))) {
|
||||
return(ERR_INVALID_RSSI_OFFSET);
|
||||
}
|
||||
|
||||
// set new register values
|
||||
state = _mod->SPIsetRegValue(SX127X_REG_RSSI_CONFIG, offset, 7, 3);
|
||||
state |= _mod->SPIsetRegValue(SX127X_REG_RSSI_CONFIG, smoothingSamples, 2, 0);
|
||||
return(state);
|
||||
}
|
||||
|
||||
int16_t SX127x::setEncoding(uint8_t encoding) {
|
||||
// check active modem
|
||||
if(getActiveModem() != SX127X_FSK_OOK) {
|
||||
return(ERR_WRONG_MODEM);
|
||||
}
|
||||
|
||||
// set encoding
|
||||
switch(encoding) {
|
||||
case 0:
|
||||
return(_mod->SPIsetRegValue(SX127X_REG_PACKET_CONFIG_1, SX127X_DC_FREE_NONE, 6, 5));
|
||||
case 1:
|
||||
return(_mod->SPIsetRegValue(SX127X_REG_PACKET_CONFIG_1, SX127X_DC_FREE_MANCHESTER, 6, 5));
|
||||
case 2:
|
||||
return(_mod->SPIsetRegValue(SX127X_REG_PACKET_CONFIG_1, SX127X_DC_FREE_WHITENING, 6, 5));
|
||||
default:
|
||||
return(ERR_INVALID_ENCODING);
|
||||
}
|
||||
}
|
||||
|
||||
int16_t SX127x::config() {
|
||||
// turn off frequency hopping
|
||||
int16_t state = _mod->SPIsetRegValue(SX127X_REG_HOP_PERIOD, SX127X_HOP_PERIOD_OFF);
|
||||
|
@ -943,6 +1026,34 @@ int16_t SX127x::configFSK() {
|
|||
return(state);
|
||||
}
|
||||
|
||||
int16_t SX127x::setPacketMode(uint8_t mode, uint8_t len) {
|
||||
// check packet length
|
||||
if (len > SX127X_MAX_PACKET_LENGTH_FSK) {
|
||||
return(ERR_PACKET_TOO_LONG);
|
||||
}
|
||||
|
||||
// check active modem
|
||||
if(getActiveModem() != SX127X_FSK_OOK) {
|
||||
return(ERR_WRONG_MODEM);
|
||||
}
|
||||
|
||||
// set to fixed packet length
|
||||
int16_t state = _mod->SPIsetRegValue(SX127X_REG_PACKET_CONFIG_1, mode, 7, 7);
|
||||
if(state != ERR_NONE) {
|
||||
return(state);
|
||||
}
|
||||
|
||||
// set length to register
|
||||
state = _mod->SPIsetRegValue(SX127X_REG_PAYLOAD_LENGTH_FSK, len);
|
||||
if(state != ERR_NONE) {
|
||||
return(state);
|
||||
}
|
||||
|
||||
// update cached value
|
||||
_packetLengthConfig = mode;
|
||||
return(state);
|
||||
}
|
||||
|
||||
bool SX127x::findChip(uint8_t ver) {
|
||||
uint8_t i = 0;
|
||||
bool flagFound = false;
|
||||
|
@ -952,16 +1063,15 @@ bool SX127x::findChip(uint8_t ver) {
|
|||
flagFound = true;
|
||||
} else {
|
||||
#ifdef RADIOLIB_DEBUG
|
||||
Serial.print(F("SX127x not found! ("));
|
||||
Serial.print(i + 1);
|
||||
Serial.print(F(" of 10 tries) SX127X_REG_VERSION == "));
|
||||
RADIOLIB_DEBUG_PRINT(F("SX127x not found! ("));
|
||||
RADIOLIB_DEBUG_PRINT(i + 1);
|
||||
RADIOLIB_DEBUG_PRINT(F(" of 10 tries) SX127X_REG_VERSION == "));
|
||||
|
||||
char buffHex[5];
|
||||
sprintf(buffHex, "0x%02X", version);
|
||||
Serial.print(buffHex);
|
||||
Serial.print(F(", expected 0x00"));
|
||||
Serial.print(ver, HEX);
|
||||
Serial.println();
|
||||
RADIOLIB_DEBUG_PRINT(buffHex);
|
||||
RADIOLIB_DEBUG_PRINT(F(", expected 0x00"));
|
||||
RADIOLIB_DEBUG_PRINTLN(ver, HEX);
|
||||
#endif
|
||||
delay(1000);
|
||||
i++;
|
||||
|
@ -1010,23 +1120,23 @@ void SX127x::clearFIFO(size_t count) {
|
|||
|
||||
#ifdef RADIOLIB_DEBUG
|
||||
void SX127x::regDump() {
|
||||
Serial.println();
|
||||
Serial.println(F("ADDR\tVALUE"));
|
||||
RADIOLIB_DEBUG_PRINTLN();
|
||||
RADIOLIB_DEBUG_PRINTLN(F("ADDR\tVALUE"));
|
||||
for(uint16_t addr = 0x01; addr <= 0x70; addr++) {
|
||||
if(addr <= 0x0F) {
|
||||
Serial.print(F("0x0"));
|
||||
RADIOLIB_DEBUG_PRINT(F("0x0"));
|
||||
} else {
|
||||
Serial.print(F("0x"));
|
||||
RADIOLIB_DEBUG_PRINT(F("0x"));
|
||||
}
|
||||
Serial.print(addr, HEX);
|
||||
Serial.print('\t');
|
||||
RADIOLIB_DEBUG_PRINT(addr, HEX);
|
||||
RADIOLIB_DEBUG_PRINT('\t');
|
||||
uint8_t val = _mod->SPIreadRegister(addr);
|
||||
if(val <= 0x0F) {
|
||||
Serial.print(F("0x0"));
|
||||
RADIOLIB_DEBUG_PRINT(F("0x0"));
|
||||
} else {
|
||||
Serial.print(F("0x"));
|
||||
RADIOLIB_DEBUG_PRINT(F("0x"));
|
||||
}
|
||||
Serial.println(val, HEX);
|
||||
RADIOLIB_DEBUG_PRINTLN(val, HEX);
|
||||
|
||||
delay(50);
|
||||
}
|
|
@ -1,15 +1,16 @@
|
|||
#ifndef _RADIOLIB_SX127X_H
|
||||
#define _RADIOLIB_SX127X_H
|
||||
|
||||
#include "TypeDef.h"
|
||||
#include "Module.h"
|
||||
#include "../../TypeDef.h"
|
||||
#include "../../Module.h"
|
||||
|
||||
#include "../protocols/PhysicalLayer.h"
|
||||
#include "../../protocols/PhysicalLayer/PhysicalLayer.h"
|
||||
|
||||
// SX127x physical layer properties
|
||||
#define SX127X_CRYSTAL_FREQ 32.0
|
||||
#define SX127X_DIV_EXPONENT 19
|
||||
#define SX127X_MAX_PACKET_LENGTH 256
|
||||
#define SX127X_MAX_PACKET_LENGTH 255
|
||||
#define SX127X_MAX_PACKET_LENGTH_FSK 64
|
||||
|
||||
// SX127x series common LoRa registers
|
||||
#define SX127X_REG_FIFO 0x00
|
||||
|
@ -842,11 +843,52 @@ class SX127x: public PhysicalLayer {
|
|||
*/
|
||||
size_t getPacketLength(bool update = true);
|
||||
|
||||
/*!
|
||||
\brief Set modem in fixed packet length mode. Available in FSK mode only.
|
||||
|
||||
\param len Packet length.
|
||||
|
||||
\returns \ref status_codes
|
||||
*/
|
||||
int16_t fixedPacketLengthMode(uint8_t len = SX127X_MAX_PACKET_LENGTH_FSK);
|
||||
|
||||
/*!
|
||||
\brief Set modem in variable packet length mode. Available in FSK mode only.
|
||||
|
||||
\param len Maximum packet length.
|
||||
|
||||
\returns \ref status_codes
|
||||
*/
|
||||
int16_t variablePacketLengthMode(uint8_t maxLen = SX127X_MAX_PACKET_LENGTH_FSK);
|
||||
|
||||
/*!
|
||||
\brief Sets RSSI measurement configuration in FSK mode.
|
||||
|
||||
\param smoothingSamples Number of samples taken to avergae the RSSI result.
|
||||
numSamples = 2 ^ (1 + smoothingSamples), allowed values are in range 0 (2 samples) - 7 (256 samples)
|
||||
|
||||
\param offset Signed RSSI offset that will be automatically compensated. 1 dB per LSB, defaults to 0, allowed values are in range -16 dB to +15 dB.
|
||||
|
||||
\returns \ref status_codes
|
||||
*/
|
||||
int16_t setRSSIConfig(uint8_t smoothingSamples, int8_t offset = 0);
|
||||
|
||||
/*!
|
||||
\brief Sets transmission encoding. Only available in FSK mode.
|
||||
|
||||
\param encoding Encoding to be used. Set to 0 for NRZ, 1 for Manchester and 2 for whitening.
|
||||
|
||||
\returns \ref status_codes
|
||||
*/
|
||||
int16_t setEncoding(uint8_t encoding);
|
||||
|
||||
#ifdef RADIOLIB_DEBUG
|
||||
void regDump();
|
||||
#endif
|
||||
|
||||
#ifndef RADIOLIB_GODMODE
|
||||
protected:
|
||||
#endif
|
||||
Module* _mod;
|
||||
|
||||
float _freq;
|
||||
|
@ -862,12 +904,15 @@ class SX127x: public PhysicalLayer {
|
|||
int16_t configFSK();
|
||||
int16_t getActiveModem();
|
||||
int16_t directMode();
|
||||
int16_t setPacketMode(uint8_t mode, uint8_t len);
|
||||
|
||||
|
||||
#ifndef RADIOLIB_GODMODE
|
||||
private:
|
||||
#endif
|
||||
float _dataRate;
|
||||
size_t _packetLength;
|
||||
bool _packetLengthQueried; // FSK packet length is the first byte in FIFO, length can only be queried once
|
||||
uint8_t _packetLengthConfig;
|
||||
|
||||
bool findChip(uint8_t ver);
|
||||
int16_t setMode(uint8_t mode);
|
|
@ -5,20 +5,19 @@ XBee::XBee(Module* mod) {
|
|||
_frameID = 0x01;
|
||||
_frameLength = 0;
|
||||
_frameHeaderProcessed = false;
|
||||
_packetData = new char[0];
|
||||
}
|
||||
|
||||
int16_t XBee::begin(long speed) {
|
||||
// set module properties
|
||||
_mod->baudrate = speed;
|
||||
_mod->init(USE_UART, INT_1);
|
||||
|
||||
_mod->init(RADIOLIB_USE_UART, RADIOLIB_INT_1);
|
||||
|
||||
// reset module
|
||||
reset();
|
||||
|
||||
|
||||
// empty UART buffer (garbage data)
|
||||
_mod->ATemptyBuffer();
|
||||
|
||||
|
||||
// try to find the XBee
|
||||
bool flagFound = false;
|
||||
uint8_t i = 0;
|
||||
|
@ -26,29 +25,29 @@ int16_t XBee::begin(long speed) {
|
|||
// hardware reset should return 2 modem status frames - 1st status 0x00, second status 0x06
|
||||
int16_t state = readApiFrame(0x00, 1, 2000);
|
||||
readApiFrame(0x00, 1, 2000);
|
||||
|
||||
|
||||
if(state == ERR_NONE) {
|
||||
flagFound = true;
|
||||
} else {
|
||||
DEBUG_PRINT(F("XBee not found! ("));
|
||||
DEBUG_PRINT(i + 1);
|
||||
DEBUG_PRINT(F(" of 10 tries) STATE == "));
|
||||
DEBUG_PRINTLN(state);
|
||||
DEBUG_PRINTLN(F("Resetting ..."));
|
||||
RADIOLIB_DEBUG_PRINT(F("XBee not found! ("));
|
||||
RADIOLIB_DEBUG_PRINT(i + 1);
|
||||
RADIOLIB_DEBUG_PRINT(F(" of 10 tries) STATE == "));
|
||||
RADIOLIB_DEBUG_PRINTLN(state);
|
||||
RADIOLIB_DEBUG_PRINTLN(F("Resetting ..."));
|
||||
reset();
|
||||
delay(1000);
|
||||
_mod->ATemptyBuffer();
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if(!flagFound) {
|
||||
DEBUG_PRINTLN(F("No XBee found!"));
|
||||
RADIOLIB_DEBUG_PRINTLN(F("No XBee found!"));
|
||||
return(ERR_CMD_MODE_FAILED);
|
||||
} else {
|
||||
DEBUG_PRINTLN(F("Found XBee!"));
|
||||
RADIOLIB_DEBUG_PRINTLN(F("Found XBee!"));
|
||||
}
|
||||
|
||||
|
||||
return(ERR_NONE);
|
||||
}
|
||||
|
||||
|
@ -69,18 +68,24 @@ int16_t XBee::transmit(uint8_t* dest, uint8_t* destNetwork, const char* payload,
|
|||
// build the frame
|
||||
size_t payloadLen = strlen(payload);
|
||||
size_t dataLen = 8 + 2 + 1 + 1 + payloadLen;
|
||||
uint8_t* cmd = new uint8_t[dataLen];
|
||||
#ifdef RADIOLIB_STATIC_ONLY
|
||||
uint8_t cmd[RADIOLIB_STATIC_ARRAY_SIZE];
|
||||
#else
|
||||
uint8_t* cmd = new uint8_t[dataLen];
|
||||
#endif
|
||||
memcpy(cmd, dest, 8);
|
||||
memcpy(cmd + 8, destNetwork, 2);
|
||||
cmd[10] = radius;
|
||||
cmd[11] = 0x01; // options: no retries
|
||||
memcpy(cmd + 12, payload, payloadLen);
|
||||
|
||||
|
||||
// send frame
|
||||
uint8_t frameID = _frameID++;
|
||||
sendApiFrame(XBEE_API_FRAME_ZIGBEE_TRANSMIT_REQUEST, frameID, cmd, dataLen);
|
||||
delete[] cmd;
|
||||
|
||||
#ifndef RADIOLIB_STATIC_ONLY
|
||||
delete[] cmd;
|
||||
#endif
|
||||
|
||||
// get response code
|
||||
return(readApiFrame(frameID, 5));
|
||||
}
|
||||
|
@ -90,47 +95,55 @@ size_t XBee::available() {
|
|||
size_t serialBytes = _mod->ModuleSerial->available();
|
||||
if(serialBytes < 3) {
|
||||
return(0);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
uint8_t header[3];
|
||||
if(!_frameHeaderProcessed) {
|
||||
// read frame header
|
||||
for(uint8_t i = 0; i < 3; i++) {
|
||||
header[i] = _mod->ModuleSerial->read();
|
||||
}
|
||||
|
||||
|
||||
// check if we received API frame
|
||||
if(header[0] != XBEE_API_START) {
|
||||
return(0);
|
||||
}
|
||||
|
||||
|
||||
// get expected frame length
|
||||
_frameLength = ((header[1] << 8) | header[2]) + 1;
|
||||
_frameHeaderProcessed = true;
|
||||
}
|
||||
|
||||
|
||||
// check if the header is complete
|
||||
if(serialBytes < _frameLength) {
|
||||
return(0);
|
||||
}
|
||||
|
||||
uint8_t* frame = new uint8_t[_frameLength]; //24
|
||||
|
||||
#ifdef RADIOLIB_STATIC_ONLY
|
||||
char frame[RADIOLIB_STATIC_ARRAY_SIZE];
|
||||
#else
|
||||
uint8_t* frame = new uint8_t[_frameLength];
|
||||
#endif
|
||||
for(size_t i = 0; i < _frameLength; i++) {
|
||||
frame[i] = _mod->ModuleSerial->read();
|
||||
}
|
||||
|
||||
|
||||
// save packet source and data
|
||||
size_t payloadLength = _frameLength - 12;
|
||||
delete[] _packetData;
|
||||
_packetData = new char[payloadLength];
|
||||
#ifndef RADIOLIB_STATIC_ONLY
|
||||
delete[] _packetData;
|
||||
_packetData = new char[payloadLength];
|
||||
#endif
|
||||
memcpy(_packetData, frame + 12, payloadLength - 1);
|
||||
_packetData[payloadLength - 1] = '\0';
|
||||
memcpy(_packetSource, frame + 1, 8);
|
||||
|
||||
delete[] frame;
|
||||
|
||||
#ifndef RADIOLIB_STATIC_ONLY
|
||||
delete[] frame;
|
||||
#endif
|
||||
_frameLength = 0;
|
||||
_frameHeaderProcessed = false;
|
||||
|
||||
|
||||
// return number of bytes in payload
|
||||
return(payloadLength);
|
||||
}
|
||||
|
@ -153,48 +166,48 @@ int16_t XBee::setPanId(uint8_t* panId) {
|
|||
uint8_t cmd[10];
|
||||
memcpy(cmd, "ID", 2);
|
||||
memcpy(cmd + 2, panId, 8);
|
||||
|
||||
|
||||
// send frame
|
||||
uint8_t frameID = _frameID++;
|
||||
sendApiFrame(XBEE_API_FRAME_AT_COMMAND_QUEUE, frameID, cmd, 10);
|
||||
|
||||
|
||||
// get response code
|
||||
int16_t state = readApiFrame(frameID, 4);
|
||||
if(state != ERR_NONE) {
|
||||
return(state);
|
||||
}
|
||||
|
||||
|
||||
// confirm changes
|
||||
return(confirmChanges());
|
||||
}
|
||||
|
||||
XBeeSerial::XBeeSerial(Module* mod) : ISerial(mod) {
|
||||
|
||||
|
||||
}
|
||||
|
||||
int16_t XBeeSerial::begin(long speed) {
|
||||
// set module properties
|
||||
_mod->AtLineFeed = "\r";
|
||||
_mod->baudrate = speed;
|
||||
_mod->init(USE_UART, INT_NONE);
|
||||
|
||||
_mod->init(RADIOLIB_USE_UART, RADIOLIB_INT_NONE);
|
||||
|
||||
// empty UART buffer (garbage data)
|
||||
_mod->ATemptyBuffer();
|
||||
|
||||
|
||||
// enter command mode
|
||||
DEBUG_PRINTLN(F("Entering command mode ..."));
|
||||
RADIOLIB_DEBUG_PRINTLN(F("Entering command mode ..."));
|
||||
if(!enterCmdMode()) {
|
||||
return(ERR_CMD_MODE_FAILED);
|
||||
}
|
||||
|
||||
|
||||
// test AT setup
|
||||
DEBUG_PRINTLN(F("Sending test command ..."));
|
||||
RADIOLIB_DEBUG_PRINTLN(F("Sending test command ..."));
|
||||
if(!_mod->ATsendCommand("AT")) {
|
||||
return(ERR_AT_FAILED);
|
||||
}
|
||||
|
||||
|
||||
// exit command mode
|
||||
DEBUG_PRINTLN(F("Exiting command mode ..."));
|
||||
RADIOLIB_DEBUG_PRINTLN(F("Exiting command mode ..."));
|
||||
if(!_mod->ATsendCommand("ATCN")) {
|
||||
return(ERR_AT_FAILED);
|
||||
}
|
||||
|
@ -212,93 +225,111 @@ void XBeeSerial::reset() {
|
|||
|
||||
int16_t XBeeSerial::setDestinationAddress(const char* destinationAddressHigh, const char* destinationAddressLow) {
|
||||
// enter command mode
|
||||
DEBUG_PRINTLN(F("Entering command mode ..."));
|
||||
RADIOLIB_DEBUG_PRINTLN(F("Entering command mode ..."));
|
||||
if(!enterCmdMode()) {
|
||||
return(ERR_CMD_MODE_FAILED);
|
||||
}
|
||||
|
||||
|
||||
// set higher address bytes
|
||||
DEBUG_PRINTLN(F("Setting address (high) ..."));
|
||||
char* addressHigh = new char[strlen(destinationAddressHigh) + 4];
|
||||
RADIOLIB_DEBUG_PRINTLN(F("Setting address (high) ..."));
|
||||
#ifdef RADIOLIB_STATIC_ONLY
|
||||
char addressHigh[13];
|
||||
#else
|
||||
char* addressHigh = new char[strlen(destinationAddressHigh) + 4];
|
||||
#endif
|
||||
strcpy(addressHigh, "ATDH");
|
||||
strcat(addressHigh, destinationAddressHigh);
|
||||
bool res = _mod->ATsendCommand(addressHigh);
|
||||
delete[] addressHigh;
|
||||
#ifndef RADIOLIB_STATIC_ONLY
|
||||
delete[] addressHigh;
|
||||
#endif
|
||||
if(!res) {
|
||||
return(ERR_AT_FAILED);
|
||||
}
|
||||
|
||||
|
||||
// set lower address bytes
|
||||
DEBUG_PRINTLN(F("Setting address (low) ..."));
|
||||
char* addressLow = new char[strlen(destinationAddressLow) + 4];
|
||||
RADIOLIB_DEBUG_PRINTLN(F("Setting address (low) ..."));
|
||||
#ifdef RADIOLIB_STATIC_ONLY
|
||||
char addressLow[13];
|
||||
#else
|
||||
char* addressLow = new char[strlen(destinationAddressLow) + 4];
|
||||
#endif
|
||||
strcpy(addressLow, "ATDL");
|
||||
strcat(addressLow, destinationAddressLow);
|
||||
res = _mod->ATsendCommand(addressLow);
|
||||
delete[] addressLow;
|
||||
#ifndef RADIOLIB_STATIC_ONLY
|
||||
delete[] addressLow;
|
||||
#endif
|
||||
if(!res) {
|
||||
return(ERR_AT_FAILED);
|
||||
}
|
||||
|
||||
|
||||
// exit command mode
|
||||
DEBUG_PRINTLN(F("Exiting command mode ..."));
|
||||
RADIOLIB_DEBUG_PRINTLN(F("Exiting command mode ..."));
|
||||
if(!_mod->ATsendCommand("ATCN")) {
|
||||
return(ERR_AT_FAILED);
|
||||
}
|
||||
|
||||
|
||||
return(ERR_NONE);
|
||||
}
|
||||
|
||||
int16_t XBeeSerial::setPanId(const char* panId) {
|
||||
// enter command mode
|
||||
DEBUG_PRINTLN(F("Entering command mode ..."));
|
||||
RADIOLIB_DEBUG_PRINTLN(F("Entering command mode ..."));
|
||||
if(!enterCmdMode()) {
|
||||
return(ERR_CMD_MODE_FAILED);
|
||||
}
|
||||
|
||||
|
||||
// set PAN ID
|
||||
DEBUG_PRINTLN(F("Setting PAN ID ..."));
|
||||
char* cmd = new char[strlen(panId) + 4];
|
||||
RADIOLIB_DEBUG_PRINTLN(F("Setting PAN ID ..."));
|
||||
#ifdef RADIOLIB_STATIC_ONLY
|
||||
char cmd[21];
|
||||
#else
|
||||
char* cmd = new char[strlen(panId) + 4];
|
||||
#endif
|
||||
strcpy(cmd, "ATID");
|
||||
strcat(cmd, panId);
|
||||
bool res = _mod->ATsendCommand(cmd);
|
||||
delete[] cmd;
|
||||
#ifndef RADIOLIB_STATIC_ONLY
|
||||
delete[] cmd;
|
||||
#endif
|
||||
if(!res) {
|
||||
return(ERR_AT_FAILED);
|
||||
}
|
||||
|
||||
|
||||
// exit command mode
|
||||
DEBUG_PRINTLN(F("Exiting command mode ..."));
|
||||
RADIOLIB_DEBUG_PRINTLN(F("Exiting command mode ..."));
|
||||
if(!_mod->ATsendCommand("ATCN")) {
|
||||
return(ERR_AT_FAILED);
|
||||
}
|
||||
|
||||
|
||||
return(ERR_NONE);
|
||||
}
|
||||
|
||||
bool XBeeSerial::enterCmdMode() {
|
||||
for(uint8_t i = 0; i < 10; i++) {
|
||||
delay(1000);
|
||||
|
||||
|
||||
_mod->ModuleSerial->write('+');
|
||||
_mod->ModuleSerial->write('+');
|
||||
_mod->ModuleSerial->write('+');
|
||||
|
||||
|
||||
delay(1000);
|
||||
|
||||
|
||||
if(_mod->ATgetResponse()) {
|
||||
return(true);
|
||||
} else {
|
||||
DEBUG_PRINT(F("Unable to enter command mode! ("));
|
||||
DEBUG_PRINT(i + 1);
|
||||
DEBUG_PRINTLN(F(" of 10 tries)"));
|
||||
|
||||
RADIOLIB_DEBUG_PRINT(F("Unable to enter command mode! ("));
|
||||
RADIOLIB_DEBUG_PRINT(i + 1);
|
||||
RADIOLIB_DEBUG_PRINTLN(F(" of 10 tries)"));
|
||||
|
||||
reset();
|
||||
|
||||
|
||||
_mod->ATsendCommand("ATCN");
|
||||
}
|
||||
}
|
||||
|
||||
DEBUG_PRINTLN(F("Terminated, check your wiring. Is AT FW uploaded?"));
|
||||
|
||||
RADIOLIB_DEBUG_PRINTLN(F("Terminated, check your wiring. Is AT FW uploaded?"));
|
||||
return(false);
|
||||
}
|
||||
|
||||
|
@ -306,23 +337,23 @@ int16_t XBee::confirmChanges() {
|
|||
// save changes to non-volatile memory
|
||||
uint8_t frameID = _frameID++;
|
||||
sendApiFrame(XBEE_API_FRAME_AT_COMMAND_QUEUE, frameID, "WR");
|
||||
|
||||
|
||||
// get response code
|
||||
int16_t state = readApiFrame(frameID, 4);
|
||||
if(state != ERR_NONE) {
|
||||
return(state);
|
||||
}
|
||||
|
||||
|
||||
// apply changes
|
||||
frameID = _frameID++;
|
||||
sendApiFrame(XBEE_API_FRAME_AT_COMMAND_QUEUE, frameID, "AC");
|
||||
|
||||
|
||||
// get response code
|
||||
state = readApiFrame(frameID, 4);
|
||||
if(state != ERR_NONE) {
|
||||
return(state);
|
||||
}
|
||||
|
||||
|
||||
return(state);
|
||||
}
|
||||
|
||||
|
@ -333,43 +364,49 @@ void XBee::sendApiFrame(uint8_t type, uint8_t id, const char* data) {
|
|||
void XBee::sendApiFrame(uint8_t type, uint8_t id, uint8_t* data, uint16_t length) {
|
||||
// build the API frame
|
||||
size_t frameLength = 1 + 2 + length + 1 + 2;
|
||||
uint8_t* frame = new uint8_t[frameLength];
|
||||
|
||||
#ifdef RADIOLIB_STATIC_ONLY
|
||||
uint8_t frame[RADIOLIB_STATIC_ARRAY_SIZE];
|
||||
#else
|
||||
uint8_t* frame = new uint8_t[frameLength];
|
||||
#endif
|
||||
|
||||
frame[0] = 0x7E; // start delimiter
|
||||
frame[1] = ((length + 2) & 0xFF00) >> 8; // length MSB
|
||||
frame[2] = (length + 2) & 0x00FF; // length LSB
|
||||
frame[3] = type; // frame type
|
||||
frame[4] = id; // frame ID
|
||||
memcpy(frame + 5, data, length); // data
|
||||
|
||||
|
||||
// calculate the checksum
|
||||
uint8_t checksum = 0;
|
||||
for(uint16_t i = 3; i < frameLength - 1; i++) {
|
||||
checksum += frame[i];
|
||||
}
|
||||
frame[5 + length] = 0xFF - checksum;
|
||||
|
||||
|
||||
// send the frame
|
||||
for(uint16_t i = 0; i < frameLength; i++) {
|
||||
_mod->ModuleSerial->write(frame[i]);
|
||||
}
|
||||
|
||||
|
||||
// deallocate memory
|
||||
delete[] frame;
|
||||
#ifndef RADIOLIB_STATIC_ONLY
|
||||
delete[] frame;
|
||||
#endif
|
||||
}
|
||||
|
||||
int16_t XBee::readApiFrame(uint8_t frameID, uint8_t codePos, uint16_t timeout) {
|
||||
// TODO: modemStatus frames may be sent at any time, interfering with frame parsing. Add check to make sure this does not happen.
|
||||
|
||||
|
||||
// get number of bytes in response (must be enough to read the length field
|
||||
uint16_t numBytes = getNumBytes(timeout/2, 3);
|
||||
if(numBytes == 0) {
|
||||
return(ERR_FRAME_NO_RESPONSE);
|
||||
}
|
||||
|
||||
|
||||
// checksum byte is not included in length field
|
||||
numBytes++;
|
||||
|
||||
|
||||
// wait until all response bytes are available (5s timeout)
|
||||
uint32_t start = millis();
|
||||
while(_mod->ModuleSerial->available() < (int16_t)numBytes) {
|
||||
|
@ -377,40 +414,46 @@ int16_t XBee::readApiFrame(uint8_t frameID, uint8_t codePos, uint16_t timeout) {
|
|||
return(ERR_FRAME_MALFORMED);
|
||||
}
|
||||
}
|
||||
DEBUG_PRINT(F("frame data field length: "));
|
||||
DEBUG_PRINTLN(numBytes);
|
||||
|
||||
RADIOLIB_DEBUG_PRINT(F("frame data field length: "));
|
||||
RADIOLIB_DEBUG_PRINTLN(numBytes);
|
||||
|
||||
// read the response
|
||||
uint8_t* resp = new uint8_t[numBytes];
|
||||
#ifdef RADIOLIB_STATIC_ONLY
|
||||
uint8_t resp[RADIOLIB_STATIC_ARRAY_SIZE];
|
||||
#else
|
||||
uint8_t* resp = new uint8_t[numBytes];
|
||||
#endif
|
||||
for(uint16_t i = 0; i < numBytes; i++) {
|
||||
resp[i] = _mod->ModuleSerial->read();
|
||||
}
|
||||
|
||||
// verify checksum
|
||||
|
||||
// verify checksum
|
||||
uint8_t checksum = 0;
|
||||
for(uint16_t i = 0; i < numBytes; i++) {
|
||||
DEBUG_PRINT(resp[i], HEX);
|
||||
DEBUG_PRINT('\t');
|
||||
RADIOLIB_DEBUG_PRINT(resp[i], HEX);
|
||||
RADIOLIB_DEBUG_PRINT('\t');
|
||||
checksum += resp[i];
|
||||
}
|
||||
DEBUG_PRINTLN();
|
||||
RADIOLIB_DEBUG_PRINTLN();
|
||||
if(checksum != 0xFF) {
|
||||
DEBUG_PRINTLN(checksum, HEX);
|
||||
RADIOLIB_DEBUG_PRINTLN(checksum, HEX);
|
||||
return(ERR_FRAME_INCORRECT_CHECKSUM);
|
||||
}
|
||||
|
||||
|
||||
// check frame ID
|
||||
if(resp[1] != frameID) {
|
||||
DEBUG_PRINT(F("received frame ID: "));
|
||||
DEBUG_PRINTLN(resp[1]);
|
||||
DEBUG_PRINT(F("expected frame ID: "));
|
||||
DEBUG_PRINTLN(frameID);
|
||||
RADIOLIB_DEBUG_PRINT(F("received frame ID: "));
|
||||
RADIOLIB_DEBUG_PRINTLN(resp[1]);
|
||||
RADIOLIB_DEBUG_PRINT(F("expected frame ID: "));
|
||||
RADIOLIB_DEBUG_PRINTLN(frameID);
|
||||
return(ERR_FRAME_UNEXPECTED_ID);
|
||||
}
|
||||
|
||||
|
||||
// codePos does not include start delimiter and frame ID
|
||||
uint8_t code = resp[codePos];
|
||||
delete[] resp;
|
||||
#ifndef RADIOLIB_STATIC_ONLY
|
||||
delete[] resp;
|
||||
#endif
|
||||
return(code);
|
||||
}
|
||||
|
||||
|
@ -422,21 +465,21 @@ uint16_t XBee::getNumBytes(uint32_t timeout, size_t minBytes) {
|
|||
return(0);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// read response
|
||||
uint8_t resp[3];
|
||||
uint8_t i = 0;
|
||||
DEBUG_PRINT(F("reading frame length: "));
|
||||
RADIOLIB_DEBUG_PRINT(F("reading frame length: "));
|
||||
while(_mod->ModuleSerial->available() > 0) {
|
||||
uint8_t b = _mod->ModuleSerial->read();
|
||||
DEBUG_PRINT(b, HEX);
|
||||
DEBUG_PRINT('\t');
|
||||
RADIOLIB_DEBUG_PRINT(b, HEX);
|
||||
RADIOLIB_DEBUG_PRINT('\t');
|
||||
resp[i++] = b;
|
||||
if(i == 3) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
DEBUG_PRINTLN();
|
||||
|
||||
RADIOLIB_DEBUG_PRINTLN();
|
||||
|
||||
return((resp[1] << 8) | resp[2]);
|
||||
}
|
|
@ -1,8 +1,8 @@
|
|||
#ifndef _RADIOLIB_XBEE_H
|
||||
#define _RADIOLIB_XBEE_H
|
||||
|
||||
#include "ISerial.h"
|
||||
#include "TypeDef.h"
|
||||
#include "../../ISerial.h"
|
||||
#include "../../TypeDef.h"
|
||||
|
||||
// API reserved characters
|
||||
#define XBEE_API_START 0x7E
|
||||
|
@ -81,7 +81,9 @@ class XBeeSerial: public ISerial {
|
|||
*/
|
||||
int16_t setPanId(const char* panID);
|
||||
|
||||
#ifndef RADIOLIB_GODMODE
|
||||
private:
|
||||
#endif
|
||||
bool enterCmdMode();
|
||||
|
||||
};
|
||||
|
@ -170,13 +172,19 @@ class XBee {
|
|||
*/
|
||||
int16_t setPanId(uint8_t* panID);
|
||||
|
||||
#ifndef RADIOLIB_GODMODE
|
||||
private:
|
||||
#endif
|
||||
Module* _mod;
|
||||
uint8_t _frameID;
|
||||
size_t _frameLength;
|
||||
bool _frameHeaderProcessed;
|
||||
|
||||
char* _packetData;
|
||||
#ifdef RADIOLIB_STATIC_ONLY
|
||||
char _packetData[RADIOLIB_STATIC_ARRAY_SIZE];
|
||||
#else
|
||||
char* _packetData = new char[0];
|
||||
#endif
|
||||
uint8_t _packetSource[8];
|
||||
|
||||
int16_t confirmChanges();
|
|
@ -8,7 +8,7 @@ int16_t nRF24::begin(int16_t freq, int16_t dataRate, int8_t power, uint8_t addrW
|
|||
// set module properties
|
||||
_mod->SPIreadCommand = NRF24_CMD_READ;
|
||||
_mod->SPIwriteCommand = NRF24_CMD_WRITE;
|
||||
_mod->init(USE_SPI, INT_BOTH);
|
||||
_mod->init(RADIOLIB_USE_SPI, RADIOLIB_INT_BOTH);
|
||||
|
||||
// override pin mode on INT0 (connected to nRF24 CE pin)
|
||||
pinMode(_mod->getInt0(), OUTPUT);
|
||||
|
@ -20,7 +20,7 @@ int16_t nRF24::begin(int16_t freq, int16_t dataRate, int8_t power, uint8_t addrW
|
|||
// check SPI connection
|
||||
int16_t val = _mod->SPIgetRegValue(NRF24_REG_SETUP_AW);
|
||||
if(!((val >= 1) && (val <= 3))) {
|
||||
DEBUG_PRINTLN(F("No nRF24 found!"));
|
||||
RADIOLIB_DEBUG_PRINTLN(F("No nRF24 found!"));
|
||||
_mod->term();
|
||||
return(ERR_CHIP_NOT_FOUND);
|
||||
}
|
||||
|
@ -386,6 +386,7 @@ int16_t nRF24::setReceivePipe(uint8_t pipeNum, uint8_t* addr) {
|
|||
case 0:
|
||||
_mod->SPIwriteRegisterBurst(NRF24_REG_RX_ADDR_P0, addr, _addrWidth);
|
||||
state |= _mod->SPIsetRegValue(NRF24_REG_EN_RXADDR, NRF24_P0_ON, 0, 0);
|
||||
break;
|
||||
case 1:
|
||||
_mod->SPIwriteRegisterBurst(NRF24_REG_RX_ADDR_P1, addr, _addrWidth);
|
||||
state |= _mod->SPIsetRegValue(NRF24_REG_EN_RXADDR, NRF24_P1_ON, 1, 1);
|
|
@ -1,10 +1,10 @@
|
|||
#ifndef _RADIOLIB_NRF24_H
|
||||
#define _RADIOLIB_NRF24_H
|
||||
|
||||
#include "Module.h"
|
||||
#include "TypeDef.h"
|
||||
#include "../../Module.h"
|
||||
#include "../../TypeDef.h"
|
||||
|
||||
#include "../protocols/PhysicalLayer.h"
|
||||
#include "../../protocols/PhysicalLayer/PhysicalLayer.h"
|
||||
|
||||
// nRF24 physical layer properties (dummy only)
|
||||
#define NRF24_CRYSTAL_FREQ 1.0
|
||||
|
@ -408,7 +408,9 @@ class nRF24: public PhysicalLayer {
|
|||
*/
|
||||
size_t getPacketLength(bool update = true);
|
||||
|
||||
#ifndef RADIOLIB_GODMODE
|
||||
private:
|
||||
#endif
|
||||
Module* _mod;
|
||||
|
||||
uint8_t _addrWidth;
|
|
@ -1,8 +1,8 @@
|
|||
#ifndef _RADIOLIB_HTTP_H
|
||||
#define _RADIOLIB_HTTP_H
|
||||
|
||||
#include "TypeDef.h"
|
||||
#include "TransportLayer.h"
|
||||
#include "../../TypeDef.h"
|
||||
#include "../TransportLayer/TransportLayer.h"
|
||||
|
||||
|
||||
/*!
|
||||
|
@ -58,7 +58,9 @@ class HTTPClient {
|
|||
*/
|
||||
int16_t post(const char* url, const char* content, String& response, const char* contentType = "text/plain");
|
||||
|
||||
#ifndef RADIOLIB_GODMODE
|
||||
private:
|
||||
#endif
|
||||
TransportLayer* _tl;
|
||||
|
||||
uint16_t _port;
|
|
@ -18,21 +18,25 @@ int16_t MQTTClient::connect(const char* host, const char* clientId, const char*
|
|||
remainingLength += (2 + userNameLen);
|
||||
}
|
||||
if(passwordLen > 0) {
|
||||
remainingLength += (2 + passwordLen);
|
||||
remainingLength += (2 + passwordLen);
|
||||
}
|
||||
if((willTopicLen > 0) && (willMessageLen > 0)) {
|
||||
remainingLength += (2 + willTopicLen) + (2 + willMessageLen);
|
||||
}
|
||||
uint8_t encoded[] = {0, 0, 0, 0};
|
||||
size_t encodedBytes = encodeLength(remainingLength, encoded);
|
||||
|
||||
|
||||
// build the CONNECT packet
|
||||
uint8_t* packet = new uint8_t[1 + encodedBytes + remainingLength];
|
||||
|
||||
#ifdef RADIOLIB_STATIC_ONLY
|
||||
uint8_t packet[256];
|
||||
#else
|
||||
uint8_t* packet = new uint8_t[1 + encodedBytes + remainingLength];
|
||||
#endif
|
||||
|
||||
// fixed header
|
||||
packet[0] = (MQTT_CONNECT << 4) | 0b0000;
|
||||
memcpy(packet + 1, encoded, encodedBytes);
|
||||
|
||||
|
||||
// variable header
|
||||
// protocol name
|
||||
size_t pos = encodedBytes + 1;
|
||||
|
@ -40,42 +44,42 @@ int16_t MQTTClient::connect(const char* host, const char* clientId, const char*
|
|||
packet[pos++] = 0x04;
|
||||
memcpy(packet + pos, "MQTT", 4);
|
||||
pos += 4;
|
||||
|
||||
|
||||
// protocol level
|
||||
packet[pos++] = 0x04;
|
||||
|
||||
// flags
|
||||
packet[pos++] = 0x04;
|
||||
|
||||
// flags
|
||||
packet[pos++] = 0x00;
|
||||
if(cleanSession) {
|
||||
packet[encodedBytes + 8] |= MQTT_CONNECT_CLEAN_SESSION;
|
||||
}
|
||||
|
||||
|
||||
// keep alive interval in seconds
|
||||
packet[pos++] = (keepAlive & 0xFF00) >> 8;
|
||||
packet[pos++] = keepAlive & 0x00FF;
|
||||
|
||||
|
||||
// payload
|
||||
// clientId
|
||||
packet[pos++] = (clientIdLen & 0xFF00) >> 8;
|
||||
packet[pos++] = clientIdLen & 0x00FF;
|
||||
memcpy(packet + pos, clientId, clientIdLen);
|
||||
pos += clientIdLen;
|
||||
|
||||
|
||||
// will topic and message
|
||||
if((willTopicLen > 0) && (willMessageLen > 0)) {
|
||||
packet[encodedBytes + 8] |= MQTT_CONNECT_WILL_FLAG;
|
||||
|
||||
|
||||
packet[pos++] = (willTopicLen & 0xFF00) >> 8;
|
||||
packet[pos++] = willTopicLen & 0x00FF;
|
||||
memcpy(packet + pos, willTopic, willTopicLen);
|
||||
pos += willTopicLen;
|
||||
|
||||
|
||||
packet[pos++] = (willMessageLen & 0xFF00) >> 8;
|
||||
packet[pos++] = willMessageLen & 0x00FF;
|
||||
memcpy(packet + pos, willMessage, willMessageLen);
|
||||
pos += willMessageLen;
|
||||
}
|
||||
|
||||
|
||||
// user name
|
||||
if(userNameLen > 0) {
|
||||
packet[encodedBytes + 8] |= MQTT_CONNECT_USER_NAME_FLAG;
|
||||
|
@ -84,7 +88,7 @@ int16_t MQTTClient::connect(const char* host, const char* clientId, const char*
|
|||
memcpy(packet + pos, userName, userNameLen);
|
||||
pos += userNameLen;
|
||||
}
|
||||
|
||||
|
||||
// password
|
||||
if(passwordLen > 0) {
|
||||
packet[encodedBytes + 8] |= MQTT_CONNECT_PASSWORD_FLAG;
|
||||
|
@ -93,54 +97,66 @@ int16_t MQTTClient::connect(const char* host, const char* clientId, const char*
|
|||
memcpy(packet + pos, password, passwordLen);
|
||||
pos += passwordLen;
|
||||
}
|
||||
|
||||
|
||||
// create TCP connection
|
||||
int16_t state = _tl->openTransportConnection(host, "TCP", _port, keepAlive);
|
||||
if(state != ERR_NONE) {
|
||||
delete[] packet;
|
||||
#ifndef RADIOLIB_STATIC_ONLY
|
||||
delete[] packet;
|
||||
#endif
|
||||
return(state);
|
||||
}
|
||||
|
||||
|
||||
// send MQTT packet
|
||||
state = _tl->send(packet, 1 + encodedBytes + remainingLength);
|
||||
delete[] packet;
|
||||
#ifndef RADIOLIB_STATIC_ONLY
|
||||
delete[] packet;
|
||||
#endif
|
||||
if(state != ERR_NONE) {
|
||||
return(state);
|
||||
}
|
||||
|
||||
|
||||
// get the response length (MQTT CONNACK response has to be 4 bytes long)
|
||||
size_t numBytes = _tl->getNumBytes();
|
||||
if(numBytes != 4) {
|
||||
return(ERR_RESPONSE_MALFORMED_AT);
|
||||
}
|
||||
|
||||
|
||||
// read the response
|
||||
uint8_t* response = new uint8_t[numBytes];
|
||||
#ifdef RADIOLIB_STATIC_ONLY
|
||||
uint8_t response[RADIOLIB_STATIC_ARRAY_SIZE];
|
||||
#else
|
||||
uint8_t* response = new uint8_t[numBytes];
|
||||
#endif
|
||||
_tl->receive(response, numBytes);
|
||||
if((response[0] == MQTT_CONNACK << 4) && (response[1] == 2)) {
|
||||
uint8_t returnCode = response[3];
|
||||
delete[] response;
|
||||
#ifndef RADIOLIB_STATIC_ONLY
|
||||
delete[] response;
|
||||
#endif
|
||||
return(returnCode);
|
||||
}
|
||||
|
||||
delete[] response;
|
||||
|
||||
#ifndef RADIOLIB_STATIC_ONLY
|
||||
delete[] response;
|
||||
#endif
|
||||
return(ERR_RESPONSE_MALFORMED);
|
||||
}
|
||||
|
||||
int16_t MQTTClient::disconnect() {
|
||||
// build the DISCONNECT packet
|
||||
uint8_t packet[2];
|
||||
|
||||
|
||||
// fixed header
|
||||
packet[0] = (MQTT_DISCONNECT << 4) | 0b0000;
|
||||
packet[1] = 0x00;
|
||||
|
||||
|
||||
// send MQTT packet
|
||||
int16_t state = _tl->send(packet, 2);
|
||||
if(state != ERR_NONE) {
|
||||
return(state);
|
||||
}
|
||||
|
||||
|
||||
// close tl connection
|
||||
return(_tl->closeTransportConnection());
|
||||
}
|
||||
|
@ -156,14 +172,18 @@ int16_t MQTTClient::publish(const char* topic, const char* message) {
|
|||
uint32_t remainingLength = (2 + topicLen) + messageLen;
|
||||
uint8_t encoded[] = {0, 0, 0, 0};
|
||||
size_t encodedBytes = encodeLength(remainingLength, encoded);
|
||||
|
||||
|
||||
// build the PUBLISH packet
|
||||
uint8_t* packet = new uint8_t[1 + encodedBytes + remainingLength];
|
||||
|
||||
#ifdef RADIOLIB_STATIC_ONLY
|
||||
uint8_t packet[RADIOLIB_STATIC_ARRAY_SIZE];
|
||||
#else
|
||||
uint8_t* packet = new uint8_t[1 + encodedBytes + remainingLength];
|
||||
#endif
|
||||
|
||||
// fixed header
|
||||
packet[0] = (MQTT_PUBLISH << 4) | 0b0000;
|
||||
memcpy(packet + 1, encoded, encodedBytes);
|
||||
|
||||
|
||||
// variable header
|
||||
// topic name
|
||||
size_t pos = encodedBytes + 1;
|
||||
|
@ -171,19 +191,21 @@ int16_t MQTTClient::publish(const char* topic, const char* message) {
|
|||
packet[pos++] = topicLen & 0x00FF;
|
||||
memcpy(packet + pos, topic, topicLen);
|
||||
pos += topicLen;
|
||||
|
||||
|
||||
// packet ID
|
||||
|
||||
|
||||
// payload
|
||||
// message
|
||||
memcpy(packet + pos, message, messageLen);
|
||||
pos += messageLen;
|
||||
|
||||
|
||||
// send MQTT packet
|
||||
int16_t state = _tl->send(packet, 1 + encodedBytes + remainingLength);
|
||||
delete[] packet;
|
||||
#ifndef RADIOLIB_STATIC_ONLY
|
||||
delete[] packet;
|
||||
#endif
|
||||
return(state);
|
||||
|
||||
|
||||
//TODO: implement QoS > 0 and PUBACK response checking
|
||||
}
|
||||
|
||||
|
@ -193,21 +215,25 @@ int16_t MQTTClient::subscribe(const char* topicFilter) {
|
|||
uint32_t remainingLength = 2 + (2 + topicFilterLen + 1);
|
||||
uint8_t encoded[] = {0, 0, 0, 0};
|
||||
size_t encodedBytes = encodeLength(remainingLength, encoded);
|
||||
|
||||
|
||||
// build the SUBSCRIBE packet
|
||||
uint8_t* packet = new uint8_t[1 + encodedBytes + remainingLength];
|
||||
|
||||
#ifdef RADIOLIB_STATIC_ONLY
|
||||
uint8_t packet[RADIOLIB_STATIC_ARRAY_SIZE];
|
||||
#else
|
||||
uint8_t* packet = new uint8_t[1 + encodedBytes + remainingLength];
|
||||
#endif
|
||||
|
||||
// fixed header
|
||||
packet[0] = (MQTT_SUBSCRIBE << 4) | 0b0010;
|
||||
memcpy(packet + 1, encoded, encodedBytes);
|
||||
|
||||
|
||||
// variable header
|
||||
// packet ID
|
||||
size_t pos = encodedBytes + 1;
|
||||
uint16_t packetId = _packetId++;
|
||||
packet[pos++] = (packetId & 0xFF00) >> 8;
|
||||
packet[pos++] = packetId & 0x00FF;
|
||||
|
||||
|
||||
// payload
|
||||
// topic filter
|
||||
packet[pos++] = (topicFilterLen & 0xFF00) >> 8;;
|
||||
|
@ -215,35 +241,45 @@ int16_t MQTTClient::subscribe(const char* topicFilter) {
|
|||
memcpy(packet + pos, topicFilter, topicFilterLen);
|
||||
pos += topicFilterLen;
|
||||
packet[pos++] = 0x00; // QoS 0
|
||||
|
||||
|
||||
// send MQTT packet
|
||||
int16_t state = _tl->send(packet, 1 + encodedBytes + remainingLength);
|
||||
delete[] packet;
|
||||
#ifndef RADIOLIB_STATIC_ONLY
|
||||
delete[] packet;
|
||||
#endif
|
||||
if(state != ERR_NONE) {
|
||||
return(state);
|
||||
}
|
||||
|
||||
|
||||
// get the response length (MQTT SUBACK response has to be 5 bytes long for single subscription)
|
||||
size_t numBytes = _tl->getNumBytes();
|
||||
if(numBytes != 5) {
|
||||
return(ERR_RESPONSE_MALFORMED_AT);
|
||||
}
|
||||
|
||||
|
||||
// read the response
|
||||
uint8_t* response = new uint8_t[numBytes];
|
||||
#ifdef RADIOLIB_STATIC_ONLY
|
||||
uint8_t response[RADIOLIB_STATIC_ARRAY_SIZE];
|
||||
#else
|
||||
uint8_t* response = new uint8_t[numBytes];
|
||||
#endif
|
||||
_tl->receive(response, numBytes);
|
||||
if((response[0] == MQTT_SUBACK << 4) && (response[1] == 3)) {
|
||||
// check packet ID
|
||||
uint16_t receivedId = response[3] | response[2] << 8;
|
||||
int16_t returnCode = response[4];
|
||||
delete[] response;
|
||||
#ifndef RADIOLIB_STATIC_ONLY
|
||||
delete[] response;
|
||||
#endif
|
||||
if(receivedId != packetId) {
|
||||
return(ERR_MQTT_UNEXPECTED_PACKET_ID);
|
||||
}
|
||||
return(returnCode);
|
||||
}
|
||||
|
||||
delete[] response;
|
||||
|
||||
#ifndef RADIOLIB_STATIC_ONLY
|
||||
delete[] response;
|
||||
#endif
|
||||
return(ERR_RESPONSE_MALFORMED);
|
||||
}
|
||||
|
||||
|
@ -253,87 +289,109 @@ int16_t MQTTClient::unsubscribe(const char* topicFilter) {
|
|||
uint32_t remainingLength = 2 + (2 + topicFilterLen);
|
||||
uint8_t encoded[] = {0, 0, 0, 0};
|
||||
size_t encodedBytes = encodeLength(remainingLength, encoded);
|
||||
|
||||
|
||||
// build the UNSUBSCRIBE packet
|
||||
uint8_t* packet = new uint8_t[1 + encodedBytes + remainingLength];
|
||||
|
||||
#ifdef RADIOLIB_STATIC_ONLY
|
||||
uint8_t packet[RADIOLIB_STATIC_ARRAY_SIZE];
|
||||
#else
|
||||
uint8_t* packet = new uint8_t[1 + encodedBytes + remainingLength];
|
||||
#endif
|
||||
|
||||
// fixed header
|
||||
packet[0] = (MQTT_UNSUBSCRIBE << 4) | 0b0010;
|
||||
memcpy(packet + 1, encoded, encodedBytes);
|
||||
|
||||
|
||||
// variable header
|
||||
// packet ID
|
||||
size_t pos = encodedBytes + 1;
|
||||
uint16_t packetId = _packetId++;
|
||||
packet[pos++] = (packetId & 0xFF00) >> 8;
|
||||
packet[pos++] = packetId & 0x00FF;
|
||||
|
||||
|
||||
// payload
|
||||
// topic filter
|
||||
packet[pos++] = (topicFilterLen & 0xFF00) >> 8;;
|
||||
packet[pos++] = topicFilterLen & 0x00FF;
|
||||
memcpy(packet + pos, topicFilter, topicFilterLen);
|
||||
pos += topicFilterLen;
|
||||
|
||||
|
||||
// send MQTT packet
|
||||
int16_t state = _tl->send(packet, 1 + encodedBytes + remainingLength);
|
||||
delete[] packet;
|
||||
#ifndef RADIOLIB_STATIC_ONLY
|
||||
delete[] packet;
|
||||
#endif
|
||||
if(state != ERR_NONE) {
|
||||
return(state);
|
||||
}
|
||||
|
||||
|
||||
// get the response length (MQTT UNSUBACK response has to be 4 bytes long)
|
||||
size_t numBytes = _tl->getNumBytes();
|
||||
if(numBytes != 4) {
|
||||
return(ERR_RESPONSE_MALFORMED_AT);
|
||||
}
|
||||
|
||||
|
||||
// read the response
|
||||
uint8_t* response = new uint8_t[numBytes];
|
||||
#ifdef RADIOLIB_STATIC_ONLY
|
||||
uint8_t response[RADIOLIB_STATIC_ARRAY_SIZE];
|
||||
#else
|
||||
uint8_t* response = new uint8_t[numBytes];
|
||||
#endif
|
||||
_tl->receive(response, numBytes);
|
||||
if((response[0] == MQTT_UNSUBACK << 4) && (response[1] == 2)) {
|
||||
// check packet ID
|
||||
uint16_t receivedId = response[3] | response[2] << 8;
|
||||
delete[] response;
|
||||
#ifndef RADIOLIB_STATIC_ONLY
|
||||
delete[] response;
|
||||
#endif
|
||||
if(receivedId != packetId) {
|
||||
return(ERR_MQTT_UNEXPECTED_PACKET_ID);
|
||||
}
|
||||
return(ERR_NONE);
|
||||
}
|
||||
|
||||
delete[] response;
|
||||
|
||||
#ifndef RADIOLIB_STATIC_ONLY
|
||||
delete[] response;
|
||||
#endif
|
||||
return(ERR_RESPONSE_MALFORMED);
|
||||
}
|
||||
|
||||
int16_t MQTTClient::ping() {
|
||||
// build the PINGREQ packet
|
||||
uint8_t packet[2];
|
||||
|
||||
|
||||
// fixed header
|
||||
packet[0] = (MQTT_PINGREQ << 4) | 0b0000;
|
||||
packet[1] = 0x00;
|
||||
|
||||
|
||||
// send MQTT packet
|
||||
int16_t state = _tl->send(packet, 2);
|
||||
if(state != ERR_NONE) {
|
||||
return(state);
|
||||
}
|
||||
|
||||
|
||||
// get the response length (MQTT PINGRESP response has to be 2 bytes long)
|
||||
size_t numBytes = _tl->getNumBytes();
|
||||
if(numBytes != 2) {
|
||||
return(ERR_RESPONSE_MALFORMED_AT);
|
||||
}
|
||||
|
||||
|
||||
// read the response
|
||||
uint8_t* response = new uint8_t[numBytes];
|
||||
#ifdef RADIOLIB_STATIC_ONLY
|
||||
uint8_t response[RADIOLIB_STATIC_ARRAY_SIZE];
|
||||
#else
|
||||
uint8_t* response = new uint8_t[numBytes];
|
||||
#endif
|
||||
_tl->receive(response, numBytes);
|
||||
if((response[0] == MQTT_PINGRESP << 4) && (response[1] == 0)) {
|
||||
delete[] response;
|
||||
#ifndef RADIOLIB_STATIC_ONLY
|
||||
delete[] response;
|
||||
#endif
|
||||
return(ERR_NONE);
|
||||
}
|
||||
|
||||
delete[] response;
|
||||
|
||||
#ifndef RADIOLIB_STATIC_ONLY
|
||||
delete[] response;
|
||||
#endif
|
||||
return(ERR_RESPONSE_MALFORMED);
|
||||
}
|
||||
|
||||
|
@ -343,42 +401,42 @@ int16_t MQTTClient::check(void (*func)(const char*, const char*)) {
|
|||
if(state != ERR_NONE) {
|
||||
return(state);
|
||||
}
|
||||
|
||||
|
||||
// check new data
|
||||
size_t numBytes = _tl->getNumBytes();
|
||||
if(numBytes == 0) {
|
||||
return(ERR_MQTT_NO_NEW_PACKET_AVAILABLE);
|
||||
}
|
||||
|
||||
|
||||
// read the PUBLISH packet from server
|
||||
uint8_t* dataIn = new uint8_t[numBytes];
|
||||
_tl->receive(dataIn, numBytes);
|
||||
if(dataIn[0] == MQTT_PUBLISH << 4) {
|
||||
// TODO: properly decode remaining length
|
||||
uint8_t remainingLength = dataIn[1];
|
||||
|
||||
|
||||
// get the topic
|
||||
size_t topicLength = dataIn[3] | dataIn[2] << 8;
|
||||
char* topic = new char[topicLength + 1];
|
||||
memcpy(topic, dataIn + 4, topicLength);
|
||||
topic[topicLength] = 0x00;
|
||||
|
||||
|
||||
// get the message
|
||||
size_t messageLength = remainingLength - topicLength - 2;
|
||||
char* message = new char[messageLength + 1];
|
||||
memcpy(message, dataIn + 4 + topicLength, messageLength);
|
||||
message[messageLength] = 0x00;
|
||||
|
||||
|
||||
// execute the callback function provided by user
|
||||
func(topic, message);
|
||||
|
||||
|
||||
delete[] topic;
|
||||
delete[] message;
|
||||
delete[] dataIn;
|
||||
return(ERR_NONE);
|
||||
}
|
||||
delete[] dataIn;
|
||||
|
||||
|
||||
return(ERR_MQTT_NO_NEW_PACKET_AVAILABLE);
|
||||
}
|
||||
|
|
@ -1,8 +1,8 @@
|
|||
#ifndef _RADIOLIB_MQTT_H
|
||||
#define _RADIOLIB_MQTT_H
|
||||
|
||||
#include "TypeDef.h"
|
||||
#include "TransportLayer.h"
|
||||
#include "../../TypeDef.h"
|
||||
#include "../TransportLayer/TransportLayer.h"
|
||||
|
||||
// MQTT packet types
|
||||
#define MQTT_CONNECT 0x01
|
||||
|
@ -127,7 +127,9 @@ class MQTTClient {
|
|||
*/
|
||||
int16_t check(void (*func)(const char*, const char*));
|
||||
|
||||
#ifndef RADIOLIB_GODMODE
|
||||
private:
|
||||
#endif
|
||||
TransportLayer* _tl;
|
||||
|
||||
uint16_t _port;
|
|
@ -119,9 +119,9 @@ size_t MorseClient::write(uint8_t b) {
|
|||
|
||||
// check if the requested code was found in the array
|
||||
if(found) {
|
||||
DEBUG_PRINT(mc.c);
|
||||
DEBUG_PRINT('\t');
|
||||
DEBUG_PRINTLN(mc.m);
|
||||
RADIOLIB_DEBUG_PRINT(mc.c);
|
||||
RADIOLIB_DEBUG_PRINT('\t');
|
||||
RADIOLIB_DEBUG_PRINTLN(mc.m);
|
||||
|
||||
// iterate over Morse code representation and output appropriate tones
|
||||
for(uint8_t i = 0; i < strlen(mc.m); i++) {
|
||||
|
@ -145,7 +145,7 @@ size_t MorseClient::write(uint8_t b) {
|
|||
}
|
||||
|
||||
// letter space
|
||||
DEBUG_PRINTLN();
|
||||
RADIOLIB_DEBUG_PRINTLN();
|
||||
delay(_dotLength * 3);
|
||||
|
||||
return(1);
|
|
@ -1,8 +1,8 @@
|
|||
#ifndef _RADIOLIB_MORSE_H
|
||||
#define _RADIOLIB_MORSE_H
|
||||
|
||||
#include "TypeDef.h"
|
||||
#include "PhysicalLayer.h"
|
||||
#include "../../TypeDef.h"
|
||||
#include "../PhysicalLayer/PhysicalLayer.h"
|
||||
|
||||
#define MORSE_LENGTH 52
|
||||
|
||||
|
@ -67,7 +67,9 @@ class MorseClient {
|
|||
size_t println(unsigned long, int = DEC);
|
||||
size_t println(double, int = 2);
|
||||
|
||||
#ifndef RADIOLIB_GODMODE
|
||||
private:
|
||||
#endif
|
||||
PhysicalLayer* _phy;
|
||||
uint32_t _base;
|
||||
uint16_t _dotLength;
|
|
@ -19,7 +19,11 @@ int16_t PhysicalLayer::transmit(__FlashStringHelper* fstr, uint8_t addr) {
|
|||
}
|
||||
|
||||
// dynamically allocate memory
|
||||
char* str = new char[len];
|
||||
#ifdef RADIOLIB_STATIC_ONLY
|
||||
char str[RADIOLIB_STATIC_ARRAY_SIZE];
|
||||
#else
|
||||
char* str = new char[len];
|
||||
#endif
|
||||
|
||||
// copy string from flash
|
||||
p = reinterpret_cast<PGM_P>(fstr);
|
||||
|
@ -29,7 +33,9 @@ int16_t PhysicalLayer::transmit(__FlashStringHelper* fstr, uint8_t addr) {
|
|||
|
||||
// transmit string
|
||||
int16_t state = transmit(str, addr);
|
||||
delete[] str;
|
||||
#ifndef RADIOLIB_STATIC_ONLY
|
||||
delete[] str;
|
||||
#endif
|
||||
return(state);
|
||||
}
|
||||
|
||||
|
@ -62,10 +68,14 @@ int16_t PhysicalLayer::readData(String& str, size_t len) {
|
|||
}
|
||||
|
||||
// build a temporary buffer
|
||||
uint8_t* data = new uint8_t[length + 1];
|
||||
if(!data) {
|
||||
return(ERR_MEMORY_ALLOCATION_FAILED);
|
||||
}
|
||||
#ifdef RADIOLIB_STATIC_ONLY
|
||||
uint8_t data[RADIOLIB_STATIC_ARRAY_SIZE + 1];
|
||||
#else
|
||||
uint8_t* data = new uint8_t[length + 1];
|
||||
if(!data) {
|
||||
return(ERR_MEMORY_ALLOCATION_FAILED);
|
||||
}
|
||||
#endif
|
||||
|
||||
// read the received data
|
||||
state = readData(data, length);
|
||||
|
@ -79,7 +89,9 @@ int16_t PhysicalLayer::readData(String& str, size_t len) {
|
|||
}
|
||||
|
||||
// deallocate temporary buffer
|
||||
delete[] data;
|
||||
#ifndef RADIOLIB_STATIC_ONLY
|
||||
delete[] data;
|
||||
#endif
|
||||
|
||||
return(state);
|
||||
}
|
||||
|
@ -96,10 +108,14 @@ int16_t PhysicalLayer::receive(String& str, size_t len) {
|
|||
}
|
||||
|
||||
// build a temporary buffer
|
||||
uint8_t* data = new uint8_t[length + 1];
|
||||
if(!data) {
|
||||
return(ERR_MEMORY_ALLOCATION_FAILED);
|
||||
}
|
||||
#ifdef RADIOLIB_STATIC_ONLY
|
||||
uint8_t data[RADIOLIB_STATIC_ARRAY_SIZE + 1];
|
||||
#else
|
||||
uint8_t* data = new uint8_t[length + 1];
|
||||
if(!data) {
|
||||
return(ERR_MEMORY_ALLOCATION_FAILED);
|
||||
}
|
||||
#endif
|
||||
|
||||
// attempt packet reception
|
||||
state = receive(data, length);
|
||||
|
@ -118,7 +134,9 @@ int16_t PhysicalLayer::receive(String& str, size_t len) {
|
|||
}
|
||||
|
||||
// deallocate temporary buffer
|
||||
delete[] data;
|
||||
#ifndef RADIOLIB_STATIC_ONLY
|
||||
delete[] data;
|
||||
#endif
|
||||
|
||||
return(state);
|
||||
}
|
|
@ -1,7 +1,7 @@
|
|||
#ifndef _RADIOLIB_PHYSICAL_LAYER_H
|
||||
#define _RADIOLIB_PHYSICAL_LAYER_H
|
||||
|
||||
#include "TypeDef.h"
|
||||
#include "../../TypeDef.h"
|
||||
|
||||
/*!
|
||||
\class PhysicalLayer
|
||||
|
@ -87,7 +87,7 @@ class PhysicalLayer {
|
|||
|
||||
/*!
|
||||
\brief Sets module to standby.
|
||||
|
||||
|
||||
\returns \ref status_codes
|
||||
*/
|
||||
virtual int16_t standby() = 0;
|
||||
|
@ -215,7 +215,9 @@ class PhysicalLayer {
|
|||
*/
|
||||
virtual size_t getPacketLength(bool update = true) = 0;
|
||||
|
||||
#ifndef RADIOLIB_GODMODE
|
||||
private:
|
||||
#endif
|
||||
float _crystalFreq;
|
||||
uint8_t _divExponent;
|
||||
size_t _maxPacketLength;
|
|
@ -2,20 +2,20 @@
|
|||
|
||||
ITA2String::ITA2String(char c) {
|
||||
_len = 1;
|
||||
_str = new char[1];
|
||||
_str[0] = c;
|
||||
_ita2Len = 0;
|
||||
}
|
||||
|
||||
ITA2String::ITA2String(const char* str) {
|
||||
_len = strlen(str);
|
||||
_str = new char[_len];
|
||||
strcpy(_str, str);
|
||||
_ita2Len = 0;
|
||||
}
|
||||
|
||||
ITA2String::~ITA2String() {
|
||||
delete[] _str;
|
||||
#ifndef RADIOLIB_STATIC_ONLY
|
||||
delete[] _str;
|
||||
#endif
|
||||
}
|
||||
|
||||
size_t ITA2String::length() {
|
||||
|
@ -32,7 +32,11 @@ size_t ITA2String::length() {
|
|||
|
||||
uint8_t* ITA2String::byteArr() {
|
||||
// create temporary array 2x the string length (figures may be 3 bytes)
|
||||
uint8_t* temp = new uint8_t[_len*2 + 1];
|
||||
#ifdef RADIOLIB_STATIC_ONLY
|
||||
uint8_t temp[RADIOLIB_STATIC_ARRAY_SIZE*2 + 1];
|
||||
#else
|
||||
uint8_t* temp = new uint8_t[_len*2 + 1];
|
||||
#endif
|
||||
|
||||
size_t arrayLen = 0;
|
||||
bool flagFigure = false;
|
||||
|
@ -75,7 +79,9 @@ uint8_t* ITA2String::byteArr() {
|
|||
|
||||
uint8_t* arr = new uint8_t[arrayLen];
|
||||
memcpy(arr, temp, arrayLen);
|
||||
delete[] temp;
|
||||
#ifndef RADIOLIB_STATIC_ONLY
|
||||
delete[] temp;
|
||||
#endif
|
||||
|
||||
return(arr);
|
||||
}
|
||||
|
@ -202,7 +208,11 @@ size_t RTTYClient::print(__FlashStringHelper* fstr) {
|
|||
}
|
||||
|
||||
// dynamically allocate memory
|
||||
char* str = new char[len];
|
||||
#ifdef RADIOLIB_STATIC_ONLY
|
||||
char str[RADIOLIB_STATIC_ARRAY_SIZE];
|
||||
#else
|
||||
char* str = new char[len];
|
||||
#endif
|
||||
|
||||
// copy string from flash
|
||||
p = reinterpret_cast<PGM_P>(fstr);
|
||||
|
@ -217,7 +227,9 @@ size_t RTTYClient::print(__FlashStringHelper* fstr) {
|
|||
} else if((_encoding == ASCII) || (_encoding == ASCII_EXTENDED)) {
|
||||
n = RTTYClient::write((uint8_t*)str, len);
|
||||
}
|
||||
delete[] str;
|
||||
#ifndef RADIOLIB_STATIC_ONLY
|
||||
delete[] str;
|
||||
#endif
|
||||
return(n);
|
||||
}
|
||||
|
|
@ -1,8 +1,8 @@
|
|||
#ifndef _RADIOLIB_RTTY_H
|
||||
#define _RADIOLIB_RTTY_H
|
||||
|
||||
#include "TypeDef.h"
|
||||
#include "PhysicalLayer.h"
|
||||
#include "../../TypeDef.h"
|
||||
#include "../PhysicalLayer/PhysicalLayer.h"
|
||||
|
||||
#define ITA2_FIGS 0x1B
|
||||
#define ITA2_LTRS 0x1F
|
||||
|
@ -57,8 +57,14 @@ class ITA2String {
|
|||
*/
|
||||
uint8_t* byteArr();
|
||||
|
||||
#ifndef RADIOLIB_GODMODE
|
||||
private:
|
||||
char* _str;
|
||||
#endif
|
||||
#ifdef RADIOLIB_STATIC_ONLY
|
||||
char _str[RADIOLIB_STATIC_ARRAY_SIZE];
|
||||
#else
|
||||
char* _str = new char[1];
|
||||
#endif
|
||||
size_t _len;
|
||||
size_t _ita2Len;
|
||||
|
||||
|
@ -137,13 +143,15 @@ class RTTYClient {
|
|||
size_t println(unsigned long, int = DEC);
|
||||
size_t println(double, int = 2);
|
||||
|
||||
#ifndef RADIOLIB_GODMODE
|
||||
private:
|
||||
#endif
|
||||
PhysicalLayer* _phy;
|
||||
|
||||
uint8_t _encoding;
|
||||
uint32_t _base;
|
||||
uint32_t _shift;
|
||||
uint16_t _bitDuration;
|
||||
uint32_t _bitDuration;
|
||||
uint8_t _dataBits;
|
||||
uint8_t _stopBits;
|
||||
|
|
@ -1,7 +1,7 @@
|
|||
#ifndef _RADIOLIB_TRANSPORT_LAYER_H
|
||||
#define _RADIOLIB_TRANSPORT_LAYER_H
|
||||
|
||||
#include "TypeDef.h"
|
||||
#include "../../TypeDef.h"
|
||||
|
||||
/*!
|
||||
\class TransportLayer
|
Loading…
Add table
Reference in a new issue