project migrated to arduino LMIC 1.6 MCCI

This commit is contained in:
Klaus K Wilting 2018-10-21 19:00:20 +02:00
parent 7b666b2737
commit f670bc1f63
50 changed files with 553 additions and 6547 deletions

39
LICENSE
View File

@ -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"
------------------------------------------------------------------------------------------------
------------------------------------------------------------------------------------------------

View File

@ -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

View File

@ -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

View File

@ -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>

View File

@ -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

View File

@ -1,5 +1,5 @@
#ifndef _SPI_H
#define _SPI_H
#ifndef _SPISEND_H
#define _SPISEND_H
extern TaskHandle_t SpiTask;
extern QueueHandle_t SPISendQueue;

View File

@ -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.

View File

@ -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!

View File

@ -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
==============================================================================

View File

@ -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=*

View File

@ -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)

View File

@ -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

View File

@ -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)

View File

@ -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);
}

View File

@ -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_

View File

@ -1,9 +0,0 @@
#ifdef __cplusplus
extern "C"{
#endif
#include "lmic/lmic.h"
#ifdef __cplusplus
}
#endif

View File

@ -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

View File

@ -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_

View File

@ -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_

View File

@ -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);
}
}

View File

@ -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_

View File

@ -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();
}

View File

@ -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}

View File

@ -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)

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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);

View File

@ -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