diff --git a/LICENSE b/LICENSE index 9288a85b..8a3b2470 100644 --- a/LICENSE +++ b/LICENSE @@ -20,9 +20,9 @@ Parts of the source files in this repository are made available under different listed below. Refer to each individual source file for more details. ------------------------------------------------------------------------------------------------ -wifiscan.cpp +wifiscan.cpp and macsniff.cpp: -Prior art was used for wifiscan.cpp and taken from +Parts were derived or taken from * Copyright (c) 2017, Łukasz Marcin Podkalicki * ESP32/016 WiFi Sniffer @@ -208,10 +208,9 @@ under this License: END OF TERMS AND CONDITIONS" ------------------------------------------------------------------------------------------------ -src/lorawan.cpp and /lib/arduino-lmic-1.5.0-<...> +lorawan.cpp -Parts of lorawan.cpp, and the arduino lmic library, which is included in the /lib directory of this -repository, were derived or taken from +Parts of lorawan.cpp, and the arduino lmic library were derived or taken from Arduino-LMIC Library TTN OTAA Example @@ -222,10 +221,32 @@ and it's fork LoraWAN-in-C library, adapted to run under the Arduino environment https://github.com/jpmeijers/arduino-lmic -under this Licence: +under this MIT Licence: + +"MIT License + +Copyright (C) 2014-2016 IBM Corporation +Copyright (c) 2016-2018 MCCI Corporation +Copyright (c) 2015 Thomas Telkamp and Matthijs Kooijman + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE." -"License -Most source files in this repository are made available under the Eclipse Public License v1.0. The examples which use a more liberal license. Some of the AES code is available under the LGPL. Refer to each individual source file for more details." ------------------------------------------------------------------------------------------------ blescan.cpp @@ -415,4 +436,4 @@ under this Licence: END OF TERMS AND CONDITIONS" ------------------------------------------------------------------------------------------------- +------------------------------------------------------------------------------------------------ \ No newline at end of file diff --git a/README.md b/README.md index 726e35f6..8907c7b7 100644 --- a/README.md +++ b/README.md @@ -59,7 +59,9 @@ Hardware dependent settings (pinout etc.) are stored in board files in /hal dire Before compiling the code, -- **edit paxcounter.conf** and tailor settings in this file according to your needs and use case. Please take care of the duty cycle regulations of the LoRaWAN network you're going to use. +- **edit src/paxcounter.conf** and tailor settings in this file according to your needs and use case. Please take care of the duty cycle regulations of the LoRaWAN network you're going to use. + +- **edit src/lmic_config.h** and tailor settings in this file according to your country and device hardware. Please take care of national regulations when selecting the frequency band for LoRaWAN. - **create file loraconf.h in your local /src directory** using the template [loraconf.sample.h](https://github.com/cyberman54/ESP32-Paxcounter/blob/master/src/loraconf.sample.h) and populate it with your personal APPEUI und APPKEY for the LoRaWAN network. If you're using popular TheThingsNetwork you can copy&paste the keys from TTN console or output of ttnctl. @@ -336,3 +338,4 @@ Thanks to - [Oliver Brandmüller](https://github.com/spmrider) for idea and initial setup of this project - [Charles Hallard](https://github.com/hallard) for major code contributions to this project - [robbi5](https://github.com/robbi5) for the payload converter +- [terrillmoore](https://github.com/mcci-catena) for maintaining the LMIC for arduino LoRaWAN stack diff --git a/include/globals.h b/include/globals.h index 947b4cfa..78df4a95 100644 --- a/include/globals.h +++ b/include/globals.h @@ -53,7 +53,7 @@ extern std::array beacons; extern TaskHandle_t irqHandlerTask, wifiSwitchTask; #ifdef HAS_GPS -#include "gps.h" +#include "gpsread.h" #endif #if (HAS_LED != NOT_A_PIN) || defined(HAS_RGB_LED) @@ -67,7 +67,7 @@ extern TaskHandle_t irqHandlerTask, wifiSwitchTask; #endif #ifdef HAS_SPI -#include "spi.h" +#include "spisend.h" #endif #ifdef HAS_DISPLAY diff --git a/include/gps.h b/include/gpsread.h similarity index 92% rename from include/gps.h rename to include/gpsread.h index 88ca24d3..6f5ed584 100644 --- a/include/gps.h +++ b/include/gpsread.h @@ -1,5 +1,5 @@ -#ifndef _GPS_H -#define _GPS_H +#ifndef _GPSREAD_H +#define _GPSREAD_H #include // library for parsing NMEA data #include diff --git a/include/ota.h b/include/ota.h index 560ee144..14f63eb0 100644 --- a/include/ota.h +++ b/include/ota.h @@ -17,7 +17,7 @@ int version_compare(const String v1, const String v2); void display(const uint8_t row, const std::string status, const std::string msg); #ifdef HAS_DISPLAY -void show_progress(size_t current, size_t size); +void show_progress(unsigned long current, unsigned long size); #endif #endif // USE_OTA diff --git a/include/spi.h b/include/spisend.h similarity index 69% rename from include/spi.h rename to include/spisend.h index b258a2ce..750a3c20 100644 --- a/include/spi.h +++ b/include/spisend.h @@ -1,5 +1,5 @@ -#ifndef _SPI_H -#define _SPI_H +#ifndef _SPISEND_H +#define _SPISEND_H extern TaskHandle_t SpiTask; extern QueueHandle_t SPISendQueue; diff --git a/lib/arduino-lmic-1.5.0-arduino-2-tweaked/README.md b/lib/arduino-lmic-1.5.0-arduino-2-tweaked/README.md deleted file mode 100644 index 69d800f5..00000000 --- a/lib/arduino-lmic-1.5.0-arduino-2-tweaked/README.md +++ /dev/null @@ -1,365 +0,0 @@ -Arduino-LMIC library -==================== -This repository contains the IBM LMIC (LoraMAC-in-C) library, slightly -modified to run in the Arduino environment, allowing using the SX1272, -SX1276 tranceivers and compatible modules (such as some HopeRF RFM9x -modules). - -This library mostly exposes the functions defined by LMIC, it makes no -attempt to wrap them in a higher level API that is more in the Arduino -style. To find out how to use the library itself, see the examples, or -see the PDF file in the doc subdirectory. - -This library requires Arduino IDE version 1.6.6 or above, since it -requires C99 mode to be enabled by default. - -Installing ----------- -To install this library: - - - install it using the Arduino Library manager ("Sketch" -> "Include - Library" -> "Manage Libraries..."), or - - download a zipfile from github using the "Download ZIP" button and - install it using the IDE ("Sketch" -> "Include Library" -> "Add .ZIP - Library..." - - clone this git repository into your sketchbook/libraries folder. - -For more info, see https://www.arduino.cc/en/Guide/Libraries - -Features --------- -The LMIC library provides a fairly complete LoRaWAN Class A and Class B -implementation, supporting the EU-868 and US-915 bands. Only a limited -number of features was tested using this port on Arduino hardware, so be -careful when using any of the untested features. - -What certainly works: - - Sending packets uplink, taking into account duty cycling. - - Encryption and message integrity checking. - - Receiving downlink packets in the RX2 window. - - Custom frequencies and datarate settings. - - Over-the-air activation (OTAA / joining). - -What has not been tested: - - Receiving downlink packets in the RX1 window. - - Receiving and processing MAC commands. - - Class B operation. - -If you try one of these untested features and it works, be sure to let -us know (creating a github issue is probably the best way for that). - -Configuration -------------- -A number of features can be configured or disabled by editing the -`config.h` file in the library folder. Unfortunately the Arduino -environment does not offer any way to do this (compile-time) -configuration from the sketch, so be careful to recheck your -configuration when you switch between sketches or update the library. - -At the very least, you should set the right type of transceiver (SX1272 -vs SX1276) in config.h, most other values should be fine at their -defaults. - -Supported hardware ------------------- -This library is intended to be used with plain LoRa transceivers, -connecting to them using SPI. In particular, the SX1272 and SX1276 -families are supported (which should include SX1273, SX1277, SX1278 and -SX1279 which only differ in the available frequencies, bandwidths and -spreading factors). It has been tested with both SX1272 and SX1276 -chips, using the Semtech SX1272 evaluation board and the HopeRF RFM92 -and RFM95 boards (which supposedly contain an SX1272 and SX1276 chip -respectively). - -This library contains a full LoRaWAN stack and is intended to drive -these Transceivers directly. It is *not* intended to be used with -full-stack devices like the Microchip RN2483 and the Embit LR1272E. -These contain a transceiver and microcontroller that implements the -LoRaWAN stack and exposes a high-level serial interface instead of the -low-level SPI transceiver interface. - -This library is intended to be used inside the Arduino environment. It -should be architecture-independent, so it should run on "normal" AVR -arduinos, but also on the ARM-based ones, and some success has been seen -running on the ESP8266 board as well. It was tested on the Arduino Uno, -Pinoccio Scout, Teensy LC and 3.x, ESP8266, Arduino 101. - -This library an be quite heavy, especially if the fairly small ATmega -328p (such as in the Arduino Uno) is used. In the default configuration, -the available 32K flash space is nearly filled up (this includes some -debug output overhead, though). By disabling some features in `config.h` -(like beacon tracking and ping slots, which are not typically needed), -some space can be freed up. Some work is underway to replace the AES -encryption implementation, which should free up another 8K or so of -flash in the future, making this library feasible to run on a 328p -microcontroller. - -Connections ------------ -To make this library work, your Arduino (or whatever Arduino-compatible -board you are using) should be connected to the transceiver. The exact -connections are a bit dependent on the transceiver board and Arduino -used, so this section tries to explain what each connection is for and -in what cases it is (not) required. - -Note that the SX1272 module runs at 3.3V and likely does not like 5V on -its pins (though the datasheet is not say anything about this, and my -transceiver did not obviously break after accidentally using 5V I/O for -a few hours). To be safe, make sure to use a level shifter, or an -Arduino running at 3.3V. The Semtech evaluation board has 100 ohm resistors in -series with all data lines that might prevent damage, but I would not -count on that. - -### Power -The SX127x transceivers need a supply voltage between 1.8V and 3.9V. -Using a 3.3V supply is typical. Some modules have a single power pin -(like the HopeRF modules, labeled 3.3V) but others expose multiple power -pins for different parts (like the Semtech evaluation board that has -`VDD_RF`, `VDD_ANA` and `VDD_FEM`), which can all be connected together. -Any *GND* pins need to be connected to the Arduino *GND* pin(s). - -### SPI -The primary way of communicating with the transceiver is through SPI -(Serial Peripheral Interface). This uses four pins: MOSI, MISO, SCK and -SS. The former three need to be directly connected: so MOSI to MOSI, -MISO to MISO, SCK to SCK. Where these pins are located on your Arduino -varies, see for example the "Connections" section of the [Arduino SPI -documentation](SPI). - -The SS (slave select) connection is a bit more flexible. On the SPI -slave side (the transceiver), this must be connect to the pin -(typically) labeled *NSS*. On the SPI master (Arduino) side, this pin -can connect to any I/O pin. Most Arduinos also have a pin labeled "SS", -but this is only relevant when the Arduino works as an SPI slave, which -is not the case here. Whatever pin you pick, you need to tell the -library what pin you used through the pin mapping (see below). - -[SPI]: https://www.arduino.cc/en/Reference/SPI - -### DIO pins -The DIO (digitial I/O) pins on the transceiver board can be configured -for various functions. The LMIC library uses them to get instant status -information from the transceiver. For example, when a LoRa transmission -starts, the DIO0 pin is configured as a TxDone output. When the -transmission is complete, the DIO0 pin is made high by the transceiver, -which can be detected by the LMIC library. - -The LMIC library needs only access to DIO0, DIO1 and DIO2, the other -DIOx pins can be left disconnected. On the Arduino side, they can -connect to any I/O pin, since the current implementation does not use -interrupts or other special hardware features (though this might be -added in the feature, see also the "Timing" section). - -In LoRa mode the DIO pins are used as follows: - * DIO0: TxDone and RxDone - * DIO1: RxTimeout - -In FSK mode they are used as follows:: - * DIO0: PayloadReady and PacketSent - * DIO2: TimeOut - -Both modes need only 2 pins, but the tranceiver does not allow mapping -them in such a way that all needed interrupts map to the same 2 pins. -So, if both LoRa and FSK modes are used, all three pins must be -connected. - -The pins used on the Arduino side should be configured in the pin -mapping in your sketch (see below). - -### Reset -The transceiver has a reset pin that can be used to explicitely reset -it. The LMIC library uses this to ensure the chip is in a consistent -state at startup. In practice, this pin can be left disconnected, since -the transceiver will already be in a sane state on power-on, but -connecting it might prevent problems in some cases. - -On the Arduino side, any I/O pin can be used. The pin number used must -be configured in the pin mapping (see below). - -### RXTX -The transceiver contains two separate antenna connections: One for RX -and one for TX. A typical transceiver board contains an antenna switch -chip, that allows switching a single antenna between these RX and TX -connections. Such a antenna switcher can typically be told what -position it should be through an input pin, often labeled *RXTX*. - -The easiest way to control the antenna switch is to use the *RXTX* pin -on the SX127x transceiver. This pin is automatically set high during TX -and low during RX. For example, the HopeRF boards seem to have this -connection in place, so they do not expose any *RXTX* pins and the pin -can be marked as unused in the pin mapping. - -Some boards do expose the antenna switcher pin, and sometimes also the -SX127x *RXTX* pin. For example, the SX1272 evaluation board calls the -former *FEM_CTX* and the latter *RXTX*. Again, simply connecting these -together with a jumper wire is the easiest solution. - -Alternatively, or if the SX127x *RXTX* pin is not available, LMIC can be -configured to control the antenna switch. Connect the antenna switch -control pin (e.g. *FEM_CTX* on the Semtech evaluation board) to any I/O -pin on the Arduino side, and configure the pin used in the pin map (see -below). It is not entirely clear why would *not* want the transceiver to -control the antenna directly, though. - -### Pin mapping -As described above, most connections can use arbitrary I/O pins on the -Arduino side. To tell the LMIC library about these, a pin mapping struct -is used in the sketch file. - -For example, this could look like this: - - lmic_pinmap lmic_pins = { - .nss = 6, - .rxtx = LMIC_UNUSED_PIN, - .rst = 5, - .dio = {2, 3, 4}, - }; - -The names refer to the pins on the transceiver side, the numbers refer -to the Arduino pin numbers (to use the analog pins, use constants like -`A0`). For the DIO pins, the three numbers refer to DIO0, DIO1 and DIO2 -respectively. Any pins that are not needed should be specified as -`LMIC_UNUSED_PIN`. The nss and dio0 pin is required, the others can -potentially left out (depending on the environments and requirements, -see the notes above for when a pin can or cannot be left out). - -The name of this struct must always be `lmic_pins`, which is a special name -recognized by the library. - -#### LoRa Nexus by Ideetron -This board uses the following pin mapping: - - const lmic_pinmap lmic_pins = { - .nss = 10, - .rxtx = LMIC_UNUSED_PIN, - .rst = LMIC_UNUSED_PIN, // hardwired to AtMega RESET - .dio = {4, 5, 7}, - }; - -Examples --------- -This library currently provides three examples: - - - `ttn-abp.ino` shows a basic transmission of a "Hello, world!" message - using the LoRaWAN protocol. It contains some frequency settings and - encryption keys intended for use with The Things Network, but these - also correspond to the default settings of most gateways, so it - should work with other networks and gateways as well. This example - uses activation-by-personalization (ABP, preconfiguring a device - address and encryption keys), and does not employ over-the-air - activation. - - Reception of packets (in response to transmission, using the RX1 and - RX2 receive windows is also supported). - - - `ttn-otaa.ino` also sends a "Hello, world!" message, but uses over - the air activation (OTAA) to first join a network to establish a - session and security keys. This was tested with The Things Network, - but should also work (perhaps with some changes) for other networks. - - - `raw.ino` shows how to access the radio on a somewhat low level, - and allows to send raw (non-LoRaWAN) packets between nodes directly. - This is useful to verify basic connectivity, and when no gateway is - available, but this example also bypasses duty cycle checks, so be - careful when changing the settings. - -Timing ------- -Unfortunately, the SX127x tranceivers do not support accurate -timekeeping themselves (there is a sequencer that is *almost* sufficient -for timing the RX1 and RX2 downlink windows, but that is only available -in FSK mode, not in LoRa mode). This means that the microcontroller is -responsible for keeping track of time. In particular, it should note -when a packet finished transmitting, so it can open up the RX1 and RX2 -receive windows at a fixed time after the end of transmission. - -This timing uses the Arduino `micros()` timer, which has a granularity -of 4μs and is based on the primary microcontroller clock. For timing -events, the tranceiver uses its DIOx pins as interrupt outputs. In the -current implementation, these pins are not handled by an actual -interrupt handler, but they are just polled once every LMIC loop, -resulting in a bit inaccuracy in the timestamping. Also, running -scheduled jobs (such as opening up the receive windows) is done using a -polling approach, which might also result in further delays. - -Fortunately, LoRa is a fairly slow protocol and the timing of the -receive windows is not super critical. To synchronize transmitter and -receiver, a preamble is first transmitted. Using LoRaWAN, this preamble -consists of 8 symbols, of which the receiver needs to see 4 symbols to -lock on. The current implementation tries to enable the receiver for 5 -symbol times at 1.5 symbol after the start of the receive window, -meaning that a inacurracy of plus or minus 2.5 symbol times should be -acceptable. - -At the fastest LoRa setting supported by the tranceiver (SF5BW500) a -single preamble symbol takes 64μs, so the receive window timing should -be accurate within 160μs (for LoRaWAN this is SF7BW250, needing accuracy -within 1280μs). This is certainly within a crystal's accuracy, but using -the internal oscillator is probably not feasible (which is 1% - 10% -accurate, depending on calibration). This accuracy should also be -feasible with the polling approach used, provided that the LMIC loop is -run often enough. - -It would be good to properly review this code at some point, since it -seems that in some places some offsets and corrections are applied that -might not be appropriate for the Arduino environment. So if reception is -not working, the timing is something to have a closer look at. - -The LMIC library was intended to connect the DIO pins to interrupt -lines and run code inside the interrupt handler. However, doing this -opens up an entire can of worms with regard to doing SPI transfers -inside interrupt routines (some of which is solved by the Arduino -`beginTransaction()` API, but possibly not everything). One simpler -alternative could be to use an interrupt handler to just store a -timestamp, and then do the actual handling in the main loop (this -requires modifications of the library to pass a timestamp to the LMIC -`radio_irq_handler()` function). - -An even more accurate solution could be to use a dedicated timer with an -input capture unit, that can store the timestamp of a change on the DIO0 -pin (the only one that is timing-critical) entirely in hardware. -Unfortunately, timer0, as used by Arduino's `millis()` and `micros()` -functions does not seem to have an input capture unit, meaning a -separate timer is needed for this. - -If the main microcontroller does not have a crystal, but uses the -internal oscillator, the clock output of the transceiver (on DIO5) could -be usable to drive this timer instead of the main microcontroller clock, -to ensure the receive window timing is sufficiently accurate. Ideally, -this would use timer2, which supports asynchronous mode (e.g. running -while the microcontroller is sleeping), but that timer does not have an -input capture unit. Timer1 has one, but it seems it will stop running -once the microcontroller sleeps. Running the microcontroller in idle -mode with a slower clock might be feasible, though. Instead of using the -main crystal oscillator of the transceiver, it could be possible to use -the transceiver's internal RC oscillator (which is calibrated against -the transceiver crystal), or to calibrate the microcontroller internal -RC oscillator using the transceiver's clkout. However, that datasheet is -a bit vague on the RC oscillator's accuracy and how to use it exactly -(some registers seem to be FSK-mode only), so this needs some -experiments. - -Downlink datarate ------------------ -Note that the datarate used for downlink packets in the RX2 window -defaults to SF12BW125 according to the specification, but some networks -use different values (iot.semtech.com and The Things Network both use -SF9BW). When using personalized activate (ABP), it is your -responsibility to set the right settings, e.g. by adding this to your -sketch (after calling `LMIC_setSession`). `ttn-abp.ino` already does -this. - - LMIC.dn2Dr = DR_SF9; - -When using OTAA, the network communicates the RX2 settings in the -join accept message, but the LMIC library does not currently process -these settings. Until that is solved (see issue #20), you should -manually set the RX2 rate, *after* joining (see the handling of -`EV_JOINED` in the `ttn-otaa.ino` for an example. - -License -------- -Most source files in this repository are made available under the -Eclipse Public License v1.0. The examples which use a more liberal -license. Some of the AES code is available under the LGPL. Refer to each -individual source file for more details. diff --git a/lib/arduino-lmic-1.5.0-arduino-2-tweaked/doc/LMiC-v1.5.pdf b/lib/arduino-lmic-1.5.0-arduino-2-tweaked/doc/LMiC-v1.5.pdf deleted file mode 100644 index b14bd693..00000000 Binary files a/lib/arduino-lmic-1.5.0-arduino-2-tweaked/doc/LMiC-v1.5.pdf and /dev/null differ diff --git a/lib/arduino-lmic-1.5.0-arduino-2-tweaked/doc/README.txt b/lib/arduino-lmic-1.5.0-arduino-2-tweaked/doc/README.txt deleted file mode 100644 index 237b1632..00000000 --- a/lib/arduino-lmic-1.5.0-arduino-2-tweaked/doc/README.txt +++ /dev/null @@ -1,4 +0,0 @@ -DISCLAIMER: -Please note that the software is provided AS IS and we cannot -provide support for optimizations, adaptations, integration, -ports to other platforms or device drivers! diff --git a/lib/arduino-lmic-1.5.0-arduino-2-tweaked/doc/release-notes.txt b/lib/arduino-lmic-1.5.0-arduino-2-tweaked/doc/release-notes.txt deleted file mode 100644 index 835154d1..00000000 --- a/lib/arduino-lmic-1.5.0-arduino-2-tweaked/doc/release-notes.txt +++ /dev/null @@ -1,28 +0,0 @@ -============================================================================== -LMIC VERSION 1.4 (17-Mar-2015) -------------------------------- - - - changed API: inverted port indicator flag in LMIC.txrxFlags - (now TXRX_PORT, previously TXRX_NOPORT) - - - fixed offset OFF_CFLIST constant - - - changed CRC-16 algorithm for beacons to CCITT(XMODEM) polynomial - - - fixed radio driver (low data rate optimization for SF11+SF12 only for BW125) - - - fixed timer rollover handling in job queue - -============================================================================== -LMIC VERSION 1.5 (8-May-2015) ------------------------------- - - - fixed condition in convFreq() - - - fixed freq*100 bug and freq==0 bug for CFList - - - fixed TX scheduling bug - - - better support for GNU compiler toolchain - -============================================================================== diff --git a/lib/arduino-lmic-1.5.0-arduino-2-tweaked/library.properties b/lib/arduino-lmic-1.5.0-arduino-2-tweaked/library.properties deleted file mode 100644 index ea924c4e..00000000 --- a/lib/arduino-lmic-1.5.0-arduino-2-tweaked/library.properties +++ /dev/null @@ -1,9 +0,0 @@ -name=IBM LMIC framework -version=1.5.0+arduino-2 -author=IBM -maintainer=Matthijs Kooijman -sentence=Arduino port of the LMIC (LoraWAN-in-C, formerly LoraMAC-in-C) framework provided by IBM. -paragraph=Supports SX1272/SX1276 and HopeRF RFM92/RFM95 tranceivers -category=Communication -url=http://www.research.ibm.com/labs/zurich/ics/lrsc/lmic.html -architectures=* diff --git a/lib/arduino-lmic-1.5.0-arduino-2-tweaked/src/aes/ideetron/AES-128_V10.cpp b/lib/arduino-lmic-1.5.0-arduino-2-tweaked/src/aes/ideetron/AES-128_V10.cpp deleted file mode 100644 index f067ebd4..00000000 --- a/lib/arduino-lmic-1.5.0-arduino-2-tweaked/src/aes/ideetron/AES-128_V10.cpp +++ /dev/null @@ -1,342 +0,0 @@ -/****************************************************************************************** -#if defined(USE_IDEETRON_AES) -* Copyright 2015, 2016 Ideetron B.V. -* -* This program is free software: you can redistribute it and/or modify -* it under the terms of the GNU Lesser General Public License as published by -* the Free Software Foundation, either version 3 of the License, or -* (at your option) any later version. -* -* This program is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU Lesser General Public License for more details. -* -* You should have received a copy of the GNU Lesser General Public License -* along with this program. If not, see . -******************************************************************************************/ -/****************************************************************************************** -* -* File: AES-128_V10.cpp -* Author: Gerben den Hartog -* Compagny: Ideetron B.V. -* Website: http://www.ideetron.nl/LoRa -* E-mail: info@ideetron.nl -******************************************************************************************/ -/**************************************************************************************** -* -* Created on: 20-10-2015 -* Supported Hardware: ID150119-02 Nexus board with RFM95 -* -* Firmware Version 1.0 -* First version -****************************************************************************************/ - -// This file was taken from -// https://github.com/Ideetron/RFM95W_Nexus/tree/master/LoRaWAN_V31 for -// use with LMIC. It was only cosmetically modified: -// - AES_Encrypt was renamed to lmic_aes_encrypt. -// - All other functions and variables were made static -// - Tabs were converted to 2 spaces -// - An #include and #if guard was added -// - S_Table is now stored in PROGMEM - -#include "../../lmic/oslmic.h" - -#if defined(USE_IDEETRON_AES) - -/* -******************************************************************************************** -* Global Variables -******************************************************************************************** -*/ - -static unsigned char State[4][4]; - -static CONST_TABLE(unsigned char, S_Table)[16][16] = { - {0x63,0x7C,0x77,0x7B,0xF2,0x6B,0x6F,0xC5,0x30,0x01,0x67,0x2B,0xFE,0xD7,0xAB,0x76}, - {0xCA,0x82,0xC9,0x7D,0xFA,0x59,0x47,0xF0,0xAD,0xD4,0xA2,0xAF,0x9C,0xA4,0x72,0xC0}, - {0xB7,0xFD,0x93,0x26,0x36,0x3F,0xF7,0xCC,0x34,0xA5,0xE5,0xF1,0x71,0xD8,0x31,0x15}, - {0x04,0xC7,0x23,0xC3,0x18,0x96,0x05,0x9A,0x07,0x12,0x80,0xE2,0xEB,0x27,0xB2,0x75}, - {0x09,0x83,0x2C,0x1A,0x1B,0x6E,0x5A,0xA0,0x52,0x3B,0xD6,0xB3,0x29,0xE3,0x2F,0x84}, - {0x53,0xD1,0x00,0xED,0x20,0xFC,0xB1,0x5B,0x6A,0xCB,0xBE,0x39,0x4A,0x4C,0x58,0xCF}, - {0xD0,0xEF,0xAA,0xFB,0x43,0x4D,0x33,0x85,0x45,0xF9,0x02,0x7F,0x50,0x3C,0x9F,0xA8}, - {0x51,0xA3,0x40,0x8F,0x92,0x9D,0x38,0xF5,0xBC,0xB6,0xDA,0x21,0x10,0xFF,0xF3,0xD2}, - {0xCD,0x0C,0x13,0xEC,0x5F,0x97,0x44,0x17,0xC4,0xA7,0x7E,0x3D,0x64,0x5D,0x19,0x73}, - {0x60,0x81,0x4F,0xDC,0x22,0x2A,0x90,0x88,0x46,0xEE,0xB8,0x14,0xDE,0x5E,0x0B,0xDB}, - {0xE0,0x32,0x3A,0x0A,0x49,0x06,0x24,0x5C,0xC2,0xD3,0xAC,0x62,0x91,0x95,0xE4,0x79}, - {0xE7,0xC8,0x37,0x6D,0x8D,0xD5,0x4E,0xA9,0x6C,0x56,0xF4,0xEA,0x65,0x7A,0xAE,0x08}, - {0xBA,0x78,0x25,0x2E,0x1C,0xA6,0xB4,0xC6,0xE8,0xDD,0x74,0x1F,0x4B,0xBD,0x8B,0x8A}, - {0x70,0x3E,0xB5,0x66,0x48,0x03,0xF6,0x0E,0x61,0x35,0x57,0xB9,0x86,0xC1,0x1D,0x9E}, - {0xE1,0xF8,0x98,0x11,0x69,0xD9,0x8E,0x94,0x9B,0x1E,0x87,0xE9,0xCE,0x55,0x28,0xDF}, - {0x8C,0xA1,0x89,0x0D,0xBF,0xE6,0x42,0x68,0x41,0x99,0x2D,0x0F,0xB0,0x54,0xBB,0x16} -}; - -extern "C" void lmic_aes_encrypt(unsigned char *Data, unsigned char *Key); -static void AES_Add_Round_Key(unsigned char *Round_Key); -static unsigned char AES_Sub_Byte(unsigned char Byte); -static void AES_Shift_Rows(); -static void AES_Mix_Collums(); -static void AES_Calculate_Round_Key(unsigned char Round, unsigned char *Round_Key); -static void Send_State(); - -/* -***************************************************************************************** -* Description : Function for encrypting data using AES-128 -* -* Arguments : *Data Data to encrypt is a 16 byte long arry -* *Key Key to encrypt data with is a 16 byte long arry -***************************************************************************************** -*/ -void lmic_aes_encrypt(unsigned char *Data, unsigned char *Key) -{ - unsigned char i; - unsigned char Row,Collum; - unsigned char Round = 0x00; - unsigned char Round_Key[16]; - - //Copy input to State arry - for(Collum = 0; Collum < 4; Collum++) - { - for(Row = 0; Row < 4; Row++) - { - State[Row][Collum] = Data[Row + (4*Collum)]; - } - } - - //Copy key to round key - for(i = 0; i < 16; i++) - { - Round_Key[i] = Key[i]; - } - - //Add round key - AES_Add_Round_Key(Round_Key); - - //Preform 9 full rounds - for(Round = 1; Round < 10; Round++) - { - //Preform Byte substitution with S table - for(Collum = 0; Collum < 4; Collum++) - { - for(Row = 0; Row < 4; Row++) - { - State[Row][Collum] = AES_Sub_Byte(State[Row][Collum]); - } - } - - //Preform Row Shift - AES_Shift_Rows(); - - //Mix Collums - AES_Mix_Collums(); - - //Calculate new round key - AES_Calculate_Round_Key(Round,Round_Key); - - //Add round key - AES_Add_Round_Key(Round_Key); - } - - //Last round whitout mix collums - //Preform Byte substitution with S table - for(Collum = 0; Collum < 4; Collum++) - { - for(Row = 0; Row < 4; Row++) - { - State[Row][Collum] = AES_Sub_Byte(State[Row][Collum]); - } - } - - //Shift rows - AES_Shift_Rows(); - - //Calculate new round key - AES_Calculate_Round_Key(Round,Round_Key); - - //Add round Key - AES_Add_Round_Key(Round_Key); - - //Copy the State into the data array - for(Collum = 0; Collum < 4; Collum++) - { - for(Row = 0; Row < 4; Row++) - { - Data[Row + (4*Collum)] = State[Row][Collum]; - } - } - -} - -/* -***************************************************************************************** -* Description : Function that add's the round key for the current round -* -* Arguments : *Round_Key 16 byte long array holding the Round Key -***************************************************************************************** -*/ -static void AES_Add_Round_Key(unsigned char *Round_Key) -{ - unsigned char Row,Collum; - - for(Collum = 0; Collum < 4; Collum++) - { - for(Row = 0; Row < 4; Row++) - { - State[Row][Collum] = State[Row][Collum] ^ Round_Key[Row + (4*Collum)]; - } - } -} - -/* -***************************************************************************************** -* Description : Function that substitutes a byte with a byte from the S_Table -* -* Arguments : Byte The byte that will be substituted -* -* Return : The return is the found byte in the S_Table -***************************************************************************************** -*/ -static unsigned char AES_Sub_Byte(unsigned char Byte) -{ - unsigned char S_Row,S_Collum; - unsigned char S_Byte; - - //Split byte up in Row and Collum - S_Row = ((Byte >> 4) & 0x0F); - S_Collum = (Byte & 0x0F); - - //Find the correct byte in the S_Table - S_Byte = TABLE_GET_U1_TWODIM(S_Table, S_Row, S_Collum); - - return S_Byte; -} - -/* -***************************************************************************************** -* Description : Function that preforms the shift row operation described in the AES standard -***************************************************************************************** -*/ -static void AES_Shift_Rows() -{ - unsigned char Buffer; - - //Row 0 doesn't change - - //Shift Row 1 one left - //Store firt byte in buffer - Buffer = State[1][0]; - //Shift all bytes - State[1][0] = State[1][1]; - State[1][1] = State[1][2]; - State[1][2] = State[1][3]; - State[1][3] = Buffer; - - //Shift row 2 two left - Buffer = State[2][0]; - State[2][0] = State[2][2]; - State[2][2] = Buffer; - Buffer = State[2][1]; - State[2][1] = State[2][3]; - State[2][3] = Buffer; - - //Shift row 3 three left - Buffer = State[3][3]; - State[3][3] = State[3][2]; - State[3][2] = State[3][1]; - State[3][1] = State[3][0]; - State[3][0] = Buffer; -} - -/* -***************************************************************************************** -* Description : Function that preforms the Mix Collums operation described in the AES standard -***************************************************************************************** -*/ -static void AES_Mix_Collums() -{ - unsigned char Row,Collum; - unsigned char a[4], b[4]; - for(Collum = 0; Collum < 4; Collum++) - { - for(Row = 0; Row < 4; Row++) - { - a[Row] = State[Row][Collum]; - b[Row] = (State[Row][Collum] << 1); - - if((State[Row][Collum] & 0x80) == 0x80) - { - b[Row] = b[Row] ^ 0x1B; - } - } - State[0][Collum] = b[0] ^ a[1] ^ b[1] ^ a[2] ^ a[3]; - State[1][Collum] = a[0] ^ b[1] ^ a[2] ^ b[2] ^ a[3]; - State[2][Collum] = a[0] ^ a[1] ^ b[2] ^ a[3] ^ b[3]; - State[3][Collum] = a[0] ^ b[0] ^ a[1] ^ a[2] ^ b[3]; - } -} - -/* -***************************************************************************************** -* Description : Function that calculaties the round key for the current round -* -* Arguments : Round Number of current Round -* *Round_Key 16 byte long array holding the Round Key -***************************************************************************************** -*/ -static void AES_Calculate_Round_Key(unsigned char Round, unsigned char *Round_Key) -{ - unsigned char i,j; - unsigned char b; - unsigned char Temp[4]; - unsigned char Buffer; - unsigned char Rcon; - - //Calculate first Temp - //Copy laste byte from previous key - for(i = 0; i < 4; i++) - { - Temp[i] = Round_Key[i+12]; - } - - //Rotate Temp - Buffer = Temp[0]; - Temp[0] = Temp[1]; - Temp[1] = Temp[2]; - Temp[2] = Temp[3]; - Temp[3] = Buffer; - - //Substitute Temp - for(i = 0; i < 4; i++) - { - Temp[i] = AES_Sub_Byte(Temp[i]); - } - - //Calculate Rcon - Rcon = 0x01; - while(Round != 1) - { - b = Rcon & 0x80; - Rcon = Rcon << 1; - if(b == 0x80) - { - Rcon = Rcon ^ 0x1b; - } - Round--; - } - - //XOR Rcon - Temp[0] = Temp[0] ^ Rcon; - - //Calculate new key - for(i = 0; i < 4; i++) - { - for(j = 0; j < 4; j++) - { - Round_Key[j + (4*i)] = Round_Key[j + (4*i)] ^ Temp[j]; - Temp[j] = Round_Key[j + (4*i)]; - } - } -} - -#endif // defined(USE_IDEETRON_AES) diff --git a/lib/arduino-lmic-1.5.0-arduino-2-tweaked/src/aes/lmic.c b/lib/arduino-lmic-1.5.0-arduino-2-tweaked/src/aes/lmic.c deleted file mode 100644 index 55a68769..00000000 --- a/lib/arduino-lmic-1.5.0-arduino-2-tweaked/src/aes/lmic.c +++ /dev/null @@ -1,370 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2014-2015 IBM Corporation. - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * http://www.eclipse.org/legal/epl-v10.html - * - * Contributors: - * IBM Zurich Research Lab - initial API, implementation and documentation - *******************************************************************************/ - -#include "../lmic/oslmic.h" - -#if defined(USE_ORIGINAL_AES) - -#define AES_MICSUB 0x30 // internal use only - -static CONST_TABLE(u4_t, AES_RCON)[10] = { - 0x01000000, 0x02000000, 0x04000000, 0x08000000, 0x10000000, - 0x20000000, 0x40000000, 0x80000000, 0x1B000000, 0x36000000 -}; - -static CONST_TABLE(u1_t, AES_S)[256] = { - 0x63, 0x7C, 0x77, 0x7B, 0xF2, 0x6B, 0x6F, 0xC5, 0x30, 0x01, 0x67, 0x2B, 0xFE, 0xD7, 0xAB, 0x76, - 0xCA, 0x82, 0xC9, 0x7D, 0xFA, 0x59, 0x47, 0xF0, 0xAD, 0xD4, 0xA2, 0xAF, 0x9C, 0xA4, 0x72, 0xC0, - 0xB7, 0xFD, 0x93, 0x26, 0x36, 0x3F, 0xF7, 0xCC, 0x34, 0xA5, 0xE5, 0xF1, 0x71, 0xD8, 0x31, 0x15, - 0x04, 0xC7, 0x23, 0xC3, 0x18, 0x96, 0x05, 0x9A, 0x07, 0x12, 0x80, 0xE2, 0xEB, 0x27, 0xB2, 0x75, - 0x09, 0x83, 0x2C, 0x1A, 0x1B, 0x6E, 0x5A, 0xA0, 0x52, 0x3B, 0xD6, 0xB3, 0x29, 0xE3, 0x2F, 0x84, - 0x53, 0xD1, 0x00, 0xED, 0x20, 0xFC, 0xB1, 0x5B, 0x6A, 0xCB, 0xBE, 0x39, 0x4A, 0x4C, 0x58, 0xCF, - 0xD0, 0xEF, 0xAA, 0xFB, 0x43, 0x4D, 0x33, 0x85, 0x45, 0xF9, 0x02, 0x7F, 0x50, 0x3C, 0x9F, 0xA8, - 0x51, 0xA3, 0x40, 0x8F, 0x92, 0x9D, 0x38, 0xF5, 0xBC, 0xB6, 0xDA, 0x21, 0x10, 0xFF, 0xF3, 0xD2, - 0xCD, 0x0C, 0x13, 0xEC, 0x5F, 0x97, 0x44, 0x17, 0xC4, 0xA7, 0x7E, 0x3D, 0x64, 0x5D, 0x19, 0x73, - 0x60, 0x81, 0x4F, 0xDC, 0x22, 0x2A, 0x90, 0x88, 0x46, 0xEE, 0xB8, 0x14, 0xDE, 0x5E, 0x0B, 0xDB, - 0xE0, 0x32, 0x3A, 0x0A, 0x49, 0x06, 0x24, 0x5C, 0xC2, 0xD3, 0xAC, 0x62, 0x91, 0x95, 0xE4, 0x79, - 0xE7, 0xC8, 0x37, 0x6D, 0x8D, 0xD5, 0x4E, 0xA9, 0x6C, 0x56, 0xF4, 0xEA, 0x65, 0x7A, 0xAE, 0x08, - 0xBA, 0x78, 0x25, 0x2E, 0x1C, 0xA6, 0xB4, 0xC6, 0xE8, 0xDD, 0x74, 0x1F, 0x4B, 0xBD, 0x8B, 0x8A, - 0x70, 0x3E, 0xB5, 0x66, 0x48, 0x03, 0xF6, 0x0E, 0x61, 0x35, 0x57, 0xB9, 0x86, 0xC1, 0x1D, 0x9E, - 0xE1, 0xF8, 0x98, 0x11, 0x69, 0xD9, 0x8E, 0x94, 0x9B, 0x1E, 0x87, 0xE9, 0xCE, 0x55, 0x28, 0xDF, - 0x8C, 0xA1, 0x89, 0x0D, 0xBF, 0xE6, 0x42, 0x68, 0x41, 0x99, 0x2D, 0x0F, 0xB0, 0x54, 0xBB, 0x16, -}; - -static CONST_TABLE(u4_t, AES_E1)[256] = { - 0xC66363A5, 0xF87C7C84, 0xEE777799, 0xF67B7B8D, 0xFFF2F20D, 0xD66B6BBD, 0xDE6F6FB1, 0x91C5C554, - 0x60303050, 0x02010103, 0xCE6767A9, 0x562B2B7D, 0xE7FEFE19, 0xB5D7D762, 0x4DABABE6, 0xEC76769A, - 0x8FCACA45, 0x1F82829D, 0x89C9C940, 0xFA7D7D87, 0xEFFAFA15, 0xB25959EB, 0x8E4747C9, 0xFBF0F00B, - 0x41ADADEC, 0xB3D4D467, 0x5FA2A2FD, 0x45AFAFEA, 0x239C9CBF, 0x53A4A4F7, 0xE4727296, 0x9BC0C05B, - 0x75B7B7C2, 0xE1FDFD1C, 0x3D9393AE, 0x4C26266A, 0x6C36365A, 0x7E3F3F41, 0xF5F7F702, 0x83CCCC4F, - 0x6834345C, 0x51A5A5F4, 0xD1E5E534, 0xF9F1F108, 0xE2717193, 0xABD8D873, 0x62313153, 0x2A15153F, - 0x0804040C, 0x95C7C752, 0x46232365, 0x9DC3C35E, 0x30181828, 0x379696A1, 0x0A05050F, 0x2F9A9AB5, - 0x0E070709, 0x24121236, 0x1B80809B, 0xDFE2E23D, 0xCDEBEB26, 0x4E272769, 0x7FB2B2CD, 0xEA75759F, - 0x1209091B, 0x1D83839E, 0x582C2C74, 0x341A1A2E, 0x361B1B2D, 0xDC6E6EB2, 0xB45A5AEE, 0x5BA0A0FB, - 0xA45252F6, 0x763B3B4D, 0xB7D6D661, 0x7DB3B3CE, 0x5229297B, 0xDDE3E33E, 0x5E2F2F71, 0x13848497, - 0xA65353F5, 0xB9D1D168, 0x00000000, 0xC1EDED2C, 0x40202060, 0xE3FCFC1F, 0x79B1B1C8, 0xB65B5BED, - 0xD46A6ABE, 0x8DCBCB46, 0x67BEBED9, 0x7239394B, 0x944A4ADE, 0x984C4CD4, 0xB05858E8, 0x85CFCF4A, - 0xBBD0D06B, 0xC5EFEF2A, 0x4FAAAAE5, 0xEDFBFB16, 0x864343C5, 0x9A4D4DD7, 0x66333355, 0x11858594, - 0x8A4545CF, 0xE9F9F910, 0x04020206, 0xFE7F7F81, 0xA05050F0, 0x783C3C44, 0x259F9FBA, 0x4BA8A8E3, - 0xA25151F3, 0x5DA3A3FE, 0x804040C0, 0x058F8F8A, 0x3F9292AD, 0x219D9DBC, 0x70383848, 0xF1F5F504, - 0x63BCBCDF, 0x77B6B6C1, 0xAFDADA75, 0x42212163, 0x20101030, 0xE5FFFF1A, 0xFDF3F30E, 0xBFD2D26D, - 0x81CDCD4C, 0x180C0C14, 0x26131335, 0xC3ECEC2F, 0xBE5F5FE1, 0x359797A2, 0x884444CC, 0x2E171739, - 0x93C4C457, 0x55A7A7F2, 0xFC7E7E82, 0x7A3D3D47, 0xC86464AC, 0xBA5D5DE7, 0x3219192B, 0xE6737395, - 0xC06060A0, 0x19818198, 0x9E4F4FD1, 0xA3DCDC7F, 0x44222266, 0x542A2A7E, 0x3B9090AB, 0x0B888883, - 0x8C4646CA, 0xC7EEEE29, 0x6BB8B8D3, 0x2814143C, 0xA7DEDE79, 0xBC5E5EE2, 0x160B0B1D, 0xADDBDB76, - 0xDBE0E03B, 0x64323256, 0x743A3A4E, 0x140A0A1E, 0x924949DB, 0x0C06060A, 0x4824246C, 0xB85C5CE4, - 0x9FC2C25D, 0xBDD3D36E, 0x43ACACEF, 0xC46262A6, 0x399191A8, 0x319595A4, 0xD3E4E437, 0xF279798B, - 0xD5E7E732, 0x8BC8C843, 0x6E373759, 0xDA6D6DB7, 0x018D8D8C, 0xB1D5D564, 0x9C4E4ED2, 0x49A9A9E0, - 0xD86C6CB4, 0xAC5656FA, 0xF3F4F407, 0xCFEAEA25, 0xCA6565AF, 0xF47A7A8E, 0x47AEAEE9, 0x10080818, - 0x6FBABAD5, 0xF0787888, 0x4A25256F, 0x5C2E2E72, 0x381C1C24, 0x57A6A6F1, 0x73B4B4C7, 0x97C6C651, - 0xCBE8E823, 0xA1DDDD7C, 0xE874749C, 0x3E1F1F21, 0x964B4BDD, 0x61BDBDDC, 0x0D8B8B86, 0x0F8A8A85, - 0xE0707090, 0x7C3E3E42, 0x71B5B5C4, 0xCC6666AA, 0x904848D8, 0x06030305, 0xF7F6F601, 0x1C0E0E12, - 0xC26161A3, 0x6A35355F, 0xAE5757F9, 0x69B9B9D0, 0x17868691, 0x99C1C158, 0x3A1D1D27, 0x279E9EB9, - 0xD9E1E138, 0xEBF8F813, 0x2B9898B3, 0x22111133, 0xD26969BB, 0xA9D9D970, 0x078E8E89, 0x339494A7, - 0x2D9B9BB6, 0x3C1E1E22, 0x15878792, 0xC9E9E920, 0x87CECE49, 0xAA5555FF, 0x50282878, 0xA5DFDF7A, - 0x038C8C8F, 0x59A1A1F8, 0x09898980, 0x1A0D0D17, 0x65BFBFDA, 0xD7E6E631, 0x844242C6, 0xD06868B8, - 0x824141C3, 0x299999B0, 0x5A2D2D77, 0x1E0F0F11, 0x7BB0B0CB, 0xA85454FC, 0x6DBBBBD6, 0x2C16163A, -}; - -static CONST_TABLE(u4_t, AES_E2)[256] = { - 0xA5C66363, 0x84F87C7C, 0x99EE7777, 0x8DF67B7B, 0x0DFFF2F2, 0xBDD66B6B, 0xB1DE6F6F, 0x5491C5C5, - 0x50603030, 0x03020101, 0xA9CE6767, 0x7D562B2B, 0x19E7FEFE, 0x62B5D7D7, 0xE64DABAB, 0x9AEC7676, - 0x458FCACA, 0x9D1F8282, 0x4089C9C9, 0x87FA7D7D, 0x15EFFAFA, 0xEBB25959, 0xC98E4747, 0x0BFBF0F0, - 0xEC41ADAD, 0x67B3D4D4, 0xFD5FA2A2, 0xEA45AFAF, 0xBF239C9C, 0xF753A4A4, 0x96E47272, 0x5B9BC0C0, - 0xC275B7B7, 0x1CE1FDFD, 0xAE3D9393, 0x6A4C2626, 0x5A6C3636, 0x417E3F3F, 0x02F5F7F7, 0x4F83CCCC, - 0x5C683434, 0xF451A5A5, 0x34D1E5E5, 0x08F9F1F1, 0x93E27171, 0x73ABD8D8, 0x53623131, 0x3F2A1515, - 0x0C080404, 0x5295C7C7, 0x65462323, 0x5E9DC3C3, 0x28301818, 0xA1379696, 0x0F0A0505, 0xB52F9A9A, - 0x090E0707, 0x36241212, 0x9B1B8080, 0x3DDFE2E2, 0x26CDEBEB, 0x694E2727, 0xCD7FB2B2, 0x9FEA7575, - 0x1B120909, 0x9E1D8383, 0x74582C2C, 0x2E341A1A, 0x2D361B1B, 0xB2DC6E6E, 0xEEB45A5A, 0xFB5BA0A0, - 0xF6A45252, 0x4D763B3B, 0x61B7D6D6, 0xCE7DB3B3, 0x7B522929, 0x3EDDE3E3, 0x715E2F2F, 0x97138484, - 0xF5A65353, 0x68B9D1D1, 0x00000000, 0x2CC1EDED, 0x60402020, 0x1FE3FCFC, 0xC879B1B1, 0xEDB65B5B, - 0xBED46A6A, 0x468DCBCB, 0xD967BEBE, 0x4B723939, 0xDE944A4A, 0xD4984C4C, 0xE8B05858, 0x4A85CFCF, - 0x6BBBD0D0, 0x2AC5EFEF, 0xE54FAAAA, 0x16EDFBFB, 0xC5864343, 0xD79A4D4D, 0x55663333, 0x94118585, - 0xCF8A4545, 0x10E9F9F9, 0x06040202, 0x81FE7F7F, 0xF0A05050, 0x44783C3C, 0xBA259F9F, 0xE34BA8A8, - 0xF3A25151, 0xFE5DA3A3, 0xC0804040, 0x8A058F8F, 0xAD3F9292, 0xBC219D9D, 0x48703838, 0x04F1F5F5, - 0xDF63BCBC, 0xC177B6B6, 0x75AFDADA, 0x63422121, 0x30201010, 0x1AE5FFFF, 0x0EFDF3F3, 0x6DBFD2D2, - 0x4C81CDCD, 0x14180C0C, 0x35261313, 0x2FC3ECEC, 0xE1BE5F5F, 0xA2359797, 0xCC884444, 0x392E1717, - 0x5793C4C4, 0xF255A7A7, 0x82FC7E7E, 0x477A3D3D, 0xACC86464, 0xE7BA5D5D, 0x2B321919, 0x95E67373, - 0xA0C06060, 0x98198181, 0xD19E4F4F, 0x7FA3DCDC, 0x66442222, 0x7E542A2A, 0xAB3B9090, 0x830B8888, - 0xCA8C4646, 0x29C7EEEE, 0xD36BB8B8, 0x3C281414, 0x79A7DEDE, 0xE2BC5E5E, 0x1D160B0B, 0x76ADDBDB, - 0x3BDBE0E0, 0x56643232, 0x4E743A3A, 0x1E140A0A, 0xDB924949, 0x0A0C0606, 0x6C482424, 0xE4B85C5C, - 0x5D9FC2C2, 0x6EBDD3D3, 0xEF43ACAC, 0xA6C46262, 0xA8399191, 0xA4319595, 0x37D3E4E4, 0x8BF27979, - 0x32D5E7E7, 0x438BC8C8, 0x596E3737, 0xB7DA6D6D, 0x8C018D8D, 0x64B1D5D5, 0xD29C4E4E, 0xE049A9A9, - 0xB4D86C6C, 0xFAAC5656, 0x07F3F4F4, 0x25CFEAEA, 0xAFCA6565, 0x8EF47A7A, 0xE947AEAE, 0x18100808, - 0xD56FBABA, 0x88F07878, 0x6F4A2525, 0x725C2E2E, 0x24381C1C, 0xF157A6A6, 0xC773B4B4, 0x5197C6C6, - 0x23CBE8E8, 0x7CA1DDDD, 0x9CE87474, 0x213E1F1F, 0xDD964B4B, 0xDC61BDBD, 0x860D8B8B, 0x850F8A8A, - 0x90E07070, 0x427C3E3E, 0xC471B5B5, 0xAACC6666, 0xD8904848, 0x05060303, 0x01F7F6F6, 0x121C0E0E, - 0xA3C26161, 0x5F6A3535, 0xF9AE5757, 0xD069B9B9, 0x91178686, 0x5899C1C1, 0x273A1D1D, 0xB9279E9E, - 0x38D9E1E1, 0x13EBF8F8, 0xB32B9898, 0x33221111, 0xBBD26969, 0x70A9D9D9, 0x89078E8E, 0xA7339494, - 0xB62D9B9B, 0x223C1E1E, 0x92158787, 0x20C9E9E9, 0x4987CECE, 0xFFAA5555, 0x78502828, 0x7AA5DFDF, - 0x8F038C8C, 0xF859A1A1, 0x80098989, 0x171A0D0D, 0xDA65BFBF, 0x31D7E6E6, 0xC6844242, 0xB8D06868, - 0xC3824141, 0xB0299999, 0x775A2D2D, 0x111E0F0F, 0xCB7BB0B0, 0xFCA85454, 0xD66DBBBB, 0x3A2C1616, -}; - -static CONST_TABLE(u4_t, AES_E3)[256] = { - 0x63A5C663, 0x7C84F87C, 0x7799EE77, 0x7B8DF67B, 0xF20DFFF2, 0x6BBDD66B, 0x6FB1DE6F, 0xC55491C5, - 0x30506030, 0x01030201, 0x67A9CE67, 0x2B7D562B, 0xFE19E7FE, 0xD762B5D7, 0xABE64DAB, 0x769AEC76, - 0xCA458FCA, 0x829D1F82, 0xC94089C9, 0x7D87FA7D, 0xFA15EFFA, 0x59EBB259, 0x47C98E47, 0xF00BFBF0, - 0xADEC41AD, 0xD467B3D4, 0xA2FD5FA2, 0xAFEA45AF, 0x9CBF239C, 0xA4F753A4, 0x7296E472, 0xC05B9BC0, - 0xB7C275B7, 0xFD1CE1FD, 0x93AE3D93, 0x266A4C26, 0x365A6C36, 0x3F417E3F, 0xF702F5F7, 0xCC4F83CC, - 0x345C6834, 0xA5F451A5, 0xE534D1E5, 0xF108F9F1, 0x7193E271, 0xD873ABD8, 0x31536231, 0x153F2A15, - 0x040C0804, 0xC75295C7, 0x23654623, 0xC35E9DC3, 0x18283018, 0x96A13796, 0x050F0A05, 0x9AB52F9A, - 0x07090E07, 0x12362412, 0x809B1B80, 0xE23DDFE2, 0xEB26CDEB, 0x27694E27, 0xB2CD7FB2, 0x759FEA75, - 0x091B1209, 0x839E1D83, 0x2C74582C, 0x1A2E341A, 0x1B2D361B, 0x6EB2DC6E, 0x5AEEB45A, 0xA0FB5BA0, - 0x52F6A452, 0x3B4D763B, 0xD661B7D6, 0xB3CE7DB3, 0x297B5229, 0xE33EDDE3, 0x2F715E2F, 0x84971384, - 0x53F5A653, 0xD168B9D1, 0x00000000, 0xED2CC1ED, 0x20604020, 0xFC1FE3FC, 0xB1C879B1, 0x5BEDB65B, - 0x6ABED46A, 0xCB468DCB, 0xBED967BE, 0x394B7239, 0x4ADE944A, 0x4CD4984C, 0x58E8B058, 0xCF4A85CF, - 0xD06BBBD0, 0xEF2AC5EF, 0xAAE54FAA, 0xFB16EDFB, 0x43C58643, 0x4DD79A4D, 0x33556633, 0x85941185, - 0x45CF8A45, 0xF910E9F9, 0x02060402, 0x7F81FE7F, 0x50F0A050, 0x3C44783C, 0x9FBA259F, 0xA8E34BA8, - 0x51F3A251, 0xA3FE5DA3, 0x40C08040, 0x8F8A058F, 0x92AD3F92, 0x9DBC219D, 0x38487038, 0xF504F1F5, - 0xBCDF63BC, 0xB6C177B6, 0xDA75AFDA, 0x21634221, 0x10302010, 0xFF1AE5FF, 0xF30EFDF3, 0xD26DBFD2, - 0xCD4C81CD, 0x0C14180C, 0x13352613, 0xEC2FC3EC, 0x5FE1BE5F, 0x97A23597, 0x44CC8844, 0x17392E17, - 0xC45793C4, 0xA7F255A7, 0x7E82FC7E, 0x3D477A3D, 0x64ACC864, 0x5DE7BA5D, 0x192B3219, 0x7395E673, - 0x60A0C060, 0x81981981, 0x4FD19E4F, 0xDC7FA3DC, 0x22664422, 0x2A7E542A, 0x90AB3B90, 0x88830B88, - 0x46CA8C46, 0xEE29C7EE, 0xB8D36BB8, 0x143C2814, 0xDE79A7DE, 0x5EE2BC5E, 0x0B1D160B, 0xDB76ADDB, - 0xE03BDBE0, 0x32566432, 0x3A4E743A, 0x0A1E140A, 0x49DB9249, 0x060A0C06, 0x246C4824, 0x5CE4B85C, - 0xC25D9FC2, 0xD36EBDD3, 0xACEF43AC, 0x62A6C462, 0x91A83991, 0x95A43195, 0xE437D3E4, 0x798BF279, - 0xE732D5E7, 0xC8438BC8, 0x37596E37, 0x6DB7DA6D, 0x8D8C018D, 0xD564B1D5, 0x4ED29C4E, 0xA9E049A9, - 0x6CB4D86C, 0x56FAAC56, 0xF407F3F4, 0xEA25CFEA, 0x65AFCA65, 0x7A8EF47A, 0xAEE947AE, 0x08181008, - 0xBAD56FBA, 0x7888F078, 0x256F4A25, 0x2E725C2E, 0x1C24381C, 0xA6F157A6, 0xB4C773B4, 0xC65197C6, - 0xE823CBE8, 0xDD7CA1DD, 0x749CE874, 0x1F213E1F, 0x4BDD964B, 0xBDDC61BD, 0x8B860D8B, 0x8A850F8A, - 0x7090E070, 0x3E427C3E, 0xB5C471B5, 0x66AACC66, 0x48D89048, 0x03050603, 0xF601F7F6, 0x0E121C0E, - 0x61A3C261, 0x355F6A35, 0x57F9AE57, 0xB9D069B9, 0x86911786, 0xC15899C1, 0x1D273A1D, 0x9EB9279E, - 0xE138D9E1, 0xF813EBF8, 0x98B32B98, 0x11332211, 0x69BBD269, 0xD970A9D9, 0x8E89078E, 0x94A73394, - 0x9BB62D9B, 0x1E223C1E, 0x87921587, 0xE920C9E9, 0xCE4987CE, 0x55FFAA55, 0x28785028, 0xDF7AA5DF, - 0x8C8F038C, 0xA1F859A1, 0x89800989, 0x0D171A0D, 0xBFDA65BF, 0xE631D7E6, 0x42C68442, 0x68B8D068, - 0x41C38241, 0x99B02999, 0x2D775A2D, 0x0F111E0F, 0xB0CB7BB0, 0x54FCA854, 0xBBD66DBB, 0x163A2C16, -}; - -static CONST_TABLE(u4_t, AES_E4)[256] = { - 0x6363A5C6, 0x7C7C84F8, 0x777799EE, 0x7B7B8DF6, 0xF2F20DFF, 0x6B6BBDD6, 0x6F6FB1DE, 0xC5C55491, - 0x30305060, 0x01010302, 0x6767A9CE, 0x2B2B7D56, 0xFEFE19E7, 0xD7D762B5, 0xABABE64D, 0x76769AEC, - 0xCACA458F, 0x82829D1F, 0xC9C94089, 0x7D7D87FA, 0xFAFA15EF, 0x5959EBB2, 0x4747C98E, 0xF0F00BFB, - 0xADADEC41, 0xD4D467B3, 0xA2A2FD5F, 0xAFAFEA45, 0x9C9CBF23, 0xA4A4F753, 0x727296E4, 0xC0C05B9B, - 0xB7B7C275, 0xFDFD1CE1, 0x9393AE3D, 0x26266A4C, 0x36365A6C, 0x3F3F417E, 0xF7F702F5, 0xCCCC4F83, - 0x34345C68, 0xA5A5F451, 0xE5E534D1, 0xF1F108F9, 0x717193E2, 0xD8D873AB, 0x31315362, 0x15153F2A, - 0x04040C08, 0xC7C75295, 0x23236546, 0xC3C35E9D, 0x18182830, 0x9696A137, 0x05050F0A, 0x9A9AB52F, - 0x0707090E, 0x12123624, 0x80809B1B, 0xE2E23DDF, 0xEBEB26CD, 0x2727694E, 0xB2B2CD7F, 0x75759FEA, - 0x09091B12, 0x83839E1D, 0x2C2C7458, 0x1A1A2E34, 0x1B1B2D36, 0x6E6EB2DC, 0x5A5AEEB4, 0xA0A0FB5B, - 0x5252F6A4, 0x3B3B4D76, 0xD6D661B7, 0xB3B3CE7D, 0x29297B52, 0xE3E33EDD, 0x2F2F715E, 0x84849713, - 0x5353F5A6, 0xD1D168B9, 0x00000000, 0xEDED2CC1, 0x20206040, 0xFCFC1FE3, 0xB1B1C879, 0x5B5BEDB6, - 0x6A6ABED4, 0xCBCB468D, 0xBEBED967, 0x39394B72, 0x4A4ADE94, 0x4C4CD498, 0x5858E8B0, 0xCFCF4A85, - 0xD0D06BBB, 0xEFEF2AC5, 0xAAAAE54F, 0xFBFB16ED, 0x4343C586, 0x4D4DD79A, 0x33335566, 0x85859411, - 0x4545CF8A, 0xF9F910E9, 0x02020604, 0x7F7F81FE, 0x5050F0A0, 0x3C3C4478, 0x9F9FBA25, 0xA8A8E34B, - 0x5151F3A2, 0xA3A3FE5D, 0x4040C080, 0x8F8F8A05, 0x9292AD3F, 0x9D9DBC21, 0x38384870, 0xF5F504F1, - 0xBCBCDF63, 0xB6B6C177, 0xDADA75AF, 0x21216342, 0x10103020, 0xFFFF1AE5, 0xF3F30EFD, 0xD2D26DBF, - 0xCDCD4C81, 0x0C0C1418, 0x13133526, 0xECEC2FC3, 0x5F5FE1BE, 0x9797A235, 0x4444CC88, 0x1717392E, - 0xC4C45793, 0xA7A7F255, 0x7E7E82FC, 0x3D3D477A, 0x6464ACC8, 0x5D5DE7BA, 0x19192B32, 0x737395E6, - 0x6060A0C0, 0x81819819, 0x4F4FD19E, 0xDCDC7FA3, 0x22226644, 0x2A2A7E54, 0x9090AB3B, 0x8888830B, - 0x4646CA8C, 0xEEEE29C7, 0xB8B8D36B, 0x14143C28, 0xDEDE79A7, 0x5E5EE2BC, 0x0B0B1D16, 0xDBDB76AD, - 0xE0E03BDB, 0x32325664, 0x3A3A4E74, 0x0A0A1E14, 0x4949DB92, 0x06060A0C, 0x24246C48, 0x5C5CE4B8, - 0xC2C25D9F, 0xD3D36EBD, 0xACACEF43, 0x6262A6C4, 0x9191A839, 0x9595A431, 0xE4E437D3, 0x79798BF2, - 0xE7E732D5, 0xC8C8438B, 0x3737596E, 0x6D6DB7DA, 0x8D8D8C01, 0xD5D564B1, 0x4E4ED29C, 0xA9A9E049, - 0x6C6CB4D8, 0x5656FAAC, 0xF4F407F3, 0xEAEA25CF, 0x6565AFCA, 0x7A7A8EF4, 0xAEAEE947, 0x08081810, - 0xBABAD56F, 0x787888F0, 0x25256F4A, 0x2E2E725C, 0x1C1C2438, 0xA6A6F157, 0xB4B4C773, 0xC6C65197, - 0xE8E823CB, 0xDDDD7CA1, 0x74749CE8, 0x1F1F213E, 0x4B4BDD96, 0xBDBDDC61, 0x8B8B860D, 0x8A8A850F, - 0x707090E0, 0x3E3E427C, 0xB5B5C471, 0x6666AACC, 0x4848D890, 0x03030506, 0xF6F601F7, 0x0E0E121C, - 0x6161A3C2, 0x35355F6A, 0x5757F9AE, 0xB9B9D069, 0x86869117, 0xC1C15899, 0x1D1D273A, 0x9E9EB927, - 0xE1E138D9, 0xF8F813EB, 0x9898B32B, 0x11113322, 0x6969BBD2, 0xD9D970A9, 0x8E8E8907, 0x9494A733, - 0x9B9BB62D, 0x1E1E223C, 0x87879215, 0xE9E920C9, 0xCECE4987, 0x5555FFAA, 0x28287850, 0xDFDF7AA5, - 0x8C8C8F03, 0xA1A1F859, 0x89898009, 0x0D0D171A, 0xBFBFDA65, 0xE6E631D7, 0x4242C684, 0x6868B8D0, - 0x4141C382, 0x9999B029, 0x2D2D775A, 0x0F0F111E, 0xB0B0CB7B, 0x5454FCA8, 0xBBBBD66D, 0x16163A2C, -}; - -#define msbf4_read(p) ((p)[0]<<24 | (p)[1]<<16 | (p)[2]<<8 | (p)[3]) -#define msbf4_write(p,v) (p)[0]=(v)>>24,(p)[1]=(v)>>16,(p)[2]=(v)>>8,(p)[3]=(v) -#define swapmsbf(x) ( (x&0xFF)<<24 | (x&0xFF00)<<8 | (x&0xFF0000)>>8 | (x>>24) ) - -#define u1(v) ((u1_t)(v)) - -#define AES_key4(r1,r2,r3,r0,i) r1 = ki[i+1]; \ - r2 = ki[i+2]; \ - r3 = ki[i+3]; \ - r0 = ki[i] - -#define AES_expr4(r1,r2,r3,r0,i) r1 ^= TABLE_GET_U4(AES_E4, u1(i)); \ - r2 ^= TABLE_GET_U4(AES_E3, u1(i>>8)); \ - r3 ^= TABLE_GET_U4(AES_E2, u1(i>>16)); \ - r0 ^= TABLE_GET_U4(AES_E1, (i>>24)) - -#define AES_expr(a,r0,r1,r2,r3,i) a = ki[i]; \ - a ^= ((u4_t)TABLE_GET_U1(AES_S, r0>>24 )<<24); \ - a ^= ((u4_t)TABLE_GET_U1(AES_S, u1(r1>>16))<<16); \ - a ^= ((u4_t)TABLE_GET_U1(AES_S, u1(r2>> 8))<< 8); \ - a ^= (u4_t)TABLE_GET_U1(AES_S, u1(r3) ) - -// global area for passing parameters (aux, key) and for storing round keys -u4_t AESAUX[16/sizeof(u4_t)]; -u4_t AESKEY[11*16/sizeof(u4_t)]; - -// generate 1+10 roundkeys for encryption with 128-bit key -// read 128-bit key from AESKEY in MSBF, generate roundkey words in place -static void aesroundkeys () { - int i; - u4_t b; - - for( i=0; i<4; i++) { - AESKEY[i] = swapmsbf(AESKEY[i]); - } - - b = AESKEY[3]; - for( ; i<44; i++ ) { - if( i%4==0 ) { - // b = SubWord(RotWord(b)) xor Rcon[i/4] - b = ((u4_t)TABLE_GET_U1(AES_S, u1(b >> 16)) << 24) ^ - ((u4_t)TABLE_GET_U1(AES_S, u1(b >> 8)) << 16) ^ - ((u4_t)TABLE_GET_U1(AES_S, u1(b) ) << 8) ^ - ((u4_t)TABLE_GET_U1(AES_S, b >> 24 ) ) ^ - TABLE_GET_U4(AES_RCON, (i-4)/4); - } - AESKEY[i] = b ^= AESKEY[i-4]; - } -} - -u4_t os_aes (u1_t mode, xref2u1_t buf, u2_t len) { - - aesroundkeys(); - - if( mode & AES_MICNOAUX ) { - AESAUX[0] = AESAUX[1] = AESAUX[2] = AESAUX[3] = 0; - } else { - AESAUX[0] = swapmsbf(AESAUX[0]); - AESAUX[1] = swapmsbf(AESAUX[1]); - AESAUX[2] = swapmsbf(AESAUX[2]); - AESAUX[3] = swapmsbf(AESAUX[3]); - } - - while( (signed char)len > 0 ) { - u4_t a0, a1, a2, a3; - u4_t t0, t1, t2, t3; - u4_t *ki, *ke; - - // load input block - if( (mode & AES_CTR) || ((mode & AES_MIC) && (mode & AES_MICNOAUX)==0) ) { // load CTR block or first MIC block - a0 = AESAUX[0]; - a1 = AESAUX[1]; - a2 = AESAUX[2]; - a3 = AESAUX[3]; - } - else if( (mode & AES_MIC) && len <= 16 ) { // last MIC block - a0 = a1 = a2 = a3 = 0; // load null block - mode |= ((len == 16) ? 1 : 2) << 4; // set MICSUB: CMAC subkey K1 or K2 - } else - LOADDATA: { // load data block (partially) - for(t0=0; t0<16; t0++) { - t1 = (t1<<8) | ((t0> 4) != 0 ) { // last block - do { - // compute CMAC subkey K1 and K2 - t0 = a0 >> 31; // save MSB - a0 = (a0 << 1) | (a1 >> 31); - a1 = (a1 << 1) | (a2 >> 31); - a2 = (a2 << 1) | (a3 >> 31); - a3 = (a3 << 1); - if( t0 ) a3 ^= 0x87; - } while( --t1 ); - - AESAUX[0] ^= a0; - AESAUX[1] ^= a1; - AESAUX[2] ^= a2; - AESAUX[3] ^= a3; - mode &= ~AES_MICSUB; - goto LOADDATA; - } else { - // save cipher block as new iv - AESAUX[0] = a0; - AESAUX[1] = a1; - AESAUX[2] = a2; - AESAUX[3] = a3; - } - } else { // CIPHER - if( mode & AES_CTR ) { // xor block (partially) - t0 = (len > 16) ? 16: len; - for(t1=0; t1>24); - a0 <<= 8; - if((t1&3)==3) { - a0 = a1; - a1 = a2; - a2 = a3; - } - } - // update counter - AESAUX[3]++; - } else { // ECB - // store block - msbf4_write(buf+0, a0); - msbf4_write(buf+4, a1); - msbf4_write(buf+8, a2); - msbf4_write(buf+12, a3); - } - } - - // update block state - if( (mode & AES_MIC)==0 || (mode & AES_MICNOAUX) ) { - buf += 16; - len -= 16; - } - mode |= AES_MICNOAUX; - } - return AESAUX[0]; -} - -#endif diff --git a/lib/arduino-lmic-1.5.0-arduino-2-tweaked/src/aes/other.c b/lib/arduino-lmic-1.5.0-arduino-2-tweaked/src/aes/other.c deleted file mode 100644 index d0156222..00000000 --- a/lib/arduino-lmic-1.5.0-arduino-2-tweaked/src/aes/other.c +++ /dev/null @@ -1,145 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2016 Matthijs Kooijman - * - * LICENSE - * - * Permission is hereby granted, free of charge, to anyone - * obtaining a copy of this document and accompanying files, - * to do whatever they want with them without any restriction, - * including, but not limited to, copying, modification and - * redistribution. - * - * NO WARRANTY OF ANY KIND IS PROVIDED. - *******************************************************************************/ - -/* - * The original LMIC AES implementation integrates raw AES encryption - * with CMAC and AES-CTR in a single piece of code. Most other AES - * implementations (only) offer raw single block AES encryption, so this - * file contains an implementation of CMAC and AES-CTR, and offers the - * same API through the os_aes() function as the original AES - * implementation. This file assumes that there is an encryption - * function available with this signature: - * - * extern "C" void lmic_aes_encrypt(u1_t *data, u1_t *key); - * - * That takes a single 16-byte buffer and encrypts it wit the given - * 16-byte key. - */ - -#include "../lmic/oslmic.h" - -#if !defined(USE_ORIGINAL_AES) - -// This should be defined elsewhere -void lmic_aes_encrypt(u1_t *data, u1_t *key); - -// global area for passing parameters (aux, key) -u4_t AESAUX[16/sizeof(u4_t)]; -u4_t AESKEY[16/sizeof(u4_t)]; - -// Shift the given buffer left one bit -static void shift_left(xref2u1_t buf, u1_t len) { - while (len--) { - u1_t next = len ? buf[1] : 0; - - u1_t val = (*buf << 1); - if (next & 0x80) - val |= 1; - *buf++ = val; - } -} - -// Apply RFC4493 CMAC, using AESKEY as the key. If prepend_aux is true, -// AESAUX is prepended to the message. AESAUX is used as working memory -// in any case. The CMAC result is returned in AESAUX as well. -static void os_aes_cmac(xref2u1_t buf, u2_t len, u1_t prepend_aux) { - if (prepend_aux) - lmic_aes_encrypt(AESaux, AESkey); - else - memset (AESaux, 0, 16); - - while (len > 0) { - u1_t need_padding = 0; - for (u1_t i = 0; i < 16; ++i, ++buf, --len) { - if (len == 0) { - // The message is padded with 0x80 and then zeroes. - // Since zeroes are no-op for xor, we can just skip them - // and leave AESAUX unchanged for them. - AESaux[i] ^= 0x80; - need_padding = 1; - break; - } - AESaux[i] ^= *buf; - } - - if (len == 0) { - // Final block, xor with K1 or K2. K1 and K2 are calculated - // by encrypting the all-zeroes block and then applying some - // shifts and xor on that. - u1_t final_key[16]; - memset(final_key, 0, sizeof(final_key)); - lmic_aes_encrypt(final_key, AESkey); - - // Calculate K1 - u1_t msb = final_key[0] & 0x80; - shift_left(final_key, sizeof(final_key)); - if (msb) - final_key[sizeof(final_key)-1] ^= 0x87; - - // If the final block was not complete, calculate K2 from K1 - if (need_padding) { - msb = final_key[0] & 0x80; - shift_left(final_key, sizeof(final_key)); - if (msb) - final_key[sizeof(final_key)-1] ^= 0x87; - } - - // Xor with K1 or K2 - for (u1_t i = 0; i < sizeof(final_key); ++i) - AESaux[i] ^= final_key[i]; - } - - lmic_aes_encrypt(AESaux, AESkey); - } -} - -// Run AES-CTR using the key in AESKEY and using AESAUX as the -// counter block. The last byte of the counter block will be incremented -// for every block. The given buffer will be encrypted in place. -static void os_aes_ctr (xref2u1_t buf, u2_t len) { - u1_t ctr[16]; - while (len) { - // Encrypt the counter block with the selected key - memcpy(ctr, AESaux, sizeof(ctr)); - lmic_aes_encrypt(ctr, AESkey); - - // Xor the payload with the resulting ciphertext - for (u1_t i = 0; i < 16 && len > 0; i++, len--, buf++) - *buf ^= ctr[i]; - - // Increment the block index byte - AESaux[15]++; - } -} - -u4_t os_aes (u1_t mode, xref2u1_t buf, u2_t len) { - switch (mode & ~AES_MICNOAUX) { - case AES_MIC: - os_aes_cmac(buf, len, /* prepend_aux */ !(mode & AES_MICNOAUX)); - return os_rmsbf4(AESaux); - - case AES_ENC: - // TODO: Check / handle when len is not a multiple of 16 - for (u1_t i = 0; i < len; i += 16) - lmic_aes_encrypt(buf+i, AESkey); - break; - - case AES_CTR: - os_aes_ctr(buf, len); - break; - } - return 0; -} - -#endif // !defined(USE_ORIGINAL_AES) diff --git a/lib/arduino-lmic-1.5.0-arduino-2-tweaked/src/hal/hal.cpp b/lib/arduino-lmic-1.5.0-arduino-2-tweaked/src/hal/hal.cpp deleted file mode 100644 index 6ee413fa..00000000 --- a/lib/arduino-lmic-1.5.0-arduino-2-tweaked/src/hal/hal.cpp +++ /dev/null @@ -1,269 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2015 Matthijs Kooijman - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * http://www.eclipse.org/legal/epl-v10.html - * - * This the HAL to run LMIC on top of the Arduino environment. - *******************************************************************************/ - -#include -#include -#include "../lmic.h" -#include "hal.h" -#include - -// ----------------------------------------------------------------------------- -// I/O - -static void hal_io_init () { - // NSS and DIO0 are required, DIO1 is required for LoRa, DIO2 for FSK - ASSERT(lmic_pins.nss != LMIC_UNUSED_PIN); - ASSERT(lmic_pins.dio[0] != LMIC_UNUSED_PIN); - ASSERT(lmic_pins.dio[1] != LMIC_UNUSED_PIN || lmic_pins.dio[2] != LMIC_UNUSED_PIN); - - #ifdef LMIC_SPI_PINS_IN_MAPPING - ASSERT(lmic_pins.mosi != LMIC_UNUSED_PIN - || lmic_pins.miso != LMIC_UNUSED_PIN - || lmic_pins.sck != LMIC_UNUSED_PIN); - #endif - - pinMode(lmic_pins.nss, OUTPUT); - if (lmic_pins.rxtx != LMIC_UNUSED_PIN) - pinMode(lmic_pins.rxtx, OUTPUT); - if (lmic_pins.rst != LMIC_UNUSED_PIN) - pinMode(lmic_pins.rst, OUTPUT); - - pinMode(lmic_pins.dio[0], INPUT); - if (lmic_pins.dio[1] != LMIC_UNUSED_PIN) - pinMode(lmic_pins.dio[1], INPUT); - if (lmic_pins.dio[2] != LMIC_UNUSED_PIN) - pinMode(lmic_pins.dio[2], INPUT); -} - -// val == 1 => tx 1 -void hal_pin_rxtx (u1_t val) { - if (lmic_pins.rxtx != LMIC_UNUSED_PIN) - digitalWrite(lmic_pins.rxtx, val); -} - -// set radio RST pin to given value (or keep floating!) -void hal_pin_rst (u1_t val) { - if (lmic_pins.rst == LMIC_UNUSED_PIN) - return; - - if(val == 0 || val == 1) { // drive pin - pinMode(lmic_pins.rst, OUTPUT); - digitalWrite(lmic_pins.rst, val); - } else { // keep pin floating - pinMode(lmic_pins.rst, INPUT); - } -} - -static bool dio_states[NUM_DIO] = {0}; - -static void hal_io_check() { - uint8_t i; - for (i = 0; i < NUM_DIO; ++i) { - if (lmic_pins.dio[i] == LMIC_UNUSED_PIN) - continue; - - if (dio_states[i] != digitalRead(lmic_pins.dio[i])) { - dio_states[i] = !dio_states[i]; - if (dio_states[i]) - radio_irq_handler(i); - } - } -} - -// ----------------------------------------------------------------------------- -// SPI - -static const SPISettings settings(10E6, MSBFIRST, SPI_MODE0); - -// Initialize SPI, allowing override of default SPI pins on certain boards. -static void hal_spi_init () { - #if defined(ESP32) - // On the ESP32 the default is _use_hw_ss(false), - // so we can set the last parameter to anything. - SPI.begin(lmic_pins.sck, lmic_pins.miso, lmic_pins.mosi, 0x00); - #elif defined(NRF51) - SPI.begin(lmic_pins.sck, lmic_pins.mosi, lmic_pins.miso); - #else - //unknown board, or board without SPI pin select ability - SPI.begin(); - #endif -} - -void hal_pin_nss (u1_t val) { - if (!val) - SPI.beginTransaction(settings); - else - SPI.endTransaction(); - - //Serial.println(val?">>":"<<"); - digitalWrite(lmic_pins.nss, val); -} - -// perform SPI transaction with radio -u1_t hal_spi (u1_t out) { - u1_t res = SPI.transfer(out); -/* - Serial.print(">"); - Serial.print(out, HEX); - Serial.print("<"); - Serial.println(res, HEX); - */ - return res; -} - -// ----------------------------------------------------------------------------- -// TIME - -static void hal_time_init () { - // Nothing to do -} - -u4_t hal_ticks () { - // Because micros() is scaled down in this function, micros() will - // overflow before the tick timer should, causing the tick timer to - // miss a significant part of its values if not corrected. To fix - // this, the "overflow" serves as an overflow area for the micros() - // counter. It consists of three parts: - // - The US_PER_OSTICK upper bits are effectively an extension for - // the micros() counter and are added to the result of this - // function. - // - The next bit overlaps with the most significant bit of - // micros(). This is used to detect micros() overflows. - // - The remaining bits are always zero. - // - // By comparing the overlapping bit with the corresponding bit in - // the micros() return value, overflows can be detected and the - // upper bits are incremented. This is done using some clever - // bitwise operations, to remove the need for comparisons and a - // jumps, which should result in efficient code. By avoiding shifts - // other than by multiples of 8 as much as possible, this is also - // efficient on AVR (which only has 1-bit shifts). - static uint8_t overflow = 0; - - // Scaled down timestamp. The top US_PER_OSTICK_EXPONENT bits are 0, - // the others will be the lower bits of our return value. - uint32_t scaled = micros() >> US_PER_OSTICK_EXPONENT; - // Most significant byte of scaled - uint8_t msb = scaled >> 24; - // Mask pointing to the overlapping bit in msb and overflow. - const uint8_t mask = (1 << (7 - US_PER_OSTICK_EXPONENT)); - // Update overflow. If the overlapping bit is different - // between overflow and msb, it is added to the stored value, - // so the overlapping bit becomes equal again and, if it changed - // from 1 to 0, the upper bits are incremented. - overflow += (msb ^ overflow) & mask; - - // Return the scaled value with the upper bits of stored added. The - // overlapping bit will be equal and the lower bits will be 0, so - // bitwise or is a no-op for them. - return scaled | ((uint32_t)overflow << 24); - - // 0 leads to correct, but overly complex code (it could just return - // micros() unmodified), 8 leaves no room for the overlapping bit. - static_assert(US_PER_OSTICK_EXPONENT > 0 && US_PER_OSTICK_EXPONENT < 8, "Invalid US_PER_OSTICK_EXPONENT value"); -} - -// Returns the number of ticks until time. Negative values indicate that -// time has already passed. -static s4_t delta_time(u4_t time) { - return (s4_t)(time - hal_ticks()); -} - -void hal_waitUntil (u4_t time) { - s4_t delta = delta_time(time); - // From delayMicroseconds docs: Currently, the largest value that - // will produce an accurate delay is 16383. - while (delta > (16000 / US_PER_OSTICK)) { - delay(16); - delta -= (16000 / US_PER_OSTICK); - } - if (delta > 0) - delayMicroseconds(delta * US_PER_OSTICK); -} - -// check and rewind for target time -u1_t hal_checkTimer (u4_t time) { - // No need to schedule wakeup, since we're not sleeping - return delta_time(time) <= 0; -} - -static uint8_t irqlevel = 0; - -void hal_disableIRQs () { - noInterrupts(); - irqlevel++; -} - -void hal_enableIRQs () { - if(--irqlevel == 0) { - interrupts(); - - // Instead of using proper interrupts (which are a bit tricky - // and/or not available on all pins on AVR), just poll the pin - // values. Since os_runloop disables and re-enables interrupts, - // putting this here makes sure we check at least once every - // loop. - // - // As an additional bonus, this prevents the can of worms that - // we would otherwise get for running SPI transfers inside ISRs - hal_io_check(); - } -} - -void hal_sleep () { - // Not implemented -} - -// ----------------------------------------------------------------------------- - -#if defined(LMIC_PRINTF_TO) -static int uart_putchar (char c, FILE *) -{ - LMIC_PRINTF_TO.write(c) ; - return 0 ; -} - -void hal_printf_init() { - // create a FILE structure to reference our UART output function - static FILE uartout; - memset(&uartout, 0, sizeof(uartout)); - - // fill in the UART file descriptor with pointer to writer. - fdev_setup_stream (&uartout, uart_putchar, NULL, _FDEV_SETUP_WRITE); - - // The uart is the standard output device STDOUT. - stdout = &uartout ; -} -#endif // defined(LMIC_PRINTF_TO) - -void hal_init () { - // configure radio I/O and interrupt handler - hal_io_init(); - // configure radio SPI - hal_spi_init(); - // configure timer and interrupt handler - hal_time_init(); -#if defined(LMIC_PRINTF_TO) - // printf support - hal_printf_init(); -#endif -} - -void hal_failed (const char *file, u2_t line) { -#if defined(LMIC_FAILURE_TO) - LMIC_FAILURE_TO.println("FAILURE "); - LMIC_FAILURE_TO.print(file); - LMIC_FAILURE_TO.print(':'); - LMIC_FAILURE_TO.println(line); - LMIC_FAILURE_TO.flush(); -#endif - hal_disableIRQs(); - while(1); -} diff --git a/lib/arduino-lmic-1.5.0-arduino-2-tweaked/src/hal/hal.h b/lib/arduino-lmic-1.5.0-arduino-2-tweaked/src/hal/hal.h deleted file mode 100644 index a7d81d79..00000000 --- a/lib/arduino-lmic-1.5.0-arduino-2-tweaked/src/hal/hal.h +++ /dev/null @@ -1,41 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2015 Matthijs Kooijman - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * http://www.eclipse.org/legal/epl-v10.html - * - * This the HAL to run LMIC on top of the Arduino environment. - *******************************************************************************/ -#ifndef _hal_hal_h_ -#define _hal_hal_h_ - -static const int NUM_DIO = 3; - -#if defined(ESP32) || defined(NRF51) -#define LMIC_SPI_PINS_IN_MAPPING - struct lmic_pinmap { - u1_t mosi; - u1_t miso; - u1_t sck; - u1_t nss; - u1_t rxtx; - u1_t rst; - u1_t dio[NUM_DIO]; - }; -#else - struct lmic_pinmap { - u1_t nss; - u1_t rxtx; - u1_t rst; - u1_t dio[NUM_DIO]; - }; -#endif - -// Use this for any unused pins. -const u1_t LMIC_UNUSED_PIN = 0xff; - -// Declared here, to be defined an initialized by the application -extern const lmic_pinmap lmic_pins; - -#endif // _hal_hal_h_ diff --git a/lib/arduino-lmic-1.5.0-arduino-2-tweaked/src/lmic.h b/lib/arduino-lmic-1.5.0-arduino-2-tweaked/src/lmic.h deleted file mode 100644 index f081e82d..00000000 --- a/lib/arduino-lmic-1.5.0-arduino-2-tweaked/src/lmic.h +++ /dev/null @@ -1,9 +0,0 @@ -#ifdef __cplusplus -extern "C"{ -#endif - -#include "lmic/lmic.h" - -#ifdef __cplusplus -} -#endif diff --git a/lib/arduino-lmic-1.5.0-arduino-2-tweaked/src/lmic/hal.h b/lib/arduino-lmic-1.5.0-arduino-2-tweaked/src/lmic/hal.h deleted file mode 100644 index 7f2a9f46..00000000 --- a/lib/arduino-lmic-1.5.0-arduino-2-tweaked/src/lmic/hal.h +++ /dev/null @@ -1,91 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2014-2015 IBM Corporation. - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * http://www.eclipse.org/legal/epl-v10.html - * - * Contributors: - * IBM Zurich Research Lab - initial API, implementation and documentation - *******************************************************************************/ - -#ifndef _hal_hpp_ -#define _hal_hpp_ - -#ifdef __cplusplus -extern "C"{ -#endif - -/* - * initialize hardware (IO, SPI, TIMER, IRQ). - */ -void hal_init (void); - -/* - * drive radio NSS pin (0=low, 1=high). - */ -void hal_pin_nss (u1_t val); - -/* - * drive radio RX/TX pins (0=rx, 1=tx). - */ -void hal_pin_rxtx (u1_t val); - -/* - * control radio RST pin (0=low, 1=high, 2=floating) - */ -void hal_pin_rst (u1_t val); - -/* - * perform 8-bit SPI transaction with radio. - * - write given byte 'outval' - * - read byte and return value - */ -u1_t hal_spi (u1_t outval); - -/* - * disable all CPU interrupts. - * - might be invoked nested - * - will be followed by matching call to hal_enableIRQs() - */ -void hal_disableIRQs (void); - -/* - * enable CPU interrupts. - */ -void hal_enableIRQs (void); - -/* - * put system and CPU in low-power mode, sleep until interrupt. - */ -void hal_sleep (void); - -/* - * return 32-bit system time in ticks. - */ -u4_t hal_ticks (void); - -/* - * busy-wait until specified timestamp (in ticks) is reached. - */ -void hal_waitUntil (u4_t time); - -/* - * check and rewind timer for target time. - * - return 1 if target time is close - * - otherwise rewind timer for target time or full period and return 0 - */ -u1_t hal_checkTimer (u4_t targettime); - -/* - * perform fatal failure action. - * - called by assertions - * - action could be HALT or reboot - */ -void hal_failed (const char *file, u2_t line); - -#ifdef __cplusplus -} // extern "C" -#endif - -#endif // _hal_hpp_ diff --git a/lib/arduino-lmic-1.5.0-arduino-2-tweaked/src/lmic/lmic.c b/lib/arduino-lmic-1.5.0-arduino-2-tweaked/src/lmic/lmic.c deleted file mode 100644 index a6e42933..00000000 --- a/lib/arduino-lmic-1.5.0-arduino-2-tweaked/src/lmic/lmic.c +++ /dev/null @@ -1,2382 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2014-2015 IBM Corporation. - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * http://www.eclipse.org/legal/epl-v10.html - * - * Contributors: - * IBM Zurich Research Lab - initial API, implementation and documentation - *******************************************************************************/ - -//! \file -#include "lmic.h" - -#if defined(DISABLE_BEACONS) && !defined(DISABLE_PING) -#error Ping needs beacon tracking -#endif - -#if !defined(MINRX_SYMS) -#define MINRX_SYMS 5 -#endif // !defined(MINRX_SYMS) -#define PAMBL_SYMS 8 -#define PAMBL_FSK 5 -#define PRERX_FSK 1 -#define RXLEN_FSK (1+5+2) - -#define BCN_INTV_osticks sec2osticks(BCN_INTV_sec) -#define TXRX_GUARD_osticks ms2osticks(TXRX_GUARD_ms) -#define JOIN_GUARD_osticks ms2osticks(JOIN_GUARD_ms) -#define DELAY_JACC1_osticks sec2osticks(DELAY_JACC1) -#define DELAY_JACC2_osticks sec2osticks(DELAY_JACC2) -#define DELAY_EXTDNW2_osticks sec2osticks(DELAY_EXTDNW2) -#define BCN_RESERVE_osticks ms2osticks(BCN_RESERVE_ms) -#define BCN_GUARD_osticks ms2osticks(BCN_GUARD_ms) -#define BCN_WINDOW_osticks ms2osticks(BCN_WINDOW_ms) -#define AIRTIME_BCN_osticks us2osticks(AIRTIME_BCN) -#if defined(CFG_eu868) -#define DNW2_SAFETY_ZONE ms2osticks(3000) -#endif -#if defined(CFG_us915) -#define DNW2_SAFETY_ZONE ms2osticks(750) -#endif - -// Special APIs - for development or testing -#define isTESTMODE() 0 - -DEFINE_LMIC; - - -// Fwd decls. -static void engineUpdate(void); -static void startScan (void); - - -// ================================================================================ -// BEG OS - default implementations for certain OS suport functions - -#if !defined(HAS_os_calls) - -#if !defined(os_rlsbf2) -u2_t os_rlsbf2 (xref2cu1_t buf) { - return (u2_t)((u2_t)buf[0] | ((u2_t)buf[1]<<8)); -} -#endif - -#if !defined(os_rlsbf4) -u4_t os_rlsbf4 (xref2cu1_t buf) { - return (u4_t)((u4_t)buf[0] | ((u4_t)buf[1]<<8) | ((u4_t)buf[2]<<16) | ((u4_t)buf[3]<<24)); -} -#endif - - -#if !defined(os_rmsbf4) -u4_t os_rmsbf4 (xref2cu1_t buf) { - return (u4_t)((u4_t)buf[3] | ((u4_t)buf[2]<<8) | ((u4_t)buf[1]<<16) | ((u4_t)buf[0]<<24)); -} -#endif - - -#if !defined(os_wlsbf2) -void os_wlsbf2 (xref2u1_t buf, u2_t v) { - buf[0] = v; - buf[1] = v>>8; -} -#endif - -#if !defined(os_wlsbf4) -void os_wlsbf4 (xref2u1_t buf, u4_t v) { - buf[0] = v; - buf[1] = v>>8; - buf[2] = v>>16; - buf[3] = v>>24; -} -#endif - -#if !defined(os_wmsbf4) -void os_wmsbf4 (xref2u1_t buf, u4_t v) { - buf[3] = v; - buf[2] = v>>8; - buf[1] = v>>16; - buf[0] = v>>24; -} -#endif - -#if !defined(os_getBattLevel) -u1_t os_getBattLevel (void) { - return MCMD_DEVS_BATT_NOINFO; -} -#endif - -#if !defined(os_crc16) -// New CRC-16 CCITT(XMODEM) checksum for beacons: -u2_t os_crc16 (xref2u1_t data, uint len) { - u2_t remainder = 0; - u2_t polynomial = 0x1021; - for( uint i = 0; i < len; i++ ) { - remainder ^= data[i] << 8; - for( u1_t bit = 8; bit > 0; bit--) { - if( (remainder & 0x8000) ) - remainder = (remainder << 1) ^ polynomial; - else - remainder <<= 1; - } - } - return remainder; -} -#endif - -#endif // !HAS_os_calls - -// END OS - default implementations for certain OS suport functions -// ================================================================================ - -// ================================================================================ -// BEG AES - -static void micB0 (u4_t devaddr, u4_t seqno, int dndir, int len) { - os_clearMem(AESaux,16); - AESaux[0] = 0x49; - AESaux[5] = dndir?1:0; - AESaux[15] = len; - os_wlsbf4(AESaux+ 6,devaddr); - os_wlsbf4(AESaux+10,seqno); -} - - -static int aes_verifyMic (xref2cu1_t key, u4_t devaddr, u4_t seqno, int dndir, xref2u1_t pdu, int len) { - micB0(devaddr, seqno, dndir, len); - os_copyMem(AESkey,key,16); - return os_aes(AES_MIC, pdu, len) == os_rmsbf4(pdu+len); -} - - -static void aes_appendMic (xref2cu1_t key, u4_t devaddr, u4_t seqno, int dndir, xref2u1_t pdu, int len) { - micB0(devaddr, seqno, dndir, len); - os_copyMem(AESkey,key,16); - // MSB because of internal structure of AES - os_wmsbf4(pdu+len, os_aes(AES_MIC, pdu, len)); -} - - -static void aes_appendMic0 (xref2u1_t pdu, int len) { - os_getDevKey(AESkey); - os_wmsbf4(pdu+len, os_aes(AES_MIC|AES_MICNOAUX, pdu, len)); // MSB because of internal structure of AES -} - - -static int aes_verifyMic0 (xref2u1_t pdu, int len) { - os_getDevKey(AESkey); - return os_aes(AES_MIC|AES_MICNOAUX, pdu, len) == os_rmsbf4(pdu+len); -} - - -static void aes_encrypt (xref2u1_t pdu, int len) { - os_getDevKey(AESkey); - os_aes(AES_ENC, pdu, len); -} - - -static void aes_cipher (xref2cu1_t key, u4_t devaddr, u4_t seqno, int dndir, xref2u1_t payload, int len) { - if( len <= 0 ) - return; - os_clearMem(AESaux, 16); - AESaux[0] = AESaux[15] = 1; // mode=cipher / dir=down / block counter=1 - AESaux[5] = dndir?1:0; - os_wlsbf4(AESaux+ 6,devaddr); - os_wlsbf4(AESaux+10,seqno); - os_copyMem(AESkey,key,16); - os_aes(AES_CTR, payload, len); -} - - -static void aes_sessKeys (u2_t devnonce, xref2cu1_t artnonce, xref2u1_t nwkkey, xref2u1_t artkey) { - os_clearMem(nwkkey, 16); - nwkkey[0] = 0x01; - os_copyMem(nwkkey+1, artnonce, LEN_ARTNONCE+LEN_NETID); - os_wlsbf2(nwkkey+1+LEN_ARTNONCE+LEN_NETID, devnonce); - os_copyMem(artkey, nwkkey, 16); - artkey[0] = 0x02; - - os_getDevKey(AESkey); - os_aes(AES_ENC, nwkkey, 16); - os_getDevKey(AESkey); - os_aes(AES_ENC, artkey, 16); -} - -// END AES -// ================================================================================ - - -// ================================================================================ -// BEG LORA - -#if defined(CFG_eu868) // ======================================== - -#define maxFrameLen(dr) ((dr)<=DR_SF9 ? TABLE_GET_U1(maxFrameLens, (dr)) : 0xFF) -CONST_TABLE(u1_t, maxFrameLens) [] = { 64,64,64,123 }; - -CONST_TABLE(u1_t, _DR2RPS_CRC)[] = { - ILLEGAL_RPS, - (u1_t)MAKERPS(SF12, BW125, CR_4_5, 0, 0), - (u1_t)MAKERPS(SF11, BW125, CR_4_5, 0, 0), - (u1_t)MAKERPS(SF10, BW125, CR_4_5, 0, 0), - (u1_t)MAKERPS(SF9, BW125, CR_4_5, 0, 0), - (u1_t)MAKERPS(SF8, BW125, CR_4_5, 0, 0), - (u1_t)MAKERPS(SF7, BW125, CR_4_5, 0, 0), - (u1_t)MAKERPS(SF7, BW250, CR_4_5, 0, 0), - (u1_t)MAKERPS(FSK, BW125, CR_4_5, 0, 0), - ILLEGAL_RPS -}; - -static CONST_TABLE(s1_t, TXPOWLEVELS)[] = { - 20, 14, 11, 8, 5, 2, 0,0, 0,0,0,0, 0,0,0,0 -}; -#define pow2dBm(mcmd_ladr_p1) (TABLE_GET_S1(TXPOWLEVELS, (mcmd_ladr_p1&MCMD_LADR_POW_MASK)>>MCMD_LADR_POW_SHIFT)) - -#elif defined(CFG_us915) // ======================================== - -#define maxFrameLen(dr) ((dr)<=DR_SF11CR ? TABLE_GET_U1(maxFrameLens, (dr)) : 0xFF) -CONST_TABLE(u1_t, maxFrameLens) [] = { 24,66,142,255,255,255,255,255, 66,142 }; - -CONST_TABLE(u1_t, _DR2RPS_CRC)[] = { - ILLEGAL_RPS, - MAKERPS(SF10, BW125, CR_4_5, 0, 0), - MAKERPS(SF9 , BW125, CR_4_5, 0, 0), - MAKERPS(SF8 , BW125, CR_4_5, 0, 0), - MAKERPS(SF7 , BW125, CR_4_5, 0, 0), - MAKERPS(SF8 , BW500, CR_4_5, 0, 0), - ILLEGAL_RPS , - ILLEGAL_RPS , - ILLEGAL_RPS , - MAKERPS(SF12, BW500, CR_4_5, 0, 0), - MAKERPS(SF11, BW500, CR_4_5, 0, 0), - MAKERPS(SF10, BW500, CR_4_5, 0, 0), - MAKERPS(SF9 , BW500, CR_4_5, 0, 0), - MAKERPS(SF8 , BW500, CR_4_5, 0, 0), - MAKERPS(SF7 , BW500, CR_4_5, 0, 0), - ILLEGAL_RPS -}; - -#define pow2dBm(mcmd_ladr_p1) ((s1_t)(30 - (((mcmd_ladr_p1)&MCMD_LADR_POW_MASK)<<1))) - -#endif // ================================================ - -static CONST_TABLE(u1_t, SENSITIVITY)[7][3] = { - // ------------bw---------- - // 125kHz 250kHz 500kHz - { 141-109, 141-109, 141-109 }, // FSK - { 141-127, 141-124, 141-121 }, // SF7 - { 141-129, 141-126, 141-123 }, // SF8 - { 141-132, 141-129, 141-126 }, // SF9 - { 141-135, 141-132, 141-129 }, // SF10 - { 141-138, 141-135, 141-132 }, // SF11 - { 141-141, 141-138, 141-135 } // SF12 -}; - -int getSensitivity (rps_t rps) { - return -141 + TABLE_GET_U1_TWODIM(SENSITIVITY, getSf(rps), getBw(rps)); -} - -ostime_t calcAirTime (rps_t rps, u1_t plen) { - u1_t bw = getBw(rps); // 0,1,2 = 125,250,500kHz - u1_t sf = getSf(rps); // 0=FSK, 1..6 = SF7..12 - if( sf == FSK ) { - return (plen+/*preamble*/5+/*syncword*/3+/*len*/1+/*crc*/2) * /*bits/byte*/8 - * (s4_t)OSTICKS_PER_SEC / /*kbit/s*/50000; - } - u1_t sfx = 4*(sf+(7-SF7)); - u1_t q = sfx - (sf >= SF11 ? 8 : 0); - int tmp = 8*plen - sfx + 28 + (getNocrc(rps)?0:16) - (getIh(rps)?20:0); - if( tmp > 0 ) { - tmp = (tmp + q - 1) / q; - tmp *= getCr(rps)+5; - tmp += 8; - } else { - tmp = 8; - } - tmp = (tmp<<2) + /*preamble*/49 /* 4 * (8 + 4.25) */; - // bw = 125000 = 15625 * 2^3 - // 250000 = 15625 * 2^4 - // 500000 = 15625 * 2^5 - // sf = 7..12 - // - // osticks = tmp * OSTICKS_PER_SEC * 1< counter reduced divisor 125000/8 => 15625 - // 2 => counter 2 shift on tmp - sfx = sf+(7-SF7) - (3+2) - bw; - int div = 15625; - if( sfx > 4 ) { - // prevent 32bit signed int overflow in last step - div >>= sfx-4; - sfx = 4; - } - // Need 32bit arithmetic for this last step - return (((ostime_t)tmp << sfx) * OSTICKS_PER_SEC + div/2) / div; -} - -extern inline rps_t updr2rps (dr_t dr); -extern inline rps_t dndr2rps (dr_t dr); -extern inline int isFasterDR (dr_t dr1, dr_t dr2); -extern inline int isSlowerDR (dr_t dr1, dr_t dr2); -extern inline dr_t incDR (dr_t dr); -extern inline dr_t decDR (dr_t dr); -extern inline dr_t assertDR (dr_t dr); -extern inline dr_t validDR (dr_t dr); -extern inline dr_t lowerDR (dr_t dr, u1_t n); - -extern inline sf_t getSf (rps_t params); -extern inline rps_t setSf (rps_t params, sf_t sf); -extern inline bw_t getBw (rps_t params); -extern inline rps_t setBw (rps_t params, bw_t cr); -extern inline cr_t getCr (rps_t params); -extern inline rps_t setCr (rps_t params, cr_t cr); -extern inline int getNocrc (rps_t params); -extern inline rps_t setNocrc (rps_t params, int nocrc); -extern inline int getIh (rps_t params); -extern inline rps_t setIh (rps_t params, int ih); -extern inline rps_t makeRps (sf_t sf, bw_t bw, cr_t cr, int ih, int nocrc); -extern inline int sameSfBw (rps_t r1, rps_t r2); - -// END LORA -// ================================================================================ - - -// Adjust DR for TX retries -// - indexed by retry count -// - return steps to lower DR -static CONST_TABLE(u1_t, DRADJUST)[2+TXCONF_ATTEMPTS] = { - // normal frames - 1st try / no retry - 0, - // confirmed frames - 0,0,1,0,1,0,1,0,0 -}; - - -// Table below defines the size of one symbol as -// symtime = 256us * 2^T(sf,bw) -// 256us is called one symunit. -// SF: -// BW: |__7___8___9__10__11__12 -// 125kHz | 2 3 4 5 6 7 -// 250kHz | 1 2 3 4 5 6 -// 500kHz | 0 1 2 3 4 5 -// -// Times for half symbol per DR -// Per DR table to minimize rounding errors -static CONST_TABLE(ostime_t, DR2HSYM_osticks)[] = { -#if defined(CFG_eu868) -#define dr2hsym(dr) (TABLE_GET_OSTIME(DR2HSYM_osticks, (dr))) - us2osticksRound(128<<7), // DR_SF12 - us2osticksRound(128<<6), // DR_SF11 - us2osticksRound(128<<5), // DR_SF10 - us2osticksRound(128<<4), // DR_SF9 - us2osticksRound(128<<3), // DR_SF8 - us2osticksRound(128<<2), // DR_SF7 - us2osticksRound(128<<1), // DR_SF7B - us2osticksRound(80) // FSK -- not used (time for 1/2 byte) -#elif defined(CFG_us915) -#define dr2hsym(dr) (TABLE_GET_OSTIME(DR2HSYM_osticks, (dr)&7)) // map DR_SFnCR -> 0-6 - us2osticksRound(128<<5), // DR_SF10 DR_SF12CR - us2osticksRound(128<<4), // DR_SF9 DR_SF11CR - us2osticksRound(128<<3), // DR_SF8 DR_SF10CR - us2osticksRound(128<<2), // DR_SF7 DR_SF9CR - us2osticksRound(128<<1), // DR_SF8C DR_SF8CR - us2osticksRound(128<<0) // ------ DR_SF7CR -#endif -}; - - -#if !defined(DISABLE_BEACONS) -static ostime_t calcRxWindow (u1_t secs, dr_t dr) { - ostime_t rxoff, err; - if( secs==0 ) { - // aka 128 secs (next becaon) - rxoff = LMIC.drift; - err = LMIC.lastDriftDiff; - } else { - // scheduled RX window within secs into current beacon period - rxoff = (LMIC.drift * (ostime_t)secs) >> BCN_INTV_exp; - err = (LMIC.lastDriftDiff * (ostime_t)secs) >> BCN_INTV_exp; - } - u1_t rxsyms = MINRX_SYMS; - err += (ostime_t)LMIC.maxDriftDiff * LMIC.missedBcns; - LMIC.rxsyms = MINRX_SYMS + (err / dr2hsym(dr)); - - return (rxsyms-PAMBL_SYMS) * dr2hsym(dr) + rxoff; -} - - -// Setup beacon RX parameters assuming we have an error of ms (aka +/-(ms/2)) -static void calcBcnRxWindowFromMillis (u1_t ms, bit_t ini) { - if( ini ) { - LMIC.drift = 0; - LMIC.maxDriftDiff = 0; - LMIC.missedBcns = 0; - LMIC.bcninfo.flags |= BCN_NODRIFT|BCN_NODDIFF; - } - ostime_t hsym = dr2hsym(DR_BCN); - LMIC.bcnRxsyms = MINRX_SYMS + ms2osticksCeil(ms) / hsym; - LMIC.bcnRxtime = LMIC.bcninfo.txtime + BCN_INTV_osticks - (LMIC.bcnRxsyms-PAMBL_SYMS) * hsym; -} -#endif // !DISABLE_BEACONS - - -#if !defined(DISABLE_PING) -// Setup scheduled RX window (ping/multicast slot) -static void rxschedInit (xref2rxsched_t rxsched) { - os_clearMem(AESkey,16); - os_clearMem(LMIC.frame+8,8); - os_wlsbf4(LMIC.frame, LMIC.bcninfo.time); - os_wlsbf4(LMIC.frame+4, LMIC.devaddr); - os_aes(AES_ENC,LMIC.frame,16); - u1_t intvExp = rxsched->intvExp; - ostime_t off = os_rlsbf2(LMIC.frame) & (0x0FFF >> (7 - intvExp)); // random offset (slot units) - rxsched->rxbase = (LMIC.bcninfo.txtime + - BCN_RESERVE_osticks + - ms2osticks(BCN_SLOT_SPAN_ms * off)); // random offset osticks - rxsched->slot = 0; - rxsched->rxtime = rxsched->rxbase - calcRxWindow(/*secs BCN_RESERVE*/2+(1<dr); - rxsched->rxsyms = LMIC.rxsyms; -} - - -static bit_t rxschedNext (xref2rxsched_t rxsched, ostime_t cando) { - again: - if( rxsched->rxtime - cando >= 0 ) - return 1; - u1_t slot; - if( (slot=rxsched->slot) >= 128 ) - return 0; - u1_t intv = 1<intvExp; - if( (rxsched->slot = (slot += (intv))) >= 128 ) - return 0; - rxsched->rxtime = rxsched->rxbase - + ((BCN_WINDOW_osticks * (ostime_t)slot) >> BCN_INTV_exp) - - calcRxWindow(/*secs BCN_RESERVE*/2+slot+intv,rxsched->dr); - rxsched->rxsyms = LMIC.rxsyms; - goto again; -} -#endif // !DISABLE_PING) - - -static ostime_t rndDelay (u1_t secSpan) { - u2_t r = os_getRndU2(); - ostime_t delay = r; - if( delay > OSTICKS_PER_SEC ) - delay = r % (u2_t)OSTICKS_PER_SEC; - if( secSpan > 0 ) - delay += ((u1_t)r % secSpan) * OSTICKS_PER_SEC; - return delay; -} - - -static void txDelay (ostime_t reftime, u1_t secSpan) { - reftime += rndDelay(secSpan); - if( LMIC.globalDutyRate == 0 || (reftime - LMIC.globalDutyAvail) > 0 ) { - LMIC.globalDutyAvail = reftime; - LMIC.opmode |= OP_RNDTX; - } -} - - -static void setDrJoin (u1_t reason, u1_t dr) { - EV(drChange, INFO, (e_.reason = reason, - e_.deveui = MAIN::CDEV->getEui(), - e_.dr = dr|DR_PAGE, - e_.txpow = LMIC.adrTxPow, - e_.prevdr = LMIC.datarate|DR_PAGE, - e_.prevtxpow = LMIC.adrTxPow)); - LMIC.datarate = dr; - DO_DEVDB(LMIC.datarate,datarate); -} - - -static void setDrTxpow (u1_t reason, u1_t dr, s1_t pow) { - EV(drChange, INFO, (e_.reason = reason, - e_.deveui = MAIN::CDEV->getEui(), - e_.dr = dr|DR_PAGE, - e_.txpow = pow, - e_.prevdr = LMIC.datarate|DR_PAGE, - e_.prevtxpow = LMIC.adrTxPow)); - - if( pow != KEEP_TXPOW ) - LMIC.adrTxPow = pow; - if( LMIC.datarate != dr ) { - LMIC.datarate = dr; - DO_DEVDB(LMIC.datarate,datarate); - LMIC.opmode |= OP_NEXTCHNL; - } -} - - -#if !defined(DISABLE_PING) -void LMIC_stopPingable (void) { - LMIC.opmode &= ~(OP_PINGABLE|OP_PINGINI); -} - - -void LMIC_setPingable (u1_t intvExp) { - // Change setting - LMIC.ping.intvExp = (intvExp & 0x7); - LMIC.opmode |= OP_PINGABLE; - // App may call LMIC_enableTracking() explicitely before - // Otherwise tracking is implicitly enabled here - if( (LMIC.opmode & (OP_TRACK|OP_SCAN)) == 0 && LMIC.bcninfoTries == 0 ) - LMIC_enableTracking(0); -} - -#endif // !DISABLE_PING - -#if defined(CFG_eu868) -// ================================================================================ -// -// BEG: EU868 related stuff -// -enum { NUM_DEFAULT_CHANNELS=3 }; -static CONST_TABLE(u4_t, iniChannelFreq)[6] = { - // Join frequencies and duty cycle limit (0.1%) - EU868_F1|BAND_MILLI, EU868_F2|BAND_MILLI, EU868_F3|BAND_MILLI, - // Default operational frequencies - EU868_F1|BAND_CENTI, EU868_F2|BAND_CENTI, EU868_F3|BAND_CENTI, -}; - -static void initDefaultChannels (bit_t join) { - os_clearMem(&LMIC.channelFreq, sizeof(LMIC.channelFreq)); - os_clearMem(&LMIC.channelDrMap, sizeof(LMIC.channelDrMap)); - os_clearMem(&LMIC.bands, sizeof(LMIC.bands)); - - LMIC.channelMap = 0x07; - u1_t su = join ? 0 : 3; - for( u1_t fu=0; fu<3; fu++,su++ ) { - LMIC.channelFreq[fu] = TABLE_GET_U4(iniChannelFreq, su); - LMIC.channelDrMap[fu] = DR_RANGE_MAP(DR_SF12,DR_SF7); - } - - LMIC.bands[BAND_MILLI].txcap = 1000; // 0.1% - LMIC.bands[BAND_MILLI].txpow = 14; - LMIC.bands[BAND_MILLI].lastchnl = os_getRndU1() % MAX_CHANNELS; - LMIC.bands[BAND_CENTI].txcap = 100; // 1% - LMIC.bands[BAND_CENTI].txpow = 14; - LMIC.bands[BAND_CENTI].lastchnl = os_getRndU1() % MAX_CHANNELS; - LMIC.bands[BAND_DECI ].txcap = 10; // 10% - LMIC.bands[BAND_DECI ].txpow = 27; - LMIC.bands[BAND_DECI ].lastchnl = os_getRndU1() % MAX_CHANNELS; - LMIC.bands[BAND_MILLI].avail = - LMIC.bands[BAND_CENTI].avail = - LMIC.bands[BAND_DECI ].avail = os_getTime(); -} - -bit_t LMIC_setupBand (u1_t bandidx, s1_t txpow, u2_t txcap) { - if( bandidx > BAND_AUX ) return 0; - band_t* b = &LMIC.bands[bandidx]; - b->txpow = txpow; - b->txcap = txcap; - b->avail = os_getTime(); - b->lastchnl = os_getRndU1() % MAX_CHANNELS; - return 1; -} - -bit_t LMIC_setupChannel (u1_t chidx, u4_t freq, u2_t drmap, s1_t band) { - if( chidx >= MAX_CHANNELS ) - return 0; - if( band == -1 ) { - if( freq >= 869400000 && freq <= 869650000 ) - freq |= BAND_DECI; // 10% 27dBm - else if( (freq >= 868000000 && freq <= 868600000) || - (freq >= 869700000 && freq <= 870000000) ) - freq |= BAND_CENTI; // 1% 14dBm - else - freq |= BAND_MILLI; // 0.1% 14dBm - } else { - if( band > BAND_AUX ) return 0; - freq = (freq&~3) | band; - } - LMIC.channelFreq [chidx] = freq; - LMIC.channelDrMap[chidx] = drmap==0 ? DR_RANGE_MAP(DR_SF12,DR_SF7) : drmap; - LMIC.channelMap |= 1<> 8) * 100; - if( freq < EU868_FREQ_MIN || freq > EU868_FREQ_MAX ) - freq = 0; - return freq; -} - -static u1_t mapChannels (u1_t chpage, u2_t chmap) { - // Bad page, disable all channel, enable non-existent - if( chpage != 0 || chmap==0 || (chmap & ~LMIC.channelMap) != 0 ) - return 0; // illegal input - for( u1_t chnl=0; chnltxpow; - band->avail = txbeg + airtime * band->txcap; - if( LMIC.globalDutyRate != 0 ) - LMIC.globalDutyAvail = txbeg + (airtime< 1 - lmic_printf("%lu: Updating info for TX at %lu, airtime will be %lu. Setting available time for band %d to %lu\n", os_getTime(), txbeg, airtime, freq & 0x3, band->avail); - if( LMIC.globalDutyRate != 0 ) - lmic_printf("%lu: Updating global duty avail to %lu\n", os_getTime(), LMIC.globalDutyAvail); - #endif -} - -static ostime_t nextTx (ostime_t now) { - u1_t bmap=0xF; - do { - ostime_t mintime = now + /*8h*/sec2osticks(28800); - u1_t band=0; - for( u1_t bi=0; bi<4; bi++ ) { - if( (bmap & (1< 0 ) { - #if LMIC_DEBUG_LEVEL > 1 - lmic_printf("%lu: Considering band %d, which is available at %lu\n", os_getTime(), bi, LMIC.bands[bi].avail); - #endif - mintime = LMIC.bands[band = bi].avail; - } - } - // Find next channel in given band - u1_t chnl = LMIC.bands[band].lastchnl; - for( u1_t ci=0; ci= MAX_CHANNELS ) - chnl -= MAX_CHANNELS; - if( (LMIC.channelMap & (1< 1 - lmic_printf("%lu: No channel found in band %d\n", os_getTime(), band); - #endif - if( (bmap &= ~(1<>LMIC.datarate)); - #if LMIC_DEBUG_LEVEL > 1 - if (failed) - lmic_printf("%lu: Join failed\n", os_getTime()); - else - lmic_printf("%lu: Scheduling next join at %lu\n", os_getTime(), LMIC.txend); - #endif - // 1 - triggers EV_JOIN_FAILED event - return failed; -} -#endif // !DISABLE_JOIN - -// -// END: EU868 related stuff -// -// ================================================================================ -#elif defined(CFG_us915) -// ================================================================================ -// -// BEG: US915 related stuff -// - - -static void initDefaultChannels (void) { - for( u1_t i=0; i<4; i++ ) - LMIC.channelMap[i] = 0xFFFF; - LMIC.channelMap[4] = 0x00FF; -} - -static u4_t convFreq (xref2u1_t ptr) { - u4_t freq = (os_rlsbf4(ptr-1) >> 8) * 100; - if( freq < US915_FREQ_MIN || freq > US915_FREQ_MAX ) - freq = 0; - return freq; -} - -bit_t LMIC_setupChannel (u1_t chidx, u4_t freq, u2_t drmap, s1_t band) { - if( chidx < 72 || chidx >= 72+MAX_XCHANNELS ) - return 0; // channels 0..71 are hardwired - chidx -= 72; - LMIC.xchFreq[chidx] = freq; - LMIC.xchDrMap[chidx] = drmap==0 ? DR_RANGE_MAP(DR_SF10,DR_SF8C) : drmap; - LMIC.channelMap[chidx>>4] |= (1<<(chidx&0xF)); - return 1; -} - -void LMIC_disableChannel (u1_t channel) { - if( channel < 72+MAX_XCHANNELS ) - LMIC.channelMap[channel>>4] &= ~(1<<(channel&0xF)); -} - -void LMIC_enableChannel (u1_t channel) { - if( channel < 72+MAX_XCHANNELS ) - LMIC.channelMap[channel>>4] |= (1<<(channel&0xF)); -} - -void LMIC_enableSubBand (u1_t band) { - ASSERT(band < 8); - u1_t start = band * 8; - u1_t end = start + 8; - for (int channel=start; channel < end; ++channel ) - LMIC_enableChannel(channel); -} -void LMIC_disableSubBand (u1_t band) { - ASSERT(band < 8); - u1_t start = band * 8; - u1_t end = start + 8; - for (int channel=start; channel < end; ++channel ) - LMIC_disableChannel(channel); -} -void LMIC_selectSubBand (u1_t band) { - ASSERT(band < 8); - for (int b=0; b<8; ++b) { - if (band==b) - LMIC_enableSubBand(b); - else - LMIC_disableSubBand(b); - } -} - -static u1_t mapChannels (u1_t chpage, u2_t chmap) { - if( chpage == MCMD_LADR_CHP_125ON || chpage == MCMD_LADR_CHP_125OFF ) { - u2_t en125 = chpage == MCMD_LADR_CHP_125ON ? 0xFFFF : 0x0000; - for( u1_t u=0; u<4; u++ ) - LMIC.channelMap[u] = en125; - LMIC.channelMap[64/16] = chmap; - } else { - if( chpage >= (72+MAX_XCHANNELS+15)/16 ) - return 0; - LMIC.channelMap[chpage] = chmap; - } - return 1; -} - -static void updateTx (ostime_t txbeg) { - u1_t chnl = LMIC.txChnl; - if( chnl < 64 ) { - LMIC.freq = US915_125kHz_UPFBASE + chnl*US915_125kHz_UPFSTEP; - LMIC.txpow = 30; - return; - } - LMIC.txpow = 26; - if( chnl < 64+8 ) { - LMIC.freq = US915_500kHz_UPFBASE + (chnl-64)*US915_500kHz_UPFSTEP; - } else { - ASSERT(chnl < 64+8+MAX_XCHANNELS); - LMIC.freq = LMIC.xchFreq[chnl-72]; - } - - // Update global duty cycle stats - if( LMIC.globalDutyRate != 0 ) { - ostime_t airtime = calcAirTime(LMIC.rps, LMIC.dataLen); - LMIC.globalDutyAvail = txbeg + (airtime<= DR_SF8C ) { // 500kHz - u1_t map = LMIC.channelMap[64/16]&0xFF; - for( u1_t i=0; i<8; i++ ) { - if( (map & (1<<(++LMIC.chRnd & 7))) != 0 ) { - LMIC.txChnl = 64 + (LMIC.chRnd & 7); - return; - } - } - } else { // 125kHz - for( u1_t i=0; i<64; i++ ) { - u1_t chnl = ++LMIC.chRnd & 0x3F; - if( (LMIC.channelMap[(chnl >> 4)] & (1<<(chnl & 0xF))) != 0 ) { - LMIC.txChnl = chnl; - return; - } - } - } - // No feasible channel found! Keep old one. -} - -#if !defined(DISABLE_BEACONS) -static void setBcnRxParams (void) { - LMIC.dataLen = 0; - LMIC.freq = US915_500kHz_DNFBASE + LMIC.bcnChnl * US915_500kHz_DNFSTEP; - LMIC.rps = setIh(setNocrc(dndr2rps((dr_t)DR_BCN),1),LEN_BCN); -} -#endif // !DISABLE_BEACONS - -#define setRx1Params() { \ - LMIC.freq = US915_500kHz_DNFBASE + (LMIC.txChnl & 0x7) * US915_500kHz_DNFSTEP; \ - if( /* TX datarate */LMIC.dndr < DR_SF8C ) \ - LMIC.dndr += DR_SF10CR - DR_SF10; \ - else if( LMIC.dndr == DR_SF8C ) \ - LMIC.dndr = DR_SF7CR; \ - LMIC.rps = dndr2rps(LMIC.dndr); \ -} - -#if !defined(DISABLE_JOIN) -static void initJoinLoop (void) { - LMIC.chRnd = 0; - LMIC.txChnl = 0; - LMIC.adrTxPow = 20; - ASSERT((LMIC.opmode & OP_NEXTCHNL)==0); - LMIC.txend = os_getTime(); - setDrJoin(DRCHG_SET, DR_SF7); -} - -static ostime_t nextJoinState (void) { - // Try the following: - // SF7/8/9/10 on a random channel 0..63 - // SF8C on a random channel 64..71 - // - u1_t failed = 0; - if( LMIC.datarate != DR_SF8C ) { - LMIC.txChnl = 64+(LMIC.txChnl&7); - setDrJoin(DRCHG_SET, DR_SF8C); - } else { - LMIC.txChnl = os_getRndU1() & 0x3F; - s1_t dr = DR_SF7 - ++LMIC.txCnt; - if( LMIC.txCnt > DR_SF7 ) { - dr = DR_SF10; - failed = 1; // All DR exhausted - signal failed - } - setDrJoin(DRCHG_SET, dr); - } - LMIC.opmode &= ~OP_NEXTCHNL; - LMIC.txend = os_getTime() + - (isTESTMODE() - // Avoid collision with JOIN ACCEPT being sent by GW (but we missed it - GW is still busy) - ? DNW2_SAFETY_ZONE - // Otherwise: randomize join (street lamp case): - // SF10:16, SF9=8,..SF8C:1secs - : rndDelay(16>>LMIC.datarate)); - // 1 - triggers EV_JOIN_FAILED event - return failed; -} -#endif // !DISABLE_JOIN - -// -// END: US915 related stuff -// -// ================================================================================ -#else -#error Unsupported frequency band! -#endif - - -static void runEngineUpdate (xref2osjob_t osjob) { - engineUpdate(); -} - - -static void reportEvent (ev_t ev) { - EV(devCond, INFO, (e_.reason = EV::devCond_t::LMIC_EV, - e_.eui = MAIN::CDEV->getEui(), - e_.info = ev)); - ON_LMIC_EVENT(ev); - engineUpdate(); -} - - -static void runReset (xref2osjob_t osjob) { - // Disable session - LMIC_reset(); -#if !defined(DISABLE_JOIN) - LMIC_startJoining(); -#endif // !DISABLE_JOIN - reportEvent(EV_RESET); -} - -static void stateJustJoined (void) { - LMIC.seqnoDn = LMIC.seqnoUp = 0; - LMIC.rejoinCnt = 0; - LMIC.dnConf = LMIC.adrChanged = LMIC.ladrAns = LMIC.devsAns = 0; -#if !defined(DISABLE_MCMD_SNCH_REQ) - LMIC.snchAns = 0; -#endif -#if !defined(DISABLE_MCMD_DN2P_SET) - LMIC.dn2Ans = 0; -#endif - LMIC.moreData = 0; -#if !defined(DISABLE_MCMD_DCAP_REQ) - LMIC.dutyCapAns = 0; -#endif -#if !defined(DISABLE_MCMD_PING_SET) && !defined(DISABLE_PING) - LMIC.pingSetAns = 0; -#endif - LMIC.upRepeat = 0; - LMIC.adrAckReq = LINK_CHECK_INIT; - LMIC.dn2Dr = DR_DNW2; - LMIC.dn2Freq = FREQ_DNW2; -#if !defined(DISABLE_BEACONS) - LMIC.bcnChnl = CHNL_BCN; -#endif -#if !defined(DISABLE_PING) - LMIC.ping.freq = FREQ_PING; - LMIC.ping.dr = DR_PING; -#endif -} - - -// ================================================================================ -// Decoding frames - - -#if !defined(DISABLE_BEACONS) -// Decode beacon - do not overwrite bcninfo unless we have a match! -static int decodeBeacon (void) { - ASSERT(LMIC.dataLen == LEN_BCN); // implicit header RX guarantees this - xref2u1_t d = LMIC.frame; - if( -#if CFG_eu868 - d[OFF_BCN_CRC1] != (u1_t)os_crc16(d,OFF_BCN_CRC1) -#elif CFG_us915 - os_rlsbf2(&d[OFF_BCN_CRC1]) != os_crc16(d,OFF_BCN_CRC1) -#endif - ) - return 0; // first (common) part fails CRC check - // First set of fields is ok - u4_t bcnnetid = os_rlsbf4(&d[OFF_BCN_NETID]) & 0xFFFFFF; - if( bcnnetid != LMIC.netid ) - return -1; // not the beacon we're looking for - - LMIC.bcninfo.flags &= ~(BCN_PARTIAL|BCN_FULL); - // Match - update bcninfo structure - LMIC.bcninfo.snr = LMIC.snr; - LMIC.bcninfo.rssi = LMIC.rssi; - LMIC.bcninfo.txtime = LMIC.rxtime - AIRTIME_BCN_osticks; - LMIC.bcninfo.time = os_rlsbf4(&d[OFF_BCN_TIME]); - LMIC.bcninfo.flags |= BCN_PARTIAL; - - // Check 2nd set - if( os_rlsbf2(&d[OFF_BCN_CRC2]) != os_crc16(d,OFF_BCN_CRC2) ) - return 1; - // Second set of fields is ok - LMIC.bcninfo.lat = (s4_t)os_rlsbf4(&d[OFF_BCN_LAT-1]) >> 8; // read as signed 24-bit - LMIC.bcninfo.lon = (s4_t)os_rlsbf4(&d[OFF_BCN_LON-1]) >> 8; // ditto - LMIC.bcninfo.info = d[OFF_BCN_INFO]; - LMIC.bcninfo.flags |= BCN_FULL; - return 2; -} -#endif // !DISABLE_BEACONS - - -static bit_t decodeFrame (void) { - xref2u1_t d = LMIC.frame; - u1_t hdr = d[0]; - u1_t ftype = hdr & HDR_FTYPE; - int dlen = LMIC.dataLen; - const char *window = (LMIC.txrxFlags & TXRX_DNW1) ? "RX1" : ((LMIC.txrxFlags & TXRX_DNW2) ? "RX2" : "Other"); - if( dlen < OFF_DAT_OPTS+4 || - (hdr & HDR_MAJOR) != HDR_MAJOR_V1 || - (ftype != HDR_FTYPE_DADN && ftype != HDR_FTYPE_DCDN) ) { - // Basic sanity checks failed - EV(specCond, WARN, (e_.reason = EV::specCond_t::UNEXPECTED_FRAME, - e_.eui = MAIN::CDEV->getEui(), - e_.info = dlen < 4 ? 0 : os_rlsbf4(&d[dlen-4]), - e_.info2 = hdr + (dlen<<8))); - norx: -#if LMIC_DEBUG_LEVEL > 0 - lmic_printf("%lu: Invalid downlink, window=%s\n", os_getTime(), window); -#endif - LMIC.dataLen = 0; - return 0; - } - // Validate exact frame length - // Note: device address was already read+evaluated in order to arrive here. - int fct = d[OFF_DAT_FCT]; - u4_t addr = os_rlsbf4(&d[OFF_DAT_ADDR]); - u4_t seqno = os_rlsbf2(&d[OFF_DAT_SEQNO]); - int olen = fct & FCT_OPTLEN; - int ackup = (fct & FCT_ACK) != 0 ? 1 : 0; // ACK last up frame - int poff = OFF_DAT_OPTS+olen; - int pend = dlen-4; // MIC - - if( addr != LMIC.devaddr ) { - EV(specCond, WARN, (e_.reason = EV::specCond_t::ALIEN_ADDRESS, - e_.eui = MAIN::CDEV->getEui(), - e_.info = addr, - e_.info2 = LMIC.devaddr)); - goto norx; - } - if( poff > pend ) { - EV(specCond, ERR, (e_.reason = EV::specCond_t::CORRUPTED_FRAME, - e_.eui = MAIN::CDEV->getEui(), - e_.info = 0x1000000 + (poff-pend) + (fct<<8) + (dlen<<16))); - goto norx; - } - - int port = -1; - int replayConf = 0; - - if( pend > poff ) - port = d[poff++]; - - seqno = LMIC.seqnoDn + (u2_t)(seqno - LMIC.seqnoDn); - - if( !aes_verifyMic(LMIC.nwkKey, LMIC.devaddr, seqno, /*dn*/1, d, pend) ) { - EV(spe3Cond, ERR, (e_.reason = EV::spe3Cond_t::CORRUPTED_MIC, - e_.eui1 = MAIN::CDEV->getEui(), - e_.info1 = Base::lsbf4(&d[pend]), - e_.info2 = seqno, - e_.info3 = LMIC.devaddr)); - goto norx; - } - if( seqno < LMIC.seqnoDn ) { - if( (s4_t)seqno > (s4_t)LMIC.seqnoDn ) { - EV(specCond, INFO, (e_.reason = EV::specCond_t::DNSEQNO_ROLL_OVER, - e_.eui = MAIN::CDEV->getEui(), - e_.info = LMIC.seqnoDn, - e_.info2 = seqno)); - goto norx; - } - if( seqno != LMIC.seqnoDn-1 || !LMIC.dnConf || ftype != HDR_FTYPE_DCDN ) { - EV(specCond, INFO, (e_.reason = EV::specCond_t::DNSEQNO_OBSOLETE, - e_.eui = MAIN::CDEV->getEui(), - e_.info = LMIC.seqnoDn, - e_.info2 = seqno)); - goto norx; - } - // Replay of previous sequence number allowed only if - // previous frame and repeated both requested confirmation - replayConf = 1; - } - else { - if( seqno > LMIC.seqnoDn ) { - EV(specCond, INFO, (e_.reason = EV::specCond_t::DNSEQNO_SKIP, - e_.eui = MAIN::CDEV->getEui(), - e_.info = LMIC.seqnoDn, - e_.info2 = seqno)); - } - LMIC.seqnoDn = seqno+1; // next number to be expected - DO_DEVDB(LMIC.seqnoDn,seqnoDn); - // DN frame requested confirmation - provide ACK once with next UP frame - LMIC.dnConf = (ftype == HDR_FTYPE_DCDN ? FCT_ACK : 0); - } - - if( LMIC.dnConf || (fct & FCT_MORE) ) - LMIC.opmode |= OP_POLL; - - // We heard from network - LMIC.adrChanged = LMIC.rejoinCnt = 0; - if( LMIC.adrAckReq != LINK_CHECK_OFF ) - LMIC.adrAckReq = LINK_CHECK_INIT; - - // Process OPTS - int m = LMIC.rssi - RSSI_OFF - getSensitivity(LMIC.rps); - LMIC.margin = m < 0 ? 0 : m > 254 ? 254 : m; - - xref2u1_t opts = &d[OFF_DAT_OPTS]; - int oidx = 0; - while( oidx < olen ) { - switch( opts[oidx] ) { - case MCMD_LCHK_ANS: { - //int gwmargin = opts[oidx+1]; - //int ngws = opts[oidx+2]; - oidx += 3; - continue; - } - case MCMD_LADR_REQ: { - u1_t p1 = opts[oidx+1]; // txpow + DR - u2_t chmap = os_rlsbf2(&opts[oidx+2]);// list of enabled channels - u1_t chpage = opts[oidx+4] & MCMD_LADR_CHPAGE_MASK; // channel page - u1_t uprpt = opts[oidx+4] & MCMD_LADR_REPEAT_MASK; // up repeat count - oidx += 5; - - LMIC.ladrAns = 0x80 | // Include an answer into next frame up - MCMD_LADR_ANS_POWACK | MCMD_LADR_ANS_CHACK | MCMD_LADR_ANS_DRACK; - if( !mapChannels(chpage, chmap) ) - LMIC.ladrAns &= ~MCMD_LADR_ANS_CHACK; - dr_t dr = (dr_t)(p1>>MCMD_LADR_DR_SHIFT); - if( !validDR(dr) ) { - LMIC.ladrAns &= ~MCMD_LADR_ANS_DRACK; - EV(specCond, ERR, (e_.reason = EV::specCond_t::BAD_MAC_CMD, - e_.eui = MAIN::CDEV->getEui(), - e_.info = Base::lsbf4(&d[pend]), - e_.info2 = Base::msbf4(&opts[oidx-4]))); - } - if( (LMIC.ladrAns & 0x7F) == (MCMD_LADR_ANS_POWACK | MCMD_LADR_ANS_CHACK | MCMD_LADR_ANS_DRACK) ) { - // Nothing went wrong - use settings - LMIC.upRepeat = uprpt; - setDrTxpow(DRCHG_NWKCMD, dr, pow2dBm(p1)); - } - LMIC.adrChanged = 1; // Trigger an ACK to NWK - continue; - } - case MCMD_DEVS_REQ: { - LMIC.devsAns = 1; - oidx += 1; - continue; - } - case MCMD_DN2P_SET: { -#if !defined(DISABLE_MCMD_DN2P_SET) - dr_t dr = (dr_t)(opts[oidx+1] & 0x0F); - u4_t freq = convFreq(&opts[oidx+2]); - LMIC.dn2Ans = 0x80; // answer pending - if( validDR(dr) ) - LMIC.dn2Ans |= MCMD_DN2P_ANS_DRACK; - if( freq != 0 ) - LMIC.dn2Ans |= MCMD_DN2P_ANS_CHACK; - if( LMIC.dn2Ans == (0x80|MCMD_DN2P_ANS_DRACK|MCMD_DN2P_ANS_CHACK) ) { - LMIC.dn2Dr = dr; - LMIC.dn2Freq = freq; - DO_DEVDB(LMIC.dn2Dr,dn2Dr); - DO_DEVDB(LMIC.dn2Freq,dn2Freq); - } -#endif // !DISABLE_MCMD_DN2P_SET - oidx += 5; - continue; - } - case MCMD_DCAP_REQ: { -#if !defined(DISABLE_MCMD_DCAP_REQ) - u1_t cap = opts[oidx+1]; - // A value cap=0xFF means device is OFF unless enabled again manually. - if( cap==0xFF ) - LMIC.opmode |= OP_SHUTDOWN; // stop any sending - LMIC.globalDutyRate = cap & 0xF; - LMIC.globalDutyAvail = os_getTime(); - DO_DEVDB(cap,dutyCap); - LMIC.dutyCapAns = 1; - oidx += 2; -#endif // !DISABLE_MCMD_DCAP_REQ - continue; - } - case MCMD_SNCH_REQ: { -#if !defined(DISABLE_MCMD_SNCH_REQ) - u1_t chidx = opts[oidx+1]; // channel - u4_t freq = convFreq(&opts[oidx+2]); // freq - u1_t drs = opts[oidx+5]; // datarate span - LMIC.snchAns = 0x80; - if( freq != 0 && LMIC_setupChannel(chidx, freq, DR_RANGE_MAP(drs&0xF,drs>>4), -1) ) - LMIC.snchAns |= MCMD_SNCH_ANS_DRACK|MCMD_SNCH_ANS_FQACK; -#endif // !DISABLE_MCMD_SNCH_REQ - oidx += 6; - continue; - } - case MCMD_PING_SET: { -#if !defined(DISABLE_MCMD_PING_SET) && !defined(DISABLE_PING) - u4_t freq = convFreq(&opts[oidx+1]); - u1_t flags = 0x80; - if( freq != 0 ) { - flags |= MCMD_PING_ANS_FQACK; - LMIC.ping.freq = freq; - DO_DEVDB(LMIC.ping.intvExp, pingIntvExp); - DO_DEVDB(LMIC.ping.freq, pingFreq); - DO_DEVDB(LMIC.ping.dr, pingDr); - } - LMIC.pingSetAns = flags; -#endif // !DISABLE_MCMD_PING_SET && !DISABLE_PING - oidx += 4; - continue; - } - case MCMD_BCNI_ANS: { -#if !defined(DISABLE_MCMD_BCNI_ANS) && !defined(DISABLE_BEACONS) - // Ignore if tracking already enabled - if( (LMIC.opmode & OP_TRACK) == 0 ) { - LMIC.bcnChnl = opts[oidx+3]; - // Enable tracking - bcninfoTries - LMIC.opmode |= OP_TRACK; - // Cleared later in txComplete handling - triggers EV_BEACON_FOUND - ASSERT(LMIC.bcninfoTries!=0); - // Setup RX parameters - LMIC.bcninfo.txtime = (LMIC.rxtime - + ms2osticks(os_rlsbf2(&opts[oidx+1]) * MCMD_BCNI_TUNIT) - + ms2osticksCeil(MCMD_BCNI_TUNIT/2) - - BCN_INTV_osticks); - LMIC.bcninfo.flags = 0; // txtime above cannot be used as reference (BCN_PARTIAL|BCN_FULL cleared) - calcBcnRxWindowFromMillis(MCMD_BCNI_TUNIT,1); // error of +/-N ms - - EV(lostFrame, INFO, (e_.reason = EV::lostFrame_t::MCMD_BCNI_ANS, - e_.eui = MAIN::CDEV->getEui(), - e_.lostmic = Base::lsbf4(&d[pend]), - e_.info = (LMIC.missedBcns | - (osticks2us(LMIC.bcninfo.txtime + BCN_INTV_osticks - - LMIC.bcnRxtime) << 8)), - e_.time = MAIN::CDEV->ostime2ustime(LMIC.bcninfo.txtime + BCN_INTV_osticks))); - } -#endif // !DISABLE_MCMD_BCNI_ANS && !DISABLE_BEACONS - oidx += 4; - continue; - } - } - EV(specCond, ERR, (e_.reason = EV::specCond_t::BAD_MAC_CMD, - e_.eui = MAIN::CDEV->getEui(), - e_.info = Base::lsbf4(&d[pend]), - e_.info2 = Base::msbf4(&opts[oidx]))); - break; - } - if( oidx != olen ) { - EV(specCond, ERR, (e_.reason = EV::specCond_t::CORRUPTED_FRAME, - e_.eui = MAIN::CDEV->getEui(), - e_.info = 0x1000000 + (oidx) + (olen<<8))); - } - - if( !replayConf ) { - // Handle payload only if not a replay - // Decrypt payload - if any - if( port >= 0 && pend-poff > 0 ) - aes_cipher(port <= 0 ? LMIC.nwkKey : LMIC.artKey, LMIC.devaddr, seqno, /*dn*/1, d+poff, pend-poff); - - EV(dfinfo, DEBUG, (e_.deveui = MAIN::CDEV->getEui(), - e_.devaddr = LMIC.devaddr, - e_.seqno = seqno, - e_.flags = (port < 0 ? EV::dfinfo_t::NOPORT : 0) | EV::dfinfo_t::DN, - e_.mic = Base::lsbf4(&d[pend]), - e_.hdr = d[LORA::OFF_DAT_HDR], - e_.fct = d[LORA::OFF_DAT_FCT], - e_.port = port, - e_.plen = dlen, - e_.opts.length = olen, - memcpy(&e_.opts[0], opts, olen))); - } else { - EV(specCond, INFO, (e_.reason = EV::specCond_t::DNSEQNO_REPLAY, - e_.eui = MAIN::CDEV->getEui(), - e_.info = Base::lsbf4(&d[pend]), - e_.info2 = seqno)); - } - - if( // NWK acks but we don't have a frame pending - (ackup && LMIC.txCnt == 0) || - // We sent up confirmed and we got a response in DNW1/DNW2 - // BUT it did not carry an ACK - this should never happen - // Do not resend and assume frame was not ACKed. - (!ackup && LMIC.txCnt != 0) ) { - EV(specCond, ERR, (e_.reason = EV::specCond_t::SPURIOUS_ACK, - e_.eui = MAIN::CDEV->getEui(), - e_.info = seqno, - e_.info2 = ackup)); - } - - if( LMIC.txCnt != 0 ) // we requested an ACK - LMIC.txrxFlags |= ackup ? TXRX_ACK : TXRX_NACK; - - if( port < 0 ) { - LMIC.txrxFlags |= TXRX_NOPORT; - LMIC.dataBeg = poff; - LMIC.dataLen = 0; - } else { - LMIC.txrxFlags |= TXRX_PORT; - LMIC.dataBeg = poff; - LMIC.dataLen = pend-poff; - } -#if LMIC_DEBUG_LEVEL > 0 - lmic_printf("%lu: Received downlink, window=%s, port=%d, ack=%d\n", os_getTime(), window, port, ackup); -#endif - return 1; -} - - -// ================================================================================ -// TX/RX transaction support - - -static void setupRx2 (void) { - LMIC.txrxFlags = TXRX_DNW2; - LMIC.rps = dndr2rps(LMIC.dn2Dr); - LMIC.freq = LMIC.dn2Freq; - LMIC.dataLen = 0; - os_radio(RADIO_RX); -} - - -static void schedRx12 (ostime_t delay, osjobcb_t func, u1_t dr) { - ostime_t hsym = dr2hsym(dr); - - LMIC.rxsyms = MINRX_SYMS; - - // If a clock error is specified, compensate for it by extending the - // receive window - if (LMIC.clockError != 0) { - // Calculate how much the clock will drift maximally after delay has - // passed. This indicates the amount of time we can be early - // _or_ late. - ostime_t drift = (int64_t)delay * LMIC.clockError / MAX_CLOCK_ERROR; - - // Increase the receive window by twice the maximum drift (to - // compensate for a slow or a fast clock). - // decrease the rxtime to compensate for. Note that hsym is a - // *half* symbol time, so the factor 2 is hidden. First check if - // this would overflow (which can happen if the drift is very - // high, or the symbol time is low at high datarates). - if ((255 - LMIC.rxsyms) * hsym < drift) - LMIC.rxsyms = 255; - else - LMIC.rxsyms += drift / hsym; - - } - - // Center the receive window on the center of the expected preamble - // (again note that hsym is half a sumbol time, so no /2 needed) - LMIC.rxtime = LMIC.txend + delay + PAMBL_SYMS * hsym - LMIC.rxsyms * hsym; - - os_setTimedCallback(&LMIC.osjob, LMIC.rxtime - RX_RAMPUP, func); -} - -static void setupRx1 (osjobcb_t func) { - LMIC.txrxFlags = TXRX_DNW1; - // Turn LMIC.rps from TX over to RX - LMIC.rps = setNocrc(LMIC.rps,1); - LMIC.dataLen = 0; - LMIC.osjob.func = func; - os_radio(RADIO_RX); -} - - -// Called by HAL once TX complete and delivers exact end of TX time stamp in LMIC.rxtime -static void txDone (ostime_t delay, osjobcb_t func) { -#if !defined(DISABLE_PING) - if( (LMIC.opmode & (OP_TRACK|OP_PINGABLE|OP_PINGINI)) == (OP_TRACK|OP_PINGABLE) ) { - rxschedInit(&LMIC.ping); // note: reuses LMIC.frame buffer! - LMIC.opmode |= OP_PINGINI; - } -#endif // !DISABLE_PING - - // Change RX frequency / rps (US only) before we increment txChnl - setRx1Params(); - // LMIC.rxsyms carries the TX datarate (can be != LMIC.datarate [confirm retries etc.]) - // Setup receive - LMIC.rxtime is preloaded with 1.5 symbols offset to tune - // into the middle of the 8 symbols preamble. -#if defined(CFG_eu868) - if( /* TX datarate */LMIC.rxsyms == DR_FSK ) { - LMIC.rxtime = LMIC.txend + delay - PRERX_FSK*us2osticksRound(160); - LMIC.rxsyms = RXLEN_FSK; - os_setTimedCallback(&LMIC.osjob, LMIC.rxtime - RX_RAMPUP, func); - } - else -#endif - { - schedRx12(delay, func, LMIC.dndr); - } -} - - -// ======================================== Join frames - - -#if !defined(DISABLE_JOIN) -static void onJoinFailed (xref2osjob_t osjob) { - // Notify app - must call LMIC_reset() to stop joining - // otherwise join procedure continues. - reportEvent(EV_JOIN_FAILED); -} - - -static bit_t processJoinAccept (void) { - ASSERT(LMIC.txrxFlags != TXRX_DNW1 || LMIC.dataLen != 0); - ASSERT((LMIC.opmode & OP_TXRXPEND)!=0); - - if( LMIC.dataLen == 0 ) { - nojoinframe: - if( (LMIC.opmode & OP_JOINING) == 0 ) { - ASSERT((LMIC.opmode & OP_REJOIN) != 0); - // REJOIN attempt for roaming - LMIC.opmode &= ~(OP_REJOIN|OP_TXRXPEND); - if( LMIC.rejoinCnt < 10 ) - LMIC.rejoinCnt++; - reportEvent(EV_REJOIN_FAILED); - return 1; - } - LMIC.opmode &= ~OP_TXRXPEND; - ostime_t delay = nextJoinState(); - EV(devCond, DEBUG, (e_.reason = EV::devCond_t::NO_JACC, - e_.eui = MAIN::CDEV->getEui(), - e_.info = LMIC.datarate|DR_PAGE, - e_.info2 = osticks2ms(delay))); - // Build next JOIN REQUEST with next engineUpdate call - // Optionally, report join failed. - // Both after a random/chosen amount of ticks. - os_setTimedCallback(&LMIC.osjob, os_getTime()+delay, - (delay&1) != 0 - ? FUNC_ADDR(onJoinFailed) // one JOIN iteration done and failed - : FUNC_ADDR(runEngineUpdate)); // next step to be delayed - return 1; - } - u1_t hdr = LMIC.frame[0]; - u1_t dlen = LMIC.dataLen; - u4_t mic = os_rlsbf4(&LMIC.frame[dlen-4]); // safe before modified by encrypt! - if( (dlen != LEN_JA && dlen != LEN_JAEXT) - || (hdr & (HDR_FTYPE|HDR_MAJOR)) != (HDR_FTYPE_JACC|HDR_MAJOR_V1) ) { - EV(specCond, ERR, (e_.reason = EV::specCond_t::UNEXPECTED_FRAME, - e_.eui = MAIN::CDEV->getEui(), - e_.info = dlen < 4 ? 0 : mic, - e_.info2 = hdr + (dlen<<8))); - badframe: - if( (LMIC.txrxFlags & TXRX_DNW1) != 0 ) - return 0; - goto nojoinframe; - } - aes_encrypt(LMIC.frame+1, dlen-1); - if( !aes_verifyMic0(LMIC.frame, dlen-4) ) { - EV(specCond, ERR, (e_.reason = EV::specCond_t::JOIN_BAD_MIC, - e_.info = mic)); - goto badframe; - } - - u4_t addr = os_rlsbf4(LMIC.frame+OFF_JA_DEVADDR); - LMIC.devaddr = addr; - LMIC.netid = os_rlsbf4(&LMIC.frame[OFF_JA_NETID]) & 0xFFFFFF; - -#if defined(CFG_eu868) - initDefaultChannels(0); -#endif - if( dlen > LEN_JA ) { -#if defined(CFG_us915) - goto badframe; -#endif - dlen = OFF_CFLIST; - for( u1_t chidx=3; chidx<8; chidx++, dlen+=3 ) { - u4_t freq = convFreq(&LMIC.frame[dlen]); - if( freq ) { - LMIC_setupChannel(chidx, freq, 0, -1); -#if LMIC_DEBUG_LEVEL > 1 - lmic_printf("%lu: Setup channel, idx=%d, freq=%lu\n", os_getTime(), chidx, (unsigned long)freq); -#endif - } - } - } - - // already incremented when JOIN REQ got sent off - aes_sessKeys(LMIC.devNonce-1, &LMIC.frame[OFF_JA_ARTNONCE], LMIC.nwkKey, LMIC.artKey); - DO_DEVDB(LMIC.netid, netid); - DO_DEVDB(LMIC.devaddr, devaddr); - DO_DEVDB(LMIC.nwkKey, nwkkey); - DO_DEVDB(LMIC.artKey, artkey); - - EV(joininfo, INFO, (e_.arteui = MAIN::CDEV->getArtEui(), - e_.deveui = MAIN::CDEV->getEui(), - e_.devaddr = LMIC.devaddr, - e_.oldaddr = oldaddr, - e_.nonce = LMIC.devNonce-1, - e_.mic = mic, - e_.reason = ((LMIC.opmode & OP_REJOIN) != 0 - ? EV::joininfo_t::REJOIN_ACCEPT - : EV::joininfo_t::ACCEPT))); - - ASSERT((LMIC.opmode & (OP_JOINING|OP_REJOIN))!=0); - if( (LMIC.opmode & OP_REJOIN) != 0 ) { - // Lower DR every try below current UP DR - LMIC.datarate = lowerDR(LMIC.datarate, LMIC.rejoinCnt); - } - LMIC.opmode &= ~(OP_JOINING|OP_TRACK|OP_REJOIN|OP_TXRXPEND|OP_PINGINI) | OP_NEXTCHNL; - LMIC.txCnt = 0; - stateJustJoined(); - LMIC.dn2Dr = LMIC.frame[OFF_JA_DLSET] & 0x0F; - LMIC.rxDelay = LMIC.frame[OFF_JA_RXDLY]; - if (LMIC.rxDelay == 0) LMIC.rxDelay = 1; - reportEvent(EV_JOINED); - return 1; -} - - -static void processRx2Jacc (xref2osjob_t osjob) { - if( LMIC.dataLen == 0 ) - LMIC.txrxFlags = 0; // nothing in 1st/2nd DN slot - processJoinAccept(); -} - - -static void setupRx2Jacc (xref2osjob_t osjob) { - LMIC.osjob.func = FUNC_ADDR(processRx2Jacc); - setupRx2(); -} - - -static void processRx1Jacc (xref2osjob_t osjob) { - if( LMIC.dataLen == 0 || !processJoinAccept() ) - schedRx12(DELAY_JACC2_osticks, FUNC_ADDR(setupRx2Jacc), LMIC.dn2Dr); -} - - -static void setupRx1Jacc (xref2osjob_t osjob) { - setupRx1(FUNC_ADDR(processRx1Jacc)); -} - - -static void jreqDone (xref2osjob_t osjob) { - txDone(DELAY_JACC1_osticks, FUNC_ADDR(setupRx1Jacc)); -} - -#endif // !DISABLE_JOIN - -// ======================================== Data frames - -// Fwd decl. -static bit_t processDnData(void); - -static void processRx2DnData (xref2osjob_t osjob) { - if( LMIC.dataLen == 0 ) { - LMIC.txrxFlags = 0; // nothing in 1st/2nd DN slot - // It could be that the gateway *is* sending a reply, but we - // just didn't pick it up. To avoid TX'ing again while the - // gateay is not listening anyway, delay the next transmission - // until DNW2_SAFETY_ZONE from now, and add up to 2 seconds of - // extra randomization. - txDelay(os_getTime() + DNW2_SAFETY_ZONE, 2); - } - processDnData(); -} - - -static void setupRx2DnData (xref2osjob_t osjob) { - LMIC.osjob.func = FUNC_ADDR(processRx2DnData); - setupRx2(); -} - - -static void processRx1DnData (xref2osjob_t osjob) { - if( LMIC.dataLen == 0 || !processDnData() ) - schedRx12(sec2osticks(LMIC.rxDelay +(int)DELAY_EXTDNW2), FUNC_ADDR(setupRx2DnData), LMIC.dn2Dr); -} - - -static void setupRx1DnData (xref2osjob_t osjob) { - setupRx1(FUNC_ADDR(processRx1DnData)); -} - - -static void updataDone (xref2osjob_t osjob) { - txDone(sec2osticks(LMIC.rxDelay), FUNC_ADDR(setupRx1DnData)); -} - -// ======================================== - - -static void buildDataFrame (void) { - bit_t txdata = ((LMIC.opmode & (OP_TXDATA|OP_POLL)) != OP_POLL); - u1_t dlen = txdata ? LMIC.pendTxLen : 0; - - // Piggyback MAC options - // Prioritize by importance - int end = OFF_DAT_OPTS; -#if !defined(DISABLE_PING) - if( (LMIC.opmode & (OP_TRACK|OP_PINGABLE)) == (OP_TRACK|OP_PINGABLE) ) { - // Indicate pingability in every UP frame - LMIC.frame[end] = MCMD_PING_IND; - LMIC.frame[end+1] = LMIC.ping.dr | (LMIC.ping.intvExp<<4); - end += 2; - } -#endif // !DISABLE_PING -#if !defined(DISABLE_MCMD_DCAP_REQ) - if( LMIC.dutyCapAns ) { - LMIC.frame[end] = MCMD_DCAP_ANS; - end += 1; - LMIC.dutyCapAns = 0; - } -#endif // !DISABLE_MCMD_DCAP_REQ -#if !defined(DISABLE_MCMD_DN2P_SET) - if( LMIC.dn2Ans ) { - LMIC.frame[end+0] = MCMD_DN2P_ANS; - LMIC.frame[end+1] = LMIC.dn2Ans & ~MCMD_DN2P_ANS_RFU; - end += 2; - LMIC.dn2Ans = 0; - } -#endif // !DISABLE_MCMD_DN2P_SET - if( LMIC.devsAns ) { // answer to device status - LMIC.frame[end+0] = MCMD_DEVS_ANS; - LMIC.frame[end+1] = os_getBattLevel(); - LMIC.frame[end+2] = LMIC.margin; - end += 3; - LMIC.devsAns = 0; - } - if( LMIC.ladrAns ) { // answer to ADR change - LMIC.frame[end+0] = MCMD_LADR_ANS; - LMIC.frame[end+1] = LMIC.ladrAns & ~MCMD_LADR_ANS_RFU; - end += 2; - LMIC.ladrAns = 0; - } -#if !defined(DISABLE_BEACONS) - if( LMIC.bcninfoTries > 0 ) { - LMIC.frame[end] = MCMD_BCNI_REQ; - end += 1; - } -#endif // !DISABLE_BEACONS - if( LMIC.adrChanged ) { - if( LMIC.adrAckReq < 0 ) - LMIC.adrAckReq = 0; - LMIC.adrChanged = 0; - } -#if !defined(DISABLE_MCMD_PING_SET) && !defined(DISABLE_PING) - if( LMIC.pingSetAns != 0 ) { - LMIC.frame[end+0] = MCMD_PING_ANS; - LMIC.frame[end+1] = LMIC.pingSetAns & ~MCMD_PING_ANS_RFU; - end += 2; - LMIC.pingSetAns = 0; - } -#endif // !DISABLE_MCMD_PING_SET && !DISABLE_PING -#if !defined(DISABLE_MCMD_SNCH_REQ) - if( LMIC.snchAns ) { - LMIC.frame[end+0] = MCMD_SNCH_ANS; - LMIC.frame[end+1] = LMIC.snchAns & ~MCMD_SNCH_ANS_RFU; - end += 2; - LMIC.snchAns = 0; - } -#endif // !DISABLE_MCMD_SNCH_REQ - ASSERT(end <= OFF_DAT_OPTS+16); - - u1_t flen = end + (txdata ? 5+dlen : 4); - if( flen > MAX_LEN_FRAME ) { - // Options and payload too big - delay payload - txdata = 0; - flen = end+4; - } - LMIC.frame[OFF_DAT_HDR] = HDR_FTYPE_DAUP | HDR_MAJOR_V1; - LMIC.frame[OFF_DAT_FCT] = (LMIC.dnConf | LMIC.adrEnabled - | (LMIC.adrAckReq >= 0 ? FCT_ADRARQ : 0) - | (end-OFF_DAT_OPTS)); - os_wlsbf4(LMIC.frame+OFF_DAT_ADDR, LMIC.devaddr); - - if( LMIC.txCnt == 0 ) { - LMIC.seqnoUp += 1; - DO_DEVDB(LMIC.seqnoUp,seqnoUp); - } else { - EV(devCond, INFO, (e_.reason = EV::devCond_t::RE_TX, - e_.eui = MAIN::CDEV->getEui(), - e_.info = LMIC.seqnoUp-1, - e_.info2 = ((LMIC.txCnt+1) | - (TABLE_GET_U1(DRADJUST, LMIC.txCnt+1) << 8) | - ((LMIC.datarate|DR_PAGE)<<16)))); - } - os_wlsbf2(LMIC.frame+OFF_DAT_SEQNO, LMIC.seqnoUp-1); - - // Clear pending DN confirmation - LMIC.dnConf = 0; - - if( txdata ) { - if( LMIC.pendTxConf ) { - // Confirmed only makes sense if we have a payload (or at least a port) - LMIC.frame[OFF_DAT_HDR] = HDR_FTYPE_DCUP | HDR_MAJOR_V1; - if( LMIC.txCnt == 0 ) LMIC.txCnt = 1; - } - LMIC.frame[end] = LMIC.pendTxPort; - os_copyMem(LMIC.frame+end+1, LMIC.pendTxData, dlen); - aes_cipher(LMIC.pendTxPort==0 ? LMIC.nwkKey : LMIC.artKey, - LMIC.devaddr, LMIC.seqnoUp-1, - /*up*/0, LMIC.frame+end+1, dlen); - } - aes_appendMic(LMIC.nwkKey, LMIC.devaddr, LMIC.seqnoUp-1, /*up*/0, LMIC.frame, flen-4); - - EV(dfinfo, DEBUG, (e_.deveui = MAIN::CDEV->getEui(), - e_.devaddr = LMIC.devaddr, - e_.seqno = LMIC.seqnoUp-1, - e_.flags = (LMIC.pendTxPort < 0 ? EV::dfinfo_t::NOPORT : EV::dfinfo_t::NOP), - e_.mic = Base::lsbf4(&LMIC.frame[flen-4]), - e_.hdr = LMIC.frame[LORA::OFF_DAT_HDR], - e_.fct = LMIC.frame[LORA::OFF_DAT_FCT], - e_.port = LMIC.pendTxPort, - e_.plen = txdata ? dlen : 0, - e_.opts.length = end-LORA::OFF_DAT_OPTS, - memcpy(&e_.opts[0], LMIC.frame+LORA::OFF_DAT_OPTS, end-LORA::OFF_DAT_OPTS))); - LMIC.dataLen = flen; -} - - -#if !defined(DISABLE_BEACONS) -// Callback from HAL during scan mode or when job timer expires. -static void onBcnRx (xref2osjob_t job) { - // If we arrive via job timer make sure to put radio to rest. - os_radio(RADIO_RST); - os_clearCallback(&LMIC.osjob); - if( LMIC.dataLen == 0 ) { - // Nothing received - timeout - LMIC.opmode &= ~(OP_SCAN | OP_TRACK); - reportEvent(EV_SCAN_TIMEOUT); - return; - } - if( decodeBeacon() <= 0 ) { - // Something is wrong with the beacon - continue scan - LMIC.dataLen = 0; - os_radio(RADIO_RXON); - os_setTimedCallback(&LMIC.osjob, LMIC.bcninfo.txtime, FUNC_ADDR(onBcnRx)); - return; - } - // Found our 1st beacon - // We don't have a previous beacon to calc some drift - assume - // an max error of 13ms = 128sec*100ppm which is roughly +/-100ppm - calcBcnRxWindowFromMillis(13,1); - LMIC.opmode &= ~OP_SCAN; // turn SCAN off - LMIC.opmode |= OP_TRACK; // auto enable tracking - reportEvent(EV_BEACON_FOUND); // can be disabled in callback -} - - -// Enable receiver to listen to incoming beacons -// netid defines when scan stops (any or specific beacon) -// This mode ends with events: EV_SCAN_TIMEOUT/EV_SCAN_BEACON -// Implicitely cancels any pending TX/RX transaction. -// Also cancels an onpoing joining procedure. -static void startScan (void) { - ASSERT(LMIC.devaddr!=0 && (LMIC.opmode & OP_JOINING)==0); - if( (LMIC.opmode & OP_SHUTDOWN) != 0 ) - return; - // Cancel onging TX/RX transaction - LMIC.txCnt = LMIC.dnConf = LMIC.bcninfo.flags = 0; - LMIC.opmode = (LMIC.opmode | OP_SCAN) & ~(OP_TXRXPEND); - setBcnRxParams(); - LMIC.rxtime = LMIC.bcninfo.txtime = os_getTime() + sec2osticks(BCN_INTV_sec+1); - os_setTimedCallback(&LMIC.osjob, LMIC.rxtime, FUNC_ADDR(onBcnRx)); - os_radio(RADIO_RXON); -} - - -bit_t LMIC_enableTracking (u1_t tryBcnInfo) { - if( (LMIC.opmode & (OP_SCAN|OP_TRACK|OP_SHUTDOWN)) != 0 ) - return 0; // already in progress or failed to enable - // If BCN info requested from NWK then app has to take are - // of sending data up so that MCMD_BCNI_REQ can be attached. - if( (LMIC.bcninfoTries = tryBcnInfo) == 0 ) - startScan(); - return 1; // enabled -} - - -void LMIC_disableTracking (void) { - LMIC.opmode &= ~(OP_SCAN|OP_TRACK); - LMIC.bcninfoTries = 0; - engineUpdate(); -} -#endif // !DISABLE_BEACONS - - -// ================================================================================ -// -// Join stuff -// -// ================================================================================ - -#if !defined(DISABLE_JOIN) -static void buildJoinRequest (u1_t ftype) { - // Do not use pendTxData since we might have a pending - // user level frame in there. Use RX holding area instead. - xref2u1_t d = LMIC.frame; - d[OFF_JR_HDR] = ftype; - os_getArtEui(d + OFF_JR_ARTEUI); - os_getDevEui(d + OFF_JR_DEVEUI); - os_wlsbf2(d + OFF_JR_DEVNONCE, LMIC.devNonce); - aes_appendMic0(d, OFF_JR_MIC); - - EV(joininfo,INFO,(e_.deveui = MAIN::CDEV->getEui(), - e_.arteui = MAIN::CDEV->getArtEui(), - e_.nonce = LMIC.devNonce, - e_.oldaddr = LMIC.devaddr, - e_.mic = Base::lsbf4(&d[LORA::OFF_JR_MIC]), - e_.reason = ((LMIC.opmode & OP_REJOIN) != 0 - ? EV::joininfo_t::REJOIN_REQUEST - : EV::joininfo_t::REQUEST))); - LMIC.dataLen = LEN_JR; - LMIC.devNonce++; - DO_DEVDB(LMIC.devNonce,devNonce); -} - -static void startJoining (xref2osjob_t osjob) { - reportEvent(EV_JOINING); -} - -// Start join procedure if not already joined. -bit_t LMIC_startJoining (void) { - if( LMIC.devaddr == 0 ) { - // There should be no TX/RX going on - ASSERT((LMIC.opmode & (OP_POLL|OP_TXRXPEND)) == 0); - // Lift any previous duty limitation - LMIC.globalDutyRate = 0; - // Cancel scanning - LMIC.opmode &= ~(OP_SCAN|OP_REJOIN|OP_LINKDEAD|OP_NEXTCHNL); - // Setup state - LMIC.rejoinCnt = LMIC.txCnt = 0; - initJoinLoop(); - LMIC.opmode |= OP_JOINING; - // reportEvent will call engineUpdate which then starts sending JOIN REQUESTS - os_setCallback(&LMIC.osjob, FUNC_ADDR(startJoining)); - return 1; - } - return 0; // already joined -} -#endif // !DISABLE_JOIN - - -// ================================================================================ -// -// -// -// ================================================================================ - -#if !defined(DISABLE_PING) -static void processPingRx (xref2osjob_t osjob) { - if( LMIC.dataLen != 0 ) { - LMIC.txrxFlags = TXRX_PING; - if( decodeFrame() ) { - reportEvent(EV_RXCOMPLETE); - return; - } - } - // Pick next ping slot - engineUpdate(); -} -#endif // !DISABLE_PING - - -static bit_t processDnData (void) { - ASSERT((LMIC.opmode & OP_TXRXPEND)!=0); - - if( LMIC.dataLen == 0 ) { - norx: - if( LMIC.txCnt != 0 ) { - if( LMIC.txCnt < TXCONF_ATTEMPTS ) { - LMIC.txCnt += 1; - setDrTxpow(DRCHG_NOACK, lowerDR(LMIC.datarate, TABLE_GET_U1(DRADJUST, LMIC.txCnt)), KEEP_TXPOW); - // Schedule another retransmission - txDelay(LMIC.rxtime, RETRY_PERIOD_secs); - LMIC.opmode &= ~OP_TXRXPEND; - engineUpdate(); - return 1; - } - LMIC.txrxFlags = TXRX_NACK | TXRX_NOPORT; - } else { - // Nothing received - implies no port - LMIC.txrxFlags = TXRX_NOPORT; - } - if( LMIC.adrAckReq != LINK_CHECK_OFF ) - LMIC.adrAckReq += 1; - LMIC.dataBeg = LMIC.dataLen = 0; - txcomplete: - LMIC.opmode &= ~(OP_TXDATA|OP_TXRXPEND); - if( (LMIC.txrxFlags & (TXRX_DNW1|TXRX_DNW2|TXRX_PING)) != 0 && (LMIC.opmode & OP_LINKDEAD) != 0 ) { - LMIC.opmode &= ~OP_LINKDEAD; - reportEvent(EV_LINK_ALIVE); - } - reportEvent(EV_TXCOMPLETE); - // If we haven't heard from NWK in a while although we asked for a sign - // assume link is dead - notify application and keep going - if( LMIC.adrAckReq > LINK_CHECK_DEAD ) { - // We haven't heard from NWK for some time although we - // asked for a response for some time - assume we're disconnected. Lower DR one notch. - EV(devCond, ERR, (e_.reason = EV::devCond_t::LINK_DEAD, - e_.eui = MAIN::CDEV->getEui(), - e_.info = LMIC.adrAckReq)); - setDrTxpow(DRCHG_NOADRACK, decDR((dr_t)LMIC.datarate), KEEP_TXPOW); - LMIC.adrAckReq = LINK_CHECK_CONT; - LMIC.opmode |= OP_REJOIN|OP_LINKDEAD; - reportEvent(EV_LINK_DEAD); - } -#if !defined(DISABLE_BEACONS) - // If this falls to zero the NWK did not answer our MCMD_BCNI_REQ commands - try full scan - if( LMIC.bcninfoTries > 0 ) { - if( (LMIC.opmode & OP_TRACK) != 0 ) { - reportEvent(EV_BEACON_FOUND); - LMIC.bcninfoTries = 0; - } - else if( --LMIC.bcninfoTries == 0 ) { - startScan(); // NWK did not answer - try scan - } - } -#endif // !DISABLE_BEACONS - return 1; - } - if( !decodeFrame() ) { - if( (LMIC.txrxFlags & TXRX_DNW1) != 0 ) - return 0; - goto norx; - } - goto txcomplete; -} - - -#if !defined(DISABLE_BEACONS) -static void processBeacon (xref2osjob_t osjob) { - ostime_t lasttx = LMIC.bcninfo.txtime; // save here - decodeBeacon might overwrite - u1_t flags = LMIC.bcninfo.flags; - ev_t ev; - - if( LMIC.dataLen != 0 && decodeBeacon() >= 1 ) { - ev = EV_BEACON_TRACKED; - if( (flags & (BCN_PARTIAL|BCN_FULL)) == 0 ) { - // We don't have a previous beacon to calc some drift - assume - // an max error of 13ms = 128sec*100ppm which is roughly +/-100ppm - calcBcnRxWindowFromMillis(13,0); - goto rev; - } - // We have a previous BEACON to calculate some drift - s2_t drift = BCN_INTV_osticks - (LMIC.bcninfo.txtime - lasttx); - if( LMIC.missedBcns > 0 ) { - drift = LMIC.drift + (drift - LMIC.drift) / (LMIC.missedBcns+1); - } - if( (LMIC.bcninfo.flags & BCN_NODRIFT) == 0 ) { - s2_t diff = LMIC.drift - drift; - if( diff < 0 ) diff = -diff; - LMIC.lastDriftDiff = diff; - if( LMIC.maxDriftDiff < diff ) - LMIC.maxDriftDiff = diff; - LMIC.bcninfo.flags &= ~BCN_NODDIFF; - } - LMIC.drift = drift; - LMIC.missedBcns = LMIC.rejoinCnt = 0; - LMIC.bcninfo.flags &= ~BCN_NODRIFT; - EV(devCond,INFO,(e_.reason = EV::devCond_t::CLOCK_DRIFT, - e_.eui = MAIN::CDEV->getEui(), - e_.info = drift, - e_.info2 = /*occasion BEACON*/0)); - ASSERT((LMIC.bcninfo.flags & (BCN_PARTIAL|BCN_FULL)) != 0); - } else { - ev = EV_BEACON_MISSED; - LMIC.bcninfo.txtime += BCN_INTV_osticks - LMIC.drift; - LMIC.bcninfo.time += BCN_INTV_sec; - LMIC.missedBcns++; - // Delay any possible TX after surmised beacon - it's there although we missed it - txDelay(LMIC.bcninfo.txtime + BCN_RESERVE_osticks, 4); - if( LMIC.missedBcns > MAX_MISSED_BCNS ) - LMIC.opmode |= OP_REJOIN; // try if we can roam to another network - if( LMIC.bcnRxsyms > MAX_RXSYMS ) { - LMIC.opmode &= ~(OP_TRACK|OP_PINGABLE|OP_PINGINI|OP_REJOIN); - reportEvent(EV_LOST_TSYNC); - return; - } - } - LMIC.bcnRxtime = LMIC.bcninfo.txtime + BCN_INTV_osticks - calcRxWindow(0,DR_BCN); - LMIC.bcnRxsyms = LMIC.rxsyms; - rev: -#if CFG_us915 - LMIC.bcnChnl = (LMIC.bcnChnl+1) & 7; -#endif -#if !defined(DISABLE_PING) - if( (LMIC.opmode & OP_PINGINI) != 0 ) - rxschedInit(&LMIC.ping); // note: reuses LMIC.frame buffer! -#endif // !DISABLE_PING - reportEvent(ev); -} - - -static void startRxBcn (xref2osjob_t osjob) { - LMIC.osjob.func = FUNC_ADDR(processBeacon); - os_radio(RADIO_RX); -} -#endif // !DISABLE_BEACONS - - -#if !defined(DISABLE_PING) -static void startRxPing (xref2osjob_t osjob) { - LMIC.osjob.func = FUNC_ADDR(processPingRx); - os_radio(RADIO_RX); -} -#endif // !DISABLE_PING - - -// Decide what to do next for the MAC layer of a device -static void engineUpdate (void) { -#if LMIC_DEBUG_LEVEL > 0 - lmic_printf("%lu: engineUpdate, opmode=0x%x\n", os_getTime(), LMIC.opmode); -#endif - // Check for ongoing state: scan or TX/RX transaction - if( (LMIC.opmode & (OP_SCAN|OP_TXRXPEND|OP_SHUTDOWN)) != 0 ) - return; - -#if !defined(DISABLE_JOIN) - if( LMIC.devaddr == 0 && (LMIC.opmode & OP_JOINING) == 0 ) { - LMIC_startJoining(); - return; - } -#endif // !DISABLE_JOIN - - ostime_t now = os_getTime(); - ostime_t rxtime = 0; - ostime_t txbeg = 0; - -#if !defined(DISABLE_BEACONS) - if( (LMIC.opmode & OP_TRACK) != 0 ) { - // We are tracking a beacon - ASSERT( now + RX_RAMPUP - LMIC.bcnRxtime <= 0 ); - rxtime = LMIC.bcnRxtime - RX_RAMPUP; - } -#endif // !DISABLE_BEACONS - - if( (LMIC.opmode & (OP_JOINING|OP_REJOIN|OP_TXDATA|OP_POLL)) != 0 ) { - // Need to TX some data... - // Assuming txChnl points to channel which first becomes available again. - bit_t jacc = ((LMIC.opmode & (OP_JOINING|OP_REJOIN)) != 0 ? 1 : 0); - #if LMIC_DEBUG_LEVEL > 1 - if (jacc) - lmic_printf("%lu: Uplink join pending\n", os_getTime()); - else - lmic_printf("%lu: Uplink data pending\n", os_getTime()); - #endif - // Find next suitable channel and return availability time - if( (LMIC.opmode & OP_NEXTCHNL) != 0 ) { - txbeg = LMIC.txend = nextTx(now); - LMIC.opmode &= ~OP_NEXTCHNL; - #if LMIC_DEBUG_LEVEL > 1 - lmic_printf("%lu: Airtime available at %lu (channel duty limit)\n", os_getTime(), txbeg); - #endif - } else { - txbeg = LMIC.txend; - #if LMIC_DEBUG_LEVEL > 1 - lmic_printf("%lu: Airtime available at %lu (previously determined)\n", os_getTime(), txbeg); - #endif - } - // Delayed TX or waiting for duty cycle? - if( (LMIC.globalDutyRate != 0 || (LMIC.opmode & OP_RNDTX) != 0) && (txbeg - LMIC.globalDutyAvail) < 0 ) { - txbeg = LMIC.globalDutyAvail; - #if LMIC_DEBUG_LEVEL > 1 - lmic_printf("%lu: Airtime available at %lu (global duty limit)\n", os_getTime(), txbeg); - #endif - } -#if !defined(DISABLE_BEACONS) - // If we're tracking a beacon... - // then make sure TX-RX transaction is complete before beacon - if( (LMIC.opmode & OP_TRACK) != 0 && - txbeg + (jacc ? JOIN_GUARD_osticks : TXRX_GUARD_osticks) - rxtime > 0 ) { - - #if LMIC_DEBUG_LEVEL > 1 - lmic_printf("%lu: Awaiting beacon before uplink\n", os_getTime()); - #endif - - // Not enough time to complete TX-RX before beacon - postpone after beacon. - // In order to avoid clustering of postponed TX right after beacon randomize start! - txDelay(rxtime + BCN_RESERVE_osticks, 16); - txbeg = 0; - goto checkrx; - } -#endif // !DISABLE_BEACONS - // Earliest possible time vs overhead to setup radio - if( txbeg - (now + TX_RAMPUP) < 0 ) { - #if LMIC_DEBUG_LEVEL > 1 - lmic_printf("%lu: Ready for uplink\n", os_getTime()); - #endif - // We could send right now! - txbeg = now; - dr_t txdr = (dr_t)LMIC.datarate; -#if !defined(DISABLE_JOIN) - if( jacc ) { - u1_t ftype; - if( (LMIC.opmode & OP_REJOIN) != 0 ) { - txdr = lowerDR(txdr, LMIC.rejoinCnt); - ftype = HDR_FTYPE_REJOIN; - } else { - ftype = HDR_FTYPE_JREQ; - } - buildJoinRequest(ftype); - LMIC.osjob.func = FUNC_ADDR(jreqDone); - } else -#endif // !DISABLE_JOIN - { - if( LMIC.seqnoDn >= 0xFFFFFF80 ) { - // Imminent roll over - proactively reset MAC - EV(specCond, INFO, (e_.reason = EV::specCond_t::DNSEQNO_ROLL_OVER, - e_.eui = MAIN::CDEV->getEui(), - e_.info = LMIC.seqnoDn, - e_.info2 = 0)); - // Device has to react! NWK will not roll over and just stop sending. - // Thus, we have N frames to detect a possible lock up. - reset: - os_setCallback(&LMIC.osjob, FUNC_ADDR(runReset)); - return; - } - if( (LMIC.txCnt==0 && LMIC.seqnoUp == 0xFFFFFFFF) ) { - // Roll over of up seq counter - EV(specCond, ERR, (e_.reason = EV::specCond_t::UPSEQNO_ROLL_OVER, - e_.eui = MAIN::CDEV->getEui(), - e_.info2 = LMIC.seqnoUp)); - // Do not run RESET event callback from here! - // App code might do some stuff after send unaware of RESET. - goto reset; - } - buildDataFrame(); - LMIC.osjob.func = FUNC_ADDR(updataDone); - } - LMIC.rps = setCr(updr2rps(txdr), (cr_t)LMIC.errcr); - LMIC.dndr = txdr; // carry TX datarate (can be != LMIC.datarate) over to txDone/setupRx1 - LMIC.opmode = (LMIC.opmode & ~(OP_POLL|OP_RNDTX)) | OP_TXRXPEND | OP_NEXTCHNL; - updateTx(txbeg); - os_radio(RADIO_TX); - return; - } - #if LMIC_DEBUG_LEVEL > 1 - lmic_printf("%lu: Uplink delayed until %lu\n", os_getTime(), txbeg); - #endif - // Cannot yet TX - if( (LMIC.opmode & OP_TRACK) == 0 ) - goto txdelay; // We don't track the beacon - nothing else to do - so wait for the time to TX - // Consider RX tasks - if( txbeg == 0 ) // zero indicates no TX pending - txbeg += 1; // TX delayed by one tick (insignificant amount of time) - } else { - // No TX pending - no scheduled RX - if( (LMIC.opmode & OP_TRACK) == 0 ) - return; - } - -#if !defined(DISABLE_BEACONS) - // Are we pingable? - checkrx: -#if !defined(DISABLE_PING) - if( (LMIC.opmode & OP_PINGINI) != 0 ) { - // One more RX slot in this beacon period? - if( rxschedNext(&LMIC.ping, now+RX_RAMPUP) ) { - if( txbeg != 0 && (txbeg - LMIC.ping.rxtime) < 0 ) - goto txdelay; - LMIC.rxsyms = LMIC.ping.rxsyms; - LMIC.rxtime = LMIC.ping.rxtime; - LMIC.freq = LMIC.ping.freq; - LMIC.rps = dndr2rps(LMIC.ping.dr); - LMIC.dataLen = 0; - ASSERT(LMIC.rxtime - now+RX_RAMPUP >= 0 ); - os_setTimedCallback(&LMIC.osjob, LMIC.rxtime - RX_RAMPUP, FUNC_ADDR(startRxPing)); - return; - } - // no - just wait for the beacon - } -#endif // !DISABLE_PING - - if( txbeg != 0 && (txbeg - rxtime) < 0 ) - goto txdelay; - - setBcnRxParams(); - LMIC.rxsyms = LMIC.bcnRxsyms; - LMIC.rxtime = LMIC.bcnRxtime; - if( now - rxtime >= 0 ) { - LMIC.osjob.func = FUNC_ADDR(processBeacon); - os_radio(RADIO_RX); - return; - } - os_setTimedCallback(&LMIC.osjob, rxtime, FUNC_ADDR(startRxBcn)); - return; -#endif // !DISABLE_BEACONS - - txdelay: - EV(devCond, INFO, (e_.reason = EV::devCond_t::TX_DELAY, - e_.eui = MAIN::CDEV->getEui(), - e_.info = osticks2ms(txbeg-now), - e_.info2 = LMIC.seqnoUp-1)); - os_setTimedCallback(&LMIC.osjob, txbeg-TX_RAMPUP, FUNC_ADDR(runEngineUpdate)); -} - - -void LMIC_setAdrMode (bit_t enabled) { - LMIC.adrEnabled = enabled ? FCT_ADREN : 0; -} - - -// Should we have/need an ext. API like this? -void LMIC_setDrTxpow (dr_t dr, s1_t txpow) { - setDrTxpow(DRCHG_SET, dr, txpow); -} - - -void LMIC_shutdown (void) { - os_clearCallback(&LMIC.osjob); - os_radio(RADIO_RST); - LMIC.opmode |= OP_SHUTDOWN; -} - - -void LMIC_reset (void) { - EV(devCond, INFO, (e_.reason = EV::devCond_t::LMIC_EV, - e_.eui = MAIN::CDEV->getEui(), - e_.info = EV_RESET)); - os_radio(RADIO_RST); - os_clearCallback(&LMIC.osjob); - - os_clearMem((xref2u1_t)&LMIC,SIZEOFEXPR(LMIC)); - LMIC.devaddr = 0; - LMIC.devNonce = os_getRndU2(); - LMIC.opmode = OP_NONE; - LMIC.errcr = CR_4_5; - LMIC.adrEnabled = FCT_ADREN; - LMIC.dn2Dr = DR_DNW2; // we need this for 2nd DN window of join accept - LMIC.dn2Freq = FREQ_DNW2; // ditto - LMIC.rxDelay = DELAY_DNW1; -#if !defined(DISABLE_PING) - LMIC.ping.freq = FREQ_PING; // defaults for ping - LMIC.ping.dr = DR_PING; // ditto - LMIC.ping.intvExp = 0xFF; -#endif // !DISABLE_PING -#if defined(CFG_us915) - initDefaultChannels(); -#endif - DO_DEVDB(LMIC.devaddr, devaddr); - DO_DEVDB(LMIC.devNonce, devNonce); - DO_DEVDB(LMIC.dn2Dr, dn2Dr); - DO_DEVDB(LMIC.dn2Freq, dn2Freq); -#if !defined(DISABLE_PING) - DO_DEVDB(LMIC.ping.freq, pingFreq); - DO_DEVDB(LMIC.ping.dr, pingDr); - DO_DEVDB(LMIC.ping.intvExp, pingIntvExp); -#endif // !DISABLE_PING -} - - -void LMIC_init (void) { - LMIC.opmode = OP_SHUTDOWN; -} - - -void LMIC_clrTxData (void) { - LMIC.opmode &= ~(OP_TXDATA|OP_TXRXPEND|OP_POLL); - LMIC.pendTxLen = 0; - if( (LMIC.opmode & (OP_JOINING|OP_SCAN)) != 0 ) // do not interfere with JOINING - return; - os_clearCallback(&LMIC.osjob); - os_radio(RADIO_RST); - engineUpdate(); -} - - -void LMIC_setTxData (void) { - LMIC.opmode |= OP_TXDATA; - if( (LMIC.opmode & OP_JOINING) == 0 ) - LMIC.txCnt = 0; // cancel any ongoing TX/RX retries - engineUpdate(); -} - - -// -int LMIC_setTxData2 (u1_t port, xref2u1_t data, u1_t dlen, u1_t confirmed) { - if( dlen > SIZEOFEXPR(LMIC.pendTxData) ) - return -2; - if( data != (xref2u1_t)0 ) - os_copyMem(LMIC.pendTxData, data, dlen); - LMIC.pendTxConf = confirmed; - LMIC.pendTxPort = port; - LMIC.pendTxLen = dlen; - LMIC_setTxData(); - return 0; -} - - -// Send a payload-less message to signal device is alive -void LMIC_sendAlive (void) { - LMIC.opmode |= OP_POLL; - engineUpdate(); -} - - -// Check if other networks are around. -void LMIC_tryRejoin (void) { - LMIC.opmode |= OP_REJOIN; - engineUpdate(); -} - -//! \brief Setup given session keys -//! and put the MAC in a state as if -//! a join request/accept would have negotiated just these keys. -//! It is crucial that the combinations `devaddr/nwkkey` and `devaddr/artkey` -//! are unique within the network identified by `netid`. -//! NOTE: on Harvard architectures when session keys are in flash: -//! Caller has to fill in LMIC.{nwk,art}Key before and pass {nwk,art}Key are NULL -//! \param netid a 24 bit number describing the network id this device is using -//! \param devaddr the 32 bit session address of the device. It is strongly recommended -//! to ensure that different devices use different numbers with high probability. -//! \param nwkKey the 16 byte network session key used for message integrity. -//! If NULL the caller has copied the key into `LMIC.nwkKey` before. -//! \param artKey the 16 byte application router session key used for message confidentiality. -//! If NULL the caller has copied the key into `LMIC.artKey` before. -void LMIC_setSession (u4_t netid, devaddr_t devaddr, xref2u1_t nwkKey, xref2u1_t artKey) { - LMIC.netid = netid; - LMIC.devaddr = devaddr; - if( nwkKey != (xref2u1_t)0 ) - os_copyMem(LMIC.nwkKey, nwkKey, 16); - if( artKey != (xref2u1_t)0 ) - os_copyMem(LMIC.artKey, artKey, 16); - -#if defined(CFG_eu868) - initDefaultChannels(0); -#endif - - LMIC.opmode &= ~(OP_JOINING|OP_TRACK|OP_REJOIN|OP_TXRXPEND|OP_PINGINI); - LMIC.opmode |= OP_NEXTCHNL; - stateJustJoined(); - DO_DEVDB(LMIC.netid, netid); - DO_DEVDB(LMIC.devaddr, devaddr); - DO_DEVDB(LMIC.nwkKey, nwkkey); - DO_DEVDB(LMIC.artKey, artkey); - DO_DEVDB(LMIC.seqnoUp, seqnoUp); - DO_DEVDB(LMIC.seqnoDn, seqnoDn); -} - -// Enable/disable link check validation. -// LMIC sets the ADRACKREQ bit in UP frames if there were no DN frames -// for a while. It expects the network to provide a DN message to prove -// connectivity with a span of UP frames. If this no such prove is coming -// then the datarate is lowered and a LINK_DEAD event is generated. -// This mode can be disabled and no connectivity prove (ADRACKREQ) is requested -// nor is the datarate changed. -// This must be called only if a session is established (e.g. after EV_JOINED) -void LMIC_setLinkCheckMode (bit_t enabled) { - LMIC.adrChanged = 0; - LMIC.adrAckReq = enabled ? LINK_CHECK_INIT : LINK_CHECK_OFF; -} - -// Sets the max clock error to compensate for (defaults to 0, which -// allows for +/- 640 at SF7BW250). MAX_CLOCK_ERROR represents +/-100%, -// so e.g. for a +/-1% error you would pass MAX_CLOCK_ERROR * 1 / 100. -void LMIC_setClockError(u2_t error) { - LMIC.clockError = error; -} diff --git a/lib/arduino-lmic-1.5.0-arduino-2-tweaked/src/lmic/lmic.h b/lib/arduino-lmic-1.5.0-arduino-2-tweaked/src/lmic/lmic.h deleted file mode 100644 index 4a4c86be..00000000 --- a/lib/arduino-lmic-1.5.0-arduino-2-tweaked/src/lmic/lmic.h +++ /dev/null @@ -1,320 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2014-2015 IBM Corporation. - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * http://www.eclipse.org/legal/epl-v10.html - * - * Contributors: - * IBM Zurich Research Lab - initial API, implementation and documentation - *******************************************************************************/ - -//! @file -//! @brief LMIC API - -#ifndef _lmic_h_ -#define _lmic_h_ - -#include "oslmic.h" -#include "lorabase.h" - -#ifdef __cplusplus -extern "C"{ -#endif - -// LMIC version -#define LMIC_VERSION_MAJOR 1 -#define LMIC_VERSION_MINOR 5 -#define LMIC_VERSION_BUILD 1431528305 - -enum { MAX_FRAME_LEN = 64 }; //!< Library cap on max frame length -enum { TXCONF_ATTEMPTS = 8 }; //!< Transmit attempts for confirmed frames -enum { MAX_MISSED_BCNS = 20 }; // threshold for triggering rejoin requests -enum { MAX_RXSYMS = 100 }; // stop tracking beacon beyond this - -enum { LINK_CHECK_CONT = 12 , // continue with this after reported dead link - LINK_CHECK_DEAD = 24 , // after this UP frames and no response from NWK assume link is dead - LINK_CHECK_INIT = -12 , // UP frame count until we inc datarate - LINK_CHECK_OFF =-128 }; // link check disabled - -enum { TIME_RESYNC = 6*128 }; // secs -enum { TXRX_GUARD_ms = 6000 }; // msecs - don't start TX-RX transaction before beacon -enum { JOIN_GUARD_ms = 9000 }; // msecs - don't start Join Req/Acc transaction before beacon -enum { TXRX_BCNEXT_secs = 2 }; // secs - earliest start after beacon time -enum { RETRY_PERIOD_secs = 3 }; // secs - random period for retrying a confirmed send - -#if defined(CFG_eu868) // EU868 spectrum ==================================================== - -enum { MAX_CHANNELS = 16 }; //!< Max supported channels -enum { MAX_BANDS = 4 }; - -enum { LIMIT_CHANNELS = (1<<4) }; // EU868 will never have more channels -//! \internal -struct band_t { - u2_t txcap; // duty cycle limitation: 1/txcap - s1_t txpow; // maximum TX power - u1_t lastchnl; // last used channel - ostime_t avail; // channel is blocked until this time -}; -TYPEDEF_xref2band_t; //!< \internal - -#elif defined(CFG_us915) // US915 spectrum ================================================= - -enum { MAX_XCHANNELS = 2 }; // extra channels in RAM, channels 0-71 are immutable -enum { MAX_TXPOW_125kHz = 30 }; - -#endif // ========================================================================== - -// Keep in sync with evdefs.hpp::drChange -enum { DRCHG_SET, DRCHG_NOJACC, DRCHG_NOACK, DRCHG_NOADRACK, DRCHG_NWKCMD }; -enum { KEEP_TXPOW = -128 }; - - -#if !defined(DISABLE_PING) -//! \internal -struct rxsched_t { - u1_t dr; - u1_t intvExp; // 0..7 - u1_t slot; // runs from 0 to 128 - u1_t rxsyms; - ostime_t rxbase; - ostime_t rxtime; // start of next spot - u4_t freq; -}; -TYPEDEF_xref2rxsched_t; //!< \internal -#endif // !DISABLE_PING - - -#if !defined(DISABLE_BEACONS) -//! Parsing and tracking states of beacons. -enum { BCN_NONE = 0x00, //!< No beacon received - BCN_PARTIAL = 0x01, //!< Only first (common) part could be decoded (info,lat,lon invalid/previous) - BCN_FULL = 0x02, //!< Full beacon decoded - BCN_NODRIFT = 0x04, //!< No drift value measured yet - BCN_NODDIFF = 0x08 }; //!< No differential drift measured yet -//! Information about the last and previous beacons. -struct bcninfo_t { - ostime_t txtime; //!< Time when the beacon was sent - s1_t rssi; //!< Adjusted RSSI value of last received beacon - s1_t snr; //!< Scaled SNR value of last received beacon - u1_t flags; //!< Last beacon reception and tracking states. See BCN_* values. - u4_t time; //!< GPS time in seconds of last beacon (received or surrogate) - // - u1_t info; //!< Info field of last beacon (valid only if BCN_FULL set) - s4_t lat; //!< Lat field of last beacon (valid only if BCN_FULL set) - s4_t lon; //!< Lon field of last beacon (valid only if BCN_FULL set) -}; -#endif // !DISABLE_BEACONS - -// purpose of receive window - lmic_t.rxState -enum { RADIO_RST=0, RADIO_TX=1, RADIO_RX=2, RADIO_RXON=3 }; -// Netid values / lmic_t.netid -enum { NETID_NONE=(int)~0U, NETID_MASK=(int)0xFFFFFF }; -// MAC operation modes (lmic_t.opmode). -enum { OP_NONE = 0x0000, - OP_SCAN = 0x0001, // radio scan to find a beacon - OP_TRACK = 0x0002, // track my networks beacon (netid) - OP_JOINING = 0x0004, // device joining in progress (blocks other activities) - OP_TXDATA = 0x0008, // TX user data (buffered in pendTxData) - OP_POLL = 0x0010, // send empty UP frame to ACK confirmed DN/fetch more DN data - OP_REJOIN = 0x0020, // occasionally send JOIN REQUEST - OP_SHUTDOWN = 0x0040, // prevent MAC from doing anything - OP_TXRXPEND = 0x0080, // TX/RX transaction pending - OP_RNDTX = 0x0100, // prevent TX lining up after a beacon - OP_PINGINI = 0x0200, // pingable is initialized and scheduling active - OP_PINGABLE = 0x0400, // we're pingable - OP_NEXTCHNL = 0x0800, // find a new channel - OP_LINKDEAD = 0x1000, // link was reported as dead - OP_TESTMODE = 0x2000, // developer test mode -}; -// TX-RX transaction flags - report back to user -enum { TXRX_ACK = 0x80, // confirmed UP frame was acked - TXRX_NACK = 0x40, // confirmed UP frame was not acked - TXRX_NOPORT = 0x20, // set if a frame with a port was RXed, clr if no frame/no port - TXRX_PORT = 0x10, // set if a frame with a port was RXed, LMIC.frame[LMIC.dataBeg-1] => port - TXRX_DNW1 = 0x01, // received in 1st DN slot - TXRX_DNW2 = 0x02, // received in 2dn DN slot - TXRX_PING = 0x04 }; // received in a scheduled RX slot -// Event types for event callback -enum _ev_t { EV_SCAN_TIMEOUT=1, EV_BEACON_FOUND, - EV_BEACON_MISSED, EV_BEACON_TRACKED, EV_JOINING, - EV_JOINED, EV_RFU1, EV_JOIN_FAILED, EV_REJOIN_FAILED, - EV_TXCOMPLETE, EV_LOST_TSYNC, EV_RESET, - EV_RXCOMPLETE, EV_LINK_DEAD, EV_LINK_ALIVE }; -typedef enum _ev_t ev_t; - -enum { - // This value represents 100% error in LMIC.clockError - MAX_CLOCK_ERROR = 65536, -}; - -struct lmic_t { - // Radio settings TX/RX (also accessed by HAL) - ostime_t txend; - ostime_t rxtime; - u4_t freq; - s1_t rssi; - s1_t snr; - rps_t rps; - u1_t rxsyms; - u1_t dndr; - s1_t txpow; // dBm - - osjob_t osjob; - - // Channel scheduling -#if defined(CFG_eu868) - band_t bands[MAX_BANDS]; - u4_t channelFreq[MAX_CHANNELS]; - u2_t channelDrMap[MAX_CHANNELS]; - u2_t channelMap; -#elif defined(CFG_us915) - u4_t xchFreq[MAX_XCHANNELS]; // extra channel frequencies (if device is behind a repeater) - u2_t xchDrMap[MAX_XCHANNELS]; // extra channel datarate ranges ---XXX: ditto - u2_t channelMap[(72+MAX_XCHANNELS+15)/16]; // enabled bits - u2_t chRnd; // channel randomizer -#endif - u1_t txChnl; // channel for next TX - u1_t globalDutyRate; // max rate: 1/2^k - ostime_t globalDutyAvail; // time device can send again - - u4_t netid; // current network id (~0 - none) - u2_t opmode; - u1_t upRepeat; // configured up repeat - s1_t adrTxPow; // ADR adjusted TX power - u1_t datarate; // current data rate - u1_t errcr; // error coding rate (used for TX only) - u1_t rejoinCnt; // adjustment for rejoin datarate -#if !defined(DISABLE_BEACONS) - s2_t drift; // last measured drift - s2_t lastDriftDiff; - s2_t maxDriftDiff; -#endif - - u2_t clockError; // Inaccuracy in the clock. CLOCK_ERROR_MAX - // represents +/-100% error - - u1_t pendTxPort; - u1_t pendTxConf; // confirmed data - u1_t pendTxLen; // +0x80 = confirmed - u1_t pendTxData[MAX_LEN_PAYLOAD]; - - u2_t devNonce; // last generated nonce - u1_t nwkKey[16]; // network session key - u1_t artKey[16]; // application router session key - devaddr_t devaddr; - u4_t seqnoDn; // device level down stream seqno - u4_t seqnoUp; - - u1_t dnConf; // dn frame confirm pending: LORA::FCT_ACK or 0 - s1_t adrAckReq; // counter until we reset data rate (0=off) - u1_t adrChanged; - - u1_t rxDelay; // Rx delay after TX - - u1_t margin; - bit_t ladrAns; // link adr adapt answer pending - bit_t devsAns; // device status answer pending - u1_t adrEnabled; - u1_t moreData; // NWK has more data pending -#if !defined(DISABLE_MCMD_DCAP_REQ) - bit_t dutyCapAns; // have to ACK duty cycle settings -#endif -#if !defined(DISABLE_MCMD_SNCH_REQ) - u1_t snchAns; // answer set new channel -#endif - // 2nd RX window (after up stream) - u1_t dn2Dr; - u4_t dn2Freq; -#if !defined(DISABLE_MCMD_DN2P_SET) - u1_t dn2Ans; // 0=no answer pend, 0x80+ACKs -#endif - - // Class B state -#if !defined(DISABLE_BEACONS) - u1_t missedBcns; // unable to track last N beacons - u1_t bcninfoTries; // how often to try (scan mode only) -#endif -#if !defined(DISABLE_MCMD_PING_SET) && !defined(DISABLE_PING) - u1_t pingSetAns; // answer set cmd and ACK bits -#endif -#if !defined(DISABLE_PING) - rxsched_t ping; // pingable setup -#endif - - // Public part of MAC state - u1_t txCnt; - u1_t txrxFlags; // transaction flags (TX-RX combo) - u1_t dataBeg; // 0 or start of data (dataBeg-1 is port) - u1_t dataLen; // 0 no data or zero length data, >0 byte count of data - u1_t frame[MAX_LEN_FRAME]; - -#if !defined(DISABLE_BEACONS) - u1_t bcnChnl; - u1_t bcnRxsyms; // - ostime_t bcnRxtime; - bcninfo_t bcninfo; // Last received beacon info -#endif -}; -//! \var struct lmic_t LMIC -//! The state of LMIC MAC layer is encapsulated in this variable. -DECLARE_LMIC; //!< \internal - -//! Construct a bit map of allowed datarates from drlo to drhi (both included). -#define DR_RANGE_MAP(drlo,drhi) (((u2_t)0xFFFF<<(drlo)) & ((u2_t)0xFFFF>>(15-(drhi)))) -#if defined(CFG_eu868) -enum { BAND_MILLI=0, BAND_CENTI=1, BAND_DECI=2, BAND_AUX=3 }; -bit_t LMIC_setupBand (u1_t bandidx, s1_t txpow, u2_t txcap); -#endif -bit_t LMIC_setupChannel (u1_t channel, u4_t freq, u2_t drmap, s1_t band); -void LMIC_disableChannel (u1_t channel); -#if defined(CFG_us915) -void LMIC_enableChannel (u1_t channel); -void LMIC_enableSubBand (u1_t band); -void LMIC_disableSubBand (u1_t band); -void LMIC_selectSubBand (u1_t band); -#endif - -void LMIC_setDrTxpow (dr_t dr, s1_t txpow); // set default/start DR/txpow -void LMIC_setAdrMode (bit_t enabled); // set ADR mode (if mobile turn off) -#if !defined(DISABLE_JOIN) -bit_t LMIC_startJoining (void); -#endif - -void LMIC_shutdown (void); -void LMIC_init (void); -void LMIC_reset (void); -void LMIC_clrTxData (void); -void LMIC_setTxData (void); -int LMIC_setTxData2 (u1_t port, xref2u1_t data, u1_t dlen, u1_t confirmed); -void LMIC_sendAlive (void); - -#if !defined(DISABLE_BEACONS) -bit_t LMIC_enableTracking (u1_t tryBcnInfo); -void LMIC_disableTracking (void); -#endif - -#if !defined(DISABLE_PING) -void LMIC_stopPingable (void); -void LMIC_setPingable (u1_t intvExp); -#endif -#if !defined(DISABLE_JOIN) -void LMIC_tryRejoin (void); -#endif - -void LMIC_setSession (u4_t netid, devaddr_t devaddr, xref2u1_t nwkKey, xref2u1_t artKey); -void LMIC_setLinkCheckMode (bit_t enabled); -void LMIC_setClockError(u2_t error); - -// Declare onEvent() function, to make sure any definition will have the -// C conventions, even when in a C++ file. -DECL_ON_LMIC_EVENT; - -// Special APIs - for development or testing -// !!!See implementation for caveats!!! - -#ifdef __cplusplus -} // extern "C" -#endif - -#endif // _lmic_h_ diff --git a/lib/arduino-lmic-1.5.0-arduino-2-tweaked/src/lmic/lorabase.h b/lib/arduino-lmic-1.5.0-arduino-2-tweaked/src/lmic/lorabase.h deleted file mode 100644 index f95cfd2d..00000000 --- a/lib/arduino-lmic-1.5.0-arduino-2-tweaked/src/lmic/lorabase.h +++ /dev/null @@ -1,391 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2014-2015 IBM Corporation. - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * http://www.eclipse.org/legal/epl-v10.html - * - * Contributors: - * IBM Zurich Research Lab - initial API, implementation and documentation - *******************************************************************************/ - -#ifndef _lorabase_h_ -#define _lorabase_h_ - -#ifdef __cplusplus -extern "C"{ -#endif - -// ================================================================================ -// BEG: Keep in sync with lorabase.hpp -// - -enum _cr_t { CR_4_5=0, CR_4_6, CR_4_7, CR_4_8 }; -enum _sf_t { FSK=0, SF7, SF8, SF9, SF10, SF11, SF12, SFrfu }; -enum _bw_t { BW125=0, BW250, BW500, BWrfu }; -typedef u1_t cr_t; -typedef u1_t sf_t; -typedef u1_t bw_t; -typedef u1_t dr_t; -// Radio parameter set (encodes SF/BW/CR/IH/NOCRC) -typedef u2_t rps_t; -TYPEDEF_xref2rps_t; - -enum { ILLEGAL_RPS = 0xFF }; -enum { DR_PAGE_EU868 = 0x00 }; -enum { DR_PAGE_US915 = 0x10 }; - -// Global maximum frame length -enum { STD_PREAMBLE_LEN = 8 }; -enum { MAX_LEN_FRAME = 64 }; -enum { LEN_DEVNONCE = 2 }; -enum { LEN_ARTNONCE = 3 }; -enum { LEN_NETID = 3 }; -enum { DELAY_JACC1 = 5 }; // in secs -enum { DELAY_DNW1 = 1 }; // in secs down window #1 -enum { DELAY_EXTDNW2 = 1 }; // in secs -enum { DELAY_JACC2 = DELAY_JACC1+(int)DELAY_EXTDNW2 }; // in secs -enum { DELAY_DNW2 = DELAY_DNW1 +(int)DELAY_EXTDNW2 }; // in secs down window #1 -enum { BCN_INTV_exp = 7 }; -enum { BCN_INTV_sec = 1<> 3) & 0x3); } -inline rps_t setBw (rps_t params, bw_t cr) { return (rps_t)((params & ~0x18) | (cr<<3)); } -inline cr_t getCr (rps_t params) { return (cr_t)((params >> 5) & 0x3); } -inline rps_t setCr (rps_t params, cr_t cr) { return (rps_t)((params & ~0x60) | (cr<<5)); } -inline int getNocrc(rps_t params) { return ((params >> 7) & 0x1); } -inline rps_t setNocrc(rps_t params, int nocrc) { return (rps_t)((params & ~0x80) | (nocrc<<7)); } -inline int getIh (rps_t params) { return ((params >> 8) & 0xFF); } -inline rps_t setIh (rps_t params, int ih) { return (rps_t)((params & ~0xFF00) | (ih<<8)); } -inline rps_t makeRps (sf_t sf, bw_t bw, cr_t cr, int ih, int nocrc) { - return sf | (bw<<3) | (cr<<5) | (nocrc?(1<<7):0) | ((ih&0xFF)<<8); -} -#define MAKERPS(sf,bw,cr,ih,nocrc) ((rps_t)((sf) | ((bw)<<3) | ((cr)<<5) | ((nocrc)?(1<<7):0) | ((ih&0xFF)<<8))) -// Two frames with params r1/r2 would interfere on air: same SFx + BWx -inline int sameSfBw(rps_t r1, rps_t r2) { return ((r1^r2)&0x1F) == 0; } - -extern CONST_TABLE(u1_t, _DR2RPS_CRC)[]; -inline rps_t updr2rps (dr_t dr) { return (rps_t)TABLE_GET_U1(_DR2RPS_CRC, dr+1); } -inline rps_t dndr2rps (dr_t dr) { return setNocrc(updr2rps(dr),1); } -inline int isFasterDR (dr_t dr1, dr_t dr2) { return dr1 > dr2; } -inline int isSlowerDR (dr_t dr1, dr_t dr2) { return dr1 < dr2; } -inline dr_t incDR (dr_t dr) { return TABLE_GET_U1(_DR2RPS_CRC, dr+2)==ILLEGAL_RPS ? dr : (dr_t)(dr+1); } // increase data rate -inline dr_t decDR (dr_t dr) { return TABLE_GET_U1(_DR2RPS_CRC, dr )==ILLEGAL_RPS ? dr : (dr_t)(dr-1); } // decrease data rate -inline dr_t assertDR (dr_t dr) { return TABLE_GET_U1(_DR2RPS_CRC, dr+1)==ILLEGAL_RPS ? DR_DFLTMIN : dr; } // force into a valid DR -inline bit_t validDR (dr_t dr) { return TABLE_GET_U1(_DR2RPS_CRC, dr+1)!=ILLEGAL_RPS; } // in range -inline dr_t lowerDR (dr_t dr, u1_t n) { while(n--){dr=decDR(dr);} return dr; } // decrease data rate by n steps - -// -// BEG: Keep in sync with lorabase.hpp -// ================================================================================ - - -// Convert between dBm values and power codes (MCMD_LADR_XdBm) -s1_t pow2dBm (u1_t mcmd_ladr_p1); -// Calculate airtime -ostime_t calcAirTime (rps_t rps, u1_t plen); -// Sensitivity at given SF/BW -int getSensitivity (rps_t rps); - -#ifdef __cplusplus -} // extern "C" -#endif - -#endif // _lorabase_h_ diff --git a/lib/arduino-lmic-1.5.0-arduino-2-tweaked/src/lmic/oslmic.c b/lib/arduino-lmic-1.5.0-arduino-2-tweaked/src/lmic/oslmic.c deleted file mode 100644 index c0883f1a..00000000 --- a/lib/arduino-lmic-1.5.0-arduino-2-tweaked/src/lmic/oslmic.c +++ /dev/null @@ -1,129 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2014-2015 IBM Corporation. - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * http://www.eclipse.org/legal/epl-v10.html - * - * Contributors: - * IBM Zurich Research Lab - initial API, implementation and documentation - *******************************************************************************/ - -#include "lmic.h" -#include - -// RUNTIME STATE -static struct { - osjob_t* scheduledjobs; - osjob_t* runnablejobs; -} OS; - -void os_init () { - memset(&OS, 0x00, sizeof(OS)); - hal_init(); - radio_init(); - LMIC_init(); -} - -ostime_t os_getTime () { - return hal_ticks(); -} - -static u1_t unlinkjob (osjob_t** pnext, osjob_t* job) { - for( ; *pnext; pnext = &((*pnext)->next)) { - if(*pnext == job) { // unlink - *pnext = job->next; - return 1; - } - } - return 0; -} - -// clear scheduled job -void os_clearCallback (osjob_t* job) { - hal_disableIRQs(); - u1_t res = unlinkjob(&OS.scheduledjobs, job) || unlinkjob(&OS.runnablejobs, job); - hal_enableIRQs(); - #if LMIC_DEBUG_LEVEL > 1 - if (res) - lmic_printf("%lu: Cleared job %p\n", os_getTime(), job); - #endif -} - -// schedule immediately runnable job -void os_setCallback (osjob_t* job, osjobcb_t cb) { - osjob_t** pnext; - hal_disableIRQs(); - // remove if job was already queued - os_clearCallback(job); - // fill-in job - job->func = cb; - job->next = NULL; - // add to end of run queue - for(pnext=&OS.runnablejobs; *pnext; pnext=&((*pnext)->next)); - *pnext = job; - hal_enableIRQs(); - #if LMIC_DEBUG_LEVEL > 1 - lmic_printf("%lu: Scheduled job %p, cb %p ASAP\n", os_getTime(), job, cb); - #endif -} - -// schedule timed job -void os_setTimedCallback (osjob_t* job, ostime_t time, osjobcb_t cb) { - osjob_t** pnext; - hal_disableIRQs(); - // remove if job was already queued - os_clearCallback(job); - // fill-in job - job->deadline = time; - job->func = cb; - job->next = NULL; - // insert into schedule - for(pnext=&OS.scheduledjobs; *pnext; pnext=&((*pnext)->next)) { - if((*pnext)->deadline - time > 0) { // (cmp diff, not abs!) - // enqueue before next element and stop - job->next = *pnext; - break; - } - } - *pnext = job; - hal_enableIRQs(); - #if LMIC_DEBUG_LEVEL > 1 - lmic_printf("%lu: Scheduled job %p, cb %p at %lu\n", os_getTime(), job, cb, time); - #endif -} - -// execute jobs from timer and from run queue -void os_runloop () { - while(1) { - os_runloop_once(); - } -} - -void os_runloop_once() { - #if LMIC_DEBUG_LEVEL > 1 - bool has_deadline = false; - #endif - osjob_t* j = NULL; - hal_disableIRQs(); - // check for runnable jobs - if(OS.runnablejobs) { - j = OS.runnablejobs; - OS.runnablejobs = j->next; - } else if(OS.scheduledjobs && hal_checkTimer(OS.scheduledjobs->deadline)) { // check for expired timed jobs - j = OS.scheduledjobs; - OS.scheduledjobs = j->next; - #if LMIC_DEBUG_LEVEL > 1 - has_deadline = true; - #endif - } else { // nothing pending - hal_sleep(); // wake by irq (timer already restarted) - } - hal_enableIRQs(); - if(j) { // run job callback - #if LMIC_DEBUG_LEVEL > 1 - lmic_printf("%lu: Running job %p, cb %p, deadline %lu\n", os_getTime(), j, j->func, has_deadline ? j->deadline : 0); - #endif - j->func(j); - } -} diff --git a/lib/arduino-lmic-1.5.0-arduino-2-tweaked/src/lmic/oslmic.h b/lib/arduino-lmic-1.5.0-arduino-2-tweaked/src/lmic/oslmic.h deleted file mode 100644 index 2253030e..00000000 --- a/lib/arduino-lmic-1.5.0-arduino-2-tweaked/src/lmic/oslmic.h +++ /dev/null @@ -1,288 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2014-2015 IBM Corporation. - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * http://www.eclipse.org/legal/epl-v10.html - * - * Contributors: - * IBM Zurich Research Lab - initial API, implementation and documentation - *******************************************************************************/ - -//! \file -#ifndef _oslmic_h_ -#define _oslmic_h_ - -// Dependencies required for the LoRa MAC in C to run. -// These settings can be adapted to the underlying system. -// You should not, however, change the lmic.[hc] - -#include "config.h" -#include -#include - -#ifdef __cplusplus -extern "C"{ -#endif - -//================================================================================ -//================================================================================ -// Target platform as C library -typedef uint8_t bit_t; -typedef uint8_t u1_t; -typedef int8_t s1_t; -typedef uint16_t u2_t; -typedef int16_t s2_t; -typedef uint32_t u4_t; -typedef int32_t s4_t; -typedef unsigned int uint; -typedef const char* str_t; - -#include -#include "hal.h" -#define EV(a,b,c) /**/ -#define DO_DEVDB(field1,field2) /**/ -#if !defined(CFG_noassert) -#define ASSERT(cond) if(!(cond)) hal_failed(__FILE__, __LINE__) -#else -#define ASSERT(cond) /**/ -#endif - -#define os_clearMem(a,b) memset(a,0,b) -#define os_copyMem(a,b,c) memcpy(a,b,c) - -typedef struct osjob_t osjob_t; -typedef struct band_t band_t; -typedef struct chnldef_t chnldef_t; -typedef struct rxsched_t rxsched_t; -typedef struct bcninfo_t bcninfo_t; -typedef const u1_t* xref2cu1_t; -typedef u1_t* xref2u1_t; -#define TYPEDEF_xref2rps_t typedef rps_t* xref2rps_t -#define TYPEDEF_xref2rxsched_t typedef rxsched_t* xref2rxsched_t -#define TYPEDEF_xref2chnldef_t typedef chnldef_t* xref2chnldef_t -#define TYPEDEF_xref2band_t typedef band_t* xref2band_t -#define TYPEDEF_xref2osjob_t typedef osjob_t* xref2osjob_t - -#define SIZEOFEXPR(x) sizeof(x) - -#define ON_LMIC_EVENT(ev) onEvent(ev) -#define DECL_ON_LMIC_EVENT void onEvent(ev_t e) - -extern u4_t AESAUX[]; -extern u4_t AESKEY[]; -#define AESkey ((u1_t*)AESKEY) -#define AESaux ((u1_t*)AESAUX) -#define FUNC_ADDR(func) (&(func)) - -u1_t radio_rand1 (void); -#define os_getRndU1() radio_rand1() - -#define DEFINE_LMIC struct lmic_t LMIC -#define DECLARE_LMIC extern struct lmic_t LMIC - -void radio_init (void); -void radio_irq_handler (u1_t dio); -void os_init (void); -void os_runloop (void); -void os_runloop_once (void); - -//================================================================================ - - -#ifndef RX_RAMPUP -#define RX_RAMPUP (us2osticks(2000)) -#endif -#ifndef TX_RAMPUP -#define TX_RAMPUP (us2osticks(2000)) -#endif - -#ifndef OSTICKS_PER_SEC -#define OSTICKS_PER_SEC 32768 -#elif OSTICKS_PER_SEC < 10000 || OSTICKS_PER_SEC > 64516 -#error Illegal OSTICKS_PER_SEC - must be in range [10000:64516]. One tick must be 15.5us .. 100us long. -#endif - -typedef s4_t ostime_t; - -#if !HAS_ostick_conv -#define us2osticks(us) ((ostime_t)( ((int64_t)(us) * OSTICKS_PER_SEC) / 1000000)) -#define ms2osticks(ms) ((ostime_t)( ((int64_t)(ms) * OSTICKS_PER_SEC) / 1000)) -#define sec2osticks(sec) ((ostime_t)( (int64_t)(sec) * OSTICKS_PER_SEC)) -#define osticks2ms(os) ((s4_t)(((os)*(int64_t)1000 ) / OSTICKS_PER_SEC)) -#define osticks2us(os) ((s4_t)(((os)*(int64_t)1000000 ) / OSTICKS_PER_SEC)) -// Special versions -#define us2osticksCeil(us) ((ostime_t)( ((int64_t)(us) * OSTICKS_PER_SEC + 999999) / 1000000)) -#define us2osticksRound(us) ((ostime_t)( ((int64_t)(us) * OSTICKS_PER_SEC + 500000) / 1000000)) -#define ms2osticksCeil(ms) ((ostime_t)( ((int64_t)(ms) * OSTICKS_PER_SEC + 999) / 1000)) -#define ms2osticksRound(ms) ((ostime_t)( ((int64_t)(ms) * OSTICKS_PER_SEC + 500) / 1000)) -#endif - - -struct osjob_t; // fwd decl. -typedef void (*osjobcb_t) (struct osjob_t*); -struct osjob_t { - struct osjob_t* next; - ostime_t deadline; - osjobcb_t func; -}; -TYPEDEF_xref2osjob_t; - - -#ifndef HAS_os_calls - -#ifndef os_getDevKey -void os_getDevKey (xref2u1_t buf); -#endif -#ifndef os_getArtEui -void os_getArtEui (xref2u1_t buf); -#endif -#ifndef os_getDevEui -void os_getDevEui (xref2u1_t buf); -#endif -#ifndef os_setCallback -void os_setCallback (xref2osjob_t job, osjobcb_t cb); -#endif -#ifndef os_setTimedCallback -void os_setTimedCallback (xref2osjob_t job, ostime_t time, osjobcb_t cb); -#endif -#ifndef os_clearCallback -void os_clearCallback (xref2osjob_t job); -#endif -#ifndef os_getTime -ostime_t os_getTime (void); -#endif -#ifndef os_getTimeSecs -uint os_getTimeSecs (void); -#endif -#ifndef os_radio -void os_radio (u1_t mode); -#endif -#ifndef os_getBattLevel -u1_t os_getBattLevel (void); -#endif - -#ifndef os_rlsbf4 -//! Read 32-bit quantity from given pointer in little endian byte order. -u4_t os_rlsbf4 (xref2cu1_t buf); -#endif -#ifndef os_wlsbf4 -//! Write 32-bit quntity into buffer in little endian byte order. -void os_wlsbf4 (xref2u1_t buf, u4_t value); -#endif -#ifndef os_rmsbf4 -//! Read 32-bit quantity from given pointer in big endian byte order. -u4_t os_rmsbf4 (xref2cu1_t buf); -#endif -#ifndef os_wmsbf4 -//! Write 32-bit quntity into buffer in big endian byte order. -void os_wmsbf4 (xref2u1_t buf, u4_t value); -#endif -#ifndef os_rlsbf2 -//! Read 16-bit quantity from given pointer in little endian byte order. -u2_t os_rlsbf2 (xref2cu1_t buf); -#endif -#ifndef os_wlsbf2 -//! Write 16-bit quntity into buffer in little endian byte order. -void os_wlsbf2 (xref2u1_t buf, u2_t value); -#endif - -//! Get random number (default impl for u2_t). -#ifndef os_getRndU2 -#define os_getRndU2() ((u2_t)((os_getRndU1()<<8)|os_getRndU1())) -#endif -#ifndef os_crc16 -u2_t os_crc16 (xref2u1_t d, uint len); -#endif - -#endif // !HAS_os_calls - -// ====================================================================== -// Table support -// These macros for defining a table of constants and retrieving values -// from it makes it easier for other platforms (like AVR) to optimize -// table accesses. -// Use CONST_TABLE() whenever declaring or defining a table, and -// TABLE_GET_xx whenever accessing its values. The actual name of the -// declared variable will be modified to prevent accidental direct -// access. The accessor macros forward to an inline function to allow -// proper type checking of the array element type. - -// Helper to add a prefix to the table name -#define RESOLVE_TABLE(table) constant_table_ ## table - -// Accessors for table elements -#define TABLE_GET_U1(table, index) table_get_u1(RESOLVE_TABLE(table), index) -#define TABLE_GET_S1(table, index) table_get_s1(RESOLVE_TABLE(table), index) -#define TABLE_GET_U2(table, index) table_get_u2(RESOLVE_TABLE(table), index) -#define TABLE_GET_S2(table, index) table_get_s2(RESOLVE_TABLE(table), index) -#define TABLE_GET_U4(table, index) table_get_u4(RESOLVE_TABLE(table), index) -#define TABLE_GET_S4(table, index) table_get_s4(RESOLVE_TABLE(table), index) -#define TABLE_GET_OSTIME(table, index) table_get_ostime(RESOLVE_TABLE(table), index) -#define TABLE_GET_U1_TWODIM(table, index1, index2) table_get_u1(RESOLVE_TABLE(table)[index1], index2) - -#if defined(__AVR__) - #include - // Macro to define the getter functions. This loads data from - // progmem using pgm_read_xx, or accesses memory directly when the - // index is a constant so gcc can optimize it away; - #define TABLE_GETTER(postfix, type, pgm_type) \ - inline type table_get ## postfix(const type *table, size_t index) { \ - if (__builtin_constant_p(table[index])) \ - return table[index]; \ - return pgm_read_ ## pgm_type(&table[index]); \ - } - - TABLE_GETTER(_u1, u1_t, byte); - TABLE_GETTER(_s1, s1_t, byte); - TABLE_GETTER(_u2, u2_t, word); - TABLE_GETTER(_s2, s2_t, word); - TABLE_GETTER(_u4, u4_t, dword); - TABLE_GETTER(_s4, s4_t, dword); - - // This assumes ostime_t is 4 bytes, so error out if it is not - typedef int check_sizeof_ostime_t[(sizeof(ostime_t) == 4) ? 0 : -1]; - TABLE_GETTER(_ostime, ostime_t, dword); - - // For AVR, store constants in PROGMEM, saving on RAM usage - #define CONST_TABLE(type, name) const type PROGMEM RESOLVE_TABLE(name) - - #define lmic_printf(fmt, ...) printf_P(PSTR(fmt), ## __VA_ARGS__) -#else - inline u1_t table_get_u1(const u1_t *table, size_t index) { return table[index]; } - inline s1_t table_get_s1(const s1_t *table, size_t index) { return table[index]; } - inline u2_t table_get_u2(const u2_t *table, size_t index) { return table[index]; } - inline s2_t table_get_s2(const s2_t *table, size_t index) { return table[index]; } - inline u4_t table_get_u4(const u4_t *table, size_t index) { return table[index]; } - inline s4_t table_get_s4(const s4_t *table, size_t index) { return table[index]; } - inline ostime_t table_get_ostime(const ostime_t *table, size_t index) { return table[index]; } - - // Declare a table - #define CONST_TABLE(type, name) const type RESOLVE_TABLE(name) - #define lmic_printf printf -#endif - -// ====================================================================== -// AES support -// !!Keep in sync with lorabase.hpp!! - -#ifndef AES_ENC // if AES_ENC is defined as macro all other values must be too -#define AES_ENC 0x00 -#define AES_DEC 0x01 -#define AES_MIC 0x02 -#define AES_CTR 0x04 -#define AES_MICNOAUX 0x08 -#endif -#ifndef AESkey // if AESkey is defined as macro all other values must be too -extern xref2u1_t AESkey; -extern xref2u1_t AESaux; -#endif -#ifndef os_aes -u4_t os_aes (u1_t mode, xref2u1_t buf, u2_t len); -#endif - -#ifdef __cplusplus -} // extern "C" -#endif - -#endif // _oslmic_h_ diff --git a/lib/arduino-lmic-1.5.0-arduino-2-tweaked/src/lmic/radio.c b/lib/arduino-lmic-1.5.0-arduino-2-tweaked/src/lmic/radio.c deleted file mode 100644 index 6c570545..00000000 --- a/lib/arduino-lmic-1.5.0-arduino-2-tweaked/src/lmic/radio.c +++ /dev/null @@ -1,860 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2014-2015 IBM Corporation. - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * http://www.eclipse.org/legal/epl-v10.html - * - * Contributors: - * IBM Zurich Research Lab - initial API, implementation and documentation - *******************************************************************************/ - -#include "lmic.h" - -// ---------------------------------------- -// Registers Mapping -#define RegFifo 0x00 // common -#define RegOpMode 0x01 // common -#define FSKRegBitrateMsb 0x02 -#define FSKRegBitrateLsb 0x03 -#define FSKRegFdevMsb 0x04 -#define FSKRegFdevLsb 0x05 -#define RegFrfMsb 0x06 // common -#define RegFrfMid 0x07 // common -#define RegFrfLsb 0x08 // common -#define RegPaConfig 0x09 // common -#define RegPaRamp 0x0A // common -#define RegOcp 0x0B // common -#define RegLna 0x0C // common -#define FSKRegRxConfig 0x0D -#define LORARegFifoAddrPtr 0x0D -#define FSKRegRssiConfig 0x0E -#define LORARegFifoTxBaseAddr 0x0E -#define FSKRegRssiCollision 0x0F -#define LORARegFifoRxBaseAddr 0x0F -#define FSKRegRssiThresh 0x10 -#define LORARegFifoRxCurrentAddr 0x10 -#define FSKRegRssiValue 0x11 -#define LORARegIrqFlagsMask 0x11 -#define FSKRegRxBw 0x12 -#define LORARegIrqFlags 0x12 -#define FSKRegAfcBw 0x13 -#define LORARegRxNbBytes 0x13 -#define FSKRegOokPeak 0x14 -#define LORARegRxHeaderCntValueMsb 0x14 -#define FSKRegOokFix 0x15 -#define LORARegRxHeaderCntValueLsb 0x15 -#define FSKRegOokAvg 0x16 -#define LORARegRxPacketCntValueMsb 0x16 -#define LORARegRxpacketCntValueLsb 0x17 -#define LORARegModemStat 0x18 -#define LORARegPktSnrValue 0x19 -#define FSKRegAfcFei 0x1A -#define LORARegPktRssiValue 0x1A -#define FSKRegAfcMsb 0x1B -#define LORARegRssiValue 0x1B -#define FSKRegAfcLsb 0x1C -#define LORARegHopChannel 0x1C -#define FSKRegFeiMsb 0x1D -#define LORARegModemConfig1 0x1D -#define FSKRegFeiLsb 0x1E -#define LORARegModemConfig2 0x1E -#define FSKRegPreambleDetect 0x1F -#define LORARegSymbTimeoutLsb 0x1F -#define FSKRegRxTimeout1 0x20 -#define LORARegPreambleMsb 0x20 -#define FSKRegRxTimeout2 0x21 -#define LORARegPreambleLsb 0x21 -#define FSKRegRxTimeout3 0x22 -#define LORARegPayloadLength 0x22 -#define FSKRegRxDelay 0x23 -#define LORARegPayloadMaxLength 0x23 -#define FSKRegOsc 0x24 -#define LORARegHopPeriod 0x24 -#define FSKRegPreambleMsb 0x25 -#define LORARegFifoRxByteAddr 0x25 -#define LORARegModemConfig3 0x26 -#define FSKRegPreambleLsb 0x26 -#define FSKRegSyncConfig 0x27 -#define LORARegFeiMsb 0x28 -#define FSKRegSyncValue1 0x28 -#define LORAFeiMib 0x29 -#define FSKRegSyncValue2 0x29 -#define LORARegFeiLsb 0x2A -#define FSKRegSyncValue3 0x2A -#define FSKRegSyncValue4 0x2B -#define LORARegRssiWideband 0x2C -#define FSKRegSyncValue5 0x2C -#define FSKRegSyncValue6 0x2D -#define FSKRegSyncValue7 0x2E -#define FSKRegSyncValue8 0x2F -#define FSKRegPacketConfig1 0x30 -#define FSKRegPacketConfig2 0x31 -#define LORARegDetectOptimize 0x31 -#define FSKRegPayloadLength 0x32 -#define FSKRegNodeAdrs 0x33 -#define LORARegInvertIQ 0x33 -#define FSKRegBroadcastAdrs 0x34 -#define FSKRegFifoThresh 0x35 -#define FSKRegSeqConfig1 0x36 -#define FSKRegSeqConfig2 0x37 -#define LORARegDetectionThreshold 0x37 -#define FSKRegTimerResol 0x38 -#define FSKRegTimer1Coef 0x39 -#define LORARegSyncWord 0x39 -#define FSKRegTimer2Coef 0x3A -#define FSKRegImageCal 0x3B -#define FSKRegTemp 0x3C -#define FSKRegLowBat 0x3D -#define FSKRegIrqFlags1 0x3E -#define FSKRegIrqFlags2 0x3F -#define RegDioMapping1 0x40 // common -#define RegDioMapping2 0x41 // common -#define RegVersion 0x42 // common -// #define RegAgcRef 0x43 // common -// #define RegAgcThresh1 0x44 // common -// #define RegAgcThresh2 0x45 // common -// #define RegAgcThresh3 0x46 // common -// #define RegPllHop 0x4B // common -// #define RegTcxo 0x58 // common -#ifdef CFG_sx1276_radio - #define RegPaDac 0x4D // common -#else - #define RegPaDac 0x5A // common -#endif -// #define RegPll 0x5C // common -// #define RegPllLowPn 0x5E // common -// #define RegFormerTemp 0x6C // common -// #define RegBitRateFrac 0x70 // common - -// ---------------------------------------- -// spread factors and mode for RegModemConfig2 -#define SX1272_MC2_FSK 0x00 -#define SX1272_MC2_SF7 0x70 -#define SX1272_MC2_SF8 0x80 -#define SX1272_MC2_SF9 0x90 -#define SX1272_MC2_SF10 0xA0 -#define SX1272_MC2_SF11 0xB0 -#define SX1272_MC2_SF12 0xC0 -// bandwidth for RegModemConfig1 -#define SX1272_MC1_BW_125 0x00 -#define SX1272_MC1_BW_250 0x40 -#define SX1272_MC1_BW_500 0x80 -// coding rate for RegModemConfig1 -#define SX1272_MC1_CR_4_5 0x08 -#define SX1272_MC1_CR_4_6 0x10 -#define SX1272_MC1_CR_4_7 0x18 -#define SX1272_MC1_CR_4_8 0x20 -#define SX1272_MC1_IMPLICIT_HEADER_MODE_ON 0x04 // required for receive -#define SX1272_MC1_RX_PAYLOAD_CRCON 0x02 -#define SX1272_MC1_LOW_DATA_RATE_OPTIMIZE 0x01 // mandated for SF11 and SF12 -// transmit power configuration for RegPaConfig -#define SX1272_PAC_PA_SELECT_PA_BOOST 0x80 -#define SX1272_PAC_PA_SELECT_RFIO_PIN 0x00 - - -// sx1276 RegModemConfig1 -#define SX1276_MC1_BW_125 0x70 -#define SX1276_MC1_BW_250 0x80 -#define SX1276_MC1_BW_500 0x90 -#define SX1276_MC1_CR_4_5 0x02 -#define SX1276_MC1_CR_4_6 0x04 -#define SX1276_MC1_CR_4_7 0x06 -#define SX1276_MC1_CR_4_8 0x08 - -#define SX1276_MC1_IMPLICIT_HEADER_MODE_ON 0x01 - -// sx1276 RegModemConfig2 -#define SX1276_MC2_RX_PAYLOAD_CRCON 0x04 - -// sx1276 RegModemConfig3 -#define SX1276_MC3_LOW_DATA_RATE_OPTIMIZE 0x08 -#define SX1276_MC3_AGCAUTO 0x04 - -// preamble for lora networks (nibbles swapped) -#define LORA_MAC_PREAMBLE 0x34 - -#define RXLORA_RXMODE_RSSI_REG_MODEM_CONFIG1 0x0A -#ifdef CFG_sx1276_radio -#define RXLORA_RXMODE_RSSI_REG_MODEM_CONFIG2 0x70 -#elif CFG_sx1272_radio -#define RXLORA_RXMODE_RSSI_REG_MODEM_CONFIG2 0x74 -#endif - - - -// ---------------------------------------- -// Constants for radio registers -#define OPMODE_LORA 0x80 -#define OPMODE_MASK 0x07 -#define OPMODE_SLEEP 0x00 -#define OPMODE_STANDBY 0x01 -#define OPMODE_FSTX 0x02 -#define OPMODE_TX 0x03 -#define OPMODE_FSRX 0x04 -#define OPMODE_RX 0x05 -#define OPMODE_RX_SINGLE 0x06 -#define OPMODE_CAD 0x07 - -// ---------------------------------------- -// Bits masking the corresponding IRQs from the radio -#define IRQ_LORA_RXTOUT_MASK 0x80 -#define IRQ_LORA_RXDONE_MASK 0x40 -#define IRQ_LORA_CRCERR_MASK 0x20 -#define IRQ_LORA_HEADER_MASK 0x10 -#define IRQ_LORA_TXDONE_MASK 0x08 -#define IRQ_LORA_CDDONE_MASK 0x04 -#define IRQ_LORA_FHSSCH_MASK 0x02 -#define IRQ_LORA_CDDETD_MASK 0x01 - -#define IRQ_FSK1_MODEREADY_MASK 0x80 -#define IRQ_FSK1_RXREADY_MASK 0x40 -#define IRQ_FSK1_TXREADY_MASK 0x20 -#define IRQ_FSK1_PLLLOCK_MASK 0x10 -#define IRQ_FSK1_RSSI_MASK 0x08 -#define IRQ_FSK1_TIMEOUT_MASK 0x04 -#define IRQ_FSK1_PREAMBLEDETECT_MASK 0x02 -#define IRQ_FSK1_SYNCADDRESSMATCH_MASK 0x01 -#define IRQ_FSK2_FIFOFULL_MASK 0x80 -#define IRQ_FSK2_FIFOEMPTY_MASK 0x40 -#define IRQ_FSK2_FIFOLEVEL_MASK 0x20 -#define IRQ_FSK2_FIFOOVERRUN_MASK 0x10 -#define IRQ_FSK2_PACKETSENT_MASK 0x08 -#define IRQ_FSK2_PAYLOADREADY_MASK 0x04 -#define IRQ_FSK2_CRCOK_MASK 0x02 -#define IRQ_FSK2_LOWBAT_MASK 0x01 - -// ---------------------------------------- -// DIO function mappings D0D1D2D3 -#define MAP_DIO0_LORA_RXDONE 0x00 // 00------ -#define MAP_DIO0_LORA_TXDONE 0x40 // 01------ -#define MAP_DIO1_LORA_RXTOUT 0x00 // --00---- -#define MAP_DIO1_LORA_NOP 0x30 // --11---- -#define MAP_DIO2_LORA_NOP 0xC0 // ----11-- - -#define MAP_DIO0_FSK_READY 0x00 // 00------ (packet sent / payload ready) -#define MAP_DIO1_FSK_NOP 0x30 // --11---- -#define MAP_DIO2_FSK_TXNOP 0x04 // ----01-- -#define MAP_DIO2_FSK_TIMEOUT 0x08 // ----10-- - - -// FSK IMAGECAL defines -#define RF_IMAGECAL_AUTOIMAGECAL_MASK 0x7F -#define RF_IMAGECAL_AUTOIMAGECAL_ON 0x80 -#define RF_IMAGECAL_AUTOIMAGECAL_OFF 0x00 // Default - -#define RF_IMAGECAL_IMAGECAL_MASK 0xBF -#define RF_IMAGECAL_IMAGECAL_START 0x40 - -#define RF_IMAGECAL_IMAGECAL_RUNNING 0x20 -#define RF_IMAGECAL_IMAGECAL_DONE 0x00 // Default - - -// RADIO STATE -// (initialized by radio_init(), used by radio_rand1()) -static u1_t randbuf[16]; - - -#ifdef CFG_sx1276_radio -#define LNA_RX_GAIN (0x20|0x1) -#elif CFG_sx1272_radio -#define LNA_RX_GAIN (0x20|0x03) -#else -#error Missing CFG_sx1272_radio/CFG_sx1276_radio -#endif - - -static void writeReg (u1_t addr, u1_t data ) { - hal_pin_nss(0); - hal_spi(addr | 0x80); - hal_spi(data); - hal_pin_nss(1); -} - -static u1_t readReg (u1_t addr) { - hal_pin_nss(0); - hal_spi(addr & 0x7F); - u1_t val = hal_spi(0x00); - hal_pin_nss(1); - return val; -} - -static void writeBuf (u1_t addr, xref2u1_t buf, u1_t len) { - hal_pin_nss(0); - hal_spi(addr | 0x80); - for (u1_t i=0; i>16)); - writeReg(RegFrfMid, (u1_t)(frf>> 8)); - writeReg(RegFrfLsb, (u1_t)(frf>> 0)); -} - - - -static void configPower () { -#ifdef CFG_sx1276_radio - // no boost used for now - s1_t pw = (s1_t)LMIC.txpow; - if(pw > 15) { - pw = 15; - } else if(pw < 2) { - pw = 2; - } - // check board type for BOOST pin - writeReg(RegPaConfig, (u1_t)(0x80|(pw&0xf))); // sets PA_BOOST pin (original lmic) - //writeReg(RegPaConfig, (u1_t)(pw&0xf)); // sets RFO pin (patched lmic) - writeReg(RegPaDac, readReg(RegPaDac)|0x4); - -#elif CFG_sx1272_radio - // set PA config (2-17 dBm using PA_BOOST) - s1_t pw = (s1_t)LMIC.txpow; - if(pw > 17) { - pw = 17; - } else if(pw < 2) { - pw = 2; - } - writeReg(RegPaConfig, (u1_t)(0x80|(pw-2))); -#else -#error Missing CFG_sx1272_radio/CFG_sx1276_radio -#endif /* CFG_sx1272_radio */ -} - -static void txfsk () { - // select FSK modem (from sleep mode) - writeReg(RegOpMode, 0x10); // FSK, BT=0.5 - ASSERT(readReg(RegOpMode) == 0x10); - // enter standby mode (required for FIFO loading)) - opmode(OPMODE_STANDBY); - // set bitrate - writeReg(FSKRegBitrateMsb, 0x02); // 50kbps - writeReg(FSKRegBitrateLsb, 0x80); - // set frequency deviation - writeReg(FSKRegFdevMsb, 0x01); // +/- 25kHz - writeReg(FSKRegFdevLsb, 0x99); - // frame and packet handler settings - writeReg(FSKRegPreambleMsb, 0x00); - writeReg(FSKRegPreambleLsb, 0x05); - writeReg(FSKRegSyncConfig, 0x12); - writeReg(FSKRegPacketConfig1, 0xD0); - writeReg(FSKRegPacketConfig2, 0x40); - writeReg(FSKRegSyncValue1, 0xC1); - writeReg(FSKRegSyncValue2, 0x94); - writeReg(FSKRegSyncValue3, 0xC1); - // configure frequency - configChannel(); - // configure output power - configPower(); - - // set the IRQ mapping DIO0=PacketSent DIO1=NOP DIO2=NOP - writeReg(RegDioMapping1, MAP_DIO0_FSK_READY|MAP_DIO1_FSK_NOP|MAP_DIO2_FSK_TXNOP); - - // initialize the payload size and address pointers - writeReg(FSKRegPayloadLength, LMIC.dataLen+1); // (insert length byte into payload)) - - // download length byte and buffer to the radio FIFO - writeReg(RegFifo, LMIC.dataLen); - writeBuf(RegFifo, LMIC.frame, LMIC.dataLen); - - // enable antenna switch for TX - hal_pin_rxtx(1); - - // now we actually start the transmission - opmode(OPMODE_TX); -} - -static void txlora () { - // select LoRa modem (from sleep mode) - //writeReg(RegOpMode, OPMODE_LORA); - opmodeLora(); - ASSERT((readReg(RegOpMode) & OPMODE_LORA) != 0); - - // enter standby mode (required for FIFO loading)) - opmode(OPMODE_STANDBY); - // configure LoRa modem (cfg1, cfg2) - configLoraModem(); - // configure frequency - configChannel(); - // configure output power - writeReg(RegPaRamp, (readReg(RegPaRamp) & 0xF0) | 0x08); // set PA ramp-up time 50 uSec - configPower(); - // set sync word - writeReg(LORARegSyncWord, LORA_MAC_PREAMBLE); - - // set the IRQ mapping DIO0=TxDone DIO1=NOP DIO2=NOP - writeReg(RegDioMapping1, MAP_DIO0_LORA_TXDONE|MAP_DIO1_LORA_NOP|MAP_DIO2_LORA_NOP); - // clear all radio IRQ flags - writeReg(LORARegIrqFlags, 0xFF); - // mask all IRQs but TxDone - writeReg(LORARegIrqFlagsMask, ~IRQ_LORA_TXDONE_MASK); - - // initialize the payload size and address pointers - writeReg(LORARegFifoTxBaseAddr, 0x00); - writeReg(LORARegFifoAddrPtr, 0x00); - writeReg(LORARegPayloadLength, LMIC.dataLen); - - // download buffer to the radio FIFO - writeBuf(RegFifo, LMIC.frame, LMIC.dataLen); - - // enable antenna switch for TX - hal_pin_rxtx(1); - - // now we actually start the transmission - opmode(OPMODE_TX); - -#if LMIC_DEBUG_LEVEL > 0 - u1_t sf = getSf(LMIC.rps) + 6; // 1 == SF7 - u1_t bw = getBw(LMIC.rps); - u1_t cr = getCr(LMIC.rps); - lmic_printf("%lu: TXMODE, freq=%lu, len=%d, SF=%d, BW=%d, CR=4/%d, IH=%d\n", - os_getTime(), LMIC.freq, LMIC.dataLen, sf, - bw == BW125 ? 125 : (bw == BW250 ? 250 : 500), - cr == CR_4_5 ? 5 : (cr == CR_4_6 ? 6 : (cr == CR_4_7 ? 7 : 8)), - getIh(LMIC.rps) - ); -#endif -} - -// start transmitter (buf=LMIC.frame, len=LMIC.dataLen) -static void starttx () { - ASSERT( (readReg(RegOpMode) & OPMODE_MASK) == OPMODE_SLEEP ); - if(getSf(LMIC.rps) == FSK) { // FSK modem - txfsk(); - } else { // LoRa modem - txlora(); - } - // the radio will go back to STANDBY mode as soon as the TX is finished - // the corresponding IRQ will inform us about completion. -} - -enum { RXMODE_SINGLE, RXMODE_SCAN, RXMODE_RSSI }; - -static CONST_TABLE(u1_t, rxlorairqmask)[] = { - [RXMODE_SINGLE] = IRQ_LORA_RXDONE_MASK|IRQ_LORA_RXTOUT_MASK, - [RXMODE_SCAN] = IRQ_LORA_RXDONE_MASK, - [RXMODE_RSSI] = 0x00, -}; - -// start LoRa receiver (time=LMIC.rxtime, timeout=LMIC.rxsyms, result=LMIC.frame[LMIC.dataLen]) -static void rxlora (u1_t rxmode) { - // select LoRa modem (from sleep mode) - opmodeLora(); - ASSERT((readReg(RegOpMode) & OPMODE_LORA) != 0); - // enter standby mode (warm up)) - opmode(OPMODE_STANDBY); - // don't use MAC settings at startup - if(rxmode == RXMODE_RSSI) { // use fixed settings for rssi scan - writeReg(LORARegModemConfig1, RXLORA_RXMODE_RSSI_REG_MODEM_CONFIG1); - writeReg(LORARegModemConfig2, RXLORA_RXMODE_RSSI_REG_MODEM_CONFIG2); - } else { // single or continuous rx mode - // configure LoRa modem (cfg1, cfg2) - configLoraModem(); - // configure frequency - configChannel(); - } - // set LNA gain - writeReg(RegLna, LNA_RX_GAIN); - // set max payload size - writeReg(LORARegPayloadMaxLength, 64); -#if !defined(DISABLE_INVERT_IQ_ON_RX) - // use inverted I/Q signal (prevent mote-to-mote communication) - writeReg(LORARegInvertIQ, readReg(LORARegInvertIQ)|(1<<6)); -#endif - // set symbol timeout (for single rx) - writeReg(LORARegSymbTimeoutLsb, LMIC.rxsyms); - // set sync word - writeReg(LORARegSyncWord, LORA_MAC_PREAMBLE); - - // configure DIO mapping DIO0=RxDone DIO1=RxTout DIO2=NOP - writeReg(RegDioMapping1, MAP_DIO0_LORA_RXDONE|MAP_DIO1_LORA_RXTOUT|MAP_DIO2_LORA_NOP); - // clear all radio IRQ flags - writeReg(LORARegIrqFlags, 0xFF); - // enable required radio IRQs - writeReg(LORARegIrqFlagsMask, ~TABLE_GET_U1(rxlorairqmask, rxmode)); - - // enable antenna switch for RX - hal_pin_rxtx(0); - - // now instruct the radio to receive - if (rxmode == RXMODE_SINGLE) { // single rx - hal_waitUntil(LMIC.rxtime); // busy wait until exact rx time - opmode(OPMODE_RX_SINGLE); - } else { // continous rx (scan or rssi) - opmode(OPMODE_RX); - } - -#if LMIC_DEBUG_LEVEL > 0 - if (rxmode == RXMODE_RSSI) { - lmic_printf("RXMODE_RSSI\n"); - } else { - u1_t sf = getSf(LMIC.rps) + 6; // 1 == SF7 - u1_t bw = getBw(LMIC.rps); - u1_t cr = getCr(LMIC.rps); - lmic_printf("%lu: %s, freq=%lu, SF=%d, BW=%d, CR=4/%d, IH=%d\n", - os_getTime(), - rxmode == RXMODE_SINGLE ? "RXMODE_SINGLE" : (rxmode == RXMODE_SCAN ? "RXMODE_SCAN" : "UNKNOWN_RX"), - LMIC.freq, sf, - bw == BW125 ? 125 : (bw == BW250 ? 250 : 500), - cr == CR_4_5 ? 5 : (cr == CR_4_6 ? 6 : (cr == CR_4_7 ? 7 : 8)), - getIh(LMIC.rps) - ); - } -#endif -} - -static void rxfsk (u1_t rxmode) { - // only single rx (no continuous scanning, no noise sampling) - ASSERT( rxmode == RXMODE_SINGLE ); - // select FSK modem (from sleep mode) - //writeReg(RegOpMode, 0x00); // (not LoRa) - opmodeFSK(); - ASSERT((readReg(RegOpMode) & OPMODE_LORA) == 0); - // enter standby mode (warm up)) - opmode(OPMODE_STANDBY); - // configure frequency - configChannel(); - // set LNA gain - //writeReg(RegLna, 0x20|0x03); // max gain, boost enable - writeReg(RegLna, LNA_RX_GAIN); - // configure receiver - writeReg(FSKRegRxConfig, 0x1E); // AFC auto, AGC, trigger on preamble?!? - // set receiver bandwidth - writeReg(FSKRegRxBw, 0x0B); // 50kHz SSb - // set AFC bandwidth - writeReg(FSKRegAfcBw, 0x12); // 83.3kHz SSB - // set preamble detection - writeReg(FSKRegPreambleDetect, 0xAA); // enable, 2 bytes, 10 chip errors - // set sync config - writeReg(FSKRegSyncConfig, 0x12); // no auto restart, preamble 0xAA, enable, fill FIFO, 3 bytes sync - // set packet config - writeReg(FSKRegPacketConfig1, 0xD8); // var-length, whitening, crc, no auto-clear, no adr filter - writeReg(FSKRegPacketConfig2, 0x40); // packet mode - // set sync value - writeReg(FSKRegSyncValue1, 0xC1); - writeReg(FSKRegSyncValue2, 0x94); - writeReg(FSKRegSyncValue3, 0xC1); - // set preamble timeout - writeReg(FSKRegRxTimeout2, 0xFF);//(LMIC.rxsyms+1)/2); - // set bitrate - writeReg(FSKRegBitrateMsb, 0x02); // 50kbps - writeReg(FSKRegBitrateLsb, 0x80); - // set frequency deviation - writeReg(FSKRegFdevMsb, 0x01); // +/- 25kHz - writeReg(FSKRegFdevLsb, 0x99); - - // configure DIO mapping DIO0=PayloadReady DIO1=NOP DIO2=TimeOut - writeReg(RegDioMapping1, MAP_DIO0_FSK_READY|MAP_DIO1_FSK_NOP|MAP_DIO2_FSK_TIMEOUT); - - // enable antenna switch for RX - hal_pin_rxtx(0); - - // now instruct the radio to receive - hal_waitUntil(LMIC.rxtime); // busy wait until exact rx time - opmode(OPMODE_RX); // no single rx mode available in FSK -} - -static void startrx (u1_t rxmode) { - ASSERT( (readReg(RegOpMode) & OPMODE_MASK) == OPMODE_SLEEP ); - if(getSf(LMIC.rps) == FSK) { // FSK modem - rxfsk(rxmode); - } else { // LoRa modem - rxlora(rxmode); - } - // the radio will go back to STANDBY mode as soon as the RX is finished - // or timed out, and the corresponding IRQ will inform us about completion. -} - -// get random seed from wideband noise rssi -void radio_init () { - hal_disableIRQs(); - - // manually reset radio -#ifdef CFG_sx1276_radio - hal_pin_rst(0); // drive RST pin low -#else - hal_pin_rst(1); // drive RST pin high -#endif - hal_waitUntil(os_getTime()+ms2osticks(1)); // wait >100us - hal_pin_rst(2); // configure RST pin floating! - hal_waitUntil(os_getTime()+ms2osticks(5)); // wait 5ms - - opmode(OPMODE_SLEEP); - - // some sanity checks, e.g., read version number - u1_t v = readReg(RegVersion); -#ifdef CFG_sx1276_radio - ASSERT(v == 0x12 ); -#elif CFG_sx1272_radio - ASSERT(v == 0x22); -#else -#error Missing CFG_sx1272_radio/CFG_sx1276_radio -#endif - // seed 15-byte randomness via noise rssi - rxlora(RXMODE_RSSI); - while( (readReg(RegOpMode) & OPMODE_MASK) != OPMODE_RX ); // continuous rx - for(int i=1; i<16; i++) { - for(int j=0; j<8; j++) { - u1_t b; // wait for two non-identical subsequent least-significant bits - while( (b = readReg(LORARegRssiWideband) & 0x01) == (readReg(LORARegRssiWideband) & 0x01) ); - randbuf[i] = (randbuf[i] << 1) | b; - } - } - randbuf[0] = 16; // set initial index - -#ifdef CFG_sx1276mb1_board - // chain calibration - writeReg(RegPaConfig, 0); - - // Launch Rx chain calibration for LF band - writeReg(FSKRegImageCal, (readReg(FSKRegImageCal) & RF_IMAGECAL_IMAGECAL_MASK)|RF_IMAGECAL_IMAGECAL_START); - while((readReg(FSKRegImageCal)&RF_IMAGECAL_IMAGECAL_RUNNING) == RF_IMAGECAL_IMAGECAL_RUNNING){ ; } - - // Sets a Frequency in HF band - u4_t frf = 868000000; - writeReg(RegFrfMsb, (u1_t)(frf>>16)); - writeReg(RegFrfMid, (u1_t)(frf>> 8)); - writeReg(RegFrfLsb, (u1_t)(frf>> 0)); - - // Launch Rx chain calibration for HF band - writeReg(FSKRegImageCal, (readReg(FSKRegImageCal) & RF_IMAGECAL_IMAGECAL_MASK)|RF_IMAGECAL_IMAGECAL_START); - while((readReg(FSKRegImageCal) & RF_IMAGECAL_IMAGECAL_RUNNING) == RF_IMAGECAL_IMAGECAL_RUNNING) { ; } -#endif /* CFG_sx1276mb1_board */ - - opmode(OPMODE_SLEEP); - - hal_enableIRQs(); -} - -// return next random byte derived from seed buffer -// (buf[0] holds index of next byte to be returned) -u1_t radio_rand1 () { - u1_t i = randbuf[0]; - ASSERT( i != 0 ); - if( i==16 ) { - os_aes(AES_ENC, randbuf, 16); // encrypt seed with any key - i = 0; - } - u1_t v = randbuf[i++]; - randbuf[0] = i; - return v; -} - -u1_t radio_rssi () { - hal_disableIRQs(); - u1_t r = readReg(LORARegRssiValue); - hal_enableIRQs(); - return r; -} - -static CONST_TABLE(u2_t, LORA_RXDONE_FIXUP)[] = { - [FSK] = us2osticks(0), // ( 0 ticks) - [SF7] = us2osticks(0), // ( 0 ticks) - [SF8] = us2osticks(1648), // ( 54 ticks) - [SF9] = us2osticks(3265), // ( 107 ticks) - [SF10] = us2osticks(7049), // ( 231 ticks) - [SF11] = us2osticks(13641), // ( 447 ticks) - [SF12] = us2osticks(31189), // (1022 ticks) -}; - -// called by hal ext IRQ handler -// (radio goes to stanby mode after tx/rx operations) -void radio_irq_handler (u1_t dio) { - ostime_t now = os_getTime(); - if( (readReg(RegOpMode) & OPMODE_LORA) != 0) { // LORA modem - u1_t flags = readReg(LORARegIrqFlags); -#if LMIC_DEBUG_LEVEL > 1 - lmic_printf("%lu: irq: dio: 0x%x flags: 0x%x\n", now, dio, flags); -#endif - if( flags & IRQ_LORA_TXDONE_MASK ) { - // save exact tx time - LMIC.txend = now - us2osticks(43); // TXDONE FIXUP - } else if( flags & IRQ_LORA_RXDONE_MASK ) { - // save exact rx time - if(getBw(LMIC.rps) == BW125) { - now -= TABLE_GET_U2(LORA_RXDONE_FIXUP, getSf(LMIC.rps)); - } - LMIC.rxtime = now; - // read the PDU and inform the MAC that we received something - LMIC.dataLen = (readReg(LORARegModemConfig1) & SX1272_MC1_IMPLICIT_HEADER_MODE_ON) ? - readReg(LORARegPayloadLength) : readReg(LORARegRxNbBytes); - // set FIFO read address pointer - writeReg(LORARegFifoAddrPtr, readReg(LORARegFifoRxCurrentAddr)); - // now read the FIFO - readBuf(RegFifo, LMIC.frame, LMIC.dataLen); - // read rx quality parameters - //LMIC.snr = readReg(LORARegPktSnrValue); // SNR [dB] * 4 - LMIC.snr = ((s1_t)readReg(LORARegPktSnrValue)) / 4; - //LMIC.rssi = readReg(LORARegPktRssiValue) - 125 + 64; // RSSI [dBm] (-196...+63) - LMIC.rssi = readReg(LORARegPktRssiValue) - 157; // RFI_HF for 868 and 915MHZ band - if (LMIC.snr < 0) - LMIC.rssi += LMIC.snr; - } else if( flags & IRQ_LORA_RXTOUT_MASK ) { - // indicate timeout - LMIC.dataLen = 0; - } - // mask all radio IRQs - writeReg(LORARegIrqFlagsMask, 0xFF); - // clear radio IRQ flags - writeReg(LORARegIrqFlags, 0xFF); - } else { // FSK modem - u1_t flags1 = readReg(FSKRegIrqFlags1); - u1_t flags2 = readReg(FSKRegIrqFlags2); - if( flags2 & IRQ_FSK2_PACKETSENT_MASK ) { - // save exact tx time - LMIC.txend = now; - } else if( flags2 & IRQ_FSK2_PAYLOADREADY_MASK ) { - // save exact rx time - LMIC.rxtime = now; - // read the PDU and inform the MAC that we received something - LMIC.dataLen = readReg(FSKRegPayloadLength); - // now read the FIFO - readBuf(RegFifo, LMIC.frame, LMIC.dataLen); - // read rx quality parameters - LMIC.snr = 0; // determine snr - LMIC.rssi = 0; // determine rssi - } else if( flags1 & IRQ_FSK1_TIMEOUT_MASK ) { - // indicate timeout - LMIC.dataLen = 0; - } else { - ASSERT(0); - } - } - // go from stanby to sleep - opmode(OPMODE_SLEEP); - // run os job (use preset func ptr) - os_setCallback(&LMIC.osjob, LMIC.osjob.func); -} - -void os_radio (u1_t mode) { - hal_disableIRQs(); - switch (mode) { - case RADIO_RST: - // put radio to sleep - opmode(OPMODE_SLEEP); - break; - - case RADIO_TX: - // transmit frame now - starttx(); // buf=LMIC.frame, len=LMIC.dataLen - break; - - case RADIO_RX: - // receive frame now (exactly at rxtime) - startrx(RXMODE_SINGLE); // buf=LMIC.frame, time=LMIC.rxtime, timeout=LMIC.rxsyms - break; - - case RADIO_RXON: - // start scanning for beacon now - startrx(RXMODE_SCAN); // buf=LMIC.frame - break; - } - hal_enableIRQs(); -} diff --git a/platformio.ini b/platformio.ini index e23b7612..38dcc1ce 100644 --- a/platformio.ini +++ b/platformio.ini @@ -6,28 +6,30 @@ ; ---> SELECT TARGET PLATFORM HERE! <--- [platformio] -env_default = generic +;env_default = generic ;env_default = ebox +;env_default = eboxtube ;env_default = heltec +;env_default = heltecv2 ;env_default = ttgov1 ;env_default = ttgov2 ;env_default = ttgov21old ;env_default = ttgov21new ;env_default = ttgobeam -;env_default = lopy +env_default = lopy ;env_default = lopy4 ;env_default = fipy ;env_default = lolin32litelora ;env_default = lolin32lora ;env_default = lolin32lite ;env_default = octopus32 -;env_default = ebox, heltec, ttgobeam, lopy4, lopy, ttgov21old, ttgov21new +;env_default = ebox, eboxtube, heltec, ttgobeam, lopy4, lopy, ttgov21old, ttgov21new ; description = Paxcounter is a proof-of-concept ESP32 device for metering passenger flows in realtime. It counts how many mobile devices are around. [common] ; for release_version use max. 10 chars total, use any decimal format like "a.b.c" -release_version = 1.6.1 +release_version = 1.6.5 ; DEBUG LEVEL: For production run set to 0, otherwise device will leak RAM while running! ; 0=None, 1=Error, 2=Warn, 3=Info, 4=Debug, 5=Verbose debug_level = 0 @@ -41,6 +43,8 @@ board_build.partitions = min_spiffs.csv monitor_speed = 115200 lib_deps_all = ArduinoJson@^5.13.1 +lib_deps_lora = + MCCI LoRaWAN LMIC library@^2.2.2 lib_deps_display = U8g2@>=2.23.16 lib_deps_rgbled = @@ -49,11 +53,10 @@ lib_deps_gps = TinyGPSPlus@>=1.0.2 Time@>=1.5 build_flags = -; override lora settings from LMiC library in lmic/config.h and use main.h instead - -D_lmic_config_h_ - -include "src/paxcounter.conf" -include "src/hal/${PIOENV}.h" + -include "src/paxcounter.conf" -w + '-DARDUINO_LMIC_PROJECT_CONFIG_H=../../../src/lmic_config.h' '-DCORE_DEBUG_LEVEL=${common.debug_level}' '-DBINTRAY_PACKAGE="${PIOENV}"' '-DPROGVERSION="${common.release_version}"' @@ -61,11 +64,27 @@ build_flags = [env:ebox] platform = ${common.platform_espressif32} framework = arduino -board = esp32dev +board = heltec_wifi_lora_32 board_build.partitions = ${common.board_build.partitions} upload_speed = 115200 lib_deps = ${common.lib_deps_all} + ${common.lib_deps_lora} +build_flags = + ${common.build_flags} +upload_protocol = ${common.upload_protocol} +extra_scripts = ${common.extra_scripts} +monitor_speed = ${common.monitor_speed} + +[env:eboxtube] +platform = ${common.platform_espressif32} +framework = arduino +board = heltec_wifi_lora_32 +board_build.partitions = ${common.board_build.partitions} +upload_speed = 115200 +lib_deps = + ${common.lib_deps_all} + ${common.lib_deps_lora} build_flags = ${common.build_flags} upload_protocol = ${common.upload_protocol} @@ -80,6 +99,23 @@ board_build.partitions = ${common.board_build.partitions} upload_speed = 921600 lib_deps = ${common.lib_deps_all} + ${common.lib_deps_lora} + ${common.lib_deps_display} +build_flags = + ${common.build_flags} +upload_protocol = ${common.upload_protocol} +extra_scripts = ${common.extra_scripts} +monitor_speed = ${common.monitor_speed} + +[env:heltecv2] +platform = ${common.platform_espressif32} +framework = arduino +board = heltec_wifi_lora_32 +board_build.partitions = ${common.board_build.partitions} +upload_speed = 921600 +lib_deps = + ${common.lib_deps_all} + ${common.lib_deps_lora} ${common.lib_deps_display} build_flags = ${common.build_flags} @@ -90,11 +126,12 @@ monitor_speed = ${common.monitor_speed} [env:ttgov1] platform = ${common.platform_espressif32} framework = arduino -board = esp32dev +board = ttgo-lora32-v1 board_build.partitions = ${common.board_build.partitions} upload_speed = 115200 lib_deps = ${common.lib_deps_all} + ${common.lib_deps_lora} ${common.lib_deps_display} build_flags = ${common.build_flags} @@ -105,11 +142,12 @@ monitor_speed = ${common.monitor_speed} [env:ttgov2] platform = ${common.platform_espressif32} framework = arduino -board = esp32dev +board = ttgo-lora32-v1 board_build.partitions = ${common.board_build.partitions} upload_speed = 921600 lib_deps = ${common.lib_deps_all} + ${common.lib_deps_lora} ${common.lib_deps_display} build_flags = ${common.build_flags} @@ -120,11 +158,12 @@ monitor_speed = ${common.monitor_speed} [env:ttgov21old] platform = ${common.platform_espressif32} framework = arduino -board = esp32dev +board = heltec_wifi_lora_32 board_build.partitions = ${common.board_build.partitions} upload_speed = 921600 lib_deps = ${common.lib_deps_all} + ${common.lib_deps_lora} ${common.lib_deps_display} build_flags = ${common.build_flags} @@ -135,11 +174,12 @@ monitor_speed = ${common.monitor_speed} [env:ttgov21new] platform = ${common.platform_espressif32} framework = arduino -board = esp32dev +board = heltec_wifi_lora_32 board_build.partitions = ${common.board_build.partitions} upload_speed = 921600 lib_deps = ${common.lib_deps_all} + ${common.lib_deps_lora} ${common.lib_deps_display} build_flags = ${common.build_flags} @@ -150,11 +190,12 @@ monitor_speed = ${common.monitor_speed} [env:ttgobeam] platform = ${common.platform_espressif32} framework = arduino -board = esp32dev +board = heltec_wifi_lora_32 board_build.partitions = ${common.board_build.partitions} upload_speed = 921600 lib_deps = ${common.lib_deps_all} + ${common.lib_deps_lora} ${common.lib_deps_gps} build_flags = ${common.build_flags} @@ -166,11 +207,12 @@ monitor_speed = ${common.monitor_speed} [env:fipy] platform = ${common.platform_espressif32} framework = arduino -board = esp32dev +board = heltec_wifi_lora_32 board_build.partitions = ${common.board_build.partitions} upload_speed = 921600 lib_deps = ${common.lib_deps_all} + ${common.lib_deps_lora} ${common.lib_deps_rgbled} build_flags = ${common.build_flags} @@ -181,11 +223,12 @@ monitor_speed = ${common.monitor_speed} [env:lopy] platform = ${common.platform_espressif32} framework = arduino -board = esp32dev +board = heltec_wifi_lora_32 board_build.partitions = ${common.board_build.partitions} upload_speed = 921600 lib_deps = ${common.lib_deps_all} + ${common.lib_deps_lora} ${common.lib_deps_rgbled} ${common.lib_deps_gps} build_flags = @@ -197,11 +240,12 @@ monitor_speed = ${common.monitor_speed} [env:lopy4] platform = ${common.platform_espressif32} framework = arduino -board = esp32dev +board = heltec_wifi_lora_32 board_build.partitions = ${common.board_build.partitions} upload_speed = 921600 lib_deps = ${common.lib_deps_all} + ${common.lib_deps_lora} ${common.lib_deps_rgbled} ${common.lib_deps_gps} build_flags = @@ -219,6 +263,7 @@ board_build.partitions = ${common.board_build.partitions} upload_speed = 921600 lib_deps = ${common.lib_deps_all} + ${common.lib_deps_lora} ${common.lib_deps_rgbled} build_flags = ${common.build_flags} @@ -234,6 +279,7 @@ board_build.partitions = ${common.board_build.partitions} upload_speed = 921600 lib_deps = ${common.lib_deps_all} + ${common.lib_deps_lora} ${common.lib_deps_rgbled} build_flags = ${common.build_flags} @@ -259,11 +305,12 @@ monitor_speed = ${common.monitor_speed} [env:octopus32] platform = ${common.platform_espressif32} framework = arduino -board = esp32dev +board = featheresp32 board_build.partitions = ${common.board_build.partitions} upload_speed = 921600 lib_deps = ${common.lib_deps_all} + ${common.lib_deps_lora} ${common.lib_deps_rgbled} build_flags = ${common.build_flags} @@ -274,11 +321,12 @@ monitor_speed = ${common.monitor_speed} [env:generic] platform = ${common.platform_espressif32} framework = arduino -board = esp32dev +board = heltec_wifi_lora_32 board_build.partitions = ${common.board_build.partitions} upload_speed = 921600 lib_deps = ${common.lib_deps_all} + ${common.lib_deps_lora} ${common.lib_deps_rgbled} ${common.lib_deps_gps} ${common.lib_deps_display} diff --git a/src/display.cpp b/src/display.cpp index 842f0249..5e35f871 100644 --- a/src/display.cpp +++ b/src/display.cpp @@ -4,7 +4,7 @@ #include "globals.h" #include // needed for reading ESP32 chip attributes -HAS_DISPLAY u8x8(OLED_RST, I2C_SCL, I2C_SDA); +HAS_DISPLAY u8x8(MY_OLED_RST, MY_OLED_SCL, MY_OLED_SDA); // helper string for converting LoRa spread factor values #if defined(CFG_eu868) diff --git a/src/gps.cpp b/src/gpsread.cpp similarity index 100% rename from src/gps.cpp rename to src/gpsread.cpp diff --git a/src/hal/ebox.h b/src/hal/ebox.h index 6b8d0016..8e107384 100644 --- a/src/hal/ebox.h +++ b/src/hal/ebox.h @@ -1,21 +1,22 @@ +#ifndef _EBOX_H +#define _EBOX_H + +#include + // Hardware related definitions for ebox ESP32-bit with external connected RFM95 LoRa #define HAS_LORA 1 // comment out if device shall not send data via LoRa #define HAS_SPI 1 // comment out if device shall not send data via SPI #define CFG_sx1276_radio 1 -#define HAS_LED GPIO_NUM_23 // blue LED on board -#define HAS_BUTTON GPIO_NUM_0 // button "PROG" on board +#define HAS_LED (23) // blue LED on board +#define HAS_BUTTON (0) // button "PROG" on board #define DISABLE_BROWNOUT 1 // comment out if you want to keep brownout feature -// re-define pin definitions of pins_arduino.h -#define PIN_SPI_SS GPIO_NUM_18 // ESP32 GPIO18 (Pin18) -- SX1276 NSS (Pin19) SPI Chip Select Input -#define PIN_SPI_MOSI GPIO_NUM_27 // ESP32 GPIO27 (Pin27) -- SX1276 MOSI (Pin18) SPI Data Input -#define PIN_SPI_MISO GPIO_NUM_19 // ESP32 GPIO19 (Pin19) -- SX1276 MISO (Pin17) SPI Data Output -#define PIN_SPI_SCK GPIO_NUM_5 // ESP32 GPIO5 (Pin5) -- SX1276 SCK (Pin16) SPI Clock Input +// Pins for LORA chip reset and interrupt lines +#define RST (14) +#define DIO0 (26) +#define DIO1 (33) +#define DIO2 LMIC_UNUSED_PIN -// non arduino pin definitions -#define RST GPIO_NUM_14 // ESP32 GPIO14 (Pin14) -- SX1276 NRESET (Pin7) Reset Trigger Input -#define DIO0 GPIO_NUM_26 // ESP32 GPIO26 (Pin15) -- SX1276 DIO0 (Pin8) used by LMIC for detecting LoRa RX_Done & TX_Done -#define DIO1 GPIO_NUM_33 // ESP32 GPIO33 (Pin13) -- SX1276 DIO1 (Pin9) used by LMIC for detecting LoRa RX_Timeout -#define DIO2 LMIC_UNUSED_PIN // 32 ESP32 GPIO32 (Pin12) -- SX1276 DIO2 (Pin10) not used by LMIC for LoRa (Timeout for FSK only) \ No newline at end of file +#endif \ No newline at end of file diff --git a/src/hal/eboxtube.h b/src/hal/eboxtube.h index 9c66dbc3..3b9ecaff 100644 --- a/src/hal/eboxtube.h +++ b/src/hal/eboxtube.h @@ -1,22 +1,23 @@ +#ifndef _EBOXTUBE_H +#define _EBOXTUBE_H + +#include + // Hardware related definitions for ebox ESP32-bit with external connected RFM95 LoRa #define HAS_LORA 1 // comment out if device shall not send data via LoRa #define HAS_SPI 1 // comment out if device shall not send data via SPI #define CFG_sx1276_radio 1 -#define HAS_LED GPIO_NUM_22 // Green LED on board -#define HAS_RGB_LED GPIO_NUM_2 // WS2812B RGB LED on board -#define HAS_BUTTON GPIO_NUM_0 // button "FLASH" on board +#define HAS_LED (22) // Green LED on board +#define HAS_RGB_LED (2) // WS2812B RGB LED on board +#define HAS_BUTTON (0) // button "FLASH" on board #define DISABLE_BROWNOUT 1 // comment out if you want to keep brownout feature -// re-define pin definitions of pins_arduino.h -#define PIN_SPI_SS GPIO_NUM_18 // ESP32 GPIO18 (Pin18) -- SX1276 NSS (Pin19) SPI Chip Select Input -#define PIN_SPI_MOSI GPIO_NUM_27 // ESP32 GPIO27 (Pin27) -- SX1276 MOSI (Pin18) SPI Data Input -#define PIN_SPI_MISO GPIO_NUM_19 // ESP32 GPIO19 (Pin19) -- SX1276 MISO (Pin17) SPI Data Output -#define PIN_SPI_SCK GPIO_NUM_5 // ESP32 GPIO5 (Pin5) -- SX1276 SCK (Pin16) SPI Clock Input +// Pins for LORA chip reset and interrupt lines +#define RST (14) +#define DIO0 (26) +#define DIO1 (33) +#define DIO2 (32) -// non arduino pin definitions -#define RST GPIO_NUM_14 // ESP32 GPIO14 (Pin14) -- SX1276 NRESET (Pin7) Reset Trigger Input -#define DIO0 GPIO_NUM_26 // ESP32 GPIO26 (Pin15) -- SX1276 DIO0 (Pin8) used by LMIC for detecting LoRa RX_Done & TX_Done -#define DIO1 GPIO_NUM_33 // ESP32 GPIO33 (Pin13) -- SX1276 DIO1 (Pin9) used by LMIC for detecting LoRa RX_Timeout -#define DIO2 GPIO_NUM_32 // ESP32 GPIO32 (Pin12) -- SX1276 DIO2 (Pin10) not used by LMIC for LoRa (Timeout for FSK only) \ No newline at end of file +#endif \ No newline at end of file diff --git a/src/hal/fipy.h b/src/hal/fipy.h index d5153b98..41c73dc4 100644 --- a/src/hal/fipy.h +++ b/src/hal/fipy.h @@ -1,3 +1,8 @@ +#ifndef _FIPY_H +#define _FIPY_H + +#include + // Hardware related definitions for Pycom FiPy Board #define HAS_LORA 1 // comment out if device shall not send data via LoRa @@ -8,16 +13,14 @@ #define HAS_RGB_LED GPIO_NUM_0 // WS2812B RGB LED on GPIO0 #define BOARD_HAS_PSRAM // use extra 4MB extern RAM -// Hardware pin definitions for Pycom FiPy board -#define PIN_SPI_SS GPIO_NUM_18 -#define PIN_SPI_MOSI GPIO_NUM_27 -#define PIN_SPI_MISO GPIO_NUM_19 -#define PIN_SPI_SCK GPIO_NUM_5 -#define RST LMIC_UNUSED_PIN -#define DIO0 GPIO_NUM_23 // LoRa IRQ -#define DIO1 GPIO_NUM_23 // workaround -#define DIO2 LMIC_UNUSED_PIN +// Pins for LORA chip reset and interrupt lines +#define RST LMIC_UNUSED_PIN +#define DIO0 (23) // LoRa IRQ +#define DIO1 (23) // Pin tied via diode to DIO0 +#define DIO2 LMIC_UNUSED_PIN // select WIFI antenna (internal = onboard / external = u.fl socket) #define HAS_ANTENNA_SWITCH GPIO_NUM_21 // pin for switching wifi antenna #define WIFI_ANTENNA 0 // 0 = internal, 1 = external + +#endif diff --git a/src/hal/generic.h b/src/hal/generic.h index f25a8219..b6344f38 100644 --- a/src/hal/generic.h +++ b/src/hal/generic.h @@ -1,3 +1,8 @@ +#ifndef _GENERIC_H +#define _GENERIC_H + +#include + // Hardware related definitions for generic ESP32 boards #define HAS_LORA 1 // comment out if device shall not send data via LoRa or has no LoRa @@ -13,30 +18,28 @@ #define HAS_BATTERY_PROBE ADC1_GPIO35_CHANNEL // uses GPIO7 #define BATT_FACTOR 2 // voltage divider 100k/100k on board -#define HAS_LED GPIO_NUM_21 // on board LED -#define HAS_BUTTON GPIO_NUM_39 // on board button -#define HAS_RGB_LED GPIO_NUM_0 // WS2812B RGB LED on GPIO0 +#define HAS_LED (21) // on board LED +#define HAS_BUTTON (39) // on board button +#define HAS_RGB_LED (0) // WS2812B RGB LED on GPIO0 #define BOARD_HAS_PSRAM // use extra 4MB extern RAM #define HAS_GPS 1 // use if board has GPS #define GPS_SERIAL 9600, SERIAL_8N1, GPIO_NUM_12, GPIO_NUM_15 // UBlox NEO 6M or 7M with default configuration -// pin definitions for SPI interface of LoRa chip -#define PIN_SPI_SS GPIO_NUM_18 // SPI Chip Select -#define PIN_SPI_MOSI GPIO_NUM_27 // SPI Data Input -#define PIN_SPI_MISO GPIO_NUM_19 // SPI Data Output -#define PIN_SPI_SCK GPIO_NUM_5 // SPI Clock -#define RST LMIC_UNUSED_PIN // LoRa Reset (if wired) -#define DIO0 GPIO_NUM_26 // LoRa IO0 -#define DIO1 GPIO_NUM_32 // LoRa IO1 -#define DIO2 LMIC_UNUSED_PIN // LoRa IO2 (not needed) +// Pins for I2C interface of OLED Display +#define MY_OLED_SDA (4) +#define MY_OLED_SCL (15) +#define MY_OLED_RST (16) -// pin definitions for I2C interface of OLED Display -#define OLED_RST GPIO_NUM_16 // SSD1306 RST -#define I2C_SDA GPIO_NUM_4 // SD1306 D1+D2 -#define I2C_SCL GPIO_NUM_15 // SD1306 D0 +// Pins for LORA chip reset and interrupt lines +#define RST (14) +#define DIO0 (26) +#define DIO1 (33) +#define DIO2 LMIC_UNUSED_PIN // I2C config for Microchip 24AA02E64 DEVEUI unique address #define MCP_24AA02E64_I2C_ADDRESS 0x50 // I2C address for the 24AA02E64 -#define MCP_24AA02E64_MAC_ADDRESS 0xF8 // Memory adress of unique deveui 64 bits \ No newline at end of file +#define MCP_24AA02E64_MAC_ADDRESS 0xF8 // Memory adress of unique deveui 64 bits + +#endif \ No newline at end of file diff --git a/src/hal/heltec.h b/src/hal/heltec.h index 44316c63..e2aea3cc 100644 --- a/src/hal/heltec.h +++ b/src/hal/heltec.h @@ -1,3 +1,8 @@ +#ifndef _HELTEC_H +#define _HELTEC_H + +#include + // Hardware related definitions for Heltec LoRa-32 Board #define HAS_LORA 1 // comment out if device shall not send data via LoRa @@ -5,22 +10,18 @@ #define CFG_sx1276_radio 1 #define HAS_DISPLAY U8X8_SSD1306_128X64_NONAME_HW_I2C // OLED-Display on board -#define HAS_LED GPIO_NUM_25 // white LED on board -#define HAS_BUTTON GPIO_NUM_0 // button "PROG" on board +#define HAS_LED (25) // white LED on board +#define HAS_BUTTON (0) // button "PROG" on board -// re-define pin definitions of pins_arduino.h -#define PIN_SPI_SS GPIO_NUM_18 // ESP32 GPIO18 (Pin18) -- SX1276 NSS (Pin19) SPI Chip Select Input -#define PIN_SPI_MOSI GPIO_NUM_27 // ESP32 GPIO27 (Pin27) -- SX1276 MOSI (Pin18) SPI Data Input -#define PIN_SPI_MISO GPIO_NUM_19 // ESP32 GPIO19 (Pin19) -- SX1276 MISO (Pin17) SPI Data Output -#define PIN_SPI_SCK GPIO_NUM_5 // ESP32 GPIO5 (Pin5) -- SX1276 SCK (Pin16) SPI Clock Input +// Pins for I2C interface of OLED Display +#define MY_OLED_SDA (4) +#define MY_OLED_SCL (15) +#define MY_OLED_RST (16) -// non arduino pin definitions -#define RST GPIO_NUM_14 // ESP32 GPIO14 (Pin14) -- SX1276 NRESET (Pin7) Reset Trigger Input -#define DIO0 GPIO_NUM_26 // ESP32 GPIO26 (Pin15) -- SX1276 DIO0 (Pin8) used by LMIC for detecting LoRa RX_Done & TX_Done -#define DIO1 GPIO_NUM_33 // ESP32 GPIO33 (Pin13) -- SX1276 DIO1 (Pin9) used by LMIC for detecting LoRa RX_Timeout -#define DIO2 LMIC_UNUSED_PIN // 32 ESP32 GPIO32 (Pin12) -- SX1276 DIO2 (Pin10) not used by LMIC for LoRa (Timeout for FSK only) +// Pins for LORA chip reset and interrupt lines +#define RST (14) +#define DIO0 (26) +#define DIO1 (33) +#define DIO2 LMIC_UNUSED_PIN -// Hardware pin definitions for Heltec LoRa-32 Board with OLED SSD1306 I2C Display -#define OLED_RST GPIO_NUM_16 // ESP32 GPIO16 (Pin16) -- SD1306 RST -#define I2C_SDA GPIO_NUM_4 // ESP32 GPIO4 (Pin4) -- SD1306 D1+D2 -#define I2C_SCL GPIO_NUM_15 // ESP32 GPIO15 (Pin15) -- SD1306 D0 +#endif diff --git a/src/hal/heltecv2.h b/src/hal/heltecv2.h index 99eb6ef9..c9c226bf 100644 --- a/src/hal/heltecv2.h +++ b/src/hal/heltecv2.h @@ -1,3 +1,8 @@ +#ifndef _HELTECV2_H +#define _HELTECV2_H + +#include + // Hardware related definitions for Heltec V2 LoRa-32 Board #define HAS_LORA 1 // comment out if device shall not send data via LoRa @@ -5,22 +10,18 @@ #define CFG_sx1276_radio 1 #define HAS_DISPLAY U8X8_SSD1306_128X64_NONAME_HW_I2C // OLED-Display on board -#define HAS_LED GPIO_NUM_25 // white LED on board -#define HAS_BUTTON GPIO_NUM_0 // button "PROG" on board +#define HAS_LED (25) // white LED on board +#define HAS_BUTTON (0) // button "PROG" on board -// re-define pin definitions of pins_arduino.h -#define PIN_SPI_SS GPIO_NUM_18 // ESP32 GPIO18 -- SX1276 NSS (Pin19) SPI Chip Select Input -#define PIN_SPI_MOSI GPIO_NUM_27 // ESP32 GPIO27 -- SX1276 MOSI (Pin18) SPI Data Input -#define PIN_SPI_MISO GPIO_NUM_19 // ESP32 GPIO19 -- SX1276 MISO (Pin17) SPI Data Output -#define PIN_SPI_SCK GPIO_NUM_5 // ESP32 GPIO5 -- SX1276 SCK (Pin16) SPI Clock Input +// Pins for I2C interface of OLED Display +#define OLED_SDA (4) +#define OLED_SCL (15) +#define OLED_RST (16) -// non arduino pin definitions -#define RST GPIO_NUM_14 // ESP32 GPIO18 -- SX1276 NRESET (Pin7) Reset Trigger Input -#define DIO0 GPIO_NUM_26 // ESP32 GPIO26 -- SX1276 DIO0 (Pin8) used by LMIC for detecting LoRa RX_Done & TX_Done -#define DIO1 GPIO_NUM_34 // ESP32 GPIO33 -- SX1276 DIO1 (Pin9) used by LMIC for detecting LoRa RX_Timeout -#define DIO2 GPIO_NUM_35 // 32 ESP32 GPIO32 -- SX1276 DIO2 (Pin10) not used by LMIC for LoRa (Timeout for FSK only) +// Pins for LORA chip reset and interrupt lines +#define RST (14) +#define DIO0 (26) +#define DIO1 (34) +#define DIO2 (35) -// Hardware pin definitions for Heltec LoRa-32 Board with OLED SSD1306 I2C Display -#define OLED_RST GPIO_NUM_16 // ESP32 GPIO16 -- SD1306 RST -#define I2C_SDA GPIO_NUM_4 // ESP32 GPIO4 -- SD1306 D1+D2 -#define I2C_SCL GPIO_NUM_15 // ESP32 GPIO15 -- SD1306 D0 \ No newline at end of file +#endif \ No newline at end of file diff --git a/src/hal/lolin32lite.h b/src/hal/lolin32lite.h index 7b400cf5..9e9f8551 100644 --- a/src/hal/lolin32lite.h +++ b/src/hal/lolin32lite.h @@ -1,3 +1,8 @@ +#ifndef _LOLINLITE_H +#define _LOLINLITE_H + +#include + // Hardware related definitions for lolin32lite (without LoRa shield) #define CFG_sx1272_radio 1 // dummy @@ -5,4 +10,6 @@ #define HAS_LED 22 // on board LED on GPIO22 #define LED_ACTIVE_LOW 1 // Onboard LED is active when pin is LOW -#define HAS_SPI 1 // comment out if device shall not send data via SPI \ No newline at end of file +#define HAS_SPI 1 // comment out if device shall not send data via SPI + +#endif \ No newline at end of file diff --git a/src/hal/lolin32litelora.h b/src/hal/lolin32litelora.h index 6427dbcd..c4e819d4 100644 --- a/src/hal/lolin32litelora.h +++ b/src/hal/lolin32litelora.h @@ -1,3 +1,8 @@ +#ifndef _LOLINLITELORA_H +#define _LOLINLITELORA_H + +#include + // Hardware related definitions for lolin32 lite with loraNode32 shield // See https://github.com/hallard/LoLin32-Lite-Lora @@ -16,24 +21,20 @@ #define HAS_SPI 1 // comment out if device shall not send data via SPI #define CFG_sx1276_radio 1 // RFM95 module -// re-define pin definitions of pins_arduino.h -#define PIN_SPI_SS 5 // ESP32 GPIO5 (Pin5) -- SX1276 NSS (Pin19) SPI Chip Select Input -#define PIN_SPI_MOSI 23 // ESP32 GPIO23 (Pin23) -- SX1276 MOSI (Pin18) SPI Data Input -#define PIN_SPI_MISO 19 // ESP32 GPIO19 (Pin19) -- SX1276 MISO (Pin17) SPI Data Output -#define PIN_SPI_SCK 18 // ESP32 GPIO18 (Pin18 -- SX1276 SCK (Pin16) SPI Clock Input +// Pins for LORA chip reset and interrupt lines +#define RST (25) +#define DIO0 (27) +#define DIO1 (26) +#define DIO2 LMIC_UNUSED_PIN +#define DIO5 LMIC_UNUSED_PIN -// non arduino pin definitions -#define RST 25 // ESP32 GPIO25 (Pin25) -- SX1276 NRESET (Pin7) Reset Trigger Input -#define DIO0 27 // ESP32 GPIO27 (Pin27) -- SX1276 DIO0 (Pin8) used by LMIC for detecting LoRa RX_Done & TX_Done -#define DIO1 26 // ESP32 GPIO26 (Pin26) -- SX1276 DIO1 (Pin9) used by LMIC for detecting LoRa RX_Timeout -#define DIO2 LMIC_UNUSED_PIN // 4 ESP32 GPIO4 (Pin4) -- SX1276 DIO2 (Pin10) not used by LMIC for LoRa (Timeout for FSK only) -#define DIO5 LMIC_UNUSED_PIN // 35 ESP32 GPIO35 (Pin35) -- SX1276 DIO5 not used by LMIC for LoRa (Timeout for FSK only) - -// Hardware pin definitions for LoRaNode32 Board with OLED I2C Display -#define OLED_RST U8X8_PIN_NONE // Not reset pin -#define I2C_SDA 14 // ESP32 GPIO14 (Pin14) -- OLED SDA -#define I2C_SCL 12 // ESP32 GPIO12 (Pin12) -- OLED SCL +// Pins for I2C interface of OLED Display +#define MY_OLED_SDA (14) +#define MY_OLED_SCL (12) +#define MY_OLED_RST U8X8_PIN_NONE // I2C config for Microchip 24AA02E64 DEVEUI unique address #define MCP_24AA02E64_I2C_ADDRESS 0x50 // I2C address for the 24AA02E64 #define MCP_24AA02E64_MAC_ADDRESS 0xF8 // Memory adress of unique deveui 64 bits + +#endif diff --git a/src/hal/lolin32lora.h b/src/hal/lolin32lora.h index 7964a561..1e52bb52 100644 --- a/src/hal/lolin32lora.h +++ b/src/hal/lolin32lora.h @@ -1,3 +1,8 @@ +#ifndef _LOLINLORA_H +#define _LOLINLORA_H + +#include + // Hardware related definitions for lolin32 with loraNode32 shield // See https://github.com/hallard/LoLin32-Lora @@ -17,24 +22,20 @@ #define HAS_SPI 1 // comment out if device shall not send data via SPI #define CFG_sx1276_radio 1 // RFM95 module -// re-define pin definitions of pins_arduino.h -#define PIN_SPI_SS 5 // ESP32 GPIO5 (Pin5) -- SX1276 NSS (Pin19) SPI Chip Select Input -#define PIN_SPI_MOSI 23 // ESP32 GPIO23 (Pin23) -- SX1276 MOSI (Pin18) SPI Data Input -#define PIN_SPI_MISO 19 // ESP32 GPIO19 (Pin19) -- SX1276 MISO (Pin17) SPI Data Output -#define PIN_SPI_SCK 18 // ESP32 GPIO18 (Pin18 -- SX1276 SCK (Pin16) SPI Clock Input +// Pins for LORA chip reset and interrupt lines +#define RST (25) +#define DIO0 (27) +#define DIO1 (26) +#define DIO2 LMIC_UNUSED_PIN +#define DIO5 LMIC_UNUSED_PIN -// non arduino pin definitions -#define RST 25 // ESP32 GPIO25 (Pin25) -- SX1276 NRESET (Pin7) Reset Trigger Input -#define DIO0 27 // ESP32 GPIO27 (Pin27) -- SX1276 DIO0 (Pin8) used by LMIC for detecting LoRa RX_Done & TX_Done -#define DIO1 26 // ESP32 GPIO26 (Pin26) -- SX1276 DIO1 (Pin9) used by LMIC for detecting LoRa RX_Timeout -#define DIO2 LMIC_UNUSED_PIN // 4 ESP32 GPIO4 (Pin4) -- SX1276 DIO2 (Pin10) not used by LMIC for LoRa (Timeout for FSK only) -#define DIO5 LMIC_UNUSED_PIN // 35 ESP32 GPIO35 (Pin35) -- SX1276 DIO5 not used by LMIC for LoRa (Timeout for FSK only) - -// Hardware pin definitions for LoRaNode32 Board with OLED I2C Display -#define OLED_RST U8X8_PIN_NONE // Not reset pin -#define I2C_SDA 21 // ESP32 GPIO21 (Pin21) -- OLED SDA -#define I2C_SCL 22 // ESP32 GPIO22 (Pin22) -- OLED SCL +// Pins for I2C interface of OLED Display +#define MY_OLED_SDA (21) +#define MY_OLED_SCL (22) +#define MY_OLED_RST U8X8_PIN_NONE // I2C config for Microchip 24AA02E64 DEVEUI unique address #define MCP_24AA02E64_I2C_ADDRESS 0x50 // I2C address for the 24AA02E64 #define MCP_24AA02E64_MAC_ADDRESS 0xF8 // Memory adress of unique deveui 64 bits + +#endif diff --git a/src/hal/lopy.h b/src/hal/lopy.h index b4a6a796..37acbab9 100644 --- a/src/hal/lopy.h +++ b/src/hal/lopy.h @@ -1,23 +1,32 @@ +#ifndef _LOPY_H +#define _LOPY_H + +#include + // Hardware related definitions for Pycom LoPy Board (NOT LoPy4) #define HAS_LORA 1 // comment out if device shall not send data via LoRa #define HAS_SPI 1 // comment out if device shall not send data via SPI #define CFG_sx1272_radio 1 #define HAS_LED NOT_A_PIN // LoPy4 has no on board mono LED, we use on board RGB LED -#define HAS_RGB_LED GPIO_NUM_0 // WS2812B RGB LED on GPIO0 +#define HAS_RGB_LED (0) // WS2812B RGB LED on GPIO0 +/* SPI remapping does currently not work!! // Hardware pin definitions for Pycom LoPy board #define PIN_SPI_SS GPIO_NUM_17 #define PIN_SPI_MOSI GPIO_NUM_27 #define PIN_SPI_MISO GPIO_NUM_19 #define PIN_SPI_SCK GPIO_NUM_5 -#define RST GPIO_NUM_18 -#define DIO0 GPIO_NUM_23 // LoRa IRQ -#define DIO1 GPIO_NUM_23 // Pin tied via diode to DIO0 -#define DIO2 GPIO_NUM_23 // Pin tied via diode to DIO0 +*/ + +// Pins for LORA chip reset and interrupt lines +#define RST (18) +#define DIO0 (23) // LoRa IRQ +#define DIO1 (23) // Pin tied via diode to DIO0 +#define DIO2 (23) // Pin tied via diode to DIO0 // select WIFI antenna (internal = onboard / external = u.fl socket) -#define HAS_ANTENNA_SWITCH GPIO_NUM_16 // pin for switching wifi antenna +#define HAS_ANTENNA_SWITCH (16) // pin for switching wifi antenna #define WIFI_ANTENNA 0 // 0 = internal, 1 = external // uncomment this only if your LoPy runs on a PYTRACK BOARD @@ -26,10 +35,12 @@ //#define GPS_ADDR 0x10 // uncomment this only if your LoPy runs on a EXPANSION BOARD -//#define HAS_LED GPIO_NUM_12 // use if LoPy is on Expansion Board, this has a user LED +//#define HAS_LED (12) // use if LoPy is on Expansion Board, this has a user LED //#define LED_ACTIVE_LOW 1 // use if LoPy is on Expansion Board, this has a user LED -//#define HAS_BUTTON GPIO_NUM_13 // user button on expansion board +//#define HAS_BUTTON (13) // user button on expansion board //#define BUTTON_PULLUP 1 // Button need pullup instead of default pulldown //#define HAS_BATTERY_PROBE ADC1_GPIO39_CHANNEL // battery probe GPIO pin -> ADC1_CHANNEL_7 //#define BATT_FACTOR 2 // voltage divider 1MOhm/1MOhm -> expansion board 3.0 //#define BATT_FACTOR 4 // voltage divider 115kOhm/56kOhm -> expansion board 2.0 + +#endif diff --git a/src/hal/lopy4.h b/src/hal/lopy4.h index db98eba9..4e60cb30 100644 --- a/src/hal/lopy4.h +++ b/src/hal/lopy4.h @@ -1,24 +1,25 @@ +#ifndef _LOPY4_H +#define _LOPY4_H + +#include + // Hardware related definitions for Pycom LoPy4 Board #define HAS_LORA 1 // comment out if device shall not send data via LoRa #define HAS_SPI 1 // comment out if device shall not send data via SPI #define CFG_sx1276_radio 1 //#define HAS_LED NOT_A_PIN // LoPy4 has no on board mono LED, we use on board RGB LED -#define HAS_RGB_LED GPIO_NUM_0 // WS2812B RGB LED on GPIO0 (P2) +#define HAS_RGB_LED (0) // WS2812B RGB LED on GPIO0 (P2) #define BOARD_HAS_PSRAM // use extra 4MB extern RAM -// Hardware pin definitions for Pycom LoPy4 board -#define PIN_SPI_SS GPIO_NUM_18 -#define PIN_SPI_MOSI GPIO_NUM_27 -#define PIN_SPI_MISO GPIO_NUM_19 -#define PIN_SPI_SCK GPIO_NUM_5 +// Pins for LORA chip reset and interrupt lines #define RST LMIC_UNUSED_PIN -#define DIO0 GPIO_NUM_23 // LoRa IRQ -#define DIO1 GPIO_NUM_23 // Pin tied via diode to DIO0 -#define DIO2 GPIO_NUM_23 // Pin tied via diode to DIO0 +#define DIO0 (23) // LoRa IRQ +#define DIO1 (23) // Pin tied via diode to DIO0 +#define DIO2 (23) // Pin tied via diode to DIO0 // select WIFI antenna (internal = onboard / external = u.fl socket) -#define HAS_ANTENNA_SWITCH GPIO_NUM_21 // pin for switching wifi antenna (P12) +#define HAS_ANTENNA_SWITCH (21) // pin for switching wifi antenna (P12) #define WIFI_ANTENNA 0 // 0 = internal, 1 = external // uncomment this only if your LoPy runs on a PYTRACK BOARD @@ -27,10 +28,12 @@ //#define GPS_ADDR 0x10 // uncomment this only if your LoPy runs on a EXPANSION BOARD -#define HAS_LED GPIO_NUM_12 // use if LoPy is on Expansion Board, this has a user LED +#define HAS_LED (12) // use if LoPy is on Expansion Board, this has a user LED #define LED_ACTIVE_LOW 1 // use if LoPy is on Expansion Board, this has a user LED -#define HAS_BUTTON GPIO_NUM_13 // user button on expansion board +#define HAS_BUTTON (13) // user button on expansion board #define BUTTON_PULLUP 1 // Button need pullup instead of default pulldown #define HAS_BATTERY_PROBE ADC1_GPIO39_CHANNEL // battery probe GPIO pin -> ADC1_CHANNEL_7 #define BATT_FACTOR 2 // voltage divider 1MOhm/1MOhm -> expansion board 3.0 -//#define BATT_FACTOR 4 // voltage divider 115kOhm/56kOhm -> expansion board 2.0 \ No newline at end of file +//#define BATT_FACTOR 4 // voltage divider 115kOhm/56kOhm -> expansion board 2.0 + +#endif \ No newline at end of file diff --git a/src/hal/octopus32.h b/src/hal/octopus32.h index a448916c..96bd9124 100644 --- a/src/hal/octopus32.h +++ b/src/hal/octopus32.h @@ -1,3 +1,8 @@ +#ifndef _OCTOPUS_H +#define _OCTOPUS_H + +#include + // Hardware related definitions for #IoT Octopus32 with the Adafruit LoRaWAN Wing // You can use this configuration also with the Adafruit ESP32 Feather + the LoRaWAN Wing // In this config we use the Adafruit OLED Wing which is only 128x32 pixel, need to find a smaller font @@ -15,27 +20,25 @@ #define HAS_SPI 1 // comment out if device shall not send data via SPI #define CFG_sx1276_radio 1 // RFM95 module +/* SPI remapping does currently not work!! */ // re-define pin definitions of pins_arduino.h #define PIN_SPI_SS 14 //14 // ESP32 GPIO5 (Pin5) -- SX1276 NSS (Pin19) SPI Chip Select Input #define PIN_SPI_MOSI 18 // ESP32 GPIO23 (Pin23) -- SX1276 MOSI (Pin18) SPI Data Input #define PIN_SPI_MISO 19 // ESP32 GPIO19 (Pin19) -- SX1276 MISO (Pin17) SPI Data Output #define PIN_SPI_SCK 5 // ESP32 GPIO18 (Pin18) -- SX1276 SCK (Pin16) SPI Clock Input -//GPIO_NUM_ -// non arduino pin definitions -#define RST LMIC_UNUSED_PIN // ESP32 GPIO25 (Pin25) -- SX1276 NRESET (Pin7) Reset Trigger Input -#define DIO0 33 // ESP32 GPIO27 (Pin27) -- SX1276 DIO0 (Pin8) used by LMIC for detecting LoRa RX_Done & TX_Done -#define DIO1 33 // ESP32 GPIO26 (Pin26) -- SX1276 DIO1 (Pin9) used by LMIC for detecting LoRa RX_Timeout -#define DIO2 LMIC_UNUSED_PIN // 4 ESP32 GPIO4 (Pin4) -- SX1276 DIO2 (Pin10) not used by LMIC for LoRa (Timeout for FSK only) -#define DIO5 LMIC_UNUSED_PIN // 35 ESP32 GPIO35 (Pin35) -- SX1276 DIO5 not used by LMIC for LoRa (Timeout for FSK only) +// Pins for LORA chip reset and interrupt lines +#define RST LMIC_UNUSED_PIN +#define DIO0 (33) +#define DIO1 (33) +#define DIO2 LMIC_UNUSED_PIN +#define DIO5 LMIC_UNUSED_PIN -// Hardware pin definitions for LoRaNode32 Board with OLED I2C Display -#define OLED_RST U8X8_PIN_NONE // Not reset pin -#define HAS_DISPLAY U8X8_SSD1306_128X64_NONAME_HW_I2C // U8X8_SSD1306_128X32_UNIVISION_SW_I2C // -//#define DISPLAY_FLIP 1 // uncomment this for rotated display -#define I2C_SDA 23 //21 // ESP32 GPIO14 (Pin14) -- OLED SDA -#define I2C_SCL 22 //22 // ESP32 GPIO12 (Pin12) -- OLED SCL +// Pins for I2C interface of OLED Display +#define HAS_DISPLAY U8X8_SSD1306_128X64_NONAME_HW_I2C // U8X8_SSD1306_128X32_UNIVISION_SW_I2C // +//#define DISPLAY_FLIP 1 // uncomment this for rotated display +#define MY_OLED_SDA (23) +#define MY_OLED_SCL (22) +#define MY_OLED_RST U8X8_PIN_NONE -// I2C config for Microchip 24AA02E64 DEVEUI unique address -//#define MCP_24AA02E64_I2C_ADDRESS 0x50 // I2C address for the 24AA02E64 -//#define MCP_24AA02E64_MAC_ADDRESS 0xF8 // Memory adress of unique deveui 64 bits +#endif diff --git a/src/hal/ttgobeam.h b/src/hal/ttgobeam.h index 7167fbfa..313d6403 100644 --- a/src/hal/ttgobeam.h +++ b/src/hal/ttgobeam.h @@ -1,3 +1,8 @@ +#ifndef _TTGOBEAM_H +#define _TTGOBEAM_H + +#include + // Hardware related definitions for TTGO T-Beam board #define HAS_LORA 1 // comment out if device shall not send data via LoRa @@ -14,15 +19,11 @@ #define HAS_GPS 1 // use on board GPS #define GPS_SERIAL 9600, SERIAL_8N1, GPIO_NUM_12, GPIO_NUM_15 // UBlox NEO 6M or 7M with default configuration -// re-define pin definitions of pins_arduino.h -#define PIN_SPI_SS GPIO_NUM_18 // ESP32 GPIO18 (Pin18) -- HPD13A NSS/SEL (Pin4) SPI Chip Select Input -#define PIN_SPI_MOSI GPIO_NUM_27 // ESP32 GPIO27 (Pin27) -- HPD13A MOSI/DSI (Pin6) SPI Data Input -#define PIN_SPI_MISO GPIO_NUM_19 // ESP32 GPIO19 (Pin19) -- HPD13A MISO/DSO (Pin7) SPI Data Output -#define PIN_SPI_SCK GPIO_NUM_5 // ESP32 GPIO5 (Pin5) -- HPD13A SCK (Pin5) SPI Clock Input +// Pins for LORA chip reset and interrupt lines +#define RST LMIC_UNUSED_PIN +#define DIO0 (26) +#define DIO1 (32) // !! NEEDS EXTERNAL WIRING !! +//#define DIO1 (33) // for T-Beam T22_V05 and T22_V07, other versions may need external wiring +#define DIO2 LMIC_UNUSED_PIN -// non arduino pin definitions -#define RST LMIC_UNUSED_PIN // connected to ESP32 RST/EN -#define DIO0 GPIO_NUM_26 // ESP32 GPIO26 <-> HPD13A IO0 -#define DIO1 GPIO_NUM_32 // Lora1 <-> HPD13A IO1 // !! NEEDS EXTERNAL WIRING !! -//#define DIO1 GPIO_NUM_33 // Lora1 <-> HPD13A IO1 // for T-Beam T22_V05 and T22_V07, other versions may need external wiring -#define DIO2 LMIC_UNUSED_PIN // Lora2 <-> HPD13A IO2 // not needed for LoRa +#endif diff --git a/src/hal/ttgov1.h b/src/hal/ttgov1.h index f64fe380..284eaf06 100644 --- a/src/hal/ttgov1.h +++ b/src/hal/ttgov1.h @@ -1,3 +1,8 @@ +#ifndef _TTGOV1_H +#define _TTGOV1_H + +#include + // Hardware related definitions for TTGOv1 board #define HAS_LORA 1 // comment out if device shall not send data via LoRa @@ -6,23 +11,19 @@ #define HAS_DISPLAY U8X8_SSD1306_128X64_NONAME_HW_I2C // OLED-Display on board //#define DISPLAY_FLIP 1 // uncomment this for rotated display -#define HAS_LED GPIO_NUM_2 // white LED on board +#define HAS_LED (2) // white LED on board #define LED_ACTIVE_LOW 1 // Onboard LED is active when pin is LOW -#define HAS_BUTTON GPIO_NUM_0 // button "PRG" on board +#define HAS_BUTTON (0) // button "PRG" on board -// re-define pin definitions of pins_arduino.h -#define PIN_SPI_SS GPIO_NUM_18 // ESP32 GPIO18 (Pin18) -- SX1276 NSS (Pin19) SPI Chip Select Input -#define PIN_SPI_MOSI GPIO_NUM_27 // ESP32 GPIO27 (Pin27) -- SX1276 MOSI (Pin18) SPI Data Input -#define PIN_SPI_MISO GPIO_NUM_19 // ESP32 GPIO19 (Pin19) -- SX1276 MISO (Pin17) SPI Data Output -#define PIN_SPI_SCK GPIO_NUM_5 // ESP32 GPIO5 (Pin5) -- SX1276 SCK (Pin16) SPI Clock Input +// Pins for I2C interface of OLED Display +#define MY_OLED_SDA (4) +#define MY_OLED_SCL (15) +#define MY_OLED_RST (16) -// non arduino pin definitions -#define RST GPIO_NUM_14 // ESP32 GPIO14 (Pin14) -- SX1276 NRESET (Pin7) Reset Trigger Input -#define DIO0 GPIO_NUM_26 // ESP32 GPIO26 (Pin15) -- SX1276 DIO0 (Pin8) used by LMIC for detecting LoRa RX_Done & TX_Done -#define DIO1 GPIO_NUM_33 // ESP32 GPIO33 (Pin13) -- SX1276 DIO1 (Pin9) used by LMIC for detecting LoRa RX_Timeout -#define DIO2 LMIC_UNUSED_PIN // 32 ESP32 GPIO32 (Pin12) -- SX1276 DIO2 (Pin10) not used by LMIC for LoRa (Timeout for FSK only) +// Pins for LORA chip reset and interrupt lines +#define RST (14) +#define DIO0 (26) +#define DIO1 (33) +#define DIO2 LMIC_UNUSED_PIN -// Hardware pin definitions for TTGOv1 Board with OLED SSD1306 I2C Display -#define OLED_RST GPIO_NUM_16 // ESP32 GPIO16 (Pin16) -- SD1306 Reset -#define I2C_SDA GPIO_NUM_4 // ESP32 GPIO4 (Pin4) -- SD1306 Data -#define I2C_SCL GPIO_NUM_15 // ESP32 GPIO15 (Pin15) -- SD1306 Clock +#endif diff --git a/src/hal/ttgov2.h b/src/hal/ttgov2.h index 0df3146e..597ba35d 100644 --- a/src/hal/ttgov2.h +++ b/src/hal/ttgov2.h @@ -1,3 +1,8 @@ +#ifndef _TTGOV2_H +#define _TTGOV2_H + +#include + // Hardware related definitions for TTGO V2 Board #define HAS_LORA 1 // comment out if device shall not send data via LoRa @@ -11,46 +16,15 @@ // disable brownout detection (needed on TTGOv2 for battery powered operation) #define DISABLE_BROWNOUT 1 // comment out if you want to keep brownout feature -// re-define pin definitions of pins_arduino.h -#define PIN_SPI_SS GPIO_NUM_18 // ESP32 GPIO18 (Pin18) -- HPD13A NSS/SEL (Pin4) SPI Chip Select Input -#define PIN_SPI_MOSI GPIO_NUM_27 // ESP32 GPIO27 (Pin27) -- HPD13A MOSI/DSI (Pin6) SPI Data Input -#define PIN_SPI_MISO GPIO_NUM_19 // ESP32 GPIO19 (Pin19) -- HPD13A MISO/DSO (Pin7) SPI Data Output -#define PIN_SPI_SCK GPIO_NUM_5 // ESP32 GPIO5 (Pin5) -- HPD13A SCK (Pin5) SPI Clock Input +// Pins for I2C interface of OLED Display +#define MY_OLED_SDA (21) +#define MY_OLED_SCL (22) +#define MY_OLED_RST U8X8_PIN_NONE -// non arduino pin definitions -#define RST LMIC_UNUSED_PIN // connected to ESP32 RST/EN -#define DIO0 GPIO_NUM_26 // ESP32 GPIO26 wired on PCB to HPD13A -#define DIO1 GPIO_NUM_33 // HPDIO1 on pcb, needs to be wired external to GPIO33 -#define DIO2 LMIC_UNUSED_PIN // 32 HPDIO2 on pcb, needs to be wired external to GPIO32 (not necessary for LoRa, only FSK) +// Pins for LORA chip reset and interrupt lines +#define RST LMIC_UNUSED_PIN +#define DIO0 (26) +#define DIO1 (33) +#define DIO2 LMIC_UNUSED_PIN -// Hardware pin definitions for TTGO V2 Board with OLED SSD1306 0,96" I2C Display -#define OLED_RST U8X8_PIN_NONE // connected to CPU RST/EN -#define I2C_SDA GPIO_NUM_21 // ESP32 GPIO21 -- SD1306 D1+D2 -#define I2C_SCL GPIO_NUM_22 // ESP32 GPIO22 -- SD1306 D0 - -/* source: -https://www.thethingsnetwork.org/forum/t/big-esp32-sx127x-topic-part-2/11973 - -TTGO LoRa32 V2: -ESP32 LoRa (SPI) Display (I2C) LED ------------ ---------- ------------- ------------------ -GPIO5 SCK SCK -GPIO27 MOSI MOSI -GPIO19 MISO MISO -GPIO18 SS NSS -EN RST RST -GPIO26 DIO0 -GPIO33 DIO1 (see #1) -GPIO32 DIO2 (see #2) -GPIO22 SCL SCL -GPIO21 SDA SDA -GPIO22 useless (see #3) - -#1 Required (used by LMIC for LoRa). -Not on-board wired to any GPIO. Must be manually wired. <<-- necessary for paxcounter - -#2 Optional (used by LMIC for FSK but not for LoRa). <<-- NOT necessary for paxcounter -Not on-board wired to any GPIO. When needed: must be manually wired. - -#3 GPIO22 is already used for SCL therefore LED cannot be used without conflicting with I2C and display. -*/ \ No newline at end of file +#endif \ No newline at end of file diff --git a/src/hal/ttgov21new.h b/src/hal/ttgov21new.h index 5cadc961..60cc12af 100644 --- a/src/hal/ttgov21new.h +++ b/src/hal/ttgov21new.h @@ -1,3 +1,8 @@ +#ifndef _TTGOV21NEW_H +#define _TTGOV21NEW_H + +#include + /* Hardware related definitions for TTGO V2.1 Board // ATTENTION: check your board version! // This settings are for boards labeled v1.6 on pcb, NOT for v1.5 or older @@ -8,23 +13,19 @@ #define CFG_sx1276_radio 1 // HPD13A LoRa SoC #define HAS_DISPLAY U8X8_SSD1306_128X64_NONAME_HW_I2C -#define HAS_LED GPIO_NUM_25 // green on board LED +#define HAS_LED (25) // green on board LED #define HAS_BATTERY_PROBE ADC1_GPIO35_CHANNEL // uses GPIO7 #define BATT_FACTOR 2 // voltage divider 100k/100k on board -// re-define pin definitions of pins_arduino.h -#define PIN_SPI_SS GPIO_NUM_18 // ESP32 GPIO18 (Pin18) -- HPD13A NSS/SEL (Pin4) SPI Chip Select Input -#define PIN_SPI_MOSI GPIO_NUM_27 // ESP32 GPIO27 (Pin27) -- HPD13A MOSI/DSI (Pin6) SPI Data Input -#define PIN_SPI_MISO GPIO_NUM_19 // ESP32 GPIO19 (Pin19) -- HPD13A MISO/DSO (Pin7) SPI Data Output -#define PIN_SPI_SCK GPIO_NUM_5 // ESP32 GPIO5 (Pin5) -- HPD13A SCK (Pin5) SPI Clock Input +// Pins for I2C interface of OLED Display +#define MY_OLED_SDA (21) +#define MY_OLED_SCL (22) +#define MY_OLED_RST U8X8_PIN_NONE -// non arduino pin definitions -#define RST GPIO_NUM_23 // ESP32 GPIO23 <-> HPD13A RESET -#define DIO0 GPIO_NUM_26 // ESP32 GPIO26 <-> HPD13A IO0 -#define DIO1 GPIO_NUM_33 // ESP32 GPIO33 <-> HPDIO1 <-> HPD13A IO1 -#define DIO2 GPIO_NUM_32 // ESP32 GPIO32 <-> HPDIO2 <-> HPD13A IO2 +// Pins for LORA chip reset and interrupt lines +#define RST (23) +#define DIO0 (26) +#define DIO1 (33) +#define DIO2 (32) -// Hardware pin definitions for TTGO V2 Board with OLED SSD1306 0,96" I2C Display -#define OLED_RST U8X8_PIN_NONE // connected to CPU RST/EN -#define I2C_SDA GPIO_NUM_21 // ESP32 GPIO21 -- SD1306 D1+D2 -#define I2C_SCL GPIO_NUM_22 // ESP32 GPIO22 -- SD1306 D0 \ No newline at end of file +#endif \ No newline at end of file diff --git a/src/hal/ttgov21old.h b/src/hal/ttgov21old.h index 25271b80..5e0e9b4f 100644 --- a/src/hal/ttgov21old.h +++ b/src/hal/ttgov21old.h @@ -1,3 +1,9 @@ +#ifndef _TTGOV21OLD_H +#define _TTGOV21OLD_H + +#include + + /* Hardware related definitions for TTGO V2.1 Board // ATTENTION: check your board version! // This settings are for boards without label on pcb, or labeled v1.5 on pcb @@ -14,20 +20,15 @@ //#define HAS_BATTERY_PROBE ADC1_GPIO35_CHANNEL // uses GPIO7 //#define BATT_FACTOR 2 // voltage divider 100k/100k on board -// re-define pin definitions of pins_arduino.h -#define PIN_SPI_SS GPIO_NUM_18 // ESP32 GPIO18 (Pin18) -- HPD13A NSS/SEL (Pin4) SPI Chip Select Input -#define PIN_SPI_MOSI GPIO_NUM_27 // ESP32 GPIO27 (Pin27) -- HPD13A MOSI/DSI (Pin6) SPI Data Input -#define PIN_SPI_MISO GPIO_NUM_19 // ESP32 GPIO19 (Pin19) -- HPD13A MISO/DSO (Pin7) SPI Data Output -#define PIN_SPI_SCK GPIO_NUM_5 // ESP32 GPIO5 (Pin5) -- HPD13A SCK (Pin5) SPI Clock Input +// Pins for I2C interface of OLED Display +#define MY_OLED_SDA (21) +#define MY_OLED_SCL (22) +#define MY_OLED_RST U8X8_PIN_NONE -// non arduino pin definitions -#define RST LMIC_UNUSED_PIN // connected to ESP32 RST/EN (old board) -//#define RST GPIO_NUM_12 // (boards labeled v1.5) -#define DIO0 GPIO_NUM_26 // ESP32 GPIO26 <-> HPD13A IO0 -#define DIO1 GPIO_NUM_33 // ESP32 GPIO33 <-> HPDIO1 <-> HPD13A IO1 -#define DIO2 GPIO_NUM_32 // ESP32 GPIO32 <-> HPDIO2 <-> HPD13A IO2 +// Pins for LORA chip reset and interrupt lines +#define RST LMIC_UNUSED_PIN +#define DIO0 (26) +#define DIO1 (33) +#define DIO2 (32) -// Hardware pin definitions for TTGO V2 Board with OLED SSD1306 0,96" I2C Display -#define OLED_RST U8X8_PIN_NONE // connected to CPU RST/EN -#define I2C_SDA GPIO_NUM_21 // ESP32 GPIO21 -- SD1306 D1+D2 -#define I2C_SCL GPIO_NUM_22 // ESP32 GPIO22 -- SD1306 D0 +#endif \ No newline at end of file diff --git a/lib/arduino-lmic-1.5.0-arduino-2-tweaked/src/lmic/config.h b/src/lmic_config.h similarity index 71% rename from lib/arduino-lmic-1.5.0-arduino-2-tweaked/src/lmic/config.h rename to src/lmic_config.h index 44c05ed0..ccda75e5 100644 --- a/lib/arduino-lmic-1.5.0-arduino-2-tweaked/src/lmic/config.h +++ b/src/lmic_config.h @@ -1,83 +1,95 @@ -#ifndef _lmic_config_h_ -#define _lmic_config_h_ - -// In the original LMIC code, these config values were defined on the -// gcc commandline. Since Arduino does not allow easily modifying the -// compiler commandline, use this file instead. - -#define CFG_eu868 1 -//#define CFG_us915 1 -// This is the SX1272/SX1273 radio, which is also used on the HopeRF -// RFM92 boards. -//#define CFG_sx1272_radio 1 -// This is the SX1276/SX1277/SX1278/SX1279 radio, which is also used on -// the HopeRF RFM95 boards. -#define CFG_sx1276_radio 1 - -// 16 μs per tick -// LMIC requires ticks to be 15.5μs - 100 μs long -#define US_PER_OSTICK_EXPONENT 4 -#define US_PER_OSTICK (1 << US_PER_OSTICK_EXPONENT) -#define OSTICKS_PER_SEC (1000000 / US_PER_OSTICK) - -// Set this to 1 to enable some basic debug output (using printf) about -// RF settings used during transmission and reception. Set to 2 to -// enable more verbose output. Make sure that printf is actually -// configured (e.g. on AVR it is not by default), otherwise using it can -// cause crashing. -#define LMIC_DEBUG_LEVEL 0 - -// Enable this to allow using printf() to print to the given serial port -// (or any other Print object). This can be easy for debugging. The -// current implementation only works on AVR, though. -//#define LMIC_PRINTF_TO Serial - -// Any runtime assertion failures are printed to this serial port (or -// any other Print object). If this is unset, any failures just silently -// halt execution. -#define LMIC_FAILURE_TO Serial - -// Uncomment this to disable all code related to joining -//#define DISABLE_JOIN -// Uncomment this to disable all code related to ping -//#define DISABLE_PING -// Uncomment this to disable all code related to beacon tracking. -// Requires ping to be disabled too -//#define DISABLE_BEACONS - -// Uncomment these to disable the corresponding MAC commands. -// Class A -//#define DISABLE_MCMD_DCAP_REQ // duty cycle cap -//#define DISABLE_MCMD_DN2P_SET // 2nd DN window param -//#define DISABLE_MCMD_SNCH_REQ // set new channel -// Class B -//#define DISABLE_MCMD_PING_SET // set ping freq, automatically disabled by DISABLE_PING -//#define DISABLE_MCMD_BCNI_ANS // next beacon start, automatical disabled by DISABLE_BEACON - -// In LoRaWAN, a gateway applies I/Q inversion on TX, and nodes do the -// same on RX. This ensures that gateways can talk to nodes and vice -// versa, but gateways will not hear other gateways and nodes will not -// hear other nodes. By uncommenting this macro, this inversion is -// disabled and this node can hear other nodes. If two nodes both have -// this macro set, they can talk to each other (but they can no longer -// hear gateways). This should probably only be used when debugging -// and/or when talking to the radio directly (e.g. like in the "raw" -// example). -//#define DISABLE_INVERT_IQ_ON_RX - -// This allows choosing between multiple included AES implementations. -// Make sure exactly one of these is uncommented. -// -// This selects the original AES implementation included LMIC. This -// implementation is optimized for speed on 32-bit processors using -// fairly big lookup tables, but it takes up big amounts of flash on the -// AVR architecture. -// #define USE_ORIGINAL_AES -// -// This selects the AES implementation written by Ideetroon for their -// own LoRaWAN library. It also uses lookup tables, but smaller -// byte-oriented ones, making it use a lot less flash space (but it is -// also about twice as slow as the original). -#define USE_IDEETRON_AES - -#endif // _lmic_config_h_ +// COUNTRY AND PROJECT SPECIFIC DEFINITIONS FOR LMIC STACK + +// COUNTRY SETTINGS +// --> please check with you local regulations for ISM band frequency use! +// +// CFG_eu868 EU 863-870 MHz +// CFG_us915 US 902-928 MHz +// CFG_au921 Australia 915-928 MHz +// CFG_as923 Asia 923 MHz +// CFG_in866 India 865-867 MHz + +#define CFG_eu868 1 +//#define CFG_us915 1 +//#define CFG_in866 1 +//#define CFG_au921 1 +//#define CFG_as923 1 +//#define LMIC_COUNTRY_CODE LMIC_COUNTRY_CODE_JP /* for as923-JP */ + +// LMIC LORAWAN STACK SETTINGS +// --> adapt to your device only if necessary + +//#define LMIC_USE_INTERRUPTS + +// 16 μs per tick +// LMIC requires ticks to be 15.5μs - 100 μs long +#define US_PER_OSTICK_EXPONENT 4 +#define US_PER_OSTICK (1 << US_PER_OSTICK_EXPONENT) +#define OSTICKS_PER_SEC (1000000 / US_PER_OSTICK) + +// This tells LMIC to make the receive windows bigger, in case your clock is +// faster or slower. This causes the transceiver to be earlier switched on, +// so consuming more power. You may sharpen (reduce) this value if you are +// limited on battery. +#define CLOCK_ERROR_PROCENTAGE 20 + +// Set this to 1 to enable some basic debug output (using printf) about +// RF settings used during transmission and reception. Set to 2 to +// enable more verbose output. Make sure that printf is actually +// configured (e.g. on AVR it is not by default), otherwise using it can +// cause crashing. +//#define LMIC_DEBUG_LEVEL 1 + +// Enable this to allow using printf() to print to the given serial port +// (or any other Print object). This can be easy for debugging. The +// current implementation only works on AVR, though. +//#define LMIC_PRINTF_TO Serial + +// Any runtime assertion failures are printed to this serial port (or +// any other Print object). If this is unset, any failures just silently +// halt execution. +#define LMIC_FAILURE_TO Serial + +// Uncomment this to disable all code related to joining +//#define DISABLE_JOIN +// Uncomment this to disable all code related to ping +#define DISABLE_PING +// Uncomment this to disable all code related to beacon tracking. +// Requires ping to be disabled too +#define DISABLE_BEACONS + +// Uncomment these to disable the corresponding MAC commands. +// Class A +//#define DISABLE_MCMD_DCAP_REQ // duty cycle cap +//#define DISABLE_MCMD_DN2P_SET // 2nd DN window param +//#define DISABLE_MCMD_SNCH_REQ // set new channel +// Class B +//#define DISABLE_MCMD_PING_SET // set ping freq, automatically disabled by +// DISABLE_PING #define DISABLE_MCMD_BCNI_ANS // next beacon start, automatical +// disabled by DISABLE_BEACON + +// In LoRaWAN, a gateway applies I/Q inversion on TX, and nodes do the +// same on RX. This ensures that gateways can talk to nodes and vice +// versa, but gateways will not hear other gateways and nodes will not +// hear other nodes. By uncommenting this macro, this inversion is +// disabled and this node can hear other nodes. If two nodes both have +// this macro set, they can talk to each other (but they can no longer +// hear gateways). This should probably only be used when debugging +// and/or when talking to the radio directly (e.g. like in the "raw" +// example). +//#define DISABLE_INVERT_IQ_ON_RX + +// This allows choosing between multiple included AES implementations. +// Make sure exactly one of these is uncommented. +// +// This selects the original AES implementation included LMIC. This +// implementation is optimized for speed on 32-bit processors using +// fairly big lookup tables, but it takes up big amounts of flash on the +// AVR architecture. +#define USE_ORIGINAL_AES +// +// This selects the AES implementation written by Ideetroon for their +// own LoRaWAN library. It also uses lookup tables, but smaller +// byte-oriented ones, making it use a lot less flash space (but it is +// also about twice as slow as the original). +// #define USE_IDEETRON_AES diff --git a/src/lorawan.cpp b/src/lorawan.cpp index d7e85d36..3c8fb146 100644 --- a/src/lorawan.cpp +++ b/src/lorawan.cpp @@ -10,13 +10,22 @@ osjob_t sendjob; QueueHandle_t LoraSendQueue; // LMIC enhanced Pin mapping -const lmic_pinmap lmic_pins = {.mosi = PIN_SPI_MOSI, - .miso = PIN_SPI_MISO, - .sck = PIN_SPI_SCK, - .nss = PIN_SPI_SS, - .rxtx = LMIC_UNUSED_PIN, - .rst = RST, - .dio = {DIO0, DIO1, DIO2}}; +const lmic_pinmap lmic_pins = { + .nss = SS, + .rxtx = LMIC_UNUSED_PIN, + .rst = RST, + .dio = {DIO0, DIO1, DIO2} + // optional: set polarity of rxtx pin. + //.rxtx_rx_active = 0, + // optional: set RSSI cal for listen-before-talk + // this value is in dB, and is added to RSSI + // measured prior to decision. + // Must include noise guardband! Ignored in US, + // EU, IN, other markets where LBT is not required. + //.rssi_cal = 0, + // optional: override LMIC_SPI_FREQ if non-zero + //.spi_freq = 0, +}; // DevEUI generator using devices's MAC address void gen_lora_deveui(uint8_t *pdeveui) { @@ -100,7 +109,7 @@ void get_hard_deveui(uint8_t *pdeveui) { uint8_t i2c_ret; // Init this just in case, no more to 100KHz - Wire.begin(I2C_SDA, I2C_SCL, 100000); + Wire.begin(SDA, SCL, 100000); Wire.beginTransmission(MCP_24AA02E64_I2C_ADDRESS); Wire.write(MCP_24AA02E64_MAC_ADDRESS); i2c_ret = Wire.endTransmission(); @@ -149,82 +158,63 @@ void showLoraKeys(void) { void onEvent(ev_t ev) { char buff[24] = ""; - switch (ev) { + case EV_SCAN_TIMEOUT: strcpy_P(buff, PSTR("SCAN TIMEOUT")); break; + case EV_BEACON_FOUND: - strcpy_P(buff, PSTR("BEACON FOUND")); + strcpy_P(buff, PSTR("BEACON_FOUND")); break; + case EV_BEACON_MISSED: - strcpy_P(buff, PSTR("BEACON MISSED")); + strcpy_P(buff, PSTR("BEACON_MISSED")); break; + case EV_BEACON_TRACKED: - strcpy_P(buff, PSTR("BEACON TRACKED")); + strcpy_P(buff, PSTR("BEACON_TRACKED")); break; + case EV_JOINING: strcpy_P(buff, PSTR("JOINING")); break; - case EV_LOST_TSYNC: - strcpy_P(buff, PSTR("LOST TSYNC")); - break; - case EV_RESET: - strcpy_P(buff, PSTR("RESET")); - break; - case EV_RXCOMPLETE: - strcpy_P(buff, PSTR("RX COMPLETE")); - break; - case EV_LINK_DEAD: - strcpy_P(buff, PSTR("LINK DEAD")); - break; - case EV_LINK_ALIVE: - strcpy_P(buff, PSTR("LINK ALIVE")); - break; - case EV_RFU1: - strcpy_P(buff, PSTR("RFUI")); - break; - case EV_JOIN_FAILED: - strcpy_P(buff, PSTR("JOIN FAILED")); - break; - case EV_REJOIN_FAILED: - strcpy_P(buff, PSTR("REJOIN FAILED")); - break; case EV_JOINED: - strcpy_P(buff, PSTR("JOINED")); sprintf(display_line6, " "); // clear previous lmic status - // set data rate adaptation according to saved setting LMIC_setAdrMode(cfg.adrmode); - // set cyclic lmic link check to off if no ADR because is not supported by // ttn (but enabled by lmic after join) LMIC_setLinkCheckMode(cfg.adrmode); - // Set data rate and transmit power (note: txpower seems to be ignored by // the library) switch_lora(cfg.lorasf, cfg.txpower); - // kickoff first send job os_setCallback(&sendjob, lora_send); - // show effective LoRa parameters after join ESP_LOGI(TAG, "ADR=%d, SF=%d, TXPOWER=%d", cfg.adrmode, cfg.lorasf, cfg.txpower); break; - case EV_TXCOMPLETE: + case EV_JOIN_FAILED: + strcpy_P(buff, PSTR("JOIN_FAILED")); + break; + case EV_REJOIN_FAILED: + strcpy_P(buff, PSTR("REJOIN_FAILED")); + break; + + case EV_TXCOMPLETE: strcpy_P(buff, (LMIC.txrxFlags & TXRX_ACK) ? PSTR("RECEIVED ACK") : PSTR("TX COMPLETE")); sprintf(display_line6, " "); // clear previous lmic status if (LMIC.dataLen) { ESP_LOGI(TAG, "Received %d bytes of payload, RSSI %d SNR %d", - LMIC.dataLen, LMIC.rssi, (signed char)LMIC.snr); - sprintf(display_line6, "RSSI %d SNR %d", LMIC.rssi, + LMIC.dataLen, (signed char)LMIC.rssi, (signed char)LMIC.snr); + sprintf(display_line6, "RSSI %d SNR %d", (signed char)LMIC.rssi, (signed char)LMIC.snr); // check if command is received on command port, then call interpreter @@ -234,6 +224,49 @@ void onEvent(ev_t ev) { } break; + case EV_LOST_TSYNC: + strcpy_P(buff, PSTR("LOST_TSYNC")); + break; + + case EV_RESET: + strcpy_P(buff, PSTR("RESET")); + break; + + case EV_RXCOMPLETE: + // data received in ping slot + strcpy_P(buff, PSTR("RX COMPLETE")); + break; + + case EV_LINK_DEAD: + strcpy_P(buff, PSTR("LINK DEAD")); + break; + + case EV_LINK_ALIVE: + strcpy_P(buff, PSTR("LINK ALIVE")); + break; + + case EV_TXSTART: + strcpy_P(buff, PSTR("TX START")); + break; + + /* + || This event is defined but not used in the code. No + || point in wasting codespace on it. + || + || case EV_SCAN_FOUND: + || Serial.println(F("EV_SCAN_FOUND")); + || break; + */ + + /* + || This event is defined but not used in the code. No + || point in wasting codespace on it. + || + || case EV_RFU1: + || Serial.println(F("EV_RFU1")); + || break; + */ + default: sprintf_P(buff, PSTR("UNKNOWN EVENT %d"), ev); break; @@ -244,8 +277,7 @@ void onEvent(ev_t ev) { ESP_LOGI(TAG, "EV_%s", buff); sprintf(display_line7, buff); } - -} // onEvent() +} // helper function to assign LoRa datarates to numeric spreadfactor values void switch_lora(uint8_t sf, uint8_t tx) { @@ -306,7 +338,7 @@ void lora_send(osjob_t *job) { LMIC_setTxData2(SendBuffer.MessagePort, SendBuffer.Message, SendBuffer.MessageSize, (cfg.countermode & 0x02)); ESP_LOGI(TAG, "%d bytes sent to LoRa", SendBuffer.MessageSize); - sprintf(display_line7, "PACKET QUEUED"); + //sprintf(display_line7, "PACKET QUEUED"); } } // reschedule job every 0,5 - 1 sec. including a bit of random to prevent diff --git a/src/main.cpp b/src/main.cpp index c1648a8a..14c03811 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -166,10 +166,7 @@ void setup() { ESP_LOGI(TAG, "Starting LMIC..."); os_init(); // initialize lmic run-time environment on core 1 LMIC_reset(); // initialize lmic MAC - LMIC_setClockError(MAX_CLOCK_ERROR * 1 / - 100); // This tells LMIC to make the receive windows - // bigger, in case your clock is 1% faster or slower. - + LMIC_setClockError(MAX_CLOCK_ERROR * CLOCK_ERROR_PROCENTAGE / 100); LMIC_startJoining(); // start joining #endif diff --git a/src/ota.cpp b/src/ota.cpp index 65ff97c4..465838f5 100644 --- a/src/ota.cpp +++ b/src/ota.cpp @@ -250,7 +250,7 @@ void do_ota_update() { // check whether we have everything for OTA update if (contentLength && isValidContentType) { - size_t written, current, size; + size_t written = 0; if (Update.begin(contentLength)) { #ifdef HAS_DISPLAY @@ -270,7 +270,7 @@ void do_ota_update() { if (written == contentLength) { ESP_LOGI(TAG, "Written %u bytes successfully", written); - snprintf(buf, 17, "%u kB Done!", (uint16_t)(written / 1024)); + snprintf(buf, 17, "%ukB Done!", (uint16_t)(written / 1024)); display(4, "OK", buf); break; } else { @@ -329,7 +329,7 @@ void display(const uint8_t row, const std::string status, #ifdef HAS_DISPLAY // callback function to show download progress while streaming data -void show_progress(size_t current, size_t size) { +void show_progress (unsigned long current, unsigned long size) { char buf[17]; snprintf(buf, 17, "%-9lu (%3lu%%)", current, current * 100 / size); display(4, "**", buf); diff --git a/src/paxcounter.conf b/src/paxcounter.conf index 8c5749d5..e048043f 100644 --- a/src/paxcounter.conf +++ b/src/paxcounter.conf @@ -72,82 +72,4 @@ #define OTA_MIN_BATT 3700 // minimum battery level vor OTA [millivolt] // LMIC settings -// define hardware independent LMIC settings here, settings of standard library in /lmic/config.h will be ignored -// define hardware specifics settings in platformio.ini as build_flag for hardware environment - -// Select frequency band here according to national regulations -#define CFG_eu868 1 -//#define CFG_us915 1 - -// This is the SX1272/SX1273 radio, which is also used on the HopeRF -// RFM92 boards. -//#define CFG_sx1272_radio 1 -// This is the SX1276/SX1277/SX1278/SX1279 radio, which is also used on -// the HopeRF RFM95 boards. -//#define CFG_sx1276_radio 1 - -// 16 μs per tick -// LMIC requires ticks to be 15.5μs - 100 μs long -#define US_PER_OSTICK_EXPONENT 4 -#define US_PER_OSTICK (1 << US_PER_OSTICK_EXPONENT) -#define OSTICKS_PER_SEC (1000000 / US_PER_OSTICK) - -// Set this to 1 to enable some basic debug output (using printf) about -// RF settings used during transmission and reception. Set to 2 to -// enable more verbose output. Make sure that printf is actually -// configured (e.g. on AVR it is not by default), otherwise using it can -// cause crashing. -//#define LMIC_DEBUG_LEVEL 1 - -// Enable this to allow using printf() to print to the given serial port -// (or any other Print object). This can be easy for debugging. The -// current implementation only works on AVR, though. -//#define LMIC_PRINTF_TO Serial - -// Any runtime assertion failures are printed to this serial port (or -// any other Print object). If this is unset, any failures just silently -// halt execution. -#define LMIC_FAILURE_TO Serial - -// Uncomment this to disable all code related to joining -//#define DISABLE_JOIN -// Uncomment this to disable all code related to ping -#define DISABLE_PING -// Uncomment this to disable all code related to beacon tracking. -// Requires ping to be disabled too -#define DISABLE_BEACONS - -// Uncomment these to disable the corresponding MAC commands. -// Class A -//#define DISABLE_MCMD_DCAP_REQ // duty cycle cap -//#define DISABLE_MCMD_DN2P_SET // 2nd DN window param -//#define DISABLE_MCMD_SNCH_REQ // set new channel -// Class B -//#define DISABLE_MCMD_PING_SET // set ping freq, automatically disabled by DISABLE_PING -//#define DISABLE_MCMD_BCNI_ANS // next beacon start, automatical disabled by DISABLE_BEACON - -// In LoRaWAN, a gateway applies I/Q inversion on TX, and nodes do the -// same on RX. This ensures that gateways can talk to nodes and vice -// versa, but gateways will not hear other gateways and nodes will not -// hear other nodes. By uncommenting this macro, this inversion is -// disabled and this node can hear other nodes. If two nodes both have -// this macro set, they can talk to each other (but they can no longer -// hear gateways). This should probably only be used when debugging -// and/or when talking to the radio directly (e.g. like in the "raw" -// example). -//#define DISABLE_INVERT_IQ_ON_RX - -// This allows choosing between multiple included AES implementations. -// Make sure exactly one of these is uncommented. -// -// This selects the original AES implementation included LMIC. This -// implementation is optimized for speed on 32-bit processors using -// fairly big lookup tables, but it takes up big amounts of flash on the -// AVR architecture. -#define USE_ORIGINAL_AES -// -// This selects the AES implementation written by Ideetroon for their -// own LoRaWAN library. It also uses lookup tables, but smaller -// byte-oriented ones, making it use a lot less flash space (but it is -// also about twice as slow as the original). -// #define USE_IDEETRON_AES +// moved to src/lmic_config.h \ No newline at end of file diff --git a/src/spi.cpp b/src/spisend.cpp similarity index 100% rename from src/spi.cpp rename to src/spisend.cpp