project migrated to arduino LMIC 1.6 MCCI
This commit is contained in:
parent
7b666b2737
commit
f670bc1f63
39
LICENSE
39
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 <lpodkalicki@gmail.com>
|
||||
* 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"
|
||||
|
||||
------------------------------------------------------------------------------------------------
|
||||
------------------------------------------------------------------------------------------------
|
@ -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 <A HREF="https://thethingsnetwork.org">TheThingsNetwork</A> 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
|
||||
|
@ -53,7 +53,7 @@ extern std::array<uint64_t, 0xff> 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
|
||||
|
@ -1,5 +1,5 @@
|
||||
#ifndef _GPS_H
|
||||
#define _GPS_H
|
||||
#ifndef _GPSREAD_H
|
||||
#define _GPSREAD_H
|
||||
|
||||
#include <TinyGPS++.h> // library for parsing NMEA data
|
||||
#include <TimeLib.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
|
||||
|
@ -1,5 +1,5 @@
|
||||
#ifndef _SPI_H
|
||||
#define _SPI_H
|
||||
#ifndef _SPISEND_H
|
||||
#define _SPISEND_H
|
||||
|
||||
extern TaskHandle_t SpiTask;
|
||||
extern QueueHandle_t SPISendQueue;
|
@ -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.
|
Binary file not shown.
@ -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!
|
@ -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
|
||||
|
||||
==============================================================================
|
@ -1,9 +0,0 @@
|
||||
name=IBM LMIC framework
|
||||
version=1.5.0+arduino-2
|
||||
author=IBM
|
||||
maintainer=Matthijs Kooijman <matthijs@stdin.nl>
|
||||
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=*
|
@ -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 <http://www.gnu.org/licenses/>.
|
||||
******************************************************************************************/
|
||||
/******************************************************************************************
|
||||
*
|
||||
* 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)
|
@ -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<len) ? buf[t0] : (t0==len) ? 0x80 : 0x00);
|
||||
if((t0&3)==3) {
|
||||
a0 = a1;
|
||||
a1 = a2;
|
||||
a2 = a3;
|
||||
a3 = t1;
|
||||
}
|
||||
}
|
||||
if( mode & AES_MIC ) {
|
||||
a0 ^= AESAUX[0];
|
||||
a1 ^= AESAUX[1];
|
||||
a2 ^= AESAUX[2];
|
||||
a3 ^= AESAUX[3];
|
||||
}
|
||||
}
|
||||
|
||||
// perform AES encryption on block in a0-a3
|
||||
ki = AESKEY;
|
||||
ke = ki + 8*4;
|
||||
a0 ^= ki[0];
|
||||
a1 ^= ki[1];
|
||||
a2 ^= ki[2];
|
||||
a3 ^= ki[3];
|
||||
do {
|
||||
AES_key4 (t1,t2,t3,t0,4);
|
||||
AES_expr4(t1,t2,t3,t0,a0);
|
||||
AES_expr4(t2,t3,t0,t1,a1);
|
||||
AES_expr4(t3,t0,t1,t2,a2);
|
||||
AES_expr4(t0,t1,t2,t3,a3);
|
||||
|
||||
AES_key4 (a1,a2,a3,a0,8);
|
||||
AES_expr4(a1,a2,a3,a0,t0);
|
||||
AES_expr4(a2,a3,a0,a1,t1);
|
||||
AES_expr4(a3,a0,a1,a2,t2);
|
||||
AES_expr4(a0,a1,a2,a3,t3);
|
||||
} while( (ki+=8) < ke );
|
||||
|
||||
AES_key4 (t1,t2,t3,t0,4);
|
||||
AES_expr4(t1,t2,t3,t0,a0);
|
||||
AES_expr4(t2,t3,t0,t1,a1);
|
||||
AES_expr4(t3,t0,t1,t2,a2);
|
||||
AES_expr4(t0,t1,t2,t3,a3);
|
||||
|
||||
AES_expr(a0,t0,t1,t2,t3,8);
|
||||
AES_expr(a1,t1,t2,t3,t0,9);
|
||||
AES_expr(a2,t2,t3,t0,t1,10);
|
||||
AES_expr(a3,t3,t0,t1,t2,11);
|
||||
// result of AES encryption in a0-a3
|
||||
|
||||
if( mode & AES_MIC ) {
|
||||
if( (t1 = (mode & AES_MICSUB) >> 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<t0; t1++) {
|
||||
buf[t1] ^= (a0>>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
|
@ -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)
|
@ -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 <Arduino.h>
|
||||
#include <SPI.h>
|
||||
#include "../lmic.h"
|
||||
#include "hal.h"
|
||||
#include <stdio.h>
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// 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);
|
||||
}
|
@ -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_
|
@ -1,9 +0,0 @@
|
||||
#ifdef __cplusplus
|
||||
extern "C"{
|
||||
#endif
|
||||
|
||||
#include "lmic/lmic.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
@ -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_
|
File diff suppressed because it is too large
Load Diff
@ -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_
|
@ -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<<BCN_INTV_exp };
|
||||
enum { BCN_INTV_ms = BCN_INTV_sec*1000L };
|
||||
enum { BCN_INTV_us = BCN_INTV_ms*1000L };
|
||||
enum { BCN_RESERVE_ms = 2120 }; // space reserved for beacon and NWK management
|
||||
enum { BCN_GUARD_ms = 3000 }; // end of beacon period to prevent interference with beacon
|
||||
enum { BCN_SLOT_SPAN_ms = 30 }; // 2^12 reception slots a this span
|
||||
enum { BCN_WINDOW_ms = BCN_INTV_ms-(int)BCN_GUARD_ms-(int)BCN_RESERVE_ms };
|
||||
enum { BCN_RESERVE_us = 2120000 };
|
||||
enum { BCN_GUARD_us = 3000000 };
|
||||
enum { BCN_SLOT_SPAN_us = 30000 };
|
||||
|
||||
#if defined(CFG_eu868) // ==============================================
|
||||
|
||||
enum _dr_eu868_t { DR_SF12=0, DR_SF11, DR_SF10, DR_SF9, DR_SF8, DR_SF7, DR_SF7B, DR_FSK, DR_NONE };
|
||||
enum { DR_DFLTMIN = DR_SF7 };
|
||||
enum { DR_PAGE = DR_PAGE_EU868 };
|
||||
|
||||
// Default frequency plan for EU 868MHz ISM band
|
||||
// Bands:
|
||||
// g1 : 1% 14dBm
|
||||
// g2 : 0.1% 14dBm
|
||||
// g3 : 10% 27dBm
|
||||
// freq band datarates
|
||||
enum { EU868_F1 = 868100000, // g1 SF7-12
|
||||
EU868_F2 = 868300000, // g1 SF7-12 FSK SF7/250
|
||||
EU868_F3 = 868500000, // g1 SF7-12
|
||||
EU868_F4 = 868850000, // g2 SF7-12
|
||||
EU868_F5 = 869050000, // g2 SF7-12
|
||||
EU868_F6 = 869525000, // g3 SF7-12
|
||||
EU868_J4 = 864100000, // g2 SF7-12 used during join
|
||||
EU868_J5 = 864300000, // g2 SF7-12 ditto
|
||||
EU868_J6 = 864500000, // g2 SF7-12 ditto
|
||||
};
|
||||
enum { EU868_FREQ_MIN = 863000000,
|
||||
EU868_FREQ_MAX = 870000000 };
|
||||
|
||||
enum { CHNL_PING = 5 };
|
||||
enum { FREQ_PING = EU868_F6 }; // default ping freq
|
||||
enum { DR_PING = DR_SF9 }; // default ping DR
|
||||
enum { CHNL_DNW2 = 5 };
|
||||
enum { FREQ_DNW2 = EU868_F6 };
|
||||
enum { DR_DNW2 = DR_SF12 };
|
||||
enum { CHNL_BCN = 5 };
|
||||
enum { FREQ_BCN = EU868_F6 };
|
||||
enum { DR_BCN = DR_SF9 };
|
||||
enum { AIRTIME_BCN = 144384 }; // micros
|
||||
|
||||
enum {
|
||||
// Beacon frame format EU SF9
|
||||
OFF_BCN_NETID = 0,
|
||||
OFF_BCN_TIME = 3,
|
||||
OFF_BCN_CRC1 = 7,
|
||||
OFF_BCN_INFO = 8,
|
||||
OFF_BCN_LAT = 9,
|
||||
OFF_BCN_LON = 12,
|
||||
OFF_BCN_CRC2 = 15,
|
||||
LEN_BCN = 17
|
||||
};
|
||||
|
||||
#elif defined(CFG_us915) // =========================================
|
||||
|
||||
enum _dr_us915_t { DR_SF10=0, DR_SF9, DR_SF8, DR_SF7, DR_SF8C, DR_NONE,
|
||||
// Devices behind a router:
|
||||
DR_SF12CR=8, DR_SF11CR, DR_SF10CR, DR_SF9CR, DR_SF8CR, DR_SF7CR };
|
||||
enum { DR_DFLTMIN = DR_SF8C };
|
||||
enum { DR_PAGE = DR_PAGE_US915 };
|
||||
|
||||
// Default frequency plan for US 915MHz
|
||||
enum { US915_125kHz_UPFBASE = 902300000,
|
||||
US915_125kHz_UPFSTEP = 200000,
|
||||
US915_500kHz_UPFBASE = 903000000,
|
||||
US915_500kHz_UPFSTEP = 1600000,
|
||||
US915_500kHz_DNFBASE = 923300000,
|
||||
US915_500kHz_DNFSTEP = 600000
|
||||
};
|
||||
enum { US915_FREQ_MIN = 902000000,
|
||||
US915_FREQ_MAX = 928000000 };
|
||||
|
||||
enum { CHNL_PING = 0 }; // used only for default init of state (follows beacon - rotating)
|
||||
enum { FREQ_PING = US915_500kHz_DNFBASE + CHNL_PING*US915_500kHz_DNFSTEP }; // default ping freq
|
||||
enum { DR_PING = DR_SF10CR }; // default ping DR
|
||||
enum { CHNL_DNW2 = 0 };
|
||||
enum { FREQ_DNW2 = US915_500kHz_DNFBASE + CHNL_DNW2*US915_500kHz_DNFSTEP };
|
||||
enum { DR_DNW2 = DR_SF12CR };
|
||||
enum { CHNL_BCN = 0 }; // used only for default init of state (rotating beacon scheme)
|
||||
enum { DR_BCN = DR_SF10CR };
|
||||
enum { AIRTIME_BCN = 72192 }; // micros
|
||||
|
||||
enum {
|
||||
// Beacon frame format US SF10
|
||||
OFF_BCN_NETID = 0,
|
||||
OFF_BCN_TIME = 3,
|
||||
OFF_BCN_CRC1 = 7,
|
||||
OFF_BCN_INFO = 9,
|
||||
OFF_BCN_LAT = 10,
|
||||
OFF_BCN_LON = 13,
|
||||
OFF_BCN_RFU1 = 16,
|
||||
OFF_BCN_CRC2 = 17,
|
||||
LEN_BCN = 19
|
||||
};
|
||||
|
||||
#endif // ===================================================
|
||||
|
||||
enum {
|
||||
// Join Request frame format
|
||||
OFF_JR_HDR = 0,
|
||||
OFF_JR_ARTEUI = 1,
|
||||
OFF_JR_DEVEUI = 9,
|
||||
OFF_JR_DEVNONCE = 17,
|
||||
OFF_JR_MIC = 19,
|
||||
LEN_JR = 23
|
||||
};
|
||||
enum {
|
||||
// Join Accept frame format
|
||||
OFF_JA_HDR = 0,
|
||||
OFF_JA_ARTNONCE = 1,
|
||||
OFF_JA_NETID = 4,
|
||||
OFF_JA_DEVADDR = 7,
|
||||
OFF_JA_RFU = 11,
|
||||
OFF_JA_DLSET = 11,
|
||||
OFF_JA_RXDLY = 12,
|
||||
OFF_CFLIST = 13,
|
||||
LEN_JA = 17,
|
||||
LEN_JAEXT = 17+16
|
||||
};
|
||||
enum {
|
||||
// Data frame format
|
||||
OFF_DAT_HDR = 0,
|
||||
OFF_DAT_ADDR = 1,
|
||||
OFF_DAT_FCT = 5,
|
||||
OFF_DAT_SEQNO = 6,
|
||||
OFF_DAT_OPTS = 8,
|
||||
};
|
||||
enum { MAX_LEN_PAYLOAD = MAX_LEN_FRAME-(int)OFF_DAT_OPTS-4 };
|
||||
enum {
|
||||
// Bitfields in frame format octet
|
||||
HDR_FTYPE = 0xE0,
|
||||
HDR_RFU = 0x1C,
|
||||
HDR_MAJOR = 0x03
|
||||
};
|
||||
enum { HDR_FTYPE_DNFLAG = 0x20 }; // flags DN frame except for HDR_FTYPE_PROP
|
||||
enum {
|
||||
// Values of frame type bit field
|
||||
HDR_FTYPE_JREQ = 0x00,
|
||||
HDR_FTYPE_JACC = 0x20,
|
||||
HDR_FTYPE_DAUP = 0x40, // data (unconfirmed) up
|
||||
HDR_FTYPE_DADN = 0x60, // data (unconfirmed) dn
|
||||
HDR_FTYPE_DCUP = 0x80, // data confirmed up
|
||||
HDR_FTYPE_DCDN = 0xA0, // data confirmed dn
|
||||
HDR_FTYPE_REJOIN = 0xC0, // rejoin for roaming
|
||||
HDR_FTYPE_PROP = 0xE0
|
||||
};
|
||||
enum {
|
||||
HDR_MAJOR_V1 = 0x00,
|
||||
};
|
||||
enum {
|
||||
// Bitfields in frame control octet
|
||||
FCT_ADREN = 0x80,
|
||||
FCT_ADRARQ = 0x40,
|
||||
FCT_ACK = 0x20,
|
||||
FCT_MORE = 0x10, // also in DN direction: Class B indicator
|
||||
FCT_OPTLEN = 0x0F,
|
||||
};
|
||||
enum {
|
||||
// In UP direction: signals class B enabled
|
||||
FCT_CLASSB = FCT_MORE
|
||||
};
|
||||
enum {
|
||||
NWKID_MASK = (int)0xFE000000,
|
||||
NWKID_BITS = 7
|
||||
};
|
||||
|
||||
// MAC uplink commands downwlink too
|
||||
enum {
|
||||
// Class A
|
||||
MCMD_LCHK_REQ = 0x02, // - link check request : -
|
||||
MCMD_LADR_ANS = 0x03, // - link ADR answer : u1:7-3:RFU, 3/2/1: pow/DR/Ch ACK
|
||||
MCMD_DCAP_ANS = 0x04, // - duty cycle answer : -
|
||||
MCMD_DN2P_ANS = 0x05, // - 2nd DN slot status : u1:7-2:RFU 1/0:datarate/channel ack
|
||||
MCMD_DEVS_ANS = 0x06, // - device status ans : u1:battery 0,1-254,255=?, u1:7-6:RFU,5-0:margin(-32..31)
|
||||
MCMD_SNCH_ANS = 0x07, // - set new channel : u1: 7-2=RFU, 1/0:DR/freq ACK
|
||||
// Class B
|
||||
MCMD_PING_IND = 0x10, // - pingability indic : u1: 7=RFU, 6-4:interval, 3-0:datarate
|
||||
MCMD_PING_ANS = 0x11, // - ack ping freq : u1: 7-1:RFU, 0:freq ok
|
||||
MCMD_BCNI_REQ = 0x12, // - next beacon start : -
|
||||
};
|
||||
|
||||
// MAC downlink commands
|
||||
enum {
|
||||
// Class A
|
||||
MCMD_LCHK_ANS = 0x02, // link check answer : u1:margin 0-254,255=unknown margin / u1:gwcnt
|
||||
MCMD_LADR_REQ = 0x03, // link ADR request : u1:DR/TXPow, u2:chmask, u1:chpage/repeat
|
||||
MCMD_DCAP_REQ = 0x04, // duty cycle cap : u1:255 dead [7-4]:RFU, [3-0]:cap 2^-k
|
||||
MCMD_DN2P_SET = 0x05, // 2nd DN window param: u1:7-4:RFU/3-0:datarate, u3:freq
|
||||
MCMD_DEVS_REQ = 0x06, // device status req : -
|
||||
MCMD_SNCH_REQ = 0x07, // set new channel : u1:chidx, u3:freq, u1:DRrange
|
||||
// Class B
|
||||
MCMD_PING_SET = 0x11, // set ping freq : u3: freq
|
||||
MCMD_BCNI_ANS = 0x12, // next beacon start : u2: delay(in TUNIT millis), u1:channel
|
||||
};
|
||||
|
||||
enum {
|
||||
MCMD_BCNI_TUNIT = 30 // time unit of delay value in millis
|
||||
};
|
||||
enum {
|
||||
MCMD_LADR_ANS_RFU = 0xF8, // RFU bits
|
||||
MCMD_LADR_ANS_POWACK = 0x04, // 0=not supported power level
|
||||
MCMD_LADR_ANS_DRACK = 0x02, // 0=unknown data rate
|
||||
MCMD_LADR_ANS_CHACK = 0x01, // 0=unknown channel enabled
|
||||
};
|
||||
enum {
|
||||
MCMD_DN2P_ANS_RFU = 0xFC, // RFU bits
|
||||
MCMD_DN2P_ANS_DRACK = 0x02, // 0=unknown data rate
|
||||
MCMD_DN2P_ANS_CHACK = 0x01, // 0=unknown channel enabled
|
||||
};
|
||||
enum {
|
||||
MCMD_SNCH_ANS_RFU = 0xFC, // RFU bits
|
||||
MCMD_SNCH_ANS_DRACK = 0x02, // 0=unknown data rate
|
||||
MCMD_SNCH_ANS_FQACK = 0x01, // 0=rejected channel frequency
|
||||
};
|
||||
enum {
|
||||
MCMD_PING_ANS_RFU = 0xFE,
|
||||
MCMD_PING_ANS_FQACK = 0x01
|
||||
};
|
||||
|
||||
enum {
|
||||
MCMD_DEVS_EXT_POWER = 0x00, // external power supply
|
||||
MCMD_DEVS_BATT_MIN = 0x01, // min battery value
|
||||
MCMD_DEVS_BATT_MAX = 0xFE, // max battery value
|
||||
MCMD_DEVS_BATT_NOINFO = 0xFF, // unknown battery level
|
||||
};
|
||||
|
||||
// Bit fields byte#3 of MCMD_LADR_REQ payload
|
||||
enum {
|
||||
MCMD_LADR_CHP_125ON = 0x60, // special channel page enable, bits applied to 64..71
|
||||
MCMD_LADR_CHP_125OFF = 0x70, // ditto
|
||||
MCMD_LADR_N3RFU_MASK = 0x80,
|
||||
MCMD_LADR_CHPAGE_MASK = 0xF0,
|
||||
MCMD_LADR_REPEAT_MASK = 0x0F,
|
||||
MCMD_LADR_REPEAT_1 = 0x01,
|
||||
MCMD_LADR_CHPAGE_1 = 0x10
|
||||
};
|
||||
// Bit fields byte#0 of MCMD_LADR_REQ payload
|
||||
enum {
|
||||
MCMD_LADR_DR_MASK = 0xF0,
|
||||
MCMD_LADR_POW_MASK = 0x0F,
|
||||
MCMD_LADR_DR_SHIFT = 4,
|
||||
MCMD_LADR_POW_SHIFT = 0,
|
||||
#if defined(CFG_eu868)
|
||||
MCMD_LADR_SF12 = DR_SF12<<4,
|
||||
MCMD_LADR_SF11 = DR_SF11<<4,
|
||||
MCMD_LADR_SF10 = DR_SF10<<4,
|
||||
MCMD_LADR_SF9 = DR_SF9 <<4,
|
||||
MCMD_LADR_SF8 = DR_SF8 <<4,
|
||||
MCMD_LADR_SF7 = DR_SF7 <<4,
|
||||
MCMD_LADR_SF7B = DR_SF7B<<4,
|
||||
MCMD_LADR_FSK = DR_FSK <<4,
|
||||
|
||||
MCMD_LADR_20dBm = 0,
|
||||
MCMD_LADR_14dBm = 1,
|
||||
MCMD_LADR_11dBm = 2,
|
||||
MCMD_LADR_8dBm = 3,
|
||||
MCMD_LADR_5dBm = 4,
|
||||
MCMD_LADR_2dBm = 5,
|
||||
#elif defined(CFG_us915)
|
||||
MCMD_LADR_SF10 = DR_SF10<<4,
|
||||
MCMD_LADR_SF9 = DR_SF9 <<4,
|
||||
MCMD_LADR_SF8 = DR_SF8 <<4,
|
||||
MCMD_LADR_SF7 = DR_SF7 <<4,
|
||||
MCMD_LADR_SF8C = DR_SF8C<<4,
|
||||
MCMD_LADR_SF12CR = DR_SF12CR<<4,
|
||||
MCMD_LADR_SF11CR = DR_SF11CR<<4,
|
||||
MCMD_LADR_SF10CR = DR_SF10CR<<4,
|
||||
MCMD_LADR_SF9CR = DR_SF9CR<<4,
|
||||
MCMD_LADR_SF8CR = DR_SF8CR<<4,
|
||||
MCMD_LADR_SF7CR = DR_SF7CR<<4,
|
||||
|
||||
MCMD_LADR_30dBm = 0,
|
||||
MCMD_LADR_28dBm = 1,
|
||||
MCMD_LADR_26dBm = 2,
|
||||
MCMD_LADR_24dBm = 3,
|
||||
MCMD_LADR_22dBm = 4,
|
||||
MCMD_LADR_20dBm = 5,
|
||||
MCMD_LADR_18dBm = 6,
|
||||
MCMD_LADR_16dBm = 7,
|
||||
MCMD_LADR_14dBm = 8,
|
||||
MCMD_LADR_12dBm = 9,
|
||||
MCMD_LADR_10dBm = 10
|
||||
#endif
|
||||
};
|
||||
|
||||
// Device address
|
||||
typedef u4_t devaddr_t;
|
||||
|
||||
// RX quality (device)
|
||||
enum { RSSI_OFF=64, SNR_SCALEUP=4 };
|
||||
|
||||
inline sf_t getSf (rps_t params) { return (sf_t)(params & 0x7); }
|
||||
inline rps_t setSf (rps_t params, sf_t sf) { return (rps_t)((params & ~0x7) | sf); }
|
||||
inline bw_t getBw (rps_t params) { return (bw_t)((params >> 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_
|
@ -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 <stdbool.h>
|
||||
|
||||
// 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);
|
||||
}
|
||||
}
|
@ -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 <stdint.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#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 <string.h>
|
||||
#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 <avr/pgmspace.h>
|
||||
// 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_
|
@ -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<len; i++) {
|
||||
hal_spi(buf[i]);
|
||||
}
|
||||
hal_pin_nss(1);
|
||||
}
|
||||
|
||||
static void readBuf (u1_t addr, xref2u1_t buf, u1_t len) {
|
||||
hal_pin_nss(0);
|
||||
hal_spi(addr & 0x7F);
|
||||
for (u1_t i=0; i<len; i++) {
|
||||
buf[i] = hal_spi(0x00);
|
||||
}
|
||||
hal_pin_nss(1);
|
||||
}
|
||||
|
||||
static void opmode (u1_t mode) {
|
||||
writeReg(RegOpMode, (readReg(RegOpMode) & ~OPMODE_MASK) | mode);
|
||||
}
|
||||
|
||||
static void opmodeLora() {
|
||||
u1_t u = OPMODE_LORA;
|
||||
#ifdef CFG_sx1276_radio
|
||||
u |= 0x8; // TBD: sx1276 high freq
|
||||
#endif
|
||||
writeReg(RegOpMode, u);
|
||||
}
|
||||
|
||||
static void opmodeFSK() {
|
||||
u1_t u = 0;
|
||||
#ifdef CFG_sx1276_radio
|
||||
u |= 0x8; // TBD: sx1276 high freq
|
||||
#endif
|
||||
writeReg(RegOpMode, u);
|
||||
}
|
||||
|
||||
// configure LoRa modem (cfg1, cfg2)
|
||||
static void configLoraModem () {
|
||||
sf_t sf = getSf(LMIC.rps);
|
||||
|
||||
#ifdef CFG_sx1276_radio
|
||||
u1_t mc1 = 0, mc2 = 0, mc3 = 0;
|
||||
|
||||
switch (getBw(LMIC.rps)) {
|
||||
case BW125: mc1 |= SX1276_MC1_BW_125; break;
|
||||
case BW250: mc1 |= SX1276_MC1_BW_250; break;
|
||||
case BW500: mc1 |= SX1276_MC1_BW_500; break;
|
||||
default:
|
||||
ASSERT(0);
|
||||
}
|
||||
switch( getCr(LMIC.rps) ) {
|
||||
case CR_4_5: mc1 |= SX1276_MC1_CR_4_5; break;
|
||||
case CR_4_6: mc1 |= SX1276_MC1_CR_4_6; break;
|
||||
case CR_4_7: mc1 |= SX1276_MC1_CR_4_7; break;
|
||||
case CR_4_8: mc1 |= SX1276_MC1_CR_4_8; break;
|
||||
default:
|
||||
ASSERT(0);
|
||||
}
|
||||
|
||||
if (getIh(LMIC.rps)) {
|
||||
mc1 |= SX1276_MC1_IMPLICIT_HEADER_MODE_ON;
|
||||
writeReg(LORARegPayloadLength, getIh(LMIC.rps)); // required length
|
||||
}
|
||||
// set ModemConfig1
|
||||
writeReg(LORARegModemConfig1, mc1);
|
||||
|
||||
mc2 = (SX1272_MC2_SF7 + ((sf-1)<<4));
|
||||
if (getNocrc(LMIC.rps) == 0) {
|
||||
mc2 |= SX1276_MC2_RX_PAYLOAD_CRCON;
|
||||
}
|
||||
writeReg(LORARegModemConfig2, mc2);
|
||||
|
||||
mc3 = SX1276_MC3_AGCAUTO;
|
||||
if ((sf == SF11 || sf == SF12) && getBw(LMIC.rps) == BW125) {
|
||||
mc3 |= SX1276_MC3_LOW_DATA_RATE_OPTIMIZE;
|
||||
}
|
||||
writeReg(LORARegModemConfig3, mc3);
|
||||
#elif CFG_sx1272_radio
|
||||
u1_t mc1 = (getBw(LMIC.rps)<<6);
|
||||
|
||||
switch( getCr(LMIC.rps) ) {
|
||||
case CR_4_5: mc1 |= SX1272_MC1_CR_4_5; break;
|
||||
case CR_4_6: mc1 |= SX1272_MC1_CR_4_6; break;
|
||||
case CR_4_7: mc1 |= SX1272_MC1_CR_4_7; break;
|
||||
case CR_4_8: mc1 |= SX1272_MC1_CR_4_8; break;
|
||||
}
|
||||
|
||||
if ((sf == SF11 || sf == SF12) && getBw(LMIC.rps) == BW125) {
|
||||
mc1 |= SX1272_MC1_LOW_DATA_RATE_OPTIMIZE;
|
||||
}
|
||||
|
||||
if (getNocrc(LMIC.rps) == 0) {
|
||||
mc1 |= SX1272_MC1_RX_PAYLOAD_CRCON;
|
||||
}
|
||||
|
||||
if (getIh(LMIC.rps)) {
|
||||
mc1 |= SX1272_MC1_IMPLICIT_HEADER_MODE_ON;
|
||||
writeReg(LORARegPayloadLength, getIh(LMIC.rps)); // required length
|
||||
}
|
||||
// set ModemConfig1
|
||||
writeReg(LORARegModemConfig1, mc1);
|
||||
|
||||
// set ModemConfig2 (sf, AgcAutoOn=1 SymbTimeoutHi=00)
|
||||
writeReg(LORARegModemConfig2, (SX1272_MC2_SF7 + ((sf-1)<<4)) | 0x04);
|
||||
#else
|
||||
#error Missing CFG_sx1272_radio/CFG_sx1276_radio
|
||||
#endif /* CFG_sx1272_radio */
|
||||
}
|
||||
|
||||
static void configChannel () {
|
||||
// set frequency: FQ = (FRF * 32 Mhz) / (2 ^ 19)
|
||||
uint64_t frf = ((uint64_t)LMIC.freq << 19) / 32000000;
|
||||
writeReg(RegFrfMsb, (u1_t)(frf>>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();
|
||||
}
|
@ -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}
|
||||
|
@ -4,7 +4,7 @@
|
||||
#include "globals.h"
|
||||
#include <esp_spi_flash.h> // 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)
|
||||
|
@ -1,21 +1,22 @@
|
||||
#ifndef _EBOX_H
|
||||
#define _EBOX_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
// 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)
|
||||
#endif
|
@ -1,22 +1,23 @@
|
||||
#ifndef _EBOXTUBE_H
|
||||
#define _EBOXTUBE_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
// 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)
|
||||
#endif
|
@ -1,3 +1,8 @@
|
||||
#ifndef _FIPY_H
|
||||
#define _FIPY_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
// 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
|
||||
|
@ -1,3 +1,8 @@
|
||||
#ifndef _GENERIC_H
|
||||
#define _GENERIC_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
// 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
|
||||
#define MCP_24AA02E64_MAC_ADDRESS 0xF8 // Memory adress of unique deveui 64 bits
|
||||
|
||||
#endif
|
@ -1,3 +1,8 @@
|
||||
#ifndef _HELTEC_H
|
||||
#define _HELTEC_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
// 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
|
||||
|
@ -1,3 +1,8 @@
|
||||
#ifndef _HELTECV2_H
|
||||
#define _HELTECV2_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
// 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
|
||||
#endif
|
@ -1,3 +1,8 @@
|
||||
#ifndef _LOLINLITE_H
|
||||
#define _LOLINLITE_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
// 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
|
||||
#define HAS_SPI 1 // comment out if device shall not send data via SPI
|
||||
|
||||
#endif
|
@ -1,3 +1,8 @@
|
||||
#ifndef _LOLINLITELORA_H
|
||||
#define _LOLINLITELORA_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
// 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
|
||||
|
@ -1,3 +1,8 @@
|
||||
#ifndef _LOLINLORA_H
|
||||
#define _LOLINLORA_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
// 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
|
||||
|
@ -1,23 +1,32 @@
|
||||
#ifndef _LOPY_H
|
||||
#define _LOPY_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
// 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
|
||||
|
@ -1,24 +1,25 @@
|
||||
#ifndef _LOPY4_H
|
||||
#define _LOPY4_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
// 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
|
||||
//#define BATT_FACTOR 4 // voltage divider 115kOhm/56kOhm -> expansion board 2.0
|
||||
|
||||
#endif
|
@ -1,3 +1,8 @@
|
||||
#ifndef _OCTOPUS_H
|
||||
#define _OCTOPUS_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
// 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
|
||||
|
@ -1,3 +1,8 @@
|
||||
#ifndef _TTGOBEAM_H
|
||||
#define _TTGOBEAM_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
// 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
|
||||
|
@ -1,3 +1,8 @@
|
||||
#ifndef _TTGOV1_H
|
||||
#define _TTGOV1_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
// 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
|
||||
|
@ -1,3 +1,8 @@
|
||||
#ifndef _TTGOV2_H
|
||||
#define _TTGOV2_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
// 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.
|
||||
*/
|
||||
#endif
|
@ -1,3 +1,8 @@
|
||||
#ifndef _TTGOV21NEW_H
|
||||
#define _TTGOV21NEW_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
/* 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
|
||||
#endif
|
@ -1,3 +1,9 @@
|
||||
#ifndef _TTGOV21OLD_H
|
||||
#define _TTGOV21OLD_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
|
||||
/* 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
|
@ -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
|
128
src/lorawan.cpp
128
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
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
|
@ -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
|
Loading…
Reference in New Issue
Block a user