LORIOT firmware for the mbed Shield

Dependencies:   LMiC2 SX1276Lib mbed

Fork of LoRaWAN-lmic-app by Semtech

Committer:
janjongboom
Date:
Tue Apr 12 11:54:23 2016 +0000
Revision:
7:9dcb6fcaf4b9
Parent:
6:e54c37d101f3
publish

Who changed what in which revision?

UserRevisionLine numberNew contents of line
sam_grove 3:ce28e3313a88 1 /*
mluis 0:a2929fa6e4f0 2 / _____) _ | |
mluis 0:a2929fa6e4f0 3 ( (____ _____ ____ _| |_ _____ ____| |__
mluis 0:a2929fa6e4f0 4 \____ \| ___ | (_ _) ___ |/ ___) _ \
mluis 0:a2929fa6e4f0 5 _____) ) ____| | | || |_| ____( (___| | | |
mluis 0:a2929fa6e4f0 6 (______/|_____)_|_|_| \__)_____)\____)_| |_|
mluis 1:60184eda0066 7 (C)2015 Semtech
mluis 0:a2929fa6e4f0 8
mluis 1:60184eda0066 9 Description: MBED LoRaWAN example application
mluis 0:a2929fa6e4f0 10
mluis 0:a2929fa6e4f0 11 License: Revised BSD License, see LICENSE.TXT file include in the project
mluis 0:a2929fa6e4f0 12
mluis 0:a2929fa6e4f0 13 Maintainer: Miguel Luis and Gregory Cristian
mluis 0:a2929fa6e4f0 14 */
mluis 1:60184eda0066 15 #include "mbed.h"
mluis 1:60184eda0066 16
mluis 0:a2929fa6e4f0 17 #include "lmic.h"
mluis 1:60184eda0066 18 #include "debug.h"
mluis 0:a2929fa6e4f0 19
janjongboom 6:e54c37d101f3 20
janjongboom 6:e54c37d101f3 21 /**********************
janjongboom 6:e54c37d101f3 22 * LORIOT SETTINGS
janjongboom 6:e54c37d101f3 23 **********************/
janjongboom 6:e54c37d101f3 24 static const uint32_t LORIOT_DEV_ADDR = 0x010E0845;
janjongboom 6:e54c37d101f3 25 static const char LORIOT_NWK_S_KEY[] = "88E5D1F343E83CE2ED96B2B6FD8B7893";
janjongboom 6:e54c37d101f3 26 static const char LORIOT_APP_S_KEY[] = "7453B7BF1C43AFC4939D96188BD88601";
janjongboom 6:e54c37d101f3 27
janjongboom 6:e54c37d101f3 28
janjongboom 6:e54c37d101f3 29
mluis 0:a2929fa6e4f0 30 /*!
mluis 0:a2929fa6e4f0 31 * When set to 1 the application uses the Over-the-Air activation procedure
mluis 0:a2929fa6e4f0 32 * When set to 0 the application uses the Personalization activation procedure
mluis 0:a2929fa6e4f0 33 */
mluis 0:a2929fa6e4f0 34 #define OVER_THE_AIR_ACTIVATION 0
mluis 0:a2929fa6e4f0 35
mluis 1:60184eda0066 36 #if( OVER_THE_AIR_ACTIVATION == 0 )
mluis 1:60184eda0066 37
mluis 1:60184eda0066 38 /*!
mluis 1:60184eda0066 39 * Defines the network ID when using personalization activation procedure
mluis 1:60184eda0066 40 */
mluis 1:60184eda0066 41 #define LORAWAN_NET_ID ( uint32_t )0x00000000
mluis 1:60184eda0066 42
mluis 1:60184eda0066 43 #endif
mluis 1:60184eda0066 44
mluis 1:60184eda0066 45 /*!
mluis 1:60184eda0066 46 * Defines the application data transmission duty cycle
mluis 1:60184eda0066 47 */
mluis 1:60184eda0066 48 #define APP_TX_DUTYCYCLE 5000 // 5 [s] value in ms
mluis 1:60184eda0066 49 #define APP_TX_DUTYCYCLE_RND 1000 // 1 [s] value in ms
mluis 1:60184eda0066 50
mluis 1:60184eda0066 51 /*!
mluis 1:60184eda0066 52 * LoRaWAN Adaptative Data Rate
mluis 1:60184eda0066 53 */
mluis 1:60184eda0066 54 #define LORAWAN_ADR_ON 1
mluis 1:60184eda0066 55
mluis 1:60184eda0066 56 /*!
mluis 1:60184eda0066 57 * LoRaWAN confirmed messages
mluis 1:60184eda0066 58 */
mluis 1:60184eda0066 59 #define LORAWAN_CONFIRMED_MSG_ON 1
mluis 1:60184eda0066 60
mluis 1:60184eda0066 61 /*!
mluis 1:60184eda0066 62 * LoRaWAN application port
mluis 1:60184eda0066 63 */
mluis 1:60184eda0066 64 #define LORAWAN_APP_PORT 15
mluis 1:60184eda0066 65
mluis 1:60184eda0066 66 /*!
mluis 1:60184eda0066 67 * User application data buffer size
mluis 1:60184eda0066 68 */
mluis 1:60184eda0066 69 #if ( LORAWAN_CONFIRMED_MSG_ON == 1 )
janjongboom 6:e54c37d101f3 70 #define LORAWAN_APP_DATA_SIZE 8
mluis 1:60184eda0066 71
mluis 1:60184eda0066 72 #else
janjongboom 6:e54c37d101f3 73 #define LORAWAN_APP_DATA_SIZE 3
mluis 1:60184eda0066 74
mluis 1:60184eda0066 75 #endif
mluis 0:a2929fa6e4f0 76
mluis 0:a2929fa6e4f0 77 //////////////////////////////////////////////////
mluis 0:a2929fa6e4f0 78 // CONFIGURATION (FOR APPLICATION CALLBACKS BELOW)
mluis 0:a2929fa6e4f0 79 //////////////////////////////////////////////////
mluis 0:a2929fa6e4f0 80
mluis 0:a2929fa6e4f0 81 // application router ID (LSBF)
mluis 1:60184eda0066 82 static const uint8_t AppEui[8] =
mluis 0:a2929fa6e4f0 83 {
mluis 1:60184eda0066 84 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
mluis 0:a2929fa6e4f0 85 };
mluis 0:a2929fa6e4f0 86
mluis 0:a2929fa6e4f0 87 // unique device ID (LSBF)
mluis 0:a2929fa6e4f0 88 static const u1_t DevEui[8] =
mluis 0:a2929fa6e4f0 89 {
mluis 0:a2929fa6e4f0 90 0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF
mluis 0:a2929fa6e4f0 91 };
mluis 0:a2929fa6e4f0 92
mluis 0:a2929fa6e4f0 93 // device-specific AES key (derived from device EUI)
mluis 1:60184eda0066 94 static const uint8_t DevKey[16] =
mluis 0:a2929fa6e4f0 95 {
mluis 1:60184eda0066 96 0x2B, 0x7E, 0x15, 0x16, 0x28, 0xAE, 0xD2, 0xA6,
mluis 1:60184eda0066 97 0xAB, 0xF7, 0x15, 0x88, 0x09, 0xCF, 0x4F, 0x3C
mluis 0:a2929fa6e4f0 98 };
mluis 0:a2929fa6e4f0 99
mluis 1:60184eda0066 100 #if( OVER_THE_AIR_ACTIVATION == 0 )
janjongboom 6:e54c37d101f3 101 static uint8_t NwkSKey[16];
janjongboom 6:e54c37d101f3 102 static uint8_t ArtSKey[16];
janjongboom 6:e54c37d101f3 103 #endif
mluis 0:a2929fa6e4f0 104
mluis 1:60184eda0066 105
mluis 0:a2929fa6e4f0 106 // LEDs and Frame jobs
mluis 0:a2929fa6e4f0 107 osjob_t rxLedJob;
mluis 0:a2929fa6e4f0 108 osjob_t txLedJob;
mluis 0:a2929fa6e4f0 109 osjob_t sendFrameJob;
mluis 0:a2929fa6e4f0 110
mluis 1:60184eda0066 111 // LED state
mluis 0:a2929fa6e4f0 112 static bool AppLedStateOn = false;
mluis 0:a2929fa6e4f0 113
mluis 0:a2929fa6e4f0 114 //////////////////////////////////////////////////
mluis 1:60184eda0066 115 // Utility functions
mluis 1:60184eda0066 116 //////////////////////////////////////////////////
mluis 1:60184eda0066 117 /*!
mluis 1:60184eda0066 118 * \brief Computes a random number between min and max
mluis 1:60184eda0066 119 *
mluis 1:60184eda0066 120 * \param [IN] min range minimum value
mluis 1:60184eda0066 121 * \param [IN] max range maximum value
mluis 1:60184eda0066 122 * \retval random random value in range min..max
mluis 1:60184eda0066 123 */
mluis 1:60184eda0066 124 int32_t randr( int32_t min, int32_t max )
mluis 1:60184eda0066 125 {
mluis 1:60184eda0066 126 return ( int32_t )rand( ) % ( max - min + 1 ) + min;
mluis 1:60184eda0066 127 }
mluis 1:60184eda0066 128
mluis 1:60184eda0066 129 //////////////////////////////////////////////////
mluis 0:a2929fa6e4f0 130 // APPLICATION CALLBACKS
mluis 0:a2929fa6e4f0 131 //////////////////////////////////////////////////
mluis 0:a2929fa6e4f0 132
mluis 0:a2929fa6e4f0 133 // provide application router ID (8 bytes, LSBF)
mluis 1:60184eda0066 134 void os_getArtEui( uint8_t *buf )
mluis 0:a2929fa6e4f0 135 {
mluis 0:a2929fa6e4f0 136 memcpy( buf, AppEui, 8 );
mluis 0:a2929fa6e4f0 137 }
mluis 0:a2929fa6e4f0 138
mluis 0:a2929fa6e4f0 139 // provide device ID (8 bytes, LSBF)
mluis 1:60184eda0066 140 void os_getDevEui( uint8_t *buf )
mluis 0:a2929fa6e4f0 141 {
mluis 0:a2929fa6e4f0 142 memcpy( buf, DevEui, 8 );
mluis 0:a2929fa6e4f0 143 }
mluis 0:a2929fa6e4f0 144
mluis 0:a2929fa6e4f0 145 // provide device key (16 bytes)
mluis 1:60184eda0066 146 void os_getDevKey( uint8_t *buf )
mluis 0:a2929fa6e4f0 147 {
mluis 0:a2929fa6e4f0 148 memcpy( buf, DevKey, 16 );
mluis 0:a2929fa6e4f0 149 }
mluis 0:a2929fa6e4f0 150
mluis 0:a2929fa6e4f0 151 //////////////////////////////////////////////////
mluis 0:a2929fa6e4f0 152 // MAIN - INITIALIZATION AND STARTUP
mluis 0:a2929fa6e4f0 153 //////////////////////////////////////////////////
mluis 0:a2929fa6e4f0 154
mluis 0:a2929fa6e4f0 155 static void onRxLed( osjob_t* j )
mluis 0:a2929fa6e4f0 156 {
mluis 1:60184eda0066 157 debug_val("LED2 = ", 0 );
mluis 0:a2929fa6e4f0 158 }
mluis 0:a2929fa6e4f0 159
mluis 0:a2929fa6e4f0 160 static void onTxLed( osjob_t* j )
mluis 0:a2929fa6e4f0 161 {
mluis 1:60184eda0066 162 debug_val("LED1 = ", 0 );
mluis 0:a2929fa6e4f0 163 }
mluis 0:a2929fa6e4f0 164
janjongboom 6:e54c37d101f3 165 static InterruptIn btn3(P0_19);
janjongboom 6:e54c37d101f3 166
janjongboom 6:e54c37d101f3 167 static int8_t clicks = 0; // overflows straight away when we register the fall() on the button
janjongboom 6:e54c37d101f3 168 static int8_t counter = 0;
mluis 0:a2929fa6e4f0 169 static void prepareTxFrame( void )
mluis 0:a2929fa6e4f0 170 {
janjongboom 6:e54c37d101f3 171 int16_t temp = (rand() % 500) + 2000;
janjongboom 6:e54c37d101f3 172
janjongboom 6:e54c37d101f3 173 // if you change this also change LORAWAN_APP_DATA_SIZE !!
janjongboom 6:e54c37d101f3 174 LMIC.frame[0] = clicks;
janjongboom 6:e54c37d101f3 175 LMIC.frame[1] = (temp >> 8) & 0xff;
janjongboom 6:e54c37d101f3 176 LMIC.frame[2] = temp & 0xff;
mluis 1:60184eda0066 177 #if ( LORAWAN_CONFIRMED_MSG_ON == 1 )
janjongboom 6:e54c37d101f3 178 LMIC.frame[3] = LMIC.seqnoDn >> 8;
janjongboom 6:e54c37d101f3 179 LMIC.frame[4] = LMIC.seqnoDn;
janjongboom 6:e54c37d101f3 180 LMIC.frame[5] = LMIC.rssi >> 8;
janjongboom 6:e54c37d101f3 181 LMIC.frame[6] = LMIC.rssi;
janjongboom 6:e54c37d101f3 182 LMIC.frame[7] = LMIC.snr;
mluis 1:60184eda0066 183 #endif
janjongboom 6:e54c37d101f3 184 printf("Sent frame %d\r\n", ++counter);
mluis 0:a2929fa6e4f0 185 }
mluis 0:a2929fa6e4f0 186
mluis 0:a2929fa6e4f0 187 void processRxFrame( void )
mluis 0:a2929fa6e4f0 188 {
mluis 0:a2929fa6e4f0 189 switch( LMIC.frame[LMIC.dataBeg - 1] ) // Check Rx port number
mluis 0:a2929fa6e4f0 190 {
mluis 0:a2929fa6e4f0 191 case 1: // The application LED can be controlled on port 1 or 2
mluis 0:a2929fa6e4f0 192 case 2:
mluis 0:a2929fa6e4f0 193 if( LMIC.dataLen == 1 )
mluis 0:a2929fa6e4f0 194 {
mluis 0:a2929fa6e4f0 195 AppLedStateOn = LMIC.frame[LMIC.dataBeg] & 0x01;
mluis 1:60184eda0066 196 debug_val( "LED3 = ", AppLedStateOn );
mluis 0:a2929fa6e4f0 197 }
mluis 0:a2929fa6e4f0 198 break;
mluis 0:a2929fa6e4f0 199 default:
mluis 0:a2929fa6e4f0 200 break;
mluis 0:a2929fa6e4f0 201 }
mluis 0:a2929fa6e4f0 202 }
mluis 0:a2929fa6e4f0 203
mluis 0:a2929fa6e4f0 204 static void onSendFrame( osjob_t* j )
mluis 0:a2929fa6e4f0 205 {
mluis 0:a2929fa6e4f0 206 prepareTxFrame( );
mluis 1:60184eda0066 207 LMIC_setTxData2( LORAWAN_APP_PORT, LMIC.frame, LORAWAN_APP_DATA_SIZE, LORAWAN_CONFIRMED_MSG_ON );
mluis 1:60184eda0066 208
mluis 1:60184eda0066 209 // Blink Tx LED
mluis 1:60184eda0066 210 debug_val( "LED1 = ", 1 );
mluis 1:60184eda0066 211 os_setTimedCallback( &txLedJob, os_getTime( ) + ms2osticks( 25 ), onTxLed );
mluis 0:a2929fa6e4f0 212 }
mluis 0:a2929fa6e4f0 213
mluis 1:60184eda0066 214 // Initialization job
mluis 1:60184eda0066 215 static void onInit( osjob_t* j )
mluis 1:60184eda0066 216 {
mluis 1:60184eda0066 217 // reset MAC state
mluis 1:60184eda0066 218 LMIC_reset( );
mluis 1:60184eda0066 219 LMIC_setAdrMode( LORAWAN_ADR_ON );
mluis 5:1b2fcc2582e8 220 #if defined(CFG_eu868)
janjongboom 6:e54c37d101f3 221 LMIC_setDrTxpow( DR_SF7, 14 );
mluis 5:1b2fcc2582e8 222 #elif defined(CFG_us915)
mluis 5:1b2fcc2582e8 223 LMIC_setDrTxpow( DR_SF10, 14 );
mluis 5:1b2fcc2582e8 224 #endif
mluis 1:60184eda0066 225
mluis 1:60184eda0066 226 // start joining
mluis 1:60184eda0066 227 #if( OVER_THE_AIR_ACTIVATION != 0 )
mluis 1:60184eda0066 228 LMIC_startJoining( );
mluis 1:60184eda0066 229 #else
janjongboom 6:e54c37d101f3 230 // parse devkey
janjongboom 6:e54c37d101f3 231 static int ni;
janjongboom 6:e54c37d101f3 232 for (ni = 0; ni < 16; ni++)
janjongboom 6:e54c37d101f3 233 {
janjongboom 6:e54c37d101f3 234 char *non_numeric_ptr;
janjongboom 6:e54c37d101f3 235 const char hex[] = { '0', 'x', LORIOT_NWK_S_KEY[ni * 2], LORIOT_NWK_S_KEY[ni * 2 + 1] };
janjongboom 6:e54c37d101f3 236 NwkSKey[ni] = strtoul(hex, &non_numeric_ptr, 16);
janjongboom 6:e54c37d101f3 237 free(non_numeric_ptr);
janjongboom 6:e54c37d101f3 238 }
janjongboom 6:e54c37d101f3 239
janjongboom 6:e54c37d101f3 240 // parse appkey
janjongboom 6:e54c37d101f3 241 static int ai;
janjongboom 6:e54c37d101f3 242 for (ai = 0; ai < 16; ai++)
janjongboom 6:e54c37d101f3 243 {
janjongboom 6:e54c37d101f3 244 char *non_numeric_ptr;
janjongboom 6:e54c37d101f3 245 const char hex[] = { '0', 'x', LORIOT_APP_S_KEY[ai * 2], LORIOT_APP_S_KEY[ai * 2 + 1] };
janjongboom 6:e54c37d101f3 246 ArtSKey[ai] = strtoul(hex, &non_numeric_ptr, 16);
janjongboom 6:e54c37d101f3 247 free(non_numeric_ptr);
janjongboom 6:e54c37d101f3 248 }
janjongboom 6:e54c37d101f3 249
janjongboom 6:e54c37d101f3 250 LMIC_setSession( LORAWAN_NET_ID, LORIOT_DEV_ADDR, NwkSKey, ArtSKey );
mluis 1:60184eda0066 251 onSendFrame( NULL );
mluis 1:60184eda0066 252 #endif
mluis 1:60184eda0066 253 // init done - onEvent( ) callback will be invoked...
mluis 1:60184eda0066 254 }
mluis 1:60184eda0066 255
janjongboom 6:e54c37d101f3 256 void btn3_click() {
janjongboom 6:e54c37d101f3 257 clicks++;
janjongboom 6:e54c37d101f3 258 printf("btn3 click count is %d\r\n", clicks);
janjongboom 6:e54c37d101f3 259 onSendFrame(NULL);
janjongboom 6:e54c37d101f3 260 }
janjongboom 6:e54c37d101f3 261
mluis 1:60184eda0066 262 int main( void )
mluis 0:a2929fa6e4f0 263 {
janjongboom 6:e54c37d101f3 264 btn3.fall(&btn3_click);
janjongboom 6:e54c37d101f3 265
mluis 0:a2929fa6e4f0 266 osjob_t initjob;
mluis 0:a2929fa6e4f0 267
mluis 0:a2929fa6e4f0 268 // initialize runtime env
mluis 0:a2929fa6e4f0 269 os_init( );
mluis 0:a2929fa6e4f0 270 // setup initial job
mluis 0:a2929fa6e4f0 271 os_setCallback( &initjob, onInit );
mluis 0:a2929fa6e4f0 272 // execute scheduled jobs and events
mluis 0:a2929fa6e4f0 273 os_runloop( );
mluis 0:a2929fa6e4f0 274 // (not reached)
mluis 0:a2929fa6e4f0 275 }
mluis 0:a2929fa6e4f0 276
mluis 0:a2929fa6e4f0 277 //////////////////////////////////////////////////
mluis 0:a2929fa6e4f0 278 // LMIC EVENT CALLBACK
mluis 0:a2929fa6e4f0 279 //////////////////////////////////////////////////
mluis 0:a2929fa6e4f0 280 void onEvent( ev_t ev )
mluis 0:a2929fa6e4f0 281 {
mluis 0:a2929fa6e4f0 282 bool txOn = false;
mluis 1:60184eda0066 283 debug_event( ev );
mluis 0:a2929fa6e4f0 284
mluis 0:a2929fa6e4f0 285 switch( ev )
mluis 0:a2929fa6e4f0 286 {
mluis 0:a2929fa6e4f0 287 // network joined, session established
mluis 0:a2929fa6e4f0 288 case EV_JOINED:
mluis 1:60184eda0066 289 debug_val( "Net ID = ", LMIC.netid );
mluis 0:a2929fa6e4f0 290 txOn = true;
mluis 0:a2929fa6e4f0 291 break;
mluis 0:a2929fa6e4f0 292 // scheduled data sent (optionally data received)
mluis 0:a2929fa6e4f0 293 case EV_TXCOMPLETE:
mluis 1:60184eda0066 294 debug_val( "Datarate = ", LMIC.datarate );
mluis 0:a2929fa6e4f0 295 // Check if we have a downlink on either Rx1 or Rx2 windows
mluis 1:60184eda0066 296 if( ( LMIC.txrxFlags & ( TXRX_DNW1 | TXRX_DNW2 ) ) != 0 )
mluis 0:a2929fa6e4f0 297 {
mluis 1:60184eda0066 298 debug_val( "LED2 = ", 1 );
mluis 1:60184eda0066 299 os_setTimedCallback( &rxLedJob, os_getTime( ) + ms2osticks( 25 ), onRxLed );
mluis 0:a2929fa6e4f0 300
mluis 1:60184eda0066 301 if( LMIC.dataLen != 0 )
mluis 0:a2929fa6e4f0 302 { // data received in rx slot after tx
mluis 1:60184eda0066 303 debug_buf( LMIC.frame + LMIC.dataBeg, LMIC.dataLen );
mluis 0:a2929fa6e4f0 304 processRxFrame( );
mluis 0:a2929fa6e4f0 305 }
mluis 0:a2929fa6e4f0 306 }
mluis 0:a2929fa6e4f0 307 txOn = true;
mluis 0:a2929fa6e4f0 308 break;
mluis 0:a2929fa6e4f0 309 default:
mluis 0:a2929fa6e4f0 310 break;
mluis 0:a2929fa6e4f0 311 }
mluis 0:a2929fa6e4f0 312 }