Porównaj commity

...

3 Commity

Autor SHA1 Wiadomość Data
Jan Gromeš cfc425970c
[LoRaWAN] Resolve warnings, fix bugs for fixed bands (#1021)
* [LoRaWAN] Resolve warnings

* [LoRaWAN] Fixed bands: improve initial datarate, fix CFList bug

* [LoRaWAN] Improve MAC debug output formatting

* Fix hexdump debug level

* Remove unnecessary error, add new ones to keywords

* [LoRaWAN] Discard useless check

---------

Co-authored-by: StevenCellist <steven@boonstoppel.nu>
2024-03-18 16:39:55 +01:00
jgromes 44f6c1d432 [CI] Enable LoRaWAN builds for previously disabled platforms 2024-03-18 09:37:16 +01:00
StevenCellist ca2a3073b9
[LoRaWAN] Change and upgrade persistence handling (#1017)
* [LoRaWAN] Change and upgrade persistence handling

* [BuildOpt] Patch to upstream

* [LoRaWAN] Fix #1018

* [LoRaWAN] Remove outdated parts

* [LoRaWAN] Resolve feedback

Warning: untested - am not at my desk

* [LoRaWAN] Small bugfixes
2024-03-18 08:51:38 +01:00
13 zmienionych plików z 626 dodań i 958 usunięć

Wyświetl plik

@ -50,22 +50,17 @@ jobs:
- id: arduino:avr:mega
run: echo "options=':cpu=atmega2560'" >> $GITHUB_OUTPUT
- id: arduino:mbed:nano33ble
run: echo "skip-pattern=(STM32WL|LoRaWAN_End_Device_Persistent)" >> $GITHUB_OUTPUT
- id: arduino:mbed:envie_m4
run: echo "skip-pattern=(STM32WL|LoRaWAN_End_Device_Persistent)" >> $GITHUB_OUTPUT
- id: arduino:megaavr:uno2018
run: |
echo "options=':mode=on'" >> $GITHUB_OUTPUT
echo "skip-pattern=(STM32WL|LoRaWAN)" >> $GITHUB_OUTPUT
- id: arduino:sam:arduino_due_x
run: echo "skip-pattern=(STM32WL|LoRaWAN_End_Device_Persistent)" >> $GITHUB_OUTPUT
- id: arduino:samd:arduino_zero_native
run: echo "skip-pattern=(STM32WL|LoRaWAN_End_Device_Persistent)" >> $GITHUB_OUTPUT
- id: adafruit:samd:adafruit_feather_m0
run: |
echo "options=':usbstack=arduino,debug=off'" >> $GITHUB_OUTPUT
echo "index-url=--additional-urls https://adafruit.github.io/arduino-board-index/package_adafruit_index.json" >> $GITHUB_OUTPUT
echo "skip-pattern=(STM32WL|LoRaWAN_End_Device_Persistent)" >> $GITHUB_OUTPUT
- id: adafruit:nrf52:feather52832
run: |
sudo apt-get update
@ -75,7 +70,6 @@ jobs:
echo "/home/runner/.local/bin" >> $GITHUB_PATH
echo "options=':softdevice=s132v6,debug=l0'" >> $GITHUB_OUTPUT
echo "index-url=--additional-urls https://adafruit.github.io/arduino-board-index/package_adafruit_index.json" >> $GITHUB_OUTPUT
echo "skip-pattern=(STM32WL|LoRaWAN_End_Device_Persistent)" >> $GITHUB_OUTPUT
- id: esp32:esp32:esp32
run: |
python -m pip install pyserial
@ -102,10 +96,8 @@ jobs:
echo "index-url=--additional-urls http://dan.drown.org/stm32duino/package_STM32duino_index.json" >> $GITHUB_OUTPUT
- id: MegaCoreX:megaavr:4809
run: |
echo "skip-pattern=(STM32WL|LoRaWAN)" >> $GITHUB_OUTPUT
echo "index-url=--additional-urls https://mcudude.github.io/MegaCoreX/package_MCUdude_MegaCoreX_index.json" >> $GITHUB_OUTPUT
- id: arduino:mbed_rp2040:pico
run: echo "skip-pattern=(STM32WL|LoRaWAN_End_Device_Persistent)" >> $GITHUB_OUTPUT
- id: rp2040:rp2040:rpipico
run: echo "index-url=--additional-urls https://github.com/earlephilhower/arduino-pico/releases/download/global/package_rp2040_index.json" >> $GITHUB_OUTPUT
- id: CubeCell:CubeCell:CubeCell-Board

Wyświetl plik

@ -293,6 +293,10 @@ setModem KEYWORD2
# LoRaWAN
wipe KEYWORD2
getBufferNonces KEYWORD2
setBufferNonces KEYWORD2
getBufferSession KEYWORD2
setBufferSession KEYWORD2
restore KEYWORD2
beginOTAA KEYWORD2
beginABP KEYWORD2
@ -426,9 +430,10 @@ RADIOLIB_ERR_INVALID_CHANNEL LITERAL1
RADIOLIB_ERR_INVALID_CID LITERAL1
RADIOLIB_ERR_UPLINK_UNAVAILABLE LITERAL1
RADIOLIB_ERR_COMMAND_QUEUE_FULL LITERAL1
RADIOLIB_ERR_COMMAND_QUEUE_EMPTY LITERAL1
RADIOLIB_ERR_COMMAND_QUEUE_ITEM_NOT_FOUND LITERAL1
RADIOLIB_ERR_JOIN_NONCE_INVALID LITERAL1
RADIOLIB_ERR_N_FCNT_DOWN_INVALID LITERAL1
RADIOLIB_ERR_A_FCNT_DOWN_INVALID LITERAL1
RADIOLIB_ERR_DATA_RATE_INVALID LITERAL1
RADIOLIB_ERR_DATA_RATE_INVALID LITERAL1
RADIOLIB_ERR_DWELL_TIME_EXCEEDED LITERAL1
RADIOLIB_ERR_CHECKSUM_MISMATCH LITERAL1

Wyświetl plik

@ -2,10 +2,6 @@
#if defined(RADIOLIB_BUILD_ARDUINO)
#if !defined(RADIOLIB_EEPROM_UNSUPPORTED)
#include <EEPROM.h>
#endif
ArduinoHal::ArduinoHal(): RadioLibHal(INPUT, OUTPUT, LOW, HIGH, RISING, FALLING), spi(&RADIOLIB_DEFAULT_SPI), initInterface(true) {}
ArduinoHal::ArduinoHal(SPIClass& spi, SPISettings spiSettings): RadioLibHal(INPUT, OUTPUT, LOW, HIGH, RISING, FALLING), spi(&spi), spiSettings(spiSettings) {}
@ -118,49 +114,6 @@ void inline ArduinoHal::spiEnd() {
spi->end();
}
void ArduinoHal::readPersistentStorage(uint32_t addr, uint8_t* buff, size_t len) {
#if !defined(RADIOLIB_EEPROM_UNSUPPORTED)
#if defined(RADIOLIB_ESP32) || defined(ARDUINO_ARCH_RP2040)
EEPROM.begin(RADIOLIB_HAL_PERSISTENT_STORAGE_SIZE);
#elif defined(ARDUINO_ARCH_APOLLO3)
EEPROM.init();
#endif
for(size_t i = 0; i < len; i++) {
buff[i] = EEPROM.read(addr + i);
}
#if defined(RADIOLIB_ESP32) || defined(ARDUINO_ARCH_RP2040)
EEPROM.end();
#endif
#else
(void)addr;
(void)buff;
(void)len;
#endif
}
void ArduinoHal::writePersistentStorage(uint32_t addr, uint8_t* buff, size_t len) {
#if !defined(RADIOLIB_EEPROM_UNSUPPORTED)
#if defined(RADIOLIB_ESP32) || defined(ARDUINO_ARCH_RP2040)
EEPROM.begin(RADIOLIB_HAL_PERSISTENT_STORAGE_SIZE);
#elif defined(ARDUINO_ARCH_APOLLO3)
EEPROM.init();
#endif
for(size_t i = 0; i < len; i++) {
if(EEPROM.read(addr + i) != buff[i]) { // only write if value is new
EEPROM.write(addr + i, buff[i]);
}
}
#if defined(RADIOLIB_ESP32) || defined(ARDUINO_ARCH_RP2040)
EEPROM.commit();
EEPROM.end();
#endif
#else
(void)addr;
(void)buff;
(void)len;
#endif
}
void inline ArduinoHal::tone(uint32_t pin, unsigned int frequency, unsigned long duration) {
#if !defined(RADIOLIB_TONE_UNSUPPORTED)
if(pin == RADIOLIB_NC) {

Wyświetl plik

@ -51,9 +51,6 @@ class ArduinoHal : public RadioLibHal {
void spiEndTransaction() override;
void spiEnd() override;
void readPersistentStorage(uint32_t addr, uint8_t* buff, size_t len) override;
void writePersistentStorage(uint32_t addr, uint8_t* buff, size_t len) override;
// implementations of virtual RadioLibHal methods
void init() override;
void term() override;

Wyświetl plik

@ -104,21 +104,6 @@
#define RADIOLIB_STATIC_ARRAY_SIZE (256)
#endif
// the base address for persistent storage
// some protocols (e.g. LoRaWAN) require a method
// to store some data persistently
// on Arduino, this will use EEPROM, on non-Arduino platform,
// it will use anything provided by the hardware abstraction layer
// RadioLib will place these starting at this address
#if !defined(RADIOLIB_HAL_PERSISTENT_STORAGE_BASE)
#define RADIOLIB_HAL_PERSISTENT_STORAGE_BASE (0)
#endif
// the amount of space allocated to the persistent storage
#if !defined(RADIOLIB_HAL_PERSISTENT_STORAGE_SIZE)
#define RADIOLIB_HAL_PERSISTENT_STORAGE_SIZE (0x01C0)
#endif
/*
* Uncomment on boards whose clock runs too slow or too fast
* Set the value according to the following scheme:
@ -238,7 +223,6 @@
#elif defined(SAMD_SERIES)
// Adafruit SAMD boards (M0 and M4)
#define RADIOLIB_PLATFORM "Adafruit SAMD"
#define RADIOLIB_EEPROM_UNSUPPORTED
#elif defined(ARDUINO_ARCH_SAMD)
// Arduino SAMD (Zero, MKR, etc.)
@ -246,18 +230,15 @@
#define RADIOLIB_ARDUINOHAL_PIN_MODE_CAST (PinMode)
#define RADIOLIB_ARDUINOHAL_PIN_STATUS_CAST (PinStatus)
#define RADIOLIB_ARDUINOHAL_INTERRUPT_MODE_CAST (PinStatus)
#define RADIOLIB_EEPROM_UNSUPPORTED
#elif defined(__SAM3X8E__)
// Arduino Due
#define RADIOLIB_PLATFORM "Arduino Due"
#define RADIOLIB_TONE_UNSUPPORTED
#define RADIOLIB_EEPROM_UNSUPPORTED
#elif (defined(NRF52832_XXAA) || defined(NRF52840_XXAA)) && !defined(ARDUINO_ARDUINO_NANO33BLE)
// Adafruit nRF52 boards
#define RADIOLIB_PLATFORM "Adafruit nRF52"
#define RADIOLIB_EEPROM_UNSUPPORTED
#elif defined(ARDUINO_ARC32_TOOLS)
// Intel Curie
@ -280,7 +261,6 @@
#define RADIOLIB_ARDUINOHAL_PIN_MODE_CAST (PinMode)
#define RADIOLIB_ARDUINOHAL_PIN_STATUS_CAST (PinStatus)
#define RADIOLIB_ARDUINOHAL_INTERRUPT_MODE_CAST (PinStatus)
#define RADIOLIB_EEPROM_UNSUPPORTED
// Arduino mbed OS boards have a really bad tone implementation which will crash after a couple seconds
#define RADIOLIB_TONE_UNSUPPORTED
@ -292,7 +272,6 @@
#define RADIOLIB_ARDUINOHAL_PIN_MODE_CAST (PinMode)
#define RADIOLIB_ARDUINOHAL_PIN_STATUS_CAST (PinStatus)
#define RADIOLIB_ARDUINOHAL_INTERRUPT_MODE_CAST (PinStatus)
#define RADIOLIB_EEPROM_UNSUPPORTED
// Arduino mbed OS boards have a really bad tone implementation which will crash after a couple seconds
#define RADIOLIB_TONE_UNSUPPORTED
@ -314,7 +293,6 @@
#define RADIOLIB_ARDUINOHAL_PIN_MODE_CAST (PinMode)
#define RADIOLIB_ARDUINOHAL_PIN_STATUS_CAST (PinStatus)
#define RADIOLIB_ARDUINOHAL_INTERRUPT_MODE_CAST (PinStatus)
#define RADIOLIB_EEPROM_UNSUPPORTED
// Arduino mbed OS boards have a really bad tone implementation which will crash after a couple seconds
#define RADIOLIB_TONE_UNSUPPORTED
@ -501,7 +479,7 @@
#define RADIOLIB_DEBUG_PRINT_FLOAT(LEVEL, VAL, DECIMALS) RADIOLIB_DEBUG_PRINT(LEVEL "%.3f", VAL)
#endif
#define RADIOLIB_DEBUG_HEXDUMP(LEVEL, ...) RADIOLIB_DEBUG_PRINT(LEVEL); Module::hexdump(__VA_ARGS__)
#define RADIOLIB_DEBUG_HEXDUMP(LEVEL, ...) Module::hexdump(LEVEL, __VA_ARGS__)
#else
#define RADIOLIB_DEBUG_PRINT(...) {}
#define RADIOLIB_DEBUG_PRINTLN(...) {}
@ -585,4 +563,4 @@
#define RADIOLIB_VERSION (((RADIOLIB_VERSION_MAJOR) << 24) | ((RADIOLIB_VERSION_MINOR) << 16) | ((RADIOLIB_VERSION_PATCH) << 8) | (RADIOLIB_VERSION_EXTRA))
#endif
#endif

Wyświetl plik

@ -33,50 +33,3 @@ void RadioLibHal::yield() {
uint32_t RadioLibHal::pinToInterrupt(uint32_t pin) {
return(pin);
}
void RadioLibHal::readPersistentStorage(uint32_t addr, uint8_t* buff, size_t len) {
// these are only needed for some protocols, so it's not needed to have them by default
(void)addr;
(void)buff;
(void)len;
}
void RadioLibHal::writePersistentStorage(uint32_t addr, uint8_t* buff, size_t len) {
// these are only needed for some protocols, so it's not needed to have them by default
(void)addr;
(void)buff;
(void)len;
}
void RadioLibHal::wipePersistentStorage() {
uint8_t dummy = 0;
for(size_t i = 0; i < RADIOLIB_HAL_PERSISTENT_STORAGE_SIZE; i++) {
this->writePersistentStorage(RADIOLIB_HAL_PERSISTENT_STORAGE_BASE + i, &dummy, sizeof(uint8_t));
}
}
uint32_t RadioLibHal::getPersistentAddr(uint32_t id) {
return(RadioLibPersistentParamTable[id]);
}
template<typename T>
void RadioLibHal::setPersistentParameter(uint32_t id, T val, uint32_t offset) {
uint8_t *ptr = (uint8_t*)&val;
this->writePersistentStorage(RADIOLIB_HAL_PERSISTENT_STORAGE_BASE + RadioLibPersistentParamTable[id] + offset, ptr, sizeof(T));
}
template void RadioLibHal::setPersistentParameter(uint32_t id, uint8_t val, uint32_t offset);
template void RadioLibHal::setPersistentParameter(uint32_t id, uint16_t val, uint32_t offset);
template void RadioLibHal::setPersistentParameter(uint32_t id, uint32_t val, uint32_t offset);
template<typename T>
T RadioLibHal::getPersistentParameter(uint32_t id) {
T val = 0;
uint8_t *ptr = (uint8_t*)&val;
this->readPersistentStorage(RADIOLIB_HAL_PERSISTENT_STORAGE_BASE + RadioLibPersistentParamTable[id], ptr, sizeof(T));
return(val);
}
template uint8_t RadioLibHal::getPersistentParameter(uint32_t id);
template uint16_t RadioLibHal::getPersistentParameter(uint32_t id);
template uint32_t RadioLibHal::getPersistentParameter(uint32_t id);

132
src/Hal.h
Wyświetl plik

@ -6,88 +6,6 @@
#include "BuildOpt.h"
#define RADIOLIB_EEPROM_TABLE_VERSION (0x0002)
// list of persistent parameters
enum RADIOLIB_EEPROM_PARAMS {
RADIOLIB_EEPROM_TABLE_VERSION_ID, // table layout version
RADIOLIB_EEPROM_LORAWAN_CLASS_ID, // class A, B or C
RADIOLIB_EEPROM_LORAWAN_MODE_ID, // none, OTAA or ABP
RADIOLIB_EEPROM_LORAWAN_CHECKSUM_ID, // checksum of keys used for device activation
RADIOLIB_EEPROM_LORAWAN_VERSION_ID, // LoRaWAN version
RADIOLIB_EEPROM_LORAWAN_LAST_TIME_ID, // last heard time through DeviceTimeReq or Beacon
RADIOLIB_EEPROM_LORAWAN_DEV_ADDR_ID,
RADIOLIB_EEPROM_LORAWAN_APP_S_KEY_ID,
RADIOLIB_EEPROM_LORAWAN_FNWK_SINT_KEY_ID,
RADIOLIB_EEPROM_LORAWAN_SNWK_SINT_KEY_ID,
RADIOLIB_EEPROM_LORAWAN_NWK_SENC_KEY_ID,
RADIOLIB_EEPROM_LORAWAN_DEV_NONCE_ID,
RADIOLIB_EEPROM_LORAWAN_JOIN_NONCE_ID,
RADIOLIB_EEPROM_LORAWAN_HOME_NET_ID,
RADIOLIB_EEPROM_LORAWAN_A_FCNT_DOWN_ID,
RADIOLIB_EEPROM_LORAWAN_N_FCNT_DOWN_ID,
RADIOLIB_EEPROM_LORAWAN_CONF_FCNT_UP_ID,
RADIOLIB_EEPROM_LORAWAN_CONF_FCNT_DOWN_ID,
RADIOLIB_EEPROM_LORAWAN_ADR_FCNT_ID,
RADIOLIB_EEPROM_LORAWAN_RJ_COUNT0_ID,
RADIOLIB_EEPROM_LORAWAN_RJ_COUNT1_ID,
RADIOLIB_EEPROM_LORAWAN_FCNT_UP_ID,
RADIOLIB_EEPROM_LORAWAN_LINK_ADR_ID,
RADIOLIB_EEPROM_LORAWAN_DUTY_CYCLE_ID,
RADIOLIB_EEPROM_LORAWAN_RX_PARAM_SETUP_ID,
RADIOLIB_EEPROM_LORAWAN_RX_TIMING_SETUP_ID,
RADIOLIB_EEPROM_LORAWAN_TX_PARAM_SETUP_ID,
RADIOLIB_EEPROM_LORAWAN_ADR_PARAM_SETUP_ID,
RADIOLIB_EEPROM_LORAWAN_REJOIN_PARAM_SETUP_ID,
RADIOLIB_EEPROM_LORAWAN_BEACON_FREQ_ID,
RADIOLIB_EEPROM_LORAWAN_PING_SLOT_CHANNEL_ID,
RADIOLIB_EEPROM_LORAWAN_PERIODICITY_ID,
RADIOLIB_EEPROM_LORAWAN_NUM_ADR_MASKS_ID,
RADIOLIB_EEPROM_LORAWAN_MAC_QUEUE_UL_ID,
RADIOLIB_EEPROM_LORAWAN_UL_CHANNELS_ID,
RADIOLIB_EEPROM_LORAWAN_DL_CHANNELS_ID
};
static const uint32_t RadioLibPersistentParamTable[] = {
0x00, // RADIOLIB_EEPROM_TABLE_VERSION_ID
0x02, // RADIOLIB_EEPROM_LORAWAN_CLASS_ID
0x03, // RADIOLIB_EEPROM_LORAWAN_MODE_ID
0x05, // RADIOLIB_EEPROM_LORAWAN_CHECKSUM_ID
0x07, // RADIOLIB_EEPROM_LORAWAN_VERSION_ID
0x08, // RADIOLIB_EEPROM_LORAWAN_LAST_TIME_ID
0x0C, // RADIOLIB_EEPROM_LORAWAN_DEV_ADDR_ID
0x10, // RADIOLIB_EEPROM_LORAWAN_APP_S_KEY_ID
0x20, // RADIOLIB_EEPROM_LORAWAN_FNWK_SINT_KEY_ID
0x30, // RADIOLIB_EEPROM_LORAWAN_SNWK_SINT_KEY_ID
0x40, // RADIOLIB_EEPROM_LORAWAN_NWK_SENC_KEY_ID
0x50, // RADIOLIB_EEPROM_LORAWAN_DEV_NONCE_ID
0x54, // RADIOLIB_EEPROM_LORAWAN_JOIN_NONCE_ID
0x58, // RADIOLIB_EEPROM_LORAWAN_HOME_NET_ID
0x5C, // RADIOLIB_EEPROM_LORAWAN_A_FCNT_DOWN_ID
0x60, // RADIOLIB_EEPROM_LORAWAN_N_FCNT_DOWN_ID
0x64, // RADIOLIB_EEPROM_LORAWAN_CONF_FCNT_UP_ID
0x68, // RADIOLIB_EEPROM_LORAWAN_CONF_FCNT_DOWN_ID
0x6C, // RADIOLIB_EEPROM_LORAWAN_ADR_FCNT_ID
0x70, // RADIOLIB_EEPROM_LORAWAN_RJ_COUNT0_ID
0x72, // RADIOLIB_EEPROM_LORAWAN_RJ_COUNT1_ID
0x74, // RADIOLIB_EEPROM_LORAWAN_FCNT_UP_ID
0xA0, // RADIOLIB_EEPROM_LORAWAN_LINK_ADR_ID
0xA4, // RADIOLIB_EEPROM_LORAWAN_DUTY_CYCLE_ID
0xA5, // RADIOLIB_EEPROM_LORAWAN_RX_PARAM_SETUP_ID
0xA9, // RADIOLIB_EEPROM_LORAWAN_RX_TIMING_SETUP_ID
0xAA, // RADIOLIB_EEPROM_LORAWAN_TX_PARAM_SETUP_ID
0xAB, // RADIOLIB_EEPROM_LORAWAN_ADR_PARAM_SETUP_ID
0xAC, // RADIOLIB_EEPROM_LORAWAN_REJOIN_PARAM_SETUP_ID
0xAD, // RADIOLIB_EEPROM_LORAWAN_BEACON_FREQ_ID
0xB0, // RADIOLIB_EEPROM_LORAWAN_PING_SLOT_CHANNEL_ID
0xB4, // RADIOLIB_EEPROM_LORAWAN_PERIODICITY_ID
0xB5, // RADIOLIB_EEPROM_LORAWAN_NUM_ADR_MASKS_ID
0xB6, // RADIOLIB_EEPROM_LORAWAN_MAC_QUEUE_UL_ID
0x0100, // RADIOLIB_EEPROM_LORAWAN_UL_CHANNELS_ID
0x0180, // RADIOLIB_EEPROM_LORAWAN_DL_CHANNELS_ID
0x01C0, // end
};
/*!
\class RadioLibHal
\brief Hardware abstraction library base interface.
@ -289,56 +207,6 @@ class RadioLibHal {
\returns The interrupt number of a given pin.
*/
virtual uint32_t pinToInterrupt(uint32_t pin);
/*!
\brief Method to read from persistent storage (e.g. EEPROM).
\param addr Address to start reading at.
\param buff Buffer to read into.
\param len Number of bytes to read.
*/
virtual void readPersistentStorage(uint32_t addr, uint8_t* buff, size_t len);
/*!
\brief Method to write to persistent storage (e.g. EEPROM).
\param addr Address to start writing to.
\param buff Buffer to write.
\param len Number of bytes to write.
*/
virtual void writePersistentStorage(uint32_t addr, uint8_t* buff, size_t len);
/*!
\brief Method to wipe the persistent storage by writing to 0.
Will write at most RADIOLIB_HAL_PERSISTENT_STORAGE_SIZE bytes.
*/
void wipePersistentStorage();
/*!
\brief Method to convert from persistent parameter ID to its physical address.
\param id Parameter ID.
\returns Parameter physical address.
*/
uint32_t getPersistentAddr(uint32_t id);
/*!
\brief Method to set arbitrary parameter to persistent storage.
This method DOES NOT perform any endianness conversion, so the value
will be stored in the system endian!
\param id Parameter ID to save at.
\param val Value to set.
\param offset An additional offset added to the address.
*/
template<typename T>
void setPersistentParameter(uint32_t id, T val, uint32_t offset = 0);
/*!
\brief Method to get arbitrary parameter from persistent storage.
This method DOES NOT perform any endianness conversion, so the value
will be retrieved in the system endian!
\param id Parameter ID to load from.
\returns The loaded value.
*/
template<typename T>
T getPersistentParameter(uint32_t id);
};
#endif

Wyświetl plik

@ -407,7 +407,7 @@ uint32_t Module::reflect(uint32_t in, uint8_t bits) {
}
#if RADIOLIB_DEBUG
void Module::hexdump(uint8_t* data, size_t len, uint32_t offset, uint8_t width, bool be) {
void Module::hexdump(const char* level, uint8_t* data, size_t len, uint32_t offset, uint8_t width, bool be) {
size_t rem_len = len;
for(size_t i = 0; i < len; i+=16) {
char str[80];
@ -446,20 +446,23 @@ void Module::hexdump(uint8_t* data, size_t len, uint32_t offset, uint8_t width,
for(size_t j = line_len; j < 16; j++) {
sprintf(&str[58 + j], " ");
}
if(level) {
RADIOLIB_DEBUG_PRINT(level);
}
RADIOLIB_DEBUG_PRINT(str);
RADIOLIB_DEBUG_PRINTLN();
rem_len -= 16;
}
}
void Module::regdump(uint16_t start, size_t len) {
void Module::regdump(const char* level, uint16_t start, size_t len) {
#if RADIOLIB_STATIC_ONLY
uint8_t buff[RADIOLIB_STATIC_ARRAY_SIZE];
#else
uint8_t* buff = new uint8_t[len];
#endif
SPIreadRegisterBurst(start, len, buff);
hexdump(buff, len, start);
hexdump(level, buff, len, start);
#if !RADIOLIB_STATIC_ONLY
delete[] buff;
#endif

Wyświetl plik

@ -471,19 +471,21 @@ class Module {
#if RADIOLIB_DEBUG
/*!
\brief Function to dump data as hex into the debug port.
\param level RadioLib debug level, set to NULL to not print.
\param data Data to dump.
\param len Number of bytes to dump.
\param width Word width (1 for uint8_t, 2 for uint16_t, 4 for uint32_t).
\param be Print multi-byte data as big endian. Defaults to false.
*/
static void hexdump(uint8_t* data, size_t len, uint32_t offset = 0, uint8_t width = 1, bool be = false);
static void hexdump(const char* level, uint8_t* data, size_t len, uint32_t offset = 0, uint8_t width = 1, bool be = false);
/*!
\brief Function to dump device registers as hex into the debug port.
\param level RadioLib debug level, set to NULL to not print.
\param start First address to dump.
\param len Number of bytes to dump.
*/
void regdump(uint16_t start, size_t len);
void regdump(const char* level, uint16_t start, size_t len);
#endif
#if RADIOLIB_DEBUG and defined(RADIOLIB_BUILD_ARDUINO)

Wyświetl plik

@ -528,35 +528,35 @@
*/
#define RADIOLIB_ERR_COMMAND_QUEUE_FULL (-1109)
/*!
\brief Unable to pop existing MAC command because the queue is empty.
*/
#define RADIOLIB_ERR_COMMAND_QUEUE_EMPTY (-1110)
/*!
\brief Unable to delete MAC command because it was not found in the queue.
*/
#define RADIOLIB_ERR_COMMAND_QUEUE_ITEM_NOT_FOUND (-1111)
#define RADIOLIB_ERR_COMMAND_QUEUE_ITEM_NOT_FOUND (-1110)
/*!
\brief Unable to join network because JoinNonce is not higher than saved value.
*/
#define RADIOLIB_ERR_JOIN_NONCE_INVALID (-1112)
#define RADIOLIB_ERR_JOIN_NONCE_INVALID (-1111)
/*!
\brief Received downlink Network frame counter is invalid (lower than last heard value).
*/
#define RADIOLIB_ERR_N_FCNT_DOWN_INVALID (-1113)
#define RADIOLIB_ERR_N_FCNT_DOWN_INVALID (-1112)
/*!
\brief Received downlink Application frame counter is invalid (lower than last heard value).
*/
#define RADIOLIB_ERR_A_FCNT_DOWN_INVALID (-1114)
#define RADIOLIB_ERR_A_FCNT_DOWN_INVALID (-1113)
/*!
\brief Uplink payload length at this datarate exceeds the active dwell time limitations.
*/
#define RADIOLIB_ERR_DWELL_TIME_EXCEEDED (-1115)
#define RADIOLIB_ERR_DWELL_TIME_EXCEEDED (-1114)
/*!
\brief The buffer integrity check did not match the supplied checksum value.
*/
#define RADIOLIB_ERR_CHECKSUM_MISMATCH (-1115)
/*!
\}

Wyświetl plik

@ -6,14 +6,14 @@
#include "../../utils/Cryptography.h"
// activation mode
#define RADIOLIB_LORAWAN_MODE_OTAA (0x01AA)
#define RADIOLIB_LORAWAN_MODE_OTAA (0x07AA)
#define RADIOLIB_LORAWAN_MODE_ABP (0x0AB9)
#define RADIOLIB_LORAWAN_MODE_NONE (0x0000)
// operation mode
#define RADIOLIB_LORAWAN_CLASS_A (0x00)
#define RADIOLIB_LORAWAN_CLASS_B (0x01)
#define RADIOLIB_LORAWAN_CLASS_C (0x02)
#define RADIOLIB_LORAWAN_CLASS_A (0x0A)
#define RADIOLIB_LORAWAN_CLASS_B (0x0B)
#define RADIOLIB_LORAWAN_CLASS_C (0x0C)
// preamble format
#define RADIOLIB_LORAWAN_LORA_SYNC_WORD (0x34)
@ -226,6 +226,56 @@ const LoRaWANMacSpec_t MacTable[RADIOLIB_LORAWAN_NUM_MAC_COMMANDS + 1] = {
{ RADIOLIB_LORAWAN_MAC_PROPRIETARY, 5, 0, true }
};
#define RADIOLIB_LORAWAN_NONCES_VERSION_VAL (0x0001)
enum LoRaWANSchemeBase_t {
RADIOLIB_LORAWAN_NONCES_VERSION = 0x00, // 2 bytes
RADIOLIB_LORAWAN_NONCES_MODE = 0x02, // 2 bytes
RADIOLIB_LORAWAN_NONCES_CLASS = 0x04, // 1 byte
RADIOLIB_LORAWAN_NONCES_PLAN = 0x05, // 1 byte
RADIOLIB_LORAWAN_NONCES_CHECKSUM = 0x06, // 2 bytes
RADIOLIB_LORAWAN_NONCES_DEV_NONCE = 0x08, // 2 bytes
RADIOLIB_LORAWAN_NONCES_JOIN_NONCE = 0x0A, // 3 bytes
RADIOLIB_LORAWAN_NONCES_ACTIVE = 0x0D, // 1 byte
RADIOLIB_LORAWAN_NONCES_SIGNATURE = 0x0E, // 2 bytes
RADIOLIB_LORAWAN_NONCES_BUF_SIZE = 0x10 // = 16 bytes
};
enum LoRaWANSchemeSession_t {
RADIOLIB_LORAWAN_SESSION_NWK_SENC_KEY = 0x00, // 16 bytes
RADIOLIB_LORAWAN_SESSION_APP_SKEY = 0x10, // 16 bytes
RADIOLIB_LORAWAN_SESSION_FNWK_SINT_KEY = 0x20, // 16 bytes
RADIOLIB_LORAWAN_SESSION_SNWK_SINT_KEY = 0x30, // 16 bytes
RADIOLIB_LORAWAN_SESSION_DEV_ADDR = 0x40, // 4 bytes
RADIOLIB_LORAWAN_SESSION_NONCES_SIGNATURE = 0x44, // 2 bytes
RADIOLIB_LORAWAN_SESSION_A_FCNT_DOWN = 0x46, // 4 bytes
RADIOLIB_LORAWAN_SESSION_CONF_FCNT_UP = 0x4A, // 4 bytes
RADIOLIB_LORAWAN_SESSION_CONF_FCNT_DOWN = 0x4E, // 4 bytes
RADIOLIB_LORAWAN_SESSION_RJ_COUNT0 = 0x52, // 2 bytes
RADIOLIB_LORAWAN_SESSION_RJ_COUNT1 = 0x54, // 2 bytes
RADIOLIB_LORAWAN_SESSION_HOMENET_ID = 0x56, // 4 bytes
RADIOLIB_LORAWAN_SESSION_VERSION = 0x5A, // 1 byte
RADIOLIB_LORAWAN_SESSION_DUTY_CYCLE = 0x5B, // 1 byte
RADIOLIB_LORAWAN_SESSION_RX_PARAM_SETUP = 0x5C, // 4 bytes
RADIOLIB_LORAWAN_SESSION_RX_TIMING_SETUP = 0x60, // 1 byte
RADIOLIB_LORAWAN_SESSION_TX_PARAM_SETUP = 0x61, // 1 byte
RADIOLIB_LORAWAN_SESSION_ADR_PARAM_SETUP = 0x62, // 1 byte
RADIOLIB_LORAWAN_SESSION_REJOIN_PARAM_SETUP = 0x63, // 1 byte
RADIOLIB_LORAWAN_SESSION_BEACON_FREQ = 0x64, // 3 bytes
RADIOLIB_LORAWAN_SESSION_PING_SLOT_CHANNEL = 0x67, // 4 bytes
RADIOLIB_LORAWAN_SESSION_PERIODICITY = 0x6B, // 1 byte
RADIOLIB_LORAWAN_SESSION_LAST_TIME = 0x6C, // 4 bytes
RADIOLIB_LORAWAN_SESSION_UL_CHANNELS = 0x70, // 16*8 bytes
RADIOLIB_LORAWAN_SESSION_DL_CHANNELS = 0xF0, // 16*4 bytes
RADIOLIB_LORAWAN_SESSION_MAC_QUEUE_UL = 0x0130, // 9*8+2 bytes
RADIOLIB_LORAWAN_SESSION_N_FCNT_DOWN = 0x017A, // 4 bytes
RADIOLIB_LORAWAN_SESSION_ADR_FCNT = 0x017E, // 4 bytes
RADIOLIB_LORAWAN_SESSION_LINK_ADR = 0x0182, // 4 bytes
RADIOLIB_LORAWAN_SESSION_FCNT_UP = 0x0186, // 4 bytes
RADIOLIB_LORAWAN_SESSION_SIGNATURE = 0x018A, // 2 bytes
RADIOLIB_LORAWAN_SESSION_BUF_SIZE = 0x018C // 396 bytes
};
/*!
\struct LoRaWANChannelSpan_t
\brief Structure to save information about LoRaWAN channels.
@ -284,6 +334,9 @@ struct LoRaWANChannelSpan_t {
\brief Structure to save information about LoRaWAN band
*/
struct LoRaWANBand_t {
/*! \brief Identier for this band */
uint8_t bandNum;
/*! \brief Whether the channels are fixed per specification, or dynamically allocated through the network (plus defaults) */
uint8_t bandType;
@ -415,7 +468,6 @@ class LoRaWANNode {
*/
LoRaWANNode(PhysicalLayer* phy, const LoRaWANBand_t* band, uint8_t subBand = 0);
#if !defined(RADIOLIB_EEPROM_UNSUPPORTED)
/*!
\brief Wipe internal persistent parameters.
This will reset all counters and saved variables, so the device will have to rejoin the network.
@ -423,12 +475,36 @@ class LoRaWANNode {
void wipe();
/*!
\brief Restore session by loading information from persistent storage.
\returns \ref status_codes in case of error,
else LoRaWAN session mode (0 = no active session, 0xAA / 170 = OTAA, 0xAB / 171 = ABP)
\brief Returns the pointer to the internal buffer that holds the LW base parameters
\returns Pointer to uint8_t array of size RADIOLIB_LORAWAN_NONCES_BUF_SIZE
*/
int16_t restore();
#endif
uint8_t* getBufferNonces();
/*!
\brief Fill the internal buffer that holds the LW base parameters with a supplied buffer
\param persistentBuffer Buffer that should match the internal format (previously extracted using getBufferNonces)
\returns \ref status_codes
*/
int16_t setBufferNonces(uint8_t* persistentBuffer);
/*!
\brief Returns the pointer to the internal buffer that holds the LW session parameters
\returns Pointer to uint8_t array of size RADIOLIB_LORAWAN_SESSION_BUF_SIZE
*/
uint8_t* getBufferSession();
/*!
\brief Fill the internal buffer that holds the LW session parameters with a supplied buffer
\param persistentBuffer Buffer that should match the internal format (previously extracted using getBufferSession)
\returns \ref status_codes
*/
int16_t setBufferSession(uint8_t* persistentBuffer);
/*!
\brief Restore session by loading information from persistent storage.
\returns \ref status_codes
*/
int16_t restore(uint16_t checkSum, uint16_t lwMode, uint8_t lwClass, uint8_t freqPlan);
/*!
\brief Join network by performing over-the-air activation. By this procedure,
@ -437,12 +513,11 @@ class LoRaWANNode {
\param devEUI 8-byte device identifier.
\param nwkKey Pointer to the network AES-128 key.
\param appKey Pointer to the application AES-128 key.
\param joinDr (OTAA:) The datarate at which to send the join-request; (ABP:) ignored
\param force Set to true to force joining even if previously joined.
\param joinDr The datarate at which to send the join-request and any subsequent uplinks (unless ADR is enabled)
\returns \ref status_codes
*/
int16_t beginOTAA(uint64_t joinEUI, uint64_t devEUI, uint8_t* nwkKey, uint8_t* appKey, uint8_t joinDr = RADIOLIB_LORAWAN_DATA_RATE_UNUSED, bool force = false);
int16_t beginOTAA(uint64_t joinEUI, uint64_t devEUI, uint8_t* nwkKey, uint8_t* appKey, bool force = false, uint8_t joinDr = RADIOLIB_LORAWAN_DATA_RATE_UNUSED);
/*!
\brief Join network by performing activation by personalization.
@ -450,19 +525,19 @@ class LoRaWANNode {
\param addr Device address.
\param nwkSKey Pointer to the network session AES-128 key (LoRaWAN 1.0) or MAC command network session key (LoRaWAN 1.1).
\param appSKey Pointer to the application session AES-128 key.
\param fNwkSIntKey Pointer to the network session F key (LoRaWAN 1.1), unused for LoRaWAN 1.0.
\param sNwkSIntKey Pointer to the network session S key (LoRaWAN 1.1), unused for LoRaWAN 1.0.
\param fNwkSIntKey Pointer to the Forwarding network session (LoRaWAN 1.1), unused for LoRaWAN 1.0.
\param sNwkSIntKey Pointer to the Serving network session (LoRaWAN 1.1), unused for LoRaWAN 1.0.
\param force Set to true to force a new session, even if one exists.
\param initialDr The datarate at which to send the first uplink and any subsequent uplinks (unless ADR is enabled)
\returns \ref status_codes
*/
int16_t beginABP(uint32_t addr, uint8_t* nwkSKey, uint8_t* appSKey, uint8_t* fNwkSIntKey = NULL, uint8_t* sNwkSIntKey = NULL, bool force = false);
int16_t beginABP(uint32_t addr, uint8_t* nwkSKey, uint8_t* appSKey, uint8_t* fNwkSIntKey = NULL, uint8_t* sNwkSIntKey = NULL, bool force = false, uint8_t initialDr = RADIOLIB_LORAWAN_DATA_RATE_UNUSED);
/*! \brief Whether there is an ongoing session active */
bool isJoined();
/*!
\brief Save the current state of the session.
All variables are compared to what is saved and only the differences are rewritten.
\brief Save the current state of the session to the session buffer.
\returns \ref status_codes
*/
int16_t saveSession();
@ -637,10 +712,9 @@ class LoRaWANNode {
/*!
\brief Set uplink datarate. This should not be used when ADR is enabled.
\param dr Datarate to use for uplinks.
\param saveToEeprom Whether to save this setting to EEPROM or not (default false).
\returns \ref status_codes
*/
int16_t setDatarate(uint8_t drUp, bool saveToEeprom = false);
int16_t setDatarate(uint8_t drUp);
/*!
\brief Toggle ADR to on or off.
@ -686,10 +760,9 @@ class LoRaWANNode {
/*!
\brief Configure TX power of the radio module.
\param txPower Output power during TX mode to be set in dBm.
\param saveToEeprom Whether to save this setting to EEPROM or not (default false).
\returns \ref status_codes
*/
int16_t setTxPower(int8_t txPower, bool saveToEeprom = false);
int16_t setTxPower(int8_t txPower);
/*!
\brief Configures CSMA for LoRaWAN as per TR-13, LoRa Alliance.
@ -732,7 +805,15 @@ class LoRaWANNode {
PhysicalLayer* phyLayer = NULL;
const LoRaWANBand_t* band = NULL;
void beginCommon(uint8_t joinDr = RADIOLIB_LORAWAN_DATA_RATE_UNUSED);
static int16_t checkBufferCommon(uint8_t *buffer, uint16_t size);
void beginCommon(uint8_t initialDr);
// a buffer that holds all LW base parameters that should persist at all times!
uint8_t bufferNonces[RADIOLIB_LORAWAN_NONCES_BUF_SIZE] = { 0 };
// a buffer that holds all LW session parameters that preferably persist, but can be afforded to get lost
uint8_t bufferSession[RADIOLIB_LORAWAN_SESSION_BUF_SIZE] = { 0 };
LoRaWANMacCommandQueue_t commandsUp = {
.numCommands = 0,
@ -776,7 +857,7 @@ class LoRaWANNode {
bool FSK = false;
// flag that shows whether the device is joined and there is an ongoing session (none, ABP or OTAA)
uint16_t activeMode = 0;
uint16_t activeMode = RADIOLIB_LORAWAN_MODE_NONE;
// ADR is enabled by default
bool adrEnabled = true;
@ -835,26 +916,6 @@ class LoRaWANNode {
// save the selected sub-band in case this must be restored in ADR control
uint8_t subBand = 0;
#if !defined(RADIOLIB_EEPROM_UNSUPPORTED)
/*!
\brief Save the current uplink frame counter.
Note that the usable frame counter width is 'only' 30 bits for highly efficient wear-levelling.
*/
void saveFcntUp();
/*!
\brief Restore frame counter for uplinks from persistent storage.
Note that the usable frame counter width is 'only' 30 bits for highly efficient wear-levelling.
*/
void restoreFcntUp();
// set all keys to zero
void clearSession();
// test if saved keys are non-zero
bool isValidSession();
#endif
// wait for, open and listen during Rx1 and Rx2 windows; only performs listening
int16_t downlinkCommon();
@ -901,13 +962,13 @@ class LoRaWANNode {
int16_t deleteMacCommand(uint8_t cid, LoRaWANMacCommandQueue_t* queue, uint8_t* payload = NULL);
// execute mac command, return the number of processed bytes for sequential processing
bool execMacCommand(LoRaWANMacCommand_t* cmd, bool saveToEeprom = true);
bool execMacCommand(LoRaWANMacCommand_t* cmd);
// apply a channel mask to a set of readily defined channels (dynamic bands only)
bool applyChannelMaskDyn(uint8_t chMaskCntl, uint16_t chMask);
// define or delete channels from a fixed set of channels (fixed bands only)
bool applyChannelMaskFix(uint8_t chMaskCntl, uint16_t chMask, bool clear);
bool applyChannelMaskFix(uint8_t chMaskCntl, uint16_t chMask);
// get the payload length for a specific MAC command
uint8_t getMacPayloadLength(uint8_t cid);
@ -922,7 +983,7 @@ class LoRaWANNode {
void processAES(uint8_t* in, size_t len, uint8_t* key, uint8_t* out, uint32_t fcnt, uint8_t dir, uint8_t ctrId, bool counter);
// 16-bit checksum method that takes a uint8_t array of even length and calculates the checksum
static uint16_t checkSum16(uint8_t *key, uint8_t keyLen);
static uint16_t checkSum16(uint8_t *key, uint16_t keyLen);
// network-to-host conversion method - takes data from network packet and converts it to the host endians
template<typename T>

Wyświetl plik

@ -2,7 +2,21 @@
#if !RADIOLIB_EXCLUDE_LORAWAN
enum LoRaWANBandNum_t {
BandNone,
BandEU868,
BandUS915,
BandCN780,
BandEU433,
BandAU915,
BandCN500,
BandAS923,
BandKR920,
BandIN865
};
const LoRaWANBand_t EU868 = {
.bandNum = BandEU868,
.bandType = RADIOLIB_LORAWAN_BAND_DYNAMIC,
.payloadLenMax = { 59, 59, 59, 123, 230, 230, 230, 230, 0, 0, 0, 0, 0, 0, 0 },
.powerMax = 16,
@ -48,6 +62,7 @@ const LoRaWANBand_t EU868 = {
};
const LoRaWANBand_t US915 = {
.bandNum = BandUS915,
.bandType = RADIOLIB_LORAWAN_BAND_FIXED,
.payloadLenMax = { 19, 61, 133, 250, 250, 0, 0, 0, 41, 117, 230, 230, 230, 230, 0 },
.powerMax = 30,
@ -114,6 +129,7 @@ const LoRaWANBand_t US915 = {
};
const LoRaWANBand_t CN780 = {
.bandNum = BandCN780,
.bandType = RADIOLIB_LORAWAN_BAND_DYNAMIC,
.payloadLenMax = { 59, 59, 59, 123, 230, 230, 250, 230, 0, 0, 0, 0, 0, 0, 0 },
.powerMax = 12,
@ -159,6 +175,7 @@ const LoRaWANBand_t CN780 = {
};
const LoRaWANBand_t EU433 = {
.bandNum = BandEU433,
.bandType = RADIOLIB_LORAWAN_BAND_DYNAMIC,
.payloadLenMax = { 59, 59, 59, 123, 230, 230, 230, 230, 0, 0, 0, 0, 0, 0, 0 },
.powerMax = 12,
@ -204,6 +221,7 @@ const LoRaWANBand_t EU433 = {
};
const LoRaWANBand_t AU915 = {
.bandNum = BandAU915,
.bandType = RADIOLIB_LORAWAN_BAND_FIXED,
.payloadLenMax = { 59, 59, 59, 123, 230, 230, 230, 0, 41, 117, 230, 230, 230, 230, 0 },
.powerMax = 30,
@ -270,6 +288,7 @@ const LoRaWANBand_t AU915 = {
};
const LoRaWANBand_t CN500 = {
.bandNum = BandCN500,
.bandType = RADIOLIB_LORAWAN_BAND_FIXED,
.payloadLenMax = { 59, 59, 59, 123, 230, 230, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
.powerMax = 19,
@ -329,6 +348,7 @@ const LoRaWANBand_t CN500 = {
};
const LoRaWANBand_t AS923 = {
.bandNum = BandAS923,
.bandType = RADIOLIB_LORAWAN_BAND_DYNAMIC,
.payloadLenMax = { 59, 59, 59, 123, 230, 230, 230, 230, 0, 0, 0, 0, 0, 0, 0 },
.powerMax = 16,
@ -374,6 +394,7 @@ const LoRaWANBand_t AS923 = {
};
const LoRaWANBand_t KR920 = {
.bandNum = BandKR920,
.bandType = RADIOLIB_LORAWAN_BAND_DYNAMIC,
.payloadLenMax = { 59, 59, 59, 123, 230, 230, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
.powerMax = 14,
@ -419,6 +440,7 @@ const LoRaWANBand_t KR920 = {
};
const LoRaWANBand_t IN865 = {
.bandNum = BandIN865,
.bandType = RADIOLIB_LORAWAN_BAND_DYNAMIC,
.payloadLenMax = { 59, 59, 59, 123, 230, 230, 230, 230, 0, 0, 0, 0, 0, 0, 0 },
.powerMax = 30,