├── lib ├── libheltec.a └── libheltec_s3.a ├── src ├── driver │ ├── board.c │ ├── delay.c │ ├── delay.h │ ├── gpio-board.c │ ├── gpio.c │ ├── lorawan_spi.h │ ├── gpio-board.h │ ├── board-config.h │ ├── rtc-board.h │ ├── board.h │ ├── gpio.h │ ├── sx1276-board.h │ ├── sx126x-board.h │ ├── debug.h │ ├── sx1262-board.c │ ├── timer.h │ ├── sx1276-board.c │ └── sx1276.h ├── ESP32_LoRaWan_102.h ├── ESP32_Mcu.h ├── loramac │ ├── Commissioning.h │ ├── cmac.h │ ├── LoRaMacTest.h │ ├── LoRaMacClassBConfig.h │ ├── utilities.c │ ├── LoRaMacCrypto.h │ ├── LoRaMacConfirmQueue.h │ ├── aes.h │ ├── cmac.c │ ├── LoRaMacConfirmQueue.c │ ├── LoRaMacCrypto.c │ ├── utilities.h │ └── region │ │ ├── RegionCommon.h │ │ └── RegionCommon.c ├── LoRaWan_APP.h └── radio │ └── radio_sx127x.h ├── examples ├── LoRaBasic │ ├── pingpong │ │ └── pingpong.ino │ ├── README.md │ ├── TxPowerTest │ │ └── TxPowerTest.ino │ ├── LoRaReceiver │ │ └── LoRaReceiver.ino │ └── LoRaSender │ │ └── LoRaSender.ino └── LoRaWAN │ ├── LoRaWan │ └── LoRaWan.ino │ ├── LoRaWan_interrupt │ └── LoRaWan_interrupt.ino │ ├── LoRaWan_OLED │ └── LoRaWan_OLED.ino │ ├── LoRaWan_multicast │ └── LoRaWan_multicast.ino │ ├── LoRaWan_TimeReq │ └── LoRaWan_TimeReq.ino │ └── LoRaWan_downlinkdatahandle │ └── LoRaWan_downlinkdatahandle.ino ├── library.json ├── LICENSE └── README.md /lib/libheltec.a: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eiannone/Heltec_Esp32_LoRaWan/HEAD/lib/libheltec.a -------------------------------------------------------------------------------- /lib/libheltec_s3.a: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eiannone/Heltec_Esp32_LoRaWan/HEAD/lib/libheltec_s3.a -------------------------------------------------------------------------------- /src/driver/board.c: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eiannone/Heltec_Esp32_LoRaWan/HEAD/src/driver/board.c -------------------------------------------------------------------------------- /examples/LoRaBasic/pingpong/pingpong.ino: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eiannone/Heltec_Esp32_LoRaWan/HEAD/examples/LoRaBasic/pingpong/pingpong.ino -------------------------------------------------------------------------------- /examples/LoRaBasic/README.md: -------------------------------------------------------------------------------- 1 | # LoRaBasic Folder 2 | 3 | All examples in this path, just directly call the SX1262 hardware layer to transmit LoRa signals, and do not include any operations with protocol layer. -------------------------------------------------------------------------------- /src/ESP32_LoRaWan_102.h: -------------------------------------------------------------------------------- 1 | #ifndef __LORAWAN_102_H__ 2 | #define __LORAWAN_102_H__ 3 | 4 | #include "loramac/LoRaMac.h" 5 | #include "loramac/Commissioning.h" 6 | #include "loramac/region/Region.h" 7 | 8 | #endif 9 | -------------------------------------------------------------------------------- /src/driver/delay.c: -------------------------------------------------------------------------------- 1 | /* 2 | / _____) _ | | 3 | ( (____ _____ ____ _| |_ _____ ____| |__ 4 | \____ \| ___ | (_ _) ___ |/ ___) _ \ 5 | _____) ) ____| | | || |_| ____( (___| | | | 6 | (______/|_____)_|_|_| \__)_____)\____)_| |_| 7 | (C)2013 Semtech 8 | 9 | Description: Delay functions implementation 10 | 11 | License: Revised BSD License, see LICENSE.TXT file include in the project 12 | 13 | Maintainer: Miguel Luis and Gregory Cristian 14 | */ 15 | #include "../driver/board.h" 16 | #include "Arduino.h" 17 | 18 | void DelayMs( uint32_t ms ) 19 | { 20 | delay(ms); 21 | } 22 | -------------------------------------------------------------------------------- /library.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "Heltec_Esp32_LoRaWan", 3 | "version": "0.7.0", 4 | "description": "Arduino/Platformio LoRaWAN library for Heltec ESP32 boards", 5 | "keywords": "esp32, lora, heltec", 6 | "repository": 7 | { 8 | "type": "git", 9 | "url": "https://github.com/eiannone/Heltec_Esp32_LoRaWan.git" 10 | }, 11 | "authors": 12 | [ 13 | { 14 | "name": "Emanuele Iannone", 15 | "email": "emanuele@fondani.it", 16 | "maintainer": true 17 | } 18 | ], 19 | "license": "MIT", 20 | "frameworks": "arduino", 21 | "platforms": "espressif32", 22 | "build": { 23 | "flags": [ 24 | "-L lib" 25 | ] 26 | } 27 | } -------------------------------------------------------------------------------- /src/driver/delay.h: -------------------------------------------------------------------------------- 1 | /* 2 | / _____) _ | | 3 | ( (____ _____ ____ _| |_ _____ ____| |__ 4 | \____ \| ___ | (_ _) ___ |/ ___) _ \ 5 | _____) ) ____| | | || |_| ____( (___| | | | 6 | (______/|_____)_|_|_| \__)_____)\____)_| |_| 7 | (C)2013 Semtech 8 | 9 | Description: Delay functions implementation 10 | 11 | License: Revised BSD License, see LICENSE.TXT file include in the project 12 | 13 | Maintainer: Miguel Luis and Gregory Cristian 14 | */ 15 | #ifndef __DELAY_H__ 16 | #define __DELAY_H__ 17 | 18 | #ifdef __cplusplus 19 | extern "C"{ 20 | #endif 21 | /*! 22 | * Blocking delay of "s" seconds 23 | */ 24 | void Delay( float s ); 25 | 26 | /*! 27 | * Blocking delay of "ms" milliseconds 28 | */ 29 | void DelayMs( uint32_t ms ); 30 | 31 | #ifdef __cplusplus 32 | } // extern "C" 33 | #endif 34 | 35 | #endif // __DELAY_H__ 36 | 37 | -------------------------------------------------------------------------------- /examples/LoRaBasic/TxPowerTest/TxPowerTest.ino: -------------------------------------------------------------------------------- 1 | #include "LoRaWan_APP.h" 2 | #include "Arduino.h" 3 | 4 | #define RF_FREQUENCY 868000000 // Hz 5 | #define TX_OUTPUT_POWER 10 // 20 dBm 6 | #define TX_TIMEOUT 10 // seconds (MAX value) 7 | static RadioEvents_t RadioEvents; 8 | 9 | void OnRadioTxTimeout( void ) 10 | { 11 | // Restarts continuous wave transmission when timeout expires 12 | Radio.SetTxContinuousWave( RF_FREQUENCY, TX_OUTPUT_POWER, TX_TIMEOUT ); 13 | } 14 | void setup() { 15 | // put your setup code here, to run once: 16 | Serial.begin(115200); 17 | Mcu.begin(); 18 | RadioEvents.TxTimeout = OnRadioTxTimeout; 19 | Radio.Init( &RadioEvents ); 20 | 21 | Radio.SetTxContinuousWave( RF_FREQUENCY, TX_OUTPUT_POWER, TX_TIMEOUT ); 22 | } 23 | 24 | void loop() { 25 | // put your main code here, to run repeatedly: 26 | Radio.IrqProcess( ); 27 | } -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2022 Emanuele Iannone 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /src/ESP32_Mcu.h: -------------------------------------------------------------------------------- 1 | #ifndef McuSet_H 2 | #define McuSet_H 3 | 4 | #include 5 | #include "SPI.h" 6 | #include "driver/rtc-board.h" 7 | #include "driver/board-config.h" 8 | #include "driver/lorawan_spi.h" 9 | 10 | 11 | #define LORA_DEFAULT_NSS_PIN 18 12 | #define LORA_DEFAULT_RESET_PIN 14 13 | #define LORA_DEFAULT_DIO0_PIN 26 14 | #define LORA_DEFAULT_DIO1_PIN 33 15 | #define Timer_DEFAULT_DIV 80 16 | extern uint8_t mcuStarted; 17 | class McuClass{ 18 | public: 19 | McuClass(); 20 | void setlicense(uint32_t * license); 21 | int begin(); 22 | void setSPIFrequency(uint32_t frequency); 23 | void sleep(uint8_t classMode,uint8_t debugLevel); 24 | SPISettings _spiSettings; 25 | private: 26 | 27 | }; 28 | extern TimerEvent_t TxNextPacketTimer; 29 | 30 | #ifdef __cplusplus 31 | extern "C" uint8_t SpiInOut(Spi_t *obj, uint8_t outData ); 32 | extern "C" void lora_printf(const char *format, ...); 33 | extern "C" uint64_t timercheck(); 34 | extern "C" uint64_t getID(); 35 | extern "C" void SX126xIoInit( void ); 36 | extern "C" void SX126xReset( void ); 37 | extern "C" void sx126xSleep( void ); 38 | #endif 39 | 40 | extern McuClass Mcu; 41 | #endif 42 | -------------------------------------------------------------------------------- /src/loramac/Commissioning.h: -------------------------------------------------------------------------------- 1 | /*! 2 | * \file Commissioning.h 3 | * 4 | * \brief End device commissioning parameters 5 | * 6 | * \copyright Revised BSD License, see section \ref LICENSE. 7 | * 8 | * \code 9 | * ______ _ 10 | * / _____) _ | | 11 | * ( (____ _____ ____ _| |_ _____ ____| |__ 12 | * \____ \| ___ | (_ _) ___ |/ ___) _ \ 13 | * _____) ) ____| | | || |_| ____( (___| | | | 14 | * (______/|_____)_|_|_| \__)_____)\____)_| |_| 15 | * (C)2013-2017 Semtech 16 | * 17 | * \endcode 18 | * 19 | * \author Miguel Luis ( Semtech ) 20 | * 21 | * \author Gregory Cristian ( Semtech ) 22 | */ 23 | #ifndef __LORA_COMMISSIONING_H__ 24 | #define __LORA_COMMISSIONING_H__ 25 | 26 | /*! 27 | * User application data buffer size 28 | */ 29 | 30 | #define LORAWAN_APP_DATA_MAX_SIZE 255 31 | 32 | /*! 33 | * Indicates if the end-device is to be connected to a private or public network 34 | */ 35 | #define LORAWAN_PUBLIC_NETWORK true 36 | 37 | /*! 38 | * Current network ID 39 | */ 40 | #define LORAWAN_NETWORK_ID ( uint32_t )0 41 | 42 | 43 | #endif // __LORA_COMMISSIONING_H__ 44 | -------------------------------------------------------------------------------- /src/driver/gpio-board.c: -------------------------------------------------------------------------------- 1 | /*! 2 | * \file gpio-board.c 3 | * 4 | * \brief Target board GPIO driver implementation 5 | * 6 | * \copyright Revised BSD License, see section \ref LICENSE. 7 | * 8 | * \code 9 | * ______ _ 10 | * / _____) _ | | 11 | * ( (____ _____ ____ _| |_ _____ ____| |__ 12 | * \____ \| ___ | (_ _) ___ |/ ___) _ \ 13 | * _____) ) ____| | | || |_| ____( (___| | | | 14 | * (______/|_____)_|_|_| \__)_____)\____)_| |_| 15 | * (C)2013-2017 Semtech 16 | * 17 | * \endcode 18 | * 19 | * \author Miguel Luis ( Semtech ) 20 | * 21 | * \author Gregory Cristian ( Semtech ) 22 | */ 23 | #include "../loramac/utilities.h" 24 | #include "../driver/rtc-board.h" 25 | #include "../driver/gpio-board.h" 26 | 27 | 28 | static GpioIrqHandler *GpioIrq[16]; 29 | 30 | void GpioMcuInit( Gpio_t *obj, uint8_t pin, uint8_t mode, PinConfigs config, PinTypes type, uint32_t value ) 31 | { 32 | obj->pin = pin; 33 | pinMode(pin,mode); 34 | if( mode == OUTPUT ) 35 | { 36 | GpioMcuWrite( obj, value ); 37 | } 38 | } 39 | 40 | void GpioMcuSetInterrupt( Gpio_t *obj, int irqMode, IrqPriorities irqPriority, GpioIrqHandler *irqHandler ) 41 | { 42 | attachInterrupt(obj->pin,irqHandler,RISING); 43 | } 44 | 45 | void GpioMcuRemoveInterrupt( Gpio_t *obj ) 46 | { 47 | detachInterrupt(obj->pin); 48 | } 49 | 50 | void GpioMcuWrite( Gpio_t *obj, uint32_t value ) 51 | { 52 | digitalWrite(obj->pin,value); 53 | } 54 | 55 | void GpioMcuToggle( Gpio_t *obj ) 56 | { 57 | 58 | } 59 | 60 | uint32_t GpioMcuRead( Gpio_t *obj ) 61 | { 62 | return digitalRead(obj->pin); 63 | } 64 | -------------------------------------------------------------------------------- /src/driver/gpio.c: -------------------------------------------------------------------------------- 1 | /*! 2 | * \file gpio.c 3 | * 4 | * \brief GPIO driver implementation 5 | * 6 | * \remark: Relies on the specific board GPIO implementation as well as on 7 | * IO expander driver implementation if one is available on the target 8 | * board. 9 | * 10 | * \copyright Revised BSD License, see section \ref LICENSE. 11 | * 12 | * \code 13 | * ______ _ 14 | * / _____) _ | | 15 | * ( (____ _____ ____ _| |_ _____ ____| |__ 16 | * \____ \| ___ | (_ _) ___ |/ ___) _ \ 17 | * _____) ) ____| | | || |_| ____( (___| | | | 18 | * (______/|_____)_|_|_| \__)_____)\____)_| |_| 19 | * (C)2013-2017 Semtech 20 | * 21 | * \endcode 22 | * 23 | * \author Miguel Luis ( Semtech ) 24 | * 25 | * \author Gregory Cristian ( Semtech ) 26 | */ 27 | #include "../driver/gpio-board.h" 28 | 29 | void GpioInit( Gpio_t *obj, uint8_t pin, uint8_t mode, PinConfigs config, PinTypes type, uint32_t value ) 30 | { 31 | GpioMcuInit( obj, pin, mode, config, type, value ); 32 | } 33 | 34 | void GpioSetInterrupt( Gpio_t *obj, IrqModes irqMode, IrqPriorities irqPriority, GpioIrqHandler *irqHandler ) 35 | { 36 | GpioMcuSetInterrupt( obj, irqMode, irqPriority, irqHandler ); 37 | } 38 | 39 | void GpioRemoveInterrupt( Gpio_t *obj ) 40 | { 41 | GpioMcuRemoveInterrupt( obj ); 42 | } 43 | 44 | void GpioWrite( Gpio_t *obj, uint32_t value ) 45 | { 46 | GpioMcuWrite( obj, value ); 47 | } 48 | 49 | void GpioToggle( Gpio_t *obj ) 50 | { 51 | GpioMcuToggle( obj ); 52 | } 53 | 54 | uint32_t GpioRead( Gpio_t *obj ) 55 | { 56 | return GpioMcuRead( obj ); 57 | } 58 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Heltec Esp32 LoRaWan library 2 | This is a Platformio library for Heltec ESP32 boards with integrated LoRa transceivers. 3 | The code is directly ported from the original Heltec Arduino library: https://github.com/Heltec-Aaron-Lee/WiFi_Kit_series 4 | 5 | As the specific [LoRaWan Platformio library](https://registry.platformio.org/libraries/heltecautomation/ESP32_LoRaWAN) seems no more being maintained, and it is not compatible with espressif32 platform versions higher than 3.5.0, I decided to create this new library. 6 | 7 | ## Supported boards 8 | - Heltec WiFi LoRa 32 ([V1](https://docs.platformio.org/en/latest/boards/espressif32/heltec_wifi_lora_32.html), [V2](https://docs.platformio.org/en/latest/boards/espressif32/heltec_wifi_lora_32_V2.html) and [V3](https://docs.platformio.org/en/latest/boards/espressif32/heltec_wifi_lora_32_V3.html)) 9 | - [Heltec Wireless Stick](https://docs.platformio.org/en/latest/boards/espressif32/heltec_wireless_stick.html) 10 | - [Heltec Wireless Stick Lite](https://docs.platformio.org/en/latest/boards/espressif32/heltec_wireless_stick_lite.html), including V3 11 | 12 | ## Configuration 13 | You need to define some constants in the `build_flags` option inside `platformio.ini` file. 14 | 15 | ```ini 16 | [env:esp32] 17 | platform = espressif32 18 | framework = arduino 19 | build_flags = 20 | -D LoRaWAN_DEBUG_LEVEL=3 21 | -D LORAWAN_PREAMBLE_LENGTH=8 22 | -D REGION_EU433 23 | -lheltec 24 | ``` 25 | 26 | When using ESP32-S3 devices, such as WiFi LoRa 32 V3 or Heltec Wireless Stick Lite V3, you need to replace flag `-lheltec` with -`-lheltec_s3`. 27 | 28 | To show debug information about LoRa activity on the embedded Oled screen, you can optionally add the `LORA_DISPLAY` constant: 29 | ```ini 30 | build_flags = 31 | -D LoRaWAN_DEBUG_LEVEL=3 32 | -D LORAWAN_PREAMBLE_LENGTH=8 33 | -D REGION_EU433 34 | -lheltec 35 | -D LORA_DISPLAY 36 | ``` 37 | In this case, you need to add also the Oled library [Heltec_Esp32_Display](https://registry.platformio.org/libraries/eiannone/Heltec_Esp32_Display) to the project dependencies. -------------------------------------------------------------------------------- /src/driver/lorawan_spi.h: -------------------------------------------------------------------------------- 1 | /*! 2 | * \file spi-board.h 3 | * 4 | * \brief SPI driver implementation 5 | * 6 | * \copyright Revised BSD License, see section \ref LICENSE. 7 | * 8 | * \code 9 | * ______ _ 10 | * / _____) _ | | 11 | * ( (____ _____ ____ _| |_ _____ ____| |__ 12 | * \____ \| ___ | (_ _) ___ |/ ___) _ \ 13 | * _____) ) ____| | | || |_| ____( (___| | | | 14 | * (______/|_____)_|_|_| \__)_____)\____)_| |_| 15 | * (C)2013-2017 Semtech 16 | * 17 | * \endcode 18 | * 19 | * \author Miguel Luis ( Semtech ) 20 | * 21 | * \author Gregory Cristian ( Semtech ) 22 | */ 23 | #ifndef __Lorawan_SPI_H__ 24 | #define __Lorawan_SPI_H__ 25 | 26 | #include "../driver/gpio.h" 27 | 28 | /*! 29 | * SPI peripheral ID 30 | */ 31 | typedef enum 32 | { 33 | SPI_1, 34 | SPI_2, 35 | }SpiId_t; 36 | 37 | /*! 38 | * SPI object type definition 39 | */ 40 | typedef struct Spi_s 41 | { 42 | SpiId_t SpiId; 43 | Gpio_t Mosi; 44 | Gpio_t Miso; 45 | Gpio_t Sclk; 46 | Gpio_t Nss; 47 | }Spi_t; 48 | 49 | /*! 50 | * \brief Initializes the SPI object and MCU peripheral 51 | * 52 | * \remark When NSS pin is software controlled set the pin name to NC otherwise 53 | * set the pin name to be used. 54 | * 55 | * \param [IN] obj SPI object 56 | * \param [IN] mosi SPI MOSI pin name to be used 57 | * \param [IN] miso SPI MISO pin name to be used 58 | * \param [IN] sclk SPI SCLK pin name to be used 59 | * \param [IN] nss SPI NSS pin name to be used 60 | */ 61 | void SpiInit( Spi_t *obj, SpiId_t spiId, uint8_t mosi, uint8_t miso, uint8_t sclk, uint8_t nss ); 62 | 63 | /*! 64 | * \brief De-initializes the SPI object and MCU peripheral 65 | * 66 | * \param [IN] obj SPI object 67 | */ 68 | void SpiDeInit( Spi_t *obj ); 69 | 70 | /*! 71 | * \brief Configures the SPI peripheral 72 | * 73 | * \remark Slave mode isn't currently handled 74 | * 75 | * \param [IN] obj SPI object 76 | * \param [IN] bits Number of bits to be used. [8 or 16] 77 | * \param [IN] cpol Clock polarity 78 | * \param [IN] cpha Clock phase 79 | * \param [IN] slave When set the peripheral acts in slave mode 80 | */ 81 | void SpiFormat( Spi_t *obj, int8_t bits, int8_t cpol, int8_t cpha, int8_t slave ); 82 | 83 | /*! 84 | * \brief Sets the SPI speed 85 | * 86 | * \param [IN] obj SPI object 87 | * \param [IN] hz SPI clock frequency in hz 88 | */ 89 | void SpiFrequency( Spi_t *obj, uint32_t hz ); 90 | 91 | 92 | #endif // __SPI_H__ 93 | -------------------------------------------------------------------------------- /examples/LoRaBasic/LoRaReceiver/LoRaReceiver.ino: -------------------------------------------------------------------------------- 1 | #include "LoRaWan_APP.h" 2 | #include "Arduino.h" 3 | 4 | 5 | #define RF_FREQUENCY 915000000 // Hz 6 | 7 | #define TX_OUTPUT_POWER 14 // dBm 8 | 9 | #define LORA_BANDWIDTH 0 // [0: 125 kHz, 10 | // 1: 250 kHz, 11 | // 2: 500 kHz, 12 | // 3: Reserved] 13 | #define LORA_SPREADING_FACTOR 7 // [SF7..SF12] 14 | #define LORA_CODINGRATE 1 // [1: 4/5, 15 | // 2: 4/6, 16 | // 3: 4/7, 17 | // 4: 4/8] 18 | #define LORA_PREAMBLE_LENGTH 8 // Same for Tx and Rx 19 | #define LORA_SYMBOL_TIMEOUT 0 // Symbols 20 | #define LORA_FIX_LENGTH_PAYLOAD_ON false 21 | #define LORA_IQ_INVERSION_ON false 22 | 23 | 24 | #define RX_TIMEOUT_VALUE 1000 25 | #define BUFFER_SIZE 30 // Define the payload size here 26 | 27 | char txpacket[BUFFER_SIZE]; 28 | char rxpacket[BUFFER_SIZE]; 29 | 30 | static RadioEvents_t RadioEvents; 31 | 32 | int16_t txNumber; 33 | 34 | int16_t rssi,rxSize; 35 | 36 | bool lora_idle = true; 37 | 38 | void setup() { 39 | Serial.begin(115200); 40 | Mcu.begin(); 41 | 42 | txNumber=0; 43 | rssi=0; 44 | 45 | RadioEvents.RxDone = OnRxDone; 46 | Radio.Init( &RadioEvents ); 47 | Radio.SetChannel( RF_FREQUENCY ); 48 | Radio.SetRxConfig( MODEM_LORA, LORA_BANDWIDTH, LORA_SPREADING_FACTOR, 49 | LORA_CODINGRATE, 0, LORA_PREAMBLE_LENGTH, 50 | LORA_SYMBOL_TIMEOUT, LORA_FIX_LENGTH_PAYLOAD_ON, 51 | 0, true, 0, 0, LORA_IQ_INVERSION_ON, true ); 52 | } 53 | 54 | 55 | 56 | void loop() 57 | { 58 | if(lora_idle) 59 | { 60 | lora_idle = false; 61 | Serial.println("into RX mode"); 62 | Radio.Rx(0); 63 | } 64 | Radio.IrqProcess( ); 65 | } 66 | 67 | void OnRxDone( uint8_t *payload, uint16_t size, int16_t rssi, int8_t snr ) 68 | { 69 | rssi=rssi; 70 | rxSize=size; 71 | memcpy(rxpacket, payload, size ); 72 | rxpacket[size]='\0'; 73 | Radio.Sleep( ); 74 | Serial.printf("\r\nreceived packet \"%s\" with rssi %d , length %d\r\n",rxpacket,rssi,rxSize); 75 | lora_idle = true; 76 | } -------------------------------------------------------------------------------- /examples/LoRaBasic/LoRaSender/LoRaSender.ino: -------------------------------------------------------------------------------- 1 | #include "LoRaWan_APP.h" 2 | #include "Arduino.h" 3 | 4 | 5 | #define RF_FREQUENCY 915000000 // Hz 6 | 7 | #define TX_OUTPUT_POWER 5 // dBm 8 | 9 | #define LORA_BANDWIDTH 0 // [0: 125 kHz, 10 | // 1: 250 kHz, 11 | // 2: 500 kHz, 12 | // 3: Reserved] 13 | #define LORA_SPREADING_FACTOR 7 // [SF7..SF12] 14 | #define LORA_CODINGRATE 1 // [1: 4/5, 15 | // 2: 4/6, 16 | // 3: 4/7, 17 | // 4: 4/8] 18 | #define LORA_PREAMBLE_LENGTH 8 // Same for Tx and Rx 19 | #define LORA_SYMBOL_TIMEOUT 0 // Symbols 20 | #define LORA_FIX_LENGTH_PAYLOAD_ON false 21 | #define LORA_IQ_INVERSION_ON false 22 | 23 | 24 | #define RX_TIMEOUT_VALUE 1000 25 | #define BUFFER_SIZE 30 // Define the payload size here 26 | 27 | char txpacket[BUFFER_SIZE]; 28 | char rxpacket[BUFFER_SIZE]; 29 | 30 | double txNumber; 31 | 32 | bool lora_idle=true; 33 | 34 | static RadioEvents_t RadioEvents; 35 | void OnTxDone( void ); 36 | void OnTxTimeout( void ); 37 | 38 | void setup() { 39 | Serial.begin(115200); 40 | Mcu.begin(); 41 | 42 | txNumber=0; 43 | 44 | RadioEvents.TxDone = OnTxDone; 45 | RadioEvents.TxTimeout = OnTxTimeout; 46 | 47 | Radio.Init( &RadioEvents ); 48 | Radio.SetChannel( RF_FREQUENCY ); 49 | Radio.SetTxConfig( MODEM_LORA, TX_OUTPUT_POWER, 0, LORA_BANDWIDTH, 50 | LORA_SPREADING_FACTOR, LORA_CODINGRATE, 51 | LORA_PREAMBLE_LENGTH, LORA_FIX_LENGTH_PAYLOAD_ON, 52 | true, 0, 0, LORA_IQ_INVERSION_ON, 3000 ); 53 | } 54 | 55 | 56 | 57 | void loop() 58 | { 59 | if(lora_idle == true) 60 | { 61 | delay(1000); 62 | txNumber += 0.01; 63 | sprintf(txpacket,"Hello world number %0.2f",txNumber); //start a package 64 | 65 | Serial.printf("\r\nsending packet \"%s\" , length %d\r\n",txpacket, strlen(txpacket)); 66 | 67 | Radio.Send( (uint8_t *)txpacket, strlen(txpacket) ); //send the package out 68 | lora_idle = false; 69 | } 70 | Radio.IrqProcess( ); 71 | } 72 | 73 | void OnTxDone( void ) 74 | { 75 | Serial.println("TX done......"); 76 | lora_idle = true; 77 | } 78 | 79 | void OnTxTimeout( void ) 80 | { 81 | Radio.Sleep( ); 82 | Serial.println("TX Timeout......"); 83 | lora_idle = true; 84 | } -------------------------------------------------------------------------------- /src/loramac/cmac.h: -------------------------------------------------------------------------------- 1 | /************************************************************************** 2 | Copyright (C) 2009 Lander Casado, Philippas Tsigas 3 | 4 | All rights reserved. 5 | 6 | Permission is hereby granted, free of charge, to any person obtaining 7 | a copy of this software and associated documentation files 8 | (the "Software"), to deal with the Software without restriction, including 9 | without limitation the rights to use, copy, modify, merge, publish, 10 | distribute, sublicense, and/or sell copies of the Software, and to 11 | permit persons to whom the Software is furnished to do so, subject to 12 | the following conditions: 13 | 14 | Redistributions of source code must retain the above copyright notice, 15 | this list of conditions and the following disclaimers. Redistributions in 16 | binary form must reproduce the above copyright notice, this list of 17 | conditions and the following disclaimers in the documentation and/or 18 | other materials provided with the distribution. 19 | 20 | In no event shall the authors or copyright holders be liable for any special, 21 | incidental, indirect or consequential damages of any kind, or any damages 22 | whatsoever resulting from loss of use, data or profits, whether or not 23 | advised of the possibility of damage, and on any theory of liability, 24 | arising out of or in connection with the use or performance of this software. 25 | 26 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 27 | OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 28 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 29 | CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 30 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 31 | FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 32 | DEALINGS WITH THE SOFTWARE 33 | 34 | *****************************************************************************/ 35 | 36 | #ifndef _CMAC_H_ 37 | #define _CMAC_H_ 38 | 39 | #include "aes.h" 40 | 41 | #define AES_CMAC_KEY_LENGTH 16 42 | #define AES_CMAC_DIGEST_LENGTH 16 43 | 44 | typedef struct _AES_CMAC_CTX { 45 | aes_context rijndael; 46 | uint8_t X[16]; 47 | uint8_t M_last[16]; 48 | uint32_t M_n; 49 | } AES_CMAC_CTX; 50 | 51 | //#include 52 | 53 | //__BEGIN_DECLS 54 | void AES_CMAC_Init(AES_CMAC_CTX * ctx); 55 | void AES_CMAC_SetKey(AES_CMAC_CTX * ctx, const uint8_t key[AES_CMAC_KEY_LENGTH]); 56 | void AES_CMAC_Update(AES_CMAC_CTX * ctx, const uint8_t * data, uint32_t len); 57 | // __attribute__((__bounded__(__string__,2,3))); 58 | void AES_CMAC_Final(uint8_t digest[AES_CMAC_DIGEST_LENGTH], AES_CMAC_CTX * ctx); 59 | // __attribute__((__bounded__(__minbytes__,1,AES_CMAC_DIGEST_LENGTH))); 60 | //__END_DECLS 61 | 62 | #endif /* _CMAC_H_ */ 63 | 64 | -------------------------------------------------------------------------------- /src/driver/gpio-board.h: -------------------------------------------------------------------------------- 1 | /*! 2 | * \file gpio-board.h 3 | * 4 | * \brief Target board GPIO driver implementation 5 | * 6 | * \copyright Revised BSD License, see section \ref LICENSE. 7 | * 8 | * \code 9 | * ______ _ 10 | * / _____) _ | | 11 | * ( (____ _____ ____ _| |_ _____ ____| |__ 12 | * \____ \| ___ | (_ _) ___ |/ ___) _ \ 13 | * _____) ) ____| | | || |_| ____( (___| | | | 14 | * (______/|_____)_|_|_| \__)_____)\____)_| |_| 15 | * (C)2013-2017 Semtech 16 | * 17 | * \endcode 18 | * 19 | * \author Miguel Luis ( Semtech ) 20 | * 21 | * \author Gregory Cristian ( Semtech ) 22 | */ 23 | #ifndef __GPIO_BOARD_H__ 24 | #define __GPIO_BOARD_H__ 25 | 26 | #include "gpio.h" 27 | 28 | /*! 29 | * \brief Initializes the given GPIO object 30 | * 31 | * \param [IN] obj Pointer to the GPIO object 32 | * \param [IN] pin Pin name ( please look in pinName-board.h file ) 33 | * \param [IN] mode Pin mode [PIN_INPUT, PIN_OUTPUT, 34 | * PIN_ALTERNATE_FCT, PIN_ANALOGIC] 35 | * \param [IN] config Pin config [PIN_PUSH_PULL, PIN_OPEN_DRAIN] 36 | * \param [IN] type Pin type [PIN_NO_PULL, PIN_PULL_UP, PIN_PULL_DOWN] 37 | * \param [IN] value Default output value at initialization 38 | */ 39 | void GpioMcuInit( Gpio_t *obj, uint8_t pin, uint8_t mode, PinConfigs config, PinTypes type, uint32_t value ); 40 | 41 | /*! 42 | * \brief GPIO IRQ Initialization 43 | * 44 | * \param [IN] obj Pointer to the GPIO object 45 | * \param [IN] irqMode IRQ mode [NO_IRQ, IRQ_RISING_EDGE, 46 | * IRQ_FALLING_EDGE, IRQ_RISING_FALLING_EDGE] 47 | * \param [IN] irqPriority IRQ priority [IRQ_VERY_LOW_PRIORITY, IRQ_LOW_PRIORITY 48 | * IRQ_MEDIUM_PRIORITY, IRQ_HIGH_PRIORITY 49 | * IRQ_VERY_HIGH_PRIORITY] 50 | * \param [IN] irqHandler Callback function pointer 51 | */ 52 | void GpioMcuSetInterrupt( Gpio_t *obj, int irqMode, IrqPriorities irqPriority, GpioIrqHandler *irqHandler ); 53 | 54 | /*! 55 | * \brief Removes the interrupt from the object 56 | * 57 | * \param [IN] obj Pointer to the GPIO object 58 | */ 59 | void GpioMcuRemoveInterrupt( Gpio_t *obj ); 60 | 61 | /*! 62 | * \brief Writes the given value to the GPIO output 63 | * 64 | * \param [IN] obj Pointer to the GPIO object 65 | * \param [IN] value New GPIO output value 66 | */ 67 | void GpioMcuWrite( Gpio_t *obj, uint32_t value ); 68 | 69 | /*! 70 | * \brief Toggle the value to the GPIO output 71 | * 72 | * \param [IN] obj Pointer to the GPIO object 73 | */ 74 | void GpioMcuToggle( Gpio_t *obj ); 75 | 76 | /*! 77 | * \brief Reads the current GPIO input value 78 | * 79 | * \param [IN] obj Pointer to the GPIO object 80 | * \retval value Current GPIO input value 81 | */ 82 | uint32_t GpioMcuRead( Gpio_t *obj ); 83 | 84 | #endif // __GPIO_BOARD_H__ 85 | -------------------------------------------------------------------------------- /src/LoRaWan_APP.h: -------------------------------------------------------------------------------- 1 | #ifndef LoRaWan_APP_H 2 | #define LoRaWan_APP_H 3 | 4 | #include "ESP32_Mcu.h" 5 | #include 6 | #include "loramac/LoRaMac.h" 7 | #include "loramac/utilities.h" 8 | #include "ESP32_LoRaWan_102.h" 9 | #include "HardwareSerial.h" 10 | #include "Arduino.h" 11 | #include "driver/board.h" 12 | #include "driver/debug.h" 13 | 14 | #if defined(__asr650x__) 15 | #include "board.h" 16 | #include "gpio.h" 17 | #include "hw.h" 18 | #include "low_power.h" 19 | #include "spi-board.h" 20 | #include "rtc-board.h" 21 | #include "asr_timer.h" 22 | #include "board-config.h" 23 | #include "hw_conf.h" 24 | #include 25 | #endif 26 | 27 | enum eDeviceState_LoraWan 28 | { 29 | DEVICE_STATE_INIT, 30 | DEVICE_STATE_JOIN, 31 | DEVICE_STATE_SEND, 32 | DEVICE_STATE_CYCLE, 33 | DEVICE_STATE_SLEEP 34 | }; 35 | 36 | enum eDeviceState_Lora 37 | { 38 | LORA_INIT, 39 | LORA_SEND, 40 | LORA_RECEIVE, 41 | LORA_CAD, 42 | MCU_SLEEP, 43 | }; 44 | 45 | 46 | extern uint8_t devEui[]; 47 | extern uint8_t appEui[]; 48 | extern uint8_t appKey[]; 49 | extern uint8_t nwkSKey[]; 50 | extern uint8_t appSKey[]; 51 | extern uint32_t devAddr; 52 | extern uint8_t appData[LORAWAN_APP_DATA_MAX_SIZE]; 53 | extern uint8_t appDataSize; 54 | extern uint8_t appPort; 55 | extern uint32_t txDutyCycleTime; 56 | extern bool overTheAirActivation; 57 | extern LoRaMacRegion_t loraWanRegion; 58 | extern bool loraWanAdr; 59 | extern bool isTxConfirmed; 60 | extern uint32_t appTxDutyCycle; 61 | extern DeviceClass_t loraWanClass; 62 | extern bool passthroughMode; 63 | extern uint8_t confirmedNbTrials; 64 | extern bool modeLoraWan; 65 | extern bool keepNet; 66 | extern uint16_t userChannelsMask[6]; 67 | 68 | /*! 69 | * Defines a random delay for application data transmission duty cycle. 1s, 70 | * value in [ms]. 71 | */ 72 | #define APP_TX_DUTYCYCLE_RND 1000 73 | 74 | class LoRaWanClass{ 75 | public: 76 | void init(DeviceClass_t lorawanClass,LoRaMacRegion_t region); 77 | void join(); 78 | void send(); 79 | void cycle(uint32_t dutyCycle); 80 | void sleep(DeviceClass_t classMode); 81 | void setDataRateForNoADR(int8_t dataRate); 82 | void ifskipjoin(); 83 | void generateDeveuiByChipID(); 84 | 85 | #if defined(LORA_DISPLAY) 86 | void displayJoining(); 87 | void displayJoined(); 88 | void displaySending(); 89 | void displayAck(); 90 | void displayMcuInit(); 91 | #endif 92 | }; 93 | 94 | extern enum eDeviceState_LoraWan deviceState; 95 | 96 | extern "C" bool SendFrame( void ); 97 | extern "C" void turnOnRGB(uint32_t color,uint32_t time); 98 | extern "C" void turnOffRGB(void); 99 | extern "C" bool checkUserAt(char * cmd, char * content); 100 | extern "C" void downLinkAckHandle(); 101 | extern "C" void downLinkDataHandle(McpsIndication_t *mcpsIndication); 102 | extern "C" void lwan_dev_params_update( void ); 103 | extern "C" void dev_time_updated( void ); 104 | 105 | 106 | extern LoRaWanClass LoRaWAN; 107 | 108 | #endif 109 | -------------------------------------------------------------------------------- /src/loramac/LoRaMacTest.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2015-2017 Alibaba Group Holding Limited 3 | */ 4 | 5 | /*! 6 | * \file LoRaMacTest.h 7 | * 8 | * \brief LoRa MAC layer test function implementation 9 | * 10 | * \copyright Revised BSD License, see section \ref LICENSE. 11 | * 12 | * \code 13 | * ______ _ 14 | * / _____) _ | | 15 | * ( (____ _____ ____ _| |_ _____ ____| |__ 16 | * \____ \| ___ | (_ _) ___ |/ ___) _ \ 17 | * _____) ) ____| | | || |_| ____( (___| | | | 18 | * (______/|_____)_|_|_| \__)_____)\____)_| |_| 19 | * (C)2013 Semtech 20 | * 21 | * ___ _____ _ ___ _ _____ ___ ___ ___ ___ 22 | * / __|_ _/_\ / __| |/ / __/ _ \| _ \/ __| __| 23 | * \__ \ | |/ _ \ (__| ' <| _| (_) | / (__| _| 24 | * |___/ |_/_/ \_\___|_|\_\_| \___/|_|_\\___|___| 25 | * embedded.connectivity.solutions=============== 26 | * 27 | * \endcode 28 | * 29 | * \author Miguel Luis ( Semtech ) 30 | * 31 | * \author Gregory Cristian ( Semtech ) 32 | * 33 | * \author Daniel Jaeckle ( STACKFORCE ) 34 | * 35 | * \defgroup LORAMACTEST LoRa MAC layer test function implementation 36 | * This module specifies the API implementation of test function of the LoRaMAC layer. 37 | * The functions in this file are only for testing purposes only. 38 | * \{ 39 | */ 40 | #ifndef __LORAMACTEST_H__ 41 | #define __LORAMACTEST_H__ 42 | 43 | /*! 44 | * \brief Enabled or disables the reception windows 45 | * 46 | * \details This is a test function. It shall be used for testing purposes only. 47 | * Changing this attribute may lead to a non-conformance LoRaMac operation. 48 | * 49 | * \param [IN] enable - Enabled or disables the reception windows 50 | */ 51 | void LoRaMacTestRxWindowsOn( bool enable ); 52 | 53 | /*! 54 | * \brief Enables the MIC field test 55 | * 56 | * \details This is a test function. It shall be used for testing purposes only. 57 | * Changing this attribute may lead to a non-conformance LoRaMac operation. 58 | * 59 | * \param [IN] txPacketCounter - Fixed Tx packet counter value 60 | */ 61 | void LoRaMacTestSetMic( uint16_t txPacketCounter ); 62 | 63 | /*! 64 | * \brief Enabled or disables the duty cycle 65 | * 66 | * \details This is a test function. It shall be used for testing purposes only. 67 | * Changing this attribute may lead to a non-conformance LoRaMac operation. 68 | * 69 | * \param [IN] enable - Enabled or disables the duty cycle 70 | */ 71 | void LoRaMacTestSetDutyCycleOn( bool enable ); 72 | 73 | /*! 74 | * \brief Sets the channel index 75 | * 76 | * \details This is a test function. It shall be used for testing purposes only. 77 | * Changing this attribute may lead to a non-conformance LoRaMac operation. 78 | * 79 | * \param [IN] channel - Channel index 80 | */ 81 | void LoRaMacTestSetChannel( uint8_t channel ); 82 | 83 | /*! \} defgroup LORAMACTEST */ 84 | 85 | #endif // __LORAMACTEST_H__ 86 | -------------------------------------------------------------------------------- /src/driver/board-config.h: -------------------------------------------------------------------------------- 1 | /*! 2 | * \file board-config.h 3 | * 4 | * \brief Board configuration 5 | * 6 | * \copyright Revised BSD License, see section \ref LICENSE. 7 | * 8 | * \code 9 | * ______ _ 10 | * / _____) _ | | 11 | * ( (____ _____ ____ _| |_ _____ ____| |__ 12 | * \____ \| ___ | (_ _) ___ |/ ___) _ \ 13 | * _____) ) ____| | | || |_| ____( (___| | | | 14 | * (______/|_____)_|_|_| \__)_____)\____)_| |_| 15 | * (C)2013-2017 Semtech 16 | * 17 | * ___ _____ _ ___ _ _____ ___ ___ ___ ___ 18 | * / __|_ _/_\ / __| |/ / __/ _ \| _ \/ __| __| 19 | * \__ \ | |/ _ \ (__| ' <| _| (_) | / (__| _| 20 | * |___/ |_/_/ \_\___|_|\_\_| \___/|_|_\\___|___| 21 | * embedded.connectivity.solutions=============== 22 | * 23 | * \endcode 24 | * 25 | * \author Miguel Luis ( Semtech ) 26 | * 27 | * \author Gregory Cristian ( Semtech ) 28 | * 29 | * \author Daniel Jaeckle ( STACKFORCE ) 30 | * 31 | * \author Johannes Bruder ( STACKFORCE ) 32 | */ 33 | #ifndef __BOARD_CONFIG_H__ 34 | #define __BOARD_CONFIG_H__ 35 | 36 | #include "Arduino.h" 37 | 38 | /*! 39 | * Defines the time required for the TCXO to wakeup [ms]. 40 | */ 41 | 42 | #define BOARD_TCXO_WAKEUP_TIME 5 43 | 44 | #if defined(WIFI_LoRa_32_V3)||defined(Wireless_Track)||(Wireless_Stick_V3)||defined(Wireless_Stick_Lite_V3) 45 | 46 | #define RADIO_DIO_1 14 47 | #define RADIO_NSS 8 48 | #define RADIO_RESET 12 49 | #define RADIO_BUSY 13 50 | 51 | #define LORA_CLK 9 52 | #define LORA_MISO 11 53 | #define LORA_MOSI 10 54 | 55 | #elif defined(WIFI_LoRa_32_V2)||defined(Wireless_Stick)||defined(Wireless_Stick_Lite)||defined(Wireless_Bridge) 56 | #define RADIO_RESET 14 57 | 58 | #define LORA_MOSI 27 59 | #define LORA_MISO 19 60 | #define LORA_CLK 5 61 | #define RADIO_NSS 18 62 | 63 | #define RADIO_DIO_0 26 64 | #define RADIO_DIO_1 35 // GPIO35 -- SX127x's IRQ(Interrupt Request) V2 65 | 66 | 67 | #elif defined(WIFI_LoRa_32_SX1262) 68 | #define RADIO_DIO_1 35 69 | #define RADIO_NSS 14 70 | #define RADIO_RESET 5 71 | #define RADIO_BUSY 34 72 | 73 | #define LORA_CLK 12 74 | #define LORA_MISO 15 75 | #define LORA_MOSI 13 76 | 77 | #elif defined(WIFI_LoRa_32) 78 | #define RADIO_RESET 14 79 | 80 | #define LORA_MOSI 27 81 | #define LORA_MISO 19 82 | #define LORA_CLK 5 83 | #define RADIO_NSS 18 84 | 85 | #define RADIO_DIO_0 26 86 | #define RADIO_DIO_1 33 // GPIO35 -- SX127x's IRQ(Interrupt Request) V2 87 | #else 88 | 89 | #define RADIO_DIO_1 3 90 | #define RADIO_NSS 8 91 | #define RADIO_RESET 5 92 | #define RADIO_BUSY 4 93 | 94 | #define LORA_CLK 10 95 | #define LORA_MISO 6 96 | #define LORA_MOSI 7 97 | #endif 98 | 99 | 100 | #endif // __BOARD_CONFIG_H__ 101 | -------------------------------------------------------------------------------- /src/loramac/LoRaMacClassBConfig.h: -------------------------------------------------------------------------------- 1 | /*! 2 | * \file LoRaMacClassBConfig.h 3 | * 4 | * \brief LoRa MAC Class B configuration 5 | * 6 | * \copyright Revised BSD License, see section \ref LICENSE. 7 | * 8 | * \code 9 | * ______ _ 10 | * / _____) _ | | 11 | * ( (____ _____ ____ _| |_ _____ ____| |__ 12 | * \____ \| ___ | (_ _) ___ |/ ___) _ \ 13 | * _____) ) ____| | | || |_| ____( (___| | | | 14 | * (______/|_____)_|_|_| \__)_____)\____)_| |_| 15 | * (C)2013 Semtech 16 | * 17 | * ___ _____ _ ___ _ _____ ___ ___ ___ ___ 18 | * / __|_ _/_\ / __| |/ / __/ _ \| _ \/ __| __| 19 | * \__ \ | |/ _ \ (__| ' <| _| (_) | / (__| _| 20 | * |___/ |_/_/ \_\___|_|\_\_| \___/|_|_\\___|___| 21 | * embedded.connectivity.solutions=============== 22 | * 23 | * \endcode 24 | * 25 | * \author Miguel Luis ( Semtech ) 26 | * 27 | * \author Gregory Cristian ( Semtech ) 28 | * 29 | * \author Daniel Jaeckle ( STACKFORCE ) 30 | * 31 | * \defgroup LORAMACCLASSB LoRa MAC Class B configuration 32 | * This header file contains parameters to configure the class b operation. 33 | * By default, all parameters are set according to the specification. 34 | * \{ 35 | */ 36 | #ifndef __LORAMACCLASSBCONFIG_H__ 37 | #define __LORAMACCLASSBCONFIG_H__ 38 | 39 | /*! 40 | * Defines the beacon interval in ms 41 | */ 42 | #define CLASSB_BEACON_INTERVAL 128000 43 | 44 | /*! 45 | * Beacon reserved time in ms 46 | */ 47 | #define CLASSB_BEACON_RESERVED 2120 48 | 49 | /*! 50 | * Beacon guard time in ms 51 | */ 52 | #define CLASSB_BEACON_GUARD 3000 53 | 54 | /*! 55 | * Beacon window time in ms 56 | */ 57 | #define CLASSB_BEACON_WINDOW 122880 58 | 59 | /*! 60 | * Beacon window time in numer of slots 61 | */ 62 | #define CLASSB_BEACON_WINDOW_SLOTS 4096 63 | 64 | /*! 65 | * Ping slot length time in ms 66 | */ 67 | #define CLASSB_PING_SLOT_WINDOW 30 68 | 69 | /*! 70 | * Maximum allowed beacon less time in ms 71 | */ 72 | #define CLASSB_MAX_BEACON_LESS_PERIOD 7200000 73 | 74 | /*! 75 | * Delay time for the BeaconTimingAns in ms 76 | */ 77 | #define CLASSB_BEACON_DELAY_BEACON_TIMING_ANS 30 78 | 79 | /*! 80 | * Default symbol timeout for beacons and ping slot windows 81 | */ 82 | #define CLASSB_BEACON_SYMBOL_TO_DEFAULT 8 83 | 84 | /*! 85 | * Maximum symbol timeout for beacons 86 | */ 87 | #define CLASSB_BEACON_SYMBOL_TO_EXPANSION_MAX 255 88 | 89 | /*! 90 | * Maximum symbol timeout for ping slots 91 | */ 92 | #define CLASSB_PING_SLOT_SYMBOL_TO_EXPANSION_MAX 30 93 | 94 | /*! 95 | * Symbol expansion value for beacon windows in case of beacon 96 | * loss in symbols 97 | */ 98 | #define CLASSB_BEACON_SYMBOL_TO_EXPANSION_FACTOR 2 99 | 100 | /*! 101 | * Defines the default window movement time 102 | */ 103 | #define CLASSB_WINDOW_MOVE_DEFAULT 2 104 | 105 | /*! 106 | * Defines the maximum time for the beacon movement 107 | */ 108 | #define CLASSB_WINDOW_MOVE_EXPANSION_MAX 256 109 | 110 | /*! 111 | * Defines the expansion factor for the beacon movement 112 | */ 113 | #define CLASSB_WINDOW_MOVE_EXPANSION_FACTOR 2 114 | 115 | #endif // __LORAMACCLASSBCONFIG_H__ 116 | -------------------------------------------------------------------------------- /src/driver/rtc-board.h: -------------------------------------------------------------------------------- 1 | /*! 2 | * \file rtc-board.h 3 | * 4 | * \brief Target board RTC timer and low power modes management 5 | * 6 | * \copyright Revised BSD License, see section \ref LICENSE. 7 | * 8 | * \code 9 | * ______ _ 10 | * / _____) _ | | 11 | * ( (____ _____ ____ _| |_ _____ ____| |__ 12 | * \____ \| ___ | (_ _) ___ |/ ___) _ \ 13 | * _____) ) ____| | | || |_| ____( (___| | | | 14 | * (______/|_____)_|_|_| \__)_____)\____)_| |_| 15 | * (C)2013-2017 Semtech 16 | * 17 | * \endcode 18 | * 19 | * \author Miguel Luis ( Semtech ) 20 | * 21 | * \author Gregory Cristian ( Semtech ) 22 | */ 23 | #ifndef __RTC_BOARD_H__ 24 | #define __RTC_BOARD_H__ 25 | 26 | #ifdef __cplusplus 27 | extern "C"{ 28 | #endif 29 | 30 | #include 31 | #include 32 | #include "../driver/timer.h" 33 | #include "Arduino.h" 34 | 35 | extern uint64_t alarmTime; 36 | 37 | /*! 38 | * \brief Timer time variable definition 39 | */ 40 | //#ifndef TimerTime_t 41 | //typedef uint64_t TimerTime_t; 42 | //#endif 43 | 44 | /*! 45 | * \brief Initializes the RTC timer 46 | * 47 | * \remark The timer is based on the RTC 48 | */ 49 | void RtcInit( void ); 50 | 51 | /*! 52 | * \brief Start the RTC timer 53 | * 54 | * \remark The timer is based on the RTC Alarm running at 32.768KHz 55 | * 56 | * \param[IN] timeout Duration of the Timer 57 | */ 58 | void RtcSetTimeout( uint32_t timeout ); 59 | 60 | void RtcStopTimeout( void ); 61 | 62 | TimerTime_t RtcGetTimerContext( void ); 63 | 64 | TimerTime_t RtcSetTimerContext( void ); 65 | 66 | TimerTime_t RtcGetElapsedTime( void ); 67 | 68 | 69 | /*! 70 | * \brief Adjust the value of the timeout to handle wakeup time from Alarm and GPIO irq 71 | * 72 | * \param[IN] timeout Duration of the Timer without compensation for wakeup time 73 | * \retval new value for the Timeout with compensations 74 | */ 75 | TimerTime_t RtcGetAdjustedTimeoutValue( uint32_t timeout ); 76 | 77 | /*! 78 | * \brief Get the RTC timer value 79 | * 80 | * \retval RTC Timer value 81 | */ 82 | TimerTime_t RtcGetTimerValue( void ); 83 | 84 | /*! 85 | * \brief Get the RTC timer elapsed time since the last Alarm was set 86 | * 87 | * \retval RTC Elapsed time since the last alarm 88 | */ 89 | TimerTime_t RtcGetElapsedAlarmTime( void ); 90 | 91 | /*! 92 | * \brief Compute the timeout time of a future event in time 93 | * 94 | * \param[IN] futureEventInTime Value in time 95 | * \retval time Time between now and the futureEventInTime 96 | */ 97 | TimerTime_t RtcComputeFutureEventTime( TimerTime_t futureEventInTime ); 98 | 99 | /*! 100 | * \brief Compute the elapsed time since a fix event in time 101 | * 102 | * \param[IN] eventInTime Value in time 103 | * \retval elapsed Time since the eventInTime 104 | */ 105 | TimerTime_t RtcComputeElapsedTime( TimerTime_t eventInTime ); 106 | 107 | /*! 108 | * \brief This function blocks the MCU from going into low power mode 109 | * 110 | * \param [IN] status [true: Enable, false: Disable 111 | */ 112 | void BlockLowPowerDuringTask ( bool status ); 113 | 114 | /*! 115 | * \brief Sets the MCU into low power STOP mode 116 | */ 117 | void lowPowerHandler( void ); 118 | 119 | /*! 120 | * \brief Restore the MCU to its normal operation mode 121 | */ 122 | void RtcRecoverMcuStatus( void ); 123 | 124 | /*! 125 | * \brief Processes pending timer events 126 | */ 127 | void RtcProcess( void ); 128 | 129 | #ifdef __cplusplus 130 | } 131 | #endif 132 | 133 | #endif // __RTC_BOARD_H__ 134 | -------------------------------------------------------------------------------- /src/loramac/utilities.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2015-2017 Alibaba Group Holding Limited 3 | */ 4 | 5 | /* 6 | / _____) _ | | 7 | ( (____ _____ ____ _| |_ _____ ____| |__ 8 | \____ \| ___ | (_ _) ___ |/ ___) _ \ 9 | _____) ) ____| | | || |_| ____( (___| | | | 10 | (______/|_____)_|_|_| \__)_____)\____)_| |_| 11 | (C)2013 Semtech 12 | 13 | Description: Helper functions implementation 14 | 15 | License: Revised BSD License, see LICENSE.TXT file include in the project 16 | 17 | Maintainer: Miguel Luis and Gregory Cristian 18 | */ 19 | #include 20 | #include 21 | #include 22 | #include "../loramac/utilities.h" 23 | 24 | /*! 25 | * Redefinition of rand() and srand() standard C functions. 26 | * These functions are redefined in order to get the same behavior across 27 | * different compiler toolchains implementations. 28 | */ 29 | // Standard random functions redefinition start 30 | #define RAND_LOCAL_MAX 2147483647L 31 | 32 | static uint32_t next = 1; 33 | 34 | int32_t rand1( void ) 35 | { 36 | return ( ( next = next * 1103515245L + 12345L ) % RAND_LOCAL_MAX ); 37 | } 38 | 39 | void srand1( uint32_t seed ) 40 | { 41 | next = seed; 42 | } 43 | // Standard random functions redefinition end 44 | 45 | int32_t randr( int32_t min, int32_t max ) 46 | { 47 | return ( int32_t )rand1( ) % ( max - min + 1 ) + min; 48 | } 49 | 50 | void memcpy1( uint8_t *dst, const uint8_t *src, uint16_t size ) 51 | { 52 | while( size-- ) 53 | { 54 | *dst++ = *src++; 55 | } 56 | } 57 | 58 | void memcpyr( uint8_t *dst, const uint8_t *src, uint16_t size ) 59 | { 60 | dst = dst + ( size - 1 ); 61 | while( size-- ) 62 | { 63 | *dst-- = *src++; 64 | } 65 | } 66 | 67 | void memset1( uint8_t *dst, uint8_t value, uint16_t size ) 68 | { 69 | while( size-- ) 70 | { 71 | *dst++ = value; 72 | } 73 | } 74 | 75 | int8_t Nibble2HexChar( uint8_t a ) 76 | { 77 | if( a < 10 ) 78 | { 79 | return '0' + a; 80 | } 81 | else if( a < 16 ) 82 | { 83 | return 'A' + ( a - 10 ); 84 | } 85 | else 86 | { 87 | return '?'; 88 | } 89 | } 90 | 91 | uint32_t Crc32( uint8_t *buffer, uint16_t length ) 92 | { 93 | // The CRC calculation follows CCITT - 0x04C11DB7 94 | const uint32_t reversedPolynom = 0xEDB88320; 95 | 96 | // CRC initial value 97 | uint32_t crc = 0xFFFFFFFF; 98 | 99 | if( buffer == NULL ) 100 | { 101 | return 0; 102 | } 103 | 104 | for( uint16_t i = 0; i < length; ++i ) 105 | { 106 | crc ^= ( uint32_t )buffer[i]; 107 | for( uint16_t i = 0; i < 8; i++ ) 108 | { 109 | crc = ( crc >> 1 ) ^ ( reversedPolynom & ~( ( crc & 0x01 ) - 1 ) ); 110 | } 111 | } 112 | 113 | return ~crc; 114 | } 115 | 116 | uint32_t Crc32Init( void ) 117 | { 118 | return 0xFFFFFFFF; 119 | } 120 | 121 | uint32_t Crc32Update( uint32_t crcInit, uint8_t *buffer, uint16_t length ) 122 | { 123 | // The CRC calculation follows CCITT - 0x04C11DB7 124 | const uint32_t reversedPolynom = 0xEDB88320; 125 | 126 | // CRC initial value 127 | uint32_t crc = crcInit; 128 | 129 | if( buffer == NULL ) 130 | { 131 | return 0; 132 | } 133 | 134 | for( uint16_t i = 0; i < length; ++i ) 135 | { 136 | crc ^= ( uint32_t )buffer[i]; 137 | for( uint16_t i = 0; i < 8; i++ ) 138 | { 139 | crc = ( crc >> 1 ) ^ ( reversedPolynom & ~( ( crc & 0x01 ) - 1 ) ); 140 | } 141 | } 142 | return crc; 143 | } 144 | 145 | uint32_t Crc32Finalize( uint32_t crc ) 146 | { 147 | return ~crc; 148 | } 149 | 150 | -------------------------------------------------------------------------------- /src/driver/board.h: -------------------------------------------------------------------------------- 1 | /*! 2 | * \file board.h 3 | * 4 | * \brief Target board general functions implementation 5 | * 6 | * \copyright Revised BSD License, see section \ref LICENSE. 7 | * 8 | * \code 9 | * ______ _ 10 | * / _____) _ | | 11 | * ( (____ _____ ____ _| |_ _____ ____| |__ 12 | * \____ \| ___ | (_ _) ___ |/ ___) _ \ 13 | * _____) ) ____| | | || |_| ____( (___| | | | 14 | * (______/|_____)_|_|_| \__)_____)\____)_| |_| 15 | * (C)2013-2017 Semtech 16 | * 17 | * \endcode 18 | * 19 | * \author Miguel Luis ( Semtech ) 20 | * 21 | * \author Gregory Cristian ( Semtech ) 22 | */ 23 | #ifndef __BOARD_H__ 24 | #define __BOARD_H__ 25 | 26 | #include 27 | #include "../driver/timer.h" 28 | 29 | #ifdef __cplusplus 30 | extern "C"{ 31 | #endif 32 | 33 | /*! 34 | * Possible power sources 35 | */ 36 | enum BoardPowerSources 37 | { 38 | USB_POWER = 0, 39 | BATTERY_POWER, 40 | }; 41 | 42 | /*! 43 | * Board Version 44 | */ 45 | typedef union BoardVersion_u 46 | { 47 | struct BoardVersion_s 48 | { 49 | uint8_t Rfu; 50 | uint8_t Revision; 51 | uint8_t Minor; 52 | uint8_t Major; 53 | }Fields; 54 | uint32_t Value; 55 | }BoardVersion_t; 56 | 57 | /*! 58 | * \brief Disable interrupts 59 | * 60 | * \remark IRQ nesting is managed 61 | */ 62 | void BoardDisableIrq( void ); 63 | 64 | /*! 65 | * \brief Enable interrupts 66 | * 67 | * \remark IRQ nesting is managed 68 | */ 69 | void BoardEnableIrq( void ); 70 | 71 | /*! 72 | * \brief Initializes the mcu. 73 | */ 74 | void BoardInitMcu( void ); 75 | 76 | /*! 77 | * \brief Resets the mcu. 78 | */ 79 | void BoardResetMcu( void ); 80 | 81 | /*! 82 | * \brief Initializes the boards peripherals. 83 | */ 84 | void BoardInitPeriph( void ); 85 | 86 | /*! 87 | * \brief De-initializes the target board peripherals to decrease power 88 | * consumption. 89 | */ 90 | void BoardDeInitMcu( void ); 91 | 92 | /*! 93 | * \brief Gets the current potentiometer level value 94 | * 95 | * \retval value Potentiometer level ( value in percent ) 96 | */ 97 | uint8_t BoardGetPotiLevel( void ); 98 | 99 | /*! 100 | * \brief Measure the Battery voltage 101 | * 102 | * \retval value battery voltage in volts 103 | */ 104 | uint32_t BoardGetBatteryVoltage( void ); 105 | 106 | /*! 107 | * \brief Get the current battery level 108 | * 109 | * \retval value battery level [ 0: USB, 110 | * 1: Min level, 111 | * x: level 112 | * 254: fully charged, 113 | * 255: Error] 114 | */ 115 | uint8_t BoardGetBatteryLevel( void ); 116 | 117 | /*! 118 | * Returns a pseudo random seed generated using the MCU Unique ID 119 | * 120 | * \retval seed Generated pseudo random seed 121 | */ 122 | uint32_t BoardGetRandomSeed( void ); 123 | 124 | /*! 125 | * \brief Gets the board 64 bits unique ID 126 | * 127 | * \param [IN] id Pointer to an array that will contain the Unique ID 128 | */ 129 | void BoardGetUniqueId( uint8_t *id ); 130 | 131 | /*! 132 | * \brief Get the board power source 133 | * 134 | * \retval value power source [0: USB_POWER, 1: BATTERY_POWER] 135 | */ 136 | uint8_t GetBoardPowerSource( void ); 137 | 138 | /*! 139 | * \brief Get the board version 140 | * 141 | * \retval value Version 142 | */ 143 | BoardVersion_t BoardGetVersion( void ); 144 | 145 | 146 | #ifdef __cplusplus 147 | } // extern "C" 148 | #endif 149 | 150 | #endif // __BOARD_H__ 151 | -------------------------------------------------------------------------------- /examples/LoRaWAN/LoRaWan/LoRaWan.ino: -------------------------------------------------------------------------------- 1 | #include "LoRaWan_APP.h" 2 | 3 | /* OTAA para*/ 4 | uint8_t devEui[] = { 0x22, 0x32, 0x33, 0x00, 0x00, 0x88, 0x88, 0x02 }; 5 | uint8_t appEui[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; 6 | uint8_t appKey[] = { 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88 }; 7 | 8 | /* ABP para*/ 9 | uint8_t nwkSKey[] = { 0x15, 0xb1, 0xd0, 0xef, 0xa4, 0x63, 0xdf, 0xbe, 0x3d, 0x11, 0x18, 0x1e, 0x1e, 0xc7, 0xda,0x85 }; 10 | uint8_t appSKey[] = { 0xd7, 0x2c, 0x78, 0x75, 0x8c, 0xdc, 0xca, 0xbf, 0x55, 0xee, 0x4a, 0x77, 0x8d, 0x16, 0xef,0x67 }; 11 | uint32_t devAddr = ( uint32_t )0x007e6ae1; 12 | 13 | /*LoraWan channelsmask, default channels 0-7*/ 14 | uint16_t userChannelsMask[6]={ 0x00FF,0x0000,0x0000,0x0000,0x0000,0x0000 }; 15 | 16 | /*LoraWan region, select in arduino IDE tools*/ 17 | LoRaMacRegion_t loraWanRegion = ACTIVE_REGION; 18 | 19 | /*LoraWan Class, Class A and Class C are supported*/ 20 | DeviceClass_t loraWanClass = CLASS_A; 21 | 22 | /*the application data transmission duty cycle. value in [ms].*/ 23 | uint32_t appTxDutyCycle = 15000; 24 | 25 | /*OTAA or ABP*/ 26 | bool overTheAirActivation = true; 27 | 28 | /*ADR enable*/ 29 | bool loraWanAdr = true; 30 | 31 | /* Indicates if the node is sending confirmed or unconfirmed messages */ 32 | bool isTxConfirmed = true; 33 | 34 | /* Application port */ 35 | uint8_t appPort = 2; 36 | /*! 37 | * Number of trials to transmit the frame, if the LoRaMAC layer did not 38 | * receive an acknowledgment. The MAC performs a datarate adaptation, 39 | * according to the LoRaWAN Specification V1.0.2, chapter 18.4, according 40 | * to the following table: 41 | * 42 | * Transmission nb | Data Rate 43 | * ----------------|----------- 44 | * 1 (first) | DR 45 | * 2 | DR 46 | * 3 | max(DR-1,0) 47 | * 4 | max(DR-1,0) 48 | * 5 | max(DR-2,0) 49 | * 6 | max(DR-2,0) 50 | * 7 | max(DR-3,0) 51 | * 8 | max(DR-3,0) 52 | * 53 | * Note, that if NbTrials is set to 1 or 2, the MAC will not decrease 54 | * the datarate, in case the LoRaMAC layer did not receive an acknowledgment 55 | */ 56 | uint8_t confirmedNbTrials = 4; 57 | 58 | /* Prepares the payload of the frame */ 59 | static void prepareTxFrame( uint8_t port ) 60 | { 61 | /*appData size is LORAWAN_APP_DATA_MAX_SIZE which is defined in "commissioning.h". 62 | *appDataSize max value is LORAWAN_APP_DATA_MAX_SIZE. 63 | *if enabled AT, don't modify LORAWAN_APP_DATA_MAX_SIZE, it may cause system hanging or failure. 64 | *if disabled AT, LORAWAN_APP_DATA_MAX_SIZE can be modified, the max value is reference to lorawan region and SF. 65 | *for example, if use REGION_CN470, 66 | *the max value for different DR can be found in MaxPayloadOfDatarateCN470 refer to DataratesCN470 and BandwidthsCN470 in "RegionCN470.h". 67 | */ 68 | appDataSize = 4; 69 | appData[0] = 0x00; 70 | appData[1] = 0x01; 71 | appData[2] = 0x02; 72 | appData[3] = 0x03; 73 | } 74 | 75 | //if true, next uplink will add MOTE_MAC_DEVICE_TIME_REQ 76 | 77 | 78 | void setup() { 79 | Serial.begin(115200); 80 | Mcu.begin(); 81 | deviceState = DEVICE_STATE_INIT; 82 | } 83 | 84 | void loop() 85 | { 86 | switch( deviceState ) 87 | { 88 | case DEVICE_STATE_INIT: 89 | { 90 | #if(LORAWAN_DEVEUI_AUTO) 91 | LoRaWAN.generateDeveuiByChipID(); 92 | #endif 93 | LoRaWAN.init(loraWanClass,loraWanRegion); 94 | break; 95 | } 96 | case DEVICE_STATE_JOIN: 97 | { 98 | LoRaWAN.join(); 99 | break; 100 | } 101 | case DEVICE_STATE_SEND: 102 | { 103 | prepareTxFrame( appPort ); 104 | LoRaWAN.send(); 105 | deviceState = DEVICE_STATE_CYCLE; 106 | break; 107 | } 108 | case DEVICE_STATE_CYCLE: 109 | { 110 | // Schedule next packet transmission 111 | txDutyCycleTime = appTxDutyCycle + randr( -APP_TX_DUTYCYCLE_RND, APP_TX_DUTYCYCLE_RND ); 112 | LoRaWAN.cycle(txDutyCycleTime); 113 | deviceState = DEVICE_STATE_SLEEP; 114 | break; 115 | } 116 | case DEVICE_STATE_SLEEP: 117 | { 118 | LoRaWAN.sleep(loraWanClass); 119 | break; 120 | } 121 | default: 122 | { 123 | deviceState = DEVICE_STATE_INIT; 124 | break; 125 | } 126 | } 127 | } 128 | -------------------------------------------------------------------------------- /examples/LoRaWAN/LoRaWan_interrupt/LoRaWan_interrupt.ino: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #define INT_PIN 0 4 | 5 | /* OTAA para*/ 6 | uint8_t devEui[] = { 0x22, 0x32, 0x33, 0x00, 0x00, 0x88, 0x88, 0x02 }; 7 | uint8_t appEui[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; 8 | uint8_t appKey[] = { 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88 }; 9 | 10 | /* ABP para*/ 11 | uint8_t nwkSKey[] = { 0x15, 0xb1, 0xd0, 0xef, 0xa4, 0x63, 0xdf, 0xbe, 0x3d, 0x11, 0x18, 0x1e, 0x1e, 0xc7, 0xda,0x85 }; 12 | uint8_t appSKey[] = { 0xd7, 0x2c, 0x78, 0x75, 0x8c, 0xdc, 0xca, 0xbf, 0x55, 0xee, 0x4a, 0x77, 0x8d, 0x16, 0xef,0x67 }; 13 | uint32_t devAddr = ( uint32_t )0x007e6ae1; 14 | 15 | /*LoraWan channelsmask, default channels 0-7*/ 16 | uint16_t userChannelsMask[6]={ 0x00FF,0x0000,0x0000,0x0000,0x0000,0x0000 }; 17 | 18 | /*LoraWan region, select in arduino IDE tools*/ 19 | LoRaMacRegion_t loraWanRegion = ACTIVE_REGION; 20 | 21 | /*LoraWan Class, Class A and Class C are supported*/ 22 | DeviceClass_t loraWanClass = CLASS_A; 23 | 24 | /*the application data transmission duty cycle. value in [ms].*/ 25 | uint32_t appTxDutyCycle = 3600*24*1000; 26 | 27 | /*OTAA or ABP*/ 28 | bool overTheAirActivation = true; 29 | 30 | /*ADR enable*/ 31 | bool loraWanAdr = true; 32 | 33 | /* Indicates if the node is sending confirmed or unconfirmed messages */ 34 | bool isTxConfirmed = true; 35 | 36 | /* Application port */ 37 | uint8_t appPort = 2; 38 | 39 | /*! 40 | * Number of trials to transmit the frame, if the LoRaMAC layer did not 41 | * receive an acknowledgment. The MAC performs a datarate adaptation, 42 | * according to the LoRaWAN Specification V1.0.2, chapter 18.4, according 43 | * to the following table: 44 | * 45 | * Transmission nb | Data Rate 46 | * ----------------|----------- 47 | * 1 (first) | DR 48 | * 2 | DR 49 | * 3 | max(DR-1,0) 50 | * 4 | max(DR-1,0) 51 | * 5 | max(DR-2,0) 52 | * 6 | max(DR-2,0) 53 | * 7 | max(DR-3,0) 54 | * 8 | max(DR-3,0) 55 | * 56 | * Note, that if NbTrials is set to 1 or 2, the MAC will not decrease 57 | * the datarate, in case the LoRaMAC layer did not receive an acknowledgment 58 | */ 59 | uint8_t confirmedNbTrials = 8; 60 | 61 | 62 | static void prepareTxFrame( uint8_t port ) 63 | { 64 | appDataSize = 4; 65 | appData[0] = 0x00; 66 | appData[1] = 0x01; 67 | appData[2] = 0x02; 68 | appData[3] = 0x03; 69 | } 70 | 71 | void keyDown() 72 | { 73 | delay(10); 74 | if(digitalRead(INT_PIN)==0 && IsLoRaMacNetworkJoined) 75 | { 76 | deviceState = DEVICE_STATE_SEND; 77 | } 78 | } 79 | 80 | void setup() { 81 | Serial.begin(115200); 82 | Mcu.begin(); 83 | if(loraWanClass==CLASS_C) 84 | { 85 | pinMode(INT_PIN,INPUT); 86 | attachInterrupt(INT_PIN,keyDown,FALLING); 87 | } 88 | deviceState = DEVICE_STATE_INIT; 89 | } 90 | 91 | // The loop function is called in an endless loop 92 | void loop() 93 | { 94 | switch( deviceState ) 95 | { 96 | case DEVICE_STATE_INIT: 97 | { 98 | #if(LORAWAN_DEVEUI_AUTO) 99 | LoRaWAN.generateDeveuiByChipID(); 100 | #endif 101 | LoRaWAN.init(loraWanClass,loraWanRegion); 102 | break; 103 | } 104 | case DEVICE_STATE_JOIN: 105 | { 106 | LoRaWAN.join(); 107 | break; 108 | } 109 | case DEVICE_STATE_SEND: 110 | { 111 | prepareTxFrame( appPort ); 112 | LoRaWAN.send(); 113 | deviceState = DEVICE_STATE_CYCLE; 114 | break; 115 | } 116 | case DEVICE_STATE_CYCLE: 117 | { 118 | // Schedule next packet transmission 119 | txDutyCycleTime = appTxDutyCycle + randr( -APP_TX_DUTYCYCLE_RND, APP_TX_DUTYCYCLE_RND ); 120 | LoRaWAN.cycle(txDutyCycleTime); 121 | deviceState = DEVICE_STATE_SLEEP; 122 | break; 123 | } 124 | case DEVICE_STATE_SLEEP: 125 | { 126 | if(loraWanClass==CLASS_A) 127 | { 128 | #ifdef Wireless_Mini_Shell 129 | esp_deep_sleep_enable_gpio_wakeup(1< 31 | 32 | 33 | /*! 34 | * Add a pull-up, a pull-down or nothing on the GPIO line 35 | */ 36 | typedef enum 37 | { 38 | PIN_NO_PULL = 0, 39 | PIN_PULL_UP, 40 | PIN_PULL_DOWN 41 | }PinTypes; 42 | 43 | /*! 44 | * Define the GPIO as Push-pull type or Open Drain 45 | */ 46 | typedef enum 47 | { 48 | PIN_PUSH_PULL = 0, 49 | PIN_OPEN_DRAIN 50 | }PinConfigs; 51 | 52 | /*! 53 | * Define the GPIO IRQ on a rising, falling or both edges 54 | */ 55 | typedef enum 56 | { 57 | NO_IRQ = 0, 58 | IRQ_RISING_EDGE, 59 | IRQ_FALLING_EDGE, 60 | IRQ_RISING_FALLING_EDGE 61 | }IrqModes; 62 | 63 | /*! 64 | * Define the IRQ priority on the GPIO 65 | */ 66 | typedef enum 67 | { 68 | IRQ_VERY_LOW_PRIORITY = 0, 69 | IRQ_LOW_PRIORITY, 70 | IRQ_MEDIUM_PRIORITY, 71 | IRQ_HIGH_PRIORITY, 72 | IRQ_VERY_HIGH_PRIORITY 73 | }IrqPriorities; 74 | 75 | /*! 76 | * Structure for the GPIO 77 | */ 78 | typedef struct 79 | { 80 | uint8_t pin; 81 | uint16_t pinIndex; 82 | void *port; 83 | uint16_t portIndex; 84 | PinTypes pull; 85 | }Gpio_t; 86 | 87 | /*! 88 | * GPIO IRQ handler function prototype 89 | */ 90 | typedef void( GpioIrqHandler )( void ); 91 | 92 | /*! 93 | * GPIO Expander IRQ handler function prototype 94 | */ 95 | typedef void( GpioIoeIrqHandler )( void ); 96 | 97 | /*! 98 | * \brief Initializes the given GPIO object 99 | * 100 | * \param [IN] obj Pointer to the GPIO object 101 | * \param [IN] pin Pin name ( please look in pinName-board.h file ) 102 | * \param [IN] mode Pin mode [PIN_INPUT, PIN_OUTPUT, 103 | * PIN_ALTERNATE_FCT, PIN_ANALOGIC] 104 | * \param [IN] config Pin config [PIN_PUSH_PULL, PIN_OPEN_DRAIN] 105 | * \param [IN] type Pin type [PIN_NO_PULL, PIN_PULL_UP, PIN_PULL_DOWN] 106 | * \param [IN] value Default output value at initialization 107 | */ 108 | void GpioInit( Gpio_t *obj, uint8_t pin, uint8_t mode, PinConfigs config, PinTypes type, uint32_t value ); 109 | 110 | /*! 111 | * \brief GPIO IRQ Initialization 112 | * 113 | * \param [IN] obj Pointer to the GPIO object 114 | * \param [IN] irqMode IRQ mode [NO_IRQ, IRQ_RISING_EDGE, 115 | * IRQ_FALLING_EDGE, IRQ_RISING_FALLING_EDGE] 116 | * \param [IN] irqPriority IRQ priority [IRQ_VERY_LOW_PRIORITY, IRQ_LOW_PRIORITY 117 | * IRQ_MEDIUM_PRIORITY, IRQ_HIGH_PRIORITY 118 | * IRQ_VERY_HIGH_PRIORITY] 119 | * \param [IN] irqHandler Callback function pointer 120 | */ 121 | void GpioSetInterrupt( Gpio_t *obj, IrqModes irqMode, IrqPriorities irqPriority, GpioIrqHandler *irqHandler ); 122 | 123 | /*! 124 | * \brief Removes the interrupt from the object 125 | * 126 | * \param [IN] obj Pointer to the GPIO object 127 | */ 128 | void GpioRemoveInterrupt( Gpio_t *obj ); 129 | 130 | /*! 131 | * \brief Writes the given value to the GPIO output 132 | * 133 | * \param [IN] obj Pointer to the GPIO object 134 | * \param [IN] value New GPIO output value 135 | */ 136 | void GpioWrite( Gpio_t *obj, uint32_t value ); 137 | 138 | /*! 139 | * \brief Toggle the value to the GPIO output 140 | * 141 | * \param [IN] obj Pointer to the GPIO object 142 | */ 143 | void GpioToggle( Gpio_t *obj ); 144 | 145 | /*! 146 | * \brief Reads the current GPIO input value 147 | * 148 | * \param [IN] obj Pointer to the GPIO object 149 | * \retval value Current GPIO input value 150 | */ 151 | uint32_t GpioRead( Gpio_t *obj ); 152 | 153 | #endif // __GPIO_H__ 154 | -------------------------------------------------------------------------------- /src/driver/sx1276-board.h: -------------------------------------------------------------------------------- 1 | /*! 2 | * \file sx1276-board.h 3 | * 4 | * \brief Target board SX1276 driver implementation 5 | * 6 | * \copyright Revised BSD License, see section \ref LICENSE. 7 | * 8 | * \code 9 | * ______ _ 10 | * / _____) _ | | 11 | * ( (____ _____ ____ _| |_ _____ ____| |__ 12 | * \____ \| ___ | (_ _) ___ |/ ___) _ \ 13 | * _____) ) ____| | | || |_| ____( (___| | | | 14 | * (______/|_____)_|_|_| \__)_____)\____)_| |_| 15 | * (C)2013-2017 Semtech 16 | * 17 | * \endcode 18 | * 19 | * \author Miguel Luis ( Semtech ) 20 | * 21 | * \author Gregory Cristian ( Semtech ) 22 | */ 23 | #ifndef __SX1276_BOARD_H__ 24 | #define __SX1276_BOARD_H__ 25 | 26 | #include 27 | #include 28 | #include "../driver/sx1276.h" 29 | 30 | /*! 31 | * \brief Radio hardware registers initialization definition 32 | * 33 | * \remark Can be automatically generated by the SX1276 GUI (not yet implemented) 34 | */ 35 | #define RADIO_INIT_REGISTERS_VALUE \ 36 | { \ 37 | { MODEM_FSK , REG_LNA , 0x23 },\ 38 | { MODEM_FSK , REG_RXCONFIG , 0x1E },\ 39 | { MODEM_FSK , REG_RSSICONFIG , 0xD2 },\ 40 | { MODEM_FSK , REG_AFCFEI , 0x01 },\ 41 | { MODEM_FSK , REG_PREAMBLEDETECT , 0xAA },\ 42 | { MODEM_FSK , REG_OSC , 0x07 },\ 43 | { MODEM_FSK , REG_SYNCCONFIG , 0x12 },\ 44 | { MODEM_FSK , REG_SYNCVALUE1 , 0xC1 },\ 45 | { MODEM_FSK , REG_SYNCVALUE2 , 0x94 },\ 46 | { MODEM_FSK , REG_SYNCVALUE3 , 0xC1 },\ 47 | { MODEM_FSK , REG_PACKETCONFIG1 , 0xD8 },\ 48 | { MODEM_FSK , REG_FIFOTHRESH , 0x8F },\ 49 | { MODEM_FSK , REG_IMAGECAL , 0x02 },\ 50 | { MODEM_FSK , REG_DIOMAPPING1 , 0x00 },\ 51 | { MODEM_FSK , REG_DIOMAPPING2 , 0x30 },\ 52 | { MODEM_LORA, REG_LR_PAYLOADMAXLENGTH, 0xFF },\ 53 | } \ 54 | 55 | #define RF_MID_BAND_THRESH 525000000 56 | 57 | /*! 58 | * \brief Initializes the radio I/Os pins interface 59 | */ 60 | void SX1276IoInit( void ); 61 | 62 | /*! 63 | * \brief Initializes DIO IRQ handlers 64 | * 65 | * \param [IN] irqHandlers Array containing the IRQ callback functions 66 | */ 67 | void SX1276IoIrqInit( DioIrqHandler **irqHandlers ); 68 | 69 | /*! 70 | * \brief De-initializes the radio I/Os pins interface. 71 | * 72 | * \remark Useful when going in MCU low power modes 73 | */ 74 | void SX1276IoDeInit( void ); 75 | 76 | /*! 77 | * \brief Resets the radio 78 | */ 79 | void SX1276Reset( void ); 80 | 81 | /*! 82 | * \brief Sets the radio output power. 83 | * 84 | * \param [IN] power Sets the RF output power 85 | */ 86 | void SX1276SetRfTxPower( int8_t power ); 87 | 88 | /*! 89 | * \brief Gets the board PA selection configuration 90 | * 91 | * \param [IN] channel Channel frequency in Hz 92 | * \retval PaSelect RegPaConfig PaSelect value 93 | */ 94 | uint8_t SX1276GetPaSelect( uint32_t channel ); 95 | 96 | /*! 97 | * \brief Set the RF Switch I/Os pins in low power mode 98 | * 99 | * \param [IN] status enable or disable 100 | */ 101 | void SX1276SetAntSwLowPower( bool status ); 102 | 103 | /*! 104 | * \brief Initializes the RF Switch I/Os pins interface 105 | */ 106 | void SX1276AntSwInit( void ); 107 | 108 | /*! 109 | * \brief De-initializes the RF Switch I/Os pins interface 110 | * 111 | * \remark Needed to decrease the power consumption in MCU low power modes 112 | */ 113 | void SX1276AntSwDeInit( void ); 114 | 115 | /*! 116 | * \brief Controls the antenna switch if necessary. 117 | * 118 | * \remark see errata note 119 | * 120 | * \param [IN] opMode Current radio operating mode 121 | */ 122 | void SX1276SetAntSw( uint8_t opMode ); 123 | 124 | /*! 125 | * \brief Checks if the given RF frequency is supported by the hardware 126 | * 127 | * \param [IN] frequency RF frequency to be checked 128 | * \retval isSupported [true: supported, false: unsupported] 129 | */ 130 | bool SX1276CheckRfFrequency( uint32_t frequency ); 131 | 132 | /*! 133 | * \brief Gets the Defines the time required for the TCXO to wakeup [ms]. 134 | * 135 | * \retval time Board TCXO wakeup time in ms. 136 | */ 137 | uint32_t SX1276GetBoardTcxoWakeupTime( void ); 138 | 139 | /*! 140 | * Radio hardware and global parameters 141 | */ 142 | extern SX1276_t SX1276; 143 | 144 | #endif // __SX1276_BOARD_H__ 145 | -------------------------------------------------------------------------------- /src/driver/sx126x-board.h: -------------------------------------------------------------------------------- 1 | /*! 2 | * \file sx126x-board.h 3 | * 4 | * \brief Target board SX126x driver implementation 5 | * 6 | * \copyright Revised BSD License, see section \ref LICENSE. 7 | * 8 | * \code 9 | * ______ _ 10 | * / _____) _ | | 11 | * ( (____ _____ ____ _| |_ _____ ____| |__ 12 | * \____ \| ___ | (_ _) ___ |/ ___) _ \ 13 | * _____) ) ____| | | || |_| ____( (___| | | | 14 | * (______/|_____)_|_|_| \__)_____)\____)_| |_| 15 | * (C)2013-2017 Semtech 16 | * 17 | * \endcode 18 | * 19 | * \author Miguel Luis ( Semtech ) 20 | * 21 | * \author Gregory Cristian ( Semtech ) 22 | */ 23 | #ifndef __SX126x_BOARD_H__ 24 | #define __SX126x_BOARD_H__ 25 | 26 | #include 27 | #include 28 | #include "../driver/sx126x.h" 29 | 30 | 31 | #ifdef __cplusplus 32 | extern "C" { 33 | #endif 34 | 35 | 36 | void SX126xLoracInit(); 37 | 38 | /*! 39 | * \brief Initializes the radio I/Os pins interface 40 | */ 41 | void SX126xIoInit( void ); 42 | 43 | /*! 44 | * \brief Initializes DIO IRQ handlers 45 | * 46 | * \param [IN] irqHandlers Array containing the IRQ callback functions 47 | */ 48 | void SX126xIoIrqInit( DioIrqHandler dioIrq ); 49 | 50 | /*! 51 | * \brief De-initializes the radio I/Os pins interface. 52 | * 53 | * \remark Useful when going in MCU low power modes 54 | */ 55 | void SX126xIoDeInit( void ); 56 | 57 | /*! 58 | * \brief HW Reset of the radio 59 | */ 60 | void SX126xReset( void ); 61 | 62 | /*! 63 | * \brief Blocking loop to wait while the Busy pin in high 64 | */ 65 | void SX126xWaitOnBusy( void ); 66 | 67 | /*! 68 | * \brief Wakes up the radio 69 | */ 70 | void SX126xWakeup( void ); 71 | 72 | /*! 73 | * \brief Send a command that write data to the radio 74 | * 75 | * \param [in] opcode Opcode of the command 76 | * \param [in] buffer Buffer to be send to the radio 77 | * \param [in] size Size of the buffer to send 78 | */ 79 | void SX126xWriteCommand( RadioCommands_t opcode, uint8_t *buffer, uint16_t size ); 80 | 81 | /*! 82 | * \brief Send a command that read data from the radio 83 | * 84 | * \param [in] opcode Opcode of the command 85 | * \param [out] buffer Buffer holding data from the radio 86 | * \param [in] size Size of the buffer 87 | */ 88 | void SX126xReadCommand( RadioCommands_t opcode, uint8_t *buffer, uint16_t size ); 89 | 90 | /*! 91 | * \brief Write a single byte of data to the radio memory 92 | * 93 | * \param [in] address The address of the first byte to write in the radio 94 | * \param [in] value The data to be written in radio's memory 95 | */ 96 | void SX126xWriteRegister( uint16_t address, uint8_t value ); 97 | 98 | /*! 99 | * \brief Read a single byte of data from the radio memory 100 | * 101 | * \param [in] address The address of the first byte to write in the radio 102 | * 103 | * \retval value The value of the byte at the given address in radio's memory 104 | */ 105 | uint8_t SX126xReadRegister( uint16_t address ); 106 | 107 | /*! 108 | * \brief Sets the radio output power. 109 | * 110 | * \param [IN] power Sets the RF output power 111 | */ 112 | void SX126xSetRfTxPower( int8_t power ); 113 | 114 | /*! 115 | * \brief Gets the board PA selection configuration 116 | * 117 | * \param [IN] channel Channel frequency in Hz 118 | * \retval PaSelect RegPaConfig PaSelect value 119 | */ 120 | uint8_t SX126xGetPaSelect( uint32_t channel ); 121 | 122 | /*! 123 | * \brief Initializes the RF Switch I/Os pins interface 124 | */ 125 | void SX126xAntSwOn( void ); 126 | 127 | /*! 128 | * \brief De-initializes the RF Switch I/Os pins interface 129 | * 130 | * \remark Needed to decrease the power consumption in MCU low power modes 131 | */ 132 | void SX126xAntSwOff( void ); 133 | 134 | /*! 135 | * \brief Checks if the given RF frequency is supported by the hardware 136 | * 137 | * \param [IN] frequency RF frequency to be checked 138 | * \retval isSupported [true: supported, false: unsupported] 139 | */ 140 | bool SX126xCheckRfFrequency( uint32_t frequency ); 141 | 142 | /*! 143 | * \brief Gets the Defines the time required for the TCXO to wakeup [ms]. 144 | * 145 | * \retval time Board TCXO wakeup time in ms. 146 | */ 147 | uint32_t SX126xGetBoardTcxoWakeupTime( void ); 148 | 149 | 150 | uint8_t SX126xGetPaOpt( void ); 151 | 152 | void SX126xSetPaOpt( uint8_t opt ); 153 | 154 | bool BoardDisableIrq( void ); 155 | 156 | void BoardEnableIrq(void); 157 | 158 | /*! 159 | * Radio hardware and global parameters 160 | */ 161 | extern SX126x_t SX126x; 162 | 163 | 164 | #ifdef __cplusplus 165 | } 166 | #endif 167 | 168 | #endif // __SX126x_BOARD_H__ 169 | -------------------------------------------------------------------------------- /examples/LoRaWAN/LoRaWan_multicast/LoRaWan_multicast.ino: -------------------------------------------------------------------------------- 1 | #include "LoRaWan_APP.h" 2 | 3 | /* OTAA para*/ 4 | uint8_t devEui[] = { 0x22, 0x32, 0x33, 0x00, 0x00, 0x88, 0x88, 0x02 }; 5 | uint8_t appEui[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; 6 | uint8_t appKey[] = { 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88 }; 7 | 8 | /* ABP para*/ 9 | uint8_t nwkSKey[] = { 0x15, 0xb1, 0xd0, 0xef, 0xa4, 0x63, 0xdf, 0xbe, 0x3d, 0x11, 0x18, 0x1e, 0x1e, 0xc7, 0xda,0x85 }; 10 | uint8_t appSKey[] = { 0xd7, 0x2c, 0x78, 0x75, 0x8c, 0xdc, 0xca, 0xbf, 0x55, 0xee, 0x4a, 0x77, 0x8d, 0x16, 0xef,0x67 }; 11 | uint32_t devAddr = ( uint32_t )0x007e6ae1; 12 | 13 | MulticastParams_t mult1; 14 | uint8_t mulNwkSKey[]={0x5c,0x1d,0xce,0x81,0xd8,0x19,0x40,0xb9,0xe0,0xfb,0x1e,0x07,0xdd,0x4d,0xd3,0x9c}; 15 | uint8_t mulAppSKey[]={0x6b,0x5b,0x47,0x6f,0x73,0xb6,0xc3,0x98,0xc8,0x11,0xa8,0xd0,0xd9,0x9f,0x25,0xc7}; 16 | uint32_t multicastAddress=0x00638f9e; 17 | 18 | 19 | /*LoraWan channelsmask, default channels 0-7*/ 20 | uint16_t userChannelsMask[6]={ 0x00FF,0x0000,0x0000,0x0000,0x0000,0x0000 }; 21 | 22 | /*LoraWan region, select in arduino IDE tools*/ 23 | LoRaMacRegion_t loraWanRegion = ACTIVE_REGION; 24 | 25 | /*LoraWan Class, Class A and Class C are supported*/ 26 | DeviceClass_t loraWanClass = CLASS_A; 27 | 28 | /*the application data transmission duty cycle. value in [ms].*/ 29 | uint32_t appTxDutyCycle = 15000; 30 | 31 | /*OTAA or ABP*/ 32 | bool overTheAirActivation = true; 33 | 34 | /*ADR enable*/ 35 | bool loraWanAdr = true; 36 | 37 | /* Indicates if the node is sending confirmed or unconfirmed messages */ 38 | bool isTxConfirmed = true; 39 | 40 | /* Application port */ 41 | uint8_t appPort = 2; 42 | /*! 43 | * Number of trials to transmit the frame, if the LoRaMAC layer did not 44 | * receive an acknowledgment. The MAC performs a datarate adaptation, 45 | * according to the LoRaWAN Specification V1.0.2, chapter 18.4, according 46 | * to the following table: 47 | * 48 | * Transmission nb | Data Rate 49 | * ----------------|----------- 50 | * 1 (first) | DR 51 | * 2 | DR 52 | * 3 | max(DR-1,0) 53 | * 4 | max(DR-1,0) 54 | * 5 | max(DR-2,0) 55 | * 6 | max(DR-2,0) 56 | * 7 | max(DR-3,0) 57 | * 8 | max(DR-3,0) 58 | * 59 | * Note, that if NbTrials is set to 1 or 2, the MAC will not decrease 60 | * the datarate, in case the LoRaMAC layer did not receive an acknowledgment 61 | */ 62 | uint8_t confirmedNbTrials = 4; 63 | 64 | /* Prepares the payload of the frame */ 65 | static void prepareTxFrame( uint8_t port ) 66 | { 67 | /*appData size is LORAWAN_APP_DATA_MAX_SIZE which is defined in "commissioning.h". 68 | *appDataSize max value is LORAWAN_APP_DATA_MAX_SIZE. 69 | *if enabled AT, don't modify LORAWAN_APP_DATA_MAX_SIZE, it may cause system hanging or failure. 70 | *if disabled AT, LORAWAN_APP_DATA_MAX_SIZE can be modified, the max value is reference to lorawan region and SF. 71 | *for example, if use REGION_CN470, 72 | *the max value for different DR can be found in MaxPayloadOfDatarateCN470 refer to DataratesCN470 and BandwidthsCN470 in "RegionCN470.h". 73 | */ 74 | appDataSize = 4; 75 | appData[0] = 0x00; 76 | appData[1] = 0x01; 77 | appData[2] = 0x02; 78 | appData[3] = 0x03; 79 | } 80 | 81 | //if true, next uplink will add MOTE_MAC_DEVICE_TIME_REQ 82 | 83 | 84 | void setup() { 85 | Serial.begin(115200); 86 | Mcu.begin(); 87 | deviceState = DEVICE_STATE_INIT; 88 | //add multicast 89 | mult1.Address=multicastAddress; 90 | for(int i=0;i<16;i++) 91 | { 92 | mult1.NwkSKey[i]=mulNwkSKey[i]; 93 | mult1.AppSKey[i]=mulAppSKey[i]; 94 | } 95 | LoRaMacMulticastChannelLink(&mult1); 96 | 97 | } 98 | 99 | void loop() 100 | { 101 | switch( deviceState ) 102 | { 103 | case DEVICE_STATE_INIT: 104 | { 105 | #if(LORAWAN_DEVEUI_AUTO) 106 | LoRaWAN.generateDeveuiByChipID(); 107 | #endif 108 | LoRaWAN.init(loraWanClass,loraWanRegion); 109 | break; 110 | } 111 | case DEVICE_STATE_JOIN: 112 | { 113 | LoRaWAN.join(); 114 | break; 115 | } 116 | case DEVICE_STATE_SEND: 117 | { 118 | prepareTxFrame( appPort ); 119 | LoRaWAN.send(); 120 | deviceState = DEVICE_STATE_CYCLE; 121 | break; 122 | } 123 | case DEVICE_STATE_CYCLE: 124 | { 125 | // Schedule next packet transmission 126 | txDutyCycleTime = appTxDutyCycle + randr( -APP_TX_DUTYCYCLE_RND, APP_TX_DUTYCYCLE_RND ); 127 | LoRaWAN.cycle(txDutyCycleTime); 128 | deviceState = DEVICE_STATE_SLEEP; 129 | break; 130 | } 131 | case DEVICE_STATE_SLEEP: 132 | { 133 | LoRaWAN.sleep(loraWanClass); 134 | break; 135 | } 136 | default: 137 | { 138 | deviceState = DEVICE_STATE_INIT; 139 | break; 140 | } 141 | } 142 | } -------------------------------------------------------------------------------- /src/driver/debug.h: -------------------------------------------------------------------------------- 1 | /****************************************************************************** 2 | * @file debug.h 3 | * @author MCD Application Team 4 | * @version V1.1.1 5 | * @date 01-June-2017 6 | * @brief Header for driver debug.c module 7 | ****************************************************************************** 8 | * @attention 9 | * 10 | *

© Copyright (c) 2017 STMicroelectronics International N.V. 11 | * All rights reserved.

12 | * 13 | * Redistribution and use in source and binary forms, with or without 14 | * modification, are permitted, provided that the following conditions are met: 15 | * 16 | * 1. Redistribution of source code must retain the above copyright notice, 17 | * this list of conditions and the following disclaimer. 18 | * 2. Redistributions in binary form must reproduce the above copyright notice, 19 | * this list of conditions and the following disclaimer in the documentation 20 | * and/or other materials provided with the distribution. 21 | * 3. Neither the name of STMicroelectronics nor the names of other 22 | * contributors to this software may be used to endorse or promote products 23 | * derived from this software without specific written permission. 24 | * 4. This software, including modifications and/or derivative works of this 25 | * software, must execute solely and exclusively on microcontroller or 26 | * microprocessor devices manufactured by or for STMicroelectronics. 27 | * 5. Redistribution and use of this software other than as permitted under 28 | * this license is void and will automatically terminate your rights under 29 | * this license. 30 | * 31 | * THIS SOFTWARE IS PROVIDED BY STMICROELECTRONICS AND CONTRIBUTORS "AS IS" 32 | * AND ANY EXPRESS, IMPLIED OR STATUTORY WARRANTIES, INCLUDING, BUT NOT 33 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A 34 | * PARTICULAR PURPOSE AND NON-INFRINGEMENT OF THIRD PARTY INTELLECTUAL PROPERTY 35 | * RIGHTS ARE DISCLAIMED TO THE FULLEST EXTENT PERMITTED BY LAW. IN NO EVENT 36 | * SHALL STMICROELECTRONICS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 37 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 38 | * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, 39 | * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 40 | * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 41 | * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, 42 | * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 43 | * 44 | ****************************************************************************** 45 | */ 46 | 47 | /* Define to prevent recursive inclusion -------------------------------------*/ 48 | #ifndef __DEBUG_H__ 49 | #define __DEBUG_H__ 50 | 51 | /* Includes ------------------------------------------------------------------*/ 52 | #include 53 | //#include 54 | #include "../loramac/utilities.h" 55 | 56 | /* Exported types ------------------------------------------------------------*/ 57 | /* Exported constants --------------------------------------------------------*/ 58 | /* External variables --------------------------------------------------------*/ 59 | /* Exported macros -----------------------------------------------------------*/ 60 | typedef enum LOG_LEVEL_E { 61 | LL_NONE, 62 | LL_ERR, 63 | LL_WARN, 64 | LL_DEBUG, 65 | LL_VDEBUG, 66 | LL_ALL 67 | } LOG_LEVEL; 68 | 69 | 70 | #ifdef __cplusplus 71 | extern "C" { 72 | #endif 73 | 74 | extern void lora_printf(const char *format, ...); 75 | 76 | #ifdef __cplusplus 77 | } 78 | #endif 79 | //#define LoRaWAN_DEBUG_LEVEL 2 80 | 81 | #define ERR_PRINTF(format, ...) do {}while(0) 82 | #define WARN_PRINTF(format, ...) do {}while(0) 83 | #define VDBG_PRINTF(format, ...) do {}while(0) 84 | #define PRINTF_RAW(...) 85 | #define PRINTF_AT(...) 86 | #define DBG_PRINTF_CRITICAL(p) 87 | #define LORAWANLOG do {}while(0) 88 | //#define LORAWANLOG lora_printf("[LoRaWan Log] ") 89 | #if LoRaWAN_DEBUG_LEVEL >= 2 90 | #define FREQ_PRINTF(format, ...) LORAWANLOG;lora_printf(format, ##__VA_ARGS__) 91 | #define DBG_PRINTF(format, ...) lora_printf(format, ##__VA_ARGS__) 92 | #define DIO_PRINTF(format, ...) LORAWANLOG;lora_printf(format, ##__VA_ARGS__) 93 | #elif LoRaWAN_DEBUG_LEVEL == 1 94 | #define FREQ_PRINTF(format, ...) lora_printf(format, ##__VA_ARGS__) 95 | #define DBG_PRINTF(format, ...) lora_printf(format, ##__VA_ARGS__) 96 | #define DIO_PRINTF(format, ...) 97 | #else 98 | #define FREQ_PRINTF(format, ...) do {}while(0) 99 | #define DBG_PRINTF(format, ...) do {}while(0) 100 | #define DIO_PRINTF(format, ...) do {}while(0) 101 | #endif 102 | 103 | #endif /* __DEBUG_H__*/ 104 | 105 | /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ 106 | -------------------------------------------------------------------------------- /examples/LoRaWAN/LoRaWan_TimeReq/LoRaWan_TimeReq.ino: -------------------------------------------------------------------------------- 1 | #include "LoRaWan_APP.h" 2 | 3 | /* OTAA para*/ 4 | uint8_t devEui[] = { 0x22, 0x32, 0x33, 0x00, 0x00, 0x88, 0x88, 0x02 }; 5 | uint8_t appEui[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; 6 | uint8_t appKey[] = { 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x66, 0x01 }; 7 | 8 | /* ABP para*/ 9 | uint8_t nwkSKey[] = { 0x15, 0xb1, 0xd0, 0xef, 0xa4, 0x63, 0xdf, 0xbe, 0x3d, 0x11, 0x18, 0x1e, 0x1e, 0xc7, 0xda,0x85 }; 10 | uint8_t appSKey[] = { 0xd7, 0x2c, 0x78, 0x75, 0x8c, 0xdc, 0xca, 0xbf, 0x55, 0xee, 0x4a, 0x77, 0x8d, 0x16, 0xef,0x67 }; 11 | uint32_t devAddr = ( uint32_t )0x007e6ae1; 12 | 13 | /*LoraWan channelsmask, default channels 0-7*/ 14 | uint16_t userChannelsMask[6]={ 0x00FF,0x0000,0x0000,0x0000,0x0000,0x0000 }; 15 | 16 | /*LoraWan region, select in arduino IDE tools*/ 17 | LoRaMacRegion_t loraWanRegion = ACTIVE_REGION; 18 | 19 | /*LoraWan Class, Class A and Class C are supported*/ 20 | DeviceClass_t loraWanClass = CLASS_A; 21 | 22 | /*the application data transmission duty cycle. value in [ms].*/ 23 | uint32_t appTxDutyCycle = 15000; 24 | 25 | /*OTAA or ABP*/ 26 | bool overTheAirActivation = true; 27 | 28 | /*ADR enable*/ 29 | bool loraWanAdr = true; 30 | 31 | /* Indicates if the node is sending confirmed or unconfirmed messages */ 32 | bool isTxConfirmed = true; 33 | 34 | /* Application port */ 35 | uint8_t appPort = 2; 36 | /*! 37 | * Number of trials to transmit the frame, if the LoRaMAC layer did not 38 | * receive an acknowledgment. The MAC performs a datarate adaptation, 39 | * according to the LoRaWAN Specification V1.0.2, chapter 18.4, according 40 | * to the following table: 41 | * 42 | * Transmission nb | Data Rate 43 | * ----------------|----------- 44 | * 1 (first) | DR 45 | * 2 | DR 46 | * 3 | max(DR-1,0) 47 | * 4 | max(DR-1,0) 48 | * 5 | max(DR-2,0) 49 | * 6 | max(DR-2,0) 50 | * 7 | max(DR-3,0) 51 | * 8 | max(DR-3,0) 52 | * 53 | * Note, that if NbTrials is set to 1 or 2, the MAC will not decrease 54 | * the datarate, in case the LoRaMAC layer did not receive an acknowledgment 55 | */ 56 | uint8_t confirmedNbTrials = 4; 57 | 58 | /* Prepares the payload of the frame */ 59 | static void prepareTxFrame( uint8_t port ) 60 | { 61 | /*appData size is LORAWAN_APP_DATA_MAX_SIZE which is defined in "commissioning.h". 62 | *appDataSize max value is LORAWAN_APP_DATA_MAX_SIZE. 63 | *if enabled AT, don't modify LORAWAN_APP_DATA_MAX_SIZE, it may cause system hanging or failure. 64 | *if disabled AT, LORAWAN_APP_DATA_MAX_SIZE can be modified, the max value is reference to lorawan region and SF. 65 | *for example, if use REGION_CN470, 66 | *the max value for different DR can be found in MaxPayloadOfDatarateCN470 refer to DataratesCN470 and BandwidthsCN470 in "RegionCN470.h". 67 | */ 68 | appDataSize = 4; 69 | appData[0] = 0x00; 70 | appData[1] = 0x01; 71 | appData[2] = 0x02; 72 | appData[3] = 0x03; 73 | } 74 | 75 | //if true, next uplink will add MOTE_MAC_DEVICE_TIME_REQ 76 | RTC_DATA_ATTR bool timeReq = true; 77 | 78 | void dev_time_updated() 79 | { 80 | printf("Once device time updated, this function run\r\n"); 81 | } 82 | 83 | void setup() { 84 | Serial.begin(115200); 85 | Mcu.begin(); 86 | deviceState = DEVICE_STATE_INIT; 87 | } 88 | 89 | void loop() 90 | { 91 | switch( deviceState ) 92 | { 93 | case DEVICE_STATE_INIT: 94 | { 95 | #if(LORAWAN_DEVEUI_AUTO) 96 | LoRaWAN.generateDeveuiByChipID(); 97 | #endif 98 | LoRaWAN.init(loraWanClass,loraWanRegion); 99 | break; 100 | } 101 | case DEVICE_STATE_JOIN: 102 | { 103 | LoRaWAN.join(); 104 | break; 105 | } 106 | case DEVICE_STATE_SEND: 107 | { 108 | TimerSysTime_t sysTimeCurrent = TimerGetSysTime( ); 109 | Serial.printf("Unix time:%u.%d\r\n",(unsigned int)sysTimeCurrent.Seconds, sysTimeCurrent.SubSeconds); 110 | if(timeReq) 111 | { 112 | timeReq = false; 113 | MlmeReq_t mlmeReq; 114 | mlmeReq.Type = MLME_DEVICE_TIME; 115 | LoRaMacMlmeRequest( &mlmeReq ); 116 | Serial.println("This uplink added time req."); 117 | } 118 | prepareTxFrame( appPort ); 119 | LoRaWAN.send(); 120 | deviceState = DEVICE_STATE_CYCLE; 121 | break; 122 | } 123 | case DEVICE_STATE_CYCLE: 124 | { 125 | // Schedule next packet transmission 126 | txDutyCycleTime = appTxDutyCycle + randr( -APP_TX_DUTYCYCLE_RND, APP_TX_DUTYCYCLE_RND ); 127 | LoRaWAN.cycle(txDutyCycleTime); 128 | deviceState = DEVICE_STATE_SLEEP; 129 | break; 130 | } 131 | case DEVICE_STATE_SLEEP: 132 | { 133 | LoRaWAN.sleep(loraWanClass); 134 | break; 135 | } 136 | default: 137 | { 138 | deviceState = DEVICE_STATE_INIT; 139 | break; 140 | } 141 | } 142 | } -------------------------------------------------------------------------------- /examples/LoRaWAN/LoRaWan_downlinkdatahandle/LoRaWan_downlinkdatahandle.ino: -------------------------------------------------------------------------------- 1 | #include "LoRaWan_APP.h" 2 | 3 | /* OTAA para*/ 4 | uint8_t devEui[] = { 0x22, 0x32, 0x33, 0x00, 0x00, 0x88, 0x88, 0x02 }; 5 | uint8_t appEui[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; 6 | uint8_t appKey[] = { 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x66, 0x01 }; 7 | 8 | /* ABP para*/ 9 | uint8_t nwkSKey[] = { 0x15, 0xb1, 0xd0, 0xef, 0xa4, 0x63, 0xdf, 0xbe, 0x3d, 0x11, 0x18, 0x1e, 0x1e, 0xc7, 0xda,0x85 }; 10 | uint8_t appSKey[] = { 0xd7, 0x2c, 0x78, 0x75, 0x8c, 0xdc, 0xca, 0xbf, 0x55, 0xee, 0x4a, 0x77, 0x8d, 0x16, 0xef,0x67 }; 11 | uint32_t devAddr = ( uint32_t )0x007e6ae1; 12 | 13 | /*LoraWan channelsmask, default channels 0-7*/ 14 | uint16_t userChannelsMask[6]={ 0x00FF,0x0000,0x0000,0x0000,0x0000,0x0000 }; 15 | 16 | /*LoraWan region, select in arduino IDE tools*/ 17 | LoRaMacRegion_t loraWanRegion = ACTIVE_REGION; 18 | 19 | /*LoraWan Class, Class A and Class C are supported*/ 20 | DeviceClass_t loraWanClass = CLASS_A; 21 | 22 | /*the application data transmission duty cycle. value in [ms].*/ 23 | uint32_t appTxDutyCycle = 15000; 24 | 25 | /*OTAA or ABP*/ 26 | bool overTheAirActivation = true; 27 | 28 | /*ADR enable*/ 29 | bool loraWanAdr = true; 30 | 31 | /* Indicates if the node is sending confirmed or unconfirmed messages */ 32 | bool isTxConfirmed = true; 33 | 34 | /* Application port */ 35 | uint8_t appPort = 2; 36 | /*! 37 | * Number of trials to transmit the frame, if the LoRaMAC layer did not 38 | * receive an acknowledgment. The MAC performs a datarate adaptation, 39 | * according to the LoRaWAN Specification V1.0.2, chapter 18.4, according 40 | * to the following table: 41 | * 42 | * Transmission nb | Data Rate 43 | * ----------------|----------- 44 | * 1 (first) | DR 45 | * 2 | DR 46 | * 3 | max(DR-1,0) 47 | * 4 | max(DR-1,0) 48 | * 5 | max(DR-2,0) 49 | * 6 | max(DR-2,0) 50 | * 7 | max(DR-3,0) 51 | * 8 | max(DR-3,0) 52 | * 53 | * Note, that if NbTrials is set to 1 or 2, the MAC will not decrease 54 | * the datarate, in case the LoRaMAC layer did not receive an acknowledgment 55 | */ 56 | uint8_t confirmedNbTrials = 4; 57 | 58 | /* Prepares the payload of the frame */ 59 | static void prepareTxFrame( uint8_t port ) 60 | { 61 | /*appData size is LORAWAN_APP_DATA_MAX_SIZE which is defined in "commissioning.h". 62 | *appDataSize max value is LORAWAN_APP_DATA_MAX_SIZE. 63 | *if enabled AT, don't modify LORAWAN_APP_DATA_MAX_SIZE, it may cause system hanging or failure. 64 | *if disabled AT, LORAWAN_APP_DATA_MAX_SIZE can be modified, the max value is reference to lorawan region and SF. 65 | *for example, if use REGION_CN470, 66 | *the max value for different DR can be found in MaxPayloadOfDatarateCN470 refer to DataratesCN470 and BandwidthsCN470 in "RegionCN470.h". 67 | */ 68 | appDataSize = 4; 69 | appData[0] = 0x00; 70 | appData[1] = 0x01; 71 | appData[2] = 0x02; 72 | appData[3] = 0x03; 73 | } 74 | 75 | //downlink data handle function example 76 | void downLinkDataHandle(McpsIndication_t *mcpsIndication) 77 | { 78 | Serial.printf("+REV DATA:%s,RXSIZE %d,PORT %d\r\n",mcpsIndication->RxSlot?"RXWIN2":"RXWIN1",mcpsIndication->BufferSize,mcpsIndication->Port); 79 | Serial.print("+REV DATA:"); 80 | for(uint8_t i=0;iBufferSize;i++) 81 | { 82 | Serial.printf("%02X",mcpsIndication->Buffer[i]); 83 | } 84 | Serial.println(); 85 | uint32_t color=mcpsIndication->Buffer[0]<<16|mcpsIndication->Buffer[1]<<8|mcpsIndication->Buffer[2]; 86 | #if(LoraWan_RGB==1) 87 | turnOnRGB(color,5000); 88 | turnOffRGB(); 89 | #endif 90 | } 91 | 92 | void setup() { 93 | Serial.begin(115200); 94 | Mcu.begin(); 95 | deviceState = DEVICE_STATE_INIT; 96 | } 97 | 98 | void loop() 99 | { 100 | switch( deviceState ) 101 | { 102 | case DEVICE_STATE_INIT: 103 | { 104 | #if(LORAWAN_DEVEUI_AUTO) 105 | LoRaWAN.generateDeveuiByChipID(); 106 | #endif 107 | LoRaWAN.init(loraWanClass,loraWanRegion); 108 | break; 109 | } 110 | case DEVICE_STATE_JOIN: 111 | { 112 | LoRaWAN.join(); 113 | break; 114 | } 115 | case DEVICE_STATE_SEND: 116 | { 117 | prepareTxFrame( appPort ); 118 | LoRaWAN.send(); 119 | deviceState = DEVICE_STATE_CYCLE; 120 | break; 121 | } 122 | case DEVICE_STATE_CYCLE: 123 | { 124 | // Schedule next packet transmission 125 | txDutyCycleTime = appTxDutyCycle + randr( -APP_TX_DUTYCYCLE_RND, APP_TX_DUTYCYCLE_RND ); 126 | LoRaWAN.cycle(txDutyCycleTime); 127 | deviceState = DEVICE_STATE_SLEEP; 128 | break; 129 | } 130 | case DEVICE_STATE_SLEEP: 131 | { 132 | LoRaWAN.sleep(loraWanClass); 133 | break; 134 | } 135 | default: 136 | { 137 | deviceState = DEVICE_STATE_INIT; 138 | break; 139 | } 140 | } 141 | } 142 | -------------------------------------------------------------------------------- /src/loramac/LoRaMacCrypto.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2015-2017 Alibaba Group Holding Limited 3 | */ 4 | 5 | /*! 6 | * \file LoRaMacCrypto.h 7 | * 8 | * \brief LoRa MAC layer cryptography implementation 9 | * 10 | * \copyright Revised BSD License, see section \ref LICENSE. 11 | * 12 | * \code 13 | * ______ _ 14 | * / _____) _ | | 15 | * ( (____ _____ ____ _| |_ _____ ____| |__ 16 | * \____ \| ___ | (_ _) ___ |/ ___) _ \ 17 | * _____) ) ____| | | || |_| ____( (___| | | | 18 | * (______/|_____)_|_|_| \__)_____)\____)_| |_| 19 | * (C)2013 Semtech 20 | * 21 | * ___ _____ _ ___ _ _____ ___ ___ ___ ___ 22 | * / __|_ _/_\ / __| |/ / __/ _ \| _ \/ __| __| 23 | * \__ \ | |/ _ \ (__| ' <| _| (_) | / (__| _| 24 | * |___/ |_/_/ \_\___|_|\_\_| \___/|_|_\\___|___| 25 | * embedded.connectivity.solutions=============== 26 | * 27 | * \endcode 28 | * 29 | * \author Miguel Luis ( Semtech ) 30 | * 31 | * \author Gregory Cristian ( Semtech ) 32 | * 33 | * \author Daniel Jaeckle ( STACKFORCE ) 34 | * 35 | * \defgroup LORAMAC_CRYPTO LoRa MAC layer cryptography implementation 36 | * This module covers the implementation of cryptographic functions 37 | * of the LoRaMAC layer. 38 | * \{ 39 | */ 40 | #ifndef __LORAMAC_CRYPTO_H__ 41 | #define __LORAMAC_CRYPTO_H__ 42 | 43 | #ifdef __cplusplus 44 | extern "C" { 45 | #endif 46 | 47 | /*! 48 | * Computes the LoRaMAC frame MIC field 49 | * 50 | * \param [IN] buffer - Data buffer 51 | * \param [IN] size - Data buffer size 52 | * \param [IN] key - AES key to be used 53 | * \param [IN] address - Frame address 54 | * \param [IN] dir - Frame direction [0: uplink, 1: downlink] 55 | * \param [IN] sequenceCounter - Frame sequence counter 56 | * \param [OUT] mic - Computed MIC field 57 | */ 58 | void LoRaMacComputeMic( const uint8_t *buffer, uint16_t size, const uint8_t *key, uint32_t address, uint8_t dir, uint32_t sequenceCounter, uint32_t *mic ); 59 | 60 | /*! 61 | * Computes the LoRaMAC payload encryption 62 | * 63 | * \param [IN] buffer - Data buffer 64 | * \param [IN] size - Data buffer size 65 | * \param [IN] key - AES key to be used 66 | * \param [IN] address - Frame address 67 | * \param [IN] dir - Frame direction [0: uplink, 1: downlink] 68 | * \param [IN] sequenceCounter - Frame sequence counter 69 | * \param [OUT] encBuffer - Encrypted buffer 70 | */ 71 | void LoRaMacPayloadEncrypt( const uint8_t *buffer, uint16_t size, const uint8_t *key, uint32_t address, uint8_t dir, uint32_t sequenceCounter, uint8_t *encBuffer ); 72 | 73 | /*! 74 | * Computes the LoRaMAC payload decryption 75 | * 76 | * \param [IN] buffer - Data buffer 77 | * \param [IN] size - Data buffer size 78 | * \param [IN] key - AES key to be used 79 | * \param [IN] address - Frame address 80 | * \param [IN] dir - Frame direction [0: uplink, 1: downlink] 81 | * \param [IN] sequenceCounter - Frame sequence counter 82 | * \param [OUT] decBuffer - Decrypted buffer 83 | */ 84 | void LoRaMacPayloadDecrypt( const uint8_t *buffer, uint16_t size, const uint8_t *key, uint32_t address, uint8_t dir, uint32_t sequenceCounter, uint8_t *decBuffer ); 85 | 86 | /*! 87 | * Computes the LoRaMAC Join Request frame MIC field 88 | * 89 | * \param [IN] buffer - Data buffer 90 | * \param [IN] size - Data buffer size 91 | * \param [IN] key - AES key to be used 92 | * \param [OUT] mic - Computed MIC field 93 | */ 94 | void LoRaMacJoinComputeMic( const uint8_t *buffer, uint16_t size, const uint8_t *key, uint32_t *mic ); 95 | 96 | /*! 97 | * Computes the LoRaMAC join frame decryption 98 | * 99 | * \param [IN] buffer - Data buffer 100 | * \param [IN] size - Data buffer size 101 | * \param [IN] key - AES key to be used 102 | * \param [OUT] decBuffer - Decrypted buffer 103 | */ 104 | void LoRaMacJoinDecrypt( const uint8_t *buffer, uint16_t size, const uint8_t *key, uint8_t *decBuffer ); 105 | 106 | /*! 107 | * Computes the LoRaMAC join frame decryption 108 | * 109 | * \param [IN] key - AES key to be used 110 | * \param [IN] appNonce - Application nonce 111 | * \param [IN] devNonce - Device nonce 112 | * \param [OUT] nwkSKey - Network session key 113 | * \param [OUT] appSKey - Application session key 114 | */ 115 | void LoRaMacJoinComputeSKeys( const uint8_t *key, const uint8_t *appNonce, uint16_t devNonce, uint8_t *nwkSKey, uint8_t *appSKey ); 116 | 117 | /*! 118 | * Computes the LoRaMAC join frame decryption 119 | * 120 | * \param [IN] beaconTime - Time of the recent received beacon 121 | * \param [IN] address - Frame address 122 | * \param [IN] pingPeriod - Ping period of the node 123 | * \param [OUT] pingOffset - Pseudo random ping offset 124 | */ 125 | void LoRaMacBeaconComputePingOffset( uint64_t beaconTime, uint32_t address, uint16_t pingPeriod, uint16_t *pingOffset ); 126 | 127 | /*! \} defgroup LORAMAC */ 128 | 129 | #ifdef __cplusplus 130 | } 131 | #endif 132 | 133 | 134 | #endif // __LORAMAC_CRYPTO_H__ 135 | -------------------------------------------------------------------------------- /src/loramac/LoRaMacConfirmQueue.h: -------------------------------------------------------------------------------- 1 | /*! 2 | * \file LoRaMacConfirmQueue.h 3 | * 4 | * \brief LoRa MAC confirm queue implementation 5 | * 6 | * \copyright Revised BSD License, see section \ref LICENSE. 7 | * 8 | * \code 9 | * ______ _ 10 | * / _____) _ | | 11 | * ( (____ _____ ____ _| |_ _____ ____| |__ 12 | * \____ \| ___ | (_ _) ___ |/ ___) _ \ 13 | * _____) ) ____| | | || |_| ____( (___| | | | 14 | * (______/|_____)_|_|_| \__)_____)\____)_| |_| 15 | * (C)2013 Semtech 16 | * 17 | * ___ _____ _ ___ _ _____ ___ ___ ___ ___ 18 | * / __|_ _/_\ / __| |/ / __/ _ \| _ \/ __| __| 19 | * \__ \ | |/ _ \ (__| ' <| _| (_) | / (__| _| 20 | * |___/ |_/_/ \_\___|_|\_\_| \___/|_|_\\___|___| 21 | * embedded.connectivity.solutions=============== 22 | * 23 | * \endcode 24 | * 25 | * \author Miguel Luis ( Semtech ) 26 | * 27 | * \author Gregory Cristian ( Semtech ) 28 | * 29 | * \author Daniel Jaeckle ( STACKFORCE ) 30 | * 31 | * \defgroup LORAMACCONFIRMQUEUE LoRa MAC confirm queue implementation 32 | * This module specifies the API implementation of the LoRaMAC confirm queue. 33 | * The confirm queue is implemented with as a ring buffer. The number of 34 | * elements can be defined with \ref LORA_MAC_MLME_CONFIRM_QUEUE_LEN. The 35 | * current implementation does not support multiple elements of the same 36 | * Mlme_t type. 37 | * \{ 38 | */ 39 | #ifndef __LORAMAC_CONFIRMQUEUE_H__ 40 | #define __LORAMAC_CONFIRMQUEUE_H__ 41 | 42 | 43 | /*! 44 | * LoRaMac MLME-Confirm queue length 45 | */ 46 | #define LORA_MAC_MLME_CONFIRM_QUEUE_LEN 5 47 | 48 | /*! 49 | * Structure to hold multiple MLME request confirm data 50 | */ 51 | typedef struct sMlmeConfirmQueue 52 | { 53 | /*! 54 | * Holds the previously performed MLME-Request 55 | */ 56 | Mlme_t Request; 57 | /*! 58 | * Status of the operation 59 | */ 60 | LoRaMacEventInfoStatus_t Status; 61 | /*! 62 | * Set to true, if the request is ready to be handled 63 | */ 64 | bool ReadyToHandle; 65 | /*! 66 | * Set to true, if it is not permitted to set the ReadyToHandle variable 67 | * with a function call to LoRaMacConfirmQueueSetStatusCmn. 68 | */ 69 | bool RestrictCommonReadyToHandle; 70 | }MlmeConfirmQueue_t; 71 | 72 | /*! 73 | * \brief Initializes the confirm queue 74 | * 75 | * \param [IN] primitives - Pointer to the LoRaMac primitives. 76 | */ 77 | void LoRaMacConfirmQueueInit( LoRaMacPrimitives_t* primitives ); 78 | 79 | /*! 80 | * \brief Adds an element to the confirm queue. 81 | * 82 | * \param [IN] mlmeConfirm - Pointer to the element to add. 83 | * 84 | * \retval [true - operation was successful, false - operation failed] 85 | */ 86 | bool LoRaMacConfirmQueueAdd( MlmeConfirmQueue_t* mlmeConfirm ); 87 | 88 | /*! 89 | * \brief Removes the last element which was added into the queue. 90 | * 91 | * \retval [true - operation was successful, false - operation failed] 92 | */ 93 | bool LoRaMacConfirmQueueRemoveLast( void ); 94 | 95 | /*! 96 | * \brief Removes the first element which was added to the confirm queue. 97 | * 98 | * \retval [true - operation was successful, false - operation failed] 99 | */ 100 | bool LoRaMacConfirmQueueRemoveFirst( void ); 101 | 102 | /*! 103 | * \brief Sets the status of an element. 104 | * 105 | * \param [IN] status - The status to set. 106 | * 107 | * \param [IN] request - The related request to set the status. 108 | */ 109 | void LoRaMacConfirmQueueSetStatus( LoRaMacEventInfoStatus_t status, Mlme_t request ); 110 | 111 | /*! 112 | * \brief Gets the status of an element. 113 | * 114 | * \param [IN] request - The request to query the status. 115 | * 116 | * \retval The status of the related MlmeRequest. 117 | */ 118 | LoRaMacEventInfoStatus_t LoRaMacConfirmQueueGetStatus( Mlme_t request ); 119 | 120 | /*! 121 | * \brief Sets a common status for all elements in the queue. 122 | * 123 | * \param [IN] status - The status to set. 124 | */ 125 | void LoRaMacConfirmQueueSetStatusCmn( LoRaMacEventInfoStatus_t status ); 126 | 127 | /*! 128 | * \brief Gets the common status of all elements. 129 | * 130 | * \retval The common status of all elements. 131 | */ 132 | LoRaMacEventInfoStatus_t LoRaMacConfirmQueueGetStatusCmn( void ); 133 | 134 | /*! 135 | * \brief Verifies if a request is in the queue and active. 136 | * 137 | * \param [IN] request - The request to verify. 138 | * 139 | * \retval [true - element is in the queue, false - element is not in the queue]. 140 | */ 141 | bool LoRaMacConfirmQueueIsCmdActive( Mlme_t request ); 142 | 143 | /*! 144 | * \brief Handles all callbacks of active requests 145 | * 146 | * \param [IN] mlmeConfirm - Pointer to the generic mlmeConfirm structure. 147 | */ 148 | void LoRaMacConfirmQueueHandleCb( MlmeConfirm_t* mlmeConfirm ); 149 | 150 | /*! 151 | * \brief Query number of elements in the queue. 152 | * 153 | * \retval Number of elements. 154 | */ 155 | uint8_t LoRaMacConfirmQueueGetCnt( void ); 156 | 157 | /*! 158 | * \brief Verify if the confirm queue is full. 159 | * 160 | * \retval [true - queue is full, false - queue is not full]. 161 | */ 162 | bool LoRaMacConfirmQueueIsFull( void ); 163 | 164 | #endif // __LORAMAC_CONFIRMQUEUE_H__ 165 | -------------------------------------------------------------------------------- /src/loramac/aes.h: -------------------------------------------------------------------------------- 1 | /* 2 | --------------------------------------------------------------------------- 3 | Copyright (c) 1998-2008, Brian Gladman, Worcester, UK. All rights reserved. 4 | 5 | LICENSE TERMS 6 | 7 | The redistribution and use of this software (with or without changes) 8 | is allowed without the payment of fees or royalties provided that: 9 | 10 | 1. source code distributions include the above copyright notice, this 11 | list of conditions and the following disclaimer; 12 | 13 | 2. binary distributions include the above copyright notice, this list 14 | of conditions and the following disclaimer in their documentation; 15 | 16 | 3. the name of the copyright holder is not used to endorse products 17 | built using this software without specific written permission. 18 | 19 | DISCLAIMER 20 | 21 | This software is provided 'as is' with no explicit or implied warranties 22 | in respect of its properties, including, but not limited to, correctness 23 | and/or fitness for purpose. 24 | --------------------------------------------------------------------------- 25 | Issue 09/09/2006 26 | 27 | This is an AES implementation that uses only 8-bit byte operations on the 28 | cipher state. 29 | */ 30 | 31 | #ifndef AES_H 32 | #define AES_H 33 | 34 | #if 1 35 | # define AES_ENC_PREKEYED /* AES encryption with a precomputed key schedule */ 36 | #endif 37 | #if 0 38 | # define AES_DEC_PREKEYED /* AES decryption with a precomputed key schedule */ 39 | #endif 40 | #if 0 41 | # define AES_ENC_128_OTFK /* AES encryption with 'on the fly' 128 bit keying */ 42 | #endif 43 | #if 0 44 | # define AES_DEC_128_OTFK /* AES decryption with 'on the fly' 128 bit keying */ 45 | #endif 46 | #if 0 47 | # define AES_ENC_256_OTFK /* AES encryption with 'on the fly' 256 bit keying */ 48 | #endif 49 | #if 0 50 | # define AES_DEC_256_OTFK /* AES decryption with 'on the fly' 256 bit keying */ 51 | #endif 52 | 53 | #define N_ROW 4 54 | #define N_COL 4 55 | #define N_BLOCK (N_ROW * N_COL) 56 | #define N_MAX_ROUNDS 14 57 | 58 | typedef uint8_t return_type; 59 | 60 | /* Warning: The key length for 256 bit keys overflows a byte 61 | (see comment below) 62 | */ 63 | 64 | typedef uint8_t length_type; 65 | 66 | typedef struct 67 | { uint8_t ksch[(N_MAX_ROUNDS + 1) * N_BLOCK]; 68 | uint8_t rnd; 69 | } aes_context; 70 | 71 | /* The following calls are for a precomputed key schedule 72 | 73 | NOTE: If the length_type used for the key length is an 74 | unsigned 8-bit character, a key length of 256 bits must 75 | be entered as a length in bytes (valid inputs are hence 76 | 128, 192, 16, 24 and 32). 77 | */ 78 | 79 | #if defined( AES_ENC_PREKEYED ) || defined( AES_DEC_PREKEYED ) 80 | 81 | return_type lorawan_aes_set_key( const uint8_t key[], 82 | length_type keylen, 83 | aes_context ctx[1] ); 84 | #endif 85 | 86 | #if defined( AES_ENC_PREKEYED ) 87 | 88 | return_type lora_aes_encrypt( const uint8_t in[N_BLOCK], 89 | uint8_t out[N_BLOCK], 90 | const aes_context ctx[1] ); 91 | 92 | return_type lorawan_aes_cbc_encrypt( const uint8_t *in, 93 | uint8_t *out, 94 | int32_t n_block, 95 | uint8_t iv[N_BLOCK], 96 | const aes_context ctx[1] ); 97 | #endif 98 | 99 | #if defined( AES_DEC_PREKEYED ) 100 | 101 | return_type aes_decrypt( const uint8_t in[N_BLOCK], 102 | uint8_t out[N_BLOCK], 103 | const aes_context ctx[1] ); 104 | 105 | return_type aes_cbc_decrypt( const uint8_t *in, 106 | uint8_t *out, 107 | int32_t n_block, 108 | uint8_t iv[N_BLOCK], 109 | const aes_context ctx[1] ); 110 | #endif 111 | 112 | /* The following calls are for 'on the fly' keying. In this case the 113 | encryption and decryption keys are different. 114 | 115 | The encryption subroutines take a key in an array of bytes in 116 | key[L] where L is 16, 24 or 32 bytes for key lengths of 128, 117 | 192, and 256 bits respectively. They then encrypts the input 118 | data, in[] with this key and put the reult in the output array 119 | out[]. In addition, the second key array, o_key[L], is used 120 | to output the key that is needed by the decryption subroutine 121 | to reverse the encryption operation. The two key arrays can 122 | be the same array but in this case the original key will be 123 | overwritten. 124 | 125 | In the same way, the decryption subroutines output keys that 126 | can be used to reverse their effect when used for encryption. 127 | 128 | Only 128 and 256 bit keys are supported in these 'on the fly' 129 | modes. 130 | */ 131 | 132 | #if defined( AES_ENC_128_OTFK ) 133 | void aes_encrypt_128( const uint8_t in[N_BLOCK], 134 | uint8_t out[N_BLOCK], 135 | const uint8_t key[N_BLOCK], 136 | uint8_t o_key[N_BLOCK] ); 137 | #endif 138 | 139 | #if defined( AES_DEC_128_OTFK ) 140 | void aes_decrypt_128( const uint8_t in[N_BLOCK], 141 | uint8_t out[N_BLOCK], 142 | const uint8_t key[N_BLOCK], 143 | uint8_t o_key[N_BLOCK] ); 144 | #endif 145 | 146 | #if defined( AES_ENC_256_OTFK ) 147 | void aes_encrypt_256( const uint8_t in[N_BLOCK], 148 | uint8_t out[N_BLOCK], 149 | const uint8_t key[2 * N_BLOCK], 150 | uint8_t o_key[2 * N_BLOCK] ); 151 | #endif 152 | 153 | #if defined( AES_DEC_256_OTFK ) 154 | void aes_decrypt_256( const uint8_t in[N_BLOCK], 155 | uint8_t out[N_BLOCK], 156 | const uint8_t key[2 * N_BLOCK], 157 | uint8_t o_key[2 * N_BLOCK] ); 158 | #endif 159 | 160 | #endif 161 | -------------------------------------------------------------------------------- /src/loramac/cmac.c: -------------------------------------------------------------------------------- 1 | /************************************************************************** 2 | Copyright (C) 2009 Lander Casado, Philippas Tsigas 3 | 4 | All rights reserved. 5 | 6 | Permission is hereby granted, free of charge, to any person obtaining 7 | a copy of this software and associated documentation files 8 | (the "Software"), to deal with the Software without restriction, including 9 | without limitation the rights to use, copy, modify, merge, publish, 10 | distribute, sublicense, and/or sell copies of the Software, and to 11 | permit persons to whom the Software is furnished to do so, subject to 12 | the following conditions: 13 | 14 | Redistributions of source code must retain the above copyright notice, 15 | this list of conditions and the following disclaimers. Redistributions in 16 | binary form must reproduce the above copyright notice, this list of 17 | conditions and the following disclaimers in the documentation and/or 18 | other materials provided with the distribution. 19 | 20 | In no event shall the authors or copyright holders be liable for any special, 21 | incidental, indirect or consequential damages of any kind, or any damages 22 | whatsoever resulting from loss of use, data or profits, whether or not 23 | advised of the possibility of damage, and on any theory of liability, 24 | arising out of or in connection with the use or performance of this software. 25 | 26 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 27 | OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 28 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 29 | CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 30 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 31 | FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 32 | DEALINGS WITH THE SOFTWARE 33 | 34 | *****************************************************************************/ 35 | //#include 36 | //#include 37 | #include 38 | #include "aes.h" 39 | #include "cmac.h" 40 | #include "../loramac/utilities.h" 41 | 42 | #define LSHIFT(v, r) do { \ 43 | int32_t i; \ 44 | for (i = 0; i < 15; i++) \ 45 | (r)[i] = (v)[i] << 1 | (v)[i + 1] >> 7; \ 46 | (r)[15] = (v)[15] << 1; \ 47 | } while (0) 48 | 49 | #define XOR(v, r) do { \ 50 | int32_t i; \ 51 | for (i = 0; i < 16; i++) \ 52 | { \ 53 | (r)[i] = (r)[i] ^ (v)[i]; \ 54 | } \ 55 | } while (0) \ 56 | 57 | 58 | void AES_CMAC_Init(AES_CMAC_CTX *ctx) 59 | { 60 | memset1(ctx->X, 0, sizeof ctx->X); 61 | ctx->M_n = 0; 62 | memset1(ctx->rijndael.ksch, '\0', 240); 63 | } 64 | 65 | void AES_CMAC_SetKey(AES_CMAC_CTX *ctx, const uint8_t key[AES_CMAC_KEY_LENGTH]) 66 | { 67 | //rijndael_set_key_enc_only(&ctx->rijndael, key, 128); 68 | lorawan_aes_set_key( key, AES_CMAC_KEY_LENGTH, &ctx->rijndael); 69 | } 70 | 71 | void AES_CMAC_Update(AES_CMAC_CTX *ctx, const uint8_t *data, uint32_t len) 72 | { 73 | uint32_t mlen; 74 | uint8_t in[16]; 75 | 76 | if (ctx->M_n > 0) { 77 | mlen = MIN(16 - ctx->M_n, len); 78 | memcpy1(ctx->M_last + ctx->M_n, data, mlen); 79 | ctx->M_n += mlen; 80 | if (ctx->M_n < 16 || len == mlen) 81 | return; 82 | XOR(ctx->M_last, ctx->X); 83 | //rijndael_encrypt(&ctx->rijndael, ctx->X, ctx->X); 84 | lora_aes_encrypt( ctx->X, ctx->X, &ctx->rijndael); 85 | data += mlen; 86 | len -= mlen; 87 | } 88 | while (len > 16) { /* not last block */ 89 | 90 | XOR(data, ctx->X); 91 | //rijndael_encrypt(&ctx->rijndael, ctx->X, ctx->X); 92 | 93 | memcpy1(in, &ctx->X[0], 16); //Bestela ez du ondo iten 94 | lora_aes_encrypt( in, in, &ctx->rijndael); 95 | memcpy1(&ctx->X[0], in, 16); 96 | 97 | data += 16; 98 | len -= 16; 99 | } 100 | /* potential last block, save it */ 101 | memcpy1(ctx->M_last, data, len); 102 | ctx->M_n = len; 103 | } 104 | 105 | void AES_CMAC_Final(uint8_t digest[AES_CMAC_DIGEST_LENGTH], AES_CMAC_CTX *ctx) 106 | { 107 | uint8_t K[16]; 108 | uint8_t in[16]; 109 | /* generate subkey K1 */ 110 | memset1(K, '\0', 16); 111 | 112 | //rijndael_encrypt(&ctx->rijndael, K, K); 113 | 114 | lora_aes_encrypt( K, K, &ctx->rijndael); 115 | 116 | if (K[0] & 0x80) { 117 | LSHIFT(K, K); 118 | K[15] ^= 0x87; 119 | } else 120 | LSHIFT(K, K); 121 | 122 | 123 | if (ctx->M_n == 16) { 124 | /* last block was a complete block */ 125 | XOR(K, ctx->M_last); 126 | 127 | } else { 128 | /* generate subkey K2 */ 129 | if (K[0] & 0x80) { 130 | LSHIFT(K, K); 131 | K[15] ^= 0x87; 132 | } else 133 | LSHIFT(K, K); 134 | 135 | /* padding(M_last) */ 136 | ctx->M_last[ctx->M_n] = 0x80; 137 | while (++ctx->M_n < 16) 138 | ctx->M_last[ctx->M_n] = 0; 139 | 140 | XOR(K, ctx->M_last); 141 | 142 | 143 | } 144 | XOR(ctx->M_last, ctx->X); 145 | 146 | //rijndael_encrypt(&ctx->rijndael, ctx->X, digest); 147 | 148 | memcpy1(in, &ctx->X[0], 16); //Bestela ez du ondo iten 149 | lora_aes_encrypt(in, digest, &ctx->rijndael); 150 | memset1(K, 0, sizeof K); 151 | 152 | } 153 | 154 | -------------------------------------------------------------------------------- /src/driver/sx1262-board.c: -------------------------------------------------------------------------------- 1 | /*! 2 | * \file sx1262dvk1cas-board.c 3 | * 4 | * \brief Target board SX1262DVK1CAS shield driver implementation 5 | * 6 | * \copyright Revised BSD License, see section \ref LICENSE. 7 | * 8 | * \code 9 | * ______ _ 10 | * / _____) _ | | 11 | * ( (____ _____ ____ _| |_ _____ ____| |__ 12 | * \____ \| ___ | (_ _) ___ |/ ___) _ \ 13 | * _____) ) ____| | | || |_| ____( (___| | | | 14 | * (______/|_____)_|_|_| \__)_____)\____)_| |_| 15 | * (C)2013-2017 Semtech 16 | * 17 | * \endcode 18 | * 19 | * \author Miguel Luis ( Semtech ) 20 | * 21 | * \author Gregory Cristian ( Semtech ) 22 | */ 23 | #include "Arduino.h" 24 | #if defined(WIFI_LoRa_32_V3)||defined(Wireless_Track)||defined(Wireless_Mini_Shell)||defined(WIFI_LoRa_32_SX1262)||defined(Wireless_Stick_V3)||defined(Wireless_Stick_Lite_V3) 25 | #include 26 | #include "../driver/sx126x-board.h" 27 | #include "../driver/sx126x.h" 28 | #include "../driver/board-config.h" 29 | 30 | uint8_t gPaOptSetting = 0; 31 | 32 | extern uint8_t SpiInOut(Spi_t *obj, uint8_t outData ); 33 | SX126x_t SX126x; 34 | uint32_t SX126xGetBoardTcxoWakeupTime( void ) 35 | { 36 | return BOARD_TCXO_WAKEUP_TIME; 37 | } 38 | 39 | void SX126xIoInit( void ) 40 | { 41 | GpioInit( &SX126x.Reset, RADIO_RESET, OUTPUT, PIN_PUSH_PULL, PIN_PULL_UP, 1 ); 42 | GpioInit( &SX126x.Spi.Nss, RADIO_NSS, OUTPUT, PIN_PUSH_PULL, PIN_PULL_UP, 1 ); 43 | GpioInit( &SX126x.BUSY, RADIO_BUSY, INPUT, PIN_PUSH_PULL, PIN_NO_PULL, 0 ); 44 | GpioInit( &SX126x.DIO1, RADIO_DIO_1, INPUT, PIN_PUSH_PULL, PIN_NO_PULL, 0 ); 45 | } 46 | 47 | void SX126xIoIrqInit( DioIrqHandler dioIrq ) 48 | { 49 | // attachInterrupt(RADIO_DIO_1,dioIrq,RISING); 50 | GpioSetInterrupt( &SX126x.DIO1, IRQ_RISING_EDGE, IRQ_HIGH_PRIORITY, dioIrq ); 51 | } 52 | 53 | void SX126xReset( void ) 54 | { 55 | pinMode(SX126x.Reset.pin,OUTPUT); 56 | delay( 20 ); 57 | digitalWrite(SX126x.Reset.pin,1); 58 | delay( 50 ); 59 | digitalWrite(SX126x.Reset.pin,0); 60 | delay( 50 ); 61 | digitalWrite(SX126x.Reset.pin,1); 62 | delay( 50 ); 63 | 64 | /* 65 | GpioInit( &SX126x.Reset, RADIO_RESET, OUTPUT, PIN_PUSH_PULL, PIN_NO_PULL, 1 ); 66 | delay( 40 ); 67 | GpioInit( &SX126x.Reset, RADIO_RESET, OUTPUT, PIN_PUSH_PULL, PIN_NO_PULL, 0 ); // internal pull-up 68 | delay( 40 ); 69 | GpioInit( &SX126x.Reset, RADIO_RESET, OUTPUT, PIN_PUSH_PULL, PIN_NO_PULL, 1 ); 70 | */ 71 | } 72 | 73 | void SX126xWaitOnBusy( void ) 74 | { 75 | uint32_t timeout=0; 76 | while( GpioRead( &SX126x.BUSY ) == 1 ) 77 | { 78 | timeout++; 79 | if(timeout>1000000) 80 | { 81 | // lora_printf("spi timeout\r\n"); 82 | break; 83 | } 84 | delayMicroseconds(1); 85 | //lora_printf("b"); 86 | } 87 | } 88 | 89 | void SX126xWakeup( void ) 90 | { 91 | GpioWrite( &SX126x.Spi.Nss, 0 ); 92 | SpiInOut( &SX126x.Spi, RADIO_GET_STATUS ); 93 | SpiInOut( &SX126x.Spi, 0x00 ); 94 | GpioWrite( &SX126x.Spi.Nss, 1 );; 95 | // Wait for chip to be ready. 96 | SX126xWaitOnBusy( ); 97 | } 98 | 99 | 100 | void SX126xWriteCommand( RadioCommands_t command, uint8_t *buffer, uint16_t size ) 101 | { 102 | SX126xCheckDeviceReady( ); 103 | GpioWrite( &SX126x.Spi.Nss, 0 ); 104 | SpiInOut( &SX126x.Spi, ( uint8_t )command ); 105 | 106 | for( uint16_t i = 0; i < size; i++ ) 107 | { 108 | SpiInOut( &SX126x.Spi, buffer[i] ); 109 | } 110 | 111 | GpioWrite( &SX126x.Spi.Nss, 1 ); 112 | 113 | if( command != RADIO_SET_SLEEP ) 114 | { 115 | SX126xWaitOnBusy( ); 116 | } 117 | } 118 | 119 | void SX126xReadCommand( RadioCommands_t command, uint8_t *buffer, uint16_t size ) 120 | { 121 | 122 | SX126xCheckDeviceReady( ); 123 | GpioWrite( &SX126x.Spi.Nss, 0 ); 124 | 125 | SpiInOut( &SX126x.Spi, ( uint8_t )command ); 126 | SpiInOut( &SX126x.Spi, 0x00 ); 127 | for( uint16_t i = 0; i < size; i++ ) 128 | { 129 | buffer[i] = SpiInOut( &SX126x.Spi, 0 ); 130 | } 131 | 132 | GpioWrite( &SX126x.Spi.Nss, 1 ); 133 | 134 | SX126xWaitOnBusy( ); 135 | } 136 | 137 | void SX126xWriteRegisters( uint16_t address, uint8_t *buffer, uint16_t size ) 138 | { 139 | SX126xCheckDeviceReady( ); 140 | 141 | GpioWrite( &SX126x.Spi.Nss, 0 ); 142 | 143 | SpiInOut( &SX126x.Spi, RADIO_WRITE_REGISTER ); 144 | SpiInOut( &SX126x.Spi, ( address & 0xFF00 ) >> 8 ); 145 | SpiInOut( &SX126x.Spi, address & 0x00FF ); 146 | 147 | for( uint16_t i = 0; i < size; i++ ) 148 | { 149 | SpiInOut( &SX126x.Spi, buffer[i] ); 150 | } 151 | 152 | GpioWrite( &SX126x.Spi.Nss, 1 ); 153 | 154 | SX126xWaitOnBusy( ); 155 | } 156 | 157 | void SX126xWriteRegister( uint16_t address, uint8_t value ) 158 | { 159 | SX126xWriteRegisters( address, &value, 1 ); 160 | } 161 | 162 | void SX126xReadRegisters( uint16_t address, uint8_t *buffer, uint16_t size ) 163 | { 164 | SX126xCheckDeviceReady( ); 165 | 166 | GpioWrite( &SX126x.Spi.Nss, 0 ); 167 | 168 | SpiInOut( &SX126x.Spi, RADIO_READ_REGISTER ); 169 | SpiInOut( &SX126x.Spi, ( address & 0xFF00 ) >> 8 ); 170 | SpiInOut( &SX126x.Spi, address & 0x00FF ); 171 | SpiInOut( &SX126x.Spi, 0 ); 172 | for( uint16_t i = 0; i < size; i++ ) 173 | { 174 | buffer[i] = SpiInOut( &SX126x.Spi, 0 ); 175 | } 176 | GpioWrite( &SX126x.Spi.Nss, 1 ); 177 | 178 | SX126xWaitOnBusy( ); 179 | } 180 | 181 | uint8_t SX126xReadRegister( uint16_t address ) 182 | { 183 | uint8_t data; 184 | SX126xReadRegisters( address, &data, 1 ); 185 | return data; 186 | } 187 | 188 | void SX126xWriteBuffer( uint8_t offset, uint8_t *buffer, uint8_t size ) 189 | { 190 | 191 | SX126xCheckDeviceReady( ); 192 | 193 | GpioWrite( &SX126x.Spi.Nss, 0 ); 194 | 195 | SpiInOut( &SX126x.Spi, RADIO_WRITE_BUFFER ); 196 | SpiInOut( &SX126x.Spi, offset ); 197 | for( uint16_t i = 0; i < size; i++ ) 198 | { 199 | SpiInOut( &SX126x.Spi, buffer[i] ); 200 | } 201 | GpioWrite( &SX126x.Spi.Nss, 1 ); 202 | 203 | SX126xWaitOnBusy( ); 204 | } 205 | 206 | void SX126xReadBuffer( uint8_t offset, uint8_t *buffer, uint8_t size ) 207 | { 208 | SX126xCheckDeviceReady( ); 209 | 210 | GpioWrite( &SX126x.Spi.Nss, 0 ); 211 | 212 | SpiInOut( &SX126x.Spi, RADIO_READ_BUFFER ); 213 | SpiInOut( &SX126x.Spi, offset ); 214 | SpiInOut( &SX126x.Spi, 0 ); 215 | for( uint16_t i = 0; i < size; i++ ) 216 | { 217 | buffer[i] = SpiInOut( &SX126x.Spi, 0 ); 218 | } 219 | GpioWrite( &SX126x.Spi.Nss, 1 ); 220 | 221 | SX126xWaitOnBusy( ); 222 | 223 | } 224 | 225 | void SX126xSetRfTxPower( int8_t power ) 226 | { 227 | SX126xSetTxParams( power, RADIO_RAMP_3400_US ); 228 | } 229 | 230 | uint8_t SX126xGetPaSelect( uint32_t channel ) 231 | { 232 | return SX1262; 233 | } 234 | 235 | void SX126xAntSwOn( void ) 236 | { 237 | } 238 | 239 | void SX126xAntSwOff( void ) 240 | { 241 | } 242 | 243 | bool SX126xCheckRfFrequency( uint32_t frequency ) 244 | { 245 | // Implement check. Currently all frequencies are supported 246 | return true; 247 | } 248 | 249 | uint8_t SX126xGetPaOpt( ) 250 | { 251 | return gPaOptSetting; 252 | } 253 | 254 | void SX126xSetPaOpt( uint8_t opt ) 255 | { 256 | if(opt>3) return; 257 | 258 | gPaOptSetting = opt; 259 | } 260 | 261 | #endif 262 | -------------------------------------------------------------------------------- /src/driver/timer.h: -------------------------------------------------------------------------------- 1 | /*! 2 | * \file timer.h 3 | * 4 | * \brief Timer objects and scheduling management implementation 5 | * 6 | * \copyright Revised BSD License, see section \ref LICENSE. 7 | * 8 | * \code 9 | * ______ _ 10 | * / _____) _ | | 11 | * ( (____ _____ ____ _| |_ _____ ____| |__ 12 | * \____ \| ___ | (_ _) ___ |/ ___) _ \ 13 | * _____) ) ____| | | || |_| ____( (___| | | | 14 | * (______/|_____)_|_|_| \__)_____)\____)_| |_| 15 | * (C)2013-2017 Semtech 16 | * 17 | * \endcode 18 | * 19 | * \author Miguel Luis ( Semtech ) 20 | * 21 | * \author Gregory Cristian ( Semtech ) 22 | * 23 | * \addtogroup LORA 24 | * 25 | * \{ 26 | * 27 | * \defgroup LORA_TIMER 28 | * 29 | * \{ 30 | * 31 | */ 32 | #ifndef __TIMER_H__ 33 | #define __TIMER_H__ 34 | 35 | #ifdef __cplusplus 36 | extern "C" { 37 | #endif 38 | 39 | /* Includes ------------------------------------------------------------------*/ 40 | 41 | #include 42 | #include "../loramac/utilities.h" 43 | 44 | /* Exported types ------------------------------------------------------------*/ 45 | 46 | /*! 47 | * \brief Timer object description 48 | */ 49 | typedef struct TimerEvent_s 50 | { 51 | uint32_t Timestamp; //! Expiring timer value in ticks from TimerContext 52 | uint32_t ReloadValue; //! Reload Value when Timer is restarted 53 | bool IsRunning; //! Is the timer currently running 54 | void ( *Callback )( void ); //! Timer IRQ callback function 55 | struct TimerEvent_s *Next; //! Pointer to the next Timer object. 56 | } TimerEvent_t; 57 | 58 | extern TimerEvent_t *TimerListHead; 59 | #ifndef TimerTime_t 60 | typedef uint64_t TimerTime_t; 61 | #endif 62 | 63 | /* Exported constants --------------------------------------------------------*/ 64 | /* External variables --------------------------------------------------------*/ 65 | /* Exported macros -----------------------------------------------------------*/ 66 | /* Exported functions ------------------------------------------------------- */ 67 | /*! 68 | * \brief Number of seconds elapsed between Unix and GPS epoch 69 | */ 70 | #define UNIX_GPS_EPOCH_OFFSET 315964800 71 | 72 | /*! 73 | * \brief Structure holding the system time in seconds and miliseconds. 74 | */ 75 | typedef struct TimerSysTime_s 76 | { 77 | uint32_t Seconds; 78 | int16_t SubSeconds; 79 | }TimerSysTime_t; 80 | 81 | /*! 82 | * Adds 2 TimerSysTime_t values 83 | * 84 | * \param a Value 85 | * \param b Value to added 86 | * 87 | * \retval result Addition result (TimerSysTime_t value) 88 | */ 89 | static inline TimerSysTime_t TimerAddSysTime( TimerSysTime_t a, TimerSysTime_t b ) 90 | { 91 | TimerSysTime_t c = { 0 }; 92 | 93 | c.Seconds = a.Seconds + b.Seconds; 94 | c.SubSeconds = a.SubSeconds + b.SubSeconds; 95 | if( c.SubSeconds >= 1000 ) 96 | { 97 | c.Seconds++; 98 | c.SubSeconds -= 1000; 99 | } 100 | return c; 101 | } 102 | 103 | /*! 104 | * Subtracts 2 TimerSysTime_t values 105 | * 106 | * \param a Value 107 | * \param b Value to be subtracted 108 | * 109 | * \retval result Subtraction result (TimerSysTime_t value) 110 | */ 111 | static inline TimerSysTime_t TimerSubSysTime( TimerSysTime_t a, TimerSysTime_t b ) 112 | { 113 | TimerSysTime_t c = { 0 }; 114 | 115 | c.Seconds = a.Seconds - b.Seconds; 116 | c.SubSeconds = a.SubSeconds - b.SubSeconds; 117 | if( c.SubSeconds < 0 ) 118 | { 119 | c.Seconds--; 120 | c.SubSeconds += 1000; 121 | } 122 | return c; 123 | } 124 | 125 | /*! 126 | * \brief Sets the system time with the number of sconds elapsed since epoch 127 | * 128 | * \param [IN] sysTime Structure provideing the number of seconds and 129 | * subseconds elapsed since epoch 130 | */ 131 | void TimerSetSysTime( TimerSysTime_t sysTime ); 132 | 133 | /*! 134 | * \brief Gets the current system number of sconds elapsed since epoch 135 | * 136 | * \retval sysTime Structure provideing the number of seconds and 137 | * subseconds elapsed since epoch 138 | */ 139 | TimerSysTime_t TimerGetSysTime( void ); 140 | 141 | 142 | /*! 143 | * \brief Gets current MCU system time 144 | * 145 | * \retval sysTime Current seconds/sub-seconds since Mcu started 146 | */ 147 | TimerSysTime_t SysTimeGetMcuTime( void ); 148 | 149 | /*! 150 | * Converts the given SysTime to the equivalent RTC value in milliseconds 151 | * 152 | * \param [IN] sysTime System time to be converted 153 | * 154 | * \retval timeMs The RTC converted time value in ms 155 | */ 156 | uint32_t SysTimeToMs( TimerSysTime_t sysTime ); 157 | 158 | /*! 159 | * Converts the given RTC value in milliseconds to the equivalent SysTime 160 | * 161 | * \param [IN] timeMs The RTC time value in ms to be converted 162 | * 163 | * \retval sysTime Converted system time 164 | */ 165 | TimerSysTime_t SysTimeFromMs( uint32_t timeMs ); 166 | 167 | 168 | /*! 169 | * \brief Initializes the timer object 170 | * 171 | * \remark TimerSetValue function must be called before starting the timer. 172 | * this function initializes timestamp and reload value at 0. 173 | * 174 | * \param [IN] obj Structure containing the timer object parameters 175 | * \param [IN] callback Function callback called at the end of the timeout 176 | */ 177 | void TimerInit( TimerEvent_t *obj, void ( *callback )( void ) ); 178 | 179 | /*! 180 | * \brief Timer IRQ event handler 181 | * 182 | * \note Head Timer Object is automaitcally removed from the List 183 | * 184 | * \note e.g. it is snot needded to stop it 185 | */ 186 | void TimerIrqHandler( void ); 187 | 188 | /*! 189 | * \brief Starts and adds the timer object to the list of timer events 190 | * 191 | * \param [IN] obj Structure containing the timer object parameters 192 | */ 193 | void TimerStart( TimerEvent_t *obj ); 194 | 195 | /*! 196 | * \brief Stops and removes the timer object from the list of timer events 197 | * 198 | * \param [IN] obj Structure containing the timer object parameters 199 | */ 200 | void TimerStop( TimerEvent_t *obj ); 201 | 202 | /*! 203 | * \brief Resets the timer object 204 | * 205 | * \param [IN] obj Structure containing the timer object parameters 206 | */ 207 | void TimerReset( TimerEvent_t *obj ); 208 | 209 | /*! 210 | * \brief Set timer new timeout value 211 | * 212 | * \param [IN] obj Structure containing the timer object parameters 213 | * \param [IN] value New timer timeout value 214 | */ 215 | void TimerSetValue( TimerEvent_t *obj, uint32_t value ); 216 | 217 | 218 | /*! 219 | * \brief Read the current time 220 | * 221 | * \retval returns current time in ms 222 | */ 223 | TimerTime_t TimerGetCurrentTime( void ); 224 | 225 | /*! 226 | * \brief Return the Time elapsed since a fix moment in Time 227 | * 228 | * \param [IN] savedTime fix moment in Time 229 | * \retval time returns elapsed time in ms 230 | */ 231 | TimerTime_t TimerGetElapsedTime( TimerTime_t savedTime ); 232 | 233 | /*! 234 | * \brief Computes the temperature compensation for a period of time on a 235 | * specific temperature. 236 | * 237 | * \param [IN] period Time period to compensate 238 | * \param [IN] temperature Current temperature 239 | * 240 | * \retval Compensated time period 241 | */ 242 | TimerTime_t TimerTempCompensation( TimerTime_t period, float temperature ); 243 | 244 | /*! 245 | * \brief Manages the entry into ARM cortex deep-sleep mode 246 | */ 247 | void TimerLowPowerHandler( void ); 248 | 249 | #ifdef __cplusplus 250 | } 251 | #endif 252 | 253 | /*! \} defgroup LORA_TIMER */ 254 | /*! \} addtogroup LORA */ 255 | 256 | #endif /* __TIMER_H__ */ 257 | -------------------------------------------------------------------------------- /src/driver/sx1276-board.c: -------------------------------------------------------------------------------- 1 | /*! 2 | * \file sx1276mb1las-board.c 3 | * 4 | * \brief Target board SX1276MB1LAS shield driver implementation 5 | * 6 | * \copyright Revised BSD License, see section \ref LICENSE. 7 | * 8 | * \code 9 | * ______ _ 10 | * / _____) _ | | 11 | * ( (____ _____ ____ _| |_ _____ ____| |__ 12 | * \____ \| ___ | (_ _) ___ |/ ___) _ \ 13 | * _____) ) ____| | | || |_| ____( (___| | | | 14 | * (______/|_____)_|_|_| \__)_____)\____)_| |_| 15 | * (C)2013-2017 Semtech 16 | * 17 | * \endcode 18 | * 19 | * \author Miguel Luis ( Semtech ) 20 | * 21 | * \author Gregory Cristian ( Semtech ) 22 | */ 23 | 24 | #include "Arduino.h" 25 | #if defined(WIFI_LoRa_32)||defined(WIFI_LoRa_32_V2)||defined(Wireless_Stick)||defined(Wireless_Stick_Lite)||defined(Wireless_Bridge) 26 | #include 27 | #include "../loramac/utilities.h" 28 | #include "../driver/board-config.h" 29 | #include "../driver/delay.h" 30 | #include "../radio/radio_sx127x.h" 31 | #include "../driver/sx1276-board.h" 32 | /*! 33 | * Flag used to set the RF switch control pins in low power mode when the radio is not active. 34 | */ 35 | static bool RadioIsActive = false; 36 | 37 | /*! 38 | * Radio driver structure initialization 39 | */ 40 | const struct Radio_s Radio = 41 | { 42 | SX1276Init, 43 | SX1276GetStatus, 44 | SX1276SetModem, 45 | SX1276SetChannel, 46 | SX1276IsChannelFree, 47 | SX1276Random, 48 | SX1276SetRxConfig, 49 | SX1276SetTxConfig, 50 | SX1276CheckRfFrequency, 51 | SX1276GetTimeOnAir, 52 | SX1276Send, 53 | SX1276SetSleep, 54 | SX1276SetStby, 55 | SX1276SetRx, 56 | SX1276StartCad, 57 | SX1276SetTxContinuousWave, 58 | SX1276ReadRssi, 59 | SX1276Write, 60 | SX1276Read, 61 | SX1276WriteBuffer, 62 | SX1276ReadBuffer, 63 | SX1276SetMaxPayloadLength, 64 | SX1276SetPublicNetwork, 65 | SX1276GetWakeupTime, 66 | sx1276RadioIrqProcess 67 | }; 68 | 69 | /*! 70 | * Antenna switch GPIO pins objects 71 | */ 72 | Gpio_t AntSwitch; 73 | 74 | void SX1276IoInit( void ) 75 | { 76 | GpioInit( &SX1276.Reset, RADIO_RESET, OUTPUT, PIN_PUSH_PULL, PIN_PULL_UP, 1 ); 77 | GpioInit( &SX1276.Spi.Nss, RADIO_NSS, OUTPUT, PIN_PUSH_PULL, PIN_PULL_UP, 1 ); 78 | GpioInit( &SX1276.DIO0, RADIO_DIO_0, INPUT, PIN_PUSH_PULL, PIN_PULL_UP, 0 ); 79 | GpioInit( &SX1276.DIO1, RADIO_DIO_1, INPUT, PIN_PUSH_PULL, PIN_PULL_UP, 0 ); 80 | 81 | } 82 | 83 | void SX1276IoIrqInit( DioIrqHandler **irqHandlers ) 84 | { 85 | GpioSetInterrupt( &SX1276.DIO0, IRQ_RISING_EDGE, IRQ_HIGH_PRIORITY, irqHandlers[0] ); 86 | GpioSetInterrupt( &SX1276.DIO1, IRQ_RISING_EDGE, IRQ_HIGH_PRIORITY, irqHandlers[1] ); 87 | 88 | } 89 | 90 | void SX1276IoDeInit( void ) 91 | { 92 | GpioInit( &SX1276.Spi.Nss, RADIO_NSS, OUTPUT, PIN_PUSH_PULL, PIN_NO_PULL, 1 ); 93 | GpioInit( &SX1276.DIO0, RADIO_DIO_0, INPUT, PIN_PUSH_PULL, PIN_NO_PULL, 0 ); 94 | GpioInit( &SX1276.DIO1, RADIO_DIO_1, INPUT, PIN_PUSH_PULL, PIN_NO_PULL, 0 ); 95 | } 96 | 97 | /*! 98 | * \brief Enables/disables the TCXO if available on board design. 99 | * 100 | * \param [IN] state TCXO enabled when true and disabled when false. 101 | */ 102 | static void SX1276SetBoardTcxo( uint8_t state ) 103 | { 104 | // No TCXO component available on this board design. 105 | #if 0 106 | if( state == true ) 107 | { 108 | TCXO_ON( ); 109 | DelayMs( BOARD_TCXO_WAKEUP_TIME ); 110 | } 111 | else 112 | { 113 | TCXO_OFF( ); 114 | } 115 | #endif 116 | } 117 | 118 | uint32_t SX1276GetBoardTcxoWakeupTime( void ) 119 | { 120 | return BOARD_TCXO_WAKEUP_TIME; 121 | } 122 | 123 | void SX1276Reset( void ) 124 | { 125 | pinMode(SX1276.Reset.pin,OUTPUT); 126 | delay( 20 ); 127 | digitalWrite(SX1276.Reset.pin,1); 128 | delay( 50 ); 129 | digitalWrite(SX1276.Reset.pin,0); 130 | delay( 50 ); 131 | digitalWrite(SX1276.Reset.pin,1); 132 | delay( 50 ); 133 | } 134 | 135 | void SX1276SetRfTxPower( int8_t power ) 136 | { 137 | uint8_t paConfig = 0; 138 | uint8_t paDac = 0; 139 | 140 | paConfig = SX1276Read( REG_PACONFIG ); 141 | paDac = SX1276Read( REG_PADAC ); 142 | 143 | paConfig = ( paConfig & RF_PACONFIG_PASELECT_MASK ) | SX1276GetPaSelect( SX1276.Settings.Channel ); 144 | paConfig = ( paConfig & RF_PACONFIG_MAX_POWER_MASK ) | 0x70; 145 | 146 | if( ( paConfig & RF_PACONFIG_PASELECT_PABOOST ) == RF_PACONFIG_PASELECT_PABOOST ) 147 | { 148 | paDac = ( paDac & RF_PADAC_20DBM_MASK ) | RF_PADAC_20DBM_ON; 149 | //if( power > 17 ) 150 | //{ 151 | // paDac = ( paDac & RF_PADAC_20DBM_MASK ) | RF_PADAC_20DBM_ON; 152 | // } 153 | // else 154 | // { 155 | // paDac = ( paDac & RF_PADAC_20DBM_MASK ) | RF_PADAC_20DBM_OFF; 156 | //} 157 | if( ( paDac & RF_PADAC_20DBM_ON ) == RF_PADAC_20DBM_ON ) 158 | { 159 | if( power < 5 ) 160 | { 161 | power = 5; 162 | } 163 | if( power > 20 ) 164 | { 165 | power = 20; 166 | } 167 | paConfig = ( paConfig & RF_PACONFIG_OUTPUTPOWER_MASK ) | ( uint8_t )( ( uint16_t )( power - 5 ) & 0x0F ); 168 | } 169 | else 170 | { 171 | if( power < 2 ) 172 | { 173 | power = 2; 174 | } 175 | if( power > 17 ) 176 | { 177 | power = 17; 178 | } 179 | paConfig = ( paConfig & RF_PACONFIG_OUTPUTPOWER_MASK ) | ( uint8_t )( ( uint16_t )( power - 2 ) & 0x0F ); 180 | } 181 | } 182 | else 183 | { 184 | if( power < -1 ) 185 | { 186 | power = -1; 187 | } 188 | if( power > 14 ) 189 | { 190 | power = 14; 191 | } 192 | paConfig = ( paConfig & RF_PACONFIG_OUTPUTPOWER_MASK ) | ( uint8_t )( ( uint16_t )( power + 1 ) & 0x0F ); 193 | } 194 | SX1276Write( REG_PACONFIG, paConfig ); 195 | SX1276Write( REG_PADAC, paDac ); 196 | } 197 | 198 | uint8_t SX1276GetPaSelect( uint32_t channel ) 199 | { 200 | /*if( channel > RF_MID_BAND_THRESH ) 201 | { 202 | return RF_PACONFIG_PASELECT_PABOOST; 203 | } 204 | else 205 | { 206 | return RF_PACONFIG_PASELECT_RFO; 207 | }*/ 208 | return RF_PACONFIG_PASELECT_PABOOST; 209 | } 210 | 211 | void SX1276SetAntSwLowPower( bool status ) 212 | { 213 | if( RadioIsActive != status ) 214 | { 215 | RadioIsActive = status; 216 | 217 | if( status == false ) 218 | { 219 | SX1276SetBoardTcxo( true ); 220 | SX1276AntSwInit( ); 221 | } 222 | else 223 | { 224 | SX1276SetBoardTcxo( false ); 225 | SX1276AntSwDeInit( ); 226 | } 227 | } 228 | } 229 | 230 | void SX1276AntSwInit( void ) 231 | { 232 | // GpioInit( &AntSwitch, RADIO_ANT_SWITCH, PIN_OUTPUT, PIN_PUSH_PULL, PIN_PULL_UP, 0 ); 233 | } 234 | 235 | void SX1276AntSwDeInit( void ) 236 | { 237 | // GpioInit( &AntSwitch, RADIO_ANT_SWITCH, PIN_OUTPUT, PIN_PUSH_PULL, PIN_NO_PULL, 0 ); 238 | } 239 | 240 | void SX1276SetAntSw( uint8_t opMode ) 241 | { 242 | switch( opMode ) 243 | { 244 | case RFLR_OPMODE_TRANSMITTER: 245 | GpioWrite( &AntSwitch, 1 ); 246 | break; 247 | case RFLR_OPMODE_RECEIVER: 248 | case RFLR_OPMODE_RECEIVER_SINGLE: 249 | case RFLR_OPMODE_CAD: 250 | default: 251 | GpioWrite( &AntSwitch, 0 ); 252 | break; 253 | } 254 | } 255 | 256 | bool SX1276CheckRfFrequency( uint32_t frequency ) 257 | { 258 | // Implement check. Currently all frequencies are supported 259 | return true; 260 | } 261 | #endif -------------------------------------------------------------------------------- /src/loramac/LoRaMacConfirmQueue.c: -------------------------------------------------------------------------------- 1 | /* 2 | / _____) _ | | 3 | ( (____ _____ ____ _| |_ _____ ____| |__ 4 | \____ \| ___ | (_ _) ___ |/ ___) _ \ 5 | _____) ) ____| | | || |_| ____( (___| | | | 6 | (______/|_____)_|_|_| \__)_____)\____)_| |_| 7 | (C)2013 Semtech 8 | ___ _____ _ ___ _ _____ ___ ___ ___ ___ 9 | / __|_ _/_\ / __| |/ / __/ _ \| _ \/ __| __| 10 | \__ \ | |/ _ \ (__| ' <| _| (_) | / (__| _| 11 | |___/ |_/_/ \_\___|_|\_\_| \___/|_|_\\___|___| 12 | embedded.connectivity.solutions=============== 13 | 14 | Description: LoRa MAC confirm queue implementation 15 | 16 | License: Revised BSD License, see LICENSE.TXT file include in the project 17 | 18 | Maintainer: Miguel Luis ( Semtech ), Gregory Cristian ( Semtech ) and Daniel Jaeckle ( STACKFORCE ) 19 | */ 20 | #include 21 | #include 22 | #include 23 | 24 | #include "../driver/timer.h" 25 | #include "../loramac/utilities.h" 26 | #include "../loramac/LoRaMac.h" 27 | #include "../loramac/LoRaMacConfirmQueue.h" 28 | 29 | 30 | static LoRaMacPrimitives_t* Primitives; 31 | 32 | /*! 33 | * MlmeConfirm queue data structure 34 | */ 35 | static MlmeConfirmQueue_t MlmeConfirmQueue[LORA_MAC_MLME_CONFIRM_QUEUE_LEN]; 36 | 37 | /*! 38 | * Counts the number of MlmeConfirms to process 39 | */ 40 | static uint8_t MlmeConfirmQueueCnt; 41 | 42 | /*! 43 | * Pointer to the first element of the ring buffer 44 | */ 45 | MlmeConfirmQueue_t* BufferStart; 46 | 47 | /*! 48 | * Pointer to the last element of the ring buffer 49 | */ 50 | MlmeConfirmQueue_t* BufferEnd; 51 | 52 | /*! 53 | * Variable which holds a common status 54 | */ 55 | LoRaMacEventInfoStatus_t CommonStatus; 56 | 57 | 58 | static MlmeConfirmQueue_t* IncreaseBufferPointer( MlmeConfirmQueue_t* bufferPointer ) 59 | { 60 | if( bufferPointer == &MlmeConfirmQueue[LORA_MAC_MLME_CONFIRM_QUEUE_LEN - 1] ) 61 | { 62 | // Reset to the first element 63 | bufferPointer = MlmeConfirmQueue; 64 | } 65 | else 66 | { 67 | // Increase 68 | bufferPointer++; 69 | } 70 | return bufferPointer; 71 | } 72 | 73 | static MlmeConfirmQueue_t* DecreaseBufferPointer( MlmeConfirmQueue_t* bufferPointer ) 74 | { 75 | if( bufferPointer == MlmeConfirmQueue ) 76 | { 77 | // Reset to the last element 78 | bufferPointer = &MlmeConfirmQueue[LORA_MAC_MLME_CONFIRM_QUEUE_LEN - 1]; 79 | } 80 | else 81 | { 82 | bufferPointer--; 83 | } 84 | return bufferPointer; 85 | } 86 | 87 | static MlmeConfirmQueue_t* GetElement( Mlme_t request, MlmeConfirmQueue_t* bufferStart, MlmeConfirmQueue_t* bufferEnd ) 88 | { 89 | MlmeConfirmQueue_t* element = bufferStart; 90 | 91 | do 92 | { 93 | if( element->Request == request ) 94 | { 95 | // We have found the element 96 | return element; 97 | } 98 | else 99 | { 100 | element = IncreaseBufferPointer( element ); 101 | } 102 | }while( element != bufferEnd ); 103 | 104 | return NULL; 105 | } 106 | 107 | 108 | void LoRaMacConfirmQueueInit( LoRaMacPrimitives_t* primitives ) 109 | { 110 | Primitives = primitives; 111 | 112 | // Init counter 113 | MlmeConfirmQueueCnt = 0; 114 | 115 | // Init buffer 116 | BufferStart = MlmeConfirmQueue; 117 | BufferEnd = MlmeConfirmQueue; 118 | 119 | memset1( (uint8_t*) MlmeConfirmQueue, 0xFF, sizeof( MlmeConfirmQueue ) ); 120 | 121 | // Common status 122 | CommonStatus = LORAMAC_EVENT_INFO_STATUS_ERROR; 123 | } 124 | 125 | bool LoRaMacConfirmQueueAdd( MlmeConfirmQueue_t* mlmeConfirm ) 126 | { 127 | if( MlmeConfirmQueueCnt >= LORA_MAC_MLME_CONFIRM_QUEUE_LEN ) 128 | { 129 | // Protect the buffer against overwrites 130 | return false; 131 | } 132 | 133 | // Add the element to the ring buffer 134 | BufferEnd->Request = mlmeConfirm->Request; 135 | BufferEnd->Status = mlmeConfirm->Status; 136 | BufferEnd->RestrictCommonReadyToHandle = mlmeConfirm->RestrictCommonReadyToHandle; 137 | BufferEnd->ReadyToHandle = false; 138 | // Increase counter 139 | MlmeConfirmQueueCnt++; 140 | // Update end pointer 141 | BufferEnd = IncreaseBufferPointer( BufferEnd ); 142 | 143 | return true; 144 | } 145 | 146 | bool LoRaMacConfirmQueueRemoveLast( void ) 147 | { 148 | if( MlmeConfirmQueueCnt == 0 ) 149 | { 150 | return false; 151 | } 152 | 153 | // Increase counter 154 | MlmeConfirmQueueCnt--; 155 | // Update start pointer 156 | BufferEnd = DecreaseBufferPointer( BufferEnd ); 157 | 158 | return true; 159 | } 160 | 161 | bool LoRaMacConfirmQueueRemoveFirst( void ) 162 | { 163 | if( MlmeConfirmQueueCnt == 0 ) 164 | { 165 | return false; 166 | } 167 | 168 | // Increase counter 169 | MlmeConfirmQueueCnt--; 170 | // Update start pointer 171 | BufferStart = IncreaseBufferPointer( BufferStart ); 172 | 173 | return true; 174 | } 175 | 176 | void LoRaMacConfirmQueueSetStatus( LoRaMacEventInfoStatus_t status, Mlme_t request ) 177 | { 178 | MlmeConfirmQueue_t* element = NULL; 179 | 180 | if( MlmeConfirmQueueCnt > 0 ) 181 | { 182 | element = GetElement( request, BufferStart, BufferEnd ); 183 | if( element != NULL ) 184 | { 185 | element->Status = status; 186 | element->ReadyToHandle = true; 187 | } 188 | } 189 | } 190 | 191 | LoRaMacEventInfoStatus_t LoRaMacConfirmQueueGetStatus( Mlme_t request ) 192 | { 193 | MlmeConfirmQueue_t* element = NULL; 194 | 195 | if( MlmeConfirmQueueCnt > 0 ) 196 | { 197 | element = GetElement( request, BufferStart, BufferEnd ); 198 | if( element != NULL ) 199 | { 200 | return element->Status; 201 | } 202 | } 203 | return LORAMAC_EVENT_INFO_STATUS_ERROR; 204 | } 205 | 206 | void LoRaMacConfirmQueueSetStatusCmn( LoRaMacEventInfoStatus_t status ) 207 | { 208 | MlmeConfirmQueue_t* element = BufferStart; 209 | 210 | CommonStatus = status; 211 | 212 | if( MlmeConfirmQueueCnt > 0 ) 213 | { 214 | do 215 | { 216 | element->Status = status; 217 | // Set the status if it is allowed to set it with a call to 218 | // LoRaMacConfirmQueueSetStatusCmn. 219 | if( element->RestrictCommonReadyToHandle == false ) 220 | { 221 | element->ReadyToHandle = true; 222 | } 223 | element = IncreaseBufferPointer( element ); 224 | }while( element != BufferEnd ); 225 | } 226 | } 227 | 228 | LoRaMacEventInfoStatus_t LoRaMacConfirmQueueGetStatusCmn( void ) 229 | { 230 | return CommonStatus; 231 | } 232 | 233 | bool LoRaMacConfirmQueueIsCmdActive( Mlme_t request ) 234 | { 235 | if( GetElement( request, BufferStart, BufferEnd ) != NULL ) 236 | { 237 | return true; 238 | } 239 | return false; 240 | } 241 | 242 | void LoRaMacConfirmQueueHandleCb( MlmeConfirm_t* mlmeConfirm ) 243 | { 244 | uint8_t nbElements = MlmeConfirmQueueCnt; 245 | bool readyToHandle = false; 246 | MlmeConfirmQueue_t mlmeConfirmToStore; 247 | 248 | for( uint8_t i = 0; i < nbElements; i++ ) 249 | { 250 | mlmeConfirm->MlmeRequest = BufferStart->Request; 251 | mlmeConfirm->Status = BufferStart->Status; 252 | readyToHandle = BufferStart->ReadyToHandle; 253 | 254 | if( readyToHandle == true ) 255 | { 256 | Primitives->MacMlmeConfirm( mlmeConfirm ); 257 | } 258 | else 259 | { 260 | // The request is not processed yet. Store the state. 261 | mlmeConfirmToStore.Request = BufferStart->Request; 262 | mlmeConfirmToStore.Status = BufferStart->Status; 263 | mlmeConfirmToStore.RestrictCommonReadyToHandle = BufferStart->RestrictCommonReadyToHandle; 264 | } 265 | 266 | // Increase the pointer afterwards to prevent overwrites 267 | LoRaMacConfirmQueueRemoveFirst( ); 268 | 269 | if( readyToHandle == false ) 270 | { 271 | // Add a request which has not been finished again to the queue 272 | LoRaMacConfirmQueueAdd( &mlmeConfirmToStore ); 273 | } 274 | } 275 | } 276 | 277 | uint8_t LoRaMacConfirmQueueGetCnt( void ) 278 | { 279 | return MlmeConfirmQueueCnt; 280 | } 281 | 282 | bool LoRaMacConfirmQueueIsFull( void ) 283 | { 284 | if( MlmeConfirmQueueCnt >= LORA_MAC_MLME_CONFIRM_QUEUE_LEN ) 285 | { 286 | return true; 287 | } 288 | else 289 | { 290 | return false; 291 | } 292 | } 293 | -------------------------------------------------------------------------------- /src/loramac/LoRaMacCrypto.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2015-2017 Alibaba Group Holding Limited 3 | */ 4 | 5 | /* 6 | / _____) _ | | 7 | ( (____ _____ ____ _| |_ _____ ____| |__ 8 | \____ \| ___ | (_ _) ___ |/ ___) _ \ 9 | _____) ) ____| | | || |_| ____( (___| | | | 10 | (______/|_____)_|_|_| \__)_____)\____)_| |_| 11 | (C)2013 Semtech 12 | ___ _____ _ ___ _ _____ ___ ___ ___ ___ 13 | / __|_ _/_\ / __| |/ / __/ _ \| _ \/ __| __| 14 | \__ \ | |/ _ \ (__| ' <| _| (_) | / (__| _| 15 | |___/ |_/_/ \_\___|_|\_\_| \___/|_|_\\___|___| 16 | embedded.connectivity.solutions=============== 17 | 18 | Description: LoRa MAC layer implementation 19 | 20 | License: Revised BSD License, see LICENSE.TXT file include in the project 21 | 22 | Maintainer: Miguel Luis ( Semtech ), Gregory Cristian ( Semtech ) and Daniel Jaeckle ( STACKFORCE ) 23 | */ 24 | #include 25 | #include 26 | #include "../loramac/utilities.h" 27 | 28 | #include "../loramac/aes.h" 29 | #include "../loramac/cmac.h" 30 | 31 | #include "../loramac/LoRaMacCrypto.h" 32 | 33 | /*! 34 | * CMAC/AES Message Integrity Code (MIC) Block B0 size 35 | */ 36 | #define LORAMAC_MIC_BLOCK_B0_SIZE 16 37 | 38 | /*! 39 | * MIC field computation initial data 40 | */ 41 | static uint8_t MicBlockB0[] = { 0x49, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 42 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 43 | }; 44 | 45 | /*! 46 | * Contains the computed MIC field. 47 | * 48 | * \remark Only the 4 first bytes are used 49 | */ 50 | static uint8_t Mic[16]; 51 | 52 | /*! 53 | * Encryption aBlock and sBlock 54 | */ 55 | static uint8_t aBlock[] = { 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 56 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 57 | }; 58 | static uint8_t sBlock[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 59 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 60 | }; 61 | 62 | /*! 63 | * AES computation context variable 64 | */ 65 | static aes_context AesContext; 66 | 67 | /*! 68 | * CMAC computation context variable 69 | */ 70 | static AES_CMAC_CTX AesCmacCtx[1]; 71 | 72 | /*! 73 | * \brief Computes the LoRaMAC frame MIC field 74 | * 75 | * \param [IN] buffer Data buffer 76 | * \param [IN] size Data buffer size 77 | * \param [IN] key AES key to be used 78 | * \param [IN] address Frame address 79 | * \param [IN] dir Frame direction [0: uplink, 1: downlink] 80 | * \param [IN] sequenceCounter Frame sequence counter 81 | * \param [OUT] mic Computed MIC field 82 | */ 83 | void LoRaMacComputeMic( const uint8_t *buffer, uint16_t size, const uint8_t *key, uint32_t address, uint8_t dir, uint32_t sequenceCounter, uint32_t *mic ) 84 | { 85 | MicBlockB0[5] = dir; 86 | 87 | MicBlockB0[6] = ( address ) & 0xFF; 88 | MicBlockB0[7] = ( address >> 8 ) & 0xFF; 89 | MicBlockB0[8] = ( address >> 16 ) & 0xFF; 90 | MicBlockB0[9] = ( address >> 24 ) & 0xFF; 91 | 92 | MicBlockB0[10] = ( sequenceCounter ) & 0xFF; 93 | MicBlockB0[11] = ( sequenceCounter >> 8 ) & 0xFF; 94 | MicBlockB0[12] = ( sequenceCounter >> 16 ) & 0xFF; 95 | MicBlockB0[13] = ( sequenceCounter >> 24 ) & 0xFF; 96 | 97 | MicBlockB0[15] = size & 0xFF; 98 | 99 | AES_CMAC_Init( AesCmacCtx ); 100 | 101 | AES_CMAC_SetKey( AesCmacCtx, key ); 102 | 103 | AES_CMAC_Update( AesCmacCtx, MicBlockB0, LORAMAC_MIC_BLOCK_B0_SIZE ); 104 | 105 | AES_CMAC_Update( AesCmacCtx, buffer, size & 0xFF ); 106 | 107 | AES_CMAC_Final( Mic, AesCmacCtx ); 108 | 109 | *mic = ( uint32_t )( ( uint32_t )Mic[3] << 24 | ( uint32_t )Mic[2] << 16 | ( uint32_t )Mic[1] << 8 | ( uint32_t )Mic[0] ); 110 | } 111 | 112 | void LoRaMacPayloadEncrypt( const uint8_t *buffer, uint16_t size, const uint8_t *key, uint32_t address, uint8_t dir, uint32_t sequenceCounter, uint8_t *encBuffer ) 113 | { 114 | uint16_t i; 115 | uint8_t bufferIndex = 0; 116 | uint16_t ctr = 1; 117 | 118 | memset1( AesContext.ksch, '\0', 240 ); 119 | lorawan_aes_set_key( key, 16, &AesContext ); 120 | 121 | aBlock[5] = dir; 122 | 123 | aBlock[6] = ( address ) & 0xFF; 124 | aBlock[7] = ( address >> 8 ) & 0xFF; 125 | aBlock[8] = ( address >> 16 ) & 0xFF; 126 | aBlock[9] = ( address >> 24 ) & 0xFF; 127 | 128 | aBlock[10] = ( sequenceCounter ) & 0xFF; 129 | aBlock[11] = ( sequenceCounter >> 8 ) & 0xFF; 130 | aBlock[12] = ( sequenceCounter >> 16 ) & 0xFF; 131 | aBlock[13] = ( sequenceCounter >> 24 ) & 0xFF; 132 | 133 | while( size >= 16 ) 134 | { 135 | aBlock[15] = ( ( ctr ) & 0xFF ); 136 | ctr++; 137 | lora_aes_encrypt( aBlock, sBlock, &AesContext ); 138 | for( i = 0; i < 16; i++ ) 139 | { 140 | encBuffer[bufferIndex + i] = buffer[bufferIndex + i] ^ sBlock[i]; 141 | } 142 | size -= 16; 143 | bufferIndex += 16; 144 | } 145 | 146 | if( size > 0 ) 147 | { 148 | aBlock[15] = ( ( ctr ) & 0xFF ); 149 | lora_aes_encrypt( aBlock, sBlock, &AesContext ); 150 | for( i = 0; i < size; i++ ) 151 | { 152 | encBuffer[bufferIndex + i] = buffer[bufferIndex + i] ^ sBlock[i]; 153 | } 154 | } 155 | } 156 | 157 | void LoRaMacPayloadDecrypt( const uint8_t *buffer, uint16_t size, const uint8_t *key, uint32_t address, uint8_t dir, uint32_t sequenceCounter, uint8_t *decBuffer ) 158 | { 159 | LoRaMacPayloadEncrypt( buffer, size, key, address, dir, sequenceCounter, decBuffer ); 160 | } 161 | 162 | void LoRaMacJoinComputeMic( const uint8_t *buffer, uint16_t size, const uint8_t *key, uint32_t *mic ) 163 | { 164 | AES_CMAC_Init( AesCmacCtx ); 165 | 166 | AES_CMAC_SetKey( AesCmacCtx, key ); 167 | 168 | AES_CMAC_Update( AesCmacCtx, buffer, size & 0xFF ); 169 | 170 | AES_CMAC_Final( Mic, AesCmacCtx ); 171 | 172 | *mic = ( uint32_t )( ( uint32_t )Mic[3] << 24 | ( uint32_t )Mic[2] << 16 | ( uint32_t )Mic[1] << 8 | ( uint32_t )Mic[0] ); 173 | } 174 | 175 | void LoRaMacJoinDecrypt( const uint8_t *buffer, uint16_t size, const uint8_t *key, uint8_t *decBuffer ) 176 | { 177 | memset1( AesContext.ksch, '\0', 240 ); 178 | lorawan_aes_set_key( key, 16, &AesContext ); 179 | lora_aes_encrypt( buffer, decBuffer, &AesContext ); 180 | // Check if optional CFList is included 181 | if( size >= 16 ) 182 | { 183 | lora_aes_encrypt( buffer + 16, decBuffer + 16, &AesContext ); 184 | } 185 | } 186 | 187 | void LoRaMacJoinComputeSKeys( const uint8_t *key, const uint8_t *appNonce, uint16_t devNonce, uint8_t *nwkSKey, uint8_t *appSKey ) 188 | { 189 | uint8_t nonce[16]; 190 | uint8_t *pDevNonce = ( uint8_t * )&devNonce; 191 | 192 | memset1( AesContext.ksch, '\0', 240 ); 193 | lorawan_aes_set_key( key, 16, &AesContext ); 194 | 195 | memset1( nonce, 0, sizeof( nonce ) ); 196 | nonce[0] = 0x01; 197 | memcpy1( nonce + 1, appNonce, 6 ); 198 | memcpy1( nonce + 7, pDevNonce, 2 ); 199 | lora_aes_encrypt( nonce, nwkSKey, &AesContext ); 200 | 201 | memset1( nonce, 0, sizeof( nonce ) ); 202 | nonce[0] = 0x02; 203 | memcpy1( nonce + 1, appNonce, 6 ); 204 | memcpy1( nonce + 7, pDevNonce, 2 ); 205 | lora_aes_encrypt( nonce, appSKey, &AesContext ); 206 | } 207 | 208 | void LoRaMacBeaconComputePingOffset( uint64_t beaconTime, uint32_t address, uint16_t pingPeriod, uint16_t *pingOffset ) 209 | { 210 | uint8_t zeroKey[16]; 211 | uint8_t buffer[16]; 212 | uint8_t cipher[16]; 213 | uint32_t result = 0; 214 | /* Refer to chapter 15.2 of the LoRaWAN specification v1.1. The beacon time 215 | * GPS time in seconds modulo 2^32 216 | */ 217 | uint32_t time = ( beaconTime % ( ( ( uint64_t ) 1 ) << 32 ) ); 218 | 219 | memset1( zeroKey, 0, 16 ); 220 | memset1( buffer, 0, 16 ); 221 | memset1( cipher, 0, 16 ); 222 | memset1( AesContext.ksch, '\0', 240 ); 223 | 224 | buffer[0] = ( time ) & 0xFF; 225 | buffer[1] = ( time >> 8 ) & 0xFF; 226 | buffer[2] = ( time >> 16 ) & 0xFF; 227 | buffer[3] = ( time >> 24 ) & 0xFF; 228 | 229 | buffer[4] = ( address ) & 0xFF; 230 | buffer[5] = ( address >> 8 ) & 0xFF; 231 | buffer[6] = ( address >> 16 ) & 0xFF; 232 | buffer[7] = ( address >> 24 ) & 0xFF; 233 | 234 | lorawan_aes_set_key( zeroKey, 16, &AesContext ); 235 | lora_aes_encrypt( buffer, cipher, &AesContext ); 236 | 237 | result = ( ( ( uint32_t ) cipher[0] ) + ( ( ( uint32_t ) cipher[1] ) * 256 ) ); 238 | 239 | *pingOffset = ( uint16_t )( result % pingPeriod ); 240 | } 241 | -------------------------------------------------------------------------------- /src/loramac/utilities.h: -------------------------------------------------------------------------------- 1 | /* 2 | / _____) _ | | 3 | ( (____ _____ ____ _| |_ _____ ____| |__ 4 | \____ \| ___ | (_ _) ___ |/ ___) _ \ 5 | _____) ) ____| | | || |_| ____( (___| | | | 6 | (______/|_____)_|_|_| \__)_____)\____)_| |_| 7 | (C)2013 Semtech 8 | 9 | Description: Helper functions implementation 10 | 11 | License: Revised BSD License, see LICENSE.TXT file include in the project 12 | 13 | Maintainer: Miguel Luis and Gregory Cristian 14 | */ 15 | /****************************************************************************** 16 | * @file utilities.h 17 | * @author MCD Application Team 18 | * @version V1.1.1 19 | * @date 01-June-2017 20 | * @brief Header for driver utilities.c module 21 | ****************************************************************************** 22 | * @attention 23 | * 24 | *

© Copyright (c) 2017 STMicroelectronics International N.V. 25 | * All rights reserved.

26 | * 27 | * Redistribution and use in source and binary forms, with or without 28 | * modification, are permitted, provided that the following conditions are met: 29 | * 30 | * 1. Redistribution of source code must retain the above copyright notice, 31 | * this list of conditions and the following disclaimer. 32 | * 2. Redistributions in binary form must reproduce the above copyright notice, 33 | * this list of conditions and the following disclaimer in the documentation 34 | * and/or other materials provided with the distribution. 35 | * 3. Neither the name of STMicroelectronics nor the names of other 36 | * contributors to this software may be used to endorse or promote products 37 | * derived from this software without specific written permission. 38 | * 4. This software, including modifications and/or derivative works of this 39 | * software, must execute solely and exclusively on microcontroller or 40 | * microprocessor devices manufactured by or for STMicroelectronics. 41 | * 5. Redistribution and use of this software other than as permitted under 42 | * this license is void and will automatically terminate your rights under 43 | * this license. 44 | * 45 | * THIS SOFTWARE IS PROVIDED BY STMICROELECTRONICS AND CONTRIBUTORS "AS IS" 46 | * AND ANY EXPRESS, IMPLIED OR STATUTORY WARRANTIES, INCLUDING, BUT NOT 47 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A 48 | * PARTICULAR PURPOSE AND NON-INFRINGEMENT OF THIRD PARTY INTELLECTUAL PROPERTY 49 | * RIGHTS ARE DISCLAIMED TO THE FULLEST EXTENT PERMITTED BY LAW. IN NO EVENT 50 | * SHALL STMICROELECTRONICS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 51 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 52 | * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, 53 | * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 54 | * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 55 | * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, 56 | * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 57 | * 58 | ****************************************************************************** 59 | */ 60 | #ifndef __UTILITIES_H__ 61 | #define __UTILITIES_H__ 62 | 63 | #ifdef __cplusplus 64 | extern "C" { 65 | #endif 66 | 67 | /* prepocessor directive to align buffer*/ 68 | #define ALIGN(n) __attribute__((aligned(n))) 69 | #include 70 | #include 71 | 72 | #define TIMERTIME_T_MAX ( ( uint32_t )~0 ) 73 | #ifndef TimerTime_t 74 | typedef uint64_t TimerTime_t; 75 | #endif 76 | 77 | /*! 78 | * \brief Returns the minimum value between a and b 79 | * 80 | * \param [IN] a 1st value 81 | * \param [IN] b 2nd value 82 | * \retval minValue Minimum value 83 | */ 84 | #ifndef MIN 85 | #define MIN( a, b ) ( ( ( a ) < ( b ) ) ? ( a ) : ( b ) ) 86 | #endif 87 | 88 | /*! 89 | * \brief Returns the maximum value between a and b 90 | * 91 | * \param [IN] a 1st value 92 | * \param [IN] b 2nd value 93 | * \retval maxValue Maximum value 94 | */ 95 | #ifndef MAX 96 | #define MAX( a, b ) ( ( ( a ) > ( b ) ) ? ( a ) : ( b ) ) 97 | #endif 98 | 99 | /*! 100 | * \brief Returns 2 raised to the power of n 101 | * 102 | * \param [IN] n power value 103 | * \retval result of raising 2 to the power n 104 | */ 105 | #define POW2( n ) ( 1 << n ) 106 | 107 | /*! 108 | * \brief Initializes the pseudo random generator initial value 109 | * 110 | * \param [IN] seed Pseudo random generator initial value 111 | */ 112 | void srand1( uint32_t seed ); 113 | 114 | int32_t rand1( void ); 115 | /*! 116 | * \brief Computes a random number between min and max 117 | * 118 | * \param [IN] min range minimum value 119 | * \param [IN] max range maximum value 120 | * \retval random random value in range min..max 121 | */ 122 | int32_t randr( int32_t min, int32_t max ); 123 | 124 | /*! 125 | * \brief Copies size elements of src array to dst array 126 | * 127 | * \remark STM32 Standard memcpy function only works on pointers that are aligned 128 | * 129 | * \param [OUT] dst Destination array 130 | * \param [IN] src Source array 131 | * \param [IN] size Number of bytes to be copied 132 | */ 133 | void memcpy1( uint8_t *dst, const uint8_t *src, uint16_t size ); 134 | 135 | /*! 136 | * \brief Copies size elements of src array to dst array reversing the byte order 137 | * 138 | * \param [OUT] dst Destination array 139 | * \param [IN] src Source array 140 | * \param [IN] size Number of bytes to be copied 141 | */ 142 | void memcpyr( uint8_t *dst, const uint8_t *src, uint16_t size ); 143 | 144 | /*! 145 | * \brief Set size elements of dst array with value 146 | * 147 | * \remark STM32 Standard memset function only works on pointers that are aligned 148 | * 149 | * \param [OUT] dst Destination array 150 | * \param [IN] value Default value 151 | * \param [IN] size Number of bytes to be copied 152 | */ 153 | void memset1( uint8_t *dst, uint8_t value, uint16_t size ); 154 | 155 | /*! 156 | * \brief Converts a nibble to an hexadecimal character 157 | * 158 | * \param [IN] a Nibble to be converted 159 | * \retval hexChar Converted hexadecimal character 160 | */ 161 | int8_t Nibble2HexChar( uint8_t a ); 162 | 163 | char * strtok_l (char *s, const char *delim); 164 | 165 | /*! 166 | * LMN (LoRaMac-node) status 167 | */ 168 | typedef enum LmnStatus_e 169 | { 170 | LMN_STATUS_ERROR = 0, 171 | LMN_STATUS_OK = !LMN_STATUS_ERROR 172 | } LmnStatus_t; 173 | 174 | 175 | /*! 176 | * Version 177 | */ 178 | typedef union Version_u 179 | { 180 | struct Version_s 181 | { 182 | uint8_t Revision; 183 | uint8_t Patch; 184 | uint8_t Minor; 185 | uint8_t Major; 186 | }Fields; 187 | uint32_t Value; 188 | }Version_t; 189 | 190 | 191 | /*! 192 | * \brief Computes a CCITT 32 bits CRC 193 | * 194 | * \param [IN] buffer Data buffer used to compute the CRC 195 | * \param [IN] length Data buffer length 196 | * 197 | * \retval crc The computed buffer of length CRC 198 | */ 199 | uint32_t Crc32( uint8_t *buffer, uint16_t length ); 200 | 201 | /*! 202 | * \brief Computes the initial value of the CCITT 32 bits CRC. This function 203 | * can be used with functions \ref Crc32Update and \ref Crc32Finalize. 204 | * 205 | * \retval crc Initial crc value. 206 | */ 207 | uint32_t Crc32Init( void ); 208 | 209 | /*! 210 | * \brief Updates the value of the crc value. 211 | * 212 | * \param [IN] crcInit Previous or initial crc value. 213 | * \param [IN] buffer Data pointer. 214 | * \param [IN] length Length of the data. 215 | * 216 | * \retval crc Updated crc value. 217 | */ 218 | uint32_t Crc32Update( uint32_t crcInit, uint8_t *buffer, uint16_t length ); 219 | 220 | /*! 221 | * \brief Finalizes the crc value after the calls to \ref Crc32Update. 222 | * 223 | * \param [IN] crc Recent crc value. 224 | * 225 | * \retval crc Updated crc value. 226 | */ 227 | uint32_t Crc32Finalize( uint32_t crc ); 228 | 229 | /*! 230 | * Begins critical section 231 | */ 232 | #define CRITICAL_SECTION_BEGIN( ) 233 | 234 | /*! 235 | * Ends critical section 236 | */ 237 | #define CRITICAL_SECTION_END( ) 238 | 239 | /* 240 | * ============================================================================ 241 | * Following functions must be implemented inside the specific platform 242 | * board.c file. 243 | * ============================================================================ 244 | */ 245 | /*! 246 | * Disable interrupts, begins critical section 247 | * 248 | * \param [IN] mask Pointer to a variable where to store the CPU IRQ mask 249 | */ 250 | void BoardCriticalSectionBegin( uint32_t *mask ); 251 | 252 | /*! 253 | * Ends critical section 254 | * 255 | * \param [IN] mask Pointer to a variable where the CPU IRQ mask was stored 256 | */ 257 | void BoardCriticalSectionEnd( uint32_t *mask ); 258 | 259 | 260 | #ifdef __cplusplus 261 | } 262 | #endif 263 | 264 | #endif // __UTILITIES_H__ 265 | -------------------------------------------------------------------------------- /src/loramac/region/RegionCommon.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2015-2017 Alibaba Group Holding Limited 3 | */ 4 | 5 | /*! 6 | * \file RegionCommon.h 7 | * 8 | * \brief Region independent implementations which are common to all regions. 9 | * 10 | * \copyright Revised BSD License, see section \ref LICENSE. 11 | * 12 | * \code 13 | * ______ _ 14 | * / _____) _ | | 15 | * ( (____ _____ ____ _| |_ _____ ____| |__ 16 | * \____ \| ___ | (_ _) ___ |/ ___) _ \ 17 | * _____) ) ____| | | || |_| ____( (___| | | | 18 | * (______/|_____)_|_|_| \__)_____)\____)_| |_| 19 | * (C)2013 Semtech 20 | * 21 | * ___ _____ _ ___ _ _____ ___ ___ ___ ___ 22 | * / __|_ _/_\ / __| |/ / __/ _ \| _ \/ __| __| 23 | * \__ \ | |/ _ \ (__| ' <| _| (_) | / (__| _| 24 | * |___/ |_/_/ \_\___|_|\_\_| \___/|_|_\\___|___| 25 | * embedded.connectivity.solutions=============== 26 | * 27 | * \endcode 28 | * 29 | * \author Miguel Luis ( Semtech ) 30 | * 31 | * \author Gregory Cristian ( Semtech ) 32 | * 33 | * \author Daniel Jaeckle ( STACKFORCE ) 34 | * 35 | * \defgroup REGIONCOMMON Common region implementation 36 | * Region independent implementations which are common to all regions. 37 | * \{ 38 | */ 39 | #ifndef __REGIONCOMMON_H__ 40 | #define __REGIONCOMMON_H__ 41 | 42 | typedef struct sLinkAdrParams 43 | { 44 | /*! 45 | * Number of repetitions. 46 | */ 47 | uint8_t NbRep; 48 | /*! 49 | * Datarate. 50 | */ 51 | int8_t Datarate; 52 | /*! 53 | * Tx power. 54 | */ 55 | int8_t TxPower; 56 | /*! 57 | * Channels mask control field. 58 | */ 59 | uint8_t ChMaskCtrl; 60 | /*! 61 | * Channels mask field. 62 | */ 63 | uint16_t ChMask; 64 | }LinkAdrParams_t; 65 | typedef struct sRegionCommonRxBeaconSetupParams 66 | { 67 | /*! 68 | * A pointer to the available datarates. 69 | */ 70 | const uint8_t* Datarates; 71 | /*! 72 | * Frequency 73 | */ 74 | uint32_t Frequency; 75 | /*! 76 | * The size of the beacon frame. 77 | */ 78 | uint8_t BeaconSize; 79 | /*! 80 | * The datarate of the beacon. 81 | */ 82 | uint8_t BeaconDatarate; 83 | /*! 84 | * The channel bandwidth of the beacon. 85 | */ 86 | uint8_t BeaconChannelBW; 87 | /*! 88 | * The RX time. 89 | */ 90 | uint32_t RxTime; 91 | /*! 92 | * The symbol timeout of the RX procedure. 93 | */ 94 | uint16_t SymbolTimeout; 95 | }RegionCommonRxBeaconSetupParams_t; 96 | 97 | /*! 98 | * \brief Calculates the join duty cycle. 99 | * This is a generic function and valid for all regions. 100 | * 101 | * \param [IN] elapsedTime Elapsed time since the start of the device. 102 | * 103 | * \retval Duty cycle restriction. 104 | */ 105 | uint16_t RegionCommonGetJoinDc( TimerTime_t elapsedTime ); 106 | 107 | /*! 108 | * \brief Verifies, if a value is in a given range. 109 | * This is a generic function and valid for all regions. 110 | * 111 | * \param [IN] value Value to verify, if it is in range. 112 | * 113 | * \param [IN] min Minimum possible value. 114 | * 115 | * \param [IN] max Maximum possible value. 116 | * 117 | * \retval Returns 1 if the value is in range, otherwise 0. 118 | */ 119 | uint8_t RegionCommonValueInRange( int8_t value, int8_t min, int8_t max ); 120 | 121 | /*! 122 | * \brief Verifies, if a datarate is available on an active channel. 123 | * This is a generic function and valid for all regions. 124 | * 125 | * \param [IN] nbChannels Number of channels. 126 | * 127 | * \param [IN] channelsMask The channels mask of the region. 128 | * 129 | * \param [IN] dr The datarate to verify. 130 | * 131 | * \param [IN] minDr Minimum datarate. 132 | * 133 | * \param [IN] maxDr Maximum datarate. 134 | * 135 | * \param [IN] channels The channels of the region. 136 | * 137 | * \retval Returns true if the datarate is supported, false if not. 138 | */ 139 | bool RegionCommonChanVerifyDr( uint8_t nbChannels, uint16_t* channelsMask, int8_t dr, 140 | int8_t minDr, int8_t maxDr, ChannelParams_t* channels ); 141 | 142 | /*! 143 | * \brief Disables a channel in a given channels mask. 144 | * This is a generic function and valid for all regions. 145 | * 146 | * \param [IN] channelsMask The channels mask of the region. 147 | * 148 | * \param [IN] id The id of the channels mask to disable. 149 | * 150 | * \param [IN] maxChannels Maximum number of channels. 151 | * 152 | * \retval Returns true if the channel could be disabled, false if not. 153 | */ 154 | bool RegionCommonChanDisable( uint16_t* channelsMask, uint8_t id, uint8_t maxChannels ); 155 | 156 | /*! 157 | * \brief Counts the number of active channels in a given channels mask. 158 | * This is a generic function and valid for all regions. 159 | * 160 | * \param [IN] channelsMask The channels mask of the region. 161 | * 162 | * \param [IN] startIdx Start index. 163 | * 164 | * \param [IN] stopIdx Stop index ( the channels of this index will not be counted ). 165 | * 166 | * \retval Returns the number of active channels. 167 | */ 168 | uint8_t RegionCommonCountChannels( uint16_t* channelsMask, uint8_t startIdx, uint8_t stopIdx ); 169 | 170 | /*! 171 | * \brief Copy a channels mask. 172 | * This is a generic function and valid for all regions. 173 | * 174 | * \param [IN] channelsMaskDest The destination channels mask. 175 | * 176 | * \param [IN] channelsMaskSrc The source channels mask. 177 | * 178 | * \param [IN] len The index length to copy. 179 | */ 180 | void RegionCommonChanMaskCopy( uint16_t* channelsMaskDest, uint16_t* channelsMaskSrc, uint8_t len ); 181 | 182 | /*! 183 | * \brief Sets the last tx done property. 184 | * This is a generic function and valid for all regions. 185 | * 186 | * \param [IN] joined Set to true, if the node has joined the network 187 | * 188 | * \param [IN] band The band to be updated. 189 | * 190 | * \param [IN] lastTxDone The time of the last TX done. 191 | */ 192 | void RegionCommonSetBandTxDone( bool joined, Band_t* band, TimerTime_t lastTxDone ); 193 | 194 | /*! 195 | * \brief Updates the time-offs of the bands. 196 | * This is a generic function and valid for all regions. 197 | * 198 | * \param [IN] joined Set to true, if the node has joined the network 199 | * 200 | * \param [IN] dutyCycle Set to true, if the duty cycle is enabled. 201 | * 202 | * \param [IN] bands A pointer to the bands. 203 | * 204 | * \param [IN] nbBands The number of bands available. 205 | * 206 | * \retval Returns the time which must be waited to perform the next uplink. 207 | */ 208 | TimerTime_t RegionCommonUpdateBandTimeOff( bool joined, bool dutyCycle, Band_t* bands, uint8_t nbBands ); 209 | 210 | /*! 211 | * \brief Parses the parameter of an LinkAdrRequest. 212 | * This is a generic function and valid for all regions. 213 | * 214 | * \param [IN] payload Pointer to the payload containing the MAC commands. The payload 215 | * must contain the CMD identifier, following by the parameters. 216 | * 217 | * \param [OUT] parseLinkAdr The function fills the structure with the ADR parameters. 218 | * 219 | * \retval Returns the length of the ADR request, if a request was found. Otherwise, the 220 | * function returns 0. 221 | */ 222 | uint8_t RegionCommonParseLinkAdrReq( uint8_t* payload, LinkAdrParams_t* parseLinkAdr ); 223 | 224 | /*! 225 | * \brief Computes the symbol time for LoRa modulation. 226 | * 227 | * \param [IN] phyDr Physical datarate to use. 228 | * 229 | * \param [IN] bandwidth Bandwidth to use. 230 | * 231 | * \retval Returns the symbol time. 232 | */ 233 | double RegionCommonComputeSymbolTimeLoRa( uint8_t phyDr, uint32_t bandwidth ); 234 | 235 | /*! 236 | * \brief Computes the symbol time for FSK modulation. 237 | * 238 | * \param [IN] phyDr Physical datarate to use. 239 | * 240 | * \param [IN] bandwidth Bandwidth to use. 241 | * 242 | * \retval Returns the symbol time. 243 | */ 244 | double RegionCommonComputeSymbolTimeFsk( uint8_t phyDr ); 245 | 246 | /*! 247 | * \brief Computes the RX window timeout and the RX window offset. 248 | * 249 | * \param [IN] tSymbol Symbol timeout. 250 | * 251 | * \param [IN] minRxSymbols Minimum required number of symbols to detect an Rx frame. 252 | * 253 | * \param [IN] rxError System maximum timing error of the receiver. In milliseconds 254 | * The receiver will turn on in a [-rxError : +rxError] ms interval around RxOffset. 255 | * 256 | * \param [IN] wakeUpTime Wakeup time of the system. 257 | * 258 | * \param [OUT] windowTimeout RX window timeout. 259 | * 260 | * \param [OUT] windowOffset RX window time offset to be applied to the RX delay. 261 | */ 262 | void RegionCommonComputeRxWindowParameters( double tSymbol, uint8_t minRxSymbols, uint32_t rxError, uint32_t wakeUpTime, uint32_t* windowTimeout, int32_t* windowOffset ); 263 | 264 | /*! 265 | * \brief Computes the txPower, based on the max EIRP and the antenna gain. 266 | * 267 | * \param [IN] txPower TX power index. 268 | * 269 | * \param [IN] maxEirp Maximum EIRP. 270 | * 271 | * \param [IN] antennaGain Antenna gain. 272 | * 273 | * \retval Returns the physical TX power. 274 | */ 275 | int8_t RegionCommonComputeTxPower( int8_t txPowerIndex, float maxEirp, float antennaGain ); 276 | 277 | /*! 278 | * \brief Sets up the radio into RX beacon mode. 279 | * 280 | * \param [IN] rxBeaconSetupParams A pointer to the input parameters. 281 | */ 282 | void RegionCommonRxBeaconSetup( RegionCommonRxBeaconSetupParams_t* rxBeaconSetupParams ); 283 | 284 | /*! \} defgroup REGIONCOMMON */ 285 | 286 | #endif // __REGIONCOMMON_H__ 287 | -------------------------------------------------------------------------------- /src/loramac/region/RegionCommon.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2015-2017 Alibaba Group Holding Limited 3 | */ 4 | 5 | /* 6 | / _____) _ | | 7 | ( (____ _____ ____ _| |_ _____ ____| |__ 8 | \____ \| ___ | (_ _) ___ |/ ___) _ \ 9 | _____) ) ____| | | || |_| ____( (___| | | | 10 | (______/|_____)_|_|_| \__)_____)\____)_| |_| 11 | (C)2013 Semtech 12 | ___ _____ _ ___ _ _____ ___ ___ ___ ___ 13 | / __|_ _/_\ / __| |/ / __/ _ \| _ \/ __| __| 14 | \__ \ | |/ _ \ (__| ' <| _| (_) | / (__| _| 15 | |___/ |_/_/ \_\___|_|\_\_| \___/|_|_\\___|___| 16 | embedded.connectivity.solutions=============== 17 | 18 | Description: LoRa MAC common region implementation 19 | 20 | License: Revised BSD License, see LICENSE.TXT file include in the project 21 | 22 | Maintainer: Miguel Luis ( Semtech ), Gregory Cristian ( Semtech ) and Daniel Jaeckle ( STACKFORCE ) 23 | */ 24 | 25 | #include 26 | #include 27 | #include 28 | #include 29 | 30 | 31 | #include "../utilities.h" 32 | #include "../LoRaMac.h" 33 | #include "RegionCommon.h" 34 | 35 | 36 | 37 | #define BACKOFF_DC_1_HOUR 1 38 | #define BACKOFF_DC_10_HOURS 2 39 | #define BACKOFF_DC_24_HOURS 3 40 | 41 | 42 | 43 | static uint8_t CountChannels( uint16_t mask, uint8_t nbBits ) 44 | { 45 | uint8_t nbActiveBits = 0; 46 | 47 | for( uint8_t j = 0; j < nbBits; j++ ) 48 | { 49 | if( ( mask & ( 1 << j ) ) == ( 1 << j ) ) 50 | { 51 | nbActiveBits++; 52 | } 53 | } 54 | return nbActiveBits; 55 | } 56 | 57 | 58 | 59 | uint16_t RegionCommonGetJoinDc( TimerTime_t elapsedTime ) 60 | { 61 | uint16_t dutyCycle = 0; 62 | 63 | if( elapsedTime < 3600000 ) 64 | { 65 | dutyCycle = BACKOFF_DC_1_HOUR; 66 | } 67 | else if( elapsedTime < ( 3600000 + 36000000 ) ) 68 | { 69 | dutyCycle = BACKOFF_DC_10_HOURS; 70 | } 71 | else 72 | { 73 | dutyCycle = BACKOFF_DC_24_HOURS; 74 | } 75 | return dutyCycle; 76 | } 77 | 78 | bool RegionCommonChanVerifyDr( uint8_t nbChannels, uint16_t* channelsMask, int8_t dr, int8_t minDr, int8_t maxDr, ChannelParams_t* channels ) 79 | { 80 | if( RegionCommonValueInRange( dr, minDr, maxDr ) == 0 ) 81 | { 82 | return false; 83 | } 84 | 85 | for( uint8_t i = 0, k = 0; i < nbChannels; i += 16, k++ ) 86 | { 87 | //4.29 workaround for when disable all channles not return server 0306 but return 0304 88 | if (channelsMask[k] == 0) 89 | return true; 90 | for( uint8_t j = 0; j < 16; j++ ) 91 | { 92 | if( ( ( channelsMask[k] & ( 1 << j ) ) != 0 ) ) 93 | {// Check datarate validity for enabled channels 94 | #ifdef CONFIG_LINKWAN 95 | if( RegionCommonValueInRange( dr, ( channels[(i + j) % 8].DrRange.Fields.Min & 0x0F ), 96 | ( channels[(i + j) % 8].DrRange.Fields.Max & 0x0F ) ) == 1 ) 97 | #else 98 | if( RegionCommonValueInRange( dr, ( channels[i + j].DrRange.Fields.Min & 0x0F ), 99 | ( channels[i + j].DrRange.Fields.Max & 0x0F ) ) == 1 ) 100 | #endif 101 | { 102 | // At least 1 channel has been found we can return OK. 103 | return true; 104 | } 105 | } 106 | } 107 | } 108 | return false; 109 | } 110 | 111 | uint8_t RegionCommonValueInRange( int8_t value, int8_t min, int8_t max ) 112 | { 113 | if( ( value >= min ) && ( value <= max ) ) 114 | { 115 | return 1; 116 | } 117 | return 0; 118 | } 119 | 120 | bool RegionCommonChanDisable( uint16_t* channelsMask, uint8_t id, uint8_t maxChannels ) 121 | { 122 | uint8_t index = id / 16; 123 | 124 | if( ( index > ( maxChannels / 16 ) ) || ( id >= maxChannels ) ) 125 | { 126 | return false; 127 | } 128 | 129 | // Deactivate channel 130 | channelsMask[index] &= ~( 1 << ( id % 16 ) ); 131 | 132 | return true; 133 | } 134 | 135 | uint8_t RegionCommonCountChannels( uint16_t* channelsMask, uint8_t startIdx, uint8_t stopIdx ) 136 | { 137 | uint8_t nbChannels = 0; 138 | 139 | if( channelsMask == NULL ) 140 | { 141 | return 0; 142 | } 143 | 144 | for( uint8_t i = startIdx; i < stopIdx; i++ ) 145 | { 146 | #if defined(REGION_US915)||defined(REGION_AU915) 147 | if(i<4) 148 | { 149 | nbChannels += CountChannels( channelsMask[i], 16 ); 150 | } 151 | else 152 | { 153 | nbChannels += CountChannels( channelsMask[i], 8 ); 154 | } 155 | #else 156 | nbChannels += CountChannels( channelsMask[i], 16 ); 157 | #endif 158 | } 159 | 160 | return nbChannels; 161 | } 162 | 163 | void RegionCommonChanMaskCopy( uint16_t* channelsMaskDest, uint16_t* channelsMaskSrc, uint8_t len ) 164 | { 165 | if( ( channelsMaskDest != NULL ) && ( channelsMaskSrc != NULL ) ) 166 | { 167 | for( uint8_t i = 0; i < len; i++ ) 168 | { 169 | channelsMaskDest[i] = channelsMaskSrc[i]; 170 | } 171 | } 172 | } 173 | 174 | void RegionCommonSetBandTxDone( bool joined, Band_t* band, TimerTime_t lastTxDone ) 175 | { 176 | if (joined == true) { 177 | band->LastTxDoneTime = lastTxDone; 178 | } else { 179 | band->LastTxDoneTime = lastTxDone; 180 | band->LastJoinTxDoneTime = lastTxDone; 181 | } 182 | } 183 | 184 | TimerTime_t RegionCommonUpdateBandTimeOff( bool joined, bool dutyCycle, Band_t* bands, uint8_t nbBands ) 185 | { 186 | TimerTime_t nextTxDelay = ( TimerTime_t )( -1 ); 187 | 188 | // Update bands Time OFF 189 | for( uint8_t i = 0; i < nbBands; i++ ) 190 | { 191 | if( joined == false ) 192 | { 193 | uint32_t txDoneTime = MAX( TimerGetElapsedTime( bands[i].LastJoinTxDoneTime ), 194 | ( dutyCycle == true ) ? TimerGetElapsedTime( bands[i].LastTxDoneTime ) : 0 ); 195 | 196 | if( bands[i].TimeOff <= txDoneTime ) 197 | { 198 | bands[i].TimeOff = 0; 199 | } 200 | if( bands[i].TimeOff != 0 ) 201 | { 202 | nextTxDelay = MIN( bands[i].TimeOff - txDoneTime, nextTxDelay ); 203 | } 204 | } 205 | else 206 | { 207 | if( dutyCycle == true ) 208 | { 209 | if( bands[i].TimeOff <= TimerGetElapsedTime( bands[i].LastTxDoneTime ) ) 210 | { 211 | bands[i].TimeOff = 0; 212 | } 213 | if( bands[i].TimeOff != 0 ) 214 | { 215 | nextTxDelay = MIN( bands[i].TimeOff - TimerGetElapsedTime( bands[i].LastTxDoneTime ), 216 | nextTxDelay ); 217 | } 218 | } 219 | else 220 | { 221 | nextTxDelay = 0; 222 | bands[i].TimeOff = 0; 223 | } 224 | } 225 | } 226 | return nextTxDelay; 227 | } 228 | 229 | uint8_t RegionCommonParseLinkAdrReq( uint8_t* payload, LinkAdrParams_t* linkAdrParams ) 230 | { 231 | uint8_t retIndex = 0; 232 | 233 | if( payload[0] == SRV_MAC_LINK_ADR_REQ ) 234 | { 235 | // Parse datarate and tx power 236 | linkAdrParams->Datarate = payload[1]; 237 | linkAdrParams->TxPower = linkAdrParams->Datarate & 0x0F; 238 | linkAdrParams->Datarate = ( linkAdrParams->Datarate >> 4 ) & 0x0F; 239 | // Parse ChMask 240 | linkAdrParams->ChMask = ( uint16_t )payload[2]; 241 | linkAdrParams->ChMask |= ( uint16_t )payload[3] << 8; 242 | // Parse ChMaskCtrl and nbRep 243 | linkAdrParams->NbRep = payload[4]; 244 | linkAdrParams->ChMaskCtrl = ( linkAdrParams->NbRep >> 4 ) & 0x07; 245 | linkAdrParams->NbRep &= 0x0F; 246 | 247 | // LinkAdrReq has 4 bytes length + 1 byte CMD 248 | retIndex = 5; 249 | } 250 | return retIndex; 251 | } 252 | 253 | double RegionCommonComputeSymbolTimeLoRa( uint8_t phyDr, uint32_t bandwidth ) 254 | { 255 | return ( ( double )( 1 << phyDr ) / ( double )bandwidth ) * 1000; 256 | } 257 | 258 | double RegionCommonComputeSymbolTimeFsk( uint8_t phyDr ) 259 | { 260 | return ( 8.0 / ( double )phyDr ); // 1 symbol equals 1 byte 261 | } 262 | 263 | void RegionCommonComputeRxWindowParameters( double tSymbol, uint8_t minRxSymbols, uint32_t rxError, uint32_t wakeUpTime, uint32_t* windowTimeout, int32_t* windowOffset ) 264 | { 265 | *windowTimeout = MAX( ( uint32_t )ceil( ( ( 2 * minRxSymbols - 8 ) * tSymbol + 2 * rxError ) / tSymbol ), minRxSymbols ); // Computed number of symbols 266 | *windowOffset = ( int32_t )ceil( ( 4.0 * tSymbol ) - ( ( *windowTimeout * tSymbol ) / 2.0 ) - wakeUpTime ); 267 | } 268 | 269 | int8_t RegionCommonComputeTxPower( int8_t txPowerIndex, float maxEirp, float antennaGain ) 270 | { 271 | int8_t phyTxPower = 0; 272 | 273 | phyTxPower = ( int8_t )floor( ( maxEirp - ( txPowerIndex * 2U ) ) - antennaGain ); 274 | 275 | return phyTxPower; 276 | } 277 | void RegionCommonRxBeaconSetup( RegionCommonRxBeaconSetupParams_t* rxBeaconSetupParams ) 278 | { 279 | bool rxContinuous = true; 280 | uint8_t datarate; 281 | 282 | // Set the radio into sleep mode 283 | Radio.Sleep( ); 284 | 285 | // Setup frequency and payload length 286 | Radio.SetChannel( rxBeaconSetupParams->Frequency ); 287 | Radio.SetMaxPayloadLength( MODEM_LORA, rxBeaconSetupParams->BeaconSize ); 288 | 289 | // Check the RX continuous mode 290 | if( rxBeaconSetupParams->RxTime != 0 ) 291 | { 292 | rxContinuous = false; 293 | } 294 | 295 | // Get region specific datarate 296 | datarate = rxBeaconSetupParams->Datarates[rxBeaconSetupParams->BeaconDatarate]; 297 | 298 | // Setup radio 299 | Radio.SetRxConfig( MODEM_LORA, rxBeaconSetupParams->BeaconChannelBW, datarate, 300 | 1, 0, 10, rxBeaconSetupParams->SymbolTimeout, true, rxBeaconSetupParams->BeaconSize, false, 0, 0, false, rxContinuous ); 301 | 302 | Radio.Rx( rxBeaconSetupParams->RxTime ); 303 | } 304 | -------------------------------------------------------------------------------- /src/radio/radio_sx127x.h: -------------------------------------------------------------------------------- 1 | /*! 2 | * \file radio.h 3 | * 4 | * \brief Radio driver API definition 5 | * 6 | * \copyright Revised BSD License, see section \ref LICENSE. 7 | * 8 | * \code 9 | * ______ _ 10 | * / _____) _ | | 11 | * ( (____ _____ ____ _| |_ _____ ____| |__ 12 | * \____ \| ___ | (_ _) ___ |/ ___) _ \ 13 | * _____) ) ____| | | || |_| ____( (___| | | | 14 | * (______/|_____)_|_|_| \__)_____)\____)_| |_| 15 | * (C)2013-2017 Semtech 16 | * 17 | * \endcode 18 | * 19 | * \author Miguel Luis ( Semtech ) 20 | * 21 | * \author Gregory Cristian ( Semtech ) 22 | */ 23 | #ifndef __RADIO_H__ 24 | #define __RADIO_H__ 25 | 26 | #include 27 | #include 28 | 29 | /*! 30 | * Radio driver supported modems 31 | */ 32 | typedef enum 33 | { 34 | MODEM_FSK = 0, 35 | MODEM_LORA, 36 | }RadioModems_t; 37 | 38 | /*! 39 | * Radio driver internal state machine states definition 40 | */ 41 | typedef enum 42 | { 43 | RF_IDLE = 0, //!< The radio is idle 44 | RF_RX_RUNNING, //!< The radio is in reception state 45 | RF_TX_RUNNING, //!< The radio is in transmission state 46 | RF_CAD, //!< The radio is doing channel activity detection 47 | }RadioState_t; 48 | 49 | /*! 50 | * \brief Radio driver callback functions 51 | */ 52 | typedef struct 53 | { 54 | /*! 55 | * \brief Tx Done callback prototype. 56 | */ 57 | void ( *TxDone )( void ); 58 | /*! 59 | * \brief Tx Timeout callback prototype. 60 | */ 61 | void ( *TxTimeout )( void ); 62 | /*! 63 | * \brief Rx Done callback prototype. 64 | * 65 | * \param [IN] payload Received buffer pointer 66 | * \param [IN] size Received buffer size 67 | * \param [IN] rssi RSSI value computed while receiving the frame [dBm] 68 | * \param [IN] snr Raw SNR value given by the radio hardware 69 | * FSK : N/A ( set to 0 ) 70 | * LoRa: SNR value in dB 71 | */ 72 | void ( *RxDone )( uint8_t *payload, uint16_t size, int16_t rssi, int8_t snr ); 73 | /*! 74 | * \brief Rx Timeout callback prototype. 75 | */ 76 | void ( *RxTimeout )( void ); 77 | /*! 78 | * \brief Rx Error callback prototype. 79 | */ 80 | void ( *RxError )( void ); 81 | /*! 82 | * \brief FHSS Change Channel callback prototype. 83 | * 84 | * \param [IN] currentChannel Index number of the current channel 85 | */ 86 | void ( *FhssChangeChannel )( uint8_t currentChannel ); 87 | 88 | /*! 89 | * \brief CAD Done callback prototype. 90 | * 91 | * \param [IN] channelDetected Channel Activity detected during the CAD 92 | */ 93 | void ( *CadDone ) ( bool channelActivityDetected ); 94 | }RadioEvents_t; 95 | 96 | /*! 97 | * \brief Radio driver definition 98 | */ 99 | struct Radio_s 100 | { 101 | /*! 102 | * \brief Initializes the radio 103 | * 104 | * \param [IN] events Structure containing the driver callback functions 105 | */ 106 | void ( *Init )( RadioEvents_t *events ); 107 | /*! 108 | * Return current radio status 109 | * 110 | * \param status Radio status.[RF_IDLE, RF_RX_RUNNING, RF_TX_RUNNING] 111 | */ 112 | RadioState_t ( *GetStatus )( void ); 113 | /*! 114 | * \brief Configures the radio with the given modem 115 | * 116 | * \param [IN] modem Modem to be used [0: FSK, 1: LoRa] 117 | */ 118 | void ( *SetModem )( RadioModems_t modem ); 119 | /*! 120 | * \brief Sets the channel frequency 121 | * 122 | * \param [IN] freq Channel RF frequency 123 | */ 124 | void ( *SetChannel )( uint32_t freq ); 125 | /*! 126 | * \brief Checks if the channel is free for the given time 127 | * 128 | * \param [IN] modem Radio modem to be used [0: FSK, 1: LoRa] 129 | * \param [IN] freq Channel RF frequency 130 | * \param [IN] rssiThresh RSSI threshold 131 | * \param [IN] maxCarrierSenseTime Max time while the RSSI is measured 132 | * 133 | * \retval isFree [true: Channel is free, false: Channel is not free] 134 | */ 135 | bool ( *IsChannelFree )( RadioModems_t modem, uint32_t freq, int16_t rssiThresh, uint32_t maxCarrierSenseTime ); 136 | /*! 137 | * \brief Generates a 32 bits random value based on the RSSI readings 138 | * 139 | * \remark This function sets the radio in LoRa modem mode and disables 140 | * all interrupts. 141 | * After calling this function either Radio.SetRxConfig or 142 | * Radio.SetTxConfig functions must be called. 143 | * 144 | * \retval randomValue 32 bits random value 145 | */ 146 | uint32_t ( *Random )( void ); 147 | /*! 148 | * \brief Sets the reception parameters 149 | * 150 | * \param [IN] modem Radio modem to be used [0: FSK, 1: LoRa] 151 | * \param [IN] bandwidth Sets the bandwidth 152 | * FSK : >= 2600 and <= 250000 Hz 153 | * LoRa: [0: 125 kHz, 1: 250 kHz, 154 | * 2: 500 kHz, 3: Reserved] 155 | * \param [IN] datarate Sets the Datarate 156 | * FSK : 600..300000 bits/s 157 | * LoRa: [6: 64, 7: 128, 8: 256, 9: 512, 158 | * 10: 1024, 11: 2048, 12: 4096 chips] 159 | * \param [IN] coderate Sets the coding rate (LoRa only) 160 | * FSK : N/A ( set to 0 ) 161 | * LoRa: [1: 4/5, 2: 4/6, 3: 4/7, 4: 4/8] 162 | * \param [IN] bandwidthAfc Sets the AFC Bandwidth (FSK only) 163 | * FSK : >= 2600 and <= 250000 Hz 164 | * LoRa: N/A ( set to 0 ) 165 | * \param [IN] preambleLen Sets the Preamble length 166 | * FSK : Number of bytes 167 | * LoRa: Length in symbols (the hardware adds 4 more symbols) 168 | * \param [IN] symbTimeout Sets the RxSingle timeout value 169 | * FSK : timeout in number of bytes 170 | * LoRa: timeout in symbols 171 | * \param [IN] fixLen Fixed length packets [0: variable, 1: fixed] 172 | * \param [IN] payloadLen Sets payload length when fixed length is used 173 | * \param [IN] crcOn Enables/Disables the CRC [0: OFF, 1: ON] 174 | * \param [IN] freqHopOn Enables disables the intra-packet frequency hopping 175 | * FSK : N/A ( set to 0 ) 176 | * LoRa: [0: OFF, 1: ON] 177 | * \param [IN] hopPeriod Number of symbols between each hop 178 | * FSK : N/A ( set to 0 ) 179 | * LoRa: Number of symbols 180 | * \param [IN] iqInverted Inverts IQ signals (LoRa only) 181 | * FSK : N/A ( set to 0 ) 182 | * LoRa: [0: not inverted, 1: inverted] 183 | * \param [IN] rxContinuous Sets the reception in continuous mode 184 | * [false: single mode, true: continuous mode] 185 | */ 186 | void ( *SetRxConfig )( RadioModems_t modem, uint32_t bandwidth, 187 | uint32_t datarate, uint8_t coderate, 188 | uint32_t bandwidthAfc, uint16_t preambleLen, 189 | uint16_t symbTimeout, bool fixLen, 190 | uint8_t payloadLen, 191 | bool crcOn, bool freqHopOn, uint8_t hopPeriod, 192 | bool iqInverted, bool rxContinuous ); 193 | /*! 194 | * \brief Sets the transmission parameters 195 | * 196 | * \param [IN] modem Radio modem to be used [0: FSK, 1: LoRa] 197 | * \param [IN] power Sets the output power [dBm] 198 | * \param [IN] fdev Sets the frequency deviation (FSK only) 199 | * FSK : [Hz] 200 | * LoRa: 0 201 | * \param [IN] bandwidth Sets the bandwidth (LoRa only) 202 | * FSK : 0 203 | * LoRa: [0: 125 kHz, 1: 250 kHz, 204 | * 2: 500 kHz, 3: Reserved] 205 | * \param [IN] datarate Sets the Datarate 206 | * FSK : 600..300000 bits/s 207 | * LoRa: [6: 64, 7: 128, 8: 256, 9: 512, 208 | * 10: 1024, 11: 2048, 12: 4096 chips] 209 | * \param [IN] coderate Sets the coding rate (LoRa only) 210 | * FSK : N/A ( set to 0 ) 211 | * LoRa: [1: 4/5, 2: 4/6, 3: 4/7, 4: 4/8] 212 | * \param [IN] preambleLen Sets the preamble length 213 | * FSK : Number of bytes 214 | * LoRa: Length in symbols (the hardware adds 4 more symbols) 215 | * \param [IN] fixLen Fixed length packets [0: variable, 1: fixed] 216 | * \param [IN] crcOn Enables disables the CRC [0: OFF, 1: ON] 217 | * \param [IN] freqHopOn Enables disables the intra-packet frequency hopping 218 | * FSK : N/A ( set to 0 ) 219 | * LoRa: [0: OFF, 1: ON] 220 | * \param [IN] hopPeriod Number of symbols between each hop 221 | * FSK : N/A ( set to 0 ) 222 | * LoRa: Number of symbols 223 | * \param [IN] iqInverted Inverts IQ signals (LoRa only) 224 | * FSK : N/A ( set to 0 ) 225 | * LoRa: [0: not inverted, 1: inverted] 226 | * \param [IN] timeout Transmission timeout [ms] 227 | */ 228 | void ( *SetTxConfig )( RadioModems_t modem, int8_t power, uint32_t fdev, 229 | uint32_t bandwidth, uint32_t datarate, 230 | uint8_t coderate, uint16_t preambleLen, 231 | bool fixLen, bool crcOn, bool freqHopOn, 232 | uint8_t hopPeriod, bool iqInverted, uint32_t timeout ); 233 | /*! 234 | * \brief Checks if the given RF frequency is supported by the hardware 235 | * 236 | * \param [IN] frequency RF frequency to be checked 237 | * \retval isSupported [true: supported, false: unsupported] 238 | */ 239 | bool ( *CheckRfFrequency )( uint32_t frequency ); 240 | /*! 241 | * \brief Computes the packet time on air in ms for the given payload 242 | * 243 | * \Remark Can only be called once SetRxConfig or SetTxConfig have been called 244 | * 245 | * \param [IN] modem Radio modem to be used [0: FSK, 1: LoRa] 246 | * \param [IN] pktLen Packet payload length 247 | * 248 | * \retval airTime Computed airTime (ms) for the given packet payload length 249 | */ 250 | uint32_t ( *TimeOnAir )( RadioModems_t modem, uint8_t pktLen ); 251 | /*! 252 | * \brief Sends the buffer of size. Prepares the packet to be sent and sets 253 | * the radio in transmission 254 | * 255 | * \param [IN]: buffer Buffer pointer 256 | * \param [IN]: size Buffer size 257 | */ 258 | void ( *Send )( uint8_t *buffer, uint8_t size ); 259 | /*! 260 | * \brief Sets the radio in sleep mode 261 | */ 262 | void ( *Sleep )( void ); 263 | /*! 264 | * \brief Sets the radio in standby mode 265 | */ 266 | void ( *Standby )( void ); 267 | /*! 268 | * \brief Sets the radio in reception mode for the given time 269 | * \param [IN] timeout Reception timeout [ms] 270 | * [0: continuous, others timeout] 271 | */ 272 | void ( *Rx )( uint32_t timeout ); 273 | /*! 274 | * \brief Start a Channel Activity Detection 275 | */ 276 | void ( *StartCad )( void ); 277 | /*! 278 | * \brief Sets the radio in continuous wave transmission mode 279 | * 280 | * \param [IN]: freq Channel RF frequency 281 | * \param [IN]: power Sets the output power [dBm] 282 | * \param [IN]: time Transmission mode timeout [s] 283 | */ 284 | void ( *SetTxContinuousWave )( uint32_t freq, int8_t power, uint16_t time ); 285 | /*! 286 | * \brief Reads the current RSSI value 287 | * 288 | * \retval rssiValue Current RSSI value in [dBm] 289 | */ 290 | int16_t ( *Rssi )( RadioModems_t modem ); 291 | /*! 292 | * \brief Writes the radio register at the specified address 293 | * 294 | * \param [IN]: addr Register address 295 | * \param [IN]: data New register value 296 | */ 297 | void ( *Write )( uint16_t addr, uint8_t data ); 298 | /*! 299 | * \brief Reads the radio register at the specified address 300 | * 301 | * \param [IN]: addr Register address 302 | * \retval data Register value 303 | */ 304 | uint8_t ( *Read )( uint16_t addr ); 305 | /*! 306 | * \brief Writes multiple radio registers starting at address 307 | * 308 | * \param [IN] addr First Radio register address 309 | * \param [IN] buffer Buffer containing the new register's values 310 | * \param [IN] size Number of registers to be written 311 | */ 312 | void ( *WriteBuffer )( uint16_t addr, uint8_t *buffer, uint8_t size ); 313 | /*! 314 | * \brief Reads multiple radio registers starting at address 315 | * 316 | * \param [IN] addr First Radio register address 317 | * \param [OUT] buffer Buffer where to copy the registers data 318 | * \param [IN] size Number of registers to be read 319 | */ 320 | void ( *ReadBuffer )( uint16_t addr, uint8_t *buffer, uint8_t size ); 321 | /*! 322 | * \brief Sets the maximum payload length. 323 | * 324 | * \param [IN] modem Radio modem to be used [0: FSK, 1: LoRa] 325 | * \param [IN] max Maximum payload length in bytes 326 | */ 327 | void ( *SetMaxPayloadLength )( RadioModems_t modem, uint8_t max ); 328 | /*! 329 | * \brief Sets the network to public or private. Updates the sync byte. 330 | * 331 | * \remark Applies to LoRa modem only 332 | * 333 | * \param [IN] enable if true, it enables a public network 334 | */ 335 | void ( *SetPublicNetwork )( bool enable ); 336 | /*! 337 | * \brief Gets the time required for the board plus radio to get out of sleep.[ms] 338 | * 339 | * \retval time Radio plus board wakeup time in ms. 340 | */ 341 | uint32_t ( *GetWakeupTime )( void ); 342 | /*! 343 | * \brief Process radio irq 344 | */ 345 | void ( *IrqProcess )( void ); 346 | }; 347 | 348 | /*! 349 | * \brief Radio driver 350 | * 351 | * \remark This variable is defined and initialized in the specific radio 352 | * board implementation 353 | */ 354 | extern const struct Radio_s Radio; 355 | 356 | #endif // __RADIO_H__ 357 | -------------------------------------------------------------------------------- /src/driver/sx1276.h: -------------------------------------------------------------------------------- 1 | /*! 2 | * \file sx1276.h 3 | * 4 | * \brief SX1276 driver implementation 5 | * 6 | * \copyright Revised BSD License, see section \ref LICENSE. 7 | * 8 | * \code 9 | * ______ _ 10 | * / _____) _ | | 11 | * ( (____ _____ ____ _| |_ _____ ____| |__ 12 | * \____ \| ___ | (_ _) ___ |/ ___) _ \ 13 | * _____) ) ____| | | || |_| ____( (___| | | | 14 | * (______/|_____)_|_|_| \__)_____)\____)_| |_| 15 | * (C)2013-2017 Semtech 16 | * 17 | * \endcode 18 | * 19 | * \author Miguel Luis ( Semtech ) 20 | * 21 | * \author Gregory Cristian ( Semtech ) 22 | */ 23 | #ifndef __SX1276_H__ 24 | #define __SX1276_H__ 25 | 26 | #include 27 | #include 28 | #include "../driver/debug.h" 29 | #include "../driver/gpio.h" 30 | #include "../driver/lorawan_spi.h" 31 | #include "../radio/radio_sx127x.h" 32 | #include "../driver/sx1276Regs-Fsk.h" 33 | #include "../driver/sx1276Regs-LoRa.h" 34 | 35 | /*! 36 | * Radio wake-up time from sleep 37 | */ 38 | #define RADIO_WAKEUP_TIME 1 // [ms] 39 | 40 | /*! 41 | * Sync word for Private LoRa networks 42 | */ 43 | #define LORA_MAC_PRIVATE_SYNCWORD 0x12 44 | 45 | /*! 46 | * Sync word for Public LoRa networks 47 | */ 48 | #define LORA_MAC_PUBLIC_SYNCWORD 0x34 49 | 50 | /*! 51 | * Radio FSK modem parameters 52 | */ 53 | typedef struct 54 | { 55 | int8_t Power; 56 | uint32_t Fdev; 57 | uint32_t Bandwidth; 58 | uint32_t BandwidthAfc; 59 | uint32_t Datarate; 60 | uint16_t PreambleLen; 61 | bool FixLen; 62 | uint8_t PayloadLen; 63 | bool CrcOn; 64 | bool IqInverted; 65 | bool RxContinuous; 66 | uint32_t TxTimeout; 67 | uint32_t RxSingleTimeout; 68 | }RadioFskSettings_t; 69 | 70 | /*! 71 | * Radio FSK packet handler state 72 | */ 73 | typedef struct 74 | { 75 | uint8_t PreambleDetected; 76 | uint8_t SyncWordDetected; 77 | int8_t RssiValue; 78 | int32_t AfcValue; 79 | uint8_t RxGain; 80 | uint16_t Size; 81 | uint16_t NbBytes; 82 | uint8_t FifoThresh; 83 | uint8_t ChunkSize; 84 | }RadioFskPacketHandler_t; 85 | 86 | /*! 87 | * Radio LoRa modem parameters 88 | */ 89 | typedef struct 90 | { 91 | int8_t Power; 92 | uint32_t Bandwidth; 93 | uint32_t Datarate; 94 | bool LowDatarateOptimize; 95 | uint8_t Coderate; 96 | uint16_t PreambleLen; 97 | bool FixLen; 98 | uint8_t PayloadLen; 99 | bool CrcOn; 100 | bool FreqHopOn; 101 | uint8_t HopPeriod; 102 | bool IqInverted; 103 | bool RxContinuous; 104 | uint32_t TxTimeout; 105 | bool PublicNetwork; 106 | }RadioLoRaSettings_t; 107 | 108 | /*! 109 | * Radio LoRa packet handler state 110 | */ 111 | typedef struct 112 | { 113 | int8_t SnrValue; 114 | int16_t RssiValue; 115 | uint8_t Size; 116 | }RadioLoRaPacketHandler_t; 117 | 118 | /*! 119 | * Radio Settings 120 | */ 121 | typedef struct 122 | { 123 | RadioState_t State; 124 | RadioModems_t Modem; 125 | uint32_t Channel; 126 | RadioFskSettings_t Fsk; 127 | RadioFskPacketHandler_t FskPacketHandler; 128 | RadioLoRaSettings_t LoRa; 129 | RadioLoRaPacketHandler_t LoRaPacketHandler; 130 | }RadioSettings_t; 131 | 132 | /*! 133 | * Radio hardware and global parameters 134 | */ 135 | typedef struct SX1276_s 136 | { 137 | Gpio_t Reset; 138 | Gpio_t DIO0; 139 | Gpio_t DIO1; 140 | Gpio_t DIO2; 141 | Gpio_t DIO3; 142 | Gpio_t DIO4; 143 | Gpio_t DIO5; 144 | Spi_t Spi; 145 | RadioSettings_t Settings; 146 | }SX1276_t; 147 | 148 | /*! 149 | * Hardware IO IRQ callback function definition 150 | */ 151 | typedef void ( DioIrqHandler )( void ); 152 | 153 | /*! 154 | * SX1276 definitions 155 | */ 156 | #define XTAL_FREQ 32000000 157 | #define FREQ_STEP 61.03515625 158 | 159 | #define RX_BUFFER_SIZE 256 160 | 161 | /*! 162 | * ============================================================================ 163 | * Public functions prototypes 164 | * ============================================================================ 165 | */ 166 | 167 | /*! 168 | * \brief Initializes the radio 169 | * 170 | * \param [IN] events Structure containing the driver callback functions 171 | */ 172 | void SX1276Init( RadioEvents_t *events ); 173 | 174 | /*! 175 | * Return current radio status 176 | * 177 | * \param status Radio status.[RF_IDLE, RF_RX_RUNNING, RF_TX_RUNNING] 178 | */ 179 | RadioState_t SX1276GetStatus( void ); 180 | 181 | /*! 182 | * \brief Configures the radio with the given modem 183 | * 184 | * \param [IN] modem Modem to be used [0: FSK, 1: LoRa] 185 | */ 186 | void SX1276SetModem( RadioModems_t modem ); 187 | 188 | /*! 189 | * \brief Sets the channel configuration 190 | * 191 | * \param [IN] freq Channel RF frequency 192 | */ 193 | void SX1276SetChannel( uint32_t freq ); 194 | 195 | /*! 196 | * \brief Checks if the channel is free for the given time 197 | * 198 | * \param [IN] modem Radio modem to be used [0: FSK, 1: LoRa] 199 | * \param [IN] freq Channel RF frequency 200 | * \param [IN] rssiThresh RSSI threshold 201 | * \param [IN] maxCarrierSenseTime Max time while the RSSI is measured 202 | * 203 | * \retval isFree [true: Channel is free, false: Channel is not free] 204 | */ 205 | bool SX1276IsChannelFree( RadioModems_t modem, uint32_t freq, int16_t rssiThresh, uint32_t maxCarrierSenseTime ); 206 | 207 | /*! 208 | * \brief Generates a 32 bits random value based on the RSSI readings 209 | * 210 | * \remark This function sets the radio in LoRa modem mode and disables 211 | * all interrupts. 212 | * After calling this function either SX1276SetRxConfig or 213 | * SX1276SetTxConfig functions must be called. 214 | * 215 | * \retval randomValue 32 bits random value 216 | */ 217 | uint32_t SX1276Random( void ); 218 | 219 | /*! 220 | * \brief Sets the reception parameters 221 | * 222 | * \remark When using LoRa modem only bandwidths 125, 250 and 500 kHz are supported 223 | * 224 | * \param [IN] modem Radio modem to be used [0: FSK, 1: LoRa] 225 | * \param [IN] bandwidth Sets the bandwidth 226 | * FSK : >= 2600 and <= 250000 Hz 227 | * LoRa: [0: 125 kHz, 1: 250 kHz, 228 | * 2: 500 kHz, 3: Reserved] 229 | * \param [IN] datarate Sets the Datarate 230 | * FSK : 600..300000 bits/s 231 | * LoRa: [6: 64, 7: 128, 8: 256, 9: 512, 232 | * 10: 1024, 11: 2048, 12: 4096 chips] 233 | * \param [IN] coderate Sets the coding rate (LoRa only) 234 | * FSK : N/A ( set to 0 ) 235 | * LoRa: [1: 4/5, 2: 4/6, 3: 4/7, 4: 4/8] 236 | * \param [IN] bandwidthAfc Sets the AFC Bandwidth (FSK only) 237 | * FSK : >= 2600 and <= 250000 Hz 238 | * LoRa: N/A ( set to 0 ) 239 | * \param [IN] preambleLen Sets the Preamble length 240 | * FSK : Number of bytes 241 | * LoRa: Length in symbols (the hardware adds 4 more symbols) 242 | * \param [IN] symbTimeout Sets the RxSingle timeout value 243 | * FSK : timeout number of bytes 244 | * LoRa: timeout in symbols 245 | * \param [IN] fixLen Fixed length packets [0: variable, 1: fixed] 246 | * \param [IN] payloadLen Sets payload length when fixed length is used 247 | * \param [IN] crcOn Enables/Disables the CRC [0: OFF, 1: ON] 248 | * \param [IN] freqHopOn Enables disables the intra-packet frequency hopping 249 | * FSK : N/A ( set to 0 ) 250 | * LoRa: [0: OFF, 1: ON] 251 | * \param [IN] hopPeriod Number of symbols between each hop 252 | * FSK : N/A ( set to 0 ) 253 | * LoRa: Number of symbols 254 | * \param [IN] iqInverted Inverts IQ signals (LoRa only) 255 | * FSK : N/A ( set to 0 ) 256 | * LoRa: [0: not inverted, 1: inverted] 257 | * \param [IN] rxContinuous Sets the reception in continuous mode 258 | * [false: single mode, true: continuous mode] 259 | */ 260 | void SX1276SetRxConfig( RadioModems_t modem, uint32_t bandwidth, 261 | uint32_t datarate, uint8_t coderate, 262 | uint32_t bandwidthAfc, uint16_t preambleLen, 263 | uint16_t symbTimeout, bool fixLen, 264 | uint8_t payloadLen, 265 | bool crcOn, bool freqHopOn, uint8_t hopPeriod, 266 | bool iqInverted, bool rxContinuous ); 267 | 268 | /*! 269 | * \brief Sets the transmission parameters 270 | * 271 | * \remark When using LoRa modem only bandwidths 125, 250 and 500 kHz are supported 272 | * 273 | * \param [IN] modem Radio modem to be used [0: FSK, 1: LoRa] 274 | * \param [IN] power Sets the output power [dBm] 275 | * \param [IN] fdev Sets the frequency deviation (FSK only) 276 | * FSK : [Hz] 277 | * LoRa: 0 278 | * \param [IN] bandwidth Sets the bandwidth (LoRa only) 279 | * FSK : 0 280 | * LoRa: [0: 125 kHz, 1: 250 kHz, 281 | * 2: 500 kHz, 3: Reserved] 282 | * \param [IN] datarate Sets the Datarate 283 | * FSK : 600..300000 bits/s 284 | * LoRa: [6: 64, 7: 128, 8: 256, 9: 512, 285 | * 10: 1024, 11: 2048, 12: 4096 chips] 286 | * \param [IN] coderate Sets the coding rate (LoRa only) 287 | * FSK : N/A ( set to 0 ) 288 | * LoRa: [1: 4/5, 2: 4/6, 3: 4/7, 4: 4/8] 289 | * \param [IN] preambleLen Sets the preamble length 290 | * FSK : Number of bytes 291 | * LoRa: Length in symbols (the hardware adds 4 more symbols) 292 | * \param [IN] fixLen Fixed length packets [0: variable, 1: fixed] 293 | * \param [IN] crcOn Enables disables the CRC [0: OFF, 1: ON] 294 | * \param [IN] freqHopOn Enables disables the intra-packet frequency hopping 295 | * FSK : N/A ( set to 0 ) 296 | * LoRa: [0: OFF, 1: ON] 297 | * \param [IN] hopPeriod Number of symbols between each hop 298 | * FSK : N/A ( set to 0 ) 299 | * LoRa: Number of symbols 300 | * \param [IN] iqInverted Inverts IQ signals (LoRa only) 301 | * FSK : N/A ( set to 0 ) 302 | * LoRa: [0: not inverted, 1: inverted] 303 | * \param [IN] timeout Transmission timeout [ms] 304 | */ 305 | void SX1276SetTxConfig( RadioModems_t modem, int8_t power, uint32_t fdev, 306 | uint32_t bandwidth, uint32_t datarate, 307 | uint8_t coderate, uint16_t preambleLen, 308 | bool fixLen, bool crcOn, bool freqHopOn, 309 | uint8_t hopPeriod, bool iqInverted, uint32_t timeout ); 310 | 311 | /*! 312 | * \brief Computes the packet time on air in ms for the given payload 313 | * 314 | * \Remark Can only be called once SetRxConfig or SetTxConfig have been called 315 | * 316 | * \param [IN] modem Radio modem to be used [0: FSK, 1: LoRa] 317 | * \param [IN] pktLen Packet payload length 318 | * 319 | * \retval airTime Computed airTime (ms) for the given packet payload length 320 | */ 321 | uint32_t SX1276GetTimeOnAir( RadioModems_t modem, uint8_t pktLen ); 322 | 323 | /*! 324 | * \brief Sends the buffer of size. Prepares the packet to be sent and sets 325 | * the radio in transmission 326 | * 327 | * \param [IN]: buffer Buffer pointer 328 | * \param [IN]: size Buffer size 329 | */ 330 | void SX1276Send( uint8_t *buffer, uint8_t size ); 331 | 332 | /*! 333 | * \brief Sets the radio in sleep mode 334 | */ 335 | void SX1276SetSleep( void ); 336 | 337 | /*! 338 | * \brief Sets the radio in standby mode 339 | */ 340 | void SX1276SetStby( void ); 341 | 342 | /*! 343 | * \brief Sets the radio in reception mode for the given time 344 | * \param [IN] timeout Reception timeout [ms] [0: continuous, others timeout] 345 | */ 346 | void SX1276SetRx( uint32_t timeout ); 347 | 348 | /*! 349 | * \brief Start a Channel Activity Detection 350 | */ 351 | void SX1276StartCad( void ); 352 | 353 | /*! 354 | * \brief Sets the radio in continuous wave transmission mode 355 | * 356 | * \param [IN]: freq Channel RF frequency 357 | * \param [IN]: power Sets the output power [dBm] 358 | * \param [IN]: time Transmission mode timeout [s] 359 | */ 360 | void SX1276SetTxContinuousWave( uint32_t freq, int8_t power, uint16_t time ); 361 | 362 | /*! 363 | * \brief Reads the current RSSI value 364 | * 365 | * \retval rssiValue Current RSSI value in [dBm] 366 | */ 367 | int16_t SX1276ReadRssi( RadioModems_t modem ); 368 | 369 | /*! 370 | * \brief Writes the radio register at the specified address 371 | * 372 | * \param [IN]: addr Register address 373 | * \param [IN]: data New register value 374 | */ 375 | void SX1276Write( uint16_t addr, uint8_t data ); 376 | 377 | /*! 378 | * \brief Reads the radio register at the specified address 379 | * 380 | * \param [IN]: addr Register address 381 | * \retval data Register value 382 | */ 383 | uint8_t SX1276Read( uint16_t addr ); 384 | 385 | /*! 386 | * \brief Writes multiple radio registers starting at address 387 | * 388 | * \param [IN] addr First Radio register address 389 | * \param [IN] buffer Buffer containing the new register's values 390 | * \param [IN] size Number of registers to be written 391 | */ 392 | void SX1276WriteBuffer( uint16_t addr, uint8_t *buffer, uint8_t size ); 393 | 394 | /*! 395 | * \brief Reads multiple radio registers starting at address 396 | * 397 | * \param [IN] addr First Radio register address 398 | * \param [OUT] buffer Buffer where to copy the registers data 399 | * \param [IN] size Number of registers to be read 400 | */ 401 | void SX1276ReadBuffer( uint16_t addr, uint8_t *buffer, uint8_t size ); 402 | 403 | /*! 404 | * \brief Sets the maximum payload length. 405 | * 406 | * \param [IN] modem Radio modem to be used [0: FSK, 1: LoRa] 407 | * \param [IN] max Maximum payload length in bytes 408 | */ 409 | void SX1276SetMaxPayloadLength( RadioModems_t modem, uint8_t max ); 410 | 411 | /*! 412 | * \brief Sets the network to public or private. Updates the sync byte. 413 | * 414 | * \remark Applies to LoRa modem only 415 | * 416 | * \param [IN] enable if true, it enables a public network 417 | */ 418 | void SX1276SetPublicNetwork( bool enable ); 419 | 420 | /*! 421 | * \brief Gets the time required for the board plus radio to get out of sleep.[ms] 422 | * 423 | * \retval time Radio plus board wakeup time in ms. 424 | */ 425 | uint32_t SX1276GetWakeupTime( void ); 426 | 427 | void sx1276RadioIrqProcess(void); 428 | 429 | #endif // __SX1276_H__ 430 | --------------------------------------------------------------------------------