├── .clang-format ├── .gitattributes ├── .gitignore ├── README.md ├── examples ├── ttn-otaa-BLE-provisioning │ └── ttn-otaa-BLE-provisioning.ino ├── ttn-otaa-sleep │ └── ttn-otaa-sleep.ino ├── ttn-otaa │ └── ttn-otaa.ino └── ttn_abp │ └── ttn_abp.ino ├── library.properties ├── project_config └── lmic_project_config.h └── src ├── ByteArrayUtils.h ├── NVSHandler.cpp ├── NVSHandler.h ├── TTN_BLE_esp32.cpp ├── TTN_BLE_esp32.h ├── TTN_CayenneLPP.cpp ├── TTN_CayenneLPP.h ├── TTN_esp32.cpp ├── TTN_esp32.h ├── helper.h └── lmic ├── aes ├── ideetron │ └── AES-128_V10.cpp ├── lmic.c └── other.c ├── arduino_lmic.h ├── arduino_lmic_hal_boards.h ├── arduino_lmic_hal_configuration.h ├── arduino_lmic_lorawan_compliance.h ├── arduino_lmic_user_configuration.h ├── hal ├── getpinmap_M5stack_Lora.cpp ├── getpinmap_catena4420.cpp ├── getpinmap_catena4551.cpp ├── getpinmap_catena4610.cpp ├── getpinmap_catena4611.cpp ├── getpinmap_catena4612.cpp ├── getpinmap_catena4617.cpp ├── getpinmap_catena4618.cpp ├── getpinmap_catena4630.cpp ├── getpinmap_catena4801.cpp ├── getpinmap_feather32u4lora.cpp ├── getpinmap_featherm0lora.cpp ├── getpinmap_heltec_Wifi_Lora_32.cpp ├── getpinmap_heltec_Wifi_Lora_32_V2.cpp ├── getpinmap_heltec_wirless_stick.cpp ├── getpinmap_thisboard.cpp ├── getpinmap_ttgo_TBEAM.cpp ├── getpinmap_ttgo_lora32_v1.cpp ├── hal.cpp └── hal.h ├── lmic.h └── lmic ├── config.h ├── hal.h ├── lmic.c ├── lmic.h ├── lmic_as923.c ├── lmic_au915.c ├── lmic_bandplan.h ├── lmic_bandplan_as923.h ├── lmic_bandplan_au915.h ├── lmic_bandplan_eu868.h ├── lmic_bandplan_in866.h ├── lmic_bandplan_kr920.h ├── lmic_bandplan_us915.h ├── lmic_channelshuffle.c ├── lmic_compat.h ├── lmic_compliance.c ├── lmic_compliance.h ├── lmic_config_preconditions.h ├── lmic_env.h ├── lmic_eu868.c ├── lmic_eu_like.c ├── lmic_eu_like.h ├── lmic_in866.c ├── lmic_kr920.c ├── lmic_us915.c ├── lmic_us_like.c ├── lmic_us_like.h ├── lmic_util.c ├── lmic_util.h ├── lorabase.h ├── lorabase_as923.h ├── lorabase_au915.h ├── lorabase_eu868.h ├── lorabase_in866.h ├── lorabase_kr920.h ├── lorabase_us915.h ├── lorawan_spec_compliance.h ├── oslmic.c ├── oslmic.h ├── oslmic_types.h └── radio.c /.clang-format: -------------------------------------------------------------------------------- 1 | --- 2 | # Based on Webkit style 3 | BasedOnStyle: Webkit 4 | IndentWidth: 4 5 | ColumnLimit: 120 6 | --- 7 | Language: Cpp 8 | Standard: Cpp11 9 | # Pointers aligned to the left 10 | DerivePointerAlignment: false 11 | PointerAlignment: Left 12 | AccessModifierOffset: -4 13 | AllowShortFunctionsOnASingleLine: Inline 14 | AlwaysBreakTemplateDeclarations: true 15 | BreakBeforeBraces: Custom 16 | BraceWrapping: 17 | AfterClass: true 18 | AfterControlStatement: true 19 | AfterEnum: true 20 | AfterFunction: true 21 | AfterNamespace: true 22 | AfterStruct: true 23 | AfterUnion: true 24 | AfterExternBlock: true 25 | BeforeCatch: true 26 | BeforeElse: true 27 | SplitEmptyFunction: false 28 | SplitEmptyRecord: false 29 | SplitEmptyNamespace: false 30 | BreakConstructorInitializers: BeforeColon 31 | CompactNamespaces: false 32 | ConstructorInitializerAllOnOneLineOrOnePerLine: true 33 | ConstructorInitializerIndentWidth: 4 34 | Cpp11BracedListStyle: true 35 | FixNamespaceComments: true 36 | IncludeBlocks: Regroup 37 | IncludeCategories: 38 | # C++ standard headers (no .h) 39 | - Regex: '<[[:alnum:]_-]+>' 40 | Priority: 1 41 | # Extenal libraries (with .h) 42 | - Regex: '<[[:alnum:]_./-]+>' 43 | Priority: 2 44 | # Headers from same folder 45 | - Regex: '"[[:alnum:]_.-]+"' 46 | Priority: 3 47 | # Headers from other folders 48 | - Regex: '"[[:alnum:]_/.-]+"' 49 | Priority: 4 50 | IndentCaseLabels: false 51 | NamespaceIndentation: All 52 | SortIncludes: true 53 | SortUsingDeclarations: true 54 | SpaceAfterTemplateKeyword: true 55 | SpacesInAngles: false 56 | SpacesInParentheses: false 57 | SpacesInSquareBrackets: false 58 | UseTab: Never -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto 3 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | 2 | src/TheThingsNetwork_esp32.cpp 3 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | This repository is archived. Please use [EzLoRaWAN](https://github.com/rgot-org/EzLoRaWAN) for now. The new library can use SX127X and SX126X chips. 2 | 3 | # API Reference 4 | 5 | The `TTN_esp32` class enables ESP32 devices with supported LoRaWAN modules to communicate via The Things Network. This library is a wrapper for MCCI-Catena/arduino-lmic library. the pre-integrated boards are the same as mcci-catena library plus : 6 | 7 | - HELTEC Wifi Lora 32 (V1 & V2) 8 | - HELTEC Wireless Stick 9 | # Configuration 10 | Like MCCI-Catena/arduino-lmic library the configuration is setup by editing `project_config/lmic_project_config.h`. See https://github.com/mcci-catena/arduino-lmic#configuration for more informations 11 | 12 | ## Class: `TTN_esp32` 13 | 14 | Include and instantiate the TTN_esp32 class. The constructor initialize the library with the Streams it should communicate with. 15 | 16 | ```c 17 | #include 18 | 19 | TTN_esp32 ttn; 20 | ``` 21 | ## Method: `begin` 22 | 23 | Start the LMIC stack with Pre-integrated boards (see https://github.com/mcci-catena/arduino-lmic#pre-integrated-boards) 24 | 25 | Following boards are tested : 26 | - HELTEC WIRELESS STICK 27 | - HELTEC WIFI LORA 32 V1 28 | - HELTEC WIFI LORA 32 V2 29 | 30 | 31 | ```c 32 | void begin(); 33 | ``` 34 | Initialize the stack with pointer to pin mapping (see https://github.com/mcci-catena/arduino-lmic#pin-mapping) 35 | ```c 36 | bool begin(const TTN_esp32_LMIC::HalPinmap_t* pPinmap); 37 | ``` 38 | Initialize the LMIC stack with pinout as arguments 39 | ```c 40 | void begin(uint8_t nss, uint8_t rxtx, uint8_t rst, uint8_t dio0, uint8_t dio1, uint8_t dio2); 41 | ``` 42 | Example for HELTEC WIRELESS STICK 43 | ```c 44 | // wireless stick pinout 45 | #define UNUSED_PIN 0xFF 46 | #define SS 18 47 | #define RST_LoRa 14 48 | #define DIO0 26 49 | #define DIO1 35 50 | #define DIO2 34 51 | ... 52 | ttn.begin(SS, UNUSED_PIN, RST_LoRa, DIO0,DIO1,DIO2); 53 | ``` 54 | ## Method: `getAppEui` 55 | 56 | Gets the provisioned AppEUI. The AppEUI is set using `provision()` or `join()`. 57 | 58 | ```c 59 | size_t getAppEui(char *buffer, size_t size); 60 | ``` 61 | return AppEui as an array of char 62 | ```c 63 | String getAppEui(); 64 | ``` 65 | return AppEui as String 66 | ## Method: `getDevEui` 67 | Gets the provisioned DevEUI. The DevEUI is set using `provision()` or `join()`. 68 | ```c 69 | size_t getDevEui(char *buffer, size_t size, bool hardwareEUI=false); 70 | ``` 71 | return DevEUI as array of char 72 | ```c 73 | String getDevEui(bool hardwareEui=false); 74 | ``` 75 | return DevEUI as String 76 | 77 | - `bool hardwareEui=false`: if true get DevEUI from Mac Address. 78 | 79 | ## Method: `isJoined` 80 | Check whether we have joined TTN 81 | ```c 82 | bool isJoined(); 83 | ``` 84 | return `true` if joined to TTN, `false` if not. 85 | ## Method: `showStatus` 86 | 87 | Writes information about the device and LoRa module to `Serial` . 88 | 89 | ```c 90 | void showStatus(); 91 | ``` 92 | 93 | Will write something like: 94 | 95 | ```bash 96 | ---------------Status-------------- 97 | Device EUI: 004D22F44E5DCE53 98 | Application EUI: 70B3D57ED0015575 99 | netid: 13 100 | devaddr: 26011B24 101 | NwkSKey: 6A2D3C24AD3C0D17614D7325BCAA976 102 | AppSKey: 9E68DCBEBF8AE9D891252FB7E6054 103 | data rate: 5 104 | tx power: 14dB 105 | freq: 867100000Hz 106 | ----------------------------------- 107 | ``` 108 | 109 | ## Method: `onMessage` 110 | 111 | Sets a function which will be called to process incoming messages. You'll want to do this in your `setup()` function and then define a `void (*cb)(const byte* payload, size_t length, port_t port)` function somewhere else in your sketch. 112 | 113 | ```c 114 | void onMessage(void (*cb)(const uint8_t *payload, size_t size, int rssi)); 115 | ``` 116 | 117 | - `const uint8_t* payload`: Bytes received. 118 | - `size_t size`: Number of bytes. 119 | - `int rssi`: the rssi in dB. 120 | 121 | See the [ttn-otaa](https://github.com/rgot-org/TheThingsNetwork_esp32/blob/master/examples/ttn-otaa/ttn-otaa.ino) example. 122 | 123 | ## Method: `join` 124 | 125 | Activate the device via OTAA (default). 126 | 127 | ```c 128 | bool join(); 129 | bool join(const char *app_eui, const char *app_key, int8_t retries = -1, uint32_t retryDelay = 10000); 130 | bool join(const char *dev_eui, const char *app_eui, const char *app_key, int8_t retries = -1, uint32_t retryDelay = 10000); 131 | ``` 132 | 133 | - `const char *app_eui`: Application EUI the device is registered to. 134 | - `const char *app_key`: Application Key assigned to the device. 135 | - `const char *dev_eui`: Device EUI 136 | - `int8_t retries = -1`: Number of times to retry after failed or unconfirmed join. Defaults to `-1` which means infinite. 137 | - `uint32_t retryDelay = 10000`: Delay in ms between attempts. Defaults to 10 seconds. 138 | 139 | Returns `true` or `false` depending on whether it received confirmation that the activation was successful before the maximum number of attempts. 140 | 141 | Call the method without the first two arguments if the device's LoRa module is provisioned or comes with NVS stored values. See `provision`, `saveKeys` and `restoreKeys` 142 | 143 | ## Method: `personalize` 144 | 145 | Activate the device via ABP. 146 | 147 | ```c 148 | bool personalize(const char *devAddr, const char *nwkSKey, const char *appSKey); 149 | bool personalize(); 150 | ``` 151 | 152 | - `const char *devAddr`: Device Address assigned to the device. 153 | - `const char *nwkSKey`: Network Session Key assigned to the device for identification. 154 | - `const char *appSKey`: Application Session Key assigned to the device for encryption. 155 | 156 | Returns `true` or `false` depending on whether the activation was successful. 157 | 158 | Call the method with no arguments if the device's LoRa module is provisioned or comes with NVS stored values. See `provisionABP`, `saveKeys` and `restoreKeys` 159 | 160 | See the [ttn_abp](https://github.com/rgot-org/TheThingsNetwork_esp32/tree/master/examples/ttn_abp) example. 161 | 162 | ## Method: `sendBytes` 163 | 164 | Send a message to the application using raw bytes. 165 | 166 | ```c 167 | bool sendBytes(uint8_t *payload, size_t length, uint8_t port = 1, uint8_t confirm = 0); 168 | ``` 169 | 170 | - `uint8_t *payload `: Bytes to send. 171 | - `size_t length`: The number of bytes. Use `sizeof(payload)` to get it. 172 | - `uint8_t port = 1`: The port to address. Defaults to `1`. 173 | - `uint8_t confirm = false`: Whether to ask for confirmation. Defaults to `false` 174 | 175 | ## Method: `poll` 176 | 177 | Calls `sendBytes()` with `{ 0x00 }` as payload to poll for incoming messages. 178 | 179 | ```c 180 | int8_t poll(uint8_t port = 1, uint8_t confirm = 0); 181 | ``` 182 | 183 | - `uint8_t port = 1`: The port to address. Defaults to `1`. 184 | - `uint8_t confirm = 0`: Whether to ask for confirmation. 185 | 186 | Returns the result of `sendBytes()`. 187 | 188 | 189 | ## Method: `provision` 190 | 191 | Sets the informations needed to activate the device via OTAA, without actually activating. Call join() without the first 2 arguments to activate. 192 | 193 | ```c 194 | bool provision(const char *appEui, const char *appKey); 195 | bool provision(const char *devEui, const char *appEui, const char *appKey); 196 | ``` 197 | 198 | - `const char *appEui`: Application Identifier for the device. 199 | - `const char *appKey`: Application Key assigned to the device. 200 | - `const char *devEui`: Device EUI. 201 | ## Method: `provisionABP` 202 | 203 | Sets the informations needed to activate the device via ABP, without actually activating. call `personalize()` without arguments to activate. 204 | ```c 205 | bool provisionABP(const char *devAddr, const char *nwkSKey, const char *appSKey); 206 | ``` 207 | - `const char *devAddr`: Device Address. 208 | - `const char *nwkSKey`: Network Session Key. 209 | - `const char *appSKey`: Application Session Key. 210 | ## Method: `saveKeys` 211 | Save the provisioning keys (OTAA and ABP) in Non Volatile Storage (NVS). 212 | ```c 213 | bool saveKeys(); 214 | ``` 215 | ## Method: `restoreKeys` 216 | Restore the keys from NVS and provisioning the informations for OTAA or ABP connection. Call `join()` or `Personalize()` after this method to activate the device. 217 | ```c 218 | boobool restoreKeys(bool silent=true); 219 | ``` 220 | - `bool silent=true`: silent mode (no log) 221 | 222 | 223 | 224 | -------------------------------------------------------------------------------- /examples/ttn-otaa-BLE-provisioning/ttn-otaa-BLE-provisioning.ino: -------------------------------------------------------------------------------- 1 | /*************************************************************************************** 2 | To use this sketch you must install the TTN ESP32 BLE Provisioning APP from gGoogle Play 3 | https://play.google.com/store/apps/details?id=org.rgot.BLE_TEST 4 | this program was tested with heltech boards (Heltec Wifi Lora 32 & Heltec Wireless Stick) 5 | 6 | When running press the user button (named PROG on board) the on board Led Light 7 | and the Bluetooth Low Energy (BLE) is power on. 8 | On the Android application you can see a new device named "RGOT_xxx" where xxx is the hardware devEui. 9 | 10 | When you tap on this device, you can complete a form with devEUI, AppEui and AppKey. 11 | On the keyboard press Save (enter) to save the parameter. 12 | When finish press the back arrow, then the esp32 board reboot and take your new parameters. 13 | 14 | */ 15 | #include "TTN_BLE_esp32.h" 16 | #include 17 | #include "TTN_CayenneLPP.h" 18 | 19 | // wireless stick pinout 20 | 21 | #define INTERVAL 30000 22 | TTN_esp32 ttn; 23 | TTN_BLE_esp32 ble; 24 | TTN_CayenneLPP lpp; 25 | 26 | void setup() { 27 | 28 | Serial.begin(115200); 29 | Serial.println("Starting"); 30 | ttn.begin(); 31 | if (ttn.restoreKeys()) {// provisioning with restored key from NVS 32 | Serial.println("devEui : "+ ttn.getDevEui()); 33 | Serial.println("appEui : "+ ttn.getAppEui()); 34 | ttn.join(); 35 | Serial.println("joining"); 36 | } 37 | else 38 | { 39 | Serial.println("No key are provisioned, please press the User Button\n\ 40 | then launch the \'TTN ESP32 Prosioning\' Android App \n\ 41 | Select the RGOT_... device and provisioning the keys\n\ 42 | Quit the android App, then the esp32 restart... "); 43 | } 44 | pinMode(KEY_BUILTIN, INPUT); 45 | pinMode(LED, OUTPUT); 46 | digitalWrite(LED, LOW); 47 | } 48 | 49 | void loop() { 50 | static bool jonction = false; 51 | static float nb = 0.0; 52 | static unsigned previoumillis = 0; 53 | if (!digitalRead(KEY_BUILTIN) && !ble.getInitialized()) 54 | { 55 | ttn.stop(); 56 | ble.begin(); 57 | digitalWrite(LED, HIGH); 58 | while (!digitalRead(KEY_BUILTIN)); 59 | 60 | } 61 | 62 | if (ttn.isJoined()) 63 | { 64 | if (!jonction) 65 | { 66 | ttn.showStatus(); 67 | jonction = true; 68 | } 69 | if (millis() - previoumillis > INTERVAL) 70 | { 71 | if (ttn.isRunning()) 72 | { 73 | nb += 0.1; 74 | lpp.reset(); 75 | lpp.addTemperature(1, nb); 76 | if (ttn.sendBytes(lpp.getBuffer(), lpp.getSize(), 1, 1)) { 77 | Serial.printf("envoi reussi : %d %x %02X%02X\n", lpp.getBuffer()[0], lpp.getBuffer()[1], lpp.getBuffer()[2], lpp.getBuffer()[3]); 78 | } 79 | } 80 | 81 | previoumillis = millis(); 82 | } 83 | } 84 | else { 85 | if (ttn.isRunning()) 86 | { 87 | Serial.print("."); 88 | delay(500); 89 | } 90 | 91 | } 92 | 93 | } 94 | -------------------------------------------------------------------------------- /examples/ttn-otaa-sleep/ttn-otaa-sleep.ino: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include "TTN_CayenneLPP.h" 4 | /*************************************************************************** 5 | * Go to your TTN console register a device then the copy fields 6 | * and replace the CHANGE_ME strings below 7 | ****************************************************************************/ 8 | const char* devEui = "CHANGE_ME"; // Change to TTN Device EUI 9 | const char* appEui = "CHANGE_ME"; // Change to TTN Application EUI 10 | const char* appKey = "CHANGE_ME"; // Chaneg to TTN Application Key 11 | 12 | TTN_esp32 ttn ; 13 | TTN_CayenneLPP lpp; 14 | 15 | void message(const uint8_t* payload, size_t size, uint8_t port, int rssi) 16 | { 17 | Serial.println("-- MESSAGE"); 18 | Serial.printf("Received %d bytes on port %d (RSSI=%ddB) :", size, port, rssi); 19 | for (int i = 0; i < size; i++) 20 | { 21 | Serial.printf(" %02X", payload[i]); 22 | } 23 | Serial.println(); 24 | } 25 | 26 | void print_wakeup_reason() 27 | { 28 | esp_sleep_wakeup_cause_t wakeup_reason; 29 | wakeup_reason = esp_sleep_get_wakeup_cause(); 30 | switch (wakeup_reason) 31 | { 32 | case 1: 33 | Serial.println("Wakeup caused by external signal using RTC_IO"); 34 | break; 35 | case 2: 36 | Serial.println("Wakeup caused by external signal using RTC_CNTL"); 37 | break; 38 | case 3: 39 | Serial.println("Wakeup caused by timer"); 40 | break; 41 | case 4: 42 | Serial.println("Wakeup caused by touchpad"); 43 | break; 44 | case 5: 45 | Serial.println("Wakeup caused by ULP program"); 46 | break; 47 | default: 48 | Serial.println("Wakeup was not caused by deep sleep"); 49 | break; 50 | } 51 | } 52 | 53 | void waitForTransactions() 54 | { 55 | Serial.println("Waiting for pending transactions... "); 56 | Serial.println("Waiting took " + String(ttn.waitForPendingTransactions()) + "ms"); 57 | } 58 | 59 | void sendData() 60 | { 61 | const float temperature = temperatureRead(); 62 | lpp.reset(); 63 | lpp.addTemperature(1, temperature); 64 | if (ttn.sendBytes(lpp.getBuffer(), lpp.getSize())) 65 | { 66 | Serial.printf("Temp: %f TTN_CayenneLPP: %d %x %02X%02X\n", temperature, lpp.getBuffer()[0], lpp.getBuffer()[1], 67 | lpp.getBuffer()[2], lpp.getBuffer()[3]); 68 | } 69 | } 70 | 71 | void setup() 72 | { 73 | Serial.begin(115200); 74 | delay(1000); 75 | Serial.println("Starting"); 76 | 77 | // Print the wakeup reason for ESP32 78 | print_wakeup_reason(); 79 | 80 | ttn.begin(); 81 | // Declare callback function for handling downlink messages from server 82 | ttn.onMessage(message); 83 | // Join the network 84 | ttn.join(devEui, appEui, appKey); 85 | Serial.print("Joining TTN "); 86 | while (!ttn.isJoined()) 87 | { 88 | Serial.print("."); 89 | delay(500); 90 | } 91 | Serial.println("\njoined!"); 92 | 93 | // Make sure any pending transactions are handled first 94 | waitForTransactions(); 95 | // Send our data 96 | sendData(); 97 | // Make sure our transactions is handled before going to sleep 98 | waitForTransactions(); 99 | 100 | // Configure GPIO33 as ext0 wake up source for HIGH logic level 101 | // esp_sleep_enable_ext0_wakeup(GPIO_NUM_35, 1); 102 | // OR 103 | // Set timer to 30 seconds 104 | // Sleep time in micro seconds so multiply by 1000000 105 | esp_sleep_enable_timer_wakeup(30 * 1000000); 106 | 107 | // Go to sleep now 108 | Serial.println("Going to sleep!"); 109 | esp_deep_sleep_start(); 110 | // Everything beyond this point will never be called 111 | } 112 | 113 | void loop() 114 | { 115 | // Never called 116 | } -------------------------------------------------------------------------------- /examples/ttn-otaa/ttn-otaa.ino: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include "TTN_CayenneLPP.h" 4 | /*************************************************************************** 5 | * Go to your TTN console register a device then the copy fields 6 | * and replace the CHANGE_ME strings below 7 | ****************************************************************************/ 8 | const char* devEui = "CHANGE_ME"; // Change to TTN Device EUI 9 | const char* appEui = "CHANGE_ME"; // Change to TTN Application EUI 10 | const char* appKey = "CHANGE_ME"; // Chaneg to TTN Application Key 11 | 12 | TTN_esp32 ttn ; 13 | TTN_CayenneLPP lpp; 14 | 15 | void message(const uint8_t* payload, size_t size, uint8_t port, int rssi) 16 | { 17 | Serial.println("-- MESSAGE"); 18 | Serial.printf("Received %d bytes on port %d (RSSI=%ddB) :", size, port, rssi); 19 | for (int i = 0; i < size; i++) 20 | { 21 | Serial.printf(" %02X", payload[i]); 22 | } 23 | Serial.println(); 24 | } 25 | 26 | void setup() 27 | { 28 | Serial.begin(115200); 29 | Serial.println("Starting"); 30 | ttn.begin(); 31 | ttn.onMessage(message); // Declare callback function for handling downlink 32 | // messages from server 33 | ttn.join(devEui, appEui, appKey); 34 | Serial.print("Joining TTN "); 35 | while (!ttn.isJoined()) 36 | { 37 | Serial.print("."); 38 | delay(500); 39 | } 40 | Serial.println("\njoined !"); 41 | ttn.showStatus(); 42 | } 43 | 44 | void loop() 45 | { 46 | static float nb = 18.2; 47 | nb += 0.1; 48 | lpp.reset(); 49 | lpp.addTemperature(1, nb); 50 | if (ttn.sendBytes(lpp.getBuffer(), lpp.getSize())) 51 | { 52 | Serial.printf("Temp: %f TTN_CayenneLPP: %d %x %02X%02X\n", nb, lpp.getBuffer()[0], lpp.getBuffer()[1], 53 | lpp.getBuffer()[2], lpp.getBuffer()[3]); 54 | } 55 | delay(10000); 56 | } -------------------------------------------------------------------------------- /examples/ttn_abp/ttn_abp.ino: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include "TTN_CayenneLPP.h" 4 | /*************************************************************************** 5 | * Go to your TTN console register a device then the copy fields 6 | * and replace the CHANGE_ME strings below 7 | ****************************************************************************/ 8 | const char* devAddr = "CHANGE_ME"; // Change to TTN Device Address 9 | const char* nwkSKey = "CHANGE_ME"; // Change to TTN Network Session Key 10 | const char* appSKey = "CHANGE_ME"; // Change to TTN Application Session Key 11 | 12 | TTN_esp32 ttn ; 13 | TTN_CayenneLPP lpp; 14 | 15 | void message(const uint8_t* payload, size_t size, uint8_t port, int rssi) 16 | { 17 | Serial.println("-- MESSAGE"); 18 | Serial.printf("Received %d bytes on port %d (RSSI=%ddB) :", size, port, rssi); 19 | for (int i = 0; i < size; i++) 20 | { 21 | Serial.printf(" %02X", payload[i]); 22 | } 23 | Serial.println(); 24 | } 25 | 26 | void setup() 27 | { 28 | Serial.begin(115200); 29 | Serial.println("Starting"); 30 | ttn.begin(); 31 | ttn.onMessage(message); // declare callback function when is downlink from server 32 | ttn.personalize(devAddr, nwkSKey, appSKey); 33 | ttn.showStatus(); 34 | } 35 | 36 | void loop() 37 | { 38 | static float nb = 18.2; 39 | nb += 0.1; 40 | lpp.reset(); 41 | lpp.addTemperature(1, nb); 42 | if (ttn.sendBytes(lpp.getBuffer(), lpp.getSize())) 43 | { 44 | Serial.printf("Temp: %f TTN_CayenneLPP: %d %x %02X%02X\n", nb, lpp.getBuffer()[0], lpp.getBuffer()[1], 45 | lpp.getBuffer()[2], lpp.getBuffer()[3]); 46 | } 47 | delay(10000); 48 | } 49 | -------------------------------------------------------------------------------- /library.properties: -------------------------------------------------------------------------------- 1 | name=TTN_esp32 2 | version=0.1.7 3 | author=Francois Riotte 4 | maintainer=Francois Riotte 5 | sentence=ESP 32 port of the Arduino TheThingsNetwork library. 6 | paragraph=Supports Heltec Wifi Lora 32 boards (Arduino esp32 core v2.XX) 7 | category=Communication 8 | url=https://github.com/rgot-org/TheThingsNetwork_esp32 9 | architectures=esp32 10 | includes=TTN_esp32.h,TTN_CayenneLPP.h 11 | -------------------------------------------------------------------------------- /project_config/lmic_project_config.h: -------------------------------------------------------------------------------- 1 | // project-specific definitions 2 | #define CFG_eu868 1 3 | //#define LMIC_REGION_eu868 1 4 | //#define CFG_us915 1 5 | //#define CFG_au921 1 6 | //#define CFG_as923 1 7 | // #define LMIC_COUNTRY_CODE LMIC_COUNTRY_CODE_JP /* for as923-JP */ 8 | //#define CFG_kr920 1 9 | //#define CFG_in866 1 10 | #define CFG_sx1276_radio 1 11 | //#define LMIC_USE_INTERRUPTS 12 | #define LMIC_LORAWAN_SPEC_VERSION LMIC_LORAWAN_SPEC_VERSION_1_0_3 13 | #define LMIC_MAX_FRAME_LENGTH 64 14 | #define hal_init LMICHAL_init -------------------------------------------------------------------------------- /src/ByteArrayUtils.h: -------------------------------------------------------------------------------- 1 | #ifndef _BYTE_ARRAY_UTILS_H 2 | #define _BYTE_ARRAY_UTILS_H 3 | 4 | class ByteArrayUtils 5 | { 6 | public: 7 | static bool hexStrToBin(const char* hex, uint8_t* buf, int len) 8 | { 9 | const char* ptr = hex; 10 | for (int i = 0; i < len; i++) 11 | { 12 | int val = hexTupleToByte(ptr); 13 | if (val < 0) 14 | { 15 | return false; 16 | } 17 | buf[i] = val; 18 | ptr += 2; 19 | } 20 | return true; 21 | } 22 | 23 | static int hexTupleToByte(const char* hex) 24 | { 25 | int nibble1 = hexDigitToVal(hex[0]); 26 | if (nibble1 < 0) 27 | { 28 | return -1; 29 | } 30 | int nibble2 = hexDigitToVal(hex[1]); 31 | if (nibble2 < 0) 32 | { 33 | return -1; 34 | } 35 | return (nibble1 << 4) | nibble2; 36 | } 37 | 38 | static int hexDigitToVal(char ch) 39 | { 40 | if (ch >= '0' && ch <= '9') 41 | { 42 | return ch - '0'; 43 | } 44 | if (ch >= 'A' && ch <= 'F') 45 | { 46 | return ch + 10 - 'A'; 47 | } 48 | if (ch >= 'a' && ch <= 'f') 49 | { 50 | return ch + 10 - 'a'; 51 | } 52 | return -1; 53 | } 54 | 55 | static void binToHexStr(const uint8_t* buf, int len, char* hex) 56 | { 57 | for (int i = 0; i < len; i++) 58 | { 59 | uint8_t b = buf[i]; 60 | *hex = valToHexDigit((b & 0xf0) >> 4); 61 | hex++; 62 | *hex = valToHexDigit(b & 0x0f); 63 | hex++; 64 | } 65 | } 66 | 67 | static char valToHexDigit(int val) { return "0123456789ABCDEF"[val]; } 68 | 69 | static void swapBytes(uint8_t* buf, int len) 70 | { 71 | uint8_t* p1 = buf; 72 | uint8_t* p2 = buf + len - 1; 73 | while (p1 < p2) 74 | { 75 | uint8_t t = *p1; 76 | *p1 = *p2; 77 | *p2 = t; 78 | p1++; 79 | p2--; 80 | } 81 | } 82 | 83 | static bool isAllZeros(const uint8_t* buf, int len) 84 | { 85 | for (int i = 0; i < len; i++) 86 | { 87 | if (buf[i] != 0) 88 | { 89 | return false; 90 | } 91 | } 92 | return true; 93 | } 94 | 95 | private: 96 | ByteArrayUtils(); 97 | ~ByteArrayUtils(); 98 | }; 99 | 100 | #endif /* _BYTE_ARRAY_UTILS_H */ -------------------------------------------------------------------------------- /src/NVSHandler.cpp: -------------------------------------------------------------------------------- 1 | #include "NVSHandler.h" 2 | 3 | #if defined(ARDUINO) && ARDUINO >= 100 4 | #include "Arduino.h" 5 | 6 | #else 7 | #include "WProgram.h" 8 | 9 | #endif 10 | #ifndef TAG 11 | #define TAG "ARDUINO" 12 | #endif 13 | 14 | bool NVSHandler::openNvsRead(const char* partition, HandleCloser& handleCloser) 15 | { 16 | nvs_handle handle = 0; 17 | const esp_err_t result = nvs_open(partition, NVS_READONLY, &handle); 18 | handleCloser.setHandle(handle); 19 | 20 | if (result == ESP_ERR_NVS_NOT_FOUND) 21 | { 22 | ESP_LOGW(TAG, "NVS partition does not exist"); 23 | } 24 | else if (result == ESP_ERR_NVS_NOT_INITIALIZED) 25 | { 26 | ESP_LOGW(TAG, "NVS storage is not initialized. Call 'nvs_flash_init()' first."); 27 | } 28 | else 29 | { 30 | ESP_ERROR_CHECK(result); 31 | } 32 | return result == ESP_OK; 33 | } 34 | 35 | bool NVSHandler::openNvsWrite(const char* partition, HandleCloser& handleCloser) 36 | { 37 | nvs_handle handle = 0; 38 | const esp_err_t result = nvs_open(partition, NVS_READWRITE, &handle); 39 | handleCloser.setHandle(handle); 40 | 41 | if (result == ESP_ERR_NVS_NOT_INITIALIZED) 42 | { 43 | ESP_LOGW(TAG, "NVS storage is not initialized. Call 'nvs_flash_init()' first."); 44 | } 45 | else 46 | { 47 | ESP_ERROR_CHECK(result); 48 | } 49 | return result == ESP_OK; 50 | } 51 | 52 | bool NVSHandler::commit(HandleCloser& handleCloser) 53 | { 54 | const esp_err_t result = nvs_commit(handleCloser.getHandle()); 55 | ESP_ERROR_CHECK(result); 56 | return result == ESP_OK; 57 | } 58 | 59 | bool NVSHandler::readNvsValue( 60 | HandleCloser& handleCloser, const char* key, uint8_t* data, size_t expected_length, bool silent) 61 | { 62 | size_t size = expected_length; 63 | const esp_err_t result = nvs_get_blob(handleCloser.getHandle(), key, data, &size); 64 | #ifdef DEBUG 65 | Serial.print("[readNvsValue] Reading " + String(key) + " with value "); 66 | for (size_t i = 0; i < size; ++i) 67 | { 68 | Serial.print(data[i], HEX); 69 | } 70 | Serial.println(); 71 | #endif 72 | 73 | bool success = result == ESP_OK && size == expected_length; 74 | if (!success && !silent) 75 | { 76 | if (result == ESP_OK && size != expected_length) 77 | { 78 | ESP_LOGW(TAG, "Invalid size of NVS data for %s", key); 79 | } 80 | 81 | if (result == ESP_ERR_NVS_NOT_FOUND) 82 | { 83 | ESP_LOGW(TAG, "No NVS data found for %s", key); 84 | } 85 | } 86 | 87 | if (result != ESP_ERR_NVS_NOT_FOUND) 88 | { 89 | ESP_ERROR_CHECK(result); 90 | } 91 | return success; 92 | } 93 | 94 | bool NVSHandler::writeNvsValue(HandleCloser& handleCloser, const char* key, const uint8_t* data, size_t len) 95 | { 96 | uint8_t buf[16]; 97 | if (!readNvsValue(handleCloser, key, buf, len, true) || memcmp(buf, data, len) != 0) 98 | { 99 | const esp_err_t result = nvs_set_blob(handleCloser.getHandle(), key, data, len); 100 | ESP_ERROR_CHECK(result); 101 | return result == ESP_OK; 102 | } 103 | 104 | return true; 105 | } -------------------------------------------------------------------------------- /src/NVSHandler.h: -------------------------------------------------------------------------------- 1 | #ifndef _NVS_HANDLER_H 2 | #define _NVS_HANDLER_H 3 | 4 | #include "nvs_flash.h" 5 | 6 | class HandleCloser 7 | { 8 | friend class NVSHandler; 9 | 10 | public: 11 | explicit HandleCloser(nvs_handle handle = 0) : h(handle) {} 12 | ~HandleCloser() { nvs_close(h); } 13 | 14 | protected: 15 | void setHandle(nvs_handle handle) { this->h = handle; } 16 | nvs_handle getHandle() { return h; } 17 | 18 | private: 19 | nvs_handle h; 20 | }; 21 | 22 | class NVSHandler 23 | { 24 | public: 25 | static bool openNvsRead(const char* partition, HandleCloser& handleCloser); 26 | static bool openNvsWrite(const char* partition, HandleCloser& handleCloser); 27 | static bool commit(HandleCloser& HandleCloser); 28 | static bool readNvsValue( 29 | HandleCloser& handleCloser, const char* key, uint8_t* data, size_t expected_length, bool silent = true); 30 | static bool writeNvsValue(HandleCloser& handleCloser, const char* key, const uint8_t* data, size_t len); 31 | 32 | private: 33 | NVSHandler(); 34 | ~NVSHandler(); 35 | }; 36 | 37 | #endif -------------------------------------------------------------------------------- /src/TTN_BLE_esp32.cpp: -------------------------------------------------------------------------------- 1 | #include "TTN_BLE_esp32.h" 2 | #include "ByteArrayUtils.h" 3 | #include "helper.h" 4 | #include 5 | #include 6 | 7 | 8 | /******************************************** 9 | * BLE callback when client connect/disconnect 10 | * reset the esp32 when disconnecting 11 | ********************************************/ 12 | class MyServerCallbacks : public BLEServerCallbacks, TTN_BLE_esp32 13 | { 14 | void onConnect(BLEServer* pServer) { 15 | ESP_LOGI(TAG,"BLE client connected"); 16 | } 17 | 18 | void onDisconnect(BLEServer* pServer) { 19 | ESP_LOGI(TAG, "BLE client disconnected"); 20 | rebootESP32(); 21 | } 22 | }; 23 | /******************************** 24 | * BLE callback when BLE client (the phone) sends data to characteristic 25 | *********************************/ 26 | class MyCallbacks : public BLECharacteristicCallbacks, TTN_BLE_esp32 27 | { 28 | void onWrite(BLECharacteristic* pCharacteristic) 29 | { 30 | BLEUUID myUUID = pCharacteristic->getUUID(); 31 | TTN_esp32* ttn = TTN_esp32::getInstance(); 32 | ttn->restoreKeys(); 33 | 34 | /*OTAA*/ 35 | if (myUUID.equals(BLEUUID::fromString(CHARACTERISTIC_DEVEUI))) 36 | { 37 | ESP_LOGI(TAG,"DevEUI"); 38 | byte* value = pCharacteristic->getData(); 39 | ByteArrayUtils::swapBytes(value, 8); 40 | ttn->setDevEui(value); 41 | } 42 | if (myUUID.equals(BLEUUID::fromString(CHARACTERISTIC_APPEUI))) 43 | { 44 | ESP_LOGI(TAG,"AppEUI"); 45 | byte* value = pCharacteristic->getData(); 46 | ByteArrayUtils::swapBytes(value, 8); 47 | ttn->setAppEui(value); 48 | } 49 | if (myUUID.equals(BLEUUID::fromString(CHARACTERISTIC_APPKEY))) 50 | { 51 | ESP_LOGI(TAG,"AppKey"); 52 | byte* value = pCharacteristic->getData(); 53 | ttn->setAppKey(value); 54 | } 55 | /*ABP*/ 56 | if (myUUID.equals(BLEUUID::fromString(CHARACTERISTIC_DEV_ADDR))) 57 | { 58 | ESP_LOGI(TAG,"devADDR"); 59 | } 60 | if (myUUID.equals(BLEUUID::fromString(CHARACTERISTIC_NWKSKEY))) 61 | { 62 | ESP_LOGI(TAG,"NwkSKey"); 63 | } 64 | if (myUUID.equals(BLEUUID::fromString(CHARACTERISTIC_APP_SKEY))) 65 | { 66 | ESP_LOGI(TAG,"AppSKey"); 67 | } 68 | 69 | ttn->saveKeys(); 70 | } 71 | }; 72 | 73 | bool TTN_BLE_esp32::begin(std::string bt_name) 74 | { 75 | TTN_esp32* ttn = TTN_esp32::getInstance(); 76 | ttn->restoreKeys(); 77 | if (bt_name == "") 78 | { 79 | std::string nameDev(ttn->getDevEui(true).c_str()); 80 | bt_name.append("RGOT_").append(nameDev); 81 | } 82 | BLEDevice::init(bt_name); 83 | ESP_LOGI(TAG, "BLE Begin server: %s", bt_name.c_str()); 84 | BLEServer* pServer = BLEDevice::createServer(); 85 | pServer->setCallbacks(new MyServerCallbacks()); 86 | BLEService* pService = pServer->createService(SERVICE_UUID); 87 | BLECharacteristic* pCharacteristicAppKey = pService->createCharacteristic( 88 | CHARACTERISTIC_APPKEY, BLECharacteristic::PROPERTY_READ | BLECharacteristic::PROPERTY_WRITE); 89 | BLECharacteristic* pCharacteristicDevEUI = pService->createCharacteristic( 90 | CHARACTERISTIC_DEVEUI, BLECharacteristic::PROPERTY_READ | BLECharacteristic::PROPERTY_WRITE); 91 | BLECharacteristic* pCharacteristicAppEUI = pService->createCharacteristic( 92 | CHARACTERISTIC_APPEUI, BLECharacteristic::PROPERTY_READ | BLECharacteristic::PROPERTY_WRITE); 93 | BLECharacteristic* pCharacteristicDevAddr = pService->createCharacteristic( 94 | CHARACTERISTIC_DEV_ADDR, BLECharacteristic::PROPERTY_READ | BLECharacteristic::PROPERTY_WRITE); 95 | BLECharacteristic* pCharacteristicNwkSKey = pService->createCharacteristic( 96 | CHARACTERISTIC_NWKSKEY, BLECharacteristic::PROPERTY_READ | BLECharacteristic::PROPERTY_WRITE); 97 | BLECharacteristic* pCharacteristicAppSKey = pService->createCharacteristic( 98 | CHARACTERISTIC_APP_SKEY, BLECharacteristic::PROPERTY_READ | BLECharacteristic::PROPERTY_WRITE); 99 | 100 | pCharacteristicDevEUI->setCallbacks(new MyCallbacks()); 101 | pCharacteristicAppEUI->setCallbacks(new MyCallbacks()); 102 | pCharacteristicAppKey->setCallbacks(new MyCallbacks()); 103 | pCharacteristicDevAddr->setCallbacks(new MyCallbacks()); 104 | pCharacteristicNwkSKey->setCallbacks(new MyCallbacks()); 105 | pCharacteristicAppSKey->setCallbacks(new MyCallbacks()); 106 | byte buf[33]; 107 | 108 | int len = ttn->getDevEui(buf); 109 | pCharacteristicDevEUI->setValue(buf, len); 110 | 111 | len = ttn->getAppEui(buf); 112 | pCharacteristicAppEUI->setValue(buf, len); 113 | 114 | len = ttn->getAppKey(buf); 115 | for (size_t i = 3; i < len-4; i++) 116 | { 117 | buf[i] = 0; 118 | } 119 | pCharacteristicAppKey->setValue(buf, len); 120 | 121 | pService->start(); 122 | BLEAdvertising* pAdvertising = pServer->getAdvertising(); 123 | pAdvertising->addServiceUUID(SERVICE_UUID); 124 | pServer->startAdvertising(); 125 | pAdvertising->start(); 126 | return true; 127 | } 128 | 129 | bool TTN_BLE_esp32::stop() 130 | { 131 | ESP_LOGI(TAG, "stop BLE"); 132 | BLEDevice::deinit(); 133 | return true; 134 | } 135 | 136 | void TTN_BLE_esp32::rebootESP32() { 137 | ESP_LOGI(TAG, "reboot esp32"); 138 | esp_task_wdt_init(1, true); // program task with watchdog to reset the esp32 139 | esp_task_wdt_add(NULL); 140 | while (true) ; 141 | } 142 | 143 | bool TTN_BLE_esp32::getInitialized() 144 | { 145 | return BLEDevice::getInitialized(); 146 | } 147 | TTN_BLE_esp32::TTN_BLE_esp32() {} 148 | void TTN_BLE_esp32::init() {} 149 | -------------------------------------------------------------------------------- /src/TTN_BLE_esp32.h: -------------------------------------------------------------------------------- 1 | /************************************ 2 | You can use this library with a BLE app. 3 | note the service uuid and characteristics below. 4 | you can install the android app TTN ESP32 Provisioning 5 | https://play.google.com/store/apps/details?id=org.rgot.BLE_TEST 6 | to use this library and provisioning the esp32 Lora 7 | ****************************************/ 8 | #ifndef _TTN_BLE_ESP32_h 9 | #define _TTN_BLE_ESP32_h 10 | 11 | #if defined(ARDUINO) && ARDUINO >= 100 12 | #include "Arduino.h" 13 | #else 14 | #include "WProgram.h" 15 | #endif 16 | #include 17 | #include 18 | #include 19 | #include 20 | 21 | // See the following for generating UUIDs: 22 | // https://www.uuidgenerator.net/ 23 | 24 | #define SERVICE_UUID "16f9e4cb-d966-4e2c-9b23-35cba66e4f09" 25 | #define CHARACTERISTIC_APPKEY "c357e06e-523e-11ea-8d77-2e728ce88125" 26 | #define CHARACTERISTIC_DEVEUI "c357e2d0-523e-11ea-8d77-2e728ce88125" 27 | #define CHARACTERISTIC_APPEUI "c357e6cc-523e-11ea-8d77-2e728ce88125" 28 | #define CHARACTERISTIC_DEV_ADDR "c357e848-523e-11ea-8d77-2e728ce88125" 29 | #define CHARACTERISTIC_NWKSKEY "c357e992-523e-11ea-8d77-2e728ce88125" 30 | #define CHARACTERISTIC_APP_SKEY "c357ebf4-523e-11ea-8d77-2e728ce88125" 31 | 32 | class TTN_BLE_esp32 33 | { 34 | protected: 35 | 36 | 37 | public: 38 | TTN_BLE_esp32(); 39 | void init(); 40 | static bool begin(std::string bt_name = ""); 41 | static bool stop(); 42 | static void rebootESP32(); 43 | static bool getInitialized(); 44 | }; 45 | 46 | #endif 47 | 48 | -------------------------------------------------------------------------------- /src/TTN_CayenneLPP.cpp: -------------------------------------------------------------------------------- 1 | // Adapted from https://developer.mbed.org/teams/myDevicesIoT/code/Cayenne-LPP/ 2 | 3 | // Copyright © 2017 The Things Network 4 | // Use of this source code is governed by the MIT license that can be found in 5 | // the LICENSE file. 6 | 7 | #include "TTN_CayenneLPP.h" 8 | 9 | TTN_CayenneLPP::TTN_CayenneLPP(uint8_t size) : maxsize(size) 10 | { 11 | buffer = (uint8_t*)malloc(size); 12 | cursor = 0; 13 | } 14 | 15 | TTN_CayenneLPP::~TTN_CayenneLPP(void) 16 | { 17 | free(buffer); 18 | } 19 | 20 | void TTN_CayenneLPP::reset(void) 21 | { 22 | cursor = 0; 23 | } 24 | 25 | uint8_t TTN_CayenneLPP::getSize(void) 26 | { 27 | return cursor; 28 | } 29 | 30 | uint8_t* TTN_CayenneLPP::getBuffer(void) 31 | { 32 | // uint8_t[cursor] result; 33 | // memcpy(result, buffer, cursor); 34 | // return result; 35 | return buffer; 36 | } 37 | 38 | uint8_t TTN_CayenneLPP::copy(uint8_t* dst) 39 | { 40 | memcpy(dst, buffer, cursor); 41 | return cursor; 42 | } 43 | 44 | uint8_t TTN_CayenneLPP::addDigitalInput(uint8_t channel, uint8_t value) 45 | { 46 | if ((cursor + LPP_DIGITAL_INPUT_SIZE) > maxsize) 47 | { 48 | return 0; 49 | } 50 | buffer[cursor++] = channel; 51 | buffer[cursor++] = LPP_DIGITAL_INPUT; 52 | buffer[cursor++] = value; 53 | 54 | return cursor; 55 | } 56 | 57 | uint8_t TTN_CayenneLPP::addDigitalOutput(uint8_t channel, uint8_t value) 58 | { 59 | if ((cursor + LPP_DIGITAL_OUTPUT_SIZE) > maxsize) 60 | { 61 | return 0; 62 | } 63 | buffer[cursor++] = channel; 64 | buffer[cursor++] = LPP_DIGITAL_OUTPUT; 65 | buffer[cursor++] = value; 66 | 67 | return cursor; 68 | } 69 | 70 | uint8_t TTN_CayenneLPP::addAnalogInput(uint8_t channel, float value) 71 | { 72 | if ((cursor + LPP_ANALOG_INPUT_SIZE) > maxsize) 73 | { 74 | return 0; 75 | } 76 | 77 | int16_t val = value * 100; 78 | buffer[cursor++] = channel; 79 | buffer[cursor++] = LPP_ANALOG_INPUT; 80 | buffer[cursor++] = val >> 8; 81 | buffer[cursor++] = val; 82 | 83 | return cursor; 84 | } 85 | 86 | uint8_t TTN_CayenneLPP::addAnalogOutput(uint8_t channel, float value) 87 | { 88 | if ((cursor + LPP_ANALOG_OUTPUT_SIZE) > maxsize) 89 | { 90 | return 0; 91 | } 92 | int16_t val = value * 100; 93 | buffer[cursor++] = channel; 94 | buffer[cursor++] = LPP_ANALOG_OUTPUT; 95 | buffer[cursor++] = val >> 8; 96 | buffer[cursor++] = val; 97 | 98 | return cursor; 99 | } 100 | 101 | uint8_t TTN_CayenneLPP::addLuminosity(uint8_t channel, uint16_t lux) 102 | { 103 | if ((cursor + LPP_LUMINOSITY_SIZE) > maxsize) 104 | { 105 | return 0; 106 | } 107 | buffer[cursor++] = channel; 108 | buffer[cursor++] = LPP_LUMINOSITY; 109 | buffer[cursor++] = lux >> 8; 110 | buffer[cursor++] = lux; 111 | 112 | return cursor; 113 | } 114 | 115 | uint8_t TTN_CayenneLPP::addPresence(uint8_t channel, uint8_t value) 116 | { 117 | if ((cursor + LPP_PRESENCE_SIZE) > maxsize) 118 | { 119 | return 0; 120 | } 121 | buffer[cursor++] = channel; 122 | buffer[cursor++] = LPP_PRESENCE; 123 | buffer[cursor++] = value; 124 | 125 | return cursor; 126 | } 127 | 128 | uint8_t TTN_CayenneLPP::addTemperature(uint8_t channel, float celsius) 129 | { 130 | if ((cursor + LPP_TEMPERATURE_SIZE) > maxsize) 131 | { 132 | return 0; 133 | } 134 | int16_t val = celsius * 10; 135 | buffer[cursor++] = channel; 136 | buffer[cursor++] = LPP_TEMPERATURE; 137 | buffer[cursor++] = val >> 8; 138 | buffer[cursor++] = val; 139 | 140 | return cursor; 141 | } 142 | 143 | uint8_t TTN_CayenneLPP::addRelativeHumidity(uint8_t channel, float rh) 144 | { 145 | if ((cursor + LPP_RELATIVE_HUMIDITY_SIZE) > maxsize) 146 | { 147 | return 0; 148 | } 149 | buffer[cursor++] = channel; 150 | buffer[cursor++] = LPP_RELATIVE_HUMIDITY; 151 | buffer[cursor++] = rh * 2; 152 | 153 | return cursor; 154 | } 155 | 156 | uint8_t TTN_CayenneLPP::addAccelerometer(uint8_t channel, float x, float y, float z) 157 | { 158 | if ((cursor + LPP_ACCELEROMETER_SIZE) > maxsize) 159 | { 160 | return 0; 161 | } 162 | int16_t vx = x * 1000; 163 | int16_t vy = y * 1000; 164 | int16_t vz = z * 1000; 165 | 166 | buffer[cursor++] = channel; 167 | buffer[cursor++] = LPP_ACCELEROMETER; 168 | buffer[cursor++] = vx >> 8; 169 | buffer[cursor++] = vx; 170 | buffer[cursor++] = vy >> 8; 171 | buffer[cursor++] = vy; 172 | buffer[cursor++] = vz >> 8; 173 | buffer[cursor++] = vz; 174 | 175 | return cursor; 176 | } 177 | 178 | uint8_t TTN_CayenneLPP::addBarometricPressure(uint8_t channel, float hpa) 179 | { 180 | if ((cursor + LPP_BAROMETRIC_PRESSURE_SIZE) > maxsize) 181 | { 182 | return 0; 183 | } 184 | int16_t val = hpa * 10; 185 | 186 | buffer[cursor++] = channel; 187 | buffer[cursor++] = LPP_BAROMETRIC_PRESSURE; 188 | buffer[cursor++] = val >> 8; 189 | buffer[cursor++] = val; 190 | 191 | return cursor; 192 | } 193 | 194 | uint8_t TTN_CayenneLPP::addGyrometer(uint8_t channel, float x, float y, float z) 195 | { 196 | if ((cursor + LPP_GYROMETER_SIZE) > maxsize) 197 | { 198 | return 0; 199 | } 200 | int16_t vx = x * 100; 201 | int16_t vy = y * 100; 202 | int16_t vz = z * 100; 203 | 204 | buffer[cursor++] = channel; 205 | buffer[cursor++] = LPP_GYROMETER; 206 | buffer[cursor++] = vx >> 8; 207 | buffer[cursor++] = vx; 208 | buffer[cursor++] = vy >> 8; 209 | buffer[cursor++] = vy; 210 | buffer[cursor++] = vz >> 8; 211 | buffer[cursor++] = vz; 212 | 213 | return cursor; 214 | } 215 | 216 | uint8_t TTN_CayenneLPP::addGPS(uint8_t channel, float latitude, float longitude, float meters) 217 | { 218 | if ((cursor + LPP_GPS_SIZE) > maxsize) 219 | { 220 | return 0; 221 | } 222 | int32_t lat = latitude * 10000; 223 | int32_t lon = longitude * 10000; 224 | int32_t alt = meters * 100; 225 | 226 | buffer[cursor++] = channel; 227 | buffer[cursor++] = LPP_GPS; 228 | 229 | buffer[cursor++] = lat >> 16; 230 | buffer[cursor++] = lat >> 8; 231 | buffer[cursor++] = lat; 232 | buffer[cursor++] = lon >> 16; 233 | buffer[cursor++] = lon >> 8; 234 | buffer[cursor++] = lon; 235 | buffer[cursor++] = alt >> 16; 236 | buffer[cursor++] = alt >> 8; 237 | buffer[cursor++] = alt; 238 | 239 | return cursor; 240 | } 241 | -------------------------------------------------------------------------------- /src/TTN_CayenneLPP.h: -------------------------------------------------------------------------------- 1 | // Adapted from https://developer.mbed.org/teams/myDevicesIoT/code/Cayenne-LPP/ 2 | 3 | // Copyright © 2017 The Things Network 4 | // Use of this source code is governed by the MIT license that can be found in 5 | // the LICENSE file. 6 | 7 | #ifndef _CAYENNE_LPP_H_ 8 | #define _CAYENNE_LPP_H_ 9 | 10 | #include 11 | 12 | // LPP_BATTERY = // TODO Unsupported in IPSO Smart Object 13 | // LPP_PROXIMITY = // TODO Unsupported in IPSO Smart Object 14 | 15 | #define LPP_DIGITAL_INPUT 0 // 1 byte 16 | #define LPP_DIGITAL_OUTPUT 1 // 1 byte 17 | #define LPP_ANALOG_INPUT 2 // 2 bytes, 0.01 signed 18 | #define LPP_ANALOG_OUTPUT 3 // 2 bytes, 0.01 signed 19 | #define LPP_LUMINOSITY 101 // 2 bytes, 1 lux unsigned 20 | #define LPP_PRESENCE 102 // 1 byte, 1 21 | #define LPP_TEMPERATURE 103 // 2 bytes, 0.1°C signed 22 | #define LPP_RELATIVE_HUMIDITY 104 // 1 byte, 0.5% unsigned 23 | #define LPP_ACCELEROMETER 113 // 2 bytes per axis, 0.001G 24 | #define LPP_BAROMETRIC_PRESSURE 115 // 2 bytes 0.1 hPa Unsigned 25 | #define LPP_GYROMETER 134 // 2 bytes per axis, 0.01 °/s 26 | #define LPP_GPS 136 // 3 byte lon/lat 0.0001 °, 3 bytes alt 0.01 meter 27 | 28 | // Data ID + Data Type + Data Size 29 | #define LPP_DIGITAL_INPUT_SIZE 3 // 1 byte 30 | #define LPP_DIGITAL_OUTPUT_SIZE 3 // 1 byte 31 | #define LPP_ANALOG_INPUT_SIZE 4 // 2 bytes, 0.01 signed 32 | #define LPP_ANALOG_OUTPUT_SIZE 4 // 2 bytes, 0.01 signed 33 | #define LPP_LUMINOSITY_SIZE 4 // 2 bytes, 1 lux unsigned 34 | #define LPP_PRESENCE_SIZE 3 // 1 byte, 1 35 | #define LPP_TEMPERATURE_SIZE 4 // 2 bytes, 0.1°C signed 36 | #define LPP_RELATIVE_HUMIDITY_SIZE 3 // 1 byte, 0.5% unsigned 37 | #define LPP_ACCELEROMETER_SIZE 8 // 2 bytes per axis, 0.001G 38 | #define LPP_BAROMETRIC_PRESSURE_SIZE 4 // 2 bytes 0.1 hPa Unsigned 39 | #define LPP_GYROMETER_SIZE 8 // 2 bytes per axis, 0.01 °/s 40 | #define LPP_GPS_SIZE 11 // 3 byte lon/lat 0.0001 °, 3 bytes alt 0.01 meter 41 | 42 | class TTN_CayenneLPP 43 | { 44 | public: 45 | TTN_CayenneLPP(uint8_t size = 51); 46 | ~TTN_CayenneLPP(); 47 | 48 | void reset(void); 49 | uint8_t getSize(void); 50 | uint8_t* getBuffer(void); 51 | uint8_t copy(uint8_t* buffer); 52 | 53 | uint8_t addDigitalInput(uint8_t channel, uint8_t value); 54 | uint8_t addDigitalOutput(uint8_t channel, uint8_t value); 55 | 56 | uint8_t addAnalogInput(uint8_t channel, float value); 57 | uint8_t addAnalogOutput(uint8_t channel, float value); 58 | 59 | uint8_t addLuminosity(uint8_t channel, uint16_t lux); 60 | uint8_t addPresence(uint8_t channel, uint8_t value); 61 | uint8_t addTemperature(uint8_t channel, float celsius); 62 | uint8_t addRelativeHumidity(uint8_t channel, float rh); 63 | uint8_t addAccelerometer(uint8_t channel, float x, float y, float z); 64 | uint8_t addBarometricPressure(uint8_t channel, float hpa); 65 | uint8_t addGyrometer(uint8_t channel, float x, float y, float z); 66 | uint8_t addGPS(uint8_t channel, float latitude, float longitude, float meters); 67 | 68 | private: 69 | uint8_t* buffer; 70 | uint8_t maxsize; 71 | uint8_t cursor; 72 | }; 73 | 74 | #endif 75 | -------------------------------------------------------------------------------- /src/helper.h: -------------------------------------------------------------------------------- 1 | #ifndef _HELPER_H 2 | #define _HELPER_H 3 | 4 | #include "nvs_flash.h" 5 | 6 | static const char* const DEBUG = "debug"; 7 | static const char* const TAG = "ttn_prov"; 8 | static const char* const NVS_FLASH_PARTITION = "ttn"; 9 | static const char* const NVS_FLASH_KEY_DEV_EUI = "devEui"; 10 | static const char* const NVS_FLASH_KEY_APP_EUI = "appEui"; 11 | static const char* const NVS_FLASH_KEY_APP_KEY = "appKey"; 12 | static const char* const NVS_FLASH_KEY_APP_SESSION_KEY = "AppSKey"; 13 | static const char* const NVS_FLASH_KEY_NWK_SESSION_KEY = "NwkSKey"; 14 | static const char* const NVS_FLASH_KEY_DEV_ADDR = "devAddr"; 15 | static const char* const NVS_FLASH_KEY_SEQ_NUM_UP = "seqNumUp"; 16 | 17 | #endif /* _HELPER_H */ 18 | -------------------------------------------------------------------------------- /src/lmic/aes/other.c: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | * Copyright (c) 2016 Matthijs Kooijman 3 | * 4 | * LICENSE 5 | * 6 | * Permission is hereby granted, free of charge, to anyone 7 | * obtaining a copy of this document and accompanying files, 8 | * to do whatever they want with them without any restriction, 9 | * including, but not limited to, copying, modification and 10 | * redistribution. 11 | * 12 | * NO WARRANTY OF ANY KIND IS PROVIDED. 13 | *******************************************************************************/ 14 | 15 | /* 16 | * The original LMIC AES implementation integrates raw AES encryption 17 | * with CMAC and AES-CTR in a single piece of code. Most other AES 18 | * implementations (only) offer raw single block AES encryption, so this 19 | * file contains an implementation of CMAC and AES-CTR, and offers the 20 | * same API through the os_aes() function as the original AES 21 | * implementation. This file assumes that there is an encryption 22 | * function available with this signature: 23 | * 24 | * extern "C" void lmic_aes_encrypt(u1_t *data, u1_t *key); 25 | * 26 | * That takes a single 16-byte buffer and encrypts it wit the given 27 | * 16-byte key. 28 | */ 29 | 30 | #include "../lmic/oslmic.h" 31 | 32 | #if !defined(USE_ORIGINAL_AES) 33 | 34 | // This should be defined elsewhere 35 | void lmic_aes_encrypt(u1_t *data, u1_t *key); 36 | 37 | // global area for passing parameters (aux, key) 38 | u4_t AESAUX[16/sizeof(u4_t)]; 39 | u4_t AESKEY[16/sizeof(u4_t)]; 40 | 41 | // Shift the given buffer left one bit 42 | static void shift_left(xref2u1_t buf, u1_t len) { 43 | while (len--) { 44 | u1_t next = len ? buf[1] : 0; 45 | 46 | u1_t val = (*buf << 1); 47 | if (next & 0x80) 48 | val |= 1; 49 | *buf++ = val; 50 | } 51 | } 52 | 53 | // Apply RFC4493 CMAC, using AESKEY as the key. If prepend_aux is true, 54 | // AESAUX is prepended to the message. AESAUX is used as working memory 55 | // in any case. The CMAC result is returned in AESAUX as well. 56 | static void os_aes_cmac(xref2u1_t buf, u2_t len, u1_t prepend_aux) { 57 | if (prepend_aux) 58 | lmic_aes_encrypt(AESaux, AESkey); 59 | else 60 | memset (AESaux, 0, 16); 61 | 62 | while (len > 0) { 63 | u1_t need_padding = 0; 64 | for (u1_t i = 0; i < 16; ++i, ++buf, --len) { 65 | if (len == 0) { 66 | // The message is padded with 0x80 and then zeroes. 67 | // Since zeroes are no-op for xor, we can just skip them 68 | // and leave AESAUX unchanged for them. 69 | AESaux[i] ^= 0x80; 70 | need_padding = 1; 71 | break; 72 | } 73 | AESaux[i] ^= *buf; 74 | } 75 | 76 | if (len == 0) { 77 | // Final block, xor with K1 or K2. K1 and K2 are calculated 78 | // by encrypting the all-zeroes block and then applying some 79 | // shifts and xor on that. 80 | u1_t final_key[16]; 81 | memset(final_key, 0, sizeof(final_key)); 82 | lmic_aes_encrypt(final_key, AESkey); 83 | 84 | // Calculate K1 85 | u1_t msb = final_key[0] & 0x80; 86 | shift_left(final_key, sizeof(final_key)); 87 | if (msb) 88 | final_key[sizeof(final_key)-1] ^= 0x87; 89 | 90 | // If the final block was not complete, calculate K2 from K1 91 | if (need_padding) { 92 | msb = final_key[0] & 0x80; 93 | shift_left(final_key, sizeof(final_key)); 94 | if (msb) 95 | final_key[sizeof(final_key)-1] ^= 0x87; 96 | } 97 | 98 | // Xor with K1 or K2 99 | for (u1_t i = 0; i < sizeof(final_key); ++i) 100 | AESaux[i] ^= final_key[i]; 101 | } 102 | 103 | lmic_aes_encrypt(AESaux, AESkey); 104 | } 105 | } 106 | 107 | // Run AES-CTR using the key in AESKEY and using AESAUX as the 108 | // counter block. The last byte of the counter block will be incremented 109 | // for every block. The given buffer will be encrypted in place. 110 | static void os_aes_ctr (xref2u1_t buf, u2_t len) { 111 | u1_t ctr[16]; 112 | while (len) { 113 | // Encrypt the counter block with the selected key 114 | memcpy(ctr, AESaux, sizeof(ctr)); 115 | lmic_aes_encrypt(ctr, AESkey); 116 | 117 | // Xor the payload with the resulting ciphertext 118 | for (u1_t i = 0; i < 16 && len > 0; i++, len--, buf++) 119 | *buf ^= ctr[i]; 120 | 121 | // Increment the block index byte 122 | AESaux[15]++; 123 | } 124 | } 125 | 126 | u4_t os_aes (u1_t mode, xref2u1_t buf, u2_t len) { 127 | switch (mode & ~AES_MICNOAUX) { 128 | case AES_MIC: 129 | os_aes_cmac(buf, len, /* prepend_aux */ !(mode & AES_MICNOAUX)); 130 | return os_rmsbf4(AESaux); 131 | 132 | case AES_ENC: 133 | // TODO: Check / handle when len is not a multiple of 16 134 | for (u1_t i = 0; i < len; i += 16) 135 | lmic_aes_encrypt(buf+i, AESkey); 136 | break; 137 | 138 | case AES_CTR: 139 | os_aes_ctr(buf, len); 140 | break; 141 | } 142 | return 0; 143 | } 144 | 145 | #endif // !defined(USE_ORIGINAL_AES) 146 | -------------------------------------------------------------------------------- /src/lmic/arduino_lmic.h: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | Module: arduino_lmic.h 4 | 5 | Function: 6 | Arduino-LMIC C++ top-level include file 7 | 8 | Copyright & License: 9 | See accompanying LICENSE file. 10 | 11 | Author: 12 | Matthijs Kooijman 2015 13 | Terry Moore, MCCI November 2018 14 | 15 | */ 16 | 17 | #pragma once 18 | 19 | #ifndef _ARDUINO_LMIC_H_ 20 | # define _ARDUINO_LMIC_H_ 21 | 22 | #ifdef __cplusplus 23 | extern "C"{ 24 | #endif 25 | 26 | #include "lmic/lmic.h" 27 | #include "lmic/lmic_bandplan.h" 28 | #include "lmic/lmic_util.h" 29 | 30 | #ifdef __cplusplus 31 | } 32 | #endif 33 | 34 | #endif /* _ARDUINO_LMIC_H_ */ 35 | -------------------------------------------------------------------------------- /src/lmic/arduino_lmic_hal_boards.h: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | Module: arduino_lmic_hal_boards.h 4 | 5 | Function: 6 | Arduino-LMIC C++ HAL pinmaps for various boards 7 | 8 | Copyright & License: 9 | See accompanying LICENSE file. 10 | 11 | Author: 12 | Terry Moore, MCCI November 2018 13 | 14 | */ 15 | 16 | #pragma once 17 | 18 | #ifndef _arduino_lmic_hal_boards_h_ 19 | # define _arduino_lmic_hal_boards_h_ 20 | 21 | #include "lmic/arduino_lmic_hal_configuration.h" 22 | 23 | namespace TTN_esp32_LMIC { 24 | 25 | const HalPinmap_t *GetPinmap_FeatherM0LoRa(); 26 | const HalPinmap_t *GetPinmap_Feather32U4LoRa(); 27 | 28 | const HalPinmap_t *GetPinmap_Catena4420(); 29 | const HalPinmap_t *GetPinmap_Catena4551(); 30 | const HalPinmap_t *GetPinmap_Catena4610(); 31 | const HalPinmap_t *GetPinmap_Catena4610(); 32 | const HalPinmap_t *GetPinmap_Catena4611(); 33 | const HalPinmap_t *GetPinmap_Catena4612(); 34 | const HalPinmap_t *GetPinmap_Catena4617(); 35 | const HalPinmap_t *GetPinmap_Catena4618(); 36 | const HalPinmap_t *GetPinmap_Catena4630(); 37 | const HalPinmap_t *GetPinmap_Catena4801(); 38 | const HalPinmap_t *GetPinmap_Catena4802(); 39 | const HalPinmap_t* GetPinmap_ttgo_lora32_v1(); 40 | const HalPinmap_t *GetPinmap_ttgo_lora32_v21(); 41 | const HalPinmap_t* GetPinmap_heltec_lora32(); 42 | const HalPinmap_t* GetPinmap_Disco_L072cz_Lrwan1(); 43 | const HalPinmap_t *GetPinmap_heltec_wifi_lora_32(); 44 | const HalPinmap_t *GetPinmap_heltec_wifi_lora_32_V2(); 45 | const HalPinmap_t *GetPinmap_heltec_wireless_stick(); 46 | const HalPinmap_t *GetPinmap_M5stack_Lora(); 47 | const HalPinmap_t *GetPinmap_ttgo_TBEAM(); 48 | 49 | 50 | const HalPinmap_t *GetPinmap_ThisBoard(); 51 | 52 | }; /* namespace Arduino_LIMC */ 53 | 54 | #endif /* _arduino_lmic_hal_boards_h_ */ 55 | -------------------------------------------------------------------------------- /src/lmic/arduino_lmic_hal_configuration.h: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | Module: arduino_lmic_hal_configuration.h 4 | 5 | Function: 6 | Arduino-LMIC C++ HAL configuration APIs 7 | 8 | Copyright & License: 9 | See accompanying LICENSE file. 10 | 11 | Author: 12 | Matthijs Kooijman 2015 13 | Terry Moore, MCCI November 2018 14 | 15 | */ 16 | #pragma once 17 | 18 | #ifndef _arduino_lmic_hal_configuration_h_ 19 | # define _arduino_lmic_hal_configuration_h_ 20 | 21 | #include 22 | #include "lmic/lmic_env.h" 23 | 24 | namespace TTN_esp32_LMIC { 25 | 26 | /* these types should match the types used by the LMIC */ 27 | typedef int32_t ostime_t; 28 | 29 | // this type is used when we need to represent a threee-state signal 30 | enum class ThreeState_t : uint8_t { 31 | Off = 0, 32 | On = 1, 33 | HiZ = 2 34 | }; 35 | 36 | // forward reference 37 | class HalConfiguration_t; 38 | 39 | // 40 | // for legacy reasons, we need a plain-old-data C-like 41 | // structure that defines the "pin mapping" for the 42 | // common pins. Many clients initialize an instance of 43 | // this structure using named-field initialization. 44 | // 45 | // Be careful of alignment below. 46 | struct HalPinmap_t { 47 | // Use this for any unused pins. 48 | static constexpr uint8_t UNUSED_PIN = 0xff; 49 | static constexpr int NUM_DIO = 3; 50 | // for backward compatibility... 51 | static constexpr uint8_t LMIC_UNUSED_PIN = UNUSED_PIN; 52 | 53 | /* the contents */ 54 | uint8_t nss; // byte 0: pin for select 55 | uint8_t rxtx; // byte 1: pin for rx/tx control 56 | uint8_t rst; // byte 2: pin for reset 57 | uint8_t dio[NUM_DIO]; // bytes 3..5: pins for DIO0, DOI1, DIO2 58 | // true if we must set rxtx for rx_active, false for tx_active 59 | uint8_t rxtx_rx_active; // byte 6: polarity of rxtx active 60 | int8_t rssi_cal; // byte 7: cal in dB -- added to RSSI 61 | // measured prior to decision. 62 | // Must include noise guardband! 63 | uint32_t spi_freq; // bytes 8..11: SPI freq in Hz. 64 | 65 | // optional pointer to configuration object (bytes 12..15) 66 | HalConfiguration_t *pConfig; 67 | }; 68 | 69 | class HalConfiguration_t 70 | { 71 | public: 72 | HalConfiguration_t() {}; 73 | 74 | // these must match the constants in radio.c 75 | enum class TxPowerPolicy_t : uint8_t 76 | { 77 | RFO, 78 | PA_BOOST, 79 | PA_BOOST_20dBm 80 | }; 81 | 82 | virtual ostime_t setModuleActive(bool state) { 83 | LMIC_API_PARAMETER(state); 84 | 85 | // by default, if not overridden, do nothing 86 | // and return 0 to indicate that the caller 87 | // need not delay. 88 | return 0; 89 | } 90 | 91 | virtual void begin(void) {} 92 | virtual void end(void) {} 93 | virtual bool queryUsingTcxo(void) { return false; } 94 | 95 | // compute desired transmit power policy. HopeRF needs 96 | // (and previous versions of this library always chose) 97 | // PA_BOOST mode. So that's our default. Override this 98 | // for the Murata module. 99 | virtual TxPowerPolicy_t getTxPowerPolicy( 100 | TxPowerPolicy_t policy, 101 | int8_t requestedPower, 102 | uint32_t frequency 103 | ) 104 | { 105 | LMIC_API_PARAMETER(policy); 106 | LMIC_API_PARAMETER(requestedPower); 107 | LMIC_API_PARAMETER(frequency); 108 | // default: use PA_BOOST exclusively 109 | return TxPowerPolicy_t::PA_BOOST; 110 | } 111 | }; 112 | 113 | bool hal_init_with_pinmap(const HalPinmap_t *pPinmap); 114 | 115 | }; // end namespace TTN_esp32_LMIC 116 | 117 | #endif 118 | -------------------------------------------------------------------------------- /src/lmic/arduino_lmic_lorawan_compliance.h: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | Module: arduino_lmic_lorawan_compliance.h 4 | 5 | Function: 6 | Arduino-LMIC C++ include file for LoRaWAN compliance 7 | 8 | Copyright & License: 9 | See accompanying LICENSE file. 10 | 11 | Author: 12 | Terry Moore, MCCI March 2019 13 | 14 | */ 15 | 16 | #pragma once 17 | 18 | #ifndef _ARDUINO_LMIC_LORAWAN_COMPLIANCE_H_ 19 | # define _ARDUINO_LMIC_LORAWAN_COMPLIANCE_H_ 20 | 21 | #ifdef __cplusplus 22 | extern "C"{ 23 | #endif 24 | 25 | #include "lmic/lorawan_spec_compliance.h" 26 | 27 | #ifdef __cplusplus 28 | } 29 | #endif 30 | 31 | #endif /* _ARDUINO_LMIC_LORAWAN_COMPLIANCE_H_ */ 32 | -------------------------------------------------------------------------------- /src/lmic/arduino_lmic_user_configuration.h: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | Module: arduino_lmic_user_configuration.h 4 | 5 | Function: 6 | Get the Arduino-LMIC configuration into scope 7 | 8 | Copyright & License: 9 | See accompanying LICENSE file. 10 | 11 | Author: 12 | Terry Moore, MCCI November 2018 13 | 14 | */ 15 | #pragma once 16 | 17 | #ifndef _arduino_lmic_user_configuration_h_ 18 | # define _arduino_lmic_user_configuration_h_ 19 | 20 | # ifdef __cplusplus 21 | extern "C" { 22 | # endif 23 | 24 | # include "lmic/lmic_config_preconditions.h" 25 | 26 | # ifdef __cplusplus 27 | } 28 | # endif 29 | 30 | #endif /* _arduino_lmic_user_configuration_h_ */ 31 | -------------------------------------------------------------------------------- /src/lmic/hal/getpinmap_M5stack_Lora.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | Module: getconfig_ttgo_lora32_v1.cpp 4 | 5 | Function: 6 | Arduino-LMIC C++ HAL pinmap for TTGO ESP32 OLED V1 7 | 8 | Copyright & License: 9 | See accompanying LICENSE file. 10 | 11 | Author: 12 | German Martin, gmag11@gmail.com June 2019 13 | 14 | */ 15 | 16 | #include 17 | 18 | #include "../lmic/oslmic.h" 19 | #include "lmic/arduino_lmic_hal_boards.h" 20 | 21 | #define SS 5 22 | #define RST_LoRa 26 23 | #define DIO0 36 24 | #define DIO1 HalPinmap_t::UNUSED_PIN 25 | #define DIO2 HalPinmap_t::UNUSED_PIN 26 | 27 | namespace TTN_esp32_LMIC 28 | { 29 | 30 | class HalConfiguration_heltec_wireless_stick : public HalConfiguration_t 31 | { 32 | public: 33 | enum DIGITAL_PINS : uint8_t 34 | { 35 | PIN_SX1276_NSS = SS, 36 | PIN_SX1276_NRESET = RST_LoRa, 37 | PIN_SX1276_DIO0 = DIO0, 38 | PIN_SX1276_DIO1 = DIO1, 39 | PIN_SX1276_DIO2 = DIO2, 40 | PIN_SX1276_ANT_SWITCH_RX = HalPinmap_t::UNUSED_PIN, 41 | PIN_SX1276_ANT_SWITCH_TX_BOOST = HalPinmap_t::UNUSED_PIN, 42 | PIN_SX1276_ANT_SWITCH_TX_RFO = HalPinmap_t::UNUSED_PIN, 43 | PIN_VDD_BOOST_ENABLE = HalPinmap_t::UNUSED_PIN, 44 | }; 45 | 46 | virtual void begin(void) override 47 | { 48 | digitalWrite(PIN_SX1276_NSS, 1); 49 | pinMode(PIN_SX1276_NSS, OUTPUT); 50 | } 51 | 52 | // virtual void end(void) override 53 | 54 | // virtual ostime_t setModuleActive(bool state) override 55 | }; 56 | 57 | static HalConfiguration_heltec_wireless_stick myConfig; 58 | 59 | static const HalPinmap_t myPinmap = { 60 | .nss = SS, 61 | .rxtx = HalPinmap_t::UNUSED_PIN, 62 | .rst = RST_LoRa, 63 | .dio = {DIO0, DIO1, DIO2}, 64 | }; 65 | 66 | const HalPinmap_t* GetPinmap_M5stack_Lora(void) { return &myPinmap; } 67 | 68 | }; // namespace TTN_esp32_LMIC 69 | -------------------------------------------------------------------------------- /src/lmic/hal/getpinmap_catena4420.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | Module: getconfig_catena4420.cpp 4 | 5 | Function: 6 | Arduino-LMIC C++ HAL pinmap for MCCI Catena 4420 7 | 8 | Copyright & License: 9 | See accompanying LICENSE file. 10 | 11 | Author: 12 | Terry Moore, MCCI November 2018 13 | 14 | */ 15 | 16 | #include "lmic/arduino_lmic_hal_boards.h" 17 | #include 18 | 19 | #include "../lmic/oslmic.h" 20 | 21 | namespace TTN_esp32_LMIC { 22 | 23 | class HalConfiguration_Catena4420_t : public HalConfiguration_t 24 | { 25 | public: 26 | enum DIGITAL_PINS : uint8_t 27 | { 28 | PIN_SX1276_NSS = 6, 29 | PIN_SX1276_NRESET = 5, 30 | PIN_SX1276_DIO0 = 12, // pin assignment for DIO0 (aka IRQ) 31 | PIN_SX1276_DIO1 = 11, 32 | PIN_SX1276_DIO2 = 10, 33 | PIN_SX1276_ANT_SWITCH_RX = HalPinmap_t::UNUSED_PIN, 34 | PIN_SX1276_ANT_SWITCH_TX_BOOST = HalPinmap_t::UNUSED_PIN, 35 | PIN_SX1276_ANT_SWITCH_TX_RFO = HalPinmap_t::UNUSED_PIN, 36 | PIN_VDD_BOOST_ENABLE = HalPinmap_t::UNUSED_PIN, 37 | }; 38 | 39 | virtual void begin(void) override 40 | { 41 | digitalWrite(PIN_SX1276_NSS, 1); 42 | pinMode(PIN_SX1276_NSS, OUTPUT); 43 | } 44 | 45 | // virtual void end(void) override 46 | 47 | // virtual ostime_t setModuleActive(bool state) override 48 | 49 | }; 50 | 51 | static HalConfiguration_Catena4420_t myConfig; 52 | 53 | static const HalPinmap_t myPinmap = 54 | { 55 | .nss = HalConfiguration_Catena4420_t::PIN_SX1276_NSS, // chip select is D7 56 | .rxtx = HalConfiguration_Catena4420_t::PIN_SX1276_ANT_SWITCH_RX, // RXTX is D29 57 | .rst = HalConfiguration_Catena4420_t::PIN_SX1276_NRESET, // NRESET is D8 58 | 59 | .dio = {HalConfiguration_Catena4420_t::PIN_SX1276_DIO0, // DIO0 (IRQ) is D25 60 | HalConfiguration_Catena4420_t::PIN_SX1276_DIO1, // DIO1 is D26 61 | HalConfiguration_Catena4420_t::PIN_SX1276_DIO2, // DIO2 is D27 62 | }, 63 | .rxtx_rx_active = 0, 64 | .rssi_cal = 10, 65 | .spi_freq = 8000000, /* 8MHz */ 66 | .pConfig = &myConfig 67 | }; 68 | 69 | const HalPinmap_t *GetPinmap_Catena4420(void) 70 | { 71 | return &myPinmap; 72 | } 73 | 74 | } // namespace TTN_esp32_LMIC; -------------------------------------------------------------------------------- /src/lmic/hal/getpinmap_catena4551.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | Module: getconfig_catena4551.cpp 4 | 5 | Function: 6 | Arduino-LMIC C++ HAL pinmaps for various boards 7 | 8 | Copyright & License: 9 | See accompanying LICENSE file. 10 | 11 | Author: 12 | Terry Moore, MCCI November 2018 13 | 14 | */ 15 | 16 | #if defined(ARDUINO_MCCI_CATENA_4551) || \ 17 | /* legacy names */ \ 18 | defined(ARDUINO_CATENA_4551) 19 | 20 | #include "lmic/arduino_lmic_hal_boards.h" 21 | #include 22 | 23 | #include "../lmic/oslmic.h" 24 | 25 | namespace TTN_esp32_LMIC { 26 | 27 | class HalConfiguration_Catena4551_t : public HalConfiguration_t 28 | { 29 | public: 30 | enum DIGITAL_PINS : uint8_t 31 | { 32 | PIN_SX1276_NSS = D7, 33 | PIN_SX1276_NRESET = D8, 34 | PIN_SX1276_DIO0 = D25, 35 | PIN_SX1276_DIO1 = D26, 36 | PIN_SX1276_DIO2 = D27, 37 | PIN_SX1276_ANT_SWITCH_RX = D29, 38 | PIN_SX1276_ANT_SWITCH_TX_BOOST = D30, 39 | PIN_SX1276_ANT_SWITCH_TX_RFO = D31, 40 | PIN_VDD_BOOST_ENABLE = A0, 41 | PIN_TCXO_VDD = D33, 42 | }; 43 | 44 | virtual void begin(void) override 45 | { 46 | digitalWrite(PIN_SX1276_NSS, 1); 47 | pinMode(PIN_SX1276_NSS, OUTPUT); 48 | } 49 | 50 | // virtual void end(void) override 51 | 52 | // On the 4551, we can't control the TCXO; it's always on. 53 | // So we use the default. 54 | // virtual ostime_t setModuleActive(bool state) override 55 | virtual bool queryUsingTcxo(void) override { return true; }; 56 | }; 57 | 58 | // save some typing by bringing the pin numbers into scope 59 | static HalConfiguration_Catena4551_t myConfig; 60 | 61 | static const HalPinmap_t myPinmap = 62 | { 63 | .nss = HalConfiguration_Catena4551_t::PIN_SX1276_NSS, // chip select is D7 64 | .rxtx = HalConfiguration_Catena4551_t::PIN_SX1276_ANT_SWITCH_RX, // RXTX is D29 65 | .rst = HalConfiguration_Catena4551_t::PIN_SX1276_NRESET, // NRESET is D8 66 | 67 | .dio = {HalConfiguration_Catena4551_t::PIN_SX1276_DIO0, // DIO0 (IRQ) is D25 68 | HalConfiguration_Catena4551_t::PIN_SX1276_DIO1, // DIO1 is D26 69 | HalConfiguration_Catena4551_t::PIN_SX1276_DIO2, // DIO2 is D27 70 | }, 71 | .rxtx_rx_active = 1, 72 | .rssi_cal = 10, 73 | .spi_freq = 8000000, /* 8MHz */ 74 | .pConfig = &myConfig, 75 | }; 76 | 77 | const HalPinmap_t *GetPinmap_Catena4551(void) 78 | { 79 | return &myPinmap; 80 | } 81 | 82 | }; // namespace TTN_esp32_LMIC 83 | 84 | #endif /* defined(ARDUINO_MCCI_CATENA_4551) */ 85 | -------------------------------------------------------------------------------- /src/lmic/hal/getpinmap_catena4610.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | Module: getconfig_catena4610.cpp 4 | 5 | Function: 6 | Arduino-LMIC C++ HAL pinmaps for the Catena 4610 7 | 8 | Copyright & License: 9 | See accompanying LICENSE file. 10 | 11 | Author: 12 | Terry Moore, MCCI November 2018 13 | 14 | */ 15 | 16 | #if defined(ARDUINO_MCCI_CATENA_4610) 17 | 18 | #include "lmic/arduino_lmic_hal_boards.h" 19 | #include 20 | 21 | #include "../lmic/oslmic.h" 22 | 23 | namespace TTN_esp32_LMIC { 24 | 25 | class HalConfiguration_Catena4610_t : public HalConfiguration_t 26 | { 27 | public: 28 | enum DIGITAL_PINS : uint8_t 29 | { 30 | PIN_SX1276_NSS = D7, 31 | PIN_SX1276_NRESET = D8, 32 | PIN_SX1276_DIO0 = D25, 33 | PIN_SX1276_DIO1 = D26, 34 | PIN_SX1276_DIO2 = D27, 35 | PIN_SX1276_ANT_SWITCH_RX = D29, 36 | PIN_SX1276_ANT_SWITCH_TX_BOOST = D30, 37 | PIN_SX1276_ANT_SWITCH_TX_RFO = D31, 38 | PIN_VDD_BOOST_ENABLE = A0, 39 | PIN_TCXO_VDD = D33, 40 | }; 41 | 42 | static constexpr ostime_t TCXO_DELAY_MS = 5; 43 | 44 | virtual void begin(void) override 45 | { 46 | digitalWrite(PIN_TCXO_VDD, 0); 47 | pinMode(PIN_TCXO_VDD, OUTPUT); 48 | } 49 | 50 | virtual void end(void) override 51 | { 52 | digitalWrite(PIN_TCXO_VDD, 0); 53 | pinMode(PIN_TCXO_VDD, INPUT); 54 | } 55 | 56 | virtual bool queryUsingTcxo(void) override { return true; }; 57 | 58 | virtual ostime_t setModuleActive(bool state) override 59 | { 60 | ostime_t result; 61 | const int oldState = digitalRead(PIN_TCXO_VDD); 62 | 63 | // if turning on, we need to delay. 64 | result = 0; 65 | if (state && ! oldState) 66 | result = ms2osticksCeil(TCXO_DELAY_MS); 67 | 68 | if (state != oldState) 69 | digitalWrite(PIN_TCXO_VDD, state); 70 | 71 | return result; 72 | } 73 | }; 74 | 75 | // save some typing by bringing the pin numbers into scope 76 | static HalConfiguration_Catena4610_t myConfig; 77 | 78 | static const HalPinmap_t myPinmap = 79 | { 80 | .nss = HalConfiguration_Catena4610_t::PIN_SX1276_NSS, // chip select is D7 81 | .rxtx = HalConfiguration_Catena4610_t::PIN_SX1276_ANT_SWITCH_RX, // RXTX is D29 82 | .rst = HalConfiguration_Catena4610_t::PIN_SX1276_NRESET, // NRESET is D8 83 | 84 | .dio = {HalConfiguration_Catena4610_t::PIN_SX1276_DIO0, // DIO0 (IRQ) is D25 85 | HalConfiguration_Catena4610_t::PIN_SX1276_DIO1, // DIO1 is D26 86 | HalConfiguration_Catena4610_t::PIN_SX1276_DIO2, // DIO2 is D27 87 | }, 88 | .rxtx_rx_active = 1, 89 | .rssi_cal = 10, 90 | .spi_freq = 8000000, /* 8MHz */ 91 | .pConfig = &myConfig 92 | }; 93 | 94 | const HalPinmap_t *GetPinmap_Catena4610(void) 95 | { 96 | return &myPinmap; 97 | } 98 | 99 | }; // namespace TTN_esp32_LMIC 100 | 101 | #endif /* defined(ARDUINO_MCCI_CATENA_4610 */ 102 | -------------------------------------------------------------------------------- /src/lmic/hal/getpinmap_catena4611.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | Module: getconfig_catena4611.cpp 4 | 5 | Function: 6 | Arduino-LMIC C++ HAL pinmaps for various boards 7 | 8 | Copyright & License: 9 | See accompanying LICENSE file. 10 | 11 | Author: 12 | Terry Moore, MCCI November 2018 13 | 14 | */ 15 | 16 | #if defined(ARDUINO_MCCI_CATENA_4611) 17 | 18 | #include "lmic/arduino_lmic_hal_boards.h" 19 | #include 20 | 21 | #include "../lmic/oslmic.h" 22 | 23 | namespace TTN_esp32_LMIC { 24 | 25 | class HalConfiguration_Catena4611_t : public HalConfiguration_t 26 | { 27 | public: 28 | enum DIGITAL_PINS : uint8_t 29 | { 30 | PIN_SX1276_NSS = D7, 31 | PIN_SX1276_NRESET = D8, 32 | PIN_SX1276_DIO0 = D25, 33 | PIN_SX1276_DIO1 = D26, 34 | PIN_SX1276_DIO2 = D27, 35 | PIN_SX1276_ANT_SWITCH_RX = D29, 36 | PIN_SX1276_ANT_SWITCH_TX_BOOST = D30, 37 | PIN_SX1276_ANT_SWITCH_TX_RFO = D31, 38 | PIN_VDD_BOOST_ENABLE = A0, 39 | PIN_TCXO_VDD = D33, 40 | }; 41 | 42 | static constexpr ostime_t TCXO_DELAY_MS = 5; 43 | 44 | virtual void begin(void) override 45 | { 46 | digitalWrite(PIN_TCXO_VDD, 0); 47 | pinMode(PIN_TCXO_VDD, OUTPUT); 48 | } 49 | 50 | virtual void end(void) override 51 | { 52 | digitalWrite(PIN_TCXO_VDD, 0); 53 | pinMode(PIN_TCXO_VDD, INPUT); 54 | } 55 | 56 | virtual bool queryUsingTcxo(void) override { return true; }; 57 | 58 | virtual ostime_t setModuleActive(bool state) override 59 | { 60 | ostime_t result; 61 | const int oldState = digitalRead(PIN_TCXO_VDD); 62 | 63 | // if turning on, we need to delay. 64 | result = 0; 65 | if (state && ! oldState) 66 | result = ms2osticksCeil(TCXO_DELAY_MS); 67 | 68 | if (state != oldState) 69 | digitalWrite(PIN_TCXO_VDD, state); 70 | 71 | return result; 72 | } 73 | }; 74 | 75 | // save some typing by bringing the pin numbers into scope 76 | static HalConfiguration_Catena4611_t myConfig; 77 | 78 | static const HalPinmap_t myPinmap = 79 | { 80 | .nss = HalConfiguration_Catena4611_t::PIN_SX1276_NSS, // chip select is D7 81 | .rxtx = HalConfiguration_Catena4611_t::PIN_SX1276_ANT_SWITCH_RX, // RXTX is D29 82 | .rst = HalConfiguration_Catena4611_t::PIN_SX1276_NRESET, // NRESET is D8 83 | 84 | .dio = {HalConfiguration_Catena4611_t::PIN_SX1276_DIO0, // DIO0 (IRQ) is D25 85 | HalConfiguration_Catena4611_t::PIN_SX1276_DIO1, // DIO1 is D26 86 | HalConfiguration_Catena4611_t::PIN_SX1276_DIO2, // DIO2 is D27 87 | }, 88 | .rxtx_rx_active = 1, 89 | .rssi_cal = 10, 90 | .spi_freq = 8000000, /* 8MHz */ 91 | .pConfig = &myConfig 92 | }; 93 | 94 | const HalPinmap_t *GetPinmap_Catena4611(void) 95 | { 96 | return &myPinmap; 97 | } 98 | 99 | }; // namespace TTN_esp32_LMIC 100 | 101 | #endif /* defined(ARDUINO_MCCI_CATENA_4611) */ 102 | -------------------------------------------------------------------------------- /src/lmic/hal/getpinmap_catena4612.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | Module: getconfig_catena4612.cpp 4 | 5 | Function: 6 | Arduino-LMIC C++ HAL pinmaps for various boards 7 | 8 | Copyright & License: 9 | See accompanying LICENSE file. 10 | 11 | Author: 12 | Terry Moore, MCCI November 2018 13 | 14 | */ 15 | 16 | #if defined(ARDUINO_MCCI_CATENA_4612) || \ 17 | /* legacy name */ \ 18 | defined(ARDUINO_CATENA_4612) 19 | 20 | #include "lmic/arduino_lmic_hal_boards.h" 21 | #include 22 | 23 | #include "../lmic/oslmic.h" 24 | 25 | namespace TTN_esp32_LMIC { 26 | 27 | class HalConfiguration_Catena4612_t : public HalConfiguration_t 28 | { 29 | public: 30 | enum DIGITAL_PINS : uint8_t 31 | { 32 | PIN_SX1276_NSS = D7, 33 | PIN_SX1276_NRESET = D8, 34 | PIN_SX1276_DIO0 = D25, 35 | PIN_SX1276_DIO1 = D26, 36 | PIN_SX1276_DIO2 = D27, 37 | PIN_SX1276_ANT_SWITCH_RX = D29, 38 | PIN_SX1276_ANT_SWITCH_TX_BOOST = D30, 39 | PIN_SX1276_ANT_SWITCH_TX_RFO = D31, 40 | PIN_VDD_BOOST_ENABLE = A0, 41 | PIN_TCXO_VDD = D33, 42 | }; 43 | 44 | static constexpr ostime_t TCXO_DELAY_MS = 5; 45 | 46 | virtual void begin(void) override 47 | { 48 | digitalWrite(PIN_TCXO_VDD, 0); 49 | pinMode(PIN_TCXO_VDD, OUTPUT); 50 | } 51 | 52 | virtual void end(void) override 53 | { 54 | digitalWrite(PIN_TCXO_VDD, 0); 55 | pinMode(PIN_TCXO_VDD, INPUT); 56 | } 57 | 58 | virtual bool queryUsingTcxo(void) override { return true; }; 59 | 60 | virtual ostime_t setModuleActive(bool state) override 61 | { 62 | ostime_t result; 63 | const int oldState = digitalRead(PIN_TCXO_VDD); 64 | 65 | // if turning on, we need to delay. 66 | result = 0; 67 | if (state && ! oldState) 68 | result = ms2osticksCeil(TCXO_DELAY_MS); 69 | 70 | if (state != oldState) 71 | digitalWrite(PIN_TCXO_VDD, state); 72 | 73 | return result; 74 | } 75 | }; 76 | 77 | // save some typing by bringing the pin numbers into scope 78 | static HalConfiguration_Catena4612_t myConfig; 79 | 80 | static const HalPinmap_t myPinmap = 81 | { 82 | .nss = HalConfiguration_Catena4612_t::PIN_SX1276_NSS, // chip select is D7 83 | .rxtx = HalConfiguration_Catena4612_t::PIN_SX1276_ANT_SWITCH_RX, // RXTX is D29 84 | .rst = HalConfiguration_Catena4612_t::PIN_SX1276_NRESET, // NRESET is D8 85 | 86 | .dio = {HalConfiguration_Catena4612_t::PIN_SX1276_DIO0, // DIO0 (IRQ) is D25 87 | HalConfiguration_Catena4612_t::PIN_SX1276_DIO1, // DIO1 is D26 88 | HalConfiguration_Catena4612_t::PIN_SX1276_DIO2, // DIO2 is D27 89 | }, 90 | .rxtx_rx_active = 1, 91 | .rssi_cal = 10, 92 | .spi_freq = 8000000, /* 8MHz */ 93 | .pConfig = &myConfig 94 | }; 95 | 96 | const HalPinmap_t *GetPinmap_Catena4612(void) 97 | { 98 | return &myPinmap; 99 | } 100 | 101 | }; // namespace TTN_esp32_LMIC 102 | 103 | #endif /* defined(ARDUINO_MCCI_CATENA_4612) || defined(ARDUINO_CATENA_4612) */ 104 | -------------------------------------------------------------------------------- /src/lmic/hal/getpinmap_catena4617.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | Module: getconfig_catena4617.cpp 4 | 5 | Function: 6 | Arduino-LMIC C++ HAL pinmaps for various boards 7 | 8 | Copyright & License: 9 | See accompanying LICENSE file. 10 | 11 | Author: 12 | Lakshmi Priya Natarajan, MCCI June 2019 13 | 14 | */ 15 | 16 | #if defined(ARDUINO_MCCI_CATENA_4617) 17 | 18 | #include "lmic/arduino_lmic_hal_boards.h" 19 | #include 20 | 21 | #include "../lmic/oslmic.h" 22 | 23 | namespace TTN_esp32_LMIC { 24 | 25 | class HalConfiguration_Catena4617_t : public HalConfiguration_t 26 | { 27 | public: 28 | enum DIGITAL_PINS : uint8_t 29 | { 30 | PIN_SX1276_NSS = D7, 31 | PIN_SX1276_NRESET = D8, 32 | PIN_SX1276_DIO0 = D25, 33 | PIN_SX1276_DIO1 = D26, 34 | PIN_SX1276_DIO2 = D27, 35 | PIN_SX1276_ANT_SWITCH_RX = D29, 36 | PIN_SX1276_ANT_SWITCH_TX_BOOST = D30, 37 | PIN_SX1276_ANT_SWITCH_TX_RFO = D31, 38 | PIN_VDD_BOOST_ENABLE = A0, 39 | PIN_TCXO_VDD = D33, 40 | }; 41 | 42 | static constexpr ostime_t TCXO_DELAY_MS = 5; 43 | 44 | virtual void begin(void) override 45 | { 46 | digitalWrite(PIN_TCXO_VDD, 0); 47 | pinMode(PIN_TCXO_VDD, OUTPUT); 48 | } 49 | 50 | virtual void end(void) override 51 | { 52 | digitalWrite(PIN_TCXO_VDD, 0); 53 | pinMode(PIN_TCXO_VDD, INPUT); 54 | } 55 | 56 | virtual bool queryUsingTcxo(void) override { return true; }; 57 | 58 | virtual ostime_t setModuleActive(bool state) override 59 | { 60 | ostime_t result; 61 | const int oldState = digitalRead(PIN_TCXO_VDD); 62 | 63 | // if turning on, we need to delay. 64 | result = 0; 65 | if (state && ! oldState) 66 | result = ms2osticksCeil(TCXO_DELAY_MS); 67 | 68 | if (state != oldState) 69 | digitalWrite(PIN_TCXO_VDD, state); 70 | 71 | return result; 72 | } 73 | }; 74 | 75 | // save some typing by bringing the pin numbers into scope 76 | static HalConfiguration_Catena4617_t myConfig; 77 | 78 | static const HalPinmap_t myPinmap = 79 | { 80 | .nss = HalConfiguration_Catena4617_t::PIN_SX1276_NSS, // chip select is D7 81 | .rxtx = HalConfiguration_Catena4617_t::PIN_SX1276_ANT_SWITCH_RX, // RXTX is D29 82 | .rst = HalConfiguration_Catena4617_t::PIN_SX1276_NRESET, // NRESET is D8 83 | 84 | .dio = {HalConfiguration_Catena4617_t::PIN_SX1276_DIO0, // DIO0 (IRQ) is D25 85 | HalConfiguration_Catena4617_t::PIN_SX1276_DIO1, // DIO1 is D26 86 | HalConfiguration_Catena4617_t::PIN_SX1276_DIO2, // DIO2 is D27 87 | }, 88 | .rxtx_rx_active = 1, 89 | .rssi_cal = 10, 90 | .spi_freq = 8000000, /* 8MHz */ 91 | .pConfig = &myConfig 92 | }; 93 | 94 | const HalPinmap_t *GetPinmap_Catena4617(void) 95 | { 96 | return &myPinmap; 97 | } 98 | 99 | }; // namespace TTN_esp32_LMIC 100 | 101 | #endif /* defined(ARDUINO_MCCI_CATENA_4617) || defined(ARDUINO_CATENA_4617) */ 102 | -------------------------------------------------------------------------------- /src/lmic/hal/getpinmap_catena4618.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | Module: getconfig_catena4618.cpp 4 | 5 | Function: 6 | Arduino-LMIC C++ HAL pinmaps for various boards 7 | 8 | Copyright & License: 9 | See accompanying LICENSE file. 10 | 11 | Author: 12 | Lakshmi Priya Natarajan, MCCI June 2019 13 | 14 | */ 15 | 16 | #if defined(ARDUINO_MCCI_CATENA_4618) 17 | 18 | #include "lmic/arduino_lmic_hal_boards.h" 19 | #include 20 | 21 | #include "../lmic/oslmic.h" 22 | 23 | namespace TTN_esp32_LMIC { 24 | 25 | class HalConfiguration_Catena4618_t : public HalConfiguration_t 26 | { 27 | public: 28 | enum DIGITAL_PINS : uint8_t 29 | { 30 | PIN_SX1276_NSS = D7, 31 | PIN_SX1276_NRESET = D8, 32 | PIN_SX1276_DIO0 = D25, 33 | PIN_SX1276_DIO1 = D26, 34 | PIN_SX1276_DIO2 = D27, 35 | PIN_SX1276_ANT_SWITCH_RX = D29, 36 | PIN_SX1276_ANT_SWITCH_TX_BOOST = D30, 37 | PIN_SX1276_ANT_SWITCH_TX_RFO = D31, 38 | PIN_VDD_BOOST_ENABLE = A0, 39 | PIN_TCXO_VDD = D33, 40 | }; 41 | 42 | static constexpr ostime_t TCXO_DELAY_MS = 5; 43 | 44 | virtual void begin(void) override 45 | { 46 | digitalWrite(PIN_TCXO_VDD, 0); 47 | pinMode(PIN_TCXO_VDD, OUTPUT); 48 | } 49 | 50 | virtual void end(void) override 51 | { 52 | digitalWrite(PIN_TCXO_VDD, 0); 53 | pinMode(PIN_TCXO_VDD, INPUT); 54 | } 55 | 56 | virtual bool queryUsingTcxo(void) override { return true; }; 57 | 58 | virtual ostime_t setModuleActive(bool state) override 59 | { 60 | ostime_t result; 61 | const int oldState = digitalRead(PIN_TCXO_VDD); 62 | 63 | // if turning on, we need to delay. 64 | result = 0; 65 | if (state && ! oldState) 66 | result = ms2osticksCeil(TCXO_DELAY_MS); 67 | 68 | if (state != oldState) 69 | digitalWrite(PIN_TCXO_VDD, state); 70 | 71 | return result; 72 | } 73 | }; 74 | 75 | // save some typing by bringing the pin numbers into scope 76 | static HalConfiguration_Catena4618_t myConfig; 77 | 78 | static const HalPinmap_t myPinmap = 79 | { 80 | .nss = HalConfiguration_Catena4618_t::PIN_SX1276_NSS, // chip select is D7 81 | .rxtx = HalConfiguration_Catena4618_t::PIN_SX1276_ANT_SWITCH_RX, // RXTX is D29 82 | .rst = HalConfiguration_Catena4618_t::PIN_SX1276_NRESET, // NRESET is D8 83 | 84 | .dio = {HalConfiguration_Catena4618_t::PIN_SX1276_DIO0, // DIO0 (IRQ) is D25 85 | HalConfiguration_Catena4618_t::PIN_SX1276_DIO1, // DIO1 is D26 86 | HalConfiguration_Catena4618_t::PIN_SX1276_DIO2, // DIO2 is D27 87 | }, 88 | .rxtx_rx_active = 1, 89 | .rssi_cal = 10, 90 | .spi_freq = 8000000, /* 8MHz */ 91 | .pConfig = &myConfig 92 | }; 93 | 94 | const HalPinmap_t *GetPinmap_Catena4618(void) 95 | { 96 | return &myPinmap; 97 | } 98 | 99 | }; // namespace TTN_esp32_LMIC 100 | 101 | #endif /* defined(ARDUINO_MCCI_CATENA_4618) || defined(ARDUINO_CATENA_4618) */ 102 | -------------------------------------------------------------------------------- /src/lmic/hal/getpinmap_catena4630.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | Module: getconfig_catena4630.cpp 4 | 5 | Function: 6 | Arduino-LMIC C++ HAL pinmaps for various boards 7 | 8 | Copyright & License: 9 | See accompanying LICENSE file. 10 | 11 | Author: 12 | Dhinesh Kumar Pitchai, MCCI June 2019 13 | 14 | */ 15 | 16 | #if defined(ARDUINO_MCCI_CATENA_4630) 17 | 18 | #include "lmic/arduino_lmic_hal_boards.h" 19 | #include 20 | 21 | #include "../lmic/oslmic.h" 22 | 23 | namespace TTN_esp32_LMIC { 24 | 25 | class HalConfiguration_Catena4630_t : public HalConfiguration_t 26 | { 27 | public: 28 | enum DIGITAL_PINS : uint8_t 29 | { 30 | PIN_SX1276_NSS = D7, 31 | PIN_SX1276_NRESET = D8, 32 | PIN_SX1276_DIO0 = D25, 33 | PIN_SX1276_DIO1 = D26, 34 | PIN_SX1276_DIO2 = D27, 35 | PIN_SX1276_ANT_SWITCH_RX = D29, 36 | PIN_SX1276_ANT_SWITCH_TX_BOOST = D30, 37 | PIN_SX1276_ANT_SWITCH_TX_RFO = D31, 38 | PIN_VDD_BOOST_ENABLE = A0, 39 | PIN_TCXO_VDD = D33, 40 | }; 41 | 42 | static constexpr ostime_t TCXO_DELAY_MS = 5; 43 | 44 | virtual void begin(void) override 45 | { 46 | digitalWrite(PIN_TCXO_VDD, 0); 47 | pinMode(PIN_TCXO_VDD, OUTPUT); 48 | } 49 | 50 | virtual void end(void) override 51 | { 52 | digitalWrite(PIN_TCXO_VDD, 0); 53 | pinMode(PIN_TCXO_VDD, INPUT); 54 | } 55 | 56 | virtual bool queryUsingTcxo(void) override { return true; }; 57 | 58 | virtual ostime_t setModuleActive(bool state) override 59 | { 60 | ostime_t result; 61 | const int oldState = digitalRead(PIN_TCXO_VDD); 62 | 63 | // if turning on, we need to delay. 64 | result = 0; 65 | if (state && ! oldState) 66 | result = ms2osticksCeil(TCXO_DELAY_MS); 67 | 68 | if (state != oldState) 69 | digitalWrite(PIN_TCXO_VDD, state); 70 | 71 | return result; 72 | } 73 | }; 74 | 75 | // save some typing by bringing the pin numbers into scope 76 | static HalConfiguration_Catena4630_t myConfig; 77 | 78 | static const HalPinmap_t myPinmap = 79 | { 80 | .nss = HalConfiguration_Catena4630_t::PIN_SX1276_NSS, // chip select is D7 81 | .rxtx = HalConfiguration_Catena4630_t::PIN_SX1276_ANT_SWITCH_RX, // RXTX is D29 82 | .rst = HalConfiguration_Catena4630_t::PIN_SX1276_NRESET, // NRESET is D8 83 | 84 | .dio = {HalConfiguration_Catena4630_t::PIN_SX1276_DIO0, // DIO0 (IRQ) is D25 85 | HalConfiguration_Catena4630_t::PIN_SX1276_DIO1, // DIO1 is D26 86 | HalConfiguration_Catena4630_t::PIN_SX1276_DIO2, // DIO2 is D27 87 | }, 88 | .rxtx_rx_active = 1, 89 | .rssi_cal = 10, 90 | .spi_freq = 8000000, /* 8MHz */ 91 | .pConfig = &myConfig 92 | }; 93 | 94 | const HalPinmap_t *GetPinmap_Catena4630(void) 95 | { 96 | return &myPinmap; 97 | } 98 | 99 | }; // namespace TTN_esp32_LMIC 100 | 101 | #endif /* defined(ARDUINO_MCCI_CATENA_4630) || defined(ARDUINO_CATENA_4630) */ 102 | -------------------------------------------------------------------------------- /src/lmic/hal/getpinmap_catena4801.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | Module: getconfig_catena4801.cpp 4 | 5 | Function: 6 | Arduino-LMIC C++ HAL pinmaps for various boards 7 | 8 | Copyright & License: 9 | See accompanying LICENSE file. 10 | 11 | Author: 12 | Terry Moore, MCCI November 2018 13 | 14 | */ 15 | 16 | #if defined(ARDUINO_MCCI_CATENA_4801) || \ 17 | /* legacy names */ \ 18 | defined(ARDUINO_CATENA_4801) 19 | 20 | #include "lmic/arduino_lmic_hal_boards.h" 21 | #include 22 | 23 | #include "../lmic/oslmic.h" 24 | 25 | namespace TTN_esp32_LMIC { 26 | 27 | class HalConfiguration_Catena4801_t : public HalConfiguration_t 28 | { 29 | public: 30 | enum DIGITAL_PINS : uint8_t 31 | { 32 | PIN_SX1276_NSS = D7, 33 | PIN_SX1276_NRESET = D8, 34 | PIN_SX1276_DIO0 = D25, 35 | PIN_SX1276_DIO1 = D26, 36 | PIN_SX1276_DIO2 = D27, 37 | PIN_SX1276_ANT_SWITCH_RX = D29, 38 | PIN_SX1276_ANT_SWITCH_TX_BOOST = D30, 39 | PIN_SX1276_ANT_SWITCH_TX_RFO = D31, 40 | PIN_VDD_BOOST_ENABLE = A0, 41 | PIN_TCXO_VDD = D33, 42 | }; 43 | 44 | virtual void begin(void) override 45 | { 46 | digitalWrite(PIN_TCXO_VDD, 0); 47 | pinMode(PIN_TCXO_VDD, OUTPUT); 48 | } 49 | 50 | virtual void end(void) override 51 | { 52 | digitalWrite(PIN_TCXO_VDD, 0); 53 | pinMode(PIN_TCXO_VDD, INPUT); 54 | } 55 | 56 | virtual bool queryUsingTcxo(void) override { return true; }; 57 | 58 | virtual ostime_t setModuleActive(bool state) override 59 | { 60 | ostime_t result; 61 | const int oldState = digitalRead(PIN_TCXO_VDD); 62 | 63 | // if turning on, we need to delay. 64 | result = 0; 65 | if (state && ! oldState) 66 | result = ms2osticksCeil(3); 67 | 68 | if (state != oldState) 69 | digitalWrite(PIN_TCXO_VDD, state); 70 | 71 | return result; 72 | } 73 | }; 74 | 75 | // save some typing by bringing the pin numbers into scope 76 | static HalConfiguration_Catena4801_t myConfig; 77 | 78 | static const HalPinmap_t myPinmap = 79 | { 80 | .nss = HalConfiguration_Catena4801_t::PIN_SX1276_NSS, // chip select is D7 81 | .rxtx = HalConfiguration_Catena4801_t::PIN_SX1276_ANT_SWITCH_RX, // RXTX is D29 82 | .rst = HalConfiguration_Catena4801_t::PIN_SX1276_NRESET, // NRESET is D8 83 | 84 | .dio = {HalConfiguration_Catena4801_t::PIN_SX1276_DIO0, // DIO0 (IRQ) is D25 85 | HalConfiguration_Catena4801_t::PIN_SX1276_DIO1, // DIO1 is D26 86 | HalConfiguration_Catena4801_t::PIN_SX1276_DIO2, // DIO2 is D27 87 | }, 88 | .rxtx_rx_active = 1, 89 | .rssi_cal = 10, 90 | .spi_freq = 8000000, /* 8MHz */ 91 | .pConfig = &myConfig 92 | }; 93 | 94 | const HalPinmap_t *GetPinmap_Catena4801(void) 95 | { 96 | return &myPinmap; 97 | } 98 | 99 | }; // namespace TTN_esp32_LMIC 100 | 101 | #endif /* defined(ARDUINO_CATENA_4611) || defined(ARDUINO_CATENA_4801) */ 102 | -------------------------------------------------------------------------------- /src/lmic/hal/getpinmap_feather32u4lora.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | Module: getconfig_feather32u4lora.cpp 4 | 5 | Function: 6 | Arduino-LMIC C++ HAL pinmap for Adafruit Feather 32U4 LoRa 7 | 8 | Copyright & License: 9 | See accompanying LICENSE file. 10 | 11 | Author: 12 | Terry Moore, MCCI November 2018 13 | 14 | */ 15 | 16 | #include "lmic/arduino_lmic_hal_boards.h" 17 | #include 18 | 19 | #include "../lmic/oslmic.h" 20 | 21 | namespace TTN_esp32_LMIC { 22 | 23 | class HalConfiguration_Feather32U4LoRa_t : public HalConfiguration_t 24 | { 25 | public: 26 | enum DIGITAL_PINS : uint8_t 27 | { 28 | PIN_SX1276_NSS = 8, 29 | PIN_SX1276_NRESET = 4, 30 | PIN_SX1276_DIO0 = 7, 31 | PIN_SX1276_DIO1 = 6, 32 | PIN_SX1276_DIO2 = HalPinmap_t::UNUSED_PIN, 33 | PIN_SX1276_ANT_SWITCH_RX = HalPinmap_t::UNUSED_PIN, 34 | PIN_SX1276_ANT_SWITCH_TX_BOOST = HalPinmap_t::UNUSED_PIN, 35 | PIN_SX1276_ANT_SWITCH_TX_RFO = HalPinmap_t::UNUSED_PIN, 36 | PIN_VDD_BOOST_ENABLE = HalPinmap_t::UNUSED_PIN, 37 | }; 38 | 39 | virtual void begin(void) override 40 | { 41 | digitalWrite(PIN_SX1276_NSS, 1); 42 | pinMode(PIN_SX1276_NSS, OUTPUT); 43 | } 44 | 45 | // virtual void end(void) override 46 | 47 | // virtual ostime_t setModuleActive(bool state) override 48 | 49 | }; 50 | 51 | static HalConfiguration_Feather32U4LoRa_t myConfig; 52 | 53 | // Pin mapping for Adafruit Feather 32u4 LoRa, etc. 54 | // Just like Feather M0 LoRa, but uses SPI at 1MHz; and that's only 55 | // because MCCI doesn't have a test board; probably higher frequencies 56 | // will work. 57 | 58 | static const HalPinmap_t myPinmap = 59 | { 60 | .nss = HalConfiguration_Feather32U4LoRa_t::PIN_SX1276_NSS, // chip select is D7 61 | .rxtx = HalConfiguration_Feather32U4LoRa_t::PIN_SX1276_ANT_SWITCH_RX, // RXTX is D29 62 | .rst = HalConfiguration_Feather32U4LoRa_t::PIN_SX1276_NRESET, // NRESET is D8 63 | 64 | .dio = {HalConfiguration_Feather32U4LoRa_t::PIN_SX1276_DIO0, // DIO0 (IRQ) is D25 65 | HalConfiguration_Feather32U4LoRa_t::PIN_SX1276_DIO1, // DIO1 is D26 66 | HalConfiguration_Feather32U4LoRa_t::PIN_SX1276_DIO2, // DIO2 is D27 67 | }, 68 | .rxtx_rx_active = 0, 69 | .rssi_cal = 8, 70 | .spi_freq = 1000000, /* 1MHz */ 71 | .pConfig = &myConfig, 72 | }; 73 | 74 | const HalPinmap_t *GetPinmap_Feather32U4LoRa(void) 75 | { 76 | 77 | 78 | return &myPinmap; 79 | } 80 | 81 | }; // namespace TTN_esp32_LMIC 82 | -------------------------------------------------------------------------------- /src/lmic/hal/getpinmap_featherm0lora.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | Module: getconfig_featherm0lora.cpp 4 | 5 | Function: 6 | Arduino-LMIC C++ HAL pinmap for Adafruit Feather M0 LoRa 7 | 8 | Copyright & License: 9 | See accompanying LICENSE file. 10 | 11 | Author: 12 | Terry Moore, MCCI November 2018 13 | 14 | */ 15 | 16 | #include "lmic/arduino_lmic_hal_boards.h" 17 | #include 18 | 19 | #include "../lmic/oslmic.h" 20 | 21 | namespace TTN_esp32_LMIC { 22 | 23 | class HalConfiguration_FeatherM0LoRa_t : public HalConfiguration_t 24 | { 25 | public: 26 | enum DIGITAL_PINS : uint8_t 27 | { 28 | PIN_SX1276_NSS = 8, 29 | PIN_SX1276_NRESET = 4, 30 | PIN_SX1276_DIO0 = 3, 31 | PIN_SX1276_DIO1 = 6, 32 | PIN_SX1276_DIO2 = HalPinmap_t::UNUSED_PIN, 33 | PIN_SX1276_ANT_SWITCH_RX = HalPinmap_t::UNUSED_PIN, 34 | PIN_SX1276_ANT_SWITCH_TX_BOOST = HalPinmap_t::UNUSED_PIN, 35 | PIN_SX1276_ANT_SWITCH_TX_RFO = HalPinmap_t::UNUSED_PIN, 36 | PIN_VDD_BOOST_ENABLE = HalPinmap_t::UNUSED_PIN, 37 | }; 38 | 39 | virtual void begin(void) override 40 | { 41 | digitalWrite(PIN_SX1276_NSS, 1); 42 | pinMode(PIN_SX1276_NSS, OUTPUT); 43 | } 44 | 45 | // virtual void end(void) override 46 | 47 | // virtual ostime_t setModuleActive(bool state) override 48 | 49 | }; 50 | 51 | static HalConfiguration_FeatherM0LoRa_t myConfig; 52 | 53 | static const HalPinmap_t myPinmap = 54 | { 55 | .nss = HalConfiguration_FeatherM0LoRa_t::PIN_SX1276_NSS, // chip select is D7 56 | .rxtx = HalConfiguration_FeatherM0LoRa_t::PIN_SX1276_ANT_SWITCH_RX, // RXTX is D29 57 | .rst = HalConfiguration_FeatherM0LoRa_t::PIN_SX1276_NRESET, // NRESET is D8 58 | 59 | .dio = {HalConfiguration_FeatherM0LoRa_t::PIN_SX1276_DIO0, // DIO0 (IRQ) is D25 60 | HalConfiguration_FeatherM0LoRa_t::PIN_SX1276_DIO1, // DIO1 is D26 61 | HalConfiguration_FeatherM0LoRa_t::PIN_SX1276_DIO2, // DIO2 is D27 62 | }, 63 | .rxtx_rx_active = 0, 64 | .rssi_cal = 10, 65 | .spi_freq = 8000000, /* 8MHz */ 66 | .pConfig = &myConfig 67 | }; 68 | 69 | const HalPinmap_t *GetPinmap_FeatherM0LoRa(void) 70 | { 71 | return &myPinmap; 72 | } 73 | 74 | }; // namespace TTN_esp32_LMIC 75 | -------------------------------------------------------------------------------- /src/lmic/hal/getpinmap_heltec_Wifi_Lora_32.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | Module: getconfig_ttgo_lora32_v1.cpp 4 | 5 | Function: 6 | Arduino-LMIC C++ HAL pinmap for TTGO ESP32 OLED V1 7 | 8 | Copyright & License: 9 | See accompanying LICENSE file. 10 | 11 | Author: 12 | German Martin, gmag11@gmail.com June 2019 13 | 14 | */ 15 | 16 | #include 17 | 18 | #include "../lmic/oslmic.h" 19 | #include "lmic/arduino_lmic_hal_boards.h" 20 | 21 | #define SS 18 22 | #define RST_LoRa 14 23 | #define DIO0 26 24 | #define DIO1 33 25 | #define DIO2 32 26 | 27 | namespace TTN_esp32_LMIC 28 | { 29 | 30 | class HalConfiguration_heltec_wifi_lora_32 : public HalConfiguration_t 31 | { 32 | public: 33 | enum DIGITAL_PINS : uint8_t 34 | { 35 | PIN_SX1276_NSS = SS, 36 | PIN_SX1276_NRESET = RST_LoRa, 37 | PIN_SX1276_DIO0 = DIO0, 38 | PIN_SX1276_DIO1 = DIO1, 39 | PIN_SX1276_DIO2 = DIO2, 40 | PIN_SX1276_ANT_SWITCH_RX = HalPinmap_t::UNUSED_PIN, 41 | PIN_SX1276_ANT_SWITCH_TX_BOOST = HalPinmap_t::UNUSED_PIN, 42 | PIN_SX1276_ANT_SWITCH_TX_RFO = HalPinmap_t::UNUSED_PIN, 43 | PIN_VDD_BOOST_ENABLE = HalPinmap_t::UNUSED_PIN, 44 | }; 45 | 46 | virtual void begin(void) override 47 | { 48 | digitalWrite(PIN_SX1276_NSS, 1); 49 | pinMode(PIN_SX1276_NSS, OUTPUT); 50 | } 51 | 52 | // virtual void end(void) override 53 | 54 | // virtual ostime_t setModuleActive(bool state) override 55 | }; 56 | 57 | static HalConfiguration_heltec_wifi_lora_32 myConfig; 58 | 59 | static const HalPinmap_t myPinmap = { 60 | .nss = SS, 61 | .rxtx = HalPinmap_t::UNUSED_PIN, 62 | .rst = RST_LoRa, 63 | .dio = {DIO0, DIO1, DIO2}, 64 | }; 65 | 66 | const HalPinmap_t* GetPinmap_heltec_wifi_lora_32(void) { return &myPinmap; } 67 | 68 | }; // namespace TTN_esp32_LMIC 69 | -------------------------------------------------------------------------------- /src/lmic/hal/getpinmap_heltec_Wifi_Lora_32_V2.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | Module: getconfig_ttgo_lora32_v1.cpp 4 | 5 | Function: 6 | Arduino-LMIC C++ HAL pinmap for TTGO ESP32 OLED V1 7 | 8 | Copyright & License: 9 | See accompanying LICENSE file. 10 | 11 | Author: 12 | German Martin, gmag11@gmail.com June 2019 13 | 14 | */ 15 | 16 | #include 17 | 18 | #include "../lmic/oslmic.h" 19 | #include "lmic/arduino_lmic_hal_boards.h" 20 | 21 | #define SS 18 22 | #define RST_LoRa 14 23 | #define DIO0 26 24 | #define DIO1 35 25 | #define DIO2 34 26 | 27 | namespace TTN_esp32_LMIC 28 | { 29 | 30 | class HalConfiguration_heltec_wifi_lora_32_V2 : public HalConfiguration_t 31 | { 32 | public: 33 | enum DIGITAL_PINS : uint8_t 34 | { 35 | PIN_SX1276_NSS = SS, 36 | PIN_SX1276_NRESET = RST_LoRa, 37 | PIN_SX1276_DIO0 = DIO0, 38 | PIN_SX1276_DIO1 = DIO1, 39 | PIN_SX1276_DIO2 = DIO2, 40 | PIN_SX1276_ANT_SWITCH_RX = HalPinmap_t::UNUSED_PIN, 41 | PIN_SX1276_ANT_SWITCH_TX_BOOST = HalPinmap_t::UNUSED_PIN, 42 | PIN_SX1276_ANT_SWITCH_TX_RFO = HalPinmap_t::UNUSED_PIN, 43 | PIN_VDD_BOOST_ENABLE = HalPinmap_t::UNUSED_PIN, 44 | }; 45 | 46 | virtual void begin(void) override 47 | { 48 | digitalWrite(PIN_SX1276_NSS, 1); 49 | pinMode(PIN_SX1276_NSS, OUTPUT); 50 | } 51 | 52 | // virtual void end(void) override 53 | 54 | // virtual ostime_t setModuleActive(bool state) override 55 | }; 56 | 57 | static HalConfiguration_heltec_wifi_lora_32_V2 myConfig; 58 | 59 | static const HalPinmap_t myPinmap = { 60 | .nss = SS, 61 | .rxtx = HalPinmap_t::UNUSED_PIN, 62 | .rst = RST_LoRa, 63 | .dio = {DIO0, DIO1, DIO2}, 64 | }; 65 | 66 | const HalPinmap_t* GetPinmap_heltec_wifi_lora_32_V2(void) { return &myPinmap; } 67 | 68 | }; // namespace TTN_esp32_LMIC 69 | -------------------------------------------------------------------------------- /src/lmic/hal/getpinmap_heltec_wirless_stick.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | Module: getconfig_ttgo_lora32_v1.cpp 4 | 5 | Function: 6 | Arduino-LMIC C++ HAL pinmap for TTGO ESP32 OLED V1 7 | 8 | Copyright & License: 9 | See accompanying LICENSE file. 10 | 11 | Author: 12 | German Martin, gmag11@gmail.com June 2019 13 | 14 | */ 15 | 16 | #include 17 | 18 | #include "../lmic/oslmic.h" 19 | #include "lmic/arduino_lmic_hal_boards.h" 20 | 21 | #define SS 18 22 | #define RST_LoRa 14 23 | #define DIO0 26 24 | #define DIO1 35 25 | #define DIO2 34 26 | 27 | namespace TTN_esp32_LMIC 28 | { 29 | 30 | class HalConfiguration_heltec_wireless_stick : public HalConfiguration_t 31 | { 32 | public: 33 | enum DIGITAL_PINS : uint8_t 34 | { 35 | PIN_SX1276_NSS = SS, 36 | PIN_SX1276_NRESET = RST_LoRa, 37 | PIN_SX1276_DIO0 = DIO0, 38 | PIN_SX1276_DIO1 = DIO1, 39 | PIN_SX1276_DIO2 = DIO2, 40 | PIN_SX1276_ANT_SWITCH_RX = HalPinmap_t::UNUSED_PIN, 41 | PIN_SX1276_ANT_SWITCH_TX_BOOST = HalPinmap_t::UNUSED_PIN, 42 | PIN_SX1276_ANT_SWITCH_TX_RFO = HalPinmap_t::UNUSED_PIN, 43 | PIN_VDD_BOOST_ENABLE = HalPinmap_t::UNUSED_PIN, 44 | }; 45 | 46 | virtual void begin(void) override 47 | { 48 | digitalWrite(PIN_SX1276_NSS, 1); 49 | pinMode(PIN_SX1276_NSS, OUTPUT); 50 | } 51 | 52 | // virtual void end(void) override 53 | 54 | // virtual ostime_t setModuleActive(bool state) override 55 | }; 56 | 57 | static HalConfiguration_heltec_wireless_stick myConfig; 58 | 59 | static const HalPinmap_t myPinmap = { 60 | .nss = SS, 61 | .rxtx = HalPinmap_t::UNUSED_PIN, 62 | .rst = RST_LoRa, 63 | .dio = {DIO0, DIO1, DIO2}, 64 | }; 65 | 66 | const HalPinmap_t* GetPinmap_heltec_wireless_stick(void) { return &myPinmap; } 67 | 68 | }; // namespace TTN_esp32_LMIC 69 | -------------------------------------------------------------------------------- /src/lmic/hal/getpinmap_thisboard.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | Module: getconfig_thisboard.cpp 4 | 5 | Function: 6 | Return a suitable LMIC config for this board. 7 | 8 | Copyright & License: 9 | See accompanying LICENSE file. 10 | 11 | Author: 12 | Terry Moore, MCCI November 2018 13 | 14 | */ 15 | #include "pins_arduino.h" 16 | 17 | #include "lmic/arduino_lmic_hal_boards.h" 18 | #include "lmic/lmic.h" 19 | namespace TTN_esp32_LMIC 20 | { 21 | 22 | const HalPinmap_t* GetPinmap_ThisBoard(void) 23 | { 24 | /* 25 | || Adafruit BSPs are not consistent -- m0 express defs ARDUINO_SAMD_FEATHER_M0, 26 | || m0 defs ADAFRUIT_FEATHER_M0 27 | */ 28 | #if defined(ARDUINO_SAMD_FEATHER_M0) || defined(ADAFRUIT_FEATHER_M0) 29 | #if defined(ARDUINO_MCCI_CATENA_4420) 30 | // this uses a radiowing and an odd configuration 31 | return GetPinmap_Catena4420(); 32 | #else 33 | // others use Feather M0 LoRa 34 | return GetPinmap_FeatherM0LoRa(); 35 | #endif 36 | #elif defined(ARDUINO_AVR_FEATHER32U4) 37 | return GetPinmap_Feather32U4LoRa(); 38 | #elif defined(ARDUINO_MCCI_CATENA_4551) || /* legacy names */ \ 39 | defined(ARDUINO_CATENA_4551) 40 | return GetPinmap_Catena4551(); 41 | #elif defined(ARDUINO_MCCI_CATENA_4610) 42 | return GetPinmap_Catena4610(); 43 | #elif defined(ARDUINO_MCCI_CATENA_4611) || /* legacy names */ \ 44 | defined(ARDUINO_CATENA_4611) 45 | return GetPinmap_Catena4611(); 46 | #elif defined(ARDUINO_MCCI_CATENA_4612) || /* legacy names */ \ 47 | defined(ARDUINO_CATENA_4612) 48 | return GetPinmap_Catena4612(); 49 | #elif defined(ARDUINO_MCCI_CATENA_4617) 50 | return GetPinmap_Catena4617(); 51 | #elif defined(ARDUINO_MCCI_CATENA_4618) 52 | return GetPinmap_Catena4618(); 53 | #elif defined(ARDUINO_MCCI_CATENA_4630) 54 | return GetPinmap_Catena4630(); 55 | #elif defined(ARDUINO_MCCI_CATENA_4801) 56 | return GetPinmap_Catena4801(); 57 | #elif defined(PINNOCHIO_SCOUT) 58 | return GetPinmap_PinnochioScount(); 59 | #elif defined(ARDUINO_HELTEC_WIFI_LORA_32) || defined(WIFI_LoRa_32) 60 | return GetPinmap_heltec_wifi_lora_32(); 61 | #elif defined(ARDUINO_HELTEC_WIFI_LORA_32_V2) || defined(WIFI_LoRa_32_V2) 62 | return GetPinmap_heltec_wifi_lora_32_V2(); 63 | #elif defined(ARDUINO_TTGO_LoRa32_V1) 64 | return GetPinmap_ttgo_lora32_v1(); 65 | #elif defined(ARDUINO_HELTEC_WIRELESS_STICK) || defined(Wireless_Stick) || defined(Wireless_Stick_Lite) 66 | return GetPinmap_heltec_wireless_stick(); // 67 | #elif defined(ARDUINO_M5STACK_FIRE) 68 | return GetPinmap_M5stack_Lora(); 69 | #elif defined(ARDUINO_TBeam) 70 | return GetPinmap_ttgo_TBEAM(); 71 | #else 72 | 73 | #pragma message("Board not supported -- use an explicit pinmap") 74 | return nullptr; 75 | 76 | #endif 77 | } 78 | 79 | }; // namespace TTN_esp32_LMIC 80 | -------------------------------------------------------------------------------- /src/lmic/hal/getpinmap_ttgo_TBEAM.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | Module: getconfig_ttgo_lora32_v1.cpp 4 | 5 | Function: 6 | Arduino-LMIC C++ HAL pinmap for TTGO ESP32 OLED V1 7 | 8 | Copyright & License: 9 | See accompanying LICENSE file. 10 | 11 | Author: 12 | German Martin, gmag11@gmail.com June 2019 13 | 14 | */ 15 | 16 | #include "lmic/arduino_lmic_hal_boards.h" 17 | #include 18 | 19 | #include "../lmic/oslmic.h" 20 | 21 | #define LORA_DIO0 26 22 | #define LORA_DIO1 33 23 | #define LORA_DIO2 32 24 | #ifdef LORA_RST 25 | namespace TTN_esp32_LMIC { 26 | 27 | class HalConfiguration_ttgo_TBEAM : public HalConfiguration_t 28 | { 29 | public: 30 | 31 | enum DIGITAL_PINS : uint8_t 32 | { 33 | 34 | 35 | 36 | PIN_SX1276_NSS = LORA_CS, 37 | PIN_SX1276_NRESET = LORA_RST, 38 | PIN_SX1276_DIO0 = LORA_DIO0, 39 | PIN_SX1276_DIO1 = LORA_DIO1, 40 | PIN_SX1276_DIO2 = LORA_DIO2, 41 | PIN_SX1276_ANT_SWITCH_RX = HalPinmap_t::UNUSED_PIN, 42 | PIN_SX1276_ANT_SWITCH_TX_BOOST = HalPinmap_t::UNUSED_PIN, 43 | PIN_SX1276_ANT_SWITCH_TX_RFO = HalPinmap_t::UNUSED_PIN, 44 | PIN_VDD_BOOST_ENABLE = HalPinmap_t::UNUSED_PIN, 45 | }; 46 | 47 | virtual void begin(void) override 48 | { 49 | digitalWrite(PIN_SX1276_NSS, 1); 50 | pinMode(PIN_SX1276_NSS, OUTPUT); 51 | } 52 | 53 | // virtual void end(void) override 54 | 55 | // virtual ostime_t setModuleActive(bool state) override 56 | 57 | }; 58 | 59 | static HalConfiguration_ttgo_TBEAM myConfig; 60 | 61 | static const HalPinmap_t myPinmap = 62 | { 63 | .nss = HalConfiguration_ttgo_TBEAM::PIN_SX1276_NSS, // chip select is D7 64 | .rxtx = HalConfiguration_ttgo_TBEAM::PIN_SX1276_ANT_SWITCH_RX, // RXTX is D29 65 | .rst = HalConfiguration_ttgo_TBEAM::PIN_SX1276_NRESET, // NRESET is D8 66 | 67 | .dio = {HalConfiguration_ttgo_TBEAM::PIN_SX1276_DIO0, // DIO0 (IRQ) is D25 68 | HalConfiguration_ttgo_TBEAM::PIN_SX1276_DIO1, // DIO1 is D26 69 | HalConfiguration_ttgo_TBEAM::PIN_SX1276_DIO2, // DIO2 is D27 70 | }, 71 | .rxtx_rx_active = 0, 72 | .rssi_cal = 10, 73 | .spi_freq = 8000000, /* 8MHz */ 74 | .pConfig = &myConfig 75 | }; 76 | 77 | const HalPinmap_t * GetPinmap_ttgo_TBEAM (void) 78 | { 79 | return &myPinmap; 80 | } 81 | 82 | 83 | }; // namespace TTN_esp32_LMIC 84 | #endif // LORA_RST -------------------------------------------------------------------------------- /src/lmic/hal/getpinmap_ttgo_lora32_v1.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | Module: getconfig_ttgo_lora32_v1.cpp 4 | 5 | Function: 6 | Arduino-LMIC C++ HAL pinmap for TTGO ESP32 OLED V1 7 | 8 | Copyright & License: 9 | See accompanying LICENSE file. 10 | 11 | Author: 12 | German Martin, gmag11@gmail.com June 2019 13 | 14 | */ 15 | 16 | #include "lmic/arduino_lmic_hal_boards.h" 17 | #include 18 | 19 | #include "../lmic/oslmic.h" 20 | 21 | #define LORA_DIO0 26 22 | #define LORA_DIO1 33 23 | #define LORA_DIO2 32 24 | 25 | namespace TTN_esp32_LMIC { 26 | 27 | class HalConfiguration_ttgo_lora32_v1 : public HalConfiguration_t 28 | { 29 | public: 30 | enum DIGITAL_PINS : uint8_t 31 | { 32 | PIN_SX1276_NSS = 18, 33 | PIN_SX1276_NRESET = 14, 34 | PIN_SX1276_DIO0 = LORA_DIO0, 35 | PIN_SX1276_DIO1 = LORA_DIO1, 36 | PIN_SX1276_DIO2 = LORA_DIO2, 37 | PIN_SX1276_ANT_SWITCH_RX = HalPinmap_t::UNUSED_PIN, 38 | PIN_SX1276_ANT_SWITCH_TX_BOOST = HalPinmap_t::UNUSED_PIN, 39 | PIN_SX1276_ANT_SWITCH_TX_RFO = HalPinmap_t::UNUSED_PIN, 40 | PIN_VDD_BOOST_ENABLE = HalPinmap_t::UNUSED_PIN, 41 | }; 42 | 43 | virtual void begin(void) override 44 | { 45 | digitalWrite(PIN_SX1276_NSS, 1); 46 | pinMode(PIN_SX1276_NSS, OUTPUT); 47 | } 48 | 49 | // virtual void end(void) override 50 | 51 | // virtual ostime_t setModuleActive(bool state) override 52 | 53 | }; 54 | 55 | static HalConfiguration_ttgo_lora32_v1 myConfig; 56 | 57 | static const HalPinmap_t myPinmap = 58 | { 59 | .nss = HalConfiguration_ttgo_lora32_v1::PIN_SX1276_NSS, // chip select is D7 60 | .rxtx = HalConfiguration_ttgo_lora32_v1::PIN_SX1276_ANT_SWITCH_RX, // RXTX is D29 61 | .rst = HalConfiguration_ttgo_lora32_v1::PIN_SX1276_NRESET, // NRESET is D8 62 | 63 | .dio = {HalConfiguration_ttgo_lora32_v1::PIN_SX1276_DIO0, // DIO0 (IRQ) is D25 64 | HalConfiguration_ttgo_lora32_v1::PIN_SX1276_DIO1, // DIO1 is D26 65 | HalConfiguration_ttgo_lora32_v1::PIN_SX1276_DIO2, // DIO2 is D27 66 | }, 67 | .rxtx_rx_active = 0, 68 | .rssi_cal = 10, 69 | .spi_freq = 8000000, /* 8MHz */ 70 | .pConfig = &myConfig 71 | }; 72 | 73 | const HalPinmap_t * GetPinmap_ttgo_lora32_v1 (void) 74 | { 75 | return &myPinmap; 76 | } 77 | 78 | }; // namespace TTN_esp32_LMIC 79 | -------------------------------------------------------------------------------- /src/lmic/hal/hal.h: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | * Copyright (c) 2015-2016 Matthijs Kooijman 3 | * Copyright (c) 2016-2018 MCCI Corporation 4 | * 5 | * All rights reserved. This program and the accompanying materials 6 | * are made available under the terms of the Eclipse Public License v1.0 7 | * which accompanies this distribution, and is available at 8 | * http://www.eclipse.org/legal/epl-v10.html 9 | * 10 | * This the HAL to run LMIC on top of the Arduino environment. 11 | *******************************************************************************/ 12 | #ifndef _hal_hal_h_ 13 | #define _hal_hal_h_ 14 | 15 | #include "lmic/arduino_lmic_hal_configuration.h" 16 | 17 | // for compatbility reasons, we need to disclose the configuration 18 | // structure as global type lmic_pinmap. 19 | using lmic_pinmap = TTN_esp32_LMIC::HalPinmap_t; 20 | 21 | // similarly, we need to disclose NUM_DIO and LMIC_UNUSED_PIN 22 | static const int NUM_DIO = lmic_pinmap::NUM_DIO; 23 | 24 | // Use this for any unused pins. 25 | const u1_t LMIC_UNUSED_PIN = lmic_pinmap::UNUSED_PIN; 26 | 27 | // Declared here, to be defined and initialized by the application. 28 | // Use os_init_ex() if you want not to use a const table, or if 29 | // you need to define a derived type (so you can override methods). 30 | extern const lmic_pinmap lmic_pins; 31 | 32 | #endif // _hal_hal_h_ 33 | -------------------------------------------------------------------------------- /src/lmic/lmic.h: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | Module: lmic.h 4 | 5 | Function: 6 | Deprecated C++ top-level include file (use instead). 7 | 8 | Copyright & License: 9 | See accompanying LICENSE file. 10 | 11 | Author: 12 | Terry Moore, MCCI November 2018 13 | 14 | Note: 15 | This header file is deprecated and is included for 16 | transitional purposes. It's deprecated because it's 17 | confusing to have src/lmic.h (this file) and src/lmic/lmic.h 18 | (the API file for the C library). We can't take it out 19 | yet, because it would inconvenience the world, but 20 | we can hope that someday it will wither away (on a major 21 | version bump). 22 | 23 | Please don't add any new functionality in this file; 24 | it is just a wrapper for arduino_lmic.h. 25 | 26 | */ 27 | 28 | #include "arduino_lmic.h" 29 | 30 | /* end of file */ 31 | -------------------------------------------------------------------------------- /src/lmic/lmic/config.h: -------------------------------------------------------------------------------- 1 | #ifndef _lmic_config_h_ 2 | #define _lmic_config_h_ 3 | 4 | // In the original LMIC code, these config values were defined on the 5 | // gcc commandline. Since Arduino does not allow easily modifying the 6 | // compiler commandline unless you modify the BSP, you have two choices: 7 | // 8 | // - edit {libraries}/arduino-lmic/project_config/lmic_project_config.h; 9 | // - use a BSP like the MCCI Arduino BSPs, which get the configuration 10 | // from the boards.txt file through a menu option. 11 | // 12 | // You definitely should not edit this file. 13 | 14 | // set up preconditions, and load configuration if needed. 15 | #ifndef _LMIC_CONFIG_PRECONDITIONS_H_ 16 | # include "lmic_config_preconditions.h" 17 | #endif 18 | 19 | // check post-conditions. 20 | 21 | // make sure that we have exactly one target region defined. 22 | #if CFG_LMIC_REGION_MASK == 0 23 | # define CFG_eu868 1 24 | #elif (CFG_LMIC_REGION_MASK & (-CFG_LMIC_REGION_MASK)) != CFG_LMIC_REGION_MASK 25 | # error You can define at most one of CFG_... variables 26 | #elif (CFG_LMIC_REGION_MASK & LMIC_REGIONS_SUPPORTED) == 0 27 | # error The selected CFG_... region is not supported yet. 28 | #endif 29 | 30 | // make sure that LMIC_COUNTRY_CODE is defined. 31 | #ifndef LMIC_COUNTRY_CODE 32 | # define LMIC_COUNTRY_CODE LMIC_COUNTRY_CODE_NONE 33 | #endif 34 | 35 | // if the country code is Japan, then the region must be AS923 36 | #if LMIC_COUNTRY_CODE == LMIC_COUNTRY_CODE_JP && CFG_region != LMIC_REGION_as923 37 | # error "If country code is JP, then region must be AS923" 38 | #endif 39 | 40 | // check for internal consistency 41 | #if !(CFG_LMIC_EU_like || CFG_LMIC_US_like) 42 | # error "Internal error: Neither EU-like nor US-like!" 43 | #endif 44 | 45 | // This is the SX1272/SX1273 radio, which is also used on the HopeRF 46 | // RFM92 boards. 47 | //#define CFG_sx1272_radio 1 48 | // This is the SX1276/SX1277/SX1278/SX1279 radio, which is also used on 49 | // the HopeRF RFM95 boards. 50 | //#define CFG_sx1276_radio 1 51 | 52 | // ensure that a radio is defined. 53 | #if ! (defined(CFG_sx1272_radio) || defined(CFG_sx1276_radio)) 54 | # warning Target radio not defined, assuming CFG_sx1276_radio 55 | #define CFG_sx1276_radio 1 56 | #elif defined(CFG_sx1272_radio) && defined(CFG_sx1276_radio) 57 | # error You can define at most one of CFG_sx1272_radio and CF_sx1276_radio 58 | #endif 59 | 60 | // LMIC requires ticks to be 15.5μs - 100 μs long 61 | #ifndef OSTICKS_PER_SEC 62 | // 16 μs per tick 63 | # ifndef US_PER_OSTICK_EXPONENT 64 | # define US_PER_OSTICK_EXPONENT 4 65 | # endif 66 | # define US_PER_OSTICK (1 << US_PER_OSTICK_EXPONENT) 67 | # define OSTICKS_PER_SEC (1000000 / US_PER_OSTICK) 68 | #endif /* OSTICKS_PER_SEC */ 69 | 70 | #if ! (10000 <= OSTICKS_PER_SEC && OSTICKS_PER_SEC < 64516) 71 | # error LMIC requires ticks to be 15.5 us to 100 us long 72 | #endif 73 | 74 | // Change the SPI clock speed if you encounter errors 75 | // communicating with the radio. 76 | // The standard range is 125kHz-8MHz, but some boards can go faster. 77 | #ifndef LMIC_SPI_FREQ 78 | #define LMIC_SPI_FREQ 1E6 79 | #endif 80 | 81 | // Set this to 1 to enable some basic debug output (using printf) about 82 | // RF settings used during transmission and reception. Set to 2 to 83 | // enable more verbose output. Make sure that printf is actually 84 | // configured (e.g. on AVR it is not by default), otherwise using it can 85 | // cause crashing. 86 | #ifndef LMIC_DEBUG_LEVEL 87 | #define LMIC_DEBUG_LEVEL 0 88 | #endif 89 | 90 | // Enable this to allow using printf() to print to the given serial port 91 | // (or any other Print object). This can be easy for debugging. The 92 | // current implementation only works on AVR, though. 93 | //#define LMIC_PRINTF_TO Serial 94 | 95 | // Enable this to use interrupt handler routines listening for RISING signals. 96 | // Otherwise, the library polls digital input lines for changes. 97 | #define LMIC_USE_INTERRUPTS 98 | 99 | // If DISABLE_LMIC_FAILURE_TO is defined, runtime assertion failures 100 | // silently halt execution. Otherwise, LMIC_FAILURE_TO should be defined 101 | // as the name of an object derived from Print, which will be used for 102 | // displaying runtime assertion failures. If you say nothing in your 103 | // lmic_project_config.h, runtime assertion failures are displayed 104 | // using the Serial object. 105 | #if ! defined(DISABLE_LMIC_FAILURE_TO) && ! defined(LMIC_FAILURE_TO) 106 | #define LMIC_FAILURE_TO Serial 107 | #endif 108 | 109 | // define this in lmic_project_config.h to disable all code related to joining 110 | //#define DISABLE_JOIN 111 | // define this in lmic_project_config.h to disable all code related to ping 112 | //#define DISABLE_PING 113 | // define this in lmic_project_config.h to disable all code related to beacon tracking. 114 | // Requires ping to be disabled too 115 | //#define DISABLE_BEACONS 116 | 117 | // define these in lmic_project_config.h to disable the corresponding MAC commands. 118 | // Class A 119 | //#define DISABLE_MCMD_DutyCycleReq // duty cycle cap 120 | //#define DISABLE_MCMD_RXParamSetupReq // 2nd DN window param 121 | //#define DISABLE_MCMD_NewChannelReq // set new channel 122 | //#define DISABLE_MCMD_DlChannelReq // set downlink channel for RX1 for given uplink channel. 123 | //#define DISABLE_MCMD_RXTimingSetupReq // delay between TX and RX 124 | // Class B 125 | //#define DISABLE_MCMD_PingSlotChannelReq // set ping freq, automatically disabled by DISABLE_PING 126 | //#define ENABLE_MCMD_BeaconTimingAns // next beacon start, DEPRECATED, normally disabled by DISABLE_BEACON 127 | 128 | // DEPRECATED(tmm@mcci.com); replaced by LMIC.noRXIQinversion (dynamic). Don't define this. 129 | //#define DISABLE_INVERT_IQ_ON_RX 130 | 131 | // This allows choosing between multiple included AES implementations. 132 | // Make sure exactly one of these is uncommented. 133 | // 134 | // This selects the original AES implementation included LMIC. This 135 | // implementation is optimized for speed on 32-bit processors using 136 | // fairly big lookup tables, but it takes up big amounts of flash on the 137 | // AVR architecture. 138 | // #define USE_ORIGINAL_AES 139 | // 140 | // This selects the AES implementation written by Ideetroon for their 141 | // own LoRaWAN library. It also uses lookup tables, but smaller 142 | // byte-oriented ones, making it use a lot less flash space (but it is 143 | // also about twice as slow as the original). 144 | // #define USE_IDEETRON_AES 145 | 146 | #if ! (defined(USE_ORIGINAL_AES) || defined(USE_IDEETRON_AES)) 147 | # define USE_IDEETRON_AES 148 | #endif 149 | 150 | #if defined(USE_ORIGINAL_AES) && defined(USE_IDEETRON_AES) 151 | # error "You may define at most one of USE_ORIGINAL_AES and USE_IDEETRON_AES" 152 | #endif 153 | 154 | // LMIC_DISABLE_DR_LEGACY 155 | // turn off legacy DR_* symbols that vary by bandplan. 156 | // Older code uses these for configuration. EU868_DR_*, US915_DR_* 157 | // etc symbols are prefered, but breaking older code is inconvenient for 158 | // everybody. We don't want to use DR_* in the LMIC itself, so we provide 159 | // this #define to allow them to be removed. 160 | #if !defined(LMIC_DR_LEGACY) 161 | # if !defined(LMIC_DISABLE_DR_LEGACY) 162 | # define LMIC_DR_LEGACY 1 163 | # else // defined(LMIC_DISABLE_DR_LEGACY) 164 | # define LMIC_DR_LEGACY 0 165 | # endif // defined(LMIC_DISABLE_DR_LEGACY) 166 | #endif // LMIC_DR_LEGACY 167 | 168 | // LMIC_ENABLE_DeviceTimeReq 169 | // enable support for MCMD_DeviceTimeReq and MCMD_DeviceTimeAns 170 | // this is always defined, and non-zero to enable it. 171 | #if !defined(LMIC_ENABLE_DeviceTimeReq) 172 | # define LMIC_ENABLE_DeviceTimeReq 1 173 | #endif 174 | 175 | // LMIC_ENABLE_user_events 176 | // Enable/disable support for programmable callbacks for events, rx, and tx. 177 | // This is always defined, and non-zero to enable. Default is enabled. 178 | #if !defined(LMIC_ENABLE_user_events) 179 | # define LMIC_ENABLE_user_events 1 180 | #endif 181 | 182 | // LMIC_ENABLE_onEvent 183 | // Enable/disable support for out-call to user-supplied `onEvent()` function. 184 | // This is always defined, and non-zero to enable. Default is enabled. 185 | #if !defined(LMIC_ENABLE_onEvent) 186 | # define LMIC_ENABLE_onEvent 1 187 | #endif 188 | 189 | // LMIC_ENABLE_long_messages 190 | // LMIC certification requires full-length 255 frames, but to save RAM, 191 | // a shorter maximum can be set. This controls both RX and TX buffers, 192 | // so reducing this by 1 saves 2 bytes of RAM. 193 | #if defined(LMIC_ENABLE_long_messages) && defined(LMIC_MAX_FRAME_LENGTH) 194 | #error "Use only one of LMIC_ENABLE_long_messages or LMIC_MAX_FRAME_LENGTH" 195 | #elif defined(LMIC_ENABLE_long_messages) && LMIC_ENABLE_long_messages == 0 196 | # define LMIC_MAX_FRAME_LENGTH 64 197 | #elif !defined(LMIC_MAX_FRAME_LENGTH) 198 | # define LMIC_MAX_FRAME_LENGTH 255 199 | #elif LMIC_MAX_FRAME_LENGTH > 255 200 | #error "LMIC_MAX_FRAME_LENGTH cannot be larger than 255" 201 | #endif 202 | 203 | // LMIC_ENABLE_event_logging 204 | // LMIC debugging for certification tests requires this, because debug prints affect 205 | // timing too dramatically. But normal operation doesn't need this. 206 | #if !defined(LMIC_ENABLE_event_logging) 207 | # define LMIC_ENABLE_event_logging 0 /* PARAM */ 208 | #endif 209 | 210 | // LMIC_LORAWAN_SPEC_VERSION 211 | #if !defined(LMIC_LORAWAN_SPEC_VERSION) 212 | # define LMIC_LORAWAN_SPEC_VERSION LMIC_LORAWAN_SPEC_VERSION_1_0_3 213 | #endif 214 | 215 | // LMIC_ENABLE_arbitrary_clock_error 216 | // We normally don't want to allow users to set wide clock errors, because 217 | // we assume reasonably-disciplined os_getTime() values. But... there might 218 | // be platforms that require wider errors. 219 | #if !defined(LMIC_ENABLE_arbitrary_clock_error) 220 | # define LMIC_ENABLE_arbitrary_clock_error 0 /* PARAM */ 221 | #endif 222 | 223 | #endif // _lmic_config_h_ 224 | -------------------------------------------------------------------------------- /src/lmic/lmic/hal.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2014-2016 IBM Corporation. 3 | * Copyright (c) 2016, 2018-2019 MCCI Corporation. 4 | * All rights reserved. 5 | * 6 | * Redistribution and use in source and binary forms, with or without 7 | * modification, are permitted provided that the following conditions are met: 8 | * * Redistributions of source code must retain the above copyright 9 | * notice, this list of conditions and the following disclaimer. 10 | * * Redistributions in binary form must reproduce the above copyright 11 | * notice, this list of conditions and the following disclaimer in the 12 | * documentation and/or other materials provided with the distribution. 13 | * * Neither the name of the nor the 14 | * names of its contributors may be used to endorse or promote products 15 | * derived from this software without specific prior written permission. 16 | * 17 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 18 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 19 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 20 | * DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY 21 | * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 22 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 23 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 24 | * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 26 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 | */ 28 | 29 | #ifndef _lmic_hal_h_ 30 | #define _lmic_hal_h_ 31 | 32 | #ifndef _oslmic_types_h_ 33 | # include "oslmic_types.h" 34 | #endif 35 | 36 | #ifndef _lmic_env_h_ 37 | # include "lmic_env.h" 38 | #endif 39 | 40 | #ifdef __cplusplus 41 | extern "C"{ 42 | #endif 43 | 44 | // The type of an optional user-defined failure handler routine 45 | typedef void LMIC_ABI_STD hal_failure_handler_t(const char* const file, const uint16_t line); 46 | 47 | /* 48 | * initialize hardware (IO, SPI, TIMER, IRQ). 49 | * This API is deprecated as it uses the const global lmic_pins, 50 | * which the platform can't control or change. 51 | */ 52 | void hal_init (void); 53 | 54 | /* 55 | * Initialize hardware, passing in platform-specific context 56 | * The pointer is to a HalPinmap_t. 57 | */ 58 | void hal_init_ex (const void *pContext); 59 | 60 | /* 61 | * drive radio RX/TX pins (0=rx, 1=tx). Actual polarity 62 | * is determined by the value of HalPinmap_t::rxtx_rx_active. 63 | */ 64 | void hal_pin_rxtx (u1_t val); 65 | 66 | /* 67 | * control radio RST pin (0=low, 1=high, 2=floating) 68 | */ 69 | void hal_pin_rst (u1_t val); 70 | 71 | /* 72 | * Perform SPI write transaction with radio chip 73 | * - write the command byte 'cmd' 74 | * - write 'len' bytes out of 'buf' 75 | */ 76 | void hal_spi_write(u1_t cmd, const u1_t* buf, size_t len); 77 | 78 | /* 79 | * Perform SPI read transaction with radio chip 80 | * - write the command byte 'cmd' 81 | * - read 'len' bytes into 'buf' 82 | */ 83 | void hal_spi_read(u1_t cmd, u1_t* buf, size_t len); 84 | 85 | /* 86 | * disable all CPU interrupts. 87 | * - might be invoked nested 88 | * - will be followed by matching call to hal_enableIRQs() 89 | */ 90 | void hal_disableIRQs (void); 91 | 92 | /* 93 | * enable CPU interrupts. 94 | */ 95 | void hal_enableIRQs (void); 96 | 97 | /* 98 | * return CPU interrupt nesting count 99 | */ 100 | uint8_t hal_getIrqLevel (void); 101 | 102 | /* 103 | * put system and CPU in low-power mode, sleep until interrupt. 104 | */ 105 | void hal_sleep (void); 106 | 107 | /* 108 | * return 32-bit system time in ticks. 109 | */ 110 | u4_t hal_ticks (void); 111 | 112 | /* 113 | * busy-wait until specified timestamp (in ticks) is reached. If on-time, return 0, 114 | * otherwise return the number of ticks we were late. 115 | */ 116 | u4_t hal_waitUntil (u4_t time); 117 | 118 | /* 119 | * check and rewind timer for target time. 120 | * - return 1 if target time is close 121 | * - otherwise rewind timer for target time or full period and return 0 122 | */ 123 | u1_t hal_checkTimer (u4_t targettime); 124 | 125 | /* 126 | * perform fatal failure action. 127 | * - called by assertions 128 | * - action could be HALT or reboot 129 | */ 130 | void hal_failed (const char *file, u2_t line); 131 | 132 | /* 133 | * set a custom hal failure handler routine. The default behaviour, defined in 134 | * hal_failed(), is to halt by looping infintely. 135 | */ 136 | void hal_set_failure_handler(const hal_failure_handler_t* const); 137 | 138 | /* 139 | * get the calibration value for radio_rssi 140 | */ 141 | s1_t hal_getRssiCal (void); 142 | 143 | /* 144 | * control the radio state 145 | * - if val == 0, turn tcxo off and otherwise prepare for sleep 146 | * - if val == 1, turn tcxo on and otherwise prep for activity 147 | * - return the number of ticks that we need to wait 148 | */ 149 | ostime_t hal_setModuleActive (bit_t val); 150 | 151 | /* find out if we're using Tcxo */ 152 | bit_t hal_queryUsingTcxo(void); 153 | 154 | /* represent the various radio TX power policy */ 155 | enum { 156 | LMICHAL_radio_tx_power_policy_rfo = 0, 157 | LMICHAL_radio_tx_power_policy_paboost = 1, 158 | LMICHAL_radio_tx_power_policy_20dBm = 2, 159 | }; 160 | 161 | /* 162 | * query the configuration as to the Tx Power Policy 163 | * to be used on this board, given our desires and 164 | * requested power. 165 | */ 166 | uint8_t hal_getTxPowerPolicy( 167 | u1_t inputPolicy, 168 | s1_t requestedPower, 169 | u4_t freq 170 | ); 171 | 172 | void hal_pollPendingIRQs_helper(); 173 | void hal_processPendingIRQs(void); 174 | 175 | /// \brief check for any pending interrupts: stub if interrupts are enabled. 176 | static inline void hal_pollPendingIRQs(void) 177 | { 178 | #if !defined(LMIC_USE_INTERRUPTS) 179 | hal_pollPendingIRQs_helper(); 180 | #endif /* !defined(LMIC_USE_INTERRUPTS) */ 181 | } 182 | 183 | #ifdef __cplusplus 184 | } // extern "C" 185 | #endif 186 | 187 | #endif // _lmic_hal_h_ 188 | -------------------------------------------------------------------------------- /src/lmic/lmic/lmic_bandplan_as923.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2014-2016 IBM Corporation. 3 | * Copyright (c) 2017, 2019-2021 MCCI Corporation. 4 | * All rights reserved. 5 | * 6 | * Redistribution and use in source and binary forms, with or without 7 | * modification, are permitted provided that the following conditions are met: 8 | * * Redistributions of source code must retain the above copyright 9 | * notice, this list of conditions and the following disclaimer. 10 | * * Redistributions in binary form must reproduce the above copyright 11 | * notice, this list of conditions and the following disclaimer in the 12 | * documentation and/or other materials provided with the distribution. 13 | * * Neither the name of the nor the 14 | * names of its contributors may be used to endorse or promote products 15 | * derived from this software without specific prior written permission. 16 | * 17 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 18 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 19 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 20 | * DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY 21 | * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 22 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 23 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 24 | * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 26 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 | */ 28 | 29 | #ifndef _lmic_bandplan_as923_h_ 30 | # define _lmic_bandplan_as923_h_ 31 | 32 | #ifndef _lmic_eu_like_h_ 33 | # include "lmic_eu_like.h" 34 | #endif 35 | 36 | // return maximum frame length (including PHY header) for this data rate (as923); 0 --> not valid dr. 37 | uint8_t LMICas923_maxFrameLen(uint8_t dr); 38 | // return maximum frame length (including PHY header) for this data rate; 0 --> not valid dr. 39 | #define LMICbandplan_maxFrameLen(dr) LMICas923_maxFrameLen(dr) 40 | 41 | int8_t LMICas923_pow2dBm(uint8_t mcmd_ladr_p1); 42 | #define pow2dBm(mcmd_ladr_p1) LMICas923_pow2dBm(mcmd_ladr_p1) 43 | 44 | // Times for half symbol per DR 45 | // Per DR table to minimize rounding errors 46 | ostime_t LMICas923_dr2hsym(uint8_t dr); 47 | #define dr2hsym(dr) LMICas923_dr2hsym(dr) 48 | 49 | static inline int 50 | LMICas923_isValidBeacon1(const uint8_t *d) { 51 | return os_rlsbf2(&d[OFF_BCN_CRC1]) != os_crc16(d, OFF_BCN_CRC1); 52 | } 53 | 54 | #undef LMICbandplan_isValidBeacon1 55 | #define LMICbandplan_isValidBeacon1(pFrame) LMICas923_isValidBeacon1(pFrame) 56 | 57 | // override default for LMICbandplan_resetDefaultChannels 58 | void 59 | LMICas923_resetDefaultChannels(void); 60 | 61 | #undef LMICbandplan_resetDefaultChannels 62 | #define LMICbandplan_resetDefaultChannels() \ 63 | LMICas923_resetDefaultChannels() 64 | 65 | // override default for LMICbandplan_init 66 | void LMICas923_init(void); 67 | 68 | #undef LMICbandplan_init 69 | #define LMICbandplan_init() \ 70 | LMICas923_init() 71 | 72 | 73 | // override default for LMICbandplan_isFSK() 74 | #undef LMICbandplan_isFSK 75 | #define LMICbandplan_isFSK() (/* RX datarate */LMIC.dndr == AS923_DR_FSK) 76 | 77 | #define LMICbandplan_getInitialDrJoin() (AS923_DR_SF10) 78 | 79 | void LMICas923_setBcnRxParams(void); 80 | #define LMICbandplan_setBcnRxParams() LMICas923_setBcnRxParams() 81 | 82 | u4_t LMICas923_convFreq(xref2cu1_t ptr); 83 | #define LMICbandplan_convFreq(ptr) LMICas923_convFreq(ptr) 84 | 85 | void LMICas923_initJoinLoop(void); 86 | #define LMICbandplan_initJoinLoop() LMICas923_initJoinLoop() 87 | 88 | // for as923, depending on dwell, we may need to do something else 89 | #undef LMICbandplan_setRx1Params 90 | void LMICas923_setRx1Params(void); 91 | #define LMICbandplan_setRx1Params() LMICas923_setRx1Params() 92 | 93 | ostime_t LMICas923_nextTx(ostime_t now); 94 | #define LMICbandplan_nextTx(now) LMICas923_nextTx(now) 95 | 96 | ostime_t LMICas923_nextJoinState(void); 97 | #define LMICbandplan_nextJoinState() LMICas923_nextJoinState() 98 | 99 | void LMICas923_initDefaultChannels(bit_t join); 100 | #define LMICbandplan_initDefaultChannels(join) LMICas923_initDefaultChannels(join) 101 | 102 | // override default for LMICbandplan_updateTX 103 | #undef LMICbandplan_updateTx 104 | void LMICas923_updateTx(ostime_t txbeg); 105 | #define LMICbandplan_updateTx(txbeg) LMICas923_updateTx(txbeg) 106 | 107 | #undef LMICbandplan_nextJoinTime 108 | ostime_t LMICas923_nextJoinTime(ostime_t now); 109 | #define LMICbandplan_nextJoinTime(now) LMICas923_nextJoinTime(now) 110 | 111 | #undef LMICbandplan_validDR 112 | bit_t LMICas923_validDR(dr_t dr); 113 | #define LMICbandplan_validDR(dr) LMICas923_validDR(dr) 114 | 115 | #endif // _lmic_bandplan_as923_h_ 116 | -------------------------------------------------------------------------------- /src/lmic/lmic/lmic_bandplan_au915.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2014-2016 IBM Corporation. 3 | * Copyright (c) 2017, 2019-2021 MCCI Corporation. 4 | * All rights reserved. 5 | * 6 | * Redistribution and use in source and binary forms, with or without 7 | * modification, are permitted provided that the following conditions are met: 8 | * * Redistributions of source code must retain the above copyright 9 | * notice, this list of conditions and the following disclaimer. 10 | * * Redistributions in binary form must reproduce the above copyright 11 | * notice, this list of conditions and the following disclaimer in the 12 | * documentation and/or other materials provided with the distribution. 13 | * * Neither the name of the nor the 14 | * names of its contributors may be used to endorse or promote products 15 | * derived from this software without specific prior written permission. 16 | * 17 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 18 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 19 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 20 | * DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY 21 | * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 22 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 23 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 24 | * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 26 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 | */ 28 | 29 | #ifndef _lmic_bandplan_au915_h_ 30 | # define _lmic_bandplan_au915_h_ 31 | 32 | // preconditions for lmic_us_like.h 33 | #define LMICuslike_getFirst500kHzDR() (LORAWAN_DR6) 34 | #define LMICuslike_getJoin125kHzDR() (LORAWAN_DR2) 35 | 36 | #ifndef _lmic_us_like_h_ 37 | # include "lmic_us_like.h" 38 | #endif 39 | 40 | // return maximum frame length (including PHY header) for this data rate (au915); 0 --> not valid dr. 41 | uint8_t LMICau915_maxFrameLen(uint8_t dr); 42 | // return maximum frame length (including PHY header) for this data rate; 0 --> not valid dr. 43 | #define LMICbandplan_maxFrameLen(dr) LMICau915_maxFrameLen(dr) 44 | 45 | int8_t LMICau915_pow2dbm(uint8_t mcmd_ladr_p1); 46 | #define pow2dBm(mcmd_ladr_p1) LMICau915_pow2dbm(mcmd_ladr_p1) 47 | 48 | ostime_t LMICau915_dr2hsym(uint8_t dr); 49 | #define dr2hsym(dr) LMICau915_dr2hsym(dr) 50 | 51 | 52 | #define LMICbandplan_getInitialDrJoin() (LORAWAN_DR2) 53 | 54 | void LMICau915_initJoinLoop(void); 55 | #define LMICbandplan_initJoinLoop() LMICau915_initJoinLoop() 56 | 57 | void LMICau915_setBcnRxParams(void); 58 | #define LMICbandplan_setBcnRxParams() LMICau915_setBcnRxParams() 59 | 60 | u4_t LMICau915_convFreq(xref2cu1_t ptr); 61 | #define LMICbandplan_convFreq(ptr) LMICau915_convFreq(ptr) 62 | 63 | void LMICau915_setRx1Params(void); 64 | #define LMICbandplan_setRx1Params() LMICau915_setRx1Params() 65 | 66 | void LMICau915_updateTx(ostime_t txbeg); 67 | #define LMICbandplan_updateTx(txbeg) LMICau915_updateTx(txbeg) 68 | 69 | #undef LMICbandplan_validDR 70 | bit_t LMICau915_validDR(dr_t dr); 71 | #define LMICbandplan_validDR(dr) LMICau915_validDR(dr) 72 | 73 | #endif // _lmic_bandplan_au915_h_ 74 | -------------------------------------------------------------------------------- /src/lmic/lmic/lmic_bandplan_eu868.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2014-2016 IBM Corporation. 3 | * Copyright (c) 2017, 2019-2021 MCCI Corporation. 4 | * All rights reserved. 5 | * 6 | * Redistribution and use in source and binary forms, with or without 7 | * modification, are permitted provided that the following conditions are met: 8 | * * Redistributions of source code must retain the above copyright 9 | * notice, this list of conditions and the following disclaimer. 10 | * * Redistributions in binary form must reproduce the above copyright 11 | * notice, this list of conditions and the following disclaimer in the 12 | * documentation and/or other materials provided with the distribution. 13 | * * Neither the name of the nor the 14 | * names of its contributors may be used to endorse or promote products 15 | * derived from this software without specific prior written permission. 16 | * 17 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 18 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 19 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 20 | * DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY 21 | * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 22 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 23 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 24 | * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 26 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 | */ 28 | 29 | #ifndef _lmic_eu868_h_ 30 | # define _lmic_eu868_h_ 31 | 32 | #ifndef _lmic_eu_like_h_ 33 | # include "lmic_eu_like.h" 34 | #endif 35 | 36 | // return maximum frame length (including PHY header) for this data rate (eu868); 0 --> not valid dr. 37 | uint8_t LMICeu868_maxFrameLen(uint8_t dr); 38 | // return maximum frame length (including PHY header) for this data rate; 0 --> not valid dr. 39 | #define LMICbandplan_maxFrameLen(dr) LMICeu868_maxFrameLen(dr) 40 | 41 | int8_t LMICeu868_pow2dBm(uint8_t mcmd_ladr_p1); 42 | #define pow2dBm(mcmd_ladr_p1) LMICeu868_pow2dBm(mcmd_ladr_p1) 43 | 44 | // Times for half symbol per DR 45 | // Per DR table to minimize rounding errors 46 | ostime_t LMICeu868_dr2hsym(uint8_t dr); 47 | #define dr2hsym(dr) LMICeu868_dr2hsym(dr) 48 | 49 | 50 | // TODO(tmm@mcci.com) this looks bogus compared to current 1.02 regional 51 | // spec. https://github.com/mcci-catena/arduino-lmic/issues/18 52 | static inline int 53 | LMICeu868_isValidBeacon1(const uint8_t *d) { 54 | return d[OFF_BCN_CRC1] != (u1_t)os_crc16(d, OFF_BCN_CRC1); 55 | } 56 | 57 | #undef LMICbandplan_isValidBeacon1 58 | #define LMICbandplan_isValidBeacon1(pFrame) LMICeu868_isValidBeacon1(pFrame) 59 | 60 | // override default for LMICbandplan_isFSK() 61 | #undef LMICbandplan_isFSK 62 | #define LMICbandplan_isFSK() (/* RX datarate */LMIC.dndr == EU868_DR_FSK) 63 | 64 | #define LMICbandplan_getInitialDrJoin() (EU868_DR_SF7) 65 | 66 | void LMICeu868_setBcnRxParams(void); 67 | #define LMICbandplan_setBcnRxParams() LMICeu868_setBcnRxParams() 68 | 69 | u4_t LMICeu868_convFreq(xref2cu1_t ptr); 70 | #define LMICbandplan_convFreq(ptr) LMICeu868_convFreq(ptr) 71 | 72 | void LMICeu868_initJoinLoop(void); 73 | #define LMICbandplan_initJoinLoop() LMICeu868_initJoinLoop() 74 | 75 | ostime_t LMICeu868_nextTx(ostime_t now); 76 | #define LMICbandplan_nextTx(now) LMICeu868_nextTx(now) 77 | 78 | ostime_t LMICeu868_nextJoinState(void); 79 | #define LMICbandplan_nextJoinState() LMICeu868_nextJoinState() 80 | 81 | void LMICeu868_initDefaultChannels(bit_t join); 82 | #define LMICbandplan_initDefaultChannels(join) LMICeu868_initDefaultChannels(join) 83 | 84 | #undef LMICbandplan_nextJoinTime 85 | ostime_t LMICeu868_nextJoinTime(ostime_t now); 86 | #define LMICbandplan_nextJoinTime(now) LMICeu868_nextJoinTime(now) 87 | 88 | void LMICeu868_setRx1Params(void); 89 | #define LMICbandplan_setRx1Params() LMICeu868_setRx1Params() 90 | 91 | #undef LMICbandplan_validDR 92 | bit_t LMICeu868_validDR(dr_t dr); 93 | #define LMICbandplan_validDR(dr) LMICeu868_validDR(dr) 94 | 95 | #endif // _lmic_eu868_h_ 96 | -------------------------------------------------------------------------------- /src/lmic/lmic/lmic_bandplan_in866.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2014-2016 IBM Corporation. 3 | * Copyright (c) 2017, 2019-2021 MCCI Corporation. 4 | * All rights reserved. 5 | * 6 | * Redistribution and use in source and binary forms, with or without 7 | * modification, are permitted provided that the following conditions are met: 8 | * * Redistributions of source code must retain the above copyright 9 | * notice, this list of conditions and the following disclaimer. 10 | * * Redistributions in binary form must reproduce the above copyright 11 | * notice, this list of conditions and the following disclaimer in the 12 | * documentation and/or other materials provided with the distribution. 13 | * * Neither the name of the nor the 14 | * names of its contributors may be used to endorse or promote products 15 | * derived from this software without specific prior written permission. 16 | * 17 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 18 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 19 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 20 | * DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY 21 | * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 22 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 23 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 24 | * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 26 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 | */ 28 | 29 | #ifndef _lmic_bandplan_in866_h_ 30 | # define _lmic_bandplan_in866_h_ 31 | 32 | #ifndef _lmic_eu_like_h_ 33 | # include "lmic_eu_like.h" 34 | #endif 35 | 36 | // return maximum frame length (including PHY header) for this data rate (in866); 0 --> not valid dr. 37 | uint8_t LMICin866_maxFrameLen(uint8_t dr); 38 | // return maximum frame length (including PHY header) for this data rate; 0 --> not valid dr. 39 | #define LMICbandplan_maxFrameLen(dr) LMICin866_maxFrameLen(dr) 40 | 41 | int8_t LMICin866_pow2dBm(uint8_t mcmd_ladr_p1); 42 | #define pow2dBm(mcmd_ladr_p1) LMICin866_pow2dBm(mcmd_ladr_p1) 43 | 44 | // Times for half symbol per DR 45 | // Per DR table to minimize rounding errors 46 | ostime_t LMICin866_dr2hsym(uint8_t dr); 47 | #define dr2hsym(dr) LMICin866_dr2hsym(dr) 48 | 49 | static inline int 50 | LMICin866_isValidBeacon1(const uint8_t *d) { 51 | return os_rlsbf2(&d[OFF_BCN_CRC1]) != os_crc16(d, OFF_BCN_CRC1); 52 | } 53 | 54 | #undef LMICbandplan_isValidBeacon1 55 | #define LMICbandplan_isValidBeacon1(pFrame) LMICin866_isValidBeacon1(pFrame) 56 | 57 | // override default for LMICbandplan_isFSK() 58 | #undef LMICbandplan_isFSK 59 | #define LMICbandplan_isFSK() (/* TX datarate */LMIC.dndr == IN866_DR_FSK) 60 | 61 | #define LMICbandplan_getInitialDrJoin() (IN866_DR_SF7) 62 | 63 | void LMICin866_setBcnRxParams(void); 64 | #define LMICbandplan_setBcnRxParams() LMICin866_setBcnRxParams() 65 | 66 | u4_t LMICin866_convFreq(xref2cu1_t ptr); 67 | #define LMICbandplan_convFreq(ptr) LMICin866_convFreq(ptr) 68 | 69 | void LMICin866_initJoinLoop(void); 70 | #define LMICbandplan_initJoinLoop() LMICin866_initJoinLoop() 71 | 72 | ostime_t LMICin866_nextTx(ostime_t now); 73 | #define LMICbandplan_nextTx(now) LMICin866_nextTx(now) 74 | 75 | ostime_t LMICin866_nextJoinState(void); 76 | #define LMICbandplan_nextJoinState() LMICin866_nextJoinState() 77 | 78 | void LMICin866_initDefaultChannels(bit_t join); 79 | #define LMICbandplan_initDefaultChannels(join) LMICin866_initDefaultChannels(join) 80 | 81 | void LMICin866_setRx1Params(void); 82 | #define LMICbandplan_setRx1Params() LMICin866_setRx1Params() 83 | 84 | #undef LMICbandplan_validDR 85 | bit_t LMICin866_validDR(dr_t dr); 86 | #define LMICbandplan_validDR(dr) LMICin866_validDR(dr) 87 | 88 | #endif // _lmic_bandplan_in866_h_ 89 | -------------------------------------------------------------------------------- /src/lmic/lmic/lmic_bandplan_kr920.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2014-2016 IBM Corporation. 3 | * Copyright (c) 2017, 2019-2021 MCCI Corporation. 4 | * All rights reserved. 5 | * 6 | * Redistribution and use in source and binary forms, with or without 7 | * modification, are permitted provided that the following conditions are met: 8 | * * Redistributions of source code must retain the above copyright 9 | * notice, this list of conditions and the following disclaimer. 10 | * * Redistributions in binary form must reproduce the above copyright 11 | * notice, this list of conditions and the following disclaimer in the 12 | * documentation and/or other materials provided with the distribution. 13 | * * Neither the name of the nor the 14 | * names of its contributors may be used to endorse or promote products 15 | * derived from this software without specific prior written permission. 16 | * 17 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 18 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 19 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 20 | * DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY 21 | * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 22 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 23 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 24 | * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 26 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 | */ 28 | 29 | #ifndef _lmic_kr920_h_ 30 | # define _lmic_kr920_h_ 31 | 32 | #ifndef _lmic_eu_like_h_ 33 | # include "lmic_eu_like.h" 34 | #endif 35 | 36 | // return maximum frame length (including PHY header) for this data rate (kr920); 0 --> not valid dr. 37 | uint8_t LMICkr920_maxFrameLen(uint8_t dr); 38 | // return maximum frame length (including PHY header) for this data rate; 0 --> not valid dr. 39 | #define LMICbandplan_maxFrameLen(dr) LMICkr920_maxFrameLen(dr) 40 | 41 | int8_t LMICkr920_pow2dBm(uint8_t mcmd_ladr_p1); 42 | #define pow2dBm(mcmd_ladr_p1) LMICkr920_pow2dBm(mcmd_ladr_p1) 43 | 44 | // Times for half symbol per DR 45 | // Per DR table to minimize rounding errors 46 | ostime_t LMICkr920_dr2hsym(uint8_t dr); 47 | #define dr2hsym(dr) LMICkr920_dr2hsym(dr) 48 | 49 | 50 | // TODO(tmm@mcci.com) this looks bogus compared to current 1.02 regional 51 | // spec. https://github.com/mcci-catena/arduino-lmic/issues/18 52 | static inline int 53 | LMICkr920_isValidBeacon1(const uint8_t *d) { 54 | return d[OFF_BCN_CRC1] != (u1_t)os_crc16(d, OFF_BCN_CRC1); 55 | } 56 | 57 | #undef LMICbandplan_isValidBeacon1 58 | #define LMICbandplan_isValidBeacon1(pFrame) LMICkr920_isValidBeacon1(pFrame) 59 | 60 | // override default for LMICbandplan_isFSK() 61 | #undef LMICbandplan_isFSK 62 | #define LMICbandplan_isFSK() (/* always false */ 0) 63 | 64 | #define LMICbandplan_getInitialDrJoin() (KR920_DR_SF7) 65 | 66 | void LMICkr920_setBcnRxParams(void); 67 | #define LMICbandplan_setBcnRxParams() LMICkr920_setBcnRxParams() 68 | 69 | u4_t LMICkr920_convFreq(xref2cu1_t ptr); 70 | #define LMICbandplan_convFreq(ptr) LMICkr920_convFreq(ptr) 71 | 72 | void LMICkr920_initJoinLoop(void); 73 | #define LMICbandplan_initJoinLoop() LMICkr920_initJoinLoop() 74 | 75 | ostime_t LMICkr920_nextTx(ostime_t now); 76 | #define LMICbandplan_nextTx(now) LMICkr920_nextTx(now) 77 | 78 | ostime_t LMICkr920_nextJoinState(void); 79 | #define LMICbandplan_nextJoinState() LMICkr920_nextJoinState() 80 | 81 | void LMICkr920_initDefaultChannels(bit_t join); 82 | #define LMICbandplan_initDefaultChannels(join) LMICkr920_initDefaultChannels(join) 83 | 84 | void LMICkr920_setRx1Params(void); 85 | #define LMICbandplan_setRx1Params() LMICkr920_setRx1Params() 86 | 87 | #undef LMICbandplan_updateTx 88 | void LMICkr920_updateTx(ostime_t txbeg); 89 | #define LMICbandplan_updateTx(t) LMICkr920_updateTx(t) 90 | 91 | #undef LMICbandplan_validDR 92 | bit_t LMICkr920_validDR(dr_t dr); 93 | #define LMICbandplan_validDR(dr) LMICkr920_validDR(dr) 94 | 95 | #endif // _lmic_kr920_h_ 96 | -------------------------------------------------------------------------------- /src/lmic/lmic/lmic_bandplan_us915.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2014-2016 IBM Corporation. 3 | * Copyright (c) 2017, 2019-2021 MCCI Corporation. 4 | * All rights reserved. 5 | * 6 | * Redistribution and use in source and binary forms, with or without 7 | * modification, are permitted provided that the following conditions are met: 8 | * * Redistributions of source code must retain the above copyright 9 | * notice, this list of conditions and the following disclaimer. 10 | * * Redistributions in binary form must reproduce the above copyright 11 | * notice, this list of conditions and the following disclaimer in the 12 | * documentation and/or other materials provided with the distribution. 13 | * * Neither the name of the nor the 14 | * names of its contributors may be used to endorse or promote products 15 | * derived from this software without specific prior written permission. 16 | * 17 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 18 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 19 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 20 | * DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY 21 | * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 22 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 23 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 24 | * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 26 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 | */ 28 | 29 | #ifndef _lmic_bandplan_us915_h_ 30 | # define _lmic_bandplan_us915_h_ 31 | 32 | // preconditions for lmic_us_like.h 33 | #define LMICuslike_getFirst500kHzDR() (LORAWAN_DR4) 34 | #define LMICuslike_getJoin125kHzDR() (LORAWAN_DR0) 35 | 36 | #ifndef _lmic_us_like_h_ 37 | # include "lmic_us_like.h" 38 | #endif 39 | 40 | // return maximum frame length (including PHY header) for this data rate (us915); 0 --> not valid dr. 41 | uint8_t LMICus915_maxFrameLen(uint8_t dr); 42 | // return maximum frame length (including PHY header) for this data rate; 0 --> not valid dr. 43 | #define LMICbandplan_maxFrameLen(dr) LMICus915_maxFrameLen(dr) 44 | 45 | int8_t LMICus915_pow2dbm(uint8_t mcmd_ladr_p1); 46 | #define pow2dBm(mcmd_ladr_p1) LMICus915_pow2dbm(mcmd_ladr_p1) 47 | 48 | ostime_t LMICus915_dr2hsym(uint8_t dr); 49 | #define dr2hsym(dr) LMICus915_dr2hsym(dr) 50 | 51 | 52 | #define LMICbandplan_getInitialDrJoin() (LORAWAN_DR0) 53 | 54 | void LMICus915_setBcnRxParams(void); 55 | #define LMICbandplan_setBcnRxParams() LMICus915_setBcnRxParams() 56 | 57 | u4_t LMICus915_convFreq(xref2cu1_t ptr); 58 | #define LMICbandplan_convFreq(ptr) LMICus915_convFreq(ptr) 59 | 60 | void LMICus915_initJoinLoop(void); 61 | #define LMICbandplan_initJoinLoop() LMICus915_initJoinLoop() 62 | 63 | void LMICus915_setRx1Params(void); 64 | #define LMICbandplan_setRx1Params() LMICus915_setRx1Params() 65 | 66 | void LMICus915_updateTx(ostime_t txbeg); 67 | #define LMICbandplan_updateTx(txbeg) LMICus915_updateTx(txbeg) 68 | 69 | #undef LMICbandplan_validDR 70 | bit_t LMICus915_validDR(dr_t dr); 71 | #define LMICbandplan_validDR(dr) LMICus915_validDR(dr) 72 | 73 | #endif // _lmic_bandplan_us915_h_ 74 | -------------------------------------------------------------------------------- /src/lmic/lmic/lmic_channelshuffle.c: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | Module: lmic_channelshuffle.c 4 | 5 | Function: 6 | Channel scheduling without replacement. 7 | 8 | Copyright and License: 9 | This file copyright (C) 2021 by 10 | 11 | MCCI Corporation 12 | 3520 Krums Corners Road 13 | Ithaca, NY 14850 14 | 15 | See accompanying LICENSE file for copyright and license information. 16 | 17 | Author: 18 | Terry Moore, MCCI Corporation April 2021 19 | 20 | */ 21 | 22 | #include "lmic.h" 23 | #include 24 | 25 | /****************************************************************************\ 26 | | 27 | | Manifest constants and local declarations. 28 | | 29 | \****************************************************************************/ 30 | 31 | static unsigned sidewaysSum16(const uint16_t *pMask, uint16_t nEntries); 32 | static unsigned findNthSetBit(const uint16_t *pMask, uint16_t bitnum); 33 | 34 | /****************************************************************************\ 35 | | 36 | | Read-only data. 37 | | 38 | \****************************************************************************/ 39 | 40 | /****************************************************************************\ 41 | | 42 | | Variables. 43 | | 44 | \****************************************************************************/ 45 | 46 | /* 47 | 48 | Name: LMIC_findNextChannel() 49 | 50 | Function: 51 | Scan a shuffle mask, and select a channel (without replacement). 52 | 53 | Definition: 54 | int LMIC_findNextChannel( 55 | uint16_t *pShuffleMask, 56 | const uint16_t *pEnableMask, 57 | uint16_t nEntries, 58 | int lastChannel 59 | ); 60 | 61 | Description: 62 | pShuffleMask and pEnableMask are bit vectors. Channels correspond to 63 | bits in little-endian order; entry [0] has channels 0 through 15, entry 64 | [1] channels 16 through 31, and so forth. nEntries specifies the number 65 | of entries in the mask vectors. The enable mask is 1 for a given channel 66 | if that channel is eligible for selection, 0 otherwise. 67 | 68 | This routine selects channels from the shuffle mask until all entries 69 | are exhausted; it then refreshes the shuffle mask from the enable mask. 70 | 71 | If it refreshes the channel mask, lastChannel is taken as a channel number 72 | that is to be avoided in the next selection. (This is to avoid back-to-back 73 | use of a channel across a refresh boundary.) Otherwise lastChannel is 74 | ignored. This avoidance can be suppresed by setting lastChannel to -1. 75 | If only one channel is enabled, lastChannel is also ignored. If lastChannel 76 | is actually disabled, lastChannel is also ignored. 77 | 78 | Returns: 79 | A channel number, in 0 .. nEntries-1, or -1 if the enable mask is 80 | identically zero. 81 | 82 | Notes: 83 | This routine is somewhat optimized for AVR processors, which don't have 84 | multi-bit shifts. 85 | 86 | */ 87 | 88 | int LMIC_findNextChannel( 89 | uint16_t *pShuffleMask, 90 | const uint16_t *pEnableMask, 91 | uint16_t nEntries, 92 | int lastChannel 93 | ) { 94 | unsigned nSet16; 95 | uint16_t saveLastChannelVal; 96 | 97 | // in case someone has changed the enable mask, update 98 | // the shuffle mask so there are no disable bits set. 99 | for (unsigned i = 0; i < nEntries; ++i) { 100 | pShuffleMask[i] &= pEnableMask[i]; 101 | } 102 | 103 | // count the set bits in the shuffle mask (with a factor of 16 for speed) 104 | nSet16 = sidewaysSum16(pShuffleMask, nEntries); 105 | 106 | // if zero, copy the enable mask to the shuffle mask, and recount 107 | if (nSet16 == 0) { 108 | memcpy(pShuffleMask, pEnableMask, nEntries * sizeof(*pShuffleMask)); 109 | nSet16 = sidewaysSum16(pShuffleMask, nEntries); 110 | } else { 111 | // don't try to skip the last channel because it can't be chosen. 112 | lastChannel = -1; 113 | } 114 | 115 | // if still zero, return -1. 116 | if (nSet16 == 0) { 117 | return -1; 118 | } 119 | 120 | // if we have to skip a channel, and we have more than one choice, turn off 121 | // the last channel bit. Post condition: if we really clered a bit, 122 | // saveLastChannelVal will be non-zero. 123 | saveLastChannelVal = 0; 124 | if (nSet16 > 16 && lastChannel >= 0 && lastChannel <= (int)(nEntries * 16)) { 125 | uint16_t const saveLastChannelMask = (1 << (lastChannel & 0xF)); 126 | 127 | saveLastChannelVal = pShuffleMask[lastChannel >> 4] & saveLastChannelMask; 128 | pShuffleMask[lastChannel >> 4] &= ~saveLastChannelMask; 129 | 130 | // if we cleared a bit, reduce the count. 131 | if (saveLastChannelVal > 0) 132 | nSet16 -= 16; 133 | } 134 | 135 | if (saveLastChannelVal == 0) { 136 | // We didn't eliminate a channel, so we don't have to worry. 137 | lastChannel = -1; 138 | } 139 | 140 | // get a random number 141 | unsigned choice = os_getRndU2() % ((uint16_t)nSet16 >> 4); 142 | 143 | // choose a bit based on set bit 144 | unsigned channel = findNthSetBit(pShuffleMask, choice); 145 | pShuffleMask[channel / 16] ^= (1 << (channel & 0xF)); 146 | 147 | // handle channel skip 148 | if (lastChannel >= 0) { 149 | pShuffleMask[lastChannel >> 4] |= saveLastChannelVal; 150 | } 151 | return channel; 152 | } 153 | 154 | static unsigned sidewaysSum16(const uint16_t *pMask, uint16_t nEntries) { 155 | unsigned result; 156 | 157 | result = 0; 158 | for (; nEntries > 0; --nEntries, ++pMask) 159 | { 160 | uint16_t v = *pMask; 161 | 162 | // the following is an adaptation of Knuth 7.1.3 (62). To avoid 163 | // lots of shifts (slow on AVR, and code intensive) and table lookups, 164 | // we sum popc * 16, then divide by 16. 165 | 166 | // sum adjacent bits, making a series of 2-bit sums 167 | v = v - ((v >> 1) & 0x5555u); 168 | v = (v & 0x3333u) + ((v >> 2) & 0x3333u); 169 | // this assumes multiplies are essentialy free; 170 | v = (v & 0xF0F0u) + ((v & 0x0F0Fu) * 16u); 171 | // Accumulate result, but note it's times 16. 172 | // AVR compiler should optimize the x8 shift. 173 | result += (v & 0xFF) + (v >> 8); 174 | } 175 | 176 | // 177 | return result; 178 | } 179 | 180 | static unsigned findNthSetBit(const uint16_t *pMask, uint16_t bitnum) { 181 | unsigned result; 182 | result = 0; 183 | bitnum = bitnum * 16; 184 | for (;; result += 16) { 185 | uint16_t m = *pMask++; 186 | if (m == 0) 187 | continue; 188 | uint16_t v = m - ((m >> 1) & 0x5555u); 189 | v = (v & 0x3333u) + ((v >> 2) & 0x3333u); 190 | // this assumes multiplies are essentialy free; 191 | v = (v & 0xF0F0u) + ((v & 0x0F0Fu) * 16u); 192 | // Accumulate result, but note it's times 16. 193 | // AVR compiler should optimize the x8 shift. 194 | v = (v & 0xFF) + (v >> 8); 195 | if (v <= bitnum) 196 | bitnum -= v; 197 | else { 198 | // the selected bit is in this word. We need to count. 199 | while (bitnum > 0) { 200 | m &= m - 1; 201 | bitnum -= 16; 202 | } 203 | // now the lsb of m is our choice. 204 | // get a mask, then use Knuth 7.1.3 (59) to find the 205 | // bit number. 206 | m &= -m; 207 | result += ((m & 0x5555u) ? 0 : 1) 208 | + ((m & 0x3333u) ? 0 : 2) 209 | + ((m & 0x0F0Fu) ? 0 : 4) 210 | + ((m & 0x00FFu) ? 0 : 8) 211 | ; 212 | break; 213 | } 214 | } 215 | 216 | return result; 217 | } -------------------------------------------------------------------------------- /src/lmic/lmic/lmic_compat.h: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | Module: lmic_compat.h 4 | 5 | Function: 6 | Symbols that are defined for backward compatibility 7 | 8 | Copyright notice and license info: 9 | See LICENSE file accompanying this project. 10 | 11 | Author: 12 | Terry Moore, MCCI Corporation January 2020 13 | 14 | Description: 15 | This include file centralizes backwards compatibility 16 | definitions. The idea is to centralize the decision, 17 | so it's clear as to what's deprecated. 18 | 19 | */ 20 | 21 | #ifndef _lmic_compat_h_ /* prevent multiple includes */ 22 | #define _lmic_compat_h_ 23 | 24 | #ifdef __cplusplus 25 | extern "C"{ 26 | #endif 27 | 28 | #ifndef ARDUINO_LMIC_VERSION 29 | # error "This file is normally included from lmic.h, not stand alone" 30 | #endif 31 | 32 | #define LMIC_DEPRECATE(m) _Pragma(#m) 33 | 34 | #if ! defined(LMIC_REGION_au921) && ARDUINO_LMIC_VERSION < ARDUINO_LMIC_VERSION_CALC(5,0,0,0) 35 | # define LMIC_REGION_au921 LMIC_DEPRECATE(GCC warning "LMIC_REGION_au921 is deprecated, EOL at V5, use LMIC_REGION_au915") \ 36 | LMIC_REGION_au915 37 | 38 | // Frequency plan symbols 39 | # define AU921_DR_SF12 LMIC_DEPRECATE(GCC warning "A921 symbols are deprecated EOL V5, use AU915") AU915_DR_SF12 40 | # define AU921_DR_SF11 LMIC_DEPRECATE(GCC warning "A921 symbols are deprecated EOL V5, use AU915") AU915_DR_SF11 41 | # define AU921_DR_SF10 LMIC_DEPRECATE(GCC warning "A921 symbols are deprecated EOL V5, use AU915") AU915_DR_SF10 42 | # define AU921_DR_SF9 LMIC_DEPRECATE(GCC warning "A921 symbols are deprecated EOL V5, use AU915") AU915_DR_SF9 43 | # define AU921_DR_SF8 LMIC_DEPRECATE(GCC warning "A921 symbols are deprecated EOL V5, use AU915") AU915_DR_SF8 44 | # define AU921_DR_SF7 LMIC_DEPRECATE(GCC warning "A921 symbols are deprecated EOL V5, use AU915") AU915_DR_SF7 45 | # define AU921_DR_SF8C LMIC_DEPRECATE(GCC warning "A921 symbols are deprecated EOL V5, use AU915") AU915_DR_SF8C 46 | # define AU921_DR_NONE LMIC_DEPRECATE(GCC warning "A921 symbols are deprecated EOL V5, use AU915") AU915_DR_NONE 47 | # define AU921_DR_SF12CR LMIC_DEPRECATE(GCC warning "A921 symbols are deprecated EOL V5, use AU915") AU915_DR_SF12CR 48 | # define AU921_DR_SF11CR LMIC_DEPRECATE(GCC warning "A921 symbols are deprecated EOL V5, use AU915") AU915_DR_SF11CR 49 | # define AU921_DR_SF10CR LMIC_DEPRECATE(GCC warning "A921 symbols are deprecated EOL V5, use AU915") AU915_DR_SF10CR 50 | # define AU921_DR_SF9CR LMIC_DEPRECATE(GCC warning "A921 symbols are deprecated EOL V5, use AU915") AU915_DR_SF9CR 51 | # define AU921_DR_SF8CR LMIC_DEPRECATE(GCC warning "A921 symbols are deprecated EOL V5, use AU915") AU915_DR_SF8CR 52 | # define AU921_DR_SF7CR LMIC_DEPRECATE(GCC warning "A921 symbols are deprecated EOL V5, use AU915") AU915_DR_SF7CR 53 | # define AU921_125kHz_UPFBASE LMIC_DEPRECATE(GCC warning "A921 symbols are deprecated EOL V5, use AU915") AU915_125kHz_UPFBASE 54 | # define AU921_125kHz_UPFSTEP LMIC_DEPRECATE(GCC warning "A921 symbols are deprecated EOL V5, use AU915") AU915_125kHz_UPFSTEP 55 | # define AU921_500kHz_UPFBASE LMIC_DEPRECATE(GCC warning "A921 symbols are deprecated EOL V5, use AU915") AU915_500kHz_UPFBASE 56 | # define AU921_500kHz_UPFSTEP LMIC_DEPRECATE(GCC warning "A921 symbols are deprecated EOL V5, use AU915") AU915_500kHz_UPFSTEP 57 | # define AU921_500kHz_DNFBASE LMIC_DEPRECATE(GCC warning "A921 symbols are deprecated EOL V5, use AU915") AU915_500kHz_DNFBASE 58 | # define AU921_500kHz_DNFSTEP LMIC_DEPRECATE(GCC warning "A921 symbols are deprecated EOL V5, use AU915") AU915_500kHz_DNFSTEP 59 | # define AU921_FREQ_MIN LMIC_DEPRECATE(GCC warning "A921 symbols are deprecated EOL V5, use AU915") AU915_FREQ_MIN 60 | # define AU921_FREQ_MAX LMIC_DEPRECATE(GCC warning "A921 symbols are deprecated EOL V5, use AU915") AU915_FREQ_MAX 61 | # define AU921_TX_EIRP_MAX_DBM LMIC_DEPRECATE(GCC warning "A921 symbols are deprecated EOL V5, use AU915") AU915_TX_EIRP_MAX_DBM 62 | # define AU921_INITIAL_TxParam_UplinkDwellTime LMIC_DEPRECATE(GCC warning "A921 symbols are deprecated EOL V5, use AU915") AU915_INITIAL_TxParam_UplinkDwellTime 63 | # define AU921_UPLINK_DWELL_TIME_osticks LMIC_DEPRECATE(GCC warning "A921 symbols are deprecated EOL V5, use AU915") AU915_UPLINK_DWELL_TIME_osticks 64 | # define DR_PAGE_AU921 LMIC_DEPRECATE(GCC warning "A921 symbols are deprecated EOL V5, use AU915") DR_PAGE_AU915 65 | # define AU921_LMIC_REGION_EIRP LMIC_DEPRECATE(GCC warning "A921 symbols are deprecated EOL V5, use AU915") AU915_LMIC_REGION_EIRP 66 | #endif 67 | 68 | #ifdef __cplusplus 69 | } 70 | #endif 71 | 72 | #endif /* _lmic_compat_h_ */ 73 | -------------------------------------------------------------------------------- /src/lmic/lmic/lmic_compliance.h: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | Module: lmic_compliance.h 4 | 5 | Function: 6 | Internal header file for compliance-related work. 7 | 8 | Copyright notice and license info: 9 | See LICENSE file accompanying this project. 10 | 11 | Author: 12 | Terry Moore, MCCI Corporation March 2019 13 | 14 | Description: 15 | This header file allows us to break up the compliance 16 | functions into multiple .c files if we wish. 17 | 18 | */ 19 | 20 | #ifndef _lmic_compliance_h_ /* prevent multiple includes */ 21 | #define _lmic_compliance_h_ 22 | 23 | #ifdef __cplusplus 24 | extern "C"{ 25 | #endif 26 | 27 | #ifndef _lmic_h_ 28 | # include "lmic.h" 29 | #endif 30 | 31 | #include 32 | #include 33 | 34 | typedef struct lmic_compliance_s lmic_compliance_t; 35 | 36 | // concrete type for the state enumeration for the compliance engine. 37 | typedef uint8_t lmic_compliance_state_t; 38 | 39 | enum lmic_compliance_state_e { 40 | LMIC_COMPLIANCE_STATE_IDLE = 0, // app state 41 | LMIC_COMPLIANCE_STATE_STOPPING = 1, // transitioning back to app 42 | LMIC_COMPLIANCE_STATE_ACTIVATING = 2, // transitioning to compliance state 43 | LMIC_COMPLIANCE_STATE_ACTIVE = 3, // in compliance state 44 | }; 45 | 46 | // return true if a state value indicates that the FSM is active. 47 | static inline bool 48 | lmic_compliance_state_IsActive(lmic_compliance_state_t s) { 49 | return s >= LMIC_COMPLIANCE_STATE_ACTIVATING; 50 | } 51 | 52 | // events from the outside world to the FSM 53 | typedef uint8_t lmic_compliance_eventflags_t; 54 | 55 | enum lmic_compliance_eventflags_e { 56 | LMIC_COMPLIANCE_EVENT_ACTIVATE = 1u << 0, 57 | LMIC_COMPLIANCE_EVENT_DEACTIVATE = 1u << 1, 58 | LMIC_COMPLIANCE_EVENT_TIMER_EXPIRED = 1u << 2, 59 | LMIC_COMPLIANCE_EVENT_UPLINK_COMPLETE = 1u << 3, 60 | LMIC_COMPLIANCE_EVENT_ECHO_REQUEST = 1u << 4, 61 | }; 62 | 63 | typedef uint8_t lmic_compliance_fsmflags_t; 64 | enum lmic_compliance_fsmflags_e { 65 | LMIC_COMPLIANCE_FSM_ACTIVE = 1u << 0, 66 | LMIC_COMPLIANCE_FSM_REENTERED = 1u << 1, 67 | LMIC_COMPLIANCE_FSM_CONFIRM = 1u << 2, 68 | }; 69 | 70 | typedef uint8_t lmic_compliance_fsmstate_t; 71 | enum lmic_compliance_fsmstate_e { 72 | LMIC_COMPLIANCE_FSMSTATE_INITIAL = 0, 73 | LMIC_COMPLIANCE_FSMSTATE_NOCHANGE = 1, 74 | LMIC_COMPLIANCE_FSMSTATE_ACTIVE = 2, 75 | LMIC_COMPLIANCE_FSMSTATE_INACTIVE = 3, 76 | LMIC_COMPLIANCE_FSMSTATE_TESTMODE = 4, // sending test uplinks 77 | LMIC_COMPLIANCE_FSMSTATE_ECHOING = 5, 78 | LMIC_COMPLIANCE_FSMSTATE_REPORTING = 6, 79 | LMIC_COMPLIANCE_FSMSTATE_RECOVERY = 7, 80 | LMIC_COMPLIANCE_FSMSTATE_TXBUSY = 8, 81 | }; 82 | 83 | #define LMIC_COMPLIANCE_FSMSTATE__NAMES \ 84 | "INITIAL", "NOCHANGE", "ACTIVE", "INACTIVE", "TESTMODE", \ 85 | "ECHOING", "REPORTING", "RECOVERY", "TXBUSY" 86 | 87 | typedef struct lmic_compliance_eventcb_s lmic_compliance_eventcb_t; 88 | struct lmic_compliance_eventcb_s { 89 | // save the user's event CB while active. 90 | lmic_event_cb_t *pEventCb; 91 | // save the user's event data while active. 92 | void *pUserData; 93 | }; 94 | 95 | // structure for saving band settings during test 96 | typedef struct lmic_compliance_band_s lmic_compliance_band_t; 97 | struct lmic_compliance_band_s { 98 | u2_t txcap; // saved 1/duty cycle 99 | }; 100 | 101 | // the state of the compliance engine. 102 | struct lmic_compliance_s { 103 | // uint64 104 | // uintptr 105 | osjob_t timerJob; // the job for driving uplinks 106 | osjob_t fsmJob; // job for reevaluating the FSM. 107 | lmic_compliance_eventcb_t saveEvent; // the user's event handler. 108 | 109 | // uint32 110 | 111 | // uint16 112 | #if CFG_LMIC_EU_like 113 | lmic_compliance_band_t saveBands[MAX_BANDS]; 114 | #endif // CFG_LMIC_EU_like 115 | 116 | // we are required to maintain a downlink count 117 | // that is reset on join/test entry and incremented for 118 | // each valid test message. 119 | uint16_t downlinkCount; 120 | 121 | // uint8 122 | 123 | lmic_compliance_state_t state; // current state of compliance engine. 124 | lmic_compliance_eventflags_t eventflags; // incoming events. 125 | lmic_compliance_fsmflags_t fsmFlags; // FSM operational flags 126 | lmic_compliance_fsmstate_t fsmState; // FSM current state 127 | 128 | uint8_t uplinkSize; 129 | uint8_t uplinkMessage[MAX_LEN_PAYLOAD]; 130 | }; 131 | 132 | extern lmic_compliance_t LMIC_Compliance; 133 | 134 | #ifdef __cplusplus 135 | } // extern "C" 136 | #endif 137 | 138 | #endif /* _lmic_compliance_h_ */ -------------------------------------------------------------------------------- /src/lmic/lmic/lmic_env.h: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | Module: lmic_env.h 4 | 5 | Function: 6 | Sets up macros etc. to make things a little easier for portabilty 7 | 8 | Copyright notice and license info: 9 | See LICENSE file accompanying this project. 10 | 11 | Author: 12 | Terry Moore, MCCI Corporation November 2018 13 | 14 | Description: 15 | This file is an adaptation of MCCI's standard IOCTL framework. 16 | We duplicate a bit of functionality that we might get from other 17 | libraries, so that the LMIC library can continue to stand alone. 18 | 19 | */ 20 | 21 | #ifndef _lmic_env_h_ /* prevent multiple includes */ 22 | #define _lmic_env_h_ 23 | 24 | /* 25 | 26 | Macro: LMIC_C_ASSERT() 27 | 28 | Function: 29 | Declaration-like macro that will cause a compile error if arg is FALSE. 30 | 31 | Definition: 32 | LMIC_C_ASSERT( 33 | BOOL fErrorIfFalse 34 | ); 35 | 36 | Description: 37 | This macro, if used where an external reference declarataion is 38 | permitted, will either compile cleanly, or will cause a compilation 39 | error. The results of using this macro where a declaration is not 40 | permitted are unspecified. 41 | 42 | This is different from #if !(fErrorIfFalse) / #error in that the 43 | expression is evaluated by the compiler rather than by the pre- 44 | processor. Therefore things like sizeof() can be used. 45 | 46 | Returns: 47 | No explicit result -- either compiles cleanly or causes a compile 48 | error. 49 | 50 | */ 51 | 52 | #ifndef LMIC_C_ASSERT 53 | # define LMIC_C_ASSERT(e) \ 54 | void LMIC_C_ASSERT__(int LMIC_C_ASSERT_x[(e) ? 1: -1]) 55 | #endif 56 | 57 | /****************************************************************************\ 58 | | 59 | | Define the begin/end declaration tags for C++ co-existance 60 | | 61 | \****************************************************************************/ 62 | 63 | #ifdef __cplusplus 64 | # define LMIC_BEGIN_DECLS extern "C" { 65 | # define LMIC_END_DECLS } 66 | #else 67 | # define LMIC_BEGIN_DECLS /* nothing */ 68 | # define LMIC_END_DECLS /* nothing */ 69 | #endif 70 | 71 | //---------------------------------------------------------------------------- 72 | // Annotations to avoid various "unused" warnings. These must appear as a 73 | // statement in the function body; the macro annotates the variable to quiet 74 | // compiler warnings. The way this is done is compiler-specific, and so these 75 | // definitions are fall-backs, which might be overridden. 76 | // 77 | // Although these are all similar, we don't want extra macro expansions, 78 | // so we define each one explicitly rather than relying on a common macro. 79 | //---------------------------------------------------------------------------- 80 | 81 | // signal that a parameter is intentionally unused. 82 | #ifndef LMIC_UNREFERENCED_PARAMETER 83 | # define LMIC_UNREFERENCED_PARAMETER(v) do { (void) (v); } while (0) 84 | #endif 85 | 86 | // an API parameter is a parameter that is required by an API definition, but 87 | // happens to be unreferenced in this implementation. This is a stronger 88 | // assertion than LMIC_UNREFERENCED_PARAMETER(): this parameter is here 89 | // becuase of an API contract, but we have no use for it in this function. 90 | #ifndef LMIC_API_PARAMETER 91 | # define LMIC_API_PARAMETER(v) do { (void) (v); } while (0) 92 | #endif 93 | 94 | // an intentionally-unreferenced variable. 95 | #ifndef LMIC_UNREFERENCED_VARIABLE 96 | # define LMIC_UNREFERENCED_VARIABLE(v) do { (void) (v); } while (0) 97 | #endif 98 | 99 | // we have three (!) debug levels (LMIC_DEBUG_LEVEL > 0, LMIC_DEBUG_LEVEL > 1, 100 | // and LMIC_X_DEBUG_LEVEL > 0. In each case we might have parameters or 101 | // or varables that are only refereneced at the target debug level. 102 | 103 | // Parameter referenced only if debugging at level > 0. 104 | #ifndef LMIC_DEBUG1_PARAMETER 105 | # if LMIC_DEBUG_LEVEL > 0 106 | # define LMIC_DEBUG1_PARAMETER(v) do { ; } while (0) 107 | # else 108 | # define LMIC_DEBUG1_PARAMETER(v) do { (void) (v); } while (0) 109 | # endif 110 | #endif 111 | 112 | // variable referenced only if debugging at level > 0 113 | #ifndef LMIC_DEBUG1_VARIABLE 114 | # if LMIC_DEBUG_LEVEL > 0 115 | # define LMIC_DEBUG1_VARIABLE(v) do { ; } while (0) 116 | # else 117 | # define LMIC_DEBUG1_VARIABLE(v) do { (void) (v); } while (0) 118 | # endif 119 | #endif 120 | 121 | // parameter referenced only if debugging at level > 1 122 | #ifndef LMIC_DEBUG2_PARAMETER 123 | # if LMIC_DEBUG_LEVEL > 1 124 | # define LMIC_DEBUG2_PARAMETER(v) do { ; } while (0) 125 | # else 126 | # define LMIC_DEBUG2_PARAMETER(v) do { (void) (v); } while (0) 127 | # endif 128 | #endif 129 | 130 | // variable referenced only if debugging at level > 1 131 | #ifndef LMIC_DEBUG2_VARIABLE 132 | # if LMIC_DEBUG_LEVEL > 1 133 | # define LMIC_DEBUG2_VARIABLE(v) do { ; } while (0) 134 | # else 135 | # define LMIC_DEBUG2_VARIABLE(v) do { (void) (v); } while (0) 136 | # endif 137 | #endif 138 | 139 | // parameter referenced only if LMIC_X_DEBUG_LEVEL > 0 140 | #ifndef LMIC_X_DEBUG_PARAMETER 141 | # if LMIC_X_DEBUG_LEVEL > 0 142 | # define LMIC_X_DEBUG_PARAMETER(v) do { ; } while (0) 143 | # else 144 | # define LMIC_X_DEBUG_PARAMETER(v) do { (void) (v); } while (0) 145 | # endif 146 | #endif 147 | 148 | // variable referenced only if LMIC_X_DEBUG_LEVEL > 0 149 | #ifndef LMIC_X_DEBUG_VARIABLE 150 | # if LMIC_X_DEBUG_LEVEL > 0 151 | # define LMIC_X_DEBUG_VARIABLE(v) do { ; } while (0) 152 | # else 153 | # define LMIC_X_DEBUG_VARIABLE(v) do { (void) (v); } while (0) 154 | # endif 155 | #endif 156 | 157 | // parameter referenced only if EV() macro is enabled (which it never is) 158 | // TODO(tmm@mcci.com) take out the EV() framework as it reuqires C++, and 159 | // this code is really C-99 to its bones. 160 | #ifndef LMIC_EV_PARAMETER 161 | # define LMIC_EV_PARAMETER(v) do { (void) (v); } while (0) 162 | #endif 163 | 164 | // variable referenced only if EV() macro is defined. 165 | #ifndef LMIC_EV_VARIABLE 166 | # define LMIC_EV_VARIABLE(v) do { (void) (v); } while (0) 167 | #endif 168 | 169 | /* 170 | 171 | Macro: LMIC_ABI_STD 172 | 173 | Index: Macro: LMIC_ABI_VARARGS 174 | 175 | Function: 176 | Annotation macros to force a particular binary calling sequence. 177 | 178 | Definition: 179 | #define LMIC_ABI_STD compiler-specific 180 | #define LMIC_ABI_VARARGS compiler-specific 181 | 182 | Description: 183 | These macros are used when declaring a function type, and indicate 184 | that a particular calling sequence is to be used. They are normally 185 | used between the type portion of the function declaration and the 186 | name of the function. For example: 187 | 188 | typedef void LMIC_ABI_STD myCallBack_t(void); 189 | 190 | It's important to use this in libraries on platforms with multiple 191 | calling sequences, because different components can be compiled with 192 | different defaults. 193 | 194 | Returns: 195 | Not applicable. 196 | 197 | */ 198 | 199 | /* ABI marker for normal (fixed parameter count) functions -- used for function types */ 200 | #ifndef LMIC_ABI_STD 201 | # ifdef _MSC_VER 202 | # define LMIC_ABI_STD __stdcall 203 | # else 204 | # define LMIC_ABI_STD /* nothing */ 205 | # endif 206 | #endif 207 | 208 | /* ABI marker for VARARG functions -- used for function types */ 209 | #ifndef LMIC_ABI_VARARGS 210 | # ifdef _MSC_VER 211 | # define LMIC_ABI_VARARGS __cdecl 212 | # else 213 | # define LMIC_ABI_VARARGS /* nothing */ 214 | # endif 215 | #endif 216 | 217 | /* 218 | 219 | Macro: LMIC_DECLARE_FUNCTION_WEAK() 220 | 221 | Function: 222 | Declare an external function as a weak reference. 223 | 224 | Definition: 225 | #define LMIC_DECLARE_FUNCTION_WEAK(ReturnType, FunctionName, Params) ... 226 | 227 | Description: 228 | This macro generates a weak reference to the specified function. 229 | 230 | Example: 231 | LMIC_DECLARE_FUNCTION_WEAK(void, onEvent, (ev_t e)); 232 | 233 | This saya that onEvent is a weak external reference. When calling 234 | onEvent, you must always first check whether it's supplied: 235 | 236 | if (onEvent != NULL) 237 | onEvent(e); 238 | 239 | Returns: 240 | This macro expands to a declaration, without a trailing semicolon. 241 | 242 | Notes: 243 | This form allows for compilers that use _Pragma(weak, name) instead 244 | of inline attributes. 245 | 246 | */ 247 | 248 | #define LMIC_DECLARE_FUNCTION_WEAK(a_ReturnType, a_FunctionName, a_Params) \ 249 | a_ReturnType __attribute__((__weak__)) a_FunctionName a_Params 250 | 251 | #endif /* _lmic_env_h_ */ -------------------------------------------------------------------------------- /src/lmic/lmic/lmic_eu_like.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2014-2016 IBM Corporation. 3 | * Copyright (c) 2017, 2019 MCCI Corporation. 4 | * All rights reserved. 5 | * 6 | * Redistribution and use in source and binary forms, with or without 7 | * modification, are permitted provided that the following conditions are met: 8 | * * Redistributions of source code must retain the above copyright 9 | * notice, this list of conditions and the following disclaimer. 10 | * * Redistributions in binary form must reproduce the above copyright 11 | * notice, this list of conditions and the following disclaimer in the 12 | * documentation and/or other materials provided with the distribution. 13 | * * Neither the name of the nor the 14 | * names of its contributors may be used to endorse or promote products 15 | * derived from this software without specific prior written permission. 16 | * 17 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 18 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 19 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 20 | * DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY 21 | * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 22 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 23 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 24 | * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 26 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 | */ 28 | 29 | #ifndef _lmic_eu_like_h_ 30 | # define _lmic_eu_like_h_ 31 | 32 | #ifndef _lmic_h_ 33 | # include "lmic.h" 34 | #endif 35 | 36 | // make sure we want US-like code 37 | #if !CFG_LMIC_EU_like 38 | # error "lmic not configured for EU-like bandplan" 39 | #endif 40 | 41 | // TODO(tmm@mcci.com): this should come from the lmic.h or lorabase.h file; and 42 | // it's probably affected by the fix to this issue: 43 | // https://github.com/mcci-catena/arduino-lmic/issues/2 44 | #define DNW2_SAFETY_ZONE ms2osticks(3000) 45 | 46 | // provide a default for LMICbandplan_isValidBeacon1() 47 | static inline int 48 | LMICeulike_isValidBeacon1(const uint8_t *d) { 49 | return os_rlsbf2(&d[OFF_BCN_CRC1]) != os_crc16(d, OFF_BCN_CRC1); 50 | } 51 | 52 | #define LMICbandplan_isValidBeacon1(pFrame) LMICeulike_isValidBeacon1(pFrame) 53 | 54 | 55 | // provide a default for LMICbandplan_isFSK() 56 | #define LMICbandplan_isFSK() (0) 57 | 58 | // provide a default LMICbandplan_txDoneDoFSK() 59 | void LMICeulike_txDoneFSK(ostime_t delay, osjobcb_t func); 60 | #define LMICbandplan_txDoneFSK(delay, func) LMICeulike_txDoneFSK(delay, func) 61 | 62 | #define LMICbandplan_joinAcceptChannelClear() LMICbandplan_initDefaultChannels(/* normal, not join */ 0) 63 | 64 | enum { BAND_MILLI = 0, BAND_CENTI = 1, BAND_DECI = 2, BAND_AUX = 3 }; 65 | 66 | // there's a CFList on joins for EU-like plans 67 | #define LMICbandplan_hasJoinCFlist() (1) 68 | 69 | /// \brief process CFLists from JoinAccept for EU-like regions 70 | void LMICeulike_processJoinAcceptCFList(void); 71 | /// \brief by default, EU-like plans use LMICeulike_processJoinAcceptCFList 72 | #define LMICbandplan_processJoinAcceptCFList LMICeulike_processJoinAcceptCFList 73 | 74 | #define LMICbandplan_advanceBeaconChannel() \ 75 | do { /* nothing */ } while (0) 76 | 77 | #define LMICbandplan_resetDefaultChannels() \ 78 | do { /* nothing */ } while (0) 79 | 80 | #define LMICbandplan_setSessionInitDefaultChannels() \ 81 | do { LMICbandplan_initDefaultChannels(/* normal, not join */ 0); } while (0) 82 | 83 | bit_t LMICeulike_canMapChannels(u1_t chpage, u2_t chmap); 84 | #define LMICbandplan_canMapChannels(c, m) LMICeulike_canMapChannels(c, m) 85 | 86 | bit_t LMICeulike_mapChannels(u1_t chpage, u2_t chmap); 87 | #define LMICbandplan_mapChannels(c, m) LMICeulike_mapChannels(c, m) 88 | 89 | void LMICeulike_initJoinLoop(u1_t nDefaultChannels, s1_t adrTxPow); 90 | 91 | void LMICeulike_updateTx(ostime_t txbeg); 92 | #define LMICbandplan_updateTx(t) LMICeulike_updateTx(t) 93 | 94 | ostime_t LMICeulike_nextJoinState(uint8_t nDefaultChannels); 95 | 96 | static inline ostime_t LMICeulike_nextJoinTime(ostime_t now) { 97 | return now; 98 | } 99 | #define LMICbandplan_nextJoinTime(now) LMICeulike_nextJoinTime(now) 100 | 101 | #define LMICbandplan_init() \ 102 | do { /* nothing */ } while (0) 103 | 104 | void LMICeulike_saveAdrState(lmic_saved_adr_state_t *pStateBuffer); 105 | #define LMICbandplan_saveAdrState(pState) LMICeulike_saveAdrState(pState) 106 | 107 | bit_t LMICeulike_compareAdrState(const lmic_saved_adr_state_t *pStateBuffer); 108 | #define LMICbandplan_compareAdrState(pState) LMICeulike_compareAdrState(pState) 109 | 110 | void LMICeulike_restoreAdrState(const lmic_saved_adr_state_t *pStateBuffer); 111 | #define LMICbandplan_restoreAdrState(pState) LMICeulike_restoreAdrState(pState) 112 | 113 | // set Rx1 frequency (might be different than uplink). 114 | void LMICeulike_setRx1Freq(void); 115 | 116 | bit_t LMICeulike_isDataRateFeasible(dr_t dr); 117 | #define LMICbandplan_isDataRateFeasible(dr) LMICeulike_isDataRateFeasible(dr) 118 | 119 | 120 | #endif // _lmic_eu_like_h_ 121 | -------------------------------------------------------------------------------- /src/lmic/lmic/lmic_us_like.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2014-2016 IBM Corporation. 3 | * Copyright (c) 2017, 2019 MCCI Corporation. 4 | * All rights reserved. 5 | * 6 | * Redistribution and use in source and binary forms, with or without 7 | * modification, are permitted provided that the following conditions are met: 8 | * * Redistributions of source code must retain the above copyright 9 | * notice, this list of conditions and the following disclaimer. 10 | * * Redistributions in binary form must reproduce the above copyright 11 | * notice, this list of conditions and the following disclaimer in the 12 | * documentation and/or other materials provided with the distribution. 13 | * * Neither the name of the nor the 14 | * names of its contributors may be used to endorse or promote products 15 | * derived from this software without specific prior written permission. 16 | * 17 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 18 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 19 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 20 | * DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY 21 | * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 22 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 23 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 24 | * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 26 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 | */ 28 | 29 | #ifndef _lmic_us_like_h_ 30 | # define _lmic_us_like_h_ 31 | 32 | // make sure we want US-like code 33 | #if !CFG_LMIC_US_like 34 | # error "lmic not configured for us-like bandplan" 35 | #endif 36 | 37 | // TODO(tmm@mcci.com): this should come from the lmic.h or lorabase.h file; and 38 | // it's probably affected by the fix to this issue: 39 | // https://github.com/mcci-catena/arduino-lmic/issues/2 40 | #define DNW2_SAFETY_ZONE ms2osticks(750) 41 | 42 | #define IS_CHANNEL_125khz(c) (c<64) 43 | #define IS_CHANNEL_500khz(c) (c>=64 && c<72) 44 | #define ENABLED_CHANNEL(chnl) ((LMIC.channelMap[(chnl >> 4)] & (1<<(chnl & 0x0F))) != 0) 45 | 46 | // library functions: called from bandplan 47 | void LMICuslike_initJoinLoop(void); 48 | 49 | // provide the isValidBeacon1 function -- int for bool. 50 | static inline int 51 | LMICuslike_isValidBeacon1(const uint8_t *d) { 52 | return os_rlsbf2(&d[OFF_BCN_CRC1]) != os_crc16(d, OFF_BCN_CRC1); 53 | } 54 | 55 | #define LMICbandplan_isValidBeacon1(pFrame) LMICuslike_isValidBeacon1(pFrame) 56 | 57 | // provide a default for LMICbandplan_isFSK() 58 | #define LMICbandplan_isFSK() (0) 59 | 60 | // provide a default LMICbandplan_txDoneFSK() 61 | #define LMICbandplan_txDoneFSK(delay, func) do { } while (0) 62 | 63 | // provide a default LMICbandplan_joinAcceptChannelClear() 64 | #define LMICbandplan_joinAcceptChannelClear() do { } while (0) 65 | 66 | /// \brief there's a CFList on joins for US-like plans 67 | #define LMICbandplan_hasJoinCFlist() (1) 68 | 69 | /// \brief process CFLists from JoinAccept for EU-like regions 70 | void LMICuslike_processJoinAcceptCFList(void); 71 | /// \brief by default, EU-like plans use LMICuslike_processJoinAcceptCFList 72 | #define LMICbandplan_processJoinAcceptCFList LMICuslike_processJoinAcceptCFList 73 | 74 | 75 | #define LMICbandplan_advanceBeaconChannel() \ 76 | do { LMIC.bcnChnl = (LMIC.bcnChnl+1) & 7; } while (0) 77 | 78 | // TODO(tmm@mcci.com): decide whether we want to do this on every 79 | // reset or just restore the last sub-band selected by the user. 80 | #define LMICbandplan_resetDefaultChannels() \ 81 | LMICbandplan_initDefaultChannels(/* normal */ 0) 82 | 83 | void LMICuslike_initDefaultChannels(bit_t fJoin); 84 | #define LMICbandplan_initDefaultChannels(fJoin) LMICuslike_initDefaultChannels(fJoin) 85 | 86 | #define LMICbandplan_setSessionInitDefaultChannels() \ 87 | do { /* nothing */} while (0) 88 | 89 | bit_t LMICuslike_canMapChannels(u1_t chpage, u2_t chmap); 90 | #define LMICbandplan_canMapChannels(chpage, chmap) LMICuslike_canMapChannels(chpage, chmap) 91 | 92 | bit_t LMICuslike_mapChannels(u1_t chpage, u2_t chmap); 93 | #define LMICbandplan_mapChannels(chpage, chmap) LMICuslike_mapChannels(chpage, chmap) 94 | 95 | ostime_t LMICuslike_nextTx(ostime_t now); 96 | #define LMICbandplan_nextTx(now) LMICuslike_nextTx(now) 97 | 98 | ostime_t LMICuslike_nextJoinState(void); 99 | #define LMICbandplan_nextJoinState() LMICuslike_nextJoinState(); 100 | 101 | static inline ostime_t LMICuslike_nextJoinTime(ostime_t now) { 102 | return now; 103 | } 104 | #define LMICbandplan_nextJoinTime(now) LMICuslike_nextJoinTime(now) 105 | 106 | #define LMICbandplan_init() \ 107 | do { /* nothing */ } while (0) 108 | 109 | void LMICuslike_saveAdrState(lmic_saved_adr_state_t *pStateBuffer); 110 | #define LMICbandplan_saveAdrState(pState) LMICuslike_saveAdrState(pState) 111 | 112 | bit_t LMICuslike_compareAdrState(const lmic_saved_adr_state_t *pStateBuffer); 113 | #define LMICbandplan_compareAdrState(pState) LMICuslike_compareAdrState(pState) 114 | 115 | void LMICuslike_restoreAdrState(const lmic_saved_adr_state_t *pStateBuffer); 116 | #define LMICbandplan_restoreAdrState(pState) LMICuslike_restoreAdrState(pState) 117 | 118 | bit_t LMICuslike_isDataRateFeasible(dr_t dr); 119 | #define LMICbandplan_isDataRateFeasible(dr) LMICuslike_isDataRateFeasible(dr) 120 | 121 | #endif // _lmic_us_like_h_ 122 | -------------------------------------------------------------------------------- /src/lmic/lmic/lmic_util.h: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | Module: lmic_util.h 4 | 5 | Function: 6 | Declare encoding and decoding utilities for LMIC clients. 7 | 8 | Copyright & License: 9 | See accompanying LICENSE file. 10 | 11 | Author: 12 | Terry Moore, MCCI September 2018 13 | 14 | */ 15 | 16 | #ifndef _LMIC_UTIL_H_ 17 | # define _LMIC_UTIL_H_ 18 | 19 | #ifdef __cplusplus 20 | extern "C" { 21 | #endif 22 | 23 | #include 24 | 25 | uint16_t LMIC_f2sflt16(float); 26 | uint16_t LMIC_f2sflt12(float); 27 | uint16_t LMIC_f2uflt16(float); 28 | uint16_t LMIC_f2uflt12(float); 29 | 30 | #ifdef __cplusplus 31 | } 32 | #endif 33 | 34 | #endif /* _LMIC_UTIL_H_ */ 35 | -------------------------------------------------------------------------------- /src/lmic/lmic/lorabase_as923.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2014-2016 IBM Corporation. 3 | * All rights reserved. 4 | * 5 | * Copyright (c) 2017 MCCI Corporation 6 | * All rights reserved. 7 | * 8 | * Redistribution and use in source and binary forms, with or without 9 | * modification, are permitted provided that the following conditions are met: 10 | * * Redistributions of source code must retain the above copyright 11 | * notice, this list of conditions and the following disclaimer. 12 | * * Redistributions in binary form must reproduce the above copyright 13 | * notice, this list of conditions and the following disclaimer in the 14 | * documentation and/or other materials provided with the distribution. 15 | * * Neither the name of the nor the 16 | * names of its contributors may be used to endorse or promote products 17 | * derived from this software without specific prior written permission. 18 | * 19 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 20 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 21 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 22 | * DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY 23 | * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 24 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 25 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 26 | * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 28 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 | */ 30 | 31 | #ifndef _lorabase_as923_h_ 32 | #define _lorabase_as923_h_ 33 | 34 | #ifndef _LMIC_CONFIG_PRECONDITIONS_H_ 35 | # include "lmic_config_preconditions.h" 36 | #endif 37 | 38 | /****************************************************************************\ 39 | | 40 | | Basic definitions for AS923 (always in scope) 41 | | 42 | \****************************************************************************/ 43 | 44 | enum _dr_as923_t { 45 | AS923_DR_SF12 = 0, 46 | AS923_DR_SF11, 47 | AS923_DR_SF10, 48 | AS923_DR_SF9, 49 | AS923_DR_SF8, 50 | AS923_DR_SF7, 51 | AS923_DR_SF7B, 52 | AS923_DR_FSK, 53 | AS923_DR_NONE 54 | }; 55 | 56 | // Bands: 57 | // g1 : 1% 16dBm 58 | // freq band datarates 59 | enum { 60 | AS923_F1 = 923200000, // g1 SF7-12 61 | AS923_F2 = 923400000, // g1 SF7-12 62 | AS923_FDOWN = 923200000, // (RX2 freq, DR2) 63 | AS923_FBCN = 923400000, // default BCN, DR3 64 | AS923_FPING = 923400000, // default ping, DR3 65 | }; 66 | enum { 67 | AS923_FREQ_MIN = 915000000, 68 | AS923_FREQ_MAX = 928000000 69 | }; 70 | enum { 71 | AS923_JP_TX_EIRP_MAX_DBM = 13, // 13 dBm = 19.95mW < 20mW 72 | AS923_TX_EIRP_MAX_DBM = 16 // 16 dBm 73 | }; 74 | enum { DR_PAGE_AS923 = 0x10 * (LMIC_REGION_as923 - 1) }; 75 | 76 | enum { AS923_LMIC_REGION_EIRP = 1 }; // region uses EIRP 77 | 78 | enum { AS923JP_LBT_US = 5000 }; // microseconds of LBT time -- 5000 ==> 79 | // 5 ms. We use us rather than ms for 80 | // future 128us support, and just for 81 | // backward compatibility -- there 82 | // is code that uses the _US constant, 83 | // and it's awkward to break it. 84 | 85 | enum { AS923JP_LBT_DB_MAX = -80 }; // maximum channel strength in dB; if TX 86 | // we measure more than this, we don't tx. 87 | 88 | // AS923 v1.1, all channels face a 1% duty cycle. So this will have to change 89 | // in the future via a config. But this code base needs major changes for 90 | // v1.1 in any case. 91 | enum { AS923_V102_TX_CAP = 100 }; // v1.0.2 allows 100% 92 | 93 | #ifndef AS923_TX_CAP 94 | # define AS923_TX_CAP AS923_V102_TX_CAP 95 | #endif 96 | 97 | // TxParam defaults 98 | enum { 99 | // initial value of UplinkDwellTime before TxParamSetupReq received. 100 | AS923_INITIAL_TxParam_UplinkDwellTime = 1, 101 | // initial value of DownlinkDwellTime before TxParamSetupReq received. 102 | AS923_INITIAL_TxParam_DownlinkDwellTime = 1, 103 | AS923_UPLINK_DWELL_TIME_osticks = sec2osticks(20), 104 | }; 105 | 106 | #endif /* _lorabase_as923_h_ */ 107 | -------------------------------------------------------------------------------- /src/lmic/lmic/lorabase_au915.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2014-2016 IBM Corporation. 3 | * All rights reserved. 4 | * 5 | * Copyright (c) 2017 MCCI Corporation 6 | * All rights reserved. 7 | * 8 | * Redistribution and use in source and binary forms, with or without 9 | * modification, are permitted provided that the following conditions are met: 10 | * * Redistributions of source code must retain the above copyright 11 | * notice, this list of conditions and the following disclaimer. 12 | * * Redistributions in binary form must reproduce the above copyright 13 | * notice, this list of conditions and the following disclaimer in the 14 | * documentation and/or other materials provided with the distribution. 15 | * * Neither the name of the nor the 16 | * names of its contributors may be used to endorse or promote products 17 | * derived from this software without specific prior written permission. 18 | * 19 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 20 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 21 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 22 | * DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY 23 | * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 24 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 25 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 26 | * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 28 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 | */ 30 | 31 | #ifndef _lorabase_au915_h_ 32 | #define _lorabase_au915_h_ 33 | 34 | #ifndef _LMIC_CONFIG_PRECONDITIONS_H_ 35 | # include "lmic_config_preconditions.h" 36 | #endif 37 | 38 | /****************************************************************************\ 39 | | 40 | | Basic definitions for AU 915 (always in scope) 41 | | 42 | \****************************************************************************/ 43 | 44 | // Frequency plan for AU 915 MHz 45 | enum _dr_au915_t { 46 | AU915_DR_SF12 = 0, 47 | AU915_DR_SF11, 48 | AU915_DR_SF10, 49 | AU915_DR_SF9, 50 | AU915_DR_SF8, 51 | AU915_DR_SF7, 52 | AU915_DR_SF8C, 53 | AU915_DR_NONE, 54 | // Devices behind a router: 55 | AU915_DR_SF12CR = 8, 56 | AU915_DR_SF11CR, 57 | AU915_DR_SF10CR, 58 | AU915_DR_SF9CR, 59 | AU915_DR_SF8CR, 60 | AU915_DR_SF7CR 61 | }; 62 | 63 | // Default frequency plan for AU 915MHz 64 | enum { 65 | AU915_125kHz_UPFBASE = 915200000, 66 | AU915_125kHz_UPFSTEP = 200000, 67 | AU915_500kHz_UPFBASE = 915900000, 68 | AU915_500kHz_UPFSTEP = 1600000, 69 | AU915_500kHz_DNFBASE = 923300000, 70 | AU915_500kHz_DNFSTEP = 600000 71 | }; 72 | enum { 73 | AU915_FREQ_MIN = 915000000, 74 | AU915_FREQ_MAX = 928000000 75 | }; 76 | enum { 77 | AU915_TX_EIRP_MAX_DBM = 30 // 30 dBm 78 | }; 79 | enum { 80 | // initial value of UplinkDwellTime before TxParamSetupReq received. 81 | AU915_INITIAL_TxParam_UplinkDwellTime = 1, 82 | AU915_UPLINK_DWELL_TIME_osticks = sec2osticks(20), 83 | }; 84 | 85 | enum { DR_PAGE_AU915 = 0x10 * (LMIC_REGION_au915 - 1) }; 86 | 87 | enum { AU915_LMIC_REGION_EIRP = 1 }; // region uses EIRP 88 | 89 | #endif /* _lorabase_au915_h_ */ -------------------------------------------------------------------------------- /src/lmic/lmic/lorabase_eu868.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2014-2016 IBM Corporation. 3 | * All rights reserved. 4 | * 5 | * Copyright (c) 2017 MCCI Corporation 6 | * All rights reserved. 7 | * 8 | * Redistribution and use in source and binary forms, with or without 9 | * modification, are permitted provided that the following conditions are met: 10 | * * Redistributions of source code must retain the above copyright 11 | * notice, this list of conditions and the following disclaimer. 12 | * * Redistributions in binary form must reproduce the above copyright 13 | * notice, this list of conditions and the following disclaimer in the 14 | * documentation and/or other materials provided with the distribution. 15 | * * Neither the name of the nor the 16 | * names of its contributors may be used to endorse or promote products 17 | * derived from this software without specific prior written permission. 18 | * 19 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 20 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 21 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 22 | * DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY 23 | * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 24 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 25 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 26 | * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 28 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 | */ 30 | 31 | #ifndef _lorabase_eu868_h_ 32 | #define _lorabase_eu868_h_ 33 | 34 | #ifndef _LMIC_CONFIG_PRECONDITIONS_H_ 35 | # include "lmic_config_preconditions.h" 36 | #endif 37 | 38 | /****************************************************************************\ 39 | | 40 | | Basic definitions for EU868 (always in scope) 41 | | 42 | \****************************************************************************/ 43 | 44 | // 45 | // Default frequency plan for EU 868MHz ISM band 46 | // data rates 47 | // this is a little confusing: the integer values of these constants are the 48 | // DataRates from the LoRaWAN Regional Parmaeter spec. The names are just 49 | // convenient indications, so we can use them in the rare case that we need to 50 | // choose a DataRate by SF and configuration, not by DR code. 51 | 52 | enum _dr_eu868_t { 53 | EU868_DR_SF12 = 0, 54 | EU868_DR_SF11, 55 | EU868_DR_SF10, 56 | EU868_DR_SF9, 57 | EU868_DR_SF8, 58 | EU868_DR_SF7, 59 | EU868_DR_SF7B, 60 | EU868_DR_FSK, 61 | EU868_DR_NONE 62 | }; 63 | 64 | // Bands: 65 | // g1 : 1% 14dBm 66 | // g2 : 0.1% 14dBm 67 | // g3 : 10% 27dBm 68 | // freq band datarates 69 | enum { 70 | EU868_F1 = 868100000, // g1 SF7-12 71 | EU868_F2 = 868300000, // g1 SF7-12 FSK SF7/250 72 | EU868_F3 = 868500000, // g1 SF7-12 73 | EU868_F4 = 868850000, // g2 SF7-12 74 | EU868_F5 = 869050000, // g2 SF7-12 75 | EU868_F6 = 869525000, // g3 SF7-12 76 | EU868_J4 = 864100000, // g2 SF7-12 used during join 77 | EU868_J5 = 864300000, // g2 SF7-12 ditto 78 | EU868_J6 = 864500000, // g2 SF7-12 ditto 79 | }; 80 | enum { 81 | EU868_FREQ_MIN = 863000000, 82 | EU868_FREQ_MAX = 870000000 83 | }; 84 | enum { 85 | EU868_TX_EIRP_MAX_DBM = 16 // 16 dBm EIRP. So subtract 3 dBm for a 3 dBi antenna. 86 | }; 87 | 88 | enum { EU868_LMIC_REGION_EIRP = 1 }; // region uses EIRP 89 | 90 | enum { DR_PAGE_EU868 = 0x10 * (LMIC_REGION_eu868 - 1) }; 91 | 92 | #endif /* _lorabase_eu868_h_ */ -------------------------------------------------------------------------------- /src/lmic/lmic/lorabase_in866.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2014-2016 IBM Corporation. 3 | * All rights reserved. 4 | * 5 | * Copyright (c) 2017 MCCI Corporation 6 | * All rights reserved. 7 | * 8 | * Redistribution and use in source and binary forms, with or without 9 | * modification, are permitted provided that the following conditions are met: 10 | * * Redistributions of source code must retain the above copyright 11 | * notice, this list of conditions and the following disclaimer. 12 | * * Redistributions in binary form must reproduce the above copyright 13 | * notice, this list of conditions and the following disclaimer in the 14 | * documentation and/or other materials provided with the distribution. 15 | * * Neither the name of the nor the 16 | * names of its contributors may be used to endorse or promote products 17 | * derived from this software without specific prior written permission. 18 | * 19 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 20 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 21 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 22 | * DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY 23 | * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 24 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 25 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 26 | * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 28 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 | */ 30 | 31 | #ifndef _lorabase_in866_h_ 32 | #define _lorabase_in866_h_ 33 | 34 | #ifndef _LMIC_CONFIG_PRECONDITIONS_H_ 35 | # include "lmic_config_preconditions.h" 36 | #endif 37 | 38 | /****************************************************************************\ 39 | | 40 | | Basic definitions for IN866 (always in scope) 41 | | 42 | \****************************************************************************/ 43 | 44 | enum _dr_in866_t { 45 | IN866_DR_SF12 = 0, // DR0 46 | IN866_DR_SF11, // DR1 47 | IN866_DR_SF10, // DR2 48 | IN866_DR_SF9, // DR3 49 | IN866_DR_SF8, // DR4 50 | IN866_DR_SF7, // DR5 51 | IN866_DR_RFU, // - 52 | IN866_DR_FSK, // DR7 53 | IN866_DR_NONE 54 | }; 55 | 56 | // There is no dwell-time or duty-cycle limitation for IN 57 | // 58 | // max power: 30dBM 59 | // 60 | // freq datarates 61 | enum { 62 | IN866_F1 = 865062500, // SF7-12 (DR0-5) 63 | IN866_F2 = 865402500, // SF7-12 (DR0-5) 64 | IN866_F3 = 865985000, // SF7-12 (DR0-5) 65 | IN866_FB = 866550000, // beacon/ping 66 | }; 67 | enum { 68 | IN866_FREQ_MIN = 865000000, 69 | IN866_FREQ_MAX = 867000000 70 | }; 71 | enum { 72 | IN866_TX_EIRP_MAX_DBM = 30 // 30 dBm 73 | }; 74 | enum { DR_PAGE_IN866 = 0x10 * (LMIC_REGION_in866 - 1) }; 75 | 76 | enum { IN866_LMIC_REGION_EIRP = 1 }; // region uses EIRP 77 | 78 | #endif /* _lorabase_in866_h_ */ -------------------------------------------------------------------------------- /src/lmic/lmic/lorabase_kr920.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2014-2016 IBM Corporation. 3 | * All rights reserved. 4 | * 5 | * Copyright (c) 2017, 2019 MCCI Corporation 6 | * All rights reserved. 7 | * 8 | * Redistribution and use in source and binary forms, with or without 9 | * modification, are permitted provided that the following conditions are met: 10 | * * Redistributions of source code must retain the above copyright 11 | * notice, this list of conditions and the following disclaimer. 12 | * * Redistributions in binary form must reproduce the above copyright 13 | * notice, this list of conditions and the following disclaimer in the 14 | * documentation and/or other materials provided with the distribution. 15 | * * Neither the name of the nor the 16 | * names of its contributors may be used to endorse or promote products 17 | * derived from this software without specific prior written permission. 18 | * 19 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 20 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 21 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 22 | * DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY 23 | * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 24 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 25 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 26 | * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 28 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 | */ 30 | 31 | #ifndef _lorabase_kr920_h_ 32 | #define _lorabase_kr920_h_ 33 | 34 | #ifndef _LMIC_CONFIG_PRECONDITIONS_H_ 35 | # include "lmic_config_preconditions.h" 36 | #endif 37 | 38 | /****************************************************************************\ 39 | | 40 | | Basic definitions for KR920 (always in scope) 41 | | 42 | \****************************************************************************/ 43 | 44 | enum _dr_kr920_t { 45 | KR920_DR_SF12 = 0, // DR0 46 | KR920_DR_SF11, // DR1 47 | KR920_DR_SF10, // DR2 48 | KR920_DR_SF9, // DR3 49 | KR920_DR_SF8, // DR4 50 | KR920_DR_SF7, // DR5 51 | KR920_DR_NONE 52 | }; 53 | 54 | // There is no dwell-time or duty-cycle limitation for IN 55 | // 56 | // max power: 30dBM 57 | // 58 | // freq datarates 59 | enum { 60 | KR920_F1 = 922100000, // SF7-12 (DR0-5) 61 | KR920_F2 = 922300000, // SF7-12 (DR0-5) 62 | KR920_F3 = 922500000, // SF7-12 (DR0-5) 63 | KR920_FBCN = 923100000, // beacon/ping 64 | KR920_F14DBM = 922100000, // Allows 14 dBm (not 10) if >= this. 65 | KR920_FDOWN = 921900000, // RX2 downlink frequency 66 | }; 67 | enum { 68 | KR920_FREQ_MIN = 920900000, 69 | KR920_FREQ_MAX = 923300000 70 | }; 71 | enum { 72 | KR920_TX_EIRP_MAX_DBM = 14, // 14 dBm for most 73 | KR920_TX_EIRP_MAX_DBM_LOW = 10, // 10 dBm for some 74 | }; 75 | enum { DR_PAGE_KR920 = 0x10 * (LMIC_REGION_kr920 - 1) }; 76 | 77 | enum { KR920_LMIC_REGION_EIRP = 1 }; // region uses EIRP 78 | 79 | enum { KR920_LBT_US = 128 }; // microseconds of LBT time. 80 | 81 | enum { KR920_LBT_DB_MAX = -80 }; // maximum channel strength in dB; if TX 82 | // we measure more than this, we don't tx. 83 | 84 | #endif /* _lorabase_in866_h_ */ -------------------------------------------------------------------------------- /src/lmic/lmic/lorabase_us915.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2014-2016 IBM Corporation. 3 | * All rights reserved. 4 | * 5 | * Copyright (c) 2017 MCCI Corporation 6 | * All rights reserved. 7 | * 8 | * Redistribution and use in source and binary forms, with or without 9 | * modification, are permitted provided that the following conditions are met: 10 | * * Redistributions of source code must retain the above copyright 11 | * notice, this list of conditions and the following disclaimer. 12 | * * Redistributions in binary form must reproduce the above copyright 13 | * notice, this list of conditions and the following disclaimer in the 14 | * documentation and/or other materials provided with the distribution. 15 | * * Neither the name of the nor the 16 | * names of its contributors may be used to endorse or promote products 17 | * derived from this software without specific prior written permission. 18 | * 19 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 20 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 21 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 22 | * DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY 23 | * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 24 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 25 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 26 | * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 28 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 | */ 30 | 31 | #ifndef _lorabase_us915_h_ 32 | #define _lorabase_us915_h_ 33 | 34 | #ifndef _LMIC_CONFIG_PRECONDITIONS_H_ 35 | # include "lmic_config_preconditions.h" 36 | #endif 37 | 38 | /****************************************************************************\ 39 | | 40 | | Basic definitions for US915 (always in scope) 41 | | 42 | \****************************************************************************/ 43 | 44 | // Frequency plan for US 915MHz ISM band 45 | // data rates 46 | enum _dr_us915_t { 47 | US915_DR_SF10 = 0, 48 | US915_DR_SF9, 49 | US915_DR_SF8, 50 | US915_DR_SF7, 51 | US915_DR_SF8C, 52 | US915_DR_NONE, 53 | // Devices "behind a router" (and upper half of DR list): 54 | US915_DR_SF12CR = 8, 55 | US915_DR_SF11CR, 56 | US915_DR_SF10CR, 57 | US915_DR_SF9CR, 58 | US915_DR_SF8CR, 59 | US915_DR_SF7CR 60 | }; 61 | 62 | // Default frequency plan for US 915MHz 63 | enum { 64 | US915_125kHz_UPFBASE = 902300000, 65 | US915_125kHz_UPFSTEP = 200000, 66 | US915_500kHz_UPFBASE = 903000000, 67 | US915_500kHz_UPFSTEP = 1600000, 68 | US915_500kHz_DNFBASE = 923300000, 69 | US915_500kHz_DNFSTEP = 600000 70 | }; 71 | enum { 72 | US915_FREQ_MIN = 902000000, 73 | US915_FREQ_MAX = 928000000 74 | }; 75 | enum { 76 | US915_TX_MAX_DBM = 30 // 30 dBm (but not EIRP): assumes we're 77 | // on an 64-channel bandplan. See code 78 | // that computes tx power. 79 | }; 80 | 81 | enum { 82 | US915_LinkAdrReq_POW_MAX_1_0_2 = 0xA, 83 | US915_LinkAdrReq_POW_MAX_1_0_3 = 0xE, 84 | }; 85 | 86 | enum { DR_PAGE_US915 = 0x10 * (LMIC_REGION_us915 - 1) }; 87 | 88 | enum { US915_LMIC_REGION_EIRP = 0 }; // region doesn't use EIRP, uses tx power 89 | 90 | #endif /* _lorabase_us915_h_ */ -------------------------------------------------------------------------------- /src/lmic/lmic/lorawan_spec_compliance.h: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | Module: lorawan_spec_compliance.h 4 | 5 | Function: 6 | Details from the LoRaWAN specification for compliance. 7 | 8 | Copyright notice and license info: 9 | See LICENSE file accompanying this project. 10 | 11 | Author: 12 | Terry Moore, MCCI Corporation March 2019 13 | 14 | */ 15 | 16 | #ifndef _lorawan_spec_COMPLIANCE_H_ /* prevent multiple includes */ 17 | #define _lorawan_spec_COMPLIANCE_H_ 18 | 19 | #ifdef __cplusplus 20 | extern "C"{ 21 | #endif 22 | 23 | enum { 24 | // the port for MAC commands 25 | LORAWAN_PORT_MAC = 0u, 26 | // the first port available for applications 27 | LORAWAN_PORT_USER_MIN = 1u, 28 | // the last port available for applications 29 | LORAWAN_PORT_USER_MAX = 223u, 30 | // the base of the reserved port numbers 31 | LORAWAN_PORT_RESERVED = 224u, 32 | // the port for the compliance protocol 33 | LORAWAN_PORT_COMPLIANCE = LORAWAN_PORT_RESERVED + 0u, 34 | }; 35 | 36 | enum lowawan_compliance_cmd_e { 37 | LORAWAN_COMPLIANCE_CMD_DEACTIVATE = 0u, 38 | LORAWAN_COMPLIANCE_CMD_ACTIVATE = 1u, 39 | LORAWAN_COMPLIANCE_CMD_SET_CONFIRM = 2u, 40 | LORAWAN_COMPLIANCE_CMD_SET_UNCONFIRM = 3u, 41 | LORAWAN_COMPLIANCE_CMD_ECHO = 4u, 42 | LORAWAN_COMPLIANCE_CMD_LINK = 5u, 43 | LORAWAN_COMPLIANCE_CMD_JOIN = 6u, 44 | LORAWAN_COMPLIANCE_CMD_CW = 7u, 45 | LORAWAN_COMPLIANCE_CMD_MFG_BASE = 0x80u, 46 | }; 47 | 48 | typedef unsigned char lorawan_compliance_cmd_t; 49 | 50 | // info on specific commands 51 | enum { 52 | LORAWAN_COMPLIANCE_CMD_ACTIVATE_LEN = 4u, 53 | LORAWAN_COMPLIANCE_CMD_ACTIVATE_MAGIC = 1u, 54 | 55 | // Maximum crypto frame size; although the spec says 18, it 56 | // is also used for testing max packet size. 57 | LORAWAN_COMPLIANCE_CMD_ECHO_LEN_MAX = 242u, 58 | }; 59 | 60 | #ifdef __cplusplus 61 | } // extern "C" 62 | #endif 63 | 64 | #endif /* _lorawan_spec_COMPLIANCE_H_ */ -------------------------------------------------------------------------------- /src/lmic/lmic/oslmic.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2014-2016 IBM Corporation. 3 | * Copyright (c) 2016-2017, 2019 MCCI Corporation. 4 | * All rights reserved. 5 | * 6 | * Redistribution and use in source and binary forms, with or without 7 | * modification, are permitted provided that the following conditions are met: 8 | * * Redistributions of source code must retain the above copyright 9 | * notice, this list of conditions and the following disclaimer. 10 | * * Redistributions in binary form must reproduce the above copyright 11 | * notice, this list of conditions and the following disclaimer in the 12 | * documentation and/or other materials provided with the distribution. 13 | * * Neither the name of the nor the 14 | * names of its contributors may be used to endorse or promote products 15 | * derived from this software without specific prior written permission. 16 | * 17 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 18 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 19 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 20 | * DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY 21 | * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 22 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 23 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 24 | * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 26 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 | */ 28 | 29 | #define LMIC_DR_LEGACY 0 30 | 31 | #include "lmic.h" 32 | 33 | extern const struct lmic_pinmap lmic_pins; 34 | 35 | // RUNTIME STATE 36 | static struct { 37 | osjob_t* scheduledjobs; 38 | osjob_t* runnablejobs; 39 | } OS; 40 | 41 | int os_init_ex (const void *pintable) { 42 | memset(&OS, 0x00, sizeof(OS)); 43 | hal_init_ex(pintable); 44 | if (! radio_init()) 45 | return 0; 46 | LMIC_init(); 47 | return 1; 48 | } 49 | 50 | void os_init() { 51 | if (os_init_ex((const void *)&lmic_pins)) 52 | return; 53 | ASSERT(0); 54 | } 55 | 56 | ostime_t os_getTime () { 57 | return hal_ticks(); 58 | } 59 | 60 | // unlink job from queue, return if removed 61 | static int unlinkjob (osjob_t** pnext, osjob_t* job) { 62 | for( ; *pnext; pnext = &((*pnext)->next)) { 63 | if(*pnext == job) { // unlink 64 | *pnext = job->next; 65 | return 1; 66 | } 67 | } 68 | return 0; 69 | } 70 | 71 | static osjob_t** getJobQueue(osjob_t* job) { 72 | return os_jobIsTimed(job) ? &OS.scheduledjobs : &OS.runnablejobs; 73 | } 74 | 75 | // clear scheduled job 76 | void os_clearCallback (osjob_t* job) { 77 | hal_disableIRQs(); 78 | 79 | unlinkjob(getJobQueue(job), job); 80 | 81 | hal_enableIRQs(); 82 | } 83 | 84 | // schedule immediately runnable job 85 | void os_setCallback (osjob_t* job, osjobcb_t cb) { 86 | osjob_t** pnext; 87 | hal_disableIRQs(); 88 | 89 | // remove if job was already queued 90 | unlinkjob(getJobQueue(job), job); 91 | 92 | // fill-in job. Ascending memory order is write-queue friendly 93 | job->next = NULL; 94 | job->deadline = 0; 95 | job->func = cb; 96 | 97 | // add to end of run queue 98 | for(pnext=&OS.runnablejobs; *pnext; pnext=&((*pnext)->next)); 99 | *pnext = job; 100 | hal_enableIRQs(); 101 | } 102 | 103 | // schedule timed job 104 | void os_setTimedCallback (osjob_t* job, ostime_t time, osjobcb_t cb) { 105 | osjob_t** pnext; 106 | 107 | // special case time 0 -- it will be one tick late. 108 | if (time == 0) 109 | time = 1; 110 | 111 | hal_disableIRQs(); 112 | 113 | // remove if job was already queued 114 | unlinkjob(getJobQueue(job), job); 115 | 116 | // fill-in job 117 | job->next = NULL; 118 | job->deadline = time; 119 | job->func = cb; 120 | 121 | // insert into schedule 122 | for(pnext=&OS.scheduledjobs; *pnext; pnext=&((*pnext)->next)) { 123 | if((*pnext)->deadline - time > 0) { // (cmp diff, not abs!) 124 | // enqueue before next element and stop 125 | job->next = *pnext; 126 | break; 127 | } 128 | } 129 | *pnext = job; 130 | hal_enableIRQs(); 131 | } 132 | 133 | // execute jobs from timer and from run queue 134 | void os_runloop () { 135 | while(1) { 136 | os_runloop_once(); 137 | } 138 | } 139 | 140 | void os_runloop_once() { 141 | osjob_t* j = NULL; 142 | //hal_processPendingIRQs(); 143 | 144 | hal_disableIRQs(); 145 | // check for runnable jobs 146 | if(OS.runnablejobs) { 147 | j = OS.runnablejobs; 148 | OS.runnablejobs = j->next; 149 | } else if(OS.scheduledjobs && hal_checkTimer(OS.scheduledjobs->deadline)) { // check for expired timed jobs 150 | j = OS.scheduledjobs; 151 | OS.scheduledjobs = j->next; 152 | } else { // nothing pending 153 | hal_sleep(); // wake by irq (timer already restarted) 154 | } 155 | hal_enableIRQs(); 156 | if(j) { // run job callback 157 | j->func(j); 158 | } 159 | } 160 | 161 | // return true if there are any jobs scheduled within time ticks from now. 162 | // return false if any jobs scheduled are at least time ticks in the future. 163 | bit_t os_queryTimeCriticalJobs(ostime_t time) { 164 | if (OS.scheduledjobs && 165 | OS.scheduledjobs->deadline - os_getTime() < time) 166 | return 1; 167 | else 168 | return 0; 169 | } 170 | -------------------------------------------------------------------------------- /src/lmic/lmic/oslmic_types.h: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | Module: oslmic_types.h 4 | 5 | Function: 6 | Basic types from oslmic.h, shared by all layers. 7 | 8 | Copyright & License: 9 | See accompanying LICENSE file. 10 | 11 | Author: 12 | Terry Moore, MCCI November 2018 13 | (based on oslmic.h from IBM). 14 | 15 | */ 16 | 17 | #ifndef _oslmic_types_h_ 18 | # define _oslmic_types_h_ 19 | 20 | #include 21 | 22 | #ifdef __cplusplus 23 | extern "C" { 24 | #endif 25 | 26 | //================================================================================ 27 | //================================================================================ 28 | // Target platform as C library 29 | typedef uint8_t bit_t; 30 | typedef uint8_t u1_t; 31 | typedef int8_t s1_t; 32 | typedef uint16_t u2_t; 33 | typedef int16_t s2_t; 34 | typedef uint32_t u4_t; 35 | typedef int32_t s4_t; 36 | typedef unsigned int uint; 37 | typedef const char* str_t; 38 | 39 | // the HAL needs to give us ticks, so it ought to know the right type. 40 | typedef s4_t ostime_t; 41 | 42 | #ifdef __cplusplus 43 | } 44 | #endif 45 | 46 | /* end of oslmic_types.h */ 47 | #endif /* _oslmic_types_h_ */ 48 | --------------------------------------------------------------------------------