LMIC for MOTE_L152RC

Dependents:   lmic_transmit

LoRa WAN in C for NA-mote 72

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 LMIC_reverse_memcpy() for AppEUI to keep same byte order as that 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 LMIC_reverse_memcpy() for DevEUI to keep same byte order as that 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.


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.

Information

DevEUI is entered in reverse order into C-code from that shown on server (unique device ID).

AppEUI is entered in reverse order into C-code from that shown on server.

AppEUI is equivalent to "Application"

transmit power limits

FCC Part 15 rules permit one watt of transmit power when more than 50 channels are used. When received by a 64-channel gateway, the maximum power may be used.

However, if end-device is sending to a 8-channel gateway (single SX1301), the maximum transmit power permitted is +20dBm.

To configure LMIC for use with 8-channel gateway, CHNL_HYBRID should be defined in in config.h, and should be undefined for use with 64-channel gateway.

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:
dudmuck
Date:
Fri Dec 04 01:05:11 2015 +0000
Revision:
10:6c0830baf10f
Parent:
9:83ae7f34e88c
correct DR4 channel used in 8ch mode.  added JOIN_SINGLE_CHANNEL_BLOCK option for faster joining in 8ch mode.

Who changed what in which revision?

UserRevisionLine numberNew contents of line
dudmuck 0:f2716e543d97 1 /*******************************************************************************
dudmuck 0:f2716e543d97 2 * Copyright (c) 2014-2015 IBM Corporation.
dudmuck 0:f2716e543d97 3 * All rights reserved. This program and the accompanying materials
dudmuck 0:f2716e543d97 4 * are made available under the terms of the Eclipse Public License v1.0
dudmuck 0:f2716e543d97 5 * which accompanies this distribution, and is available at
dudmuck 0:f2716e543d97 6 * http://www.eclipse.org/legal/epl-v10.html
dudmuck 0:f2716e543d97 7 *
dudmuck 0:f2716e543d97 8 * Contributors:
dudmuck 0:f2716e543d97 9 * IBM Zurich Research Lab - initial API, implementation and documentation
dudmuck 0:f2716e543d97 10 *******************************************************************************/
dudmuck 0:f2716e543d97 11
dudmuck 0:f2716e543d97 12 #include "lmic.h"
dudmuck 0:f2716e543d97 13
dudmuck 0:f2716e543d97 14 // RUNTIME STATE
dudmuck 0:f2716e543d97 15 static struct {
dudmuck 0:f2716e543d97 16 osjob_t* scheduledjobs;
dudmuck 0:f2716e543d97 17 osjob_t* runnablejobs;
dudmuck 0:f2716e543d97 18 } OS;
dudmuck 0:f2716e543d97 19
dudmuck 0:f2716e543d97 20 void os_init () {
dudmuck 0:f2716e543d97 21 memset(&OS, 0x00, sizeof(OS));
dudmuck 0:f2716e543d97 22 hal_init();
dudmuck 0:f2716e543d97 23 radio_init();
dudmuck 0:f2716e543d97 24 LMIC_init();
dudmuck 0:f2716e543d97 25 }
dudmuck 0:f2716e543d97 26
dudmuck 0:f2716e543d97 27 ostime_t os_getTime () {
dudmuck 0:f2716e543d97 28 return hal_ticks();
dudmuck 0:f2716e543d97 29 }
dudmuck 0:f2716e543d97 30
dudmuck 0:f2716e543d97 31 static u1_t unlinkjob (osjob_t** pnext, osjob_t* job) {
dudmuck 0:f2716e543d97 32 for( ; *pnext; pnext = &((*pnext)->next)) {
dudmuck 0:f2716e543d97 33 if(*pnext == job) { // unlink
dudmuck 0:f2716e543d97 34 *pnext = job->next;
dudmuck 0:f2716e543d97 35 return 1;
dudmuck 0:f2716e543d97 36 }
dudmuck 0:f2716e543d97 37 }
dudmuck 0:f2716e543d97 38 return 0;
dudmuck 0:f2716e543d97 39 }
dudmuck 0:f2716e543d97 40
dudmuck 0:f2716e543d97 41 // clear scheduled job
dudmuck 0:f2716e543d97 42 void os_clearCallback (osjob_t* job) {
dudmuck 0:f2716e543d97 43 hal_disableIRQs();
dudmuck 0:f2716e543d97 44 unlinkjob(&OS.scheduledjobs, job) || unlinkjob(&OS.runnablejobs, job);
dudmuck 0:f2716e543d97 45 hal_enableIRQs();
dudmuck 0:f2716e543d97 46 }
dudmuck 0:f2716e543d97 47
dudmuck 0:f2716e543d97 48 // schedule immediately runnable job
dudmuck 0:f2716e543d97 49 void os_setCallback (osjob_t* job, osjobcb_t cb) {
dudmuck 0:f2716e543d97 50 osjob_t** pnext;
dudmuck 0:f2716e543d97 51 hal_disableIRQs();
dudmuck 0:f2716e543d97 52 // remove if job was already queued
dudmuck 0:f2716e543d97 53 os_clearCallback(job);
dudmuck 0:f2716e543d97 54 // fill-in job
dudmuck 0:f2716e543d97 55 job->func = cb;
dudmuck 0:f2716e543d97 56 job->next = NULL;
dudmuck 0:f2716e543d97 57 // add to end of run queue
dudmuck 0:f2716e543d97 58 for(pnext=&OS.runnablejobs; *pnext; pnext=&((*pnext)->next));
dudmuck 0:f2716e543d97 59 *pnext = job;
dudmuck 0:f2716e543d97 60 hal_enableIRQs();
dudmuck 0:f2716e543d97 61 }
dudmuck 0:f2716e543d97 62
dudmuck 0:f2716e543d97 63 // schedule timed job
dudmuck 0:f2716e543d97 64 void os_setTimedCallback (osjob_t* job, ostime_t time, osjobcb_t cb) {
dudmuck 0:f2716e543d97 65 osjob_t** pnext;
dudmuck 0:f2716e543d97 66 hal_disableIRQs();
dudmuck 0:f2716e543d97 67 // remove if job was already queued
dudmuck 0:f2716e543d97 68 os_clearCallback(job);
dudmuck 0:f2716e543d97 69 // fill-in job
dudmuck 0:f2716e543d97 70 job->deadline = time;
dudmuck 0:f2716e543d97 71 job->func = cb;
dudmuck 0:f2716e543d97 72 job->next = NULL;
dudmuck 0:f2716e543d97 73 // insert into schedule
dudmuck 0:f2716e543d97 74 for(pnext=&OS.scheduledjobs; *pnext; pnext=&((*pnext)->next)) {
dudmuck 0:f2716e543d97 75 if((*pnext)->deadline - time > 0) { // (cmp diff, not abs!)
dudmuck 0:f2716e543d97 76 // enqueue before next element and stop
dudmuck 0:f2716e543d97 77 job->next = *pnext;
dudmuck 0:f2716e543d97 78 break;
dudmuck 0:f2716e543d97 79 }
dudmuck 0:f2716e543d97 80 }
dudmuck 0:f2716e543d97 81 *pnext = job;
dudmuck 0:f2716e543d97 82 hal_enableIRQs();
dudmuck 0:f2716e543d97 83 }
dudmuck 0:f2716e543d97 84
dudmuck 0:f2716e543d97 85 // execute jobs from timer and from run queue
dudmuck 0:f2716e543d97 86 void os_runloop () {
dudmuck 0:f2716e543d97 87 while(1) {
dudmuck 0:f2716e543d97 88 osjob_t* j = NULL;
dudmuck 0:f2716e543d97 89 hal_disableIRQs();
dudmuck 0:f2716e543d97 90 // check for runnable jobs
dudmuck 0:f2716e543d97 91 if(OS.runnablejobs) {
dudmuck 0:f2716e543d97 92 j = OS.runnablejobs;
dudmuck 0:f2716e543d97 93 OS.runnablejobs = j->next;
dudmuck 0:f2716e543d97 94 } else if(OS.scheduledjobs && hal_checkTimer(OS.scheduledjobs->deadline)) { // check for expired timed jobs
dudmuck 0:f2716e543d97 95 j = OS.scheduledjobs;
dudmuck 0:f2716e543d97 96 OS.scheduledjobs = j->next;
dudmuck 0:f2716e543d97 97 } else { // nothing pending
dudmuck 0:f2716e543d97 98 hal_sleep(); // wake by irq (timer already restarted)
dudmuck 0:f2716e543d97 99 }
dudmuck 0:f2716e543d97 100 hal_enableIRQs();
dudmuck 0:f2716e543d97 101 if(j) { // run job callback
dudmuck 0:f2716e543d97 102 j->func(j);
dudmuck 0:f2716e543d97 103 }
dudmuck 0:f2716e543d97 104 }
dudmuck 0:f2716e543d97 105 }
dudmuck 9:83ae7f34e88c 106