Dependencies:   STM32F103c8t6-LoRaWAN-lmic SX1276Lib mbed-STM32F103C8T6 mbed

Fork of LoRaWAN-lmic-app by Semtech

Committer:
mistery
Date:
Wed Apr 19 08:00:38 2017 +0000
Revision:
6:6fe6c547ba55
Parent:
5:1b2fcc2582e8
LoRaWAN

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 */
mistery 6:6fe6c547ba55 15 #include "stm32f103c8t6.h"
mluis 1:60184eda0066 16 #include "mbed.h"
mluis 1:60184eda0066 17
mluis 0:a2929fa6e4f0 18 #include "lmic.h"
mluis 1:60184eda0066 19 #include "debug.h"
mluis 0:a2929fa6e4f0 20
mluis 0:a2929fa6e4f0 21 /*!
mluis 0:a2929fa6e4f0 22 * When set to 1 the application uses the Over-the-Air activation procedure
mluis 0:a2929fa6e4f0 23 * When set to 0 the application uses the Personalization activation procedure
mluis 0:a2929fa6e4f0 24 */
mistery 6:6fe6c547ba55 25
mistery 6:6fe6c547ba55 26 #define SINGLE_CHANNEL_GATEWAY 1
mistery 6:6fe6c547ba55 27 #define OVER_THE_AIR_ACTIVATION 1
mluis 0:a2929fa6e4f0 28
mluis 1:60184eda0066 29 #if( OVER_THE_AIR_ACTIVATION == 0 )
mluis 1:60184eda0066 30
mluis 1:60184eda0066 31 /*!
mluis 1:60184eda0066 32 * Defines the network ID when using personalization activation procedure
mluis 1:60184eda0066 33 */
mluis 1:60184eda0066 34 #define LORAWAN_NET_ID ( uint32_t )0x00000000
mluis 1:60184eda0066 35
mluis 1:60184eda0066 36 /*!
mluis 1:60184eda0066 37 * Defines the device address when using personalization activation procedure
mluis 1:60184eda0066 38 */
mistery 6:6fe6c547ba55 39 #define LORAWAN_DEV_ADDR ( uint32_t )0x12345679
mluis 1:60184eda0066 40
mluis 1:60184eda0066 41 #endif
mluis 1:60184eda0066 42
mluis 1:60184eda0066 43 /*!
mluis 1:60184eda0066 44 * Defines the application data transmission duty cycle
mluis 1:60184eda0066 45 */
mistery 6:6fe6c547ba55 46 #define APP_TX_DUTYCYCLE 60000 // 5 [s] value in ms 1min
mistery 6:6fe6c547ba55 47 #define APP_TX_DUTYCYCLE_RND 50000 // 1 [s] value in ms
mluis 1:60184eda0066 48
mluis 1:60184eda0066 49 /*!
mluis 1:60184eda0066 50 * LoRaWAN Adaptative Data Rate
mluis 1:60184eda0066 51 */
mluis 1:60184eda0066 52 #define LORAWAN_ADR_ON 1
mistery 6:6fe6c547ba55 53 //#define LORAWAN_ADR_ON 1
mluis 1:60184eda0066 54
mluis 1:60184eda0066 55 /*!
mluis 1:60184eda0066 56 * LoRaWAN confirmed messages
mluis 1:60184eda0066 57 */
mistery 6:6fe6c547ba55 58 //#define LORAWAN_CONFIRMED_MSG_ON 1
mluis 1:60184eda0066 59 #define LORAWAN_CONFIRMED_MSG_ON 1
mluis 1:60184eda0066 60 /*!
mluis 1:60184eda0066 61 * LoRaWAN application port
mluis 1:60184eda0066 62 */
mluis 1:60184eda0066 63 #define LORAWAN_APP_PORT 15
mluis 1:60184eda0066 64
mluis 1:60184eda0066 65 /*!
mluis 1:60184eda0066 66 * User application data buffer size
mluis 1:60184eda0066 67 */
mluis 1:60184eda0066 68 #if ( LORAWAN_CONFIRMED_MSG_ON == 1 )
mluis 1:60184eda0066 69 #define LORAWAN_APP_DATA_SIZE 6
mluis 1:60184eda0066 70
mluis 1:60184eda0066 71 #else
mluis 1:60184eda0066 72 #define LORAWAN_APP_DATA_SIZE 1
mluis 1:60184eda0066 73
mluis 1:60184eda0066 74 #endif
mluis 0:a2929fa6e4f0 75
mluis 0:a2929fa6e4f0 76 //////////////////////////////////////////////////
mluis 0:a2929fa6e4f0 77 // CONFIGURATION (FOR APPLICATION CALLBACKS BELOW)
mluis 0:a2929fa6e4f0 78 //////////////////////////////////////////////////
mluis 0:a2929fa6e4f0 79
mistery 6:6fe6c547ba55 80 //fe dc ba 98 76 54 32 10
mluis 0:a2929fa6e4f0 81 // application router ID (LSBF)
mluis 1:60184eda0066 82 static const uint8_t AppEui[8] =
mluis 0:a2929fa6e4f0 83 {
mistery 6:6fe6c547ba55 84 0xb8, 0x27, 0xeb, 0xff, 0xff, 0xef, 0x00, 0x62
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 {
mistery 6:6fe6c547ba55 90 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
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 {
mistery 6:6fe6c547ba55 96
mistery 6:6fe6c547ba55 97 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
mistery 6:6fe6c547ba55 98 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
mluis 0:a2929fa6e4f0 99 };
mluis 0:a2929fa6e4f0 100
mluis 1:60184eda0066 101 #if( OVER_THE_AIR_ACTIVATION == 0 )
mluis 1:60184eda0066 102 // network session key
mluis 0:a2929fa6e4f0 103 static uint8_t NwkSKey[] =
mluis 0:a2929fa6e4f0 104 {
mistery 6:6fe6c547ba55 105 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
mistery 6:6fe6c547ba55 106 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
mluis 0:a2929fa6e4f0 107 };
mluis 0:a2929fa6e4f0 108
mluis 1:60184eda0066 109 // application session key
mluis 0:a2929fa6e4f0 110 static uint8_t ArtSKey[] =
mluis 0:a2929fa6e4f0 111 {
mistery 6:6fe6c547ba55 112 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
mistery 6:6fe6c547ba55 113 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
mluis 0:a2929fa6e4f0 114 };
mluis 0:a2929fa6e4f0 115
mluis 1:60184eda0066 116 #endif
mluis 1:60184eda0066 117
mluis 0:a2929fa6e4f0 118 // LEDs and Frame jobs
mluis 0:a2929fa6e4f0 119 osjob_t rxLedJob;
mluis 0:a2929fa6e4f0 120 osjob_t txLedJob;
mluis 0:a2929fa6e4f0 121 osjob_t sendFrameJob;
mistery 6:6fe6c547ba55 122 DigitalOut myled(LED1);
mluis 0:a2929fa6e4f0 123
mluis 1:60184eda0066 124 // LED state
mistery 6:6fe6c547ba55 125 static bool AppLedStateOn = true;
mluis 0:a2929fa6e4f0 126
mluis 0:a2929fa6e4f0 127 //////////////////////////////////////////////////
mluis 1:60184eda0066 128 // Utility functions
mluis 1:60184eda0066 129 //////////////////////////////////////////////////
mluis 1:60184eda0066 130 /*!
mluis 1:60184eda0066 131 * \brief Computes a random number between min and max
mluis 1:60184eda0066 132 *
mluis 1:60184eda0066 133 * \param [IN] min range minimum value
mluis 1:60184eda0066 134 * \param [IN] max range maximum value
mluis 1:60184eda0066 135 * \retval random random value in range min..max
mluis 1:60184eda0066 136 */
mluis 1:60184eda0066 137 int32_t randr( int32_t min, int32_t max )
mluis 1:60184eda0066 138 {
mluis 1:60184eda0066 139 return ( int32_t )rand( ) % ( max - min + 1 ) + min;
mluis 1:60184eda0066 140 }
mluis 1:60184eda0066 141
mluis 1:60184eda0066 142 //////////////////////////////////////////////////
mluis 0:a2929fa6e4f0 143 // APPLICATION CALLBACKS
mluis 0:a2929fa6e4f0 144 //////////////////////////////////////////////////
mluis 0:a2929fa6e4f0 145
mluis 0:a2929fa6e4f0 146 // provide application router ID (8 bytes, LSBF)
mluis 1:60184eda0066 147 void os_getArtEui( uint8_t *buf )
mluis 0:a2929fa6e4f0 148 {
mluis 0:a2929fa6e4f0 149 memcpy( buf, AppEui, 8 );
mluis 0:a2929fa6e4f0 150 }
mluis 0:a2929fa6e4f0 151
mluis 0:a2929fa6e4f0 152 // provide device ID (8 bytes, LSBF)
mluis 1:60184eda0066 153 void os_getDevEui( uint8_t *buf )
mluis 0:a2929fa6e4f0 154 {
mluis 0:a2929fa6e4f0 155 memcpy( buf, DevEui, 8 );
mluis 0:a2929fa6e4f0 156 }
mluis 0:a2929fa6e4f0 157
mluis 0:a2929fa6e4f0 158 // provide device key (16 bytes)
mluis 1:60184eda0066 159 void os_getDevKey( uint8_t *buf )
mluis 0:a2929fa6e4f0 160 {
mluis 0:a2929fa6e4f0 161 memcpy( buf, DevKey, 16 );
mluis 0:a2929fa6e4f0 162 }
mluis 0:a2929fa6e4f0 163
mluis 0:a2929fa6e4f0 164 //////////////////////////////////////////////////
mluis 0:a2929fa6e4f0 165 // MAIN - INITIALIZATION AND STARTUP
mluis 0:a2929fa6e4f0 166 //////////////////////////////////////////////////
mluis 0:a2929fa6e4f0 167
mluis 0:a2929fa6e4f0 168 static void onRxLed( osjob_t* j )
mluis 0:a2929fa6e4f0 169 {
mluis 1:60184eda0066 170 debug_val("LED2 = ", 0 );
mluis 0:a2929fa6e4f0 171 }
mluis 0:a2929fa6e4f0 172
mluis 0:a2929fa6e4f0 173 static void onTxLed( osjob_t* j )
mluis 0:a2929fa6e4f0 174 {
mluis 1:60184eda0066 175 debug_val("LED1 = ", 0 );
mluis 0:a2929fa6e4f0 176 }
mluis 0:a2929fa6e4f0 177
mluis 0:a2929fa6e4f0 178 static void prepareTxFrame( void )
mluis 0:a2929fa6e4f0 179 {
mluis 0:a2929fa6e4f0 180 LMIC.frame[0] = AppLedStateOn;
mluis 1:60184eda0066 181 #if ( LORAWAN_CONFIRMED_MSG_ON == 1 )
mluis 1:60184eda0066 182 LMIC.frame[1] = LMIC.seqnoDn >> 8;
mluis 1:60184eda0066 183 LMIC.frame[2] = LMIC.seqnoDn;
mluis 1:60184eda0066 184 LMIC.frame[3] = LMIC.rssi >> 8;
mluis 1:60184eda0066 185 LMIC.frame[4] = LMIC.rssi;
mluis 1:60184eda0066 186 LMIC.frame[5] = LMIC.snr;
mluis 1:60184eda0066 187 #endif
mluis 0:a2929fa6e4f0 188 }
mluis 0:a2929fa6e4f0 189
mluis 0:a2929fa6e4f0 190 void processRxFrame( void )
mluis 0:a2929fa6e4f0 191 {
mluis 0:a2929fa6e4f0 192 switch( LMIC.frame[LMIC.dataBeg - 1] ) // Check Rx port number
mluis 0:a2929fa6e4f0 193 {
mluis 0:a2929fa6e4f0 194 case 1: // The application LED can be controlled on port 1 or 2
mluis 0:a2929fa6e4f0 195 case 2:
mluis 0:a2929fa6e4f0 196 if( LMIC.dataLen == 1 )
mluis 0:a2929fa6e4f0 197 {
mluis 0:a2929fa6e4f0 198 AppLedStateOn = LMIC.frame[LMIC.dataBeg] & 0x01;
mluis 1:60184eda0066 199 debug_val( "LED3 = ", AppLedStateOn );
mluis 0:a2929fa6e4f0 200 }
mluis 0:a2929fa6e4f0 201 break;
mluis 0:a2929fa6e4f0 202 default:
mluis 0:a2929fa6e4f0 203 break;
mluis 0:a2929fa6e4f0 204 }
mluis 0:a2929fa6e4f0 205 }
mluis 0:a2929fa6e4f0 206
mluis 0:a2929fa6e4f0 207 static void onSendFrame( osjob_t* j )
mluis 0:a2929fa6e4f0 208 {
mluis 0:a2929fa6e4f0 209 prepareTxFrame( );
mluis 1:60184eda0066 210 LMIC_setTxData2( LORAWAN_APP_PORT, LMIC.frame, LORAWAN_APP_DATA_SIZE, LORAWAN_CONFIRMED_MSG_ON );
mluis 1:60184eda0066 211
mluis 1:60184eda0066 212 // Blink Tx LED
mluis 1:60184eda0066 213 debug_val( "LED1 = ", 1 );
mluis 1:60184eda0066 214 os_setTimedCallback( &txLedJob, os_getTime( ) + ms2osticks( 25 ), onTxLed );
mluis 0:a2929fa6e4f0 215 }
mluis 0:a2929fa6e4f0 216
mluis 1:60184eda0066 217 // Initialization job
mluis 1:60184eda0066 218 static void onInit( osjob_t* j )
mluis 1:60184eda0066 219 {
mluis 1:60184eda0066 220 // reset MAC state
mluis 1:60184eda0066 221 LMIC_reset( );
mistery 6:6fe6c547ba55 222 //LMIC_setAdrMode( LORAWAN_ADR_ON );
mistery 6:6fe6c547ba55 223 LMIC_setAdrMode(0);
mistery 6:6fe6c547ba55 224 LMIC_setLinkCheckMode(0);
mistery 6:6fe6c547ba55 225 LMIC_disableTracking ();
mistery 6:6fe6c547ba55 226 LMIC_stopPingable();
mistery 6:6fe6c547ba55 227 // LMIC_setDrTxpow(DR_SF7,14);
mistery 6:6fe6c547ba55 228
mluis 5:1b2fcc2582e8 229 #if defined(CFG_eu868)
mistery 6:6fe6c547ba55 230 //LMIC_setDrTxpow( DR_SF12, 14 );
mistery 6:6fe6c547ba55 231 LMIC_setDrTxpow(DR_SF12,14);
mluis 5:1b2fcc2582e8 232 #elif defined(CFG_us915)
mluis 5:1b2fcc2582e8 233 LMIC_setDrTxpow( DR_SF10, 14 );
mluis 5:1b2fcc2582e8 234 #endif
mluis 1:60184eda0066 235
mluis 1:60184eda0066 236 // start joining
mluis 1:60184eda0066 237 #if( OVER_THE_AIR_ACTIVATION != 0 )
mluis 1:60184eda0066 238 LMIC_startJoining( );
mluis 1:60184eda0066 239 #else
mluis 1:60184eda0066 240 LMIC_setSession( LORAWAN_NET_ID, LORAWAN_DEV_ADDR, NwkSKey, ArtSKey );
mluis 1:60184eda0066 241 onSendFrame( NULL );
mluis 1:60184eda0066 242 #endif
mluis 1:60184eda0066 243 // init done - onEvent( ) callback will be invoked...
mluis 1:60184eda0066 244 }
mluis 1:60184eda0066 245
mluis 1:60184eda0066 246 int main( void )
mluis 0:a2929fa6e4f0 247 {
mistery 6:6fe6c547ba55 248
mistery 6:6fe6c547ba55 249 #ifdef SINGLE_CHANNEL_GATEWAY
mistery 6:6fe6c547ba55 250 //MAX_CHANNELS = 1;
mistery 6:6fe6c547ba55 251 //MAX_BANDS = 1;
mistery 6:6fe6c547ba55 252 //LIMIT_CHANNELS = 1;
mistery 6:6fe6c547ba55 253 for (int i=1; i<16; i++)
mistery 6:6fe6c547ba55 254 LMIC_disableChannel(i);
mistery 6:6fe6c547ba55 255 #endif
mistery 6:6fe6c547ba55 256 //confSysClock();
mistery 6:6fe6c547ba55 257 //DigitalOut myled(LED1);
mistery 6:6fe6c547ba55 258 myled = 0; // turn the LED on
mistery 6:6fe6c547ba55 259
mluis 0:a2929fa6e4f0 260 osjob_t initjob;
mluis 0:a2929fa6e4f0 261 // initialize runtime env
mluis 0:a2929fa6e4f0 262 os_init( );
mluis 0:a2929fa6e4f0 263 // setup initial job
mluis 0:a2929fa6e4f0 264 os_setCallback( &initjob, onInit );
mluis 0:a2929fa6e4f0 265 // execute scheduled jobs and events
mluis 0:a2929fa6e4f0 266 os_runloop( );
mluis 0:a2929fa6e4f0 267 // (not reached)
mluis 0:a2929fa6e4f0 268 }
mluis 0:a2929fa6e4f0 269
mluis 0:a2929fa6e4f0 270 //////////////////////////////////////////////////
mluis 0:a2929fa6e4f0 271 // LMIC EVENT CALLBACK
mluis 0:a2929fa6e4f0 272 //////////////////////////////////////////////////
mluis 0:a2929fa6e4f0 273 void onEvent( ev_t ev )
mluis 0:a2929fa6e4f0 274 {
mluis 0:a2929fa6e4f0 275 bool txOn = false;
mluis 1:60184eda0066 276 debug_event( ev );
mluis 0:a2929fa6e4f0 277
mluis 0:a2929fa6e4f0 278 switch( ev )
mluis 0:a2929fa6e4f0 279 {
mluis 0:a2929fa6e4f0 280 // network joined, session established
mluis 0:a2929fa6e4f0 281 case EV_JOINED:
mluis 1:60184eda0066 282 debug_val( "Net ID = ", LMIC.netid );
mluis 0:a2929fa6e4f0 283 txOn = true;
mluis 0:a2929fa6e4f0 284 break;
mluis 0:a2929fa6e4f0 285 // scheduled data sent (optionally data received)
mluis 0:a2929fa6e4f0 286 case EV_TXCOMPLETE:
mluis 1:60184eda0066 287 debug_val( "Datarate = ", LMIC.datarate );
mluis 0:a2929fa6e4f0 288 // Check if we have a downlink on either Rx1 or Rx2 windows
mluis 1:60184eda0066 289 if( ( LMIC.txrxFlags & ( TXRX_DNW1 | TXRX_DNW2 ) ) != 0 )
mluis 0:a2929fa6e4f0 290 {
mluis 1:60184eda0066 291 debug_val( "LED2 = ", 1 );
mluis 1:60184eda0066 292 os_setTimedCallback( &rxLedJob, os_getTime( ) + ms2osticks( 25 ), onRxLed );
mluis 0:a2929fa6e4f0 293
mluis 1:60184eda0066 294 if( LMIC.dataLen != 0 )
mluis 0:a2929fa6e4f0 295 { // data received in rx slot after tx
mluis 1:60184eda0066 296 debug_buf( LMIC.frame + LMIC.dataBeg, LMIC.dataLen );
mluis 0:a2929fa6e4f0 297 processRxFrame( );
mluis 0:a2929fa6e4f0 298 }
mluis 0:a2929fa6e4f0 299 }
mluis 0:a2929fa6e4f0 300 txOn = true;
mluis 0:a2929fa6e4f0 301 break;
mluis 0:a2929fa6e4f0 302 default:
mluis 0:a2929fa6e4f0 303 break;
mluis 0:a2929fa6e4f0 304 }
mistery 6:6fe6c547ba55 305 myled = 1; // turn the LED off
mluis 0:a2929fa6e4f0 306 if( txOn == true )
mluis 0:a2929fa6e4f0 307 {
mluis 1:60184eda0066 308 //Sends frame every APP_TX_DUTYCYCLE +/- APP_TX_DUTYCYCLE_RND random time (if not duty cycle limited)
mluis 1:60184eda0066 309 os_setTimedCallback( &sendFrameJob,
mistery 6:6fe6c547ba55 310 os_getTime( ) + ms2osticks( ((APP_TX_DUTYCYCLE) + randr( 10000, 60000 ))*2 ),
mluis 1:60184eda0066 311 onSendFrame );
mistery 6:6fe6c547ba55 312 myled = !myled; // turn the LED on
mluis 1:60184eda0066 313 ////Sends frame as soon as possible (duty cylce limitations)
mluis 1:60184eda0066 314 //onSendFrame( NULL );
mluis 0:a2929fa6e4f0 315 }
mluis 0:a2929fa6e4f0 316 }