Semtech / LMiC

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
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 * Semtech Apps Team - Modified to support the MBED sx1276 driver
mluis 0:62d1edcc13d1 11 * library.
mluis 0:62d1edcc13d1 12 * Possibility to use original or Semtech's MBED
mluis 0:62d1edcc13d1 13 * radio driver. The selection is done by setting
mluis 0:62d1edcc13d1 14 * USE_SMTC_RADIO_DRIVER preprocessing directive
mluis 0:62d1edcc13d1 15 * in lmic.h
mluis 0:62d1edcc13d1 16 *******************************************************************************/
mluis 0:62d1edcc13d1 17 #include "mbed.h"
mluis 0:62d1edcc13d1 18 #include "lmic.h"
mluis 0:62d1edcc13d1 19 #include "mbed_debug.h"
mluis 0:62d1edcc13d1 20
mluis 0:62d1edcc13d1 21 #if USE_SMTC_RADIO_DRIVER
mluis 0:62d1edcc13d1 22
mluis 0:62d1edcc13d1 23 #else
mluis 0:62d1edcc13d1 24
mluis 0:62d1edcc13d1 25 extern void radio_irq_handler( u1_t dio );
mluis 0:62d1edcc13d1 26
mluis 0:62d1edcc13d1 27 static DigitalOut nss( D10 );
mluis 0:62d1edcc13d1 28 static SPI spi( D11, D12, D13 ); // ( mosi, miso, sclk )
mluis 0:62d1edcc13d1 29
mluis 0:62d1edcc13d1 30 static DigitalInOut rst( A0 );
mluis 0:62d1edcc13d1 31 static DigitalOut rxtx( A4 );
mluis 0:62d1edcc13d1 32
mluis 0:62d1edcc13d1 33 static InterruptIn dio0( D2 );
mluis 0:62d1edcc13d1 34 static InterruptIn dio1( D3 );
mluis 0:62d1edcc13d1 35 static InterruptIn dio2( D4 );
mluis 0:62d1edcc13d1 36
mluis 0:62d1edcc13d1 37 static void dio0Irq( void )
mluis 0:62d1edcc13d1 38 {
mluis 0:62d1edcc13d1 39 radio_irq_handler( 0 );
mluis 0:62d1edcc13d1 40 }
mluis 0:62d1edcc13d1 41
mluis 0:62d1edcc13d1 42 static void dio1Irq( void )
mluis 0:62d1edcc13d1 43 {
mluis 0:62d1edcc13d1 44 radio_irq_handler( 1 );
mluis 0:62d1edcc13d1 45 }
mluis 0:62d1edcc13d1 46 static void dio2Irq( void )
mluis 0:62d1edcc13d1 47 {
mluis 0:62d1edcc13d1 48 radio_irq_handler( 2 );
mluis 0:62d1edcc13d1 49 }
mluis 0:62d1edcc13d1 50
mluis 0:62d1edcc13d1 51 #endif
mluis 0:62d1edcc13d1 52
mluis 0:62d1edcc13d1 53 static u1_t irqlevel = 0;
mluis 0:62d1edcc13d1 54 static u4_t ticks = 0;
mluis 0:62d1edcc13d1 55
mluis 0:62d1edcc13d1 56 static Timer timer;
mluis 0:62d1edcc13d1 57 static Ticker ticker;
mluis 0:62d1edcc13d1 58
mluis 0:62d1edcc13d1 59 static void reset_timer( void )
mluis 0:62d1edcc13d1 60 {
mluis 0:62d1edcc13d1 61 ticks += timer.read_us( ) >> 6;
mluis 0:62d1edcc13d1 62 timer.reset( );
mluis 0:62d1edcc13d1 63 }
mluis 0:62d1edcc13d1 64
mluis 0:62d1edcc13d1 65 void hal_init( void )
mluis 0:62d1edcc13d1 66 {
mluis 0:62d1edcc13d1 67 __disable_irq( );
mluis 0:62d1edcc13d1 68 irqlevel = 0;
mluis 0:62d1edcc13d1 69
mluis 0:62d1edcc13d1 70 #if USE_SMTC_RADIO_DRIVER
mluis 0:62d1edcc13d1 71
mluis 0:62d1edcc13d1 72 #else
mluis 0:62d1edcc13d1 73 // configure input lines
mluis 0:62d1edcc13d1 74 dio0.mode( PullDown );
mluis 0:62d1edcc13d1 75 dio0.rise( dio0Irq );
mluis 0:62d1edcc13d1 76 dio0.enable_irq( );
mluis 0:62d1edcc13d1 77 dio1.mode( PullDown );
mluis 0:62d1edcc13d1 78 dio1.rise( dio1Irq );
mluis 0:62d1edcc13d1 79 dio1.enable_irq( );
mluis 0:62d1edcc13d1 80 dio2.mode( PullDown );
mluis 0:62d1edcc13d1 81 dio2.rise( dio2Irq );
mluis 0:62d1edcc13d1 82 dio2.enable_irq( );
mluis 0:62d1edcc13d1 83 // configure reset line
mluis 0:62d1edcc13d1 84 rst.input( );
mluis 0:62d1edcc13d1 85 // configure spi
mluis 0:62d1edcc13d1 86 spi.frequency( 8000000 );
mluis 0:62d1edcc13d1 87 spi.format( 8, 0 );
mluis 0:62d1edcc13d1 88 nss = 1;
mluis 0:62d1edcc13d1 89 #endif
mluis 0:62d1edcc13d1 90 // configure timer
mluis 0:62d1edcc13d1 91 timer.start( );
mluis 0:62d1edcc13d1 92 ticker.attach_us( reset_timer, 10000000 ); // reset timer every 10sec
mluis 0:62d1edcc13d1 93 __enable_irq( );
mluis 0:62d1edcc13d1 94 }
mluis 0:62d1edcc13d1 95
mluis 0:62d1edcc13d1 96 #if USE_SMTC_RADIO_DRIVER
mluis 0:62d1edcc13d1 97
mluis 0:62d1edcc13d1 98 #else
mluis 0:62d1edcc13d1 99
mluis 0:62d1edcc13d1 100 void hal_pin_rxtx( u1_t val )
mluis 0:62d1edcc13d1 101 {
mluis 0:62d1edcc13d1 102 rxtx = !val;
mluis 0:62d1edcc13d1 103 }
mluis 0:62d1edcc13d1 104
mluis 0:62d1edcc13d1 105 void hal_pin_nss( u1_t val )
mluis 0:62d1edcc13d1 106 {
mluis 0:62d1edcc13d1 107 nss = val;
mluis 0:62d1edcc13d1 108 }
mluis 0:62d1edcc13d1 109
mluis 0:62d1edcc13d1 110 void hal_pin_rst( u1_t val )
mluis 0:62d1edcc13d1 111 {
mluis 0:62d1edcc13d1 112 if( val == 0 || val == 1 )
mluis 0:62d1edcc13d1 113 { // drive pin
mluis 0:62d1edcc13d1 114 rst.output( );
mluis 0:62d1edcc13d1 115 rst = val;
mluis 0:62d1edcc13d1 116 }
mluis 0:62d1edcc13d1 117 else
mluis 0:62d1edcc13d1 118 { // keep pin floating
mluis 0:62d1edcc13d1 119 rst.input( );
mluis 0:62d1edcc13d1 120 }
mluis 0:62d1edcc13d1 121 }
mluis 0:62d1edcc13d1 122
mluis 0:62d1edcc13d1 123 u1_t hal_spi( u1_t out )
mluis 0:62d1edcc13d1 124 {
mluis 0:62d1edcc13d1 125 return spi.write( out );
mluis 0:62d1edcc13d1 126 }
mluis 0:62d1edcc13d1 127
mluis 0:62d1edcc13d1 128 #endif
mluis 0:62d1edcc13d1 129
mluis 0:62d1edcc13d1 130 void hal_disableIRQs( void )
mluis 0:62d1edcc13d1 131 {
mluis 0:62d1edcc13d1 132 __disable_irq( );
mluis 0:62d1edcc13d1 133 irqlevel++;
mluis 0:62d1edcc13d1 134 }
mluis 0:62d1edcc13d1 135
mluis 0:62d1edcc13d1 136 void hal_enableIRQs( void )
mluis 0:62d1edcc13d1 137 {
mluis 0:62d1edcc13d1 138 if( --irqlevel == 0 )
mluis 0:62d1edcc13d1 139 {
mluis 0:62d1edcc13d1 140 __enable_irq( );
mluis 0:62d1edcc13d1 141 }
mluis 0:62d1edcc13d1 142 }
mluis 0:62d1edcc13d1 143
mluis 0:62d1edcc13d1 144 void hal_sleep( void )
mluis 0:62d1edcc13d1 145 {
mluis 0:62d1edcc13d1 146 // NOP
mluis 0:62d1edcc13d1 147 }
mluis 0:62d1edcc13d1 148
mluis 0:62d1edcc13d1 149 u4_t hal_ticks( void )
mluis 0:62d1edcc13d1 150 {
mluis 0:62d1edcc13d1 151 hal_disableIRQs( );
mluis 0:62d1edcc13d1 152 int t = ticks + ( timer.read_us( ) >> 6 );
mluis 0:62d1edcc13d1 153 hal_enableIRQs( );
mluis 0:62d1edcc13d1 154 return t;
mluis 0:62d1edcc13d1 155 }
mluis 0:62d1edcc13d1 156
mluis 0:62d1edcc13d1 157 static u2_t deltaticks( u4_t time )
mluis 0:62d1edcc13d1 158 {
mluis 0:62d1edcc13d1 159 u4_t t = hal_ticks( );
mluis 0:62d1edcc13d1 160 s4_t d = time - t;
mluis 0:62d1edcc13d1 161 if( d <= 0 )
mluis 0:62d1edcc13d1 162 {
mluis 0:62d1edcc13d1 163 return 0; // in the past
mluis 0:62d1edcc13d1 164 }
mluis 0:62d1edcc13d1 165 if( ( d >> 16 ) != 0 )
mluis 0:62d1edcc13d1 166 {
mluis 0:62d1edcc13d1 167 return 0xFFFF; // far ahead
mluis 0:62d1edcc13d1 168 }
mluis 0:62d1edcc13d1 169 return ( u2_t )d;
mluis 0:62d1edcc13d1 170 }
mluis 0:62d1edcc13d1 171
mluis 0:62d1edcc13d1 172 void hal_waitUntil( u4_t time )
mluis 0:62d1edcc13d1 173 {
mluis 0:62d1edcc13d1 174 while( deltaticks( time ) != 0 ); // busy wait until timestamp is reached
mluis 0:62d1edcc13d1 175 }
mluis 0:62d1edcc13d1 176
mluis 0:62d1edcc13d1 177 u1_t hal_checkTimer( u4_t time )
mluis 0:62d1edcc13d1 178 {
mluis 0:62d1edcc13d1 179 return ( deltaticks( time ) < 2 );
mluis 0:62d1edcc13d1 180 }
mluis 0:62d1edcc13d1 181
mluis 0:62d1edcc13d1 182 void hal_failed( void )
mluis 0:62d1edcc13d1 183 {
mluis 0:62d1edcc13d1 184 while( 1 );
mluis 0:62d1edcc13d1 185 }
mluis 0:62d1edcc13d1 186
mluis 0:62d1edcc13d1 187 //////////////////////////////////////////////////////////////////////
mluis 0:62d1edcc13d1 188 // DEBUG CODE BELOW (use CFG_DEBUG)
mluis 0:62d1edcc13d1 189 //////////////////////////////////////////////////////////////////////
mluis 0:62d1edcc13d1 190 #ifdef CFG_DEBUG
mluis 0:62d1edcc13d1 191
mluis 0:62d1edcc13d1 192 void debug_init( void )
mluis 0:62d1edcc13d1 193 {
mluis 0:62d1edcc13d1 194 // print banner
mluis 0:62d1edcc13d1 195 debug( "\r\n============== DEBUG STARTED ==============\r\n" );
mluis 0:62d1edcc13d1 196 }
mluis 0:62d1edcc13d1 197
mluis 0:62d1edcc13d1 198 void debug_char( u1_t c )
mluis 0:62d1edcc13d1 199 {
mluis 0:62d1edcc13d1 200 debug( "%c", c );
mluis 0:62d1edcc13d1 201 }
mluis 0:62d1edcc13d1 202
mluis 0:62d1edcc13d1 203 void debug_hex( u1_t b )
mluis 0:62d1edcc13d1 204 {
mluis 0:62d1edcc13d1 205 debug( "%02X", b );
mluis 0:62d1edcc13d1 206 }
mluis 0:62d1edcc13d1 207
mluis 0:62d1edcc13d1 208 void debug_buf( const u1_t* buf, u2_t len )
mluis 0:62d1edcc13d1 209 {
mluis 0:62d1edcc13d1 210 while( len-- )
mluis 0:62d1edcc13d1 211 {
mluis 0:62d1edcc13d1 212 debug_hex( *buf++ );
mluis 0:62d1edcc13d1 213 debug_char( ' ' );
mluis 0:62d1edcc13d1 214 }
mluis 0:62d1edcc13d1 215 debug_char( '\r' );
mluis 0:62d1edcc13d1 216 debug_char( '\n' );
mluis 0:62d1edcc13d1 217 }
mluis 0:62d1edcc13d1 218
mluis 0:62d1edcc13d1 219 void debug_uint( u4_t v )
mluis 0:62d1edcc13d1 220 {
mluis 0:62d1edcc13d1 221 for( s1_t n = 24; n >= 0; n -= 8 )
mluis 0:62d1edcc13d1 222 {
mluis 0:62d1edcc13d1 223 debug_hex( v >> n );
mluis 0:62d1edcc13d1 224 }
mluis 0:62d1edcc13d1 225 }
mluis 0:62d1edcc13d1 226
mluis 0:62d1edcc13d1 227 void debug_str( const u1_t* str )
mluis 0:62d1edcc13d1 228 {
mluis 0:62d1edcc13d1 229 while( *str )
mluis 0:62d1edcc13d1 230 {
mluis 0:62d1edcc13d1 231 debug_char( *str++ );
mluis 0:62d1edcc13d1 232 }
mluis 0:62d1edcc13d1 233 }
mluis 0:62d1edcc13d1 234
mluis 0:62d1edcc13d1 235 void debug_val( const u1_t* label, u4_t val )
mluis 0:62d1edcc13d1 236 {
mluis 0:62d1edcc13d1 237 debug_str( label );
mluis 0:62d1edcc13d1 238 debug_uint( val );
mluis 0:62d1edcc13d1 239 debug_char( '\r' );
mluis 0:62d1edcc13d1 240 debug_char( '\n' );
mluis 0:62d1edcc13d1 241 }
mluis 0:62d1edcc13d1 242
mluis 0:62d1edcc13d1 243 void debug_led( u1_t val )
mluis 0:62d1edcc13d1 244 {
mluis 0:62d1edcc13d1 245 debug_val( "LED = ", val );
mluis 0:62d1edcc13d1 246 }
mluis 0:62d1edcc13d1 247
mluis 0:62d1edcc13d1 248 void debug_event( int ev )
mluis 0:62d1edcc13d1 249 {
mluis 0:62d1edcc13d1 250 static const u1_t* evnames[] =
mluis 0:62d1edcc13d1 251 {
mluis 0:62d1edcc13d1 252 [EV_SCAN_TIMEOUT] = "SCAN_TIMEOUT",
mluis 0:62d1edcc13d1 253 [EV_BEACON_FOUND] = "BEACON_FOUND",
mluis 0:62d1edcc13d1 254 [EV_BEACON_MISSED] = "BEACON_MISSED",
mluis 0:62d1edcc13d1 255 [EV_BEACON_TRACKED] = "BEACON_TRACKED",
mluis 0:62d1edcc13d1 256 [EV_JOINING] = "JOINING",
mluis 0:62d1edcc13d1 257 [EV_JOINED] = "JOINED",
mluis 0:62d1edcc13d1 258 [EV_RFU1] = "RFU1",
mluis 0:62d1edcc13d1 259 [EV_JOIN_FAILED] = "JOIN_FAILED",
mluis 0:62d1edcc13d1 260 [EV_REJOIN_FAILED] = "REJOIN_FAILED",
mluis 0:62d1edcc13d1 261 [EV_TXCOMPLETE] = "TXCOMPLETE",
mluis 0:62d1edcc13d1 262 [EV_LOST_TSYNC] = "LOST_TSYNC",
mluis 0:62d1edcc13d1 263 [EV_RESET] = "RESET",
mluis 0:62d1edcc13d1 264 [EV_RXCOMPLETE] = "RXCOMPLETE",
mluis 0:62d1edcc13d1 265 [EV_LINK_DEAD] = "LINK_DEAD",
mluis 0:62d1edcc13d1 266 [EV_LINK_ALIVE] = "LINK_ALIVE",
mluis 0:62d1edcc13d1 267 };
mluis 0:62d1edcc13d1 268 debug( "%s\r\n", evnames[ev] );
mluis 0:62d1edcc13d1 269 }
mluis 0:62d1edcc13d1 270 #endif // CFG_DEBUG