IBM LoRa MAC in C (LMiC) mbed library port

Dependents:   lora-temperature LoRaWAN-lmic-app_HS LoRaWAN-lmic-app_huynh

LoRa WAN in C for sx1276 shield

Currently version 1.5


LoRaWAN network configuration for end-device

The following three pieces of information uniquely identifies end-device to network to allow over-the-air activation. These are stored in the end-device prior to join procedure.

AppEUI

Uniquely identifies application provider of end-device.

Least-significant byte first, 8 bytes, use reverse memcpy() to keep same order as shown on lora server.

example C code

static const u1_t APPEUI[8]  = { 0x01, 0x00, 0x01, 0x00, 0x00, 0x0C, 0x25, 0x00 };

This is copied into LMIC by os_getArtEui() callback function in application.

DevEUI

End-device ID, unique to each end-node.

Least-significant byte first, 8 bytes, use reverse memcpy() to keep same order as shown on lora server.

example C code

static const u1_t DEVEUI[8]  = { 0x00, 0x00, 0x00, 0x00, 0x01, 0x0C, 0x25, 0x00 }; 

This is copied into LMIC by os_getDevEui() callback function in application.

AppKey (aka DevKey)

128-bit (16byte) AES key.

example C code

static const u1_t DEVKEY[16] = { 0xe4, 0x72, 0x71, 0xc5, 0xf5, 0x30, 0xa9, 0x9f, 0xcf, 0xc4, 0x0e, 0xab, 0xea, 0xd7, 0x19, 0x42 };

This is copied into LMIC by os_getDevKey() callback function in application.

Using over-the air activation, the end-device (LMIC) performs a join procedure every time it starts for first time, or has lost session context information. When join procedure has successfully completed, the end-device will have a network session key (NwkSKey) and an application session key (AppSKey), which are used for encryption and message integrity check.


US915 configuration with http://us01-iot.semtech.com/

  • log in to server
  • click on Applications
  • find your application and click it
  • go to configure motes
  • to create a mote, you may enter a new DevEUI
    • you may copy-paste the 16byte application key from an already existing mote, if you desire.
CHNL_HYBRID125KHz500KHz
defined valuechannelschannel
00 to 764
18 to 1565
216 to 2366
324 to 3167
432 to 3968
540 to 4769
648 to 5570
756 to 6371
undef0 to 6364 to 71
Committer:
mluis
Date:
Thu Jan 22 12:50:49 2015 +0000
Revision:
0:62d1edcc13d1
Child:
1:d3b7bde3995c
Porting of IBM LoRa MAC in C (LMiC) to the mbed platform.

Who changed what in which revision?

UserRevisionLine numberNew contents of line
mluis 0:62d1edcc13d1 1 /*******************************************************************************
mluis 0:62d1edcc13d1 2 * Copyright (c) 2014 IBM Corporation.
mluis 0:62d1edcc13d1 3 * All rights reserved. This program and the accompanying materials
mluis 0:62d1edcc13d1 4 * are made available under the terms of the Eclipse Public License v1.0
mluis 0:62d1edcc13d1 5 * which accompanies this distribution, and is available at
mluis 0:62d1edcc13d1 6 * http://www.eclipse.org/legal/epl-v10.html
mluis 0:62d1edcc13d1 7 *
mluis 0:62d1edcc13d1 8 * Contributors:
mluis 0:62d1edcc13d1 9 * IBM Zurich Research Lab - initial API, implementation and documentation
mluis 0:62d1edcc13d1 10 *******************************************************************************/
mluis 0:62d1edcc13d1 11
mluis 0:62d1edcc13d1 12 #define NEW_CHNL 1
mluis 0:62d1edcc13d1 13
mluis 0:62d1edcc13d1 14 #ifndef _lmic_h_
mluis 0:62d1edcc13d1 15 #define _lmic_h_
mluis 0:62d1edcc13d1 16
mluis 0:62d1edcc13d1 17 #define CFG_DEBUG 1
mluis 0:62d1edcc13d1 18 #define CFG_eu868 1
mluis 0:62d1edcc13d1 19 //#define CFG_us915 0
mluis 0:62d1edcc13d1 20
mluis 0:62d1edcc13d1 21 #define USE_SMTC_RADIO_DRIVER 1
mluis 0:62d1edcc13d1 22
mluis 0:62d1edcc13d1 23 //#define CFG_sx1272_radio 0
mluis 0:62d1edcc13d1 24 #define CFG_sx1276_radio 1
mluis 0:62d1edcc13d1 25
mluis 0:62d1edcc13d1 26 #include "mbed.h"
mluis 0:62d1edcc13d1 27 #include "oslmic.h"
mluis 0:62d1edcc13d1 28 #include "lorabase.h"
mluis 0:62d1edcc13d1 29
mluis 0:62d1edcc13d1 30 enum { MAX_FRAME_LEN = 64 }; // Library cap on max frame length
mluis 0:62d1edcc13d1 31 enum { TXCONF_ATTEMPTS = 8 }; // transmit attempts for confirmed frames
mluis 0:62d1edcc13d1 32 enum { MAX_MISSED_BCNS = 20 }; // threshold for triggering rejoin requests
mluis 0:62d1edcc13d1 33 enum { MAX_RXSYMS = 100 }; // stop tracking beacon beyond this
mluis 0:62d1edcc13d1 34
mluis 0:62d1edcc13d1 35 enum { LINK_CHECK_CONT = 6 }; // continue with this after reported dead link
mluis 0:62d1edcc13d1 36 enum { LINK_CHECK_DEAD = 12 }; // after this UP frames and no response from NWK assume link is dead
mluis 0:62d1edcc13d1 37 enum { LINK_CHECK_INIT = -12 }; // UP frame count until we inc datarate
mluis 0:62d1edcc13d1 38
mluis 0:62d1edcc13d1 39 enum { TIME_RESYNC = 6*128 }; // secs
mluis 0:62d1edcc13d1 40 enum { TXRX_GUARD_ms = 6000 }; // msecs - don't start TX-RX transaction before beacon
mluis 0:62d1edcc13d1 41 enum { JOIN_GUARD_ms = 9000 }; // msecs - don't start Join Req/Acc transaction before beacon
mluis 0:62d1edcc13d1 42 enum { TXRX_BCNEXT_secs = 2 }; // secs - earliest start after beacon time
mluis 0:62d1edcc13d1 43 enum { RETRY_PERIOD_secs = 3 }; // secs - random period for retrying a confirmed send
mluis 0:62d1edcc13d1 44
mluis 0:62d1edcc13d1 45 #if CFG_eu868 // EU868 spectrum ====================================================
mluis 0:62d1edcc13d1 46
mluis 0:62d1edcc13d1 47 enum { MAX_CHANNELS = 8 }; // library may not support all 16 channels
mluis 0:62d1edcc13d1 48 enum { MAX_BANDS = 4 };
mluis 0:62d1edcc13d1 49
mluis 0:62d1edcc13d1 50 enum { LIMIT_CHANNELS = (1<<4) }; // EU868 will never have more channels
mluis 0:62d1edcc13d1 51 struct band_t {
mluis 0:62d1edcc13d1 52 u2_t txcap; // duty cycle limitation: 1/txcap
mluis 0:62d1edcc13d1 53 s1_t txpow; // maximum TX power
mluis 0:62d1edcc13d1 54 ostime_t avail; // channel is blocked until this time
mluis 0:62d1edcc13d1 55 };
mluis 0:62d1edcc13d1 56 TYPEDEF_xref2band_t;
mluis 0:62d1edcc13d1 57
mluis 0:62d1edcc13d1 58 #elif CFG_us915 // US915 spectrum =================================================
mluis 0:62d1edcc13d1 59
mluis 0:62d1edcc13d1 60 enum { MAX_XCHANNELS = 2 }; // extra channels in RAM, channels 0-71 are immutable
mluis 0:62d1edcc13d1 61 enum { MAX_TXPOW_125kHz = 30 };
mluis 0:62d1edcc13d1 62
mluis 0:62d1edcc13d1 63 #endif // ==========================================================================
mluis 0:62d1edcc13d1 64
mluis 0:62d1edcc13d1 65 // Keep in sync with evdefs.hpp::drChange
mluis 0:62d1edcc13d1 66 enum { DRCHG_SET, DRCHG_NOJACC, DRCHG_NOACK, DRCHG_NOADRACK, DRCHG_NWKCMD };
mluis 0:62d1edcc13d1 67 enum { KEEP_TXPOW = -128 };
mluis 0:62d1edcc13d1 68
mluis 0:62d1edcc13d1 69
mluis 0:62d1edcc13d1 70 struct rxsched_t {
mluis 0:62d1edcc13d1 71 u1_t dr;
mluis 0:62d1edcc13d1 72 u1_t intvExp; // 0..7
mluis 0:62d1edcc13d1 73 u1_t slot; // runs from 0 to 128
mluis 0:62d1edcc13d1 74 u1_t rxsyms;
mluis 0:62d1edcc13d1 75 ostime_t rxbase;
mluis 0:62d1edcc13d1 76 ostime_t rxtime; // start of next spot
mluis 0:62d1edcc13d1 77 u4_t freq;
mluis 0:62d1edcc13d1 78 };
mluis 0:62d1edcc13d1 79 TYPEDEF_xref2rxsched_t;
mluis 0:62d1edcc13d1 80
mluis 0:62d1edcc13d1 81
mluis 0:62d1edcc13d1 82 // Information extracted from (last) beacon
mluis 0:62d1edcc13d1 83 enum { BCN_NONE = 0x00,
mluis 0:62d1edcc13d1 84 BCN_PARTIAL = 0x01,
mluis 0:62d1edcc13d1 85 BCN_FULL = 0x02,
mluis 0:62d1edcc13d1 86 BCN_NODRIFT = 0x04, // no drift value measured
mluis 0:62d1edcc13d1 87 BCN_NODDIFF = 0x08 }; // no differential drift measured yet
mluis 0:62d1edcc13d1 88 struct bcninfo_t {
mluis 0:62d1edcc13d1 89 rxqu_t rxq;
mluis 0:62d1edcc13d1 90 ostime_t txtime; // time when beacon was sent
mluis 0:62d1edcc13d1 91 u1_t flags;
mluis 0:62d1edcc13d1 92 u4_t time; // GPS time in seconds
mluis 0:62d1edcc13d1 93 // This part is valid only if flags==BCN_FULL
mluis 0:62d1edcc13d1 94 u1_t info; // info field
mluis 0:62d1edcc13d1 95 s4_t lat;
mluis 0:62d1edcc13d1 96 s4_t lon;
mluis 0:62d1edcc13d1 97 };
mluis 0:62d1edcc13d1 98
mluis 0:62d1edcc13d1 99 // purpose of receive window - lmic_t.rxState
mluis 0:62d1edcc13d1 100 enum { RADIO_RST=0, RADIO_TX=1, RADIO_RX=2, RADIO_RXON=3 };
mluis 0:62d1edcc13d1 101 // Netid values / lmic_t.netid
mluis 0:62d1edcc13d1 102 enum { NETID_NONE=(int)~0U, NETID_MASK=0xFFFFFF };
mluis 0:62d1edcc13d1 103 // MAC operation modes (lmic_t.opmode).
mluis 0:62d1edcc13d1 104 enum { OP_NONE = 0x0000,
mluis 0:62d1edcc13d1 105 OP_SCAN = 0x0001, // radio scan to find a beacon
mluis 0:62d1edcc13d1 106 OP_TRACK = 0x0002, // track my networks beacon (netid)
mluis 0:62d1edcc13d1 107 OP_JOINING = 0x0004, // device joining in progress (blocks other activities)
mluis 0:62d1edcc13d1 108 OP_TXDATA = 0x0008, // TX user data (buffered in pendTxData)
mluis 0:62d1edcc13d1 109 OP_POLL = 0x0010, // send empty UP frame to ACK confirmed DN/fetch more DN data
mluis 0:62d1edcc13d1 110 OP_REJOIN = 0x0020, // occasionally send JOIN REQUEST
mluis 0:62d1edcc13d1 111 OP_SHUTDOWN = 0x0040, // prevent MAC from doing anything
mluis 0:62d1edcc13d1 112 OP_TXRXPEND = 0x0080, // TX/RX transaction pending
mluis 0:62d1edcc13d1 113 OP_RNDTX = 0x0100, // prevent TX lining up after a beacon
mluis 0:62d1edcc13d1 114 OP_PINGINI = 0x0200, // pingable is initialized and scheduling active
mluis 0:62d1edcc13d1 115 OP_PINGABLE = 0x0400, // we're pingable
mluis 0:62d1edcc13d1 116 OP_NEXTCHNL = 0x0800, // find a new channel
mluis 0:62d1edcc13d1 117 OP_LINKDEAD = 0x1000, // link was reported as dead
mluis 0:62d1edcc13d1 118 OP_OTA = 0x2000, // Over the Air Activation in use
mluis 0:62d1edcc13d1 119 };
mluis 0:62d1edcc13d1 120 // TX-RX transaction flags - report back to user
mluis 0:62d1edcc13d1 121 enum { TXRX_ACK = 0x80, // confirmed UP frame was acked
mluis 0:62d1edcc13d1 122 TXRX_NACK = 0x40, // confirmed UP frame was not acked
mluis 0:62d1edcc13d1 123 TXRX_NOPORT = 0x20, // set if a frame with a port was RXed, clr if no frame/no port
mluis 0:62d1edcc13d1 124 TXRX_DNW1 = 0x01, // received in 1st DN slot
mluis 0:62d1edcc13d1 125 TXRX_DNW2 = 0x02, // received in 2dn DN slot
mluis 0:62d1edcc13d1 126 TXRX_PING = 0x04 }; // received in a scheduled RX slot
mluis 0:62d1edcc13d1 127 // Event types for event callback
mluis 0:62d1edcc13d1 128 enum _ev_t { EV_SCAN_TIMEOUT=1, EV_BEACON_FOUND,
mluis 0:62d1edcc13d1 129 EV_BEACON_MISSED, EV_BEACON_TRACKED, EV_JOINING,
mluis 0:62d1edcc13d1 130 EV_JOINED, EV_RFU1, EV_JOIN_FAILED, EV_REJOIN_FAILED,
mluis 0:62d1edcc13d1 131 EV_TXCOMPLETE, EV_LOST_TSYNC, EV_RESET,
mluis 0:62d1edcc13d1 132 EV_RXCOMPLETE, EV_LINK_DEAD, EV_LINK_ALIVE };
mluis 0:62d1edcc13d1 133 typedef enum _ev_t ev_t;
mluis 0:62d1edcc13d1 134
mluis 0:62d1edcc13d1 135
mluis 0:62d1edcc13d1 136 struct lmic_t {
mluis 0:62d1edcc13d1 137 // Radio settings TX/RX (also accessed by HAL)
mluis 0:62d1edcc13d1 138 ostime_t txend;
mluis 0:62d1edcc13d1 139 ostime_t rxtime;
mluis 0:62d1edcc13d1 140 rxqu_t rxq;
mluis 0:62d1edcc13d1 141 u4_t freq;
mluis 0:62d1edcc13d1 142 rps_t rps;
mluis 0:62d1edcc13d1 143 u1_t rxsyms;
mluis 0:62d1edcc13d1 144 s1_t txpow; // dBm
mluis 0:62d1edcc13d1 145
mluis 0:62d1edcc13d1 146 osjob_t osjob;
mluis 0:62d1edcc13d1 147
mluis 0:62d1edcc13d1 148 // Channel scheduling
mluis 0:62d1edcc13d1 149 #if CFG_eu868
mluis 0:62d1edcc13d1 150 band_t bands[MAX_BANDS];
mluis 0:62d1edcc13d1 151 u4_t channelFreq[MAX_CHANNELS];
mluis 0:62d1edcc13d1 152 u1_t channelDrs[MAX_CHANNELS];
mluis 0:62d1edcc13d1 153 u2_t channelMap;
mluis 0:62d1edcc13d1 154 #elif CFG_us915
mluis 0:62d1edcc13d1 155 u4_t xchFreq[MAX_XCHANNELS]; // extra channel frequencies (if device is behind a repeater)
mluis 0:62d1edcc13d1 156 u1_t xchDrs[MAX_XCHANNELS]; // extra channel datarate ranges ---XXX: ditto
mluis 0:62d1edcc13d1 157 u2_t channelMap[(72+MAX_XCHANNELS+15)/16]; // enabled bits
mluis 0:62d1edcc13d1 158 u1_t chRnd; // channel randomizer
mluis 0:62d1edcc13d1 159 #endif
mluis 0:62d1edcc13d1 160 u1_t txChnl; // channel for next TX
mluis 0:62d1edcc13d1 161 u1_t globalDutyRate; // max rate: 1/2^k
mluis 0:62d1edcc13d1 162 ostime_t globalDutyAvail; // time device can send again
mluis 0:62d1edcc13d1 163
mluis 0:62d1edcc13d1 164 u4_t netid; // current network id (~0 - none)
mluis 0:62d1edcc13d1 165 u2_t opmode;
mluis 0:62d1edcc13d1 166 u1_t upRepeat; // configured up repeat
mluis 0:62d1edcc13d1 167 s1_t adrTxPow; // ADR adjusted TX power
mluis 0:62d1edcc13d1 168 u1_t datarate; // current data rate
mluis 0:62d1edcc13d1 169 u1_t errcr; // error coding rate (used for TX only)
mluis 0:62d1edcc13d1 170 u1_t rejoinCnt; // adjustment for rejoin datarate
mluis 0:62d1edcc13d1 171 s2_t drift; // last measured drift
mluis 0:62d1edcc13d1 172 s2_t lastDriftDiff;
mluis 0:62d1edcc13d1 173 s2_t maxDriftDiff;
mluis 0:62d1edcc13d1 174
mluis 0:62d1edcc13d1 175 u1_t pendTxPort;
mluis 0:62d1edcc13d1 176 u1_t pendTxConf; // confirmed data
mluis 0:62d1edcc13d1 177 u1_t pendTxLen; // +0x80 = confirmed
mluis 0:62d1edcc13d1 178 u1_t pendTxData[MAX_LEN_PAYLOAD];
mluis 0:62d1edcc13d1 179
mluis 0:62d1edcc13d1 180 u2_t devNonce; // last generated nonce
mluis 0:62d1edcc13d1 181 u1_t nwkKey[16]; // network session key
mluis 0:62d1edcc13d1 182 u1_t artKey[16]; // application router session key
mluis 0:62d1edcc13d1 183 devaddr_t devaddr;
mluis 0:62d1edcc13d1 184 u4_t seqnoDn; // device level down stream seqno
mluis 0:62d1edcc13d1 185 u4_t seqnoUp;
mluis 0:62d1edcc13d1 186
mluis 0:62d1edcc13d1 187 u1_t dnConf; // dn frame confirm pending: LORA::FCT_ACK or 0
mluis 0:62d1edcc13d1 188 s1_t adrAckReq; // counter until we reset data rate (0=off)
mluis 0:62d1edcc13d1 189 u1_t adrChanged;
mluis 0:62d1edcc13d1 190
mluis 0:62d1edcc13d1 191 u1_t margin;
mluis 0:62d1edcc13d1 192 bit_t ladrAns; // link adr adapt answer pending
mluis 0:62d1edcc13d1 193 bit_t devsAns; // device status answer pending
mluis 0:62d1edcc13d1 194 u1_t adrEnabled;
mluis 0:62d1edcc13d1 195 u1_t moreData; // NWK has more data pending
mluis 0:62d1edcc13d1 196 bit_t dutyCapAns; // have to ACK duty cycle settings
mluis 0:62d1edcc13d1 197 u1_t snchAns; // answer set new channel
mluis 0:62d1edcc13d1 198 // 2nd RX window (after up stream)
mluis 0:62d1edcc13d1 199 u1_t dn2Dr;
mluis 0:62d1edcc13d1 200 u4_t dn2Freq;
mluis 0:62d1edcc13d1 201 u1_t dn2Ans; // 0=no answer pend, 0x80+ACKs
mluis 0:62d1edcc13d1 202
mluis 0:62d1edcc13d1 203 // Class B state
mluis 0:62d1edcc13d1 204 u1_t missedBcns; // unable to track last N beacons
mluis 0:62d1edcc13d1 205 u1_t bcninfoTries; // how often to try (scan mode only)
mluis 0:62d1edcc13d1 206 u1_t pingSetAns; // answer set cmd and ACK bits
mluis 0:62d1edcc13d1 207 rxsched_t ping; // pingable setup
mluis 0:62d1edcc13d1 208
mluis 0:62d1edcc13d1 209 // Public part of MAC state
mluis 0:62d1edcc13d1 210 u1_t txCnt;
mluis 0:62d1edcc13d1 211 u1_t txrxFlags; // transaction flags (TX-RX combo)
mluis 0:62d1edcc13d1 212 u1_t dataBeg; // 0 or start of data (dataBeg-1 is port)
mluis 0:62d1edcc13d1 213 u1_t dataLen; // 0 no data or zero length data, >0 byte count of data
mluis 0:62d1edcc13d1 214 u1_t frame[MAX_LEN_FRAME];
mluis 0:62d1edcc13d1 215
mluis 0:62d1edcc13d1 216 u1_t bcnChnl;
mluis 0:62d1edcc13d1 217 u1_t bcnRxsyms; //
mluis 0:62d1edcc13d1 218 ostime_t bcnRxtime;
mluis 0:62d1edcc13d1 219 bcninfo_t bcninfo; // Last received beacon info
mluis 0:62d1edcc13d1 220 };
mluis 0:62d1edcc13d1 221 DECLARE_LMIC;
mluis 0:62d1edcc13d1 222
mluis 0:62d1edcc13d1 223
mluis 0:62d1edcc13d1 224 void LMIC_setDrTxpow (dr_t dr, s1_t txpow); // set default/start DR/txpow
mluis 0:62d1edcc13d1 225 void LMIC_setAdrMode (bit_t enabled); // set ADR mode (if mobile turn off)
mluis 0:62d1edcc13d1 226 bit_t LMIC_startJoining (void);
mluis 0:62d1edcc13d1 227
mluis 0:62d1edcc13d1 228 void LMIC_shutdown (void);
mluis 0:62d1edcc13d1 229 void LMIC_init (void);
mluis 0:62d1edcc13d1 230 void LMIC_reset (void);
mluis 0:62d1edcc13d1 231 void LMIC_clrTxData (void);
mluis 0:62d1edcc13d1 232 void LMIC_setTxData (void);
mluis 0:62d1edcc13d1 233 int LMIC_setTxData2 (u1_t port, xref2u1_t data, u1_t dlen, u1_t confirmed);
mluis 0:62d1edcc13d1 234 void LMIC_sendAlive (void);
mluis 0:62d1edcc13d1 235
mluis 0:62d1edcc13d1 236 bit_t LMIC_enableTracking (u1_t tryBcnInfo);
mluis 0:62d1edcc13d1 237 void LMIC_disableTracking (void);
mluis 0:62d1edcc13d1 238
mluis 0:62d1edcc13d1 239 void LMIC_stopPingable (void);
mluis 0:62d1edcc13d1 240 void LMIC_setPingable (u1_t intvExp);
mluis 0:62d1edcc13d1 241 void LMIC_tryRejoin (void);
mluis 0:62d1edcc13d1 242 void LMIC_startABP (u4_t netid, devaddr_t devaddr, u1_t* nwkKey, u1_t* artKey);
mluis 0:62d1edcc13d1 243
mluis 0:62d1edcc13d1 244 #endif // _lmic_h_