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 #ifndef _oslmic_h_
mluis 0:62d1edcc13d1 13 #define _oslmic_h_
mluis 0:62d1edcc13d1 14
mluis 0:62d1edcc13d1 15 // Dependencies required for the LoRa MAC in C to run.
mluis 0:62d1edcc13d1 16 // These settings can be adapted to the underlying system.
mluis 0:62d1edcc13d1 17 // You should not, however, change the lmic.[hc]
mluis 0:62d1edcc13d1 18
mluis 0:62d1edcc13d1 19
mluis 0:62d1edcc13d1 20
mluis 0:62d1edcc13d1 21 //================================================================================
mluis 0:62d1edcc13d1 22 //================================================================================
mluis 0:62d1edcc13d1 23 // Target platform as C library
mluis 0:62d1edcc13d1 24 typedef unsigned char bit_t;
mluis 0:62d1edcc13d1 25 typedef unsigned char u1_t;
mluis 0:62d1edcc13d1 26 typedef signed char s1_t;
mluis 0:62d1edcc13d1 27 typedef unsigned short u2_t;
mluis 0:62d1edcc13d1 28 typedef short s2_t;
mluis 0:62d1edcc13d1 29 typedef unsigned int u4_t;
mluis 0:62d1edcc13d1 30 typedef int s4_t;
mluis 0:62d1edcc13d1 31 typedef unsigned long long u8_t;
mluis 0:62d1edcc13d1 32 typedef long long s8_t;
mluis 0:62d1edcc13d1 33 typedef unsigned int uint;
mluis 0:62d1edcc13d1 34 typedef const char* str_t;
mluis 0:62d1edcc13d1 35
mluis 0:62d1edcc13d1 36 #define CFG_noassert 1
mluis 0:62d1edcc13d1 37 #include <string.h>
mluis 0:62d1edcc13d1 38 #include "hal.h"
mluis 0:62d1edcc13d1 39 #define EV(a,b,c) /**/
mluis 0:62d1edcc13d1 40 #define DO_DEVDB(meth,...) /**/
mluis 0:62d1edcc13d1 41 #if !CFG_noassert
mluis 0:62d1edcc13d1 42 #define ASSERT(cond) if(!(cond)) hal_failed()
mluis 0:62d1edcc13d1 43 #else
mluis 0:62d1edcc13d1 44 #define ASSERT(cond) /**/
mluis 0:62d1edcc13d1 45 #endif
mluis 0:62d1edcc13d1 46
mluis 0:62d1edcc13d1 47 #define os_clearMem(a,b) memset(a,0,b)
mluis 0:62d1edcc13d1 48 #define os_copyMem(a,b,c) memcpy(a,b,c)
mluis 0:62d1edcc13d1 49
mluis 0:62d1edcc13d1 50 typedef struct osjob_t osjob_t;
mluis 0:62d1edcc13d1 51 typedef struct band_t band_t;
mluis 0:62d1edcc13d1 52 typedef struct rxqu_t rxqu_t;
mluis 0:62d1edcc13d1 53 typedef struct chnldef_t chnldef_t;
mluis 0:62d1edcc13d1 54 typedef struct rxsched_t rxsched_t;
mluis 0:62d1edcc13d1 55 typedef struct bcninfo_t bcninfo_t;
mluis 0:62d1edcc13d1 56 typedef const u1_t* xref2cu1_t;
mluis 0:62d1edcc13d1 57 typedef u1_t* xref2u1_t;
mluis 0:62d1edcc13d1 58 #define TYPEDEF_xref2rps_t typedef rps_t* xref2rps_t
mluis 0:62d1edcc13d1 59 #define TYPEDEF_xref2rxqu_t typedef rxqu_t* xref2rxqu_t
mluis 0:62d1edcc13d1 60 #define TYPEDEF_xref2rxsched_t typedef rxsched_t* xref2rxsched_t
mluis 0:62d1edcc13d1 61 #define TYPEDEF_xref2chnldef_t typedef chnldef_t* xref2chnldef_t
mluis 0:62d1edcc13d1 62 #define TYPEDEF_xref2band_t typedef band_t* xref2band_t
mluis 0:62d1edcc13d1 63 #define TYPEDEF_xref2osjob_t typedef osjob_t* xref2osjob_t
mluis 0:62d1edcc13d1 64
mluis 0:62d1edcc13d1 65 #define SIZEOFEXPR(x) sizeof(x)
mluis 0:62d1edcc13d1 66
mluis 0:62d1edcc13d1 67 #define ON_LMIC_EVENT(ev) onEvent(ev)
mluis 0:62d1edcc13d1 68 #define DECL_ON_LMIC_EVENT void onEvent(ev_t e)
mluis 0:62d1edcc13d1 69
mluis 0:62d1edcc13d1 70 extern u4_t AESAUX[];
mluis 0:62d1edcc13d1 71 extern u4_t AESKEY[];
mluis 0:62d1edcc13d1 72 #define AESkey ((u1_t*)AESKEY)
mluis 0:62d1edcc13d1 73 #define AESaux ((u1_t*)AESAUX)
mluis 0:62d1edcc13d1 74 #define FUNC_ADDR(func) (&(func))
mluis 0:62d1edcc13d1 75
mluis 0:62d1edcc13d1 76 u1_t radio_rand1 (void);
mluis 0:62d1edcc13d1 77 #define os_getRndU1() radio_rand1()
mluis 0:62d1edcc13d1 78
mluis 0:62d1edcc13d1 79 #define DEFINE_LMIC struct lmic_t LMIC
mluis 0:62d1edcc13d1 80 #define DECLARE_LMIC extern struct lmic_t LMIC
mluis 0:62d1edcc13d1 81
mluis 0:62d1edcc13d1 82 void radio_init(void);
mluis 0:62d1edcc13d1 83 void radio_irq_handler (u1_t dio);
mluis 0:62d1edcc13d1 84 void os_init (void);
mluis 0:62d1edcc13d1 85 void os_runloop (void);
mluis 0:62d1edcc13d1 86
mluis 0:62d1edcc13d1 87 //================================================================================
mluis 0:62d1edcc13d1 88
mluis 0:62d1edcc13d1 89
mluis 0:62d1edcc13d1 90 #ifndef RX_RAMPUP
mluis 0:62d1edcc13d1 91 #define RX_RAMPUP (us2osticks(2000))
mluis 0:62d1edcc13d1 92 #endif
mluis 0:62d1edcc13d1 93 #ifndef TX_RAMPUP
mluis 0:62d1edcc13d1 94 #define TX_RAMPUP (us2osticks(2000))
mluis 0:62d1edcc13d1 95 #endif
mluis 0:62d1edcc13d1 96
mluis 0:62d1edcc13d1 97 #ifndef OSTICKS_PER_SEC
mluis 0:62d1edcc13d1 98 #define OSTICKS_PER_SEC 15625
mluis 0:62d1edcc13d1 99 #elif OSTICKS_PER_SEC < 10000 || OSTICKS_PER_SEC > 64516
mluis 0:62d1edcc13d1 100 #error Illegal OSTICKS_PER_SEC - must be in range [10000:64516]. One tick must be 15.5us .. 100us long.
mluis 0:62d1edcc13d1 101 #endif
mluis 0:62d1edcc13d1 102
mluis 0:62d1edcc13d1 103 typedef s4_t ostime_t;
mluis 0:62d1edcc13d1 104
mluis 0:62d1edcc13d1 105 #if !HAS_ostick_conv
mluis 0:62d1edcc13d1 106 #define us2osticks(us) ((ostime_t)( ((s8_t)(us) * OSTICKS_PER_SEC) / 1000000))
mluis 0:62d1edcc13d1 107 #define ms2osticks(ms) ((ostime_t)( ((s8_t)(ms) * OSTICKS_PER_SEC) / 1000))
mluis 0:62d1edcc13d1 108 #define sec2osticks(sec) ((ostime_t)( (s8_t)(sec) * OSTICKS_PER_SEC))
mluis 0:62d1edcc13d1 109 #define osticks2ms(os) ((s4_t)(((os)*(s8_t)1000 ) / OSTICKS_PER_SEC))
mluis 0:62d1edcc13d1 110 #define osticks2us(os) ((s4_t)(((os)*(s8_t)1000000 ) / OSTICKS_PER_SEC))
mluis 0:62d1edcc13d1 111 // Special versions
mluis 0:62d1edcc13d1 112 #define us2osticksCeil(us) ((ostime_t)( ((s8_t)(us) * OSTICKS_PER_SEC + 999999) / 1000000))
mluis 0:62d1edcc13d1 113 #define us2osticksRound(us) ((ostime_t)( ((s8_t)(us) * OSTICKS_PER_SEC + 500000) / 1000000))
mluis 0:62d1edcc13d1 114 #define ms2osticksCeil(ms) ((ostime_t)( ((s8_t)(ms) * OSTICKS_PER_SEC + 999) / 1000))
mluis 0:62d1edcc13d1 115 #define ms2osticksRound(ms) ((ostime_t)( ((s8_t)(ms) * OSTICKS_PER_SEC + 500) / 1000))
mluis 0:62d1edcc13d1 116 #endif
mluis 0:62d1edcc13d1 117
mluis 0:62d1edcc13d1 118
mluis 0:62d1edcc13d1 119 struct osjob_t; // fwd decl.
mluis 0:62d1edcc13d1 120 typedef void (*osjobcb_t) (struct osjob_t*);
mluis 0:62d1edcc13d1 121 struct osjob_t {
mluis 0:62d1edcc13d1 122 struct osjob_t* next;
mluis 0:62d1edcc13d1 123 ostime_t deadline;
mluis 0:62d1edcc13d1 124 osjobcb_t func;
mluis 0:62d1edcc13d1 125 };
mluis 0:62d1edcc13d1 126 TYPEDEF_xref2osjob_t;
mluis 0:62d1edcc13d1 127
mluis 0:62d1edcc13d1 128
mluis 0:62d1edcc13d1 129 #if !HAS_os_calls
mluis 0:62d1edcc13d1 130
mluis 0:62d1edcc13d1 131 #ifndef os_getDevKey
mluis 0:62d1edcc13d1 132 void os_getDevKey (xref2u1_t buf);
mluis 0:62d1edcc13d1 133 #endif
mluis 0:62d1edcc13d1 134 #ifndef os_getArtEui
mluis 0:62d1edcc13d1 135 void os_getArtEui (xref2u1_t buf);
mluis 0:62d1edcc13d1 136 #endif
mluis 0:62d1edcc13d1 137 #ifndef os_getDevEui
mluis 0:62d1edcc13d1 138 void os_getDevEui (xref2u1_t buf);
mluis 0:62d1edcc13d1 139 #endif
mluis 0:62d1edcc13d1 140 #ifndef os_setCallback
mluis 0:62d1edcc13d1 141 void os_setCallback (xref2osjob_t job, osjobcb_t cb);
mluis 0:62d1edcc13d1 142 #endif
mluis 0:62d1edcc13d1 143 #ifndef os_setTimedCallback
mluis 0:62d1edcc13d1 144 void os_setTimedCallback (xref2osjob_t job, ostime_t time, osjobcb_t cb);
mluis 0:62d1edcc13d1 145 #endif
mluis 0:62d1edcc13d1 146 #ifndef os_clearCallback
mluis 0:62d1edcc13d1 147 void os_clearCallback (xref2osjob_t job);
mluis 0:62d1edcc13d1 148 #endif
mluis 0:62d1edcc13d1 149 #ifndef os_getTime
mluis 0:62d1edcc13d1 150 ostime_t os_getTime (void);
mluis 0:62d1edcc13d1 151 #endif
mluis 0:62d1edcc13d1 152 #ifndef os_getTimeSecs
mluis 0:62d1edcc13d1 153 uint os_getTimeSecs (void);
mluis 0:62d1edcc13d1 154 #endif
mluis 0:62d1edcc13d1 155 #ifndef os_radio
mluis 0:62d1edcc13d1 156 void os_radio (u1_t mode);
mluis 0:62d1edcc13d1 157 #endif
mluis 0:62d1edcc13d1 158 #ifndef os_getBattLevel
mluis 0:62d1edcc13d1 159 u1_t os_getBattLevel (void);
mluis 0:62d1edcc13d1 160 #endif
mluis 0:62d1edcc13d1 161
mluis 0:62d1edcc13d1 162 #ifndef os_rlsbf4
mluis 0:62d1edcc13d1 163 //! Read 32-bit quantity from given pointer in little endian byte order.
mluis 0:62d1edcc13d1 164 u4_t os_rlsbf4 (xref2cu1_t buf);
mluis 0:62d1edcc13d1 165 #endif
mluis 0:62d1edcc13d1 166 #ifndef os_wlsbf4
mluis 0:62d1edcc13d1 167 //! Write 32-bit quntity into buffer in little endian byte order.
mluis 0:62d1edcc13d1 168 void os_wlsbf4 (xref2u1_t buf, u4_t value);
mluis 0:62d1edcc13d1 169 #endif
mluis 0:62d1edcc13d1 170 #ifndef os_rmsbf4
mluis 0:62d1edcc13d1 171 //! Read 32-bit quantity from given pointer in big endian byte order.
mluis 0:62d1edcc13d1 172 u4_t os_rmsbf4 (xref2cu1_t buf);
mluis 0:62d1edcc13d1 173 #endif
mluis 0:62d1edcc13d1 174 #ifndef os_wmsbf4
mluis 0:62d1edcc13d1 175 //! Write 32-bit quntity into buffer in big endian byte order.
mluis 0:62d1edcc13d1 176 void os_wmsbf4 (xref2u1_t buf, u4_t value);
mluis 0:62d1edcc13d1 177 #endif
mluis 0:62d1edcc13d1 178 #ifndef os_rlsbf2
mluis 0:62d1edcc13d1 179 //! Read 16-bit quantity from given pointer in little endian byte order.
mluis 0:62d1edcc13d1 180 u2_t os_rlsbf2 (xref2cu1_t buf);
mluis 0:62d1edcc13d1 181 #endif
mluis 0:62d1edcc13d1 182 #ifndef os_wlsbf2
mluis 0:62d1edcc13d1 183 //! Write 16-bit quntity into buffer in little endian byte order.
mluis 0:62d1edcc13d1 184 void os_wlsbf2 (xref2u1_t buf, u2_t value);
mluis 0:62d1edcc13d1 185 #endif
mluis 0:62d1edcc13d1 186
mluis 0:62d1edcc13d1 187 //! Get random number (default impl for u2_t).
mluis 0:62d1edcc13d1 188 #ifndef os_getRndU2
mluis 0:62d1edcc13d1 189 #define os_getRndU2() ((u2_t)((os_getRndU1()<<8)|os_getRndU1()))
mluis 0:62d1edcc13d1 190 #endif
mluis 0:62d1edcc13d1 191 #ifndef os_crc16
mluis 0:62d1edcc13d1 192 u2_t os_crc16 (xref2u1_t d, uint len);
mluis 0:62d1edcc13d1 193 #endif
mluis 0:62d1edcc13d1 194
mluis 0:62d1edcc13d1 195 #endif // !HAS_os_calls
mluis 0:62d1edcc13d1 196
mluis 0:62d1edcc13d1 197 // ======================================================================
mluis 0:62d1edcc13d1 198 // AES support
mluis 0:62d1edcc13d1 199 // !!Keep in sync with lorabase.hpp!!
mluis 0:62d1edcc13d1 200
mluis 0:62d1edcc13d1 201 #ifndef AES_ENC // if AES_ENC is defined as macro all other values must be too
mluis 0:62d1edcc13d1 202 #define AES_ENC 0x00
mluis 0:62d1edcc13d1 203 #define AES_DEC 0x01
mluis 0:62d1edcc13d1 204 #define AES_MIC 0x02
mluis 0:62d1edcc13d1 205 #define AES_CTR 0x04
mluis 0:62d1edcc13d1 206 #define AES_MICNOAUX 0x08
mluis 0:62d1edcc13d1 207 #endif
mluis 0:62d1edcc13d1 208 #ifndef AESkey // if AESkey is defined as macro all other values must be too
mluis 0:62d1edcc13d1 209 extern xref2u1_t AESkey;
mluis 0:62d1edcc13d1 210 extern xref2u1_t AESaux;
mluis 0:62d1edcc13d1 211 #endif
mluis 0:62d1edcc13d1 212 #ifndef os_aes
mluis 0:62d1edcc13d1 213 u4_t os_aes (u1_t mode, xref2u1_t buf, u2_t len);
mluis 0:62d1edcc13d1 214 #endif
mluis 0:62d1edcc13d1 215
mluis 0:62d1edcc13d1 216
mluis 0:62d1edcc13d1 217
mluis 0:62d1edcc13d1 218 #endif // _oslmic_h_