Merge branch 'master' into development

This commit is contained in:
jgromes 2019-11-22 14:48:29 +01:00
commit 43eefd4703
75 changed files with 2229 additions and 826 deletions

View file

@ -5,9 +5,10 @@ env:
# see https://github.com/arduino/Arduino/blob/master/build/shared/manpage.adoc#options # 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 # and https://github.com/arduino/Arduino/wiki/Arduino-IDE-1.5-3rd-party-Hardware-specification#boardstxt
- BOARD="esp32:esp32:esp32" - 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="esp8266:esp8266:generic:xtal=80,ResetMethod=ck,CrystalFreq=26,FlashFreq=40,FlashMode=qio,eesz=512K"
- BOARD="arduino:samd:arduino_zero_native" - BOARD="arduino:samd:arduino_zero_native"
- BOARD="arduino:sam:arduino_due_x"
- BOARD="arduino:avr:uno" - BOARD="arduino:avr:uno"
- BOARD="arduino:avr:leonardo" - BOARD="arduino:avr:leonardo"
- BOARD="arduino:avr:mega:cpu=atmega2560" - BOARD="arduino:avr:mega:cpu=atmega2560"
@ -28,7 +29,7 @@ before_install:
- sudo iptables -A INPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT - sudo iptables -A INPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT
# install 3rd party boards # 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 - if [[ "$BOARD" =~ "esp8266:esp8266:" ]]; then
arduino --install-boards esp8266:esp8266; arduino --install-boards esp8266:esp8266;
export SKIP_PAT='(HTTP|MQTT).*ino'; export SKIP_PAT='(HTTP|MQTT).*ino';
@ -38,6 +39,8 @@ before_install:
arduino --install-boards STM32:stm32; arduino --install-boards STM32:stm32;
elif [[ "$BOARD" =~ "arduino:samd:" ]]; then elif [[ "$BOARD" =~ "arduino:samd:" ]]; then
arduino --install-boards arduino:samd; arduino --install-boards arduino:samd;
elif [[ "$BOARD" =~ "arduino:sam:" ]]; then
arduino --install-boards arduino:sam;
fi fi
# create directory to save the library and create symbolic link # create directory to save the library and create symbolic link

View file

@ -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. 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.** 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. 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 ## 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** 1. **Bracket style**
This library uses the following style of bracket indentation (1TBS, or "javascript" style): This library uses the following style of bracket indentation (1TBS, or "javascript" style):
```c++ ```c++
if (foo) { if (foo) {
bar(); bar();
@ -35,6 +38,7 @@ Use 2 space characters for tabs.
3. **Single-line comments** 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. 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++ ```c++
// this function does something // this function does something
foo("bar"); foo("bar");
@ -45,6 +49,7 @@ foo(12345);
4. **Split code into blocks** 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! 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++ ```c++
// build a temporary buffer (first block) // build a temporary buffer (first block)
uint8_t* data = new uint8_t[len + 1]; 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. If you're adding a new method, make sure to add appropriate Doxygen comments, so that the documentation is always complete.
6. **Keywords** 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!**

View file

@ -32,8 +32,9 @@ RadioLib was originally created as a driver for [__RadioShield__](https://github
* __Arduino AVR boards__ - tested on Uno, Mega and Leonardo * __Arduino AVR boards__ - tested on Uno, Mega and Leonardo
* __ESP8266 boards__ - NodeMCU, Wemos D1, etc. * __ESP8266 boards__ - NodeMCU, Wemos D1, etc.
* __ESP32 boards__ - tested on ESP-WROOM-32 * __ESP32 boards__ - tested on ESP-WROOM-32
* __STM32 boards__ - tested on BluePill F103C6 * __STM32 boards__ - tested on Nucleo L452RE-P
* __SAMD boards__ - Arduino Zero * __SAMD boards__ - Arduino Zero
* __SAM boards__ - Arduino Due
### In development: ### In development:
* __SIM800C__ GSM module * __SIM800C__ GSM module

View file

@ -70,6 +70,7 @@ void setup() {
// cc.sleep() // cc.sleep()
// cc.transmit(); // cc.transmit();
// cc.receive(); // cc.receive();
// cc.readData();
} }
// flag to indicate that a packet was received // 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, // we're ready to receive more packets,
// enable interrupt service routine // enable interrupt service routine
enableInterrupt = true; enableInterrupt = true;

View file

@ -64,6 +64,7 @@ void setup() {
// rf.sleep() // rf.sleep()
// rf.transmit(); // rf.transmit();
// rf.receive(); // rf.receive();
// rf.readData();
} }
// flag to indicate that a packet was received // 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, // we're ready to receive more packets,
// enable interrupt service routine // enable interrupt service routine
enableInterrupt = true; enableInterrupt = true;

View file

@ -53,6 +53,28 @@ void setup() {
Serial.println(state); Serial.println(state);
while (true); 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() { void loop() {
@ -89,7 +111,7 @@ void loop() {
// of the last received packet // of the last received packet
Serial.print(F("[SX1262] SNR:\t\t")); Serial.print(F("[SX1262] SNR:\t\t"));
Serial.print(lora.getSNR()); Serial.print(lora.getSNR());
Serial.println(F(" dBm")); Serial.println(F(" dB"));
} else if (state == ERR_RX_TIMEOUT) { } else if (state == ERR_RX_TIMEOUT) {
// timeout occurred while waiting for a packet // timeout occurred while waiting for a packet

View file

@ -77,6 +77,7 @@ void setup() {
// lora.sleep() // lora.sleep()
// lora.transmit(); // lora.transmit();
// lora.receive(); // lora.receive();
// lora.readData();
// lora.scanChannel(); // lora.scanChannel();
} }
@ -136,7 +137,7 @@ void loop() {
// print SNR (Signal-to-Noise Ratio) // print SNR (Signal-to-Noise Ratio)
Serial.print(F("[SX1262] SNR:\t\t")); Serial.print(F("[SX1262] SNR:\t\t"));
Serial.print(lora.getSNR()); Serial.print(lora.getSNR());
Serial.println(F(" dBm")); Serial.println(F(" dB"));
} else if (state == ERR_CRC_MISMATCH) { } else if (state == ERR_CRC_MISMATCH) {
// packet was received, but is malformed // 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, // we're ready to receive more packets,
// enable interrupt service routine // enable interrupt service routine
enableInterrupt = true; enableInterrupt = true;

View file

@ -88,7 +88,7 @@ void loop() {
// of the last received packet // of the last received packet
Serial.print(F("[SX1278] SNR:\t\t\t")); Serial.print(F("[SX1278] SNR:\t\t\t"));
Serial.print(lora.getSNR()); Serial.print(lora.getSNR());
Serial.println(F(" dBm")); Serial.println(F(" dB"));
// print frequency error // print frequency error
// of the last received packet // of the last received packet

View file

@ -76,6 +76,7 @@ void setup() {
// lora.sleep() // lora.sleep()
// lora.transmit(); // lora.transmit();
// lora.receive(); // lora.receive();
// lora.readData();
// lora.scanChannel(); // lora.scanChannel();
} }
@ -135,7 +136,7 @@ void loop() {
// print SNR (Signal-to-Noise Ratio) // print SNR (Signal-to-Noise Ratio)
Serial.print(F("[SX1278] SNR:\t\t")); Serial.print(F("[SX1278] SNR:\t\t"));
Serial.print(lora.getSNR()); Serial.print(lora.getSNR());
Serial.println(F(" dBm")); Serial.println(F(" dB"));
// print frequency error // print frequency error
Serial.print(F("[SX1278] Frequency error:\t")); 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, // we're ready to receive more packets,
// enable interrupt service routine // enable interrupt service routine
enableInterrupt = true; enableInterrupt = true;

View file

@ -88,7 +88,9 @@ class <module_name> {
All implemented methods SHOULD return the status as int16_t type. All implemented methods SHOULD return the status as int16_t type.
*/ */
#ifndef RADIOLIB_GODMODE
private: private:
#endif
/* /*
The class MUST contain private member "Module* _mod" The class MUST contain private member "Module* _mod"
*/ */

View file

@ -88,6 +88,14 @@ setDataShaping KEYWORD2
setOOK KEYWORD2 setOOK KEYWORD2
setDataShapingOOK KEYWORD2 setDataShapingOOK KEYWORD2
setCRC KEYWORD2 setCRC KEYWORD2
variablePacketLengthMode KEYWORD2
fixedPacketLengthMode KEYWORD2
setCrcFiltering KEYWORD2
enableSyncWordFiltering KEYWORD2
disableSyncWordFiltering KEYWORD2
setPromiscuous KEYWORD2
setRSSIConfig KEYWORD2
setEncoding KEYWORD2
# RF69-specific # RF69-specific
setAESKey KEYWORD2 setAESKey KEYWORD2
@ -107,6 +115,7 @@ setTCXO KEYWORD2
setDio2AsRfSwitch KEYWORD2 setDio2AsRfSwitch KEYWORD2
getTimeOnAir KEYWORD2 getTimeOnAir KEYWORD2
setSyncBits KEYWORD2 setSyncBits KEYWORD2
setWhitening KEYWORD2
# ESP8266 # ESP8266
join KEYWORD2 join KEYWORD2
@ -182,6 +191,9 @@ ERR_INVALID_CURRENT_LIMIT LITERAL1
ERR_INVALID_PREAMBLE_LENGTH LITERAL1 ERR_INVALID_PREAMBLE_LENGTH LITERAL1
ERR_INVALID_GAIN LITERAL1 ERR_INVALID_GAIN LITERAL1
ERR_WRONG_MODEM 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_BIT_RATE LITERAL1
ERR_INVALID_FREQUENCY_DEVIATION LITERAL1 ERR_INVALID_FREQUENCY_DEVIATION LITERAL1

View file

@ -1,5 +1,5 @@
name=RadioLib name=RadioLib
version=1.6.1 version=1.8.0
author=Jan Gromes <gromes.jan@gmail.com> author=Jan Gromes <gromes.jan@gmail.com>
maintainer=Jan Gromes <gromes.jan@gmail.com> maintainer=Jan Gromes <gromes.jan@gmail.com>
sentence=Universal wireless communication library for Arduino sentence=Universal wireless communication library for Arduino

View file

@ -9,7 +9,7 @@ void ISerial::begin(long speed) {
} }
bool ISerial::listen() { bool ISerial::listen() {
#if defined ( ESP32 ) || defined (SAMD_SERIES) || defined (ARDUINO_ARCH_STM32) #ifdef RADIOLIB_SOFTWARE_SERIAL_UNSUPPORTED
return true; return true;
#else #else
return(_mod->ModuleSerial->listen()); return(_mod->ModuleSerial->listen());
@ -21,7 +21,7 @@ void ISerial::end() {
} }
bool ISerial::isListening() { bool ISerial::isListening() {
#if defined( ESP32 ) || defined ( SAMD_SERIES ) || defined (ARDUINO_ARCH_STM32) #ifdef RADIOLIB_SOFTWARE_SERIAL_UNSUPPORTED
return true; return true;
#else #else
return(_mod->ModuleSerial->isListening()); return(_mod->ModuleSerial->isListening());
@ -29,7 +29,7 @@ bool ISerial::isListening() {
} }
bool ISerial::stopListening() { bool ISerial::stopListening() {
#if defined( ESP32 ) || defined ( SAMD_SERIES ) || defined (ARDUINO_ARCH_STM32) #ifdef RADIOLIB_SOFTWARE_SERIAL_UNSUPPORTED
return true; return true;
#else #else
return(_mod->ModuleSerial->stopListening()); return(_mod->ModuleSerial->stopListening());
@ -37,7 +37,7 @@ bool ISerial::stopListening() {
} }
bool ISerial::overflow() { bool ISerial::overflow() {
#if defined( ESP32 ) || defined ( SAMD_SERIES ) || defined (ARDUINO_ARCH_STM32) #ifdef RADIOLIB_SOFTWARE_SERIAL_UNSUPPORTED
return false; return false;
#else #else
return(_mod->ModuleSerial->overflow()); return(_mod->ModuleSerial->overflow());

View file

@ -54,7 +54,9 @@ class ISerial {
size_t println(const Printable&); size_t println(const Printable&);
size_t println(void); size_t println(void);
#ifndef RADIOLIB_GODMODE
protected: protected:
#endif
Module* _mod; Module* _mod;
}; };

View file

@ -7,10 +7,11 @@ Module::Module(int rx, int tx, HardwareSerial* useSer) {
_int0 = -1; _int0 = -1;
_int1 = -1; _int1 = -1;
#if defined(ESP32) || defined(SAMD_SERIES) || defined (ARDUINO_ARCH_STM32) #ifdef RADIOLIB_SOFTWARE_SERIAL_UNSUPPORTED
ModuleSerial = useSer; ModuleSerial = useSer;
#else #else
ModuleSerial = new SoftwareSerial(_rx, _tx); ModuleSerial = new SoftwareSerial(_rx, _tx);
(void)useSer;
#endif #endif
} }
@ -33,10 +34,11 @@ Module::Module(int cs, int int0, int int1, int rx, int tx, SPIClass& spi, SPISet
_spi = &spi; _spi = &spi;
_spiSettings = spiSettings; _spiSettings = spiSettings;
#if defined(ESP32) || defined(SAMD_SERIES) || defined (ARDUINO_ARCH_STM32) #ifdef RADIOLIB_SOFTWARE_SERIAL_UNSUPPORTED
ModuleSerial = useSer; ModuleSerial = useSer;
#else #else
ModuleSerial = new SoftwareSerial(_rx, _tx); ModuleSerial = new SoftwareSerial(_rx, _tx);
(void)useSer;
#endif #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) { void Module::init(uint8_t interface, uint8_t gpio) {
// select interface // select interface
switch(interface) { switch(interface) {
case USE_SPI: case RADIOLIB_USE_SPI:
pinMode(_cs, OUTPUT); pinMode(_cs, OUTPUT);
digitalWrite(_cs, HIGH); digitalWrite(_cs, HIGH);
_spi->begin(); _spi->begin();
break; break;
case USE_UART: case RADIOLIB_USE_UART:
#if defined(ESP32) #if defined(ESP32)
ModuleSerial->begin(baudrate, SERIAL_8N1, _rx, _tx); ModuleSerial->begin(baudrate, SERIAL_8N1, _rx, _tx);
#else #else
ModuleSerial->begin(baudrate); ModuleSerial->begin(baudrate);
#endif #endif
break; break;
case USE_I2C: case RADIOLIB_USE_I2C:
break; break;
} }
// select GPIO // select GPIO
switch(gpio) { switch(gpio) {
case INT_NONE: case RADIOLIB_INT_NONE:
break; break;
case INT_0: case RADIOLIB_INT_0:
pinMode(_int0, INPUT); pinMode(_int0, INPUT);
break; break;
case INT_1: case RADIOLIB_INT_1:
pinMode(_int1, INPUT); pinMode(_int1, INPUT);
break; break;
case INT_BOTH: case RADIOLIB_INT_BOTH:
pinMode(_int0, INPUT); pinMode(_int0, INPUT);
pinMode(_int1, INPUT); pinMode(_int1, INPUT);
break; break;
@ -120,20 +122,20 @@ bool Module::ATgetResponse() {
while (millis() - start < _ATtimeout) { while (millis() - start < _ATtimeout) {
while(ModuleSerial->available() > 0) { while(ModuleSerial->available() > 0) {
char c = ModuleSerial->read(); char c = ModuleSerial->read();
DEBUG_PRINT(c); RADIOLIB_VERBOSE_PRINT(c);
data += c; data += c;
} }
if(data.indexOf("OK") != -1) { if(data.indexOf("OK") != -1) {
DEBUG_PRINTLN(); RADIOLIB_VERBOSE_PRINTLN();
return(true); return(true);
} else if (data.indexOf("ERROR") != -1) { } else if (data.indexOf("ERROR") != -1) {
DEBUG_PRINTLN(); RADIOLIB_VERBOSE_PRINTLN();
return(false); return(false);
} }
} }
DEBUG_PRINTLN(); RADIOLIB_VERBOSE_PRINTLN();
return(false); 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 // check failed, print debug info
DEBUG_PRINTLN(); RADIOLIB_DEBUG_PRINTLN();
DEBUG_PRINT(F("address:\t0x")); RADIOLIB_DEBUG_PRINT(F("address:\t0x"));
DEBUG_PRINTLN(reg, HEX); RADIOLIB_DEBUG_PRINTLN(reg, HEX);
DEBUG_PRINT(F("bits:\t\t")); RADIOLIB_DEBUG_PRINT(F("bits:\t\t"));
DEBUG_PRINT(msb); RADIOLIB_DEBUG_PRINT(msb);
DEBUG_PRINT(' '); RADIOLIB_DEBUG_PRINT(' ');
DEBUG_PRINTLN(lsb); RADIOLIB_DEBUG_PRINTLN(lsb);
DEBUG_PRINT(F("value:\t\t0b")); RADIOLIB_DEBUG_PRINT(F("value:\t\t0b"));
DEBUG_PRINTLN(value, BIN); RADIOLIB_DEBUG_PRINTLN(value, BIN);
DEBUG_PRINT(F("current:\t0b")); RADIOLIB_DEBUG_PRINT(F("current:\t0b"));
DEBUG_PRINTLN(currentValue, BIN); RADIOLIB_DEBUG_PRINTLN(currentValue, BIN);
DEBUG_PRINT(F("mask:\t\t0b")); RADIOLIB_DEBUG_PRINT(F("mask:\t\t0b"));
DEBUG_PRINTLN(mask, BIN); RADIOLIB_DEBUG_PRINTLN(mask, BIN);
DEBUG_PRINT(F("new:\t\t0b")); RADIOLIB_DEBUG_PRINT(F("new:\t\t0b"));
DEBUG_PRINTLN(newValue, BIN); RADIOLIB_DEBUG_PRINTLN(newValue, BIN);
DEBUG_PRINT(F("read:\t\t0b")); RADIOLIB_DEBUG_PRINT(F("read:\t\t0b"));
DEBUG_PRINTLN(readValue, BIN); RADIOLIB_DEBUG_PRINTLN(readValue, BIN);
DEBUG_PRINTLN(); RADIOLIB_DEBUG_PRINTLN();
return(ERR_SPI_WRITE_FAILED); 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 // send SPI register address with access command
_spi->transfer(reg | cmd); _spi->transfer(reg | cmd);
DEBUG_PRINT(reg | cmd, HEX); RADIOLIB_VERBOSE_PRINT(reg | cmd, HEX);
DEBUG_PRINT('\t'); RADIOLIB_VERBOSE_PRINT('\t');
DEBUG_PRINT(reg | cmd, BIN); RADIOLIB_VERBOSE_PRINT(reg | cmd, BIN);
DEBUG_PRINT('\t'); RADIOLIB_VERBOSE_PRINT('\t');
// send data or get response // send data or get response
if(cmd == SPIwriteCommand) { if(cmd == SPIwriteCommand) {
for(size_t n = 0; n < numBytes; n++) { for(size_t n = 0; n < numBytes; n++) {
_spi->transfer(dataOut[n]); _spi->transfer(dataOut[n]);
DEBUG_PRINT(dataOut[n], HEX); RADIOLIB_VERBOSE_PRINT(dataOut[n], HEX);
DEBUG_PRINT('\t'); RADIOLIB_VERBOSE_PRINT('\t');
DEBUG_PRINT(dataOut[n], BIN); RADIOLIB_VERBOSE_PRINT(dataOut[n], BIN);
DEBUG_PRINT('\t'); RADIOLIB_VERBOSE_PRINT('\t');
} }
} else if (cmd == SPIreadCommand) { } else if (cmd == SPIreadCommand) {
for(size_t n = 0; n < numBytes; n++) { for(size_t n = 0; n < numBytes; n++) {
dataIn[n] = _spi->transfer(0x00); dataIn[n] = _spi->transfer(0x00);
DEBUG_PRINT(dataIn[n], HEX); RADIOLIB_VERBOSE_PRINT(dataIn[n], HEX);
DEBUG_PRINT('\t'); RADIOLIB_VERBOSE_PRINT('\t');
DEBUG_PRINT(dataIn[n], BIN); RADIOLIB_VERBOSE_PRINT(dataIn[n], BIN);
DEBUG_PRINT('\t'); RADIOLIB_VERBOSE_PRINT('\t');
} }
} }
DEBUG_PRINTLN(); RADIOLIB_VERBOSE_PRINTLN();
// release CS // release CS
digitalWrite(_cs, HIGH); digitalWrite(_cs, HIGH);

View file

@ -1,15 +1,14 @@
#ifndef _RADIOLIB_MODULE_H #ifndef _RADIOLIB_MODULE_H
#define _RADIOLIB_MODULE_H #define _RADIOLIB_MODULE_H
#include "TypeDef.h"
#include <SPI.h> #include <SPI.h>
//#include <Wire.h> //#include <Wire.h>
#if defined(ESP32) || defined(SAMD_SERIES) || defined (ARDUINO_ARCH_STM32) #ifndef RADIOLIB_SOFTWARE_SERIAL_UNSUPPORTED
#else
#include <SoftwareSerial.h> #include <SoftwareSerial.h>
#endif #endif
#include "TypeDef.h"
/*! /*!
\class Module \class Module
@ -28,7 +27,7 @@ class Module {
\param serial HardwareSerial to be used on ESP32 and SAMD. Defaults to 1 \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); Module(int tx, int rx, HardwareSerial* useSer = &Serial1);
#else #else
Module(int tx, int rx, HardwareSerial* useSer = nullptr); 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 \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); 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 #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); 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. \brief Internal SoftwareSerial instance.
*/ */
#if defined(ESP32) || defined(SAMD_SERIES) || defined (ARDUINO_ARCH_STM32) #ifdef RADIOLIB_SOFTWARE_SERIAL_UNSUPPORTED
HardwareSerial* ModuleSerial; HardwareSerial* ModuleSerial;
#else #else
SoftwareSerial* ModuleSerial; SoftwareSerial* ModuleSerial;
@ -311,7 +310,9 @@ class Module {
*/ */
SPISettings getSpiSettings() const { return(_spiSettings); } SPISettings getSpiSettings() const { return(_spiSettings); }
#ifndef RADIOLIB_GODMODE
private: private:
#endif
int _cs; int _cs;
int _tx; int _tx;
int _rx; int _rx;

View file

@ -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;

View file

@ -38,42 +38,43 @@
#include "TypeDef.h" #include "TypeDef.h"
#include "Module.h" #include "Module.h"
#include "modules/CC1101.h" #ifdef RADIOLIB_GODMODE
#ifndef ESP8266 #warning "God mode active, I hope it was intentional. Buckle up, lads."
#include "modules/ESP8266.h"
#endif #endif
#include "modules/HC05.h"
#include "modules/JDY08.h" #include "modules/CC1101/CC1101.h"
#include "modules/nRF24.h" #ifndef ESP8266
#include "modules/RF69.h" #include "modules/ESP8266/ESP8266.h"
#include "modules/RFM95.h" #endif
#include "modules/RFM96.h" #include "modules/HC05/HC05.h"
#include "modules/RFM97.h" #include "modules/JDY08/JDY08.h"
#include "modules/SIM800.h" #include "modules/nRF24/nRF24.h"
#include "modules/SX1231.h" #include "modules/RF69/RF69.h"
#include "modules/SX1261.h" #include "modules/RFM9x/RFM95.h"
#include "modules/SX1262.h" #include "modules/RFM9x/RFM96.h"
#include "modules/SX1268.h" #include "modules/RFM9x/RFM97.h"
#include "modules/SX1272.h" #include "modules/SX1231/SX1231.h"
#include "modules/SX1273.h" #include "modules/SX126x/SX1261.h"
#include "modules/SX1276.h" #include "modules/SX126x/SX1262.h"
#include "modules/SX1277.h" #include "modules/SX126x/SX1268.h"
#include "modules/SX1278.h" #include "modules/SX127x/SX1272.h"
#include "modules/SX1279.h" #include "modules/SX127x/SX1273.h"
#include "modules/XBee.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 // physical layer protocols
#include "protocols/PhysicalLayer.h" #include "protocols/PhysicalLayer/PhysicalLayer.h"
#include "protocols/Morse.h" #include "protocols/Morse/Morse.h"
#include "protocols/RTTY.h" #include "protocols/RTTY/RTTY.h"
#include "protocols/Pager.h"
#include "protocols/PSK.h"
// transport layer protocols // transport layer protocols
#ifndef ESP8266 #ifndef ESP8266
#include "protocols/TransportLayer.h" #include "protocols/TransportLayer/TransportLayer.h"
#include "protocols/HTTP.h" #include "protocols/HTTP/HTTP.h"
#include "protocols/MQTT.h" #include "protocols/MQTT/MQTT.h"
#endif #endif
// RadioShield pin definitions // RadioShield pin definitions
@ -96,18 +97,23 @@
class Radio { class Radio {
public: public:
/*!
\brief Default constructor. Only used to set ModuleA and ModuleB configuration.
*/
Radio();
Module* ModuleA; Module* ModuleA;
Module* ModuleB; 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: private:
#endif
}; };
extern Radio RadioShield; Radio RadioShield;
#endif #endif

View file

@ -1,20 +1,63 @@
#ifndef _RADIOLIB_TYPES_H #ifndef _RADIOLIB_TYPES_H
#define _RADIOLIB_TYPES_H #define _RADIOLIB_TYPES_H
#if ARDUINO >= 100 #if ARDUINO >= 100
#include "Arduino.h" #include "Arduino.h"
#else #else
#error "Unsupported Arduino version (< 1.0.0)" #error "Unsupported Arduino version (< 1.0.0)"
#endif #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_DEBUG
//#define RADIOLIB_VERBOSE
// set which Serial port should be used for debug output
#define RADIOLIB_DEBUG_PORT Serial
#ifdef RADIOLIB_DEBUG #ifdef RADIOLIB_DEBUG
#define DEBUG_PRINT(...) { Serial.print(__VA_ARGS__); } #define RADIOLIB_DEBUG_PRINT(...) { RADIOLIB_DEBUG_PORT.print(__VA_ARGS__); }
#define DEBUG_PRINTLN(...) { Serial.println(__VA_ARGS__); } #define RADIOLIB_DEBUG_PRINTLN(...) { RADIOLIB_DEBUG_PORT.println(__VA_ARGS__); }
#else #else
#define DEBUG_PRINT(...) {} #define RADIOLIB_DEBUG_PRINT(...) {}
#define DEBUG_PRINTLN(...) {} #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 #endif
/*! /*!
@ -26,37 +69,37 @@
/*! /*!
\brief Use SPI interface. \brief Use SPI interface.
*/ */
#define USE_SPI 0x00 #define RADIOLIB_USE_SPI 0x00
/*! /*!
\brief Use UART interface. \brief Use UART interface.
*/ */
#define USE_UART 0x01 #define RADIOLIB_USE_UART 0x01
/*! /*!
\brief Use I2C interface. \brief Use I2C interface.
*/ */
#define USE_I2C 0x02 #define RADIOLIB_USE_I2C 0x02
/*! /*!
\brief Do not use any interrupts/GPIOs. \brief Do not use any interrupts/GPIOs.
*/ */
#define INT_NONE 0x00 #define RADIOLIB_INT_NONE 0x00
/*! /*!
\brief Use interrupt/GPIO 0. \brief Use interrupt/GPIO 0.
*/ */
#define INT_0 0x01 #define RADIOLIB_INT_0 0x01
/*! /*!
\brief Use interrupt/GPIO 1. \brief Use interrupt/GPIO 1.
*/ */
#define INT_1 0x02 #define RADIOLIB_INT_1 0x02
/*! /*!
\brief Use both interrupts/GPIOs. \brief Use both interrupts/GPIOs.
*/ */
#define INT_BOTH 0x03 #define RADIOLIB_INT_BOTH 0x03
/*! /*!
\} \}
@ -242,6 +285,21 @@
*/ */
#define ERR_WRONG_MODEM -20 #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 // RF69-specific status codes
/*! /*!

View file

@ -3,13 +3,16 @@
CC1101::CC1101(Module* module) : PhysicalLayer(CC1101_CRYSTAL_FREQ, CC1101_DIV_EXPONENT, CC1101_MAX_PACKET_LENGTH) { CC1101::CC1101(Module* module) : PhysicalLayer(CC1101_CRYSTAL_FREQ, CC1101_DIV_EXPONENT, CC1101_MAX_PACKET_LENGTH) {
_mod = module; _mod = module;
_packetLengthQueried = false; _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 // set module properties
_mod->SPIreadCommand = CC1101_CMD_READ; _mod->SPIreadCommand = CC1101_CMD_READ;
_mod->SPIwriteCommand = CC1101_CMD_WRITE; _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 // try to find the CC1101 chip
uint8_t i = 0; 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; flagFound = true;
} else { } else {
#ifdef RADIOLIB_DEBUG #ifdef RADIOLIB_DEBUG
Serial.print(F("CC1101 not found! (")); RADIOLIB_DEBUG_PRINT(F("CC1101 not found! ("));
Serial.print(i + 1); RADIOLIB_DEBUG_PRINT(i + 1);
Serial.print(F(" of 10 tries) CC1101_REG_VERSION == ")); RADIOLIB_DEBUG_PRINT(F(" of 10 tries) CC1101_REG_VERSION == "));
char buffHex[7]; char buffHex[7];
sprintf(buffHex, "0x%04X", version); sprintf(buffHex, "0x%04X", version);
Serial.print(buffHex); RADIOLIB_DEBUG_PRINT(buffHex);
Serial.print(F(", expected 0x0014")); RADIOLIB_DEBUG_PRINT(F(", expected 0x0014"));
Serial.println(); RADIOLIB_DEBUG_PRINTLN();
#endif #endif
delay(1000); delay(1000);
i++; i++;
@ -36,11 +39,11 @@ int16_t CC1101::begin(float freq, float br, float rxBw, float freqDev, int8_t po
} }
if(!flagFound) { if(!flagFound) {
DEBUG_PRINTLN(F("No CC1101 found!")); RADIOLIB_DEBUG_PRINTLN(F("No CC1101 found!"));
SPI.end(); SPI.end();
return(ERR_CHIP_NOT_FOUND); return(ERR_CHIP_NOT_FOUND);
} else { } 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 // 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); return(state);
} }
// configure bitrate
state = setBitRate(br); state = setBitRate(br);
if(state != ERR_NONE) { if(state != ERR_NONE) {
return(state); return(state);
} }
// configure default RX bandwidth
state = setRxBandwidth(rxBw); state = setRxBandwidth(rxBw);
if(state != ERR_NONE) { if(state != ERR_NONE) {
return(state); return(state);
} }
// configure default frequency deviation
state = setFrequencyDeviation(freqDev); state = setFrequencyDeviation(freqDev);
if(state != ERR_NONE) { if(state != ERR_NONE) {
return(state); return(state);
} }
// configure default TX output power
state = setOutputPower(power); state = setOutputPower(power);
if(state != ERR_NONE) { if(state != ERR_NONE) {
return(state); 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 // flush FIFOs
SPIsendCommand(CC1101_CMD_FLUSH_RX); SPIsendCommand(CC1101_CMD_FLUSH_RX);
SPIsendCommand(CC1101_CMD_FLUSH_TX); SPIsendCommand(CC1101_CMD_FLUSH_TX);
@ -162,7 +181,7 @@ int16_t CC1101::receiveDirect() {
int16_t CC1101::packetMode() { 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); 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_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); return(state);
} }
@ -192,8 +211,10 @@ int16_t CC1101::startTransmit(uint8_t* data, size_t len, uint8_t addr) {
return(state); return(state);
} }
// write packet length // optionally write packet length
if (_packetLengthConfig == CC1101_LENGTH_CONFIG_VARIABLE) {
SPIwriteRegister(CC1101_REG_FIFO, len); SPIwriteRegister(CC1101_REG_FIFO, len);
}
// check address filtering // check address filtering
uint8_t filter = SPIgetRegValue(CC1101_REG_PKTCTRL1, 1, 0); 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)); return(SPIsetRegValue(CC1101_REG_PATABLE, powerRaw));
} }
int16_t CC1101::setSyncWord(uint8_t syncH, uint8_t syncL) { int16_t CC1101::setSyncWord(uint8_t* syncWord, uint8_t len, uint8_t maxErrBits) {
// set sync word if((maxErrBits > 1) || (len > 2)) {
int16_t state = SPIsetRegValue(CC1101_REG_SYNC1, syncH); return(ERR_INVALID_SYNC_WORD);
state |= SPIsetRegValue(CC1101_REG_SYNC0, syncL); }
// 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); 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) { int16_t CC1101::setNodeAddress(uint8_t nodeAddr, uint8_t numBroadcastAddrs) {
if(!(numBroadcastAddrs > 0) && (numBroadcastAddrs <= 2)) { if(!(numBroadcastAddrs > 0) && (numBroadcastAddrs <= 2)) {
return(ERR_INVALID_NUM_BROAD_ADDRS); return(ERR_INVALID_NUM_BROAD_ADDRS);
@ -477,13 +559,96 @@ uint8_t CC1101::getLQI() {
size_t CC1101::getPacketLength(bool update) { size_t CC1101::getPacketLength(bool update) {
if(!_packetLengthQueried && update) { if(!_packetLengthQueried && update) {
if (_packetLengthConfig == CC1101_LENGTH_CONFIG_VARIABLE) {
_packetLength = _mod->SPIreadRegister(CC1101_REG_FIFO); _packetLength = _mod->SPIreadRegister(CC1101_REG_FIFO);
} else {
_packetLength = _mod->SPIreadRegister(CC1101_REG_PKTLEN);
}
_packetLengthQueried = true; _packetLengthQueried = true;
} }
return(_packetLength); 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() { int16_t CC1101::config() {
// enable automatic frequency synthesizer calibration // enable automatic frequency synthesizer calibration
int16_t state = SPIsetRegValue(CC1101_REG_MCSM0, CC1101_FS_AUTOCAL_IDLE_TO_RXTX, 5, 4); 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) { int16_t CC1101::SPIgetRegValue(uint8_t reg, uint8_t msb, uint8_t lsb) {
// status registers require special command // status registers require special command
if(reg > CC1101_REG_TEST0) { if(reg > CC1101_REG_TEST0) {

View file

@ -1,10 +1,10 @@
#ifndef _RADIOLIB_CC1101_H #ifndef _RADIOLIB_CC1101_H
#define _RADIOLIB_CC1101_H #define _RADIOLIB_CC1101_H
#include "TypeDef.h" #include "../../TypeDef.h"
#include "Module.h" #include "../../Module.h"
#include "../protocols/PhysicalLayer.h" #include "../../protocols/PhysicalLayer/PhysicalLayer.h"
// CC1101 physical layer properties // CC1101 physical layer properties
#define CC1101_CRYSTAL_FREQ 26.0 #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_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_OFF 0b00000000 // 3 3 Manchester encoding: disabled (default)
#define CC1101_MANCHESTER_EN_ON 0b00001000 // 3 3 enabled #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_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_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 #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 power Output power in dBm. Defaults to 0 dBm.
\param preambleLength Preamble Length in bytes. Defaults to 4 bytes.
\returns \ref status_codes \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. \brief Blocking binary transmit method.
@ -694,9 +696,33 @@ class CC1101: public PhysicalLayer {
\param syncL LSB of the sync word. \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 \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. \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); 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: private:
#endif
Module* _mod; Module* _mod;
float _freq; float _freq;
@ -748,10 +828,16 @@ class CC1101: public PhysicalLayer {
size_t _packetLength; size_t _packetLength;
bool _packetLengthQueried; bool _packetLengthQueried;
uint8_t _packetLengthConfig;
bool _promiscuous;
uint8_t _syncWordLength;
int16_t config(); int16_t config();
int16_t directMode(); int16_t directMode();
void getExpMant(float target, uint16_t mantOffset, uint8_t divExp, uint8_t expMax, uint8_t& exp, uint8_t& mant); 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 // 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); int16_t SPIgetRegValue(uint8_t reg, uint8_t msb = 7, uint8_t lsb = 0);

View file

@ -9,7 +9,7 @@ int16_t ESP8266::begin(long speed) {
// set module properties // set module properties
_mod->AtLineFeed = "\r\n"; _mod->AtLineFeed = "\r\n";
_mod->baudrate = speed; _mod->baudrate = speed;
_mod->init(USE_UART, INT_NONE); _mod->init(RADIOLIB_USE_UART, RADIOLIB_INT_NONE);
// empty UART buffer (garbage data) // empty UART buffer (garbage data)
_mod->ATemptyBuffer(); _mod->ATemptyBuffer();
@ -52,8 +52,12 @@ int16_t ESP8266::join(const char* ssid, const char* password) {
// build AT command // build AT command
const char* atStr = "AT+CWJAP_CUR=\""; const char* atStr = "AT+CWJAP_CUR=\"";
#ifdef RADIOLIB_STATIC_ONLY
char cmd[RADIOLIB_STATIC_ARRAY_SIZE];
#else
uint8_t cmdLen = strlen(atStr) + strlen(ssid) + strlen(password) + 4; uint8_t cmdLen = strlen(atStr) + strlen(ssid) + strlen(password) + 4;
char* cmd = new char[cmdLen + 1]; char* cmd = new char[cmdLen + 1];
#endif
strcpy(cmd, atStr); strcpy(cmd, atStr);
strcat(cmd, ssid); strcat(cmd, ssid);
strcat(cmd, "\",\""); strcat(cmd, "\",\"");
@ -62,7 +66,9 @@ int16_t ESP8266::join(const char* ssid, const char* password) {
// send command // send command
bool res = _mod->ATsendCommand(cmd); bool res = _mod->ATsendCommand(cmd);
#ifndef RADIOLIB_STATIC_ONLY
delete[] cmd; delete[] cmd;
#endif
if(!res) { if(!res) {
return(ERR_AT_FAILED); 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)) { if((strcmp(protocol, "TCP") == 0) && (tcpKeepAlive > 0)) {
cmdLen += strlen(tcpKeepAliveStr) + 1; cmdLen += strlen(tcpKeepAliveStr) + 1;
} }
#ifdef RADIOLIB_STATIC_ONLY
char cmd[RADIOLIB_STATIC_ARRAY_SIZE];
#else
char* cmd = new char[cmdLen + 1]; char* cmd = new char[cmdLen + 1];
#endif
strcpy(cmd, atStr); strcpy(cmd, atStr);
strcat(cmd, protocol); strcat(cmd, protocol);
strcat(cmd, "\",\""); strcat(cmd, "\",\"");
@ -101,7 +111,9 @@ int16_t ESP8266::openTransportConnection(const char* host, const char* protocol,
// send command // send command
bool res = _mod->ATsendCommand(cmd); bool res = _mod->ATsendCommand(cmd);
#ifndef RADIOLIB_STATIC_ONLY
delete[] cmd; delete[] cmd;
#endif
if(!res) { if(!res) {
return(ERR_AT_FAILED); return(ERR_AT_FAILED);
} }
@ -122,13 +134,19 @@ int16_t ESP8266::send(const char* data) {
char lenStr[8]; char lenStr[8];
itoa(strlen(data), lenStr, 10); itoa(strlen(data), lenStr, 10);
const char* atStr = "AT+CIPSEND="; const char* atStr = "AT+CIPSEND=";
#ifdef RADIOLIB_STATIC_ONLY
char cmd[RADIOLIB_STATIC_ARRAY_SIZE];
#else
char* cmd = new char[strlen(atStr) + strlen(lenStr) + 1]; char* cmd = new char[strlen(atStr) + strlen(lenStr) + 1];
#endif
strcpy(cmd, atStr); strcpy(cmd, atStr);
strcat(cmd, lenStr); strcat(cmd, lenStr);
// send command // send command
bool res = _mod->ATsendCommand(cmd); bool res = _mod->ATsendCommand(cmd);
#ifndef RADIOLIB_STATIC_ONLY
delete[] cmd; delete[] cmd;
#endif
if(!res) { if(!res) {
return(ERR_AT_FAILED); return(ERR_AT_FAILED);
} }
@ -146,13 +164,19 @@ int16_t ESP8266::send(uint8_t* data, uint32_t len) {
char lenStr[8]; char lenStr[8];
itoa(len, lenStr, 10); itoa(len, lenStr, 10);
const char atStr[] = "AT+CIPSEND="; const char atStr[] = "AT+CIPSEND=";
#ifdef RADIOLIB_STATIC_ONLY
char cmd[RADIOLIB_STATIC_ARRAY_SIZE];
#else
char* cmd = new char[strlen(atStr) + strlen(lenStr) + 1]; char* cmd = new char[strlen(atStr) + strlen(lenStr) + 1];
#endif
strcpy(cmd, atStr); strcpy(cmd, atStr);
strcat(cmd, lenStr); strcat(cmd, lenStr);
// send command // send command
bool res = _mod->ATsendCommand(cmd); bool res = _mod->ATsendCommand(cmd);
#ifndef RADIOLIB_STATIC_ONLY
delete[] cmd; delete[] cmd;
#endif
if(!res) { if(!res) {
return(ERR_AT_FAILED); 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((millis() - start < timeout) && (i < len)) {
while(_mod->ModuleSerial->available() > 0) { while(_mod->ModuleSerial->available() > 0) {
uint8_t b = _mod->ModuleSerial->read(); uint8_t b = _mod->ModuleSerial->read();
DEBUG_PRINT(b); RADIOLIB_DEBUG_PRINT(b);
data[i] = b; data[i] = b;
i++; i++;
} }

View file

@ -1,9 +1,9 @@
#if !defined(_RADIOLIB_ESP8266_H) && !defined(ESP8266) #if !defined(_RADIOLIB_ESP8266_H) && !defined(ESP8266)
#define _RADIOLIB_ESP8266_H #define _RADIOLIB_ESP8266_H
#include "Module.h" #include "../../Module.h"
#include "../protocols/TransportLayer.h" #include "../../protocols/TransportLayer/TransportLayer.h"
/*! /*!
\class ESP8266 \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 receive(uint8_t* data, size_t len, uint32_t timeout = 10000);
size_t getNumBytes(uint32_t timeout = 10000, size_t minBytes = 10); size_t getNumBytes(uint32_t timeout = 10000, size_t minBytes = 10);
#ifndef RADIOLIB_GODMODE
private: private:
#endif
Module* _mod; Module* _mod;
}; };

View file

@ -7,5 +7,5 @@ HC05::HC05(Module* mod) : ISerial(mod) {
void HC05::begin(long speed) { void HC05::begin(long speed) {
// set module properties // set module properties
_mod->baudrate = speed; _mod->baudrate = speed;
_mod->init(USE_UART, INT_NONE); _mod->init(RADIOLIB_USE_UART, RADIOLIB_INT_NONE);
} }

View file

@ -1,7 +1,7 @@
#ifndef _RADIOLIB_HC05_H #ifndef _RADIOLIB_HC05_H
#define _RADIOLIB_HC05_H #define _RADIOLIB_HC05_H
#include "ISerial.h" #include "../../ISerial.h"
/*! /*!
\class HC05 \class HC05

View file

@ -8,5 +8,5 @@ void JDY08::begin(long speed) {
// set module properties // set module properties
_mod->AtLineFeed = ""; _mod->AtLineFeed = "";
_mod->baudrate = speed; _mod->baudrate = speed;
_mod->init(USE_UART, INT_NONE); _mod->init(RADIOLIB_USE_UART, RADIOLIB_INT_NONE);
} }

View file

@ -1,7 +1,7 @@
#ifndef _RADIOLIB_JDY08_H #ifndef _RADIOLIB_JDY08_H
#define _RADIOLIB_JDY08_H #define _RADIOLIB_JDY08_H
#include "ISerial.h" #include "../../ISerial.h"
/*! /*!
\class JDY08 \class JDY08

View file

@ -3,12 +3,18 @@
RF69::RF69(Module* module) : PhysicalLayer(RF69_CRYSTAL_FREQ, RF69_DIV_EXPONENT, RF69_MAX_PACKET_LENGTH) { RF69::RF69(Module* module) : PhysicalLayer(RF69_CRYSTAL_FREQ, RF69_DIV_EXPONENT, RF69_MAX_PACKET_LENGTH) {
_mod = module; _mod = module;
_tempOffset = 0; _tempOffset = 0;
_packetLengthQueried = false; _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) { int16_t RF69::begin(float freq, float br, float rxBw, float freqDev, int8_t power) {
// set module properties // set module properties
_mod->init(USE_SPI, INT_0); _mod->init(RADIOLIB_USE_SPI, RADIOLIB_INT_0);
// try to find the RF69 chip // try to find the RF69 chip
uint8_t i = 0; 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; flagFound = true;
} else { } else {
#ifdef RADIOLIB_DEBUG #ifdef RADIOLIB_DEBUG
Serial.print(F("RF69 not found! (")); RADIOLIB_DEBUG_PRINT(F("RF69 not found! ("));
Serial.print(i + 1); RADIOLIB_DEBUG_PRINT(i + 1);
Serial.print(F(" of 10 tries) RF69_REG_VERSION == ")); RADIOLIB_DEBUG_PRINT(F(" of 10 tries) RF69_REG_VERSION == "));
char buffHex[7]; char buffHex[7];
sprintf(buffHex, "0x%04X", version); sprintf(buffHex, "0x%04X", version);
Serial.print(buffHex); RADIOLIB_DEBUG_PRINT(buffHex);
Serial.print(F(", expected 0x0024")); RADIOLIB_DEBUG_PRINT(F(", expected 0x0024"));
Serial.println(); RADIOLIB_DEBUG_PRINTLN();
#endif #endif
delay(1000); delay(1000);
i++; i++;
@ -35,11 +41,11 @@ int16_t RF69::begin(float freq, float br, float rxBw, float freqDev, int8_t powe
} }
if(!flagFound) { if(!flagFound) {
DEBUG_PRINTLN(F("No RF69 found!")); RADIOLIB_DEBUG_PRINTLN(F("No RF69 found!"));
SPI.end(); SPI.end();
return(ERR_CHIP_NOT_FOUND); return(ERR_CHIP_NOT_FOUND);
} else { } 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 // 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); return(state);
} }
// configure bitrate
_rxBw = 125.0; _rxBw = 125.0;
state = setBitRate(br); state = setBitRate(br);
if(state != ERR_NONE) { if(state != ERR_NONE) {
return(state); return(state);
} }
// configure default RX bandwidth
state = setRxBandwidth(rxBw); state = setRxBandwidth(rxBw);
if(state != ERR_NONE) { if(state != ERR_NONE) {
return(state); return(state);
} }
// configure default frequency deviation
state = setFrequencyDeviation(freqDev); state = setFrequencyDeviation(freqDev);
if(state != ERR_NONE) { if(state != ERR_NONE) {
return(state); return(state);
} }
// configure default TX output power
state = setOutputPower(power); state = setOutputPower(power);
if(state != ERR_NONE) { if(state != ERR_NONE) {
return(state); 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 // default sync word values 0x2D01 is the same as the default in LowPowerLab RFM69 library
uint8_t syncWord[] = {0x2D, 0x01}; uint8_t syncWord[] = {0x2D, 0x01};
state = setSyncWord(syncWord, 2); state = setSyncWord(syncWord, sizeof(syncWord));
if(state != ERR_NONE) { if(state != ERR_NONE) {
return(state); return(state);
} }
@ -250,6 +266,11 @@ int16_t RF69::startTransmit(uint8_t* data, size_t len, uint8_t addr) {
// set packet length // set packet length
_mod->SPIwriteRegister(RF69_REG_FIFO, len); _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 // check address filtering
uint8_t filter = _mod->SPIgetRegValue(RF69_REG_PACKET_CONFIG_1, 2, 1); uint8_t filter = _mod->SPIgetRegValue(RF69_REG_PACKET_CONFIG_1, 2, 1);
if((filter == RF69_ADDRESS_FILTERING_NODE) || (filter == RF69_ADDRESS_FILTERING_NODE_BROADCAST)) { 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) { 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 // get packet length
size_t length = len; size_t length = len;
if(len == RF69_MAX_PACKET_LENGTH) { 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 _syncWordLength = len;
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) { int16_t state = enableSyncWordFiltering(maxErrBits);
if (state != ERR_NONE) {
return(state); return(state);
} }
// set sync word // set sync word register
_mod->SPIwriteRegisterBurst(RF69_REG_SYNC_VALUE_1, syncWord, len); _mod->SPIwriteRegisterBurst(RF69_REG_SYNC_VALUE_1, syncWord, len);
return(ERR_NONE); return(ERR_NONE);
} }
@ -563,13 +591,90 @@ int16_t RF69::getTemperature() {
size_t RF69::getPacketLength(bool update) { size_t RF69::getPacketLength(bool update) {
if(!_packetLengthQueried && update) { if(!_packetLengthQueried && update) {
if (_packetLengthConfig == RF69_PACKET_FORMAT_VARIABLE) {
_packetLength = _mod->SPIreadRegister(RF69_REG_FIFO); _packetLength = _mod->SPIreadRegister(RF69_REG_FIFO);
} else {
_packetLength = _mod->SPIreadRegister(RF69_REG_PAYLOAD_LENGTH);
}
_packetLengthQueried = true; _packetLengthQueried = true;
} }
return(_packetLength); 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 RF69::config() {
int16_t state = ERR_NONE; int16_t state = ERR_NONE;
@ -649,6 +754,29 @@ int16_t RF69::config() {
return(ERR_NONE); 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) { int16_t RF69::setMode(uint8_t mode) {
return(_mod->SPIsetRegValue(RF69_REG_OP_MODE, mode, 4, 2)); return(_mod->SPIsetRegValue(RF69_REG_OP_MODE, mode, 4, 2));
} }

View file

@ -1,10 +1,10 @@
#ifndef _RADIOLIB_RF69_H #ifndef _RADIOLIB_RF69_H
#define _RADIOLIB_RF69_H #define _RADIOLIB_RF69_H
#include "TypeDef.h" #include "../../TypeDef.h"
#include "Module.h" #include "../../Module.h"
#include "../protocols/PhysicalLayer.h" #include "../../protocols/PhysicalLayer/PhysicalLayer.h"
// RF69 physical layer properties // RF69 physical layer properties
#define RF69_CRYSTAL_FREQ 32.0 #define RF69_CRYSTAL_FREQ 32.0
@ -646,7 +646,7 @@ class RF69: public PhysicalLayer {
int16_t setOutputPower(int8_t power); 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. \param syncWord Pointer to the array of sync word bytes.
@ -706,7 +706,61 @@ class RF69: public PhysicalLayer {
*/ */
size_t getPacketLength(bool update = true); 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: protected:
#endif
Module* _mod; Module* _mod;
float _br; float _br;
@ -715,11 +769,19 @@ class RF69: public PhysicalLayer {
size_t _packetLength; size_t _packetLength;
bool _packetLengthQueried; bool _packetLengthQueried;
uint8_t _packetLengthConfig;
bool _promiscuous;
uint8_t _syncWordLength;
int16_t config(); int16_t config();
int16_t directMode(); int16_t directMode();
int16_t setPacketMode(uint8_t mode, uint8_t len);
#ifndef RADIOLIB_GODMODE
private: private:
#endif
int16_t setMode(uint8_t mode); int16_t setMode(uint8_t mode);
void clearIRQFlags(); void clearIRQFlags();
}; };

View file

@ -1,10 +1,10 @@
#ifndef _RADIOLIB_RFM95_H #ifndef _RADIOLIB_RFM95_H
#define _RADIOLIB_RFM95_H #define _RADIOLIB_RFM95_H
#include "TypeDef.h" #include "../../TypeDef.h"
#include "Module.h" #include "../../Module.h"
#include "SX127x.h" #include "../SX127x/SX127x.h"
#include "SX1278.h" #include "../SX127x/SX1278.h"
// SX127X_REG_VERSION // SX127X_REG_VERSION
#define RFM95_CHIP_VERSION 0x11 #define RFM95_CHIP_VERSION 0x11
@ -67,7 +67,9 @@ class RFM95: public SX1278 {
*/ */
int16_t setFrequency(float freq); int16_t setFrequency(float freq);
#ifndef RADIOLIB_GODMODE
private: private:
#endif
}; };

View file

@ -1,10 +1,10 @@
#ifndef _RADIOLIB_RFM96_H #ifndef _RADIOLIB_RFM96_H
#define _RADIOLIB_RFM96_H #define _RADIOLIB_RFM96_H
#include "TypeDef.h" #include "../../TypeDef.h"
#include "Module.h" #include "../../Module.h"
#include "SX127x.h" #include "../SX127x/SX127x.h"
#include "SX1278.h" #include "../SX127x/SX1278.h"
// SX127X_REG_VERSION // SX127X_REG_VERSION
#define RFM9X_CHIP_VERSION 0x12 // according to datasheet, this should be 0x11, but all modules seem to have 0x12 #define RFM9X_CHIP_VERSION 0x12 // according to datasheet, this should be 0x11, but all modules seem to have 0x12
@ -67,7 +67,9 @@ class RFM96: public SX1278 {
*/ */
int16_t setFrequency(float freq); int16_t setFrequency(float freq);
#ifndef RADIOLIB_GODMODE
private: private:
#endif
}; };

View file

@ -1,10 +1,10 @@
#ifndef _RADIOLIB_RFM97_H #ifndef _RADIOLIB_RFM97_H
#define _RADIOLIB_RFM97_H #define _RADIOLIB_RFM97_H
#include "TypeDef.h" #include "../../TypeDef.h"
#include "Module.h" #include "../../Module.h"
#include "SX127x.h" #include "../SX127x/SX127x.h"
#include "SX1278.h" #include "../SX127x/SX1278.h"
#include "RFM95.h" #include "RFM95.h"
/*! /*!
@ -35,7 +35,10 @@ class RFM97: public RFM95 {
*/ */
int16_t setSpreadingFactor(uint8_t sf); int16_t setSpreadingFactor(uint8_t sf);
#ifndef RADIOLIB_GODMODE
private: private:
#endif
}; };
#endif #endif

View file

@ -6,7 +6,7 @@ SX1231::SX1231(Module* mod) : RF69(mod) {
int16_t SX1231::begin(float freq, float br, float rxBw, float freqDev, int8_t power) { int16_t SX1231::begin(float freq, float br, float rxBw, float freqDev, int8_t power) {
// set module properties // set module properties
_mod->init(USE_SPI, INT_BOTH); _mod->init(RADIOLIB_USE_SPI, RADIOLIB_INT_BOTH);
// try to find the SX1231 chip // try to find the SX1231 chip
uint8_t i = 0; uint8_t i = 0;
@ -18,15 +18,15 @@ int16_t SX1231::begin(float freq, float br, float rxBw, float freqDev, int8_t po
_chipRevision = version; _chipRevision = version;
} else { } else {
#ifdef RADIOLIB_DEBUG #ifdef RADIOLIB_DEBUG
Serial.print(F("SX127x not found! (")); RADIOLIB_DEBUG_PRINT(F("SX127x not found! ("));
Serial.print(i + 1); RADIOLIB_DEBUG_PRINT(i + 1);
Serial.print(F(" of 10 tries) SX127X_REG_VERSION == ")); RADIOLIB_DEBUG_PRINT(F(" of 10 tries) SX127X_REG_VERSION == "));
char buffHex[7]; char buffHex[7];
sprintf(buffHex, "0x%04X", version); sprintf(buffHex, "0x%04X", version);
Serial.print(buffHex); RADIOLIB_DEBUG_PRINT(buffHex);
Serial.print(F(", expected 0x0021 / 0x0022 / 0x0023")); RADIOLIB_DEBUG_PRINT(F(", expected 0x0021 / 0x0022 / 0x0023"));
Serial.println(); RADIOLIB_DEBUG_PRINTLN();
#endif #endif
delay(1000); delay(1000);
i++; i++;
@ -34,11 +34,11 @@ int16_t SX1231::begin(float freq, float br, float rxBw, float freqDev, int8_t po
} }
if(!flagFound) { if(!flagFound) {
DEBUG_PRINTLN(F("No SX1231 found!")); RADIOLIB_DEBUG_PRINTLN(F("No SX1231 found!"));
SPI.end(); SPI.end();
return(ERR_CHIP_NOT_FOUND); return(ERR_CHIP_NOT_FOUND);
} else { } else {
DEBUG_PRINTLN(F("Found SX1231!")); RADIOLIB_DEBUG_PRINTLN(F("Found SX1231!"));
} }
// configure settings not accessible by API // configure settings not accessible by API
@ -53,22 +53,26 @@ int16_t SX1231::begin(float freq, float br, float rxBw, float freqDev, int8_t po
return(state); return(state);
} }
// configure bitrate
_rxBw = 125.0; _rxBw = 125.0;
state = setBitRate(br); state = setBitRate(br);
if(state != ERR_NONE) { if(state != ERR_NONE) {
return(state); return(state);
} }
// configure default RX bandwidth
state = setRxBandwidth(rxBw); state = setRxBandwidth(rxBw);
if(state != ERR_NONE) { if(state != ERR_NONE) {
return(state); return(state);
} }
// configure default frequency deviation
state = setFrequencyDeviation(freqDev); state = setFrequencyDeviation(freqDev);
if(state != ERR_NONE) { if(state != ERR_NONE) {
return(state); return(state);
} }
// configure default TX output power
state = setOutputPower(power); state = setOutputPower(power);
if(state != ERR_NONE) { if(state != ERR_NONE) {
return(state); return(state);
@ -81,6 +85,12 @@ int16_t SX1231::begin(float freq, float br, float rxBw, float freqDev, int8_t po
return(state); return(state);
} }
// set default packet length mode
state = variablePacketLengthMode();
if (state != ERR_NONE) {
return(state);
}
// SX1231 V2a only // SX1231 V2a only
if(_chipRevision == SX1231_CHIP_REVISION_2_A) { if(_chipRevision == SX1231_CHIP_REVISION_2_A) {
// modify default OOK threshold value // modify default OOK threshold value

View file

@ -1,9 +1,9 @@
#ifndef _RADIOLIB_SX1231_H #ifndef _RADIOLIB_SX1231_H
#define _RADIOLIB_SX1231_H #define _RADIOLIB_SX1231_H
#include "TypeDef.h" #include "../../TypeDef.h"
#include "Module.h" #include "../../Module.h"
#include "RF69.h" #include "../RF69/RF69.h"
#define SX1231_CHIP_REVISION_2_A 0x21 #define SX1231_CHIP_REVISION_2_A 0x21
#define SX1231_CHIP_REVISION_2_B 0x22 #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); 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: private:
#endif
uint8_t _chipRevision; uint8_t _chipRevision;
}; };

View file

@ -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

View 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;
}

View 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

View file

@ -22,6 +22,11 @@ int16_t SX1262::begin(float freq, float bw, uint8_t sf, uint8_t cr, uint16_t syn
return(state); return(state);
} }
state = SX126x::fixPaClamping();
if (state != ERR_NONE) {
return state;
}
return(state); return(state);
} }
@ -43,6 +48,11 @@ int16_t SX1262::beginFSK(float freq, float br, float freqDev, float rxBw, int8_t
return(state); return(state);
} }
state = SX126x::fixPaClamping();
if (state != ERR_NONE) {
return state;
}
return(state); return(state);
} }
@ -85,28 +95,32 @@ int16_t SX1262::setFrequency(float freq, bool calibrate) {
int16_t SX1262::setOutputPower(int8_t power) { int16_t SX1262::setOutputPower(int8_t power) {
// check allowed power range // check allowed power range
if(!((power >= -17) && (power <= 22))) { if (!((power >= -17) && (power <= 22))) {
return(ERR_INVALID_OUTPUT_POWER); return(ERR_INVALID_OUTPUT_POWER);
} }
// get current OCP configuration // get current OCP configuration
uint8_t ocp = 0; uint8_t ocp = 0;
int16_t state = readRegister(SX126X_REG_OCP_CONFIGURATION, &ocp, 1); int16_t state = readRegister(SX126X_REG_OCP_CONFIGURATION, &ocp, 1);
if(state != ERR_NONE) { if (state != ERR_NONE) {
return(state); return(state);
} }
// enable high power PA for output power higher than 14 dBm // this function sets the optimal PA settings
if(power > 13) { // and adjusts power based on the PA settings chosen
SX126x::setPaConfig(0x04, SX126X_PA_CONFIG_SX1262); // so that output power matches requested power.
} else { state = SX126x::setOptimalHiPowerPaConfig(&power);
SX126x::setPaConfig(0x04, SX126X_PA_CONFIG_SX1261); if (state != ERR_NONE) {
return(state);
} }
// set output power // set output power
// TODO power ramp time configuration // TODO power ramp time configuration
SX126x::setTxParams(power); state = SX126x::setTxParams(power);
if (state != ERR_NONE) {
return(state);
}
// restore OCP configuration // restore OCP configuration
return(writeRegister(SX126X_REG_OCP_CONFIGURATION, &ocp, 1)); return writeRegister(SX126X_REG_OCP_CONFIGURATION, &ocp, 1);
} }

View file

@ -1,14 +1,10 @@
#ifndef _RADIOLIB_SX1262_H #ifndef _RADIOLIB_SX1262_H
#define _RADIOLIB_SX1262_H #define _RADIOLIB_SX1262_H
#include "TypeDef.h" #include "../../TypeDef.h"
#include "Module.h" #include "../../Module.h"
#include "SX126x.h" #include "SX126x.h"
//SX126X_CMD_SET_PA_CONFIG
#define SX126X_PA_CONFIG_SX1261 0x01
#define SX126X_PA_CONFIG_SX1262 0x00
/*! /*!
\class SX1262 \class SX1262
@ -93,8 +89,9 @@ class SX1262: public SX126x {
*/ */
int16_t setOutputPower(int8_t power); int16_t setOutputPower(int8_t power);
#ifndef RADIOLIB_GODMODE
private: private:
#endif
}; };

View file

@ -22,6 +22,11 @@ int16_t SX1268::begin(float freq, float bw, uint8_t sf, uint8_t cr, uint16_t syn
return(state); return(state);
} }
state = SX126x::fixPaClamping();
if (state != ERR_NONE) {
return state;
}
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) { 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); return(state);
} }
state = SX126x::fixPaClamping();
if (state != ERR_NONE) {
return state;
}
return(state); return(state);
} }
@ -89,13 +99,19 @@ int16_t SX1268::setOutputPower(int8_t power) {
return(state); return(state);
} }
// enable high power PA // enable optimal PA - this changes the value of power.
SX126x::setPaConfig(0x04, SX126X_PA_CONFIG_SX1268); state = SX126x::setOptimalHiPowerPaConfig(&power);
if (state != ERR_NONE) {
return(state);
}
// set output power // set output power
// TODO power ramp time configuration // TODO power ramp time configuration
SX126x::setTxParams(power); state = SX126x::setTxParams(power);
if (state != ERR_NONE) {
return(state);
}
// restore OCP configuration // restore OCP configuration
return(writeRegister(SX126X_REG_OCP_CONFIGURATION, &ocp, 1)); return writeRegister(SX126X_REG_OCP_CONFIGURATION, &ocp, 1);
} }

View file

@ -1,8 +1,8 @@
#ifndef _RADIOLIB_SX1268_H #ifndef _RADIOLIB_SX1268_H
#define _RADIOLIB_SX1268_H #define _RADIOLIB_SX1268_H
#include "TypeDef.h" #include "../../TypeDef.h"
#include "Module.h" #include "../../Module.h"
#include "SX126x.h" #include "SX126x.h"
//SX126X_CMD_SET_PA_CONFIG //SX126X_CMD_SET_PA_CONFIG
@ -91,6 +91,11 @@ class SX1268: public SX126x {
\returns \ref status_codes \returns \ref status_codes
*/ */
int16_t setOutputPower(int8_t power); int16_t setOutputPower(int8_t power);
#ifndef RADIOLIB_GODMODE
private:
#endif
}; };
#endif #endif

View file

@ -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) { int16_t SX126x::begin(float bw, uint8_t sf, uint8_t cr, uint16_t syncWord, float currentLimit, uint16_t preambleLength) {
// set module properties // set module properties
_mod->init(USE_SPI, INT_BOTH); _mod->init(RADIOLIB_USE_SPI, RADIOLIB_INT_BOTH);
pinMode(_mod->getRx(), INPUT); pinMode(_mod->getRx(), INPUT);
// BW in kHz and SF are required in order to calculate LDRO for setModulationParams // 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) { int16_t SX126x::beginFSK(float br, float freqDev, float rxBw, float currentLimit, uint16_t preambleLength, float dataShaping) {
// set module properties // set module properties
_mod->init(USE_SPI, INT_BOTH); _mod->init(RADIOLIB_USE_SPI, RADIOLIB_INT_BOTH);
pinMode(_mod->getRx(), INPUT); pinMode(_mod->getRx(), INPUT);
// initialize configuration variables (will be overwritten during public settings configuration) // 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); return(state);
} }
state = setWhitening(true, 0x0100);
if(state != ERR_NONE) {
return(state);
}
state = setDio2AsRfSwitch(false); state = setDio2AsRfSwitch(false);
return(state); return(state);
@ -167,9 +172,9 @@ int16_t SX126x::transmit(uint8_t* data, size_t len, uint8_t addr) {
return(ERR_UNKNOWN); return(ERR_UNKNOWN);
} }
DEBUG_PRINT(F("Timeout in ")); RADIOLIB_DEBUG_PRINT(F("Timeout in "));
DEBUG_PRINT(timeout); RADIOLIB_DEBUG_PRINT(timeout);
DEBUG_PRINTLN(F(" us")); RADIOLIB_DEBUG_PRINTLN(F(" us"));
// start transmission // start transmission
state = startTransmit(data, len, addr); state = startTransmit(data, len, addr);
@ -231,9 +236,9 @@ int16_t SX126x::receive(uint8_t* data, size_t len) {
return(ERR_UNKNOWN); return(ERR_UNKNOWN);
} }
DEBUG_PRINT(F("Timeout in ")); RADIOLIB_DEBUG_PRINT(F("Timeout in "));
DEBUG_PRINT(timeout); RADIOLIB_DEBUG_PRINT(timeout);
DEBUG_PRINTLN(F(" us")); RADIOLIB_DEBUG_PRINTLN(F(" us"));
// start reception // start reception
uint32_t timeoutValue = (uint32_t)((float)timeout / 15.625); 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(); uint32_t start = micros();
while(!digitalRead(_mod->getInt0())) { while(!digitalRead(_mod->getInt0())) {
if(micros() - start > timeout) { if(micros() - start > timeout) {
fixImplicitTimeout();
clearIrqStatus(); clearIrqStatus();
return(ERR_RX_TIMEOUT); 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 // read the received data
return(readData(data, len)); 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); 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 // set packet Length
int16_t state = ERR_NONE; int16_t state = ERR_NONE;
uint8_t modem = getPacketType(); uint8_t modem = getPacketType();
if(modem == SX126X_PACKET_TYPE_LORA) { if(modem == SX126X_PACKET_TYPE_LORA) {
state = setPacketParams(_preambleLength, _crcType, len); state = setPacketParams(_preambleLength, _crcType, len);
} else if(modem == SX126X_PACKET_TYPE_GFSK) { } else if(modem == SX126X_PACKET_TYPE_GFSK) {
state = setPacketParamsFSK(_preambleLengthFSK, _crcTypeFSK, _syncWordLength, _addrComp, len); state = setPacketParamsFSK(_preambleLengthFSK, _crcTypeFSK, _syncWordLength, _addrComp, _whitening, _packetType, len);
} else { } else {
return(ERR_UNKNOWN); return(ERR_UNKNOWN);
} }
@ -397,6 +414,12 @@ int16_t SX126x::startTransmit(uint8_t* data, size_t len, uint8_t addr) {
return(state); return(state);
} }
// fix sensitivity
state = fixSensitivity();
if(state != ERR_NONE) {
return(state);
}
// start transmission // start transmission
state = setTx(SX126X_TX_TIMEOUT_NONE); state = setTx(SX126X_TX_TIMEOUT_NONE);
if(state != ERR_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) { 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 // check integrity CRC
uint16_t irq = getIrqStatus(); uint16_t irq = getIrqStatus();
if((irq & SX126X_IRQ_CRC_ERR) || (irq & SX126X_IRQ_HEADER_ERR)) { 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 // read packet data
int16_t state = readBuffer(data, length); state = readBuffer(data, length);
if(state != ERR_NONE) { if(state != ERR_NONE) {
return(state); return(state);
} }
@ -554,7 +583,7 @@ int16_t SX126x::setPreambleLength(uint16_t preambleLength) {
return(setPacketParams(_preambleLength, _crcType)); return(setPacketParams(_preambleLength, _crcType));
} else if(modem == SX126X_PACKET_TYPE_GFSK) { } else if(modem == SX126X_PACKET_TYPE_GFSK) {
_preambleLengthFSK = preambleLength; _preambleLengthFSK = preambleLength;
return(setPacketParamsFSK(_preambleLengthFSK, _crcTypeFSK, _syncWordLength, _addrComp)); return(setPacketParamsFSK(_preambleLengthFSK, _crcTypeFSK, _syncWordLength, _addrComp, _whitening, _packetType));
} }
return(ERR_UNKNOWN); return(ERR_UNKNOWN);
@ -716,7 +745,7 @@ int16_t SX126x::setSyncWord(uint8_t* syncWord, uint8_t len) {
// update packet parameters // update packet parameters
_syncWordLength = len * 8; _syncWordLength = len * 8;
state = setPacketParamsFSK(_preambleLengthFSK, _crcTypeFSK, _syncWordLength, _addrComp); state = setPacketParamsFSK(_preambleLengthFSK, _crcTypeFSK, _syncWordLength, _addrComp, _whitening, _packetType);
return(state); return(state);
} }
@ -745,7 +774,7 @@ int16_t SX126x::setSyncBits(uint8_t *syncWord, uint8_t bitsLen) {
// update packet parameters // update packet parameters
_syncWordLength = bitsLen; _syncWordLength = bitsLen;
state = setPacketParamsFSK(_preambleLengthFSK, _crcTypeFSK, _syncWordLength, _addrComp); state = setPacketParamsFSK(_preambleLengthFSK, _crcTypeFSK, _syncWordLength, _addrComp, _whitening, _packetType);
return(state); return(state);
} }
@ -758,7 +787,7 @@ int16_t SX126x::setNodeAddress(uint8_t nodeAddr) {
// enable address filtering (node only) // enable address filtering (node only)
_addrComp = SX126X_GFSK_ADDRESS_FILT_NODE; _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) { if(state != ERR_NONE) {
return(state); return(state);
} }
@ -777,7 +806,7 @@ int16_t SX126x::setBroadcastAddress(uint8_t broadAddr) {
// enable address filtering (node and broadcast) // enable address filtering (node and broadcast)
_addrComp = SX126X_GFSK_ADDRESS_FILT_NODE_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) { if(state != ERR_NONE) {
return(state); return(state);
} }
@ -796,7 +825,7 @@ int16_t SX126x::disableAddressFiltering() {
// disable address filtering // disable address filtering
_addrComp = SX126X_GFSK_ADDRESS_FILT_OFF; _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) { 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); 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) { if(state != ERR_NONE) {
return(state); return(state);
} }
@ -862,6 +891,50 @@ int16_t SX126x::setCRC(uint8_t len, uint16_t initial, uint16_t polynomial, bool
return(ERR_UNKNOWN); 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() { float SX126x::getDataRate() {
return(_dataRate); return(_dataRate);
} }
@ -892,6 +965,14 @@ size_t SX126x::getPacketLength(bool update) {
return((size_t)rxBufStatus[0]); 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) { uint32_t SX126x::getTimeOnAir(size_t len) {
if(getPacketType() == SX126X_PACKET_TYPE_LORA) { if(getPacketType() == SX126X_PACKET_TYPE_LORA) {
float symbolLength = (float)((uint32_t)(1) << _sf) / (float)_bwKhz; 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 // set mode to standby
standby(); standby();
// check SX126X_XOSC_START_ERR flag and clear it
if(getDeviceErrors() & SX126X_XOSC_START_ERR) {
clearDeviceErrors();
}
// check alowed voltage values // check alowed voltage values
uint8_t data[4]; uint8_t data[4];
if(abs(voltage - 1.6) <= 0.001) { 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); return(ERR_INVALID_TCXO_VOLTAGE);
} }
// calculate timeout // calculate delay
uint32_t timeoutValue = (float)timeout / 15.625; uint32_t delayValue = (float)delay / 15.625;
data[1] = (uint8_t)((timeoutValue >> 16) & 0xFF); data[1] = (uint8_t)((delayValue >> 16) & 0xFF);
data[2] = (uint8_t)((timeoutValue >> 8) & 0xFF); data[2] = (uint8_t)((delayValue >> 8) & 0xFF);
data[3] = (uint8_t)(timeoutValue & 0xFF); data[3] = (uint8_t)(delayValue & 0xFF);
// enable TCXO control on DIO3 // enable TCXO control on DIO3
SPIwriteCommand(SX126X_CMD_SET_DIO3_AS_TCXO_CTRL, data, 4); 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) { int16_t SX126x::writeRegister(uint16_t addr, uint8_t* data, uint8_t numBytes) {
uint8_t* dat = new uint8_t[2 + numBytes]; uint8_t cmd[] = { SX126X_CMD_WRITE_REGISTER, (uint8_t)((addr >> 8) & 0xFF), (uint8_t)(addr & 0xFF) };
dat[0] = (uint8_t)((addr >> 8) & 0xFF); int16_t state = SPIwriteCommand(cmd, 3, data, numBytes);
dat[1] = (uint8_t)(addr & 0xFF);
memcpy(dat + 2, data, numBytes);
int16_t state = SPIwriteCommand(SX126X_CMD_WRITE_REGISTER, dat, 2 + numBytes);
delete[] dat;
return(state); 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) { int16_t SX126x::writeBuffer(uint8_t* data, uint8_t numBytes, uint8_t offset) {
uint8_t* dat = new uint8_t[1 + numBytes]; uint8_t cmd[] = { SX126X_CMD_WRITE_BUFFER, offset };
dat[0] = offset; int16_t state = SPIwriteCommand(cmd, 2, data, numBytes);
memcpy(dat + 1, data, numBytes);
int16_t state = SPIwriteCommand(SX126X_CMD_WRITE_BUFFER, dat, 1 + numBytes);
delete[] dat;
return(state); return(state);
} }
int16_t SX126x::readBuffer(uint8_t* data, uint8_t numBytes) { int16_t SX126x::readBuffer(uint8_t* data, uint8_t numBytes) {
// offset will be always set to 0 (one extra NOP is sent) uint8_t cmd[] = { SX126X_CMD_READ_BUFFER, SX126X_CMD_NOP };
uint8_t* dat = new uint8_t[1 + numBytes]; int16_t state = SPIreadCommand(cmd, 2, data, 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;
return(state); 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)); 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) { 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 // calculate symbol length and enable low data rate optimization, if needed
if(ldro == 0xFF) { if(ldro == 0xFF) {
float symbolLength = (float)(uint32_t(1) << _sf) / (float)_bwKhz; float symbolLength = (float)(uint32_t(1) << _sf) / (float)_bwKhz;
DEBUG_PRINT("Symbol length: "); RADIOLIB_DEBUG_PRINT("Symbol length: ");
DEBUG_PRINT(symbolLength); RADIOLIB_DEBUG_PRINT(symbolLength);
DEBUG_PRINTLN(" ms"); RADIOLIB_DEBUG_PRINTLN(" ms");
if(symbolLength >= 16.0) { if(symbolLength >= 16.0) {
_ldro = SX126X_LORA_LOW_DATA_RATE_OPTIMIZE_ON; _ldro = SX126X_LORA_LOW_DATA_RATE_OPTIMIZE_ON;
} else { } 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) { 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}; 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)); 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), uint8_t data[9] = {(uint8_t)((preambleLength >> 8) & 0xFF), (uint8_t)(preambleLength & 0xFF),
preambleDetectorLength, syncWordLength, addrComp, preambleDetectorLength, syncWordLength, addrComp,
packetType, payloadLength, crcType, whitening}; packetType, payloadLength, crcType, whitening};
@ -1118,8 +1235,8 @@ uint16_t SX126x::getDeviceErrors() {
} }
int16_t SX126x::clearDeviceErrors() { int16_t SX126x::clearDeviceErrors() {
uint8_t data[1] = {SX126X_CMD_NOP}; uint8_t data[2] = {SX126X_CMD_NOP, SX126X_CMD_NOP};
return(SPIwriteCommand(SX126X_CMD_CLEAR_DEVICE_ERRORS, data, 1)); return(SPIwriteCommand(SX126X_CMD_CLEAR_DEVICE_ERRORS, data, 2));
} }
int16_t SX126x::setFrequencyRaw(float freq) { int16_t SX126x::setFrequencyRaw(float freq) {
@ -1129,9 +1246,90 @@ int16_t SX126x::setFrequencyRaw(float freq) {
return(ERR_NONE); 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) { int16_t SX126x::config(uint8_t modem) {
// set regulator mode // set regulator mode
uint8_t* data = new uint8_t[1]; uint8_t data[7];
data[0] = SX126X_REGULATOR_DC_DC; data[0] = SX126X_REGULATOR_DC_DC;
int16_t state = SPIwriteCommand(SX126X_CMD_SET_REGULATOR_MODE, data, 1); int16_t state = SPIwriteCommand(SX126X_CMD_SET_REGULATOR_MODE, data, 1);
if(state != ERR_NONE) { if(state != ERR_NONE) {
@ -1159,8 +1357,6 @@ int16_t SX126x::config(uint8_t modem) {
} }
// set CAD parameters // set CAD parameters
delete[] data;
data = new uint8_t[7];
data[0] = SX126X_CAD_ON_8_SYMB; data[0] = SX126X_CAD_ON_8_SYMB;
data[1] = _sf + 13; data[1] = _sf + 13;
data[2] = 10; data[2] = 10;
@ -1181,8 +1377,6 @@ int16_t SX126x::config(uint8_t modem) {
} }
// calibrate all blocks // calibrate all blocks
delete[] data;
data = new uint8_t[1];
data[0] = SX126X_CALIBRATE_ALL; data[0] = SX126X_CALIBRATE_ALL;
state = SPIwriteCommand(SX126X_CMD_CALIBRATE, data, 1); state = SPIwriteCommand(SX126X_CMD_CALIBRATE, data, 1);
if(state != ERR_NONE) { if(state != ERR_NONE) {
@ -1193,19 +1387,23 @@ int16_t SX126x::config(uint8_t modem) {
delayMicroseconds(1); delayMicroseconds(1);
while(digitalRead(_mod->getRx())); while(digitalRead(_mod->getRx()));
delete[] data;
return(ERR_NONE); 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) { int16_t SX126x::SPIwriteCommand(uint8_t cmd, uint8_t* data, uint8_t numBytes, bool waitForBusy) {
uint8_t cmdBuffer[] = {cmd}; return(SX126x::SPItransfer(&cmd, 1, true, data, NULL, numBytes, waitForBusy));
return(SX126x::SPItransfer(cmdBuffer, 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) { int16_t SX126x::SPIreadCommand(uint8_t cmd, uint8_t* data, uint8_t numBytes, bool waitForBusy) {
uint8_t cmdBuffer[] = {cmd}; return(SX126x::SPItransfer(&cmd, 1, false, NULL, data, numBytes, waitForBusy));
return(SX126x::SPItransfer(cmdBuffer, 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) { 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(); SPIClass* spi = _mod->getSpi();
SPISettings spiSettings = _mod->getSpiSettings(); 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) // ensure BUSY is low (state meachine ready)
RADIOLIB_VERBOSE_PRINTLN(F("Wait for BUSY ... "));
uint32_t start = millis(); uint32_t start = millis();
while(digitalRead(_mod->getRx())) { while(digitalRead(_mod->getRx())) {
if(millis() - start >= timeout) { 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 // start transfer
digitalWrite(_mod->getCs(), LOW);
spi->beginTransaction(spiSettings); spi->beginTransaction(spiSettings);
// send command byte(s) // send command byte(s)
for(uint8_t n = 0; n < cmdLen; n++) { for(uint8_t n = 0; n < cmdLen; n++) {
spi->transfer(cmd[n]); spi->transfer(cmd[n]);
DEBUG_PRINT(cmd[n], HEX);
DEBUG_PRINT('\t');
} }
// variable to save error during SPI transfer // 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++) { for(uint8_t n = 0; n < numBytes; n++) {
// send byte // send byte
uint8_t in = spi->transfer(dataOut[n]); uint8_t in = spi->transfer(dataOut[n]);
DEBUG_PRINT(dataOut[n], HEX); #ifdef RADIOLIB_VERBOSE
DEBUG_PRINT('\t'); debugBuff[n] = in;
DEBUG_PRINT(in, HEX); #endif
DEBUG_PRINT('\t');
// check status // check status
if(((in & 0b00001110) == SX126X_STATUS_CMD_TIMEOUT) || if(((in & 0b00001110) == SX126X_STATUS_CMD_TIMEOUT) ||
((in & 0b00001110) == SX126X_STATUS_CMD_INVALID) || ((in & 0b00001110) == SX126X_STATUS_CMD_INVALID) ||
((in & 0b00001110) == SX126X_STATUS_CMD_FAILED)) { ((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 { } else {
// skip the first byte for read-type commands (status-only) // skip the first byte for read-type commands (status-only)
uint8_t in = spi->transfer(SX126X_CMD_NOP); uint8_t in = spi->transfer(SX126X_CMD_NOP);
DEBUG_PRINT(SX126X_CMD_NOP, HEX); #ifdef RADIOLIB_VERBOSE
DEBUG_PRINT('\t'); debugBuff[0] = in;
DEBUG_PRINT(in, HEX); #endif
DEBUG_PRINT('\t')
// check status // check status
if(((in & 0b00001110) == SX126X_STATUS_CMD_TIMEOUT) || if(((in & 0b00001110) == SX126X_STATUS_CMD_TIMEOUT) ||
((in & 0b00001110) == SX126X_STATUS_CMD_INVALID) || ((in & 0b00001110) == SX126X_STATUS_CMD_INVALID) ||
((in & 0b00001110) == SX126X_STATUS_CMD_FAILED)) { ((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++) { for(uint8_t n = 0; n < numBytes; n++) {
dataIn[n] = spi->transfer(SX126X_CMD_NOP); 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 // stop transfer
@ -1287,11 +1490,52 @@ int16_t SX126x::SPItransfer(uint8_t* cmd, uint8_t cmdLen, bool write, uint8_t* d
start = millis(); start = millis();
while(digitalRead(_mod->getRx())) { while(digitalRead(_mod->getRx())) {
if(millis() - start >= timeout) { 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 // parse status
switch(status) { switch(status) {
case SX126X_STATUS_CMD_TIMEOUT: 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); return(ERR_SPI_CMD_INVALID);
case SX126X_STATUS_CMD_FAILED: case SX126X_STATUS_CMD_FAILED:
return(ERR_SPI_CMD_FAILED); return(ERR_SPI_CMD_FAILED);
case SX126X_STATUS_SPI_FAILED:
return(ERR_CHIP_NOT_FOUND);
default: default:
return(ERR_NONE); return(ERR_NONE);
} }

View file

@ -1,10 +1,10 @@
#ifndef _RADIOLIB_SX126X_H #ifndef _RADIOLIB_SX126X_H
#define _RADIOLIB_SX126X_H #define _RADIOLIB_SX126X_H
#include "TypeDef.h" #include "../../TypeDef.h"
#include "Module.h" #include "../../Module.h"
#include "../protocols/PhysicalLayer.h" #include "../../protocols/PhysicalLayer/PhysicalLayer.h"
// SX126X physical layer properties // SX126X physical layer properties
#define SX126X_CRYSTAL_FREQ 32.0 #define SX126X_CRYSTAL_FREQ 32.0
@ -93,6 +93,16 @@
#define SX126X_REG_XTA_TRIM 0x0911 #define SX126X_REG_XTA_TRIM 0x0911
#define SX126X_REG_XTB_TRIM 0x0912 #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 SPI command variables
//SX126X_CMD_SET_SLEEP //SX126X_CMD_SET_SLEEP
@ -152,6 +162,7 @@
//SX126X_CMD_SET_PA_CONFIG //SX126X_CMD_SET_PA_CONFIG
#define SX126X_PA_CONFIG_HP_MAX 0x07 #define SX126X_PA_CONFIG_HP_MAX 0x07
#define SX126X_PA_CONFIG_PA_LUT 0x01 #define SX126X_PA_CONFIG_PA_LUT 0x01
#define SX126X_PA_CONFIG_SX1262_8 0x00
//SX126X_CMD_SET_RX_TX_FALLBACK_MODE //SX126X_CMD_SET_RX_TX_FALLBACK_MODE
#define SX126X_RX_TX_FALLBACK_MODE_FS 0x40 // 7 0 after Rx/Tx go to: FS 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_INVALID 0b00001000 // 3 1 invalid SPI command
#define SX126X_STATUS_CMD_FAILED 0b00001010 // 3 1 SPI command failed to execute #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_TX_DONE 0b00001100 // 3 1 packet transmission done
#define SX126X_STATUS_SPI_FAILED 0b11111111 // 7 0 SPI transaction failed
//SX126X_CMD_GET_PACKET_STATUS //SX126X_CMD_GET_PACKET_STATUS
#define SX126X_GFSK_RX_STATUS_PREAMBLE_ERR 0b10000000 // 7 7 GFSK Rx status: preamble error #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); 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. \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. \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). \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); 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 \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); uint32_t getTimeOnAir(size_t len);
#ifndef RADIOLIB_GODMODE
protected: protected:
#endif
// SX1276x SPI command implementations // SX1276x SPI command implementations
int16_t setTx(uint32_t timeout = 0); int16_t setTx(uint32_t timeout = 0);
int16_t setRx(uint32_t timeout); 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 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 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 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); int16_t setBufferBaseAddress(uint8_t txBaseAddress = 0x00, uint8_t rxBaseAddress = 0x00);
uint8_t getStatus(); uint8_t getStatus();
uint32_t getPacketStatus(); uint32_t getPacketStatus();
@ -738,8 +781,18 @@ class SX126x: public PhysicalLayer {
int16_t clearDeviceErrors(); int16_t clearDeviceErrors();
int16_t setFrequencyRaw(float freq); 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: private:
#endif
Module* _mod; Module* _mod;
uint8_t _bw, _sf, _cr, _ldro, _crcType; uint8_t _bw, _sf, _cr, _ldro, _crcType;
@ -747,7 +800,7 @@ class SX126x: public PhysicalLayer {
float _bwKhz; float _bwKhz;
uint32_t _br, _freqDev; uint32_t _br, _freqDev;
uint8_t _rxBw, _pulseShape, _crcTypeFSK, _syncWordLength, _addrComp; uint8_t _rxBw, _pulseShape, _crcTypeFSK, _syncWordLength, _addrComp, _whitening, _packetType;
uint16_t _preambleLengthFSK; uint16_t _preambleLengthFSK;
float _rxBwKhz; float _rxBwKhz;
@ -757,7 +810,9 @@ class SX126x: public PhysicalLayer {
// common low-level SPI interface // 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* 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* 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); 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);
}; };

View file

@ -125,9 +125,9 @@ int16_t SX1272::setBandwidth(float bw) {
// calculate symbol length and set low data rate optimization, if needed // calculate symbol length and set low data rate optimization, if needed
float symbolLength = (float)(uint32_t(1) << SX127x::_sf) / (float)SX127x::_bw; float symbolLength = (float)(uint32_t(1) << SX127x::_sf) / (float)SX127x::_bw;
DEBUG_PRINT("Symbol length: "); RADIOLIB_DEBUG_PRINT("Symbol length: ");
DEBUG_PRINT(symbolLength); RADIOLIB_DEBUG_PRINT(symbolLength);
DEBUG_PRINTLN(" ms"); RADIOLIB_DEBUG_PRINTLN(" ms");
if(symbolLength >= 16.0) { if(symbolLength >= 16.0) {
state = _mod->SPIsetRegValue(SX127X_REG_MODEM_CONFIG_1, SX1272_LOW_DATA_RATE_OPT_ON, 0, 0); state = _mod->SPIsetRegValue(SX127X_REG_MODEM_CONFIG_1, SX1272_LOW_DATA_RATE_OPT_ON, 0, 0);
} else { } else {
@ -179,9 +179,9 @@ int16_t SX1272::setSpreadingFactor(uint8_t sf) {
// calculate symbol length and set low data rate optimization, if needed // calculate symbol length and set low data rate optimization, if needed
float symbolLength = (float)(uint32_t(1) << SX127x::_sf) / (float)SX127x::_bw; float symbolLength = (float)(uint32_t(1) << SX127x::_sf) / (float)SX127x::_bw;
DEBUG_PRINT("Symbol length: "); RADIOLIB_DEBUG_PRINT("Symbol length: ");
DEBUG_PRINT(symbolLength); RADIOLIB_DEBUG_PRINT(symbolLength);
DEBUG_PRINTLN(" ms"); RADIOLIB_DEBUG_PRINTLN(" ms");
if(symbolLength >= 16.0) { if(symbolLength >= 16.0) {
state = _mod->SPIsetRegValue(SX127X_REG_MODEM_CONFIG_1, SX1272_LOW_DATA_RATE_OPT_ON, 0, 0); state = _mod->SPIsetRegValue(SX127X_REG_MODEM_CONFIG_1, SX1272_LOW_DATA_RATE_OPT_ON, 0, 0);
} else { } else {
@ -342,13 +342,10 @@ int16_t SX1272::setDataShapingOOK(uint8_t sh) {
return(state); return(state);
} }
int8_t SX1272::getRSSI() { float SX1272::getRSSI() {
// check active modem if(getActiveModem() == SX127X_LORA) {
if(getActiveModem() != SX127X_LORA) { // RSSI calculation uses different constant for low-frequency and high-frequency ports
return(0); float lastPacketRSSI = -139 + _mod->SPIgetRegValue(SX127X_REG_PKT_RSSI_VALUE);
}
int8_t lastPacketRSSI = -139 + _mod->SPIgetRegValue(SX127X_REG_PKT_RSSI_VALUE);
// spread-spectrum modulation signal can be received below noise floor // 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 // check last packet SNR and if it's less than 0, add it to reported RSSI to get the correct value
@ -358,6 +355,20 @@ int8_t SX1272::getRSSI() {
} }
return(lastPacketRSSI); 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);
}
} }
int16_t SX1272::setCRC(bool enableCRC) { int16_t SX1272::setCRC(bool enableCRC) {

View file

@ -1,8 +1,8 @@
#ifndef _RADIOLIB_SX1272_H #ifndef _RADIOLIB_SX1272_H
#define _RADIOLIB_SX1272_H #define _RADIOLIB_SX1272_H
#include "TypeDef.h" #include "../../TypeDef.h"
#include "Module.h" #include "../../Module.h"
#include "SX127x.h" #include "SX127x.h"
// SX1272 specific register map // SX1272 specific register map
@ -235,11 +235,11 @@ class SX1272: public SX127x {
int16_t setDataShapingOOK(uint8_t sh); 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. \brief Enables/disables CRC check of received packets.
@ -250,14 +250,18 @@ class SX1272: public SX127x {
*/ */
int16_t setCRC(bool enableCRC); int16_t setCRC(bool enableCRC);
#ifndef RADIOLIB_GODMODE
protected: protected:
#endif
int16_t setBandwidthRaw(uint8_t newBandwidth); int16_t setBandwidthRaw(uint8_t newBandwidth);
int16_t setSpreadingFactorRaw(uint8_t newSpreadingFactor); int16_t setSpreadingFactorRaw(uint8_t newSpreadingFactor);
int16_t setCodingRateRaw(uint8_t newCodingRate); int16_t setCodingRateRaw(uint8_t newCodingRate);
int16_t configFSK(); int16_t configFSK();
#ifndef RADIOLIB_GODMODE
private: private:
#endif
}; };

View file

@ -1,7 +1,7 @@
#ifndef _RADIOLIB_SX1273_H #ifndef _RADIOLIB_SX1273_H
#define _RADIOLIB_SX1273_H #define _RADIOLIB_SX1273_H
#include "TypeDef.h" #include "../../TypeDef.h"
#include "SX1272.h" #include "SX1272.h"
/*! /*!
@ -61,6 +61,11 @@ class SX1273: public SX1272 {
\returns \ref status_codes \returns \ref status_codes
*/ */
int16_t setSpreadingFactor(uint8_t sf); int16_t setSpreadingFactor(uint8_t sf);
#ifndef RADIOLIB_GODMODE
private:
#endif
}; };
#endif #endif

View file

@ -1,7 +1,7 @@
#ifndef _RADIOLIB_SX1276_H #ifndef _RADIOLIB_SX1276_H
#define _RADIOLIB_SX1276_H #define _RADIOLIB_SX1276_H
#include "TypeDef.h" #include "../../TypeDef.h"
#include "SX1278.h" #include "SX1278.h"
/*! /*!
@ -61,6 +61,11 @@ class SX1276: public SX1278 {
\returns \ref status_codes \returns \ref status_codes
*/ */
int16_t setFrequency(float freq); int16_t setFrequency(float freq);
#ifndef RADIOLIB_GODMODE
private:
#endif
}; };
#endif #endif

View file

@ -1,7 +1,7 @@
#ifndef _RADIOLIB_SX1277_H #ifndef _RADIOLIB_SX1277_H
#define _RADIOLIB_SX1277_H #define _RADIOLIB_SX1277_H
#include "TypeDef.h" #include "../../TypeDef.h"
#include "SX1278.h" #include "SX1278.h"
/*! /*!
@ -70,6 +70,11 @@ class SX1277: public SX1278 {
\returns \ref status_codes \returns \ref status_codes
*/ */
int16_t setSpreadingFactor(uint8_t sf); int16_t setSpreadingFactor(uint8_t sf);
#ifndef RADIOLIB_GODMODE
private:
#endif
}; };
#endif #endif

View file

@ -195,9 +195,9 @@ int16_t SX1278::setBandwidth(float bw) {
// calculate symbol length and set low data rate optimization, if needed // calculate symbol length and set low data rate optimization, if needed
float symbolLength = (float)(uint32_t(1) << SX127x::_sf) / (float)SX127x::_bw; float symbolLength = (float)(uint32_t(1) << SX127x::_sf) / (float)SX127x::_bw;
DEBUG_PRINT("Symbol length: "); RADIOLIB_DEBUG_PRINT("Symbol length: ");
DEBUG_PRINT(symbolLength); RADIOLIB_DEBUG_PRINT(symbolLength);
DEBUG_PRINTLN(" ms"); RADIOLIB_DEBUG_PRINTLN(" ms");
if(symbolLength >= 16.0) { if(symbolLength >= 16.0) {
state = _mod->SPIsetRegValue(SX1278_REG_MODEM_CONFIG_3, SX1278_LOW_DATA_RATE_OPT_ON, 3, 3); state = _mod->SPIsetRegValue(SX1278_REG_MODEM_CONFIG_3, SX1278_LOW_DATA_RATE_OPT_ON, 3, 3);
} else { } else {
@ -249,9 +249,9 @@ int16_t SX1278::setSpreadingFactor(uint8_t sf) {
// calculate symbol length and set low data rate optimization, if needed // calculate symbol length and set low data rate optimization, if needed
float symbolLength = (float)(uint32_t(1) << SX127x::_sf) / (float)SX127x::_bw; float symbolLength = (float)(uint32_t(1) << SX127x::_sf) / (float)SX127x::_bw;
DEBUG_PRINT("Symbol length: "); RADIOLIB_DEBUG_PRINT("Symbol length: ");
DEBUG_PRINT(symbolLength); RADIOLIB_DEBUG_PRINT(symbolLength);
DEBUG_PRINTLN(" ms"); RADIOLIB_DEBUG_PRINTLN(" ms");
if(symbolLength >= 16.0) { if(symbolLength >= 16.0) {
state = _mod->SPIsetRegValue(SX1278_REG_MODEM_CONFIG_3, SX1278_LOW_DATA_RATE_OPT_ON, 3, 3); state = _mod->SPIsetRegValue(SX1278_REG_MODEM_CONFIG_3, SX1278_LOW_DATA_RATE_OPT_ON, 3, 3);
} else { } else {
@ -411,13 +411,10 @@ int16_t SX1278::setDataShapingOOK(uint8_t sh) {
return(state); return(state);
} }
int8_t SX1278::getRSSI() { float SX1278::getRSSI() {
// check active modem if(getActiveModem() == SX127X_LORA) {
if(getActiveModem() != SX127X_LORA) { // for LoRa, get RSSI of the last packet
return(0); float lastPacketRSSI;
}
int8_t lastPacketRSSI;
// RSSI calculation uses different constant for low-frequency and high-frequency ports // RSSI calculation uses different constant for low-frequency and high-frequency ports
if(_freq < 868.0) { if(_freq < 868.0) {
@ -434,6 +431,20 @@ int8_t SX1278::getRSSI() {
} }
return(lastPacketRSSI); 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);
}
} }
int16_t SX1278::setCRC(bool enableCRC) { int16_t SX1278::setCRC(bool enableCRC) {

View file

@ -1,8 +1,8 @@
#ifndef _RADIOLIB_SX1278_H #ifndef _RADIOLIB_SX1278_H
#define _RADIOLIB_SX1278_H #define _RADIOLIB_SX1278_H
#include "TypeDef.h" #include "../../TypeDef.h"
#include "Module.h" #include "../../Module.h"
#include "SX127x.h" #include "SX127x.h"
// SX1278 specific register map // SX1278 specific register map
@ -244,11 +244,11 @@ class SX1278: public SX127x {
int16_t setDataShapingOOK(uint8_t sh); 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. \brief Enables/disables CRC check of received packets.
@ -259,14 +259,18 @@ class SX1278: public SX127x {
*/ */
int16_t setCRC(bool enableCRC); int16_t setCRC(bool enableCRC);
#ifndef RADIOLIB_GODMODE
protected: protected:
#endif
int16_t setBandwidthRaw(uint8_t newBandwidth); int16_t setBandwidthRaw(uint8_t newBandwidth);
int16_t setSpreadingFactorRaw(uint8_t newSpreadingFactor); int16_t setSpreadingFactorRaw(uint8_t newSpreadingFactor);
int16_t setCodingRateRaw(uint8_t newCodingRate); int16_t setCodingRateRaw(uint8_t newCodingRate);
int16_t configFSK(); int16_t configFSK();
#ifndef RADIOLIB_GODMODE
private: private:
#endif
}; };

View file

@ -1,7 +1,7 @@
#ifndef _RADIOLIB_SX1279_H #ifndef _RADIOLIB_SX1279_H
#define _RADIOLIB_SX1279_H #define _RADIOLIB_SX1279_H
#include "TypeDef.h" #include "../../TypeDef.h"
#include "SX1278.h" #include "SX1278.h"
/*! /*!
@ -61,6 +61,11 @@ class SX1279: public SX1278 {
\returns \ref status_codes \returns \ref status_codes
*/ */
int16_t setFrequency(float freq); int16_t setFrequency(float freq);
#ifndef RADIOLIB_GODMODE
private:
#endif
}; };
#endif #endif

View file

@ -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) { int16_t SX127x::begin(uint8_t chipVersion, uint8_t syncWord, uint8_t currentLimit, uint16_t preambleLength) {
// set module properties // set module properties
_mod->init(USE_SPI, INT_BOTH); _mod->init(RADIOLIB_USE_SPI, RADIOLIB_INT_BOTH);
// try to find the SX127x chip // try to find the SX127x chip
if(!SX127x::findChip(chipVersion)) { if(!SX127x::findChip(chipVersion)) {
DEBUG_PRINTLN(F("No SX127x found!")); RADIOLIB_DEBUG_PRINTLN(F("No SX127x found!"));
_mod->term(); _mod->term();
return(ERR_CHIP_NOT_FOUND); return(ERR_CHIP_NOT_FOUND);
} else { } else {
DEBUG_PRINTLN(F("Found SX127x!")); RADIOLIB_DEBUG_PRINTLN(F("Found SX127x!"));
} }
// check active modem // check active modem
@ -42,6 +42,9 @@ int16_t SX127x::begin(uint8_t chipVersion, uint8_t syncWord, uint8_t currentLimi
// set preamble length // set preamble length
state = SX127x::setPreambleLength(preambleLength); state = SX127x::setPreambleLength(preambleLength);
if(state != ERR_NONE) {
return(state);
}
// initalize internal variables // initalize internal variables
_dataRate = 0.0; _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) { int16_t SX127x::beginFSK(uint8_t chipVersion, float br, float freqDev, float rxBw, uint8_t currentLimit, uint16_t preambleLength, bool enableOOK) {
// set module properties // set module properties
_mod->init(USE_SPI, INT_BOTH); _mod->init(RADIOLIB_USE_SPI, RADIOLIB_INT_BOTH);
// try to find the SX127x chip // try to find the SX127x chip
if(!SX127x::findChip(chipVersion)) { if(!SX127x::findChip(chipVersion)) {
DEBUG_PRINTLN(F("No SX127x found!")); RADIOLIB_DEBUG_PRINTLN(F("No SX127x found!"));
_mod->term(); _mod->term();
return(ERR_CHIP_NOT_FOUND); return(ERR_CHIP_NOT_FOUND);
} else { } else {
DEBUG_PRINTLN(F("Found SX127x!")); RADIOLIB_DEBUG_PRINTLN(F("Found SX127x!"));
} }
// check currently active modem // check currently active modem
@ -117,6 +120,27 @@ int16_t SX127x::beginFSK(uint8_t chipVersion, float br, float freqDev, float rxB
// enable/disable OOK // enable/disable OOK
state = setOOK(enableOOK); 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); return(state);
} }
@ -174,6 +198,8 @@ int16_t SX127x::transmit(uint8_t* data, size_t len, uint8_t addr) {
return(ERR_TX_TIMEOUT); return(ERR_TX_TIMEOUT);
} }
} }
} else {
return(ERR_UNKNOWN);
} }
// update data rate // update data rate
@ -399,7 +425,7 @@ int16_t SX127x::startTransmit(uint8_t* data, size_t len, uint8_t addr) {
int16_t modem = getActiveModem(); int16_t modem = getActiveModem();
if(modem == SX127X_LORA) { if(modem == SX127X_LORA) {
// check packet length // check packet length
if(len >= 256) { if(len >= SX127X_MAX_PACKET_LENGTH) {
return(ERR_PACKET_TOO_LONG); 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) { } else if(modem == SX127X_FSK_OOK) {
// check packet length // check packet length
if(len >= 64) { if(len >= SX127X_MAX_PACKET_LENGTH_FSK) {
return(ERR_PACKET_TOO_LONG); return(ERR_PACKET_TOO_LONG);
} }
@ -467,6 +493,9 @@ int16_t SX127x::readData(uint8_t* data, size_t len) {
int16_t modem = getActiveModem(); int16_t modem = getActiveModem();
size_t length = len; size_t length = len;
// put module to standby
standby();
if(modem == SX127X_LORA) { if(modem == SX127X_LORA) {
// len set to maximum indicates unknown packet length, read the number of actually received bytes // len set to maximum indicates unknown packet length, read the number of actually received bytes
if(len == SX127X_MAX_PACKET_LENGTH) { if(len == SX127X_MAX_PACKET_LENGTH) {
@ -888,6 +917,60 @@ size_t SX127x::getPacketLength(bool update) {
return(_packetLength); 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() { int16_t SX127x::config() {
// turn off frequency hopping // turn off frequency hopping
int16_t state = _mod->SPIsetRegValue(SX127X_REG_HOP_PERIOD, SX127X_HOP_PERIOD_OFF); int16_t state = _mod->SPIsetRegValue(SX127X_REG_HOP_PERIOD, SX127X_HOP_PERIOD_OFF);
@ -943,6 +1026,34 @@ int16_t SX127x::configFSK() {
return(state); 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) { bool SX127x::findChip(uint8_t ver) {
uint8_t i = 0; uint8_t i = 0;
bool flagFound = false; bool flagFound = false;
@ -952,16 +1063,15 @@ bool SX127x::findChip(uint8_t ver) {
flagFound = true; flagFound = true;
} else { } else {
#ifdef RADIOLIB_DEBUG #ifdef RADIOLIB_DEBUG
Serial.print(F("SX127x not found! (")); RADIOLIB_DEBUG_PRINT(F("SX127x not found! ("));
Serial.print(i + 1); RADIOLIB_DEBUG_PRINT(i + 1);
Serial.print(F(" of 10 tries) SX127X_REG_VERSION == ")); RADIOLIB_DEBUG_PRINT(F(" of 10 tries) SX127X_REG_VERSION == "));
char buffHex[5]; char buffHex[5];
sprintf(buffHex, "0x%02X", version); sprintf(buffHex, "0x%02X", version);
Serial.print(buffHex); RADIOLIB_DEBUG_PRINT(buffHex);
Serial.print(F(", expected 0x00")); RADIOLIB_DEBUG_PRINT(F(", expected 0x00"));
Serial.print(ver, HEX); RADIOLIB_DEBUG_PRINTLN(ver, HEX);
Serial.println();
#endif #endif
delay(1000); delay(1000);
i++; i++;
@ -1010,23 +1120,23 @@ void SX127x::clearFIFO(size_t count) {
#ifdef RADIOLIB_DEBUG #ifdef RADIOLIB_DEBUG
void SX127x::regDump() { void SX127x::regDump() {
Serial.println(); RADIOLIB_DEBUG_PRINTLN();
Serial.println(F("ADDR\tVALUE")); RADIOLIB_DEBUG_PRINTLN(F("ADDR\tVALUE"));
for(uint16_t addr = 0x01; addr <= 0x70; addr++) { for(uint16_t addr = 0x01; addr <= 0x70; addr++) {
if(addr <= 0x0F) { if(addr <= 0x0F) {
Serial.print(F("0x0")); RADIOLIB_DEBUG_PRINT(F("0x0"));
} else { } else {
Serial.print(F("0x")); RADIOLIB_DEBUG_PRINT(F("0x"));
} }
Serial.print(addr, HEX); RADIOLIB_DEBUG_PRINT(addr, HEX);
Serial.print('\t'); RADIOLIB_DEBUG_PRINT('\t');
uint8_t val = _mod->SPIreadRegister(addr); uint8_t val = _mod->SPIreadRegister(addr);
if(val <= 0x0F) { if(val <= 0x0F) {
Serial.print(F("0x0")); RADIOLIB_DEBUG_PRINT(F("0x0"));
} else { } else {
Serial.print(F("0x")); RADIOLIB_DEBUG_PRINT(F("0x"));
} }
Serial.println(val, HEX); RADIOLIB_DEBUG_PRINTLN(val, HEX);
delay(50); delay(50);
} }

View file

@ -1,15 +1,16 @@
#ifndef _RADIOLIB_SX127X_H #ifndef _RADIOLIB_SX127X_H
#define _RADIOLIB_SX127X_H #define _RADIOLIB_SX127X_H
#include "TypeDef.h" #include "../../TypeDef.h"
#include "Module.h" #include "../../Module.h"
#include "../protocols/PhysicalLayer.h" #include "../../protocols/PhysicalLayer/PhysicalLayer.h"
// SX127x physical layer properties // SX127x physical layer properties
#define SX127X_CRYSTAL_FREQ 32.0 #define SX127X_CRYSTAL_FREQ 32.0
#define SX127X_DIV_EXPONENT 19 #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 // SX127x series common LoRa registers
#define SX127X_REG_FIFO 0x00 #define SX127X_REG_FIFO 0x00
@ -842,11 +843,52 @@ class SX127x: public PhysicalLayer {
*/ */
size_t getPacketLength(bool update = true); 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 #ifdef RADIOLIB_DEBUG
void regDump(); void regDump();
#endif #endif
#ifndef RADIOLIB_GODMODE
protected: protected:
#endif
Module* _mod; Module* _mod;
float _freq; float _freq;
@ -862,12 +904,15 @@ class SX127x: public PhysicalLayer {
int16_t configFSK(); int16_t configFSK();
int16_t getActiveModem(); int16_t getActiveModem();
int16_t directMode(); int16_t directMode();
int16_t setPacketMode(uint8_t mode, uint8_t len);
#ifndef RADIOLIB_GODMODE
private: private:
#endif
float _dataRate; float _dataRate;
size_t _packetLength; size_t _packetLength;
bool _packetLengthQueried; // FSK packet length is the first byte in FIFO, length can only be queried once 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); bool findChip(uint8_t ver);
int16_t setMode(uint8_t mode); int16_t setMode(uint8_t mode);

View file

@ -5,13 +5,12 @@ XBee::XBee(Module* mod) {
_frameID = 0x01; _frameID = 0x01;
_frameLength = 0; _frameLength = 0;
_frameHeaderProcessed = false; _frameHeaderProcessed = false;
_packetData = new char[0];
} }
int16_t XBee::begin(long speed) { int16_t XBee::begin(long speed) {
// set module properties // set module properties
_mod->baudrate = speed; _mod->baudrate = speed;
_mod->init(USE_UART, INT_1); _mod->init(RADIOLIB_USE_UART, RADIOLIB_INT_1);
// reset module // reset module
reset(); reset();
@ -30,11 +29,11 @@ int16_t XBee::begin(long speed) {
if(state == ERR_NONE) { if(state == ERR_NONE) {
flagFound = true; flagFound = true;
} else { } else {
DEBUG_PRINT(F("XBee not found! (")); RADIOLIB_DEBUG_PRINT(F("XBee not found! ("));
DEBUG_PRINT(i + 1); RADIOLIB_DEBUG_PRINT(i + 1);
DEBUG_PRINT(F(" of 10 tries) STATE == ")); RADIOLIB_DEBUG_PRINT(F(" of 10 tries) STATE == "));
DEBUG_PRINTLN(state); RADIOLIB_DEBUG_PRINTLN(state);
DEBUG_PRINTLN(F("Resetting ...")); RADIOLIB_DEBUG_PRINTLN(F("Resetting ..."));
reset(); reset();
delay(1000); delay(1000);
_mod->ATemptyBuffer(); _mod->ATemptyBuffer();
@ -43,10 +42,10 @@ int16_t XBee::begin(long speed) {
} }
if(!flagFound) { if(!flagFound) {
DEBUG_PRINTLN(F("No XBee found!")); RADIOLIB_DEBUG_PRINTLN(F("No XBee found!"));
return(ERR_CMD_MODE_FAILED); return(ERR_CMD_MODE_FAILED);
} else { } else {
DEBUG_PRINTLN(F("Found XBee!")); RADIOLIB_DEBUG_PRINTLN(F("Found XBee!"));
} }
return(ERR_NONE); return(ERR_NONE);
@ -69,7 +68,11 @@ int16_t XBee::transmit(uint8_t* dest, uint8_t* destNetwork, const char* payload,
// build the frame // build the frame
size_t payloadLen = strlen(payload); size_t payloadLen = strlen(payload);
size_t dataLen = 8 + 2 + 1 + 1 + payloadLen; size_t dataLen = 8 + 2 + 1 + 1 + payloadLen;
#ifdef RADIOLIB_STATIC_ONLY
uint8_t cmd[RADIOLIB_STATIC_ARRAY_SIZE];
#else
uint8_t* cmd = new uint8_t[dataLen]; uint8_t* cmd = new uint8_t[dataLen];
#endif
memcpy(cmd, dest, 8); memcpy(cmd, dest, 8);
memcpy(cmd + 8, destNetwork, 2); memcpy(cmd + 8, destNetwork, 2);
cmd[10] = radius; cmd[10] = radius;
@ -79,7 +82,9 @@ int16_t XBee::transmit(uint8_t* dest, uint8_t* destNetwork, const char* payload,
// send frame // send frame
uint8_t frameID = _frameID++; uint8_t frameID = _frameID++;
sendApiFrame(XBEE_API_FRAME_ZIGBEE_TRANSMIT_REQUEST, frameID, cmd, dataLen); sendApiFrame(XBEE_API_FRAME_ZIGBEE_TRANSMIT_REQUEST, frameID, cmd, dataLen);
#ifndef RADIOLIB_STATIC_ONLY
delete[] cmd; delete[] cmd;
#endif
// get response code // get response code
return(readApiFrame(frameID, 5)); return(readApiFrame(frameID, 5));
@ -114,20 +119,28 @@ size_t XBee::available() {
return(0); 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++) { for(size_t i = 0; i < _frameLength; i++) {
frame[i] = _mod->ModuleSerial->read(); frame[i] = _mod->ModuleSerial->read();
} }
// save packet source and data // save packet source and data
size_t payloadLength = _frameLength - 12; size_t payloadLength = _frameLength - 12;
#ifndef RADIOLIB_STATIC_ONLY
delete[] _packetData; delete[] _packetData;
_packetData = new char[payloadLength]; _packetData = new char[payloadLength];
#endif
memcpy(_packetData, frame + 12, payloadLength - 1); memcpy(_packetData, frame + 12, payloadLength - 1);
_packetData[payloadLength - 1] = '\0'; _packetData[payloadLength - 1] = '\0';
memcpy(_packetSource, frame + 1, 8); memcpy(_packetSource, frame + 1, 8);
#ifndef RADIOLIB_STATIC_ONLY
delete[] frame; delete[] frame;
#endif
_frameLength = 0; _frameLength = 0;
_frameHeaderProcessed = false; _frameHeaderProcessed = false;
@ -176,25 +189,25 @@ int16_t XBeeSerial::begin(long speed) {
// set module properties // set module properties
_mod->AtLineFeed = "\r"; _mod->AtLineFeed = "\r";
_mod->baudrate = speed; _mod->baudrate = speed;
_mod->init(USE_UART, INT_NONE); _mod->init(RADIOLIB_USE_UART, RADIOLIB_INT_NONE);
// empty UART buffer (garbage data) // empty UART buffer (garbage data)
_mod->ATemptyBuffer(); _mod->ATemptyBuffer();
// enter command mode // enter command mode
DEBUG_PRINTLN(F("Entering command mode ...")); RADIOLIB_DEBUG_PRINTLN(F("Entering command mode ..."));
if(!enterCmdMode()) { if(!enterCmdMode()) {
return(ERR_CMD_MODE_FAILED); return(ERR_CMD_MODE_FAILED);
} }
// test AT setup // test AT setup
DEBUG_PRINTLN(F("Sending test command ...")); RADIOLIB_DEBUG_PRINTLN(F("Sending test command ..."));
if(!_mod->ATsendCommand("AT")) { if(!_mod->ATsendCommand("AT")) {
return(ERR_AT_FAILED); return(ERR_AT_FAILED);
} }
// exit command mode // exit command mode
DEBUG_PRINTLN(F("Exiting command mode ...")); RADIOLIB_DEBUG_PRINTLN(F("Exiting command mode ..."));
if(!_mod->ATsendCommand("ATCN")) { if(!_mod->ATsendCommand("ATCN")) {
return(ERR_AT_FAILED); return(ERR_AT_FAILED);
} }
@ -212,35 +225,47 @@ void XBeeSerial::reset() {
int16_t XBeeSerial::setDestinationAddress(const char* destinationAddressHigh, const char* destinationAddressLow) { int16_t XBeeSerial::setDestinationAddress(const char* destinationAddressHigh, const char* destinationAddressLow) {
// enter command mode // enter command mode
DEBUG_PRINTLN(F("Entering command mode ...")); RADIOLIB_DEBUG_PRINTLN(F("Entering command mode ..."));
if(!enterCmdMode()) { if(!enterCmdMode()) {
return(ERR_CMD_MODE_FAILED); return(ERR_CMD_MODE_FAILED);
} }
// set higher address bytes // set higher address bytes
DEBUG_PRINTLN(F("Setting address (high) ...")); RADIOLIB_DEBUG_PRINTLN(F("Setting address (high) ..."));
#ifdef RADIOLIB_STATIC_ONLY
char addressHigh[13];
#else
char* addressHigh = new char[strlen(destinationAddressHigh) + 4]; char* addressHigh = new char[strlen(destinationAddressHigh) + 4];
#endif
strcpy(addressHigh, "ATDH"); strcpy(addressHigh, "ATDH");
strcat(addressHigh, destinationAddressHigh); strcat(addressHigh, destinationAddressHigh);
bool res = _mod->ATsendCommand(addressHigh); bool res = _mod->ATsendCommand(addressHigh);
#ifndef RADIOLIB_STATIC_ONLY
delete[] addressHigh; delete[] addressHigh;
#endif
if(!res) { if(!res) {
return(ERR_AT_FAILED); return(ERR_AT_FAILED);
} }
// set lower address bytes // set lower address bytes
DEBUG_PRINTLN(F("Setting address (low) ...")); RADIOLIB_DEBUG_PRINTLN(F("Setting address (low) ..."));
#ifdef RADIOLIB_STATIC_ONLY
char addressLow[13];
#else
char* addressLow = new char[strlen(destinationAddressLow) + 4]; char* addressLow = new char[strlen(destinationAddressLow) + 4];
#endif
strcpy(addressLow, "ATDL"); strcpy(addressLow, "ATDL");
strcat(addressLow, destinationAddressLow); strcat(addressLow, destinationAddressLow);
res = _mod->ATsendCommand(addressLow); res = _mod->ATsendCommand(addressLow);
#ifndef RADIOLIB_STATIC_ONLY
delete[] addressLow; delete[] addressLow;
#endif
if(!res) { if(!res) {
return(ERR_AT_FAILED); return(ERR_AT_FAILED);
} }
// exit command mode // exit command mode
DEBUG_PRINTLN(F("Exiting command mode ...")); RADIOLIB_DEBUG_PRINTLN(F("Exiting command mode ..."));
if(!_mod->ATsendCommand("ATCN")) { if(!_mod->ATsendCommand("ATCN")) {
return(ERR_AT_FAILED); return(ERR_AT_FAILED);
} }
@ -250,24 +275,30 @@ int16_t XBeeSerial::setDestinationAddress(const char* destinationAddressHigh, co
int16_t XBeeSerial::setPanId(const char* panId) { int16_t XBeeSerial::setPanId(const char* panId) {
// enter command mode // enter command mode
DEBUG_PRINTLN(F("Entering command mode ...")); RADIOLIB_DEBUG_PRINTLN(F("Entering command mode ..."));
if(!enterCmdMode()) { if(!enterCmdMode()) {
return(ERR_CMD_MODE_FAILED); return(ERR_CMD_MODE_FAILED);
} }
// set PAN ID // set PAN ID
DEBUG_PRINTLN(F("Setting PAN ID ...")); RADIOLIB_DEBUG_PRINTLN(F("Setting PAN ID ..."));
#ifdef RADIOLIB_STATIC_ONLY
char cmd[21];
#else
char* cmd = new char[strlen(panId) + 4]; char* cmd = new char[strlen(panId) + 4];
#endif
strcpy(cmd, "ATID"); strcpy(cmd, "ATID");
strcat(cmd, panId); strcat(cmd, panId);
bool res = _mod->ATsendCommand(cmd); bool res = _mod->ATsendCommand(cmd);
#ifndef RADIOLIB_STATIC_ONLY
delete[] cmd; delete[] cmd;
#endif
if(!res) { if(!res) {
return(ERR_AT_FAILED); return(ERR_AT_FAILED);
} }
// exit command mode // exit command mode
DEBUG_PRINTLN(F("Exiting command mode ...")); RADIOLIB_DEBUG_PRINTLN(F("Exiting command mode ..."));
if(!_mod->ATsendCommand("ATCN")) { if(!_mod->ATsendCommand("ATCN")) {
return(ERR_AT_FAILED); return(ERR_AT_FAILED);
} }
@ -288,9 +319,9 @@ bool XBeeSerial::enterCmdMode() {
if(_mod->ATgetResponse()) { if(_mod->ATgetResponse()) {
return(true); return(true);
} else { } else {
DEBUG_PRINT(F("Unable to enter command mode! (")); RADIOLIB_DEBUG_PRINT(F("Unable to enter command mode! ("));
DEBUG_PRINT(i + 1); RADIOLIB_DEBUG_PRINT(i + 1);
DEBUG_PRINTLN(F(" of 10 tries)")); RADIOLIB_DEBUG_PRINTLN(F(" of 10 tries)"));
reset(); reset();
@ -298,7 +329,7 @@ bool XBeeSerial::enterCmdMode() {
} }
} }
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); return(false);
} }
@ -333,7 +364,11 @@ 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) { void XBee::sendApiFrame(uint8_t type, uint8_t id, uint8_t* data, uint16_t length) {
// build the API frame // build the API frame
size_t frameLength = 1 + 2 + length + 1 + 2; size_t frameLength = 1 + 2 + length + 1 + 2;
#ifdef RADIOLIB_STATIC_ONLY
uint8_t frame[RADIOLIB_STATIC_ARRAY_SIZE];
#else
uint8_t* frame = new uint8_t[frameLength]; uint8_t* frame = new uint8_t[frameLength];
#endif
frame[0] = 0x7E; // start delimiter frame[0] = 0x7E; // start delimiter
frame[1] = ((length + 2) & 0xFF00) >> 8; // length MSB frame[1] = ((length + 2) & 0xFF00) >> 8; // length MSB
@ -355,7 +390,9 @@ void XBee::sendApiFrame(uint8_t type, uint8_t id, uint8_t* data, uint16_t length
} }
// deallocate memory // deallocate memory
#ifndef RADIOLIB_STATIC_ONLY
delete[] frame; delete[] frame;
#endif
} }
int16_t XBee::readApiFrame(uint8_t frameID, uint8_t codePos, uint16_t timeout) { int16_t XBee::readApiFrame(uint8_t frameID, uint8_t codePos, uint16_t timeout) {
@ -377,11 +414,15 @@ int16_t XBee::readApiFrame(uint8_t frameID, uint8_t codePos, uint16_t timeout) {
return(ERR_FRAME_MALFORMED); return(ERR_FRAME_MALFORMED);
} }
} }
DEBUG_PRINT(F("frame data field length: ")); RADIOLIB_DEBUG_PRINT(F("frame data field length: "));
DEBUG_PRINTLN(numBytes); RADIOLIB_DEBUG_PRINTLN(numBytes);
// read the response // read the response
#ifdef RADIOLIB_STATIC_ONLY
uint8_t resp[RADIOLIB_STATIC_ARRAY_SIZE];
#else
uint8_t* resp = new uint8_t[numBytes]; uint8_t* resp = new uint8_t[numBytes];
#endif
for(uint16_t i = 0; i < numBytes; i++) { for(uint16_t i = 0; i < numBytes; i++) {
resp[i] = _mod->ModuleSerial->read(); resp[i] = _mod->ModuleSerial->read();
} }
@ -389,28 +430,30 @@ int16_t XBee::readApiFrame(uint8_t frameID, uint8_t codePos, uint16_t timeout) {
// verify checksum // verify checksum
uint8_t checksum = 0; uint8_t checksum = 0;
for(uint16_t i = 0; i < numBytes; i++) { for(uint16_t i = 0; i < numBytes; i++) {
DEBUG_PRINT(resp[i], HEX); RADIOLIB_DEBUG_PRINT(resp[i], HEX);
DEBUG_PRINT('\t'); RADIOLIB_DEBUG_PRINT('\t');
checksum += resp[i]; checksum += resp[i];
} }
DEBUG_PRINTLN(); RADIOLIB_DEBUG_PRINTLN();
if(checksum != 0xFF) { if(checksum != 0xFF) {
DEBUG_PRINTLN(checksum, HEX); RADIOLIB_DEBUG_PRINTLN(checksum, HEX);
return(ERR_FRAME_INCORRECT_CHECKSUM); return(ERR_FRAME_INCORRECT_CHECKSUM);
} }
// check frame ID // check frame ID
if(resp[1] != frameID) { if(resp[1] != frameID) {
DEBUG_PRINT(F("received frame ID: ")); RADIOLIB_DEBUG_PRINT(F("received frame ID: "));
DEBUG_PRINTLN(resp[1]); RADIOLIB_DEBUG_PRINTLN(resp[1]);
DEBUG_PRINT(F("expected frame ID: ")); RADIOLIB_DEBUG_PRINT(F("expected frame ID: "));
DEBUG_PRINTLN(frameID); RADIOLIB_DEBUG_PRINTLN(frameID);
return(ERR_FRAME_UNEXPECTED_ID); return(ERR_FRAME_UNEXPECTED_ID);
} }
// codePos does not include start delimiter and frame ID // codePos does not include start delimiter and frame ID
uint8_t code = resp[codePos]; uint8_t code = resp[codePos];
#ifndef RADIOLIB_STATIC_ONLY
delete[] resp; delete[] resp;
#endif
return(code); return(code);
} }
@ -426,17 +469,17 @@ uint16_t XBee::getNumBytes(uint32_t timeout, size_t minBytes) {
// read response // read response
uint8_t resp[3]; uint8_t resp[3];
uint8_t i = 0; uint8_t i = 0;
DEBUG_PRINT(F("reading frame length: ")); RADIOLIB_DEBUG_PRINT(F("reading frame length: "));
while(_mod->ModuleSerial->available() > 0) { while(_mod->ModuleSerial->available() > 0) {
uint8_t b = _mod->ModuleSerial->read(); uint8_t b = _mod->ModuleSerial->read();
DEBUG_PRINT(b, HEX); RADIOLIB_DEBUG_PRINT(b, HEX);
DEBUG_PRINT('\t'); RADIOLIB_DEBUG_PRINT('\t');
resp[i++] = b; resp[i++] = b;
if(i == 3) { if(i == 3) {
break; break;
} }
} }
DEBUG_PRINTLN(); RADIOLIB_DEBUG_PRINTLN();
return((resp[1] << 8) | resp[2]); return((resp[1] << 8) | resp[2]);
} }

View file

@ -1,8 +1,8 @@
#ifndef _RADIOLIB_XBEE_H #ifndef _RADIOLIB_XBEE_H
#define _RADIOLIB_XBEE_H #define _RADIOLIB_XBEE_H
#include "ISerial.h" #include "../../ISerial.h"
#include "TypeDef.h" #include "../../TypeDef.h"
// API reserved characters // API reserved characters
#define XBEE_API_START 0x7E #define XBEE_API_START 0x7E
@ -81,7 +81,9 @@ class XBeeSerial: public ISerial {
*/ */
int16_t setPanId(const char* panID); int16_t setPanId(const char* panID);
#ifndef RADIOLIB_GODMODE
private: private:
#endif
bool enterCmdMode(); bool enterCmdMode();
}; };
@ -170,13 +172,19 @@ class XBee {
*/ */
int16_t setPanId(uint8_t* panID); int16_t setPanId(uint8_t* panID);
#ifndef RADIOLIB_GODMODE
private: private:
#endif
Module* _mod; Module* _mod;
uint8_t _frameID; uint8_t _frameID;
size_t _frameLength; size_t _frameLength;
bool _frameHeaderProcessed; 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]; uint8_t _packetSource[8];
int16_t confirmChanges(); int16_t confirmChanges();

View file

@ -8,7 +8,7 @@ int16_t nRF24::begin(int16_t freq, int16_t dataRate, int8_t power, uint8_t addrW
// set module properties // set module properties
_mod->SPIreadCommand = NRF24_CMD_READ; _mod->SPIreadCommand = NRF24_CMD_READ;
_mod->SPIwriteCommand = NRF24_CMD_WRITE; _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) // override pin mode on INT0 (connected to nRF24 CE pin)
pinMode(_mod->getInt0(), OUTPUT); 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 // check SPI connection
int16_t val = _mod->SPIgetRegValue(NRF24_REG_SETUP_AW); int16_t val = _mod->SPIgetRegValue(NRF24_REG_SETUP_AW);
if(!((val >= 1) && (val <= 3))) { if(!((val >= 1) && (val <= 3))) {
DEBUG_PRINTLN(F("No nRF24 found!")); RADIOLIB_DEBUG_PRINTLN(F("No nRF24 found!"));
_mod->term(); _mod->term();
return(ERR_CHIP_NOT_FOUND); return(ERR_CHIP_NOT_FOUND);
} }
@ -386,6 +386,7 @@ int16_t nRF24::setReceivePipe(uint8_t pipeNum, uint8_t* addr) {
case 0: case 0:
_mod->SPIwriteRegisterBurst(NRF24_REG_RX_ADDR_P0, addr, _addrWidth); _mod->SPIwriteRegisterBurst(NRF24_REG_RX_ADDR_P0, addr, _addrWidth);
state |= _mod->SPIsetRegValue(NRF24_REG_EN_RXADDR, NRF24_P0_ON, 0, 0); state |= _mod->SPIsetRegValue(NRF24_REG_EN_RXADDR, NRF24_P0_ON, 0, 0);
break;
case 1: case 1:
_mod->SPIwriteRegisterBurst(NRF24_REG_RX_ADDR_P1, addr, _addrWidth); _mod->SPIwriteRegisterBurst(NRF24_REG_RX_ADDR_P1, addr, _addrWidth);
state |= _mod->SPIsetRegValue(NRF24_REG_EN_RXADDR, NRF24_P1_ON, 1, 1); state |= _mod->SPIsetRegValue(NRF24_REG_EN_RXADDR, NRF24_P1_ON, 1, 1);

View file

@ -1,10 +1,10 @@
#ifndef _RADIOLIB_NRF24_H #ifndef _RADIOLIB_NRF24_H
#define _RADIOLIB_NRF24_H #define _RADIOLIB_NRF24_H
#include "Module.h" #include "../../Module.h"
#include "TypeDef.h" #include "../../TypeDef.h"
#include "../protocols/PhysicalLayer.h" #include "../../protocols/PhysicalLayer/PhysicalLayer.h"
// nRF24 physical layer properties (dummy only) // nRF24 physical layer properties (dummy only)
#define NRF24_CRYSTAL_FREQ 1.0 #define NRF24_CRYSTAL_FREQ 1.0
@ -408,7 +408,9 @@ class nRF24: public PhysicalLayer {
*/ */
size_t getPacketLength(bool update = true); size_t getPacketLength(bool update = true);
#ifndef RADIOLIB_GODMODE
private: private:
#endif
Module* _mod; Module* _mod;
uint8_t _addrWidth; uint8_t _addrWidth;

View file

@ -1,8 +1,8 @@
#ifndef _RADIOLIB_HTTP_H #ifndef _RADIOLIB_HTTP_H
#define _RADIOLIB_HTTP_H #define _RADIOLIB_HTTP_H
#include "TypeDef.h" #include "../../TypeDef.h"
#include "TransportLayer.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"); int16_t post(const char* url, const char* content, String& response, const char* contentType = "text/plain");
#ifndef RADIOLIB_GODMODE
private: private:
#endif
TransportLayer* _tl; TransportLayer* _tl;
uint16_t _port; uint16_t _port;

View file

@ -27,7 +27,11 @@ int16_t MQTTClient::connect(const char* host, const char* clientId, const char*
size_t encodedBytes = encodeLength(remainingLength, encoded); size_t encodedBytes = encodeLength(remainingLength, encoded);
// build the CONNECT packet // build the CONNECT packet
#ifdef RADIOLIB_STATIC_ONLY
uint8_t packet[256];
#else
uint8_t* packet = new uint8_t[1 + encodedBytes + remainingLength]; uint8_t* packet = new uint8_t[1 + encodedBytes + remainingLength];
#endif
// fixed header // fixed header
packet[0] = (MQTT_CONNECT << 4) | 0b0000; packet[0] = (MQTT_CONNECT << 4) | 0b0000;
@ -97,13 +101,17 @@ int16_t MQTTClient::connect(const char* host, const char* clientId, const char*
// create TCP connection // create TCP connection
int16_t state = _tl->openTransportConnection(host, "TCP", _port, keepAlive); int16_t state = _tl->openTransportConnection(host, "TCP", _port, keepAlive);
if(state != ERR_NONE) { if(state != ERR_NONE) {
#ifndef RADIOLIB_STATIC_ONLY
delete[] packet; delete[] packet;
#endif
return(state); return(state);
} }
// send MQTT packet // send MQTT packet
state = _tl->send(packet, 1 + encodedBytes + remainingLength); state = _tl->send(packet, 1 + encodedBytes + remainingLength);
#ifndef RADIOLIB_STATIC_ONLY
delete[] packet; delete[] packet;
#endif
if(state != ERR_NONE) { if(state != ERR_NONE) {
return(state); return(state);
} }
@ -115,15 +123,23 @@ int16_t MQTTClient::connect(const char* host, const char* clientId, const char*
} }
// read the response // read the response
#ifdef RADIOLIB_STATIC_ONLY
uint8_t response[RADIOLIB_STATIC_ARRAY_SIZE];
#else
uint8_t* response = new uint8_t[numBytes]; uint8_t* response = new uint8_t[numBytes];
#endif
_tl->receive(response, numBytes); _tl->receive(response, numBytes);
if((response[0] == MQTT_CONNACK << 4) && (response[1] == 2)) { if((response[0] == MQTT_CONNACK << 4) && (response[1] == 2)) {
uint8_t returnCode = response[3]; uint8_t returnCode = response[3];
#ifndef RADIOLIB_STATIC_ONLY
delete[] response; delete[] response;
#endif
return(returnCode); return(returnCode);
} }
#ifndef RADIOLIB_STATIC_ONLY
delete[] response; delete[] response;
#endif
return(ERR_RESPONSE_MALFORMED); return(ERR_RESPONSE_MALFORMED);
} }
@ -158,7 +174,11 @@ int16_t MQTTClient::publish(const char* topic, const char* message) {
size_t encodedBytes = encodeLength(remainingLength, encoded); size_t encodedBytes = encodeLength(remainingLength, encoded);
// build the PUBLISH packet // build the PUBLISH packet
#ifdef RADIOLIB_STATIC_ONLY
uint8_t packet[RADIOLIB_STATIC_ARRAY_SIZE];
#else
uint8_t* packet = new uint8_t[1 + encodedBytes + remainingLength]; uint8_t* packet = new uint8_t[1 + encodedBytes + remainingLength];
#endif
// fixed header // fixed header
packet[0] = (MQTT_PUBLISH << 4) | 0b0000; packet[0] = (MQTT_PUBLISH << 4) | 0b0000;
@ -181,7 +201,9 @@ int16_t MQTTClient::publish(const char* topic, const char* message) {
// send MQTT packet // send MQTT packet
int16_t state = _tl->send(packet, 1 + encodedBytes + remainingLength); int16_t state = _tl->send(packet, 1 + encodedBytes + remainingLength);
#ifndef RADIOLIB_STATIC_ONLY
delete[] packet; delete[] packet;
#endif
return(state); return(state);
//TODO: implement QoS > 0 and PUBACK response checking //TODO: implement QoS > 0 and PUBACK response checking
@ -195,7 +217,11 @@ int16_t MQTTClient::subscribe(const char* topicFilter) {
size_t encodedBytes = encodeLength(remainingLength, encoded); size_t encodedBytes = encodeLength(remainingLength, encoded);
// build the SUBSCRIBE packet // build the SUBSCRIBE packet
#ifdef RADIOLIB_STATIC_ONLY
uint8_t packet[RADIOLIB_STATIC_ARRAY_SIZE];
#else
uint8_t* packet = new uint8_t[1 + encodedBytes + remainingLength]; uint8_t* packet = new uint8_t[1 + encodedBytes + remainingLength];
#endif
// fixed header // fixed header
packet[0] = (MQTT_SUBSCRIBE << 4) | 0b0010; packet[0] = (MQTT_SUBSCRIBE << 4) | 0b0010;
@ -218,7 +244,9 @@ int16_t MQTTClient::subscribe(const char* topicFilter) {
// send MQTT packet // send MQTT packet
int16_t state = _tl->send(packet, 1 + encodedBytes + remainingLength); int16_t state = _tl->send(packet, 1 + encodedBytes + remainingLength);
#ifndef RADIOLIB_STATIC_ONLY
delete[] packet; delete[] packet;
#endif
if(state != ERR_NONE) { if(state != ERR_NONE) {
return(state); return(state);
} }
@ -230,20 +258,28 @@ int16_t MQTTClient::subscribe(const char* topicFilter) {
} }
// read the response // read the response
#ifdef RADIOLIB_STATIC_ONLY
uint8_t response[RADIOLIB_STATIC_ARRAY_SIZE];
#else
uint8_t* response = new uint8_t[numBytes]; uint8_t* response = new uint8_t[numBytes];
#endif
_tl->receive(response, numBytes); _tl->receive(response, numBytes);
if((response[0] == MQTT_SUBACK << 4) && (response[1] == 3)) { if((response[0] == MQTT_SUBACK << 4) && (response[1] == 3)) {
// check packet ID // check packet ID
uint16_t receivedId = response[3] | response[2] << 8; uint16_t receivedId = response[3] | response[2] << 8;
int16_t returnCode = response[4]; int16_t returnCode = response[4];
#ifndef RADIOLIB_STATIC_ONLY
delete[] response; delete[] response;
#endif
if(receivedId != packetId) { if(receivedId != packetId) {
return(ERR_MQTT_UNEXPECTED_PACKET_ID); return(ERR_MQTT_UNEXPECTED_PACKET_ID);
} }
return(returnCode); return(returnCode);
} }
#ifndef RADIOLIB_STATIC_ONLY
delete[] response; delete[] response;
#endif
return(ERR_RESPONSE_MALFORMED); return(ERR_RESPONSE_MALFORMED);
} }
@ -255,7 +291,11 @@ int16_t MQTTClient::unsubscribe(const char* topicFilter) {
size_t encodedBytes = encodeLength(remainingLength, encoded); size_t encodedBytes = encodeLength(remainingLength, encoded);
// build the UNSUBSCRIBE packet // build the UNSUBSCRIBE packet
#ifdef RADIOLIB_STATIC_ONLY
uint8_t packet[RADIOLIB_STATIC_ARRAY_SIZE];
#else
uint8_t* packet = new uint8_t[1 + encodedBytes + remainingLength]; uint8_t* packet = new uint8_t[1 + encodedBytes + remainingLength];
#endif
// fixed header // fixed header
packet[0] = (MQTT_UNSUBSCRIBE << 4) | 0b0010; packet[0] = (MQTT_UNSUBSCRIBE << 4) | 0b0010;
@ -277,7 +317,9 @@ int16_t MQTTClient::unsubscribe(const char* topicFilter) {
// send MQTT packet // send MQTT packet
int16_t state = _tl->send(packet, 1 + encodedBytes + remainingLength); int16_t state = _tl->send(packet, 1 + encodedBytes + remainingLength);
#ifndef RADIOLIB_STATIC_ONLY
delete[] packet; delete[] packet;
#endif
if(state != ERR_NONE) { if(state != ERR_NONE) {
return(state); return(state);
} }
@ -289,19 +331,27 @@ int16_t MQTTClient::unsubscribe(const char* topicFilter) {
} }
// read the response // read the response
#ifdef RADIOLIB_STATIC_ONLY
uint8_t response[RADIOLIB_STATIC_ARRAY_SIZE];
#else
uint8_t* response = new uint8_t[numBytes]; uint8_t* response = new uint8_t[numBytes];
#endif
_tl->receive(response, numBytes); _tl->receive(response, numBytes);
if((response[0] == MQTT_UNSUBACK << 4) && (response[1] == 2)) { if((response[0] == MQTT_UNSUBACK << 4) && (response[1] == 2)) {
// check packet ID // check packet ID
uint16_t receivedId = response[3] | response[2] << 8; uint16_t receivedId = response[3] | response[2] << 8;
#ifndef RADIOLIB_STATIC_ONLY
delete[] response; delete[] response;
#endif
if(receivedId != packetId) { if(receivedId != packetId) {
return(ERR_MQTT_UNEXPECTED_PACKET_ID); return(ERR_MQTT_UNEXPECTED_PACKET_ID);
} }
return(ERR_NONE); return(ERR_NONE);
} }
#ifndef RADIOLIB_STATIC_ONLY
delete[] response; delete[] response;
#endif
return(ERR_RESPONSE_MALFORMED); return(ERR_RESPONSE_MALFORMED);
} }
@ -326,14 +376,22 @@ int16_t MQTTClient::ping() {
} }
// read the response // read the response
#ifdef RADIOLIB_STATIC_ONLY
uint8_t response[RADIOLIB_STATIC_ARRAY_SIZE];
#else
uint8_t* response = new uint8_t[numBytes]; uint8_t* response = new uint8_t[numBytes];
#endif
_tl->receive(response, numBytes); _tl->receive(response, numBytes);
if((response[0] == MQTT_PINGRESP << 4) && (response[1] == 0)) { if((response[0] == MQTT_PINGRESP << 4) && (response[1] == 0)) {
#ifndef RADIOLIB_STATIC_ONLY
delete[] response; delete[] response;
#endif
return(ERR_NONE); return(ERR_NONE);
} }
#ifndef RADIOLIB_STATIC_ONLY
delete[] response; delete[] response;
#endif
return(ERR_RESPONSE_MALFORMED); return(ERR_RESPONSE_MALFORMED);
} }

View file

@ -1,8 +1,8 @@
#ifndef _RADIOLIB_MQTT_H #ifndef _RADIOLIB_MQTT_H
#define _RADIOLIB_MQTT_H #define _RADIOLIB_MQTT_H
#include "TypeDef.h" #include "../../TypeDef.h"
#include "TransportLayer.h" #include "../TransportLayer/TransportLayer.h"
// MQTT packet types // MQTT packet types
#define MQTT_CONNECT 0x01 #define MQTT_CONNECT 0x01
@ -127,7 +127,9 @@ class MQTTClient {
*/ */
int16_t check(void (*func)(const char*, const char*)); int16_t check(void (*func)(const char*, const char*));
#ifndef RADIOLIB_GODMODE
private: private:
#endif
TransportLayer* _tl; TransportLayer* _tl;
uint16_t _port; uint16_t _port;

View file

@ -119,9 +119,9 @@ size_t MorseClient::write(uint8_t b) {
// check if the requested code was found in the array // check if the requested code was found in the array
if(found) { if(found) {
DEBUG_PRINT(mc.c); RADIOLIB_DEBUG_PRINT(mc.c);
DEBUG_PRINT('\t'); RADIOLIB_DEBUG_PRINT('\t');
DEBUG_PRINTLN(mc.m); RADIOLIB_DEBUG_PRINTLN(mc.m);
// iterate over Morse code representation and output appropriate tones // iterate over Morse code representation and output appropriate tones
for(uint8_t i = 0; i < strlen(mc.m); i++) { for(uint8_t i = 0; i < strlen(mc.m); i++) {
@ -145,7 +145,7 @@ size_t MorseClient::write(uint8_t b) {
} }
// letter space // letter space
DEBUG_PRINTLN(); RADIOLIB_DEBUG_PRINTLN();
delay(_dotLength * 3); delay(_dotLength * 3);
return(1); return(1);

View file

@ -1,8 +1,8 @@
#ifndef _RADIOLIB_MORSE_H #ifndef _RADIOLIB_MORSE_H
#define _RADIOLIB_MORSE_H #define _RADIOLIB_MORSE_H
#include "TypeDef.h" #include "../../TypeDef.h"
#include "PhysicalLayer.h" #include "../PhysicalLayer/PhysicalLayer.h"
#define MORSE_LENGTH 52 #define MORSE_LENGTH 52
@ -67,7 +67,9 @@ class MorseClient {
size_t println(unsigned long, int = DEC); size_t println(unsigned long, int = DEC);
size_t println(double, int = 2); size_t println(double, int = 2);
#ifndef RADIOLIB_GODMODE
private: private:
#endif
PhysicalLayer* _phy; PhysicalLayer* _phy;
uint32_t _base; uint32_t _base;
uint16_t _dotLength; uint16_t _dotLength;

View file

@ -19,7 +19,11 @@ int16_t PhysicalLayer::transmit(__FlashStringHelper* fstr, uint8_t addr) {
} }
// dynamically allocate memory // dynamically allocate memory
#ifdef RADIOLIB_STATIC_ONLY
char str[RADIOLIB_STATIC_ARRAY_SIZE];
#else
char* str = new char[len]; char* str = new char[len];
#endif
// copy string from flash // copy string from flash
p = reinterpret_cast<PGM_P>(fstr); p = reinterpret_cast<PGM_P>(fstr);
@ -29,7 +33,9 @@ int16_t PhysicalLayer::transmit(__FlashStringHelper* fstr, uint8_t addr) {
// transmit string // transmit string
int16_t state = transmit(str, addr); int16_t state = transmit(str, addr);
#ifndef RADIOLIB_STATIC_ONLY
delete[] str; delete[] str;
#endif
return(state); return(state);
} }
@ -62,10 +68,14 @@ int16_t PhysicalLayer::readData(String& str, size_t len) {
} }
// build a temporary buffer // build a temporary buffer
#ifdef RADIOLIB_STATIC_ONLY
uint8_t data[RADIOLIB_STATIC_ARRAY_SIZE + 1];
#else
uint8_t* data = new uint8_t[length + 1]; uint8_t* data = new uint8_t[length + 1];
if(!data) { if(!data) {
return(ERR_MEMORY_ALLOCATION_FAILED); return(ERR_MEMORY_ALLOCATION_FAILED);
} }
#endif
// read the received data // read the received data
state = readData(data, length); state = readData(data, length);
@ -79,7 +89,9 @@ int16_t PhysicalLayer::readData(String& str, size_t len) {
} }
// deallocate temporary buffer // deallocate temporary buffer
#ifndef RADIOLIB_STATIC_ONLY
delete[] data; delete[] data;
#endif
return(state); return(state);
} }
@ -96,10 +108,14 @@ int16_t PhysicalLayer::receive(String& str, size_t len) {
} }
// build a temporary buffer // build a temporary buffer
#ifdef RADIOLIB_STATIC_ONLY
uint8_t data[RADIOLIB_STATIC_ARRAY_SIZE + 1];
#else
uint8_t* data = new uint8_t[length + 1]; uint8_t* data = new uint8_t[length + 1];
if(!data) { if(!data) {
return(ERR_MEMORY_ALLOCATION_FAILED); return(ERR_MEMORY_ALLOCATION_FAILED);
} }
#endif
// attempt packet reception // attempt packet reception
state = receive(data, length); state = receive(data, length);
@ -118,7 +134,9 @@ int16_t PhysicalLayer::receive(String& str, size_t len) {
} }
// deallocate temporary buffer // deallocate temporary buffer
#ifndef RADIOLIB_STATIC_ONLY
delete[] data; delete[] data;
#endif
return(state); return(state);
} }

View file

@ -1,7 +1,7 @@
#ifndef _RADIOLIB_PHYSICAL_LAYER_H #ifndef _RADIOLIB_PHYSICAL_LAYER_H
#define _RADIOLIB_PHYSICAL_LAYER_H #define _RADIOLIB_PHYSICAL_LAYER_H
#include "TypeDef.h" #include "../../TypeDef.h"
/*! /*!
\class PhysicalLayer \class PhysicalLayer
@ -215,7 +215,9 @@ class PhysicalLayer {
*/ */
virtual size_t getPacketLength(bool update = true) = 0; virtual size_t getPacketLength(bool update = true) = 0;
#ifndef RADIOLIB_GODMODE
private: private:
#endif
float _crystalFreq; float _crystalFreq;
uint8_t _divExponent; uint8_t _divExponent;
size_t _maxPacketLength; size_t _maxPacketLength;

View file

@ -2,20 +2,20 @@
ITA2String::ITA2String(char c) { ITA2String::ITA2String(char c) {
_len = 1; _len = 1;
_str = new char[1];
_str[0] = c; _str[0] = c;
_ita2Len = 0; _ita2Len = 0;
} }
ITA2String::ITA2String(const char* str) { ITA2String::ITA2String(const char* str) {
_len = strlen(str); _len = strlen(str);
_str = new char[_len];
strcpy(_str, str); strcpy(_str, str);
_ita2Len = 0; _ita2Len = 0;
} }
ITA2String::~ITA2String() { ITA2String::~ITA2String() {
#ifndef RADIOLIB_STATIC_ONLY
delete[] _str; delete[] _str;
#endif
} }
size_t ITA2String::length() { size_t ITA2String::length() {
@ -32,7 +32,11 @@ size_t ITA2String::length() {
uint8_t* ITA2String::byteArr() { uint8_t* ITA2String::byteArr() {
// create temporary array 2x the string length (figures may be 3 bytes) // create temporary array 2x the string length (figures may be 3 bytes)
#ifdef RADIOLIB_STATIC_ONLY
uint8_t temp[RADIOLIB_STATIC_ARRAY_SIZE*2 + 1];
#else
uint8_t* temp = new uint8_t[_len*2 + 1]; uint8_t* temp = new uint8_t[_len*2 + 1];
#endif
size_t arrayLen = 0; size_t arrayLen = 0;
bool flagFigure = false; bool flagFigure = false;
@ -75,7 +79,9 @@ uint8_t* ITA2String::byteArr() {
uint8_t* arr = new uint8_t[arrayLen]; uint8_t* arr = new uint8_t[arrayLen];
memcpy(arr, temp, arrayLen); memcpy(arr, temp, arrayLen);
#ifndef RADIOLIB_STATIC_ONLY
delete[] temp; delete[] temp;
#endif
return(arr); return(arr);
} }
@ -202,7 +208,11 @@ size_t RTTYClient::print(__FlashStringHelper* fstr) {
} }
// dynamically allocate memory // dynamically allocate memory
#ifdef RADIOLIB_STATIC_ONLY
char str[RADIOLIB_STATIC_ARRAY_SIZE];
#else
char* str = new char[len]; char* str = new char[len];
#endif
// copy string from flash // copy string from flash
p = reinterpret_cast<PGM_P>(fstr); p = reinterpret_cast<PGM_P>(fstr);
@ -217,7 +227,9 @@ size_t RTTYClient::print(__FlashStringHelper* fstr) {
} else if((_encoding == ASCII) || (_encoding == ASCII_EXTENDED)) { } else if((_encoding == ASCII) || (_encoding == ASCII_EXTENDED)) {
n = RTTYClient::write((uint8_t*)str, len); n = RTTYClient::write((uint8_t*)str, len);
} }
#ifndef RADIOLIB_STATIC_ONLY
delete[] str; delete[] str;
#endif
return(n); return(n);
} }

View file

@ -1,8 +1,8 @@
#ifndef _RADIOLIB_RTTY_H #ifndef _RADIOLIB_RTTY_H
#define _RADIOLIB_RTTY_H #define _RADIOLIB_RTTY_H
#include "TypeDef.h" #include "../../TypeDef.h"
#include "PhysicalLayer.h" #include "../PhysicalLayer/PhysicalLayer.h"
#define ITA2_FIGS 0x1B #define ITA2_FIGS 0x1B
#define ITA2_LTRS 0x1F #define ITA2_LTRS 0x1F
@ -57,8 +57,14 @@ class ITA2String {
*/ */
uint8_t* byteArr(); uint8_t* byteArr();
#ifndef RADIOLIB_GODMODE
private: 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 _len;
size_t _ita2Len; size_t _ita2Len;
@ -137,13 +143,15 @@ class RTTYClient {
size_t println(unsigned long, int = DEC); size_t println(unsigned long, int = DEC);
size_t println(double, int = 2); size_t println(double, int = 2);
#ifndef RADIOLIB_GODMODE
private: private:
#endif
PhysicalLayer* _phy; PhysicalLayer* _phy;
uint8_t _encoding; uint8_t _encoding;
uint32_t _base; uint32_t _base;
uint32_t _shift; uint32_t _shift;
uint16_t _bitDuration; uint32_t _bitDuration;
uint8_t _dataBits; uint8_t _dataBits;
uint8_t _stopBits; uint8_t _stopBits;

View file

@ -1,7 +1,7 @@
#ifndef _RADIOLIB_TRANSPORT_LAYER_H #ifndef _RADIOLIB_TRANSPORT_LAYER_H
#define _RADIOLIB_TRANSPORT_LAYER_H #define _RADIOLIB_TRANSPORT_LAYER_H
#include "TypeDef.h" #include "../../TypeDef.h"
/*! /*!
\class TransportLayer \class TransportLayer