The upstream version is 1.5, the .0 is added to comply with Arduino
semantic versioning requirements. And additional +arduino-0 version
number is added, which will be used to track changes in the
arduino-specific part of this library.
This adds a lot more documentation, and reflects the fact that this
library should now be usable for actual projects as well, not just for
node-node prototypes.
This sketch is aimed at The Things Network, but it should work for other
networks as well. It employs personalization, over-the-air activation
has not been tested yet.
This:
- Removes support for the Pinoccio Scout RGB led and just uses a single
led (using LED_BUILTIN) on all boards.
- Fixes some indentation.
- Uses a constant for the TX interval, and increases it to comply with
the duty cycle limits.
- Uses more explicit radio settings, instead of referring to the "ping"
settings defined by LMIC.
- Uses os_runloop_once() instead of os_runloop(), so the example can be
more easily modified to do other things in addition to radio RX and
TX.
- Shows how to use LMIC_UNUSED_PIN for unused pins.
This should decrease the likelyhood of a naming conflict, and making it
const might help the compiler optimize.
In the future, configuring pins might change to use some initialization
function to pass the pin mapping, but for now this approach seems simple
and efficient.
By uncommenting a maco in config.h, this inversion is enabled, and
communication between nodes can be enabled. This should be used just for
debugging, though.
These functions convert four individiual bytes from a buffer into a
32-bit integer. The upper two bytes were cast to u4_t before being
shifted in place, but not the lower bytes. It seems that this was not
needed, since even when int is 16-bits, shifting a byte by 8 will not
cause any bits to "fall off". However, a problem with sign-extension
would occur in some cases.
The problematic expression is:
return (u4_t)(buf[0] | (buf[1]<<8) | ((u4_t)buf[2]<<16) | ((u4_t)buf[3]<<24));
Here, `buf[1]` would be integer-promoted before shifting. It is
promoted to a *signed* `int`, since the original `u1_t` type is small
enough to fit in there. Now, if the MSB of `buf[1]` is 1, it is then
shifted to become the MSB (i.e. sign bit) of the resulting *signed*
integer. Then, before the bitwise-or operator is applied, this value is
extended to 32-bits, since the right operand is 32-bit. Since the
left-hand side is signed, it is sign-extended, causing all upper 16 bits
to become 1, making them also 1 in the resulting value.
To fix this, all bytes are first explicitely cast to `u4_t` to make sure
they are already big enough and remain unsigned. For consistency, the
same is done for `os_rlsbf2()`, even though this same problem cannot
occur there (C guarantees that an int is at least 16-bits wide).
This causes these commands to be silently ignored, but they are
recognized and skipped, so MAC commands coming after them can still be
processed.
Not all commands can be disabled, since commands like ADR are typically
needed to prevent nodes from interfering with proper network operation.
This allows disabling joining (over the air activation), beacon tracking
and ping reception. Disabling these shrinks the code by a fair bit, so this
is interesting for low-memory applications that do not need these
things.
This can also disable processing of some MAC commands. They are silently
ignored, but they are recognized and skipped, so MAC commands coming
after them can still be processed.
By default, LMIC uses 6 standard channels for joining and 3 standard
channels for normal operation which are defined in the LoRaWAN
specification. On top of that, it defines 3 additional channels.
However, in practice it turns out that 3 of the 6 joining channels are
not actually used by gateway, and neither are the 3 additional channels
for normal operation. To maximize default operability, this commit
reduces the default channels list to just (the same) 3 channels for both
joining and normal operation (but at different duty cycles).
Extra channels can be configured from the sketch, using
LMIC_setupChannel(), and the example sketches will be modifed according
to this.
When micros() overflows, the LMIC tick value would make big jump back to
zero, which caused the library to grind to a halt (waiting for timer
values that never occurred). This fixes by detecting overflows and
virtually extending the tick counter with a few bits.
When figuring out what band and channel is available next, nextTx loops
over all bands to find the one with the earliest available time. The
mintime variable, that records this minimal time, is initialized to
large value, namely 10 hours from now, to ensure that all available
times will be earlier than that.
However, when TICKS_PER_SECOND is big, 10 hours converted to ticks
overflows the range of ostime_t (32-bit signed integer). Instead of
making all comparisons with this value succeed, this causes all of them
to fail, which makes nextTx run in an infinite loop trying to find an
available band.
This problem occurs when TICKS_PER_SECOND is 59653 or more, which
corresponds to a US_PER_TICK of 16.76 or less. The documented range for
TICKS_PER_SECOND is 10000-64516, so this is affects just the upper
range, which is probably why this bug was not found before.
This commit changes the large initial value from 10 to 8 hours, which is
small enough to fit over the full range for TICKS_PER_SECOND, so this
should no longer occur.
When compiling for an Arduino Uno, this saves 4546 bytes of RAM (5860 -> 1214)
at the expense of 302 additional bytes of code. Most of this additional
code is used by the AES implementation, probably because the use of
special PROGMEM loading instructions reduces the optimization's freedom
with regard to instruction ordering and register assignment.
This should not change any behaviour right now, but makes it easier to
introduce custom constant lookup code in a single spot (e.g. to put
tables in PROGMEM on AVR). To prevent accidental direct access of the
tables, their name is mangled by the macros. To prevent using the wrong
accessor macro (for another array element type), the accessor macros use
an inline function to actually return the values.
Note that the generated code is not totally identical, since the inline
functions seem to cause gcc to take different optimization decisions. On
AVR, this commit actually shrinks the compiled program by hundred bytes
or so.
This declares the onEvent() callback function that must be defined by an
application. Previously, the application was expected to define this
itself, and a reference to it was declared in lmic.c.
By moving the declaration into lmic.h, this prevents problems when an
application uses a different function signature for the function, or
when defining the callback in a C++ file (which will now be compiled as
a C function automatically).
This simplifies debug printing in .c files, which do not have access to
the Serial C++ object. To use this, just include stdio.h and call
printf. This replaces the `debug()` and `debug_str()` functions that
were previously present.
This support can be disabled in config.h, which saves some flash space
(but note that this also makes failed assertions silent!).
The AES_S array contains 16-bit integers, which are shifted upwards
during processing. On platforms where int is 32-bit or wider, these
integers are integer-promoted to 32-bit before shifting, making them
work as expected. On smaller platforms, this does not happen, causing
the upper 16 bits to be shifted off before the value is converted to a
32-bit integer.
By manually casting these values to 32-bit before shifting, this issue
is prevented.
It seems there was a typo in a constant, causing the CENTI band starting
channel to be randomized twice, while the initial channel for the DECI
band was left unset (so presumably 0).
This fixes the code to properly randomize the channel again.
This adds the "lmic" and "doc" directories from lmic-release-v1.5.zip as
downloaded from IBM. The other directories ("stm32" containing the HAL for
stm32 boards and "examples", containing plain C examples) are left out.
All text files were converted to unix line endings and had trailing
whitespace stripped, so it's easier for git to handle them.
dos2unix src/lmic/* doc/*.txt
sed -i 's/\s*$//' src/lmic/* doc/*.txt
This is Arduino-specific, so it should be removed in the upstream
branch. This will probably cause this file to be removed in the next
merg with the upstream branch, so it should be re-added there.
By setting some more parameters (frequency, txpower), RX and TX now work
properly. Whenever a packet is received, reception is now restarted.
It now also updates leds to indicate reception status. The led is red (on
Pinoccio, or off for normal Arduino boards) when no packet was received
in 2500ms, green (or off) when there was. Whenever a packet is received, the LED
very briefly blinks to indicate this.
Packets are sent about once every second. When a packet is received, the
next TX is rescheduled to prevent TX collisions (in a very basic way).
Since we're using this libary for initial testing of the LoRa modules,
we need node-to-node communication without any gateways or servers
involved.
This change will break downstream LoRaWAN communication.
Previously, DR_PING was initialized to SF9. However, the value is used
as a datarate index, not as the raw Spreading Factor to send to the
modem, so it should use DR_SF9 instead.
Because both constants have the same value, this commit does not change
any behaviour. However, all of the other spreading factor constants do
have different values from the DR_ equivalents, so if the value would be
changed, things could become unexpected.
This implements all HAL functions using the Arduino environment. Since
we cannot guarantee that interrupts are actually available on all DIO
pins, this implements the interrupt stuff by polling on every loop
invocation.
Instead of using char/short/int/long, use the types inside stdint.h to
get specific length types. This allows using the library on
architectures with non-standard integer sizes, such as AVR.
This allows including the lmic library from an Arduino sketch using
just #include <lmic.h>. This includes the necessary header file and
makes it work also from C++.
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.