first draft

Dependencies:   LMiC SX1272Libx mbed

Fork of LoRaWAN-lmic-app by Semtech

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers main.cpp Source File

main.cpp

00001 /* 
00002  / _____)             _              | |
00003 ( (____  _____ ____ _| |_ _____  ____| |__
00004  \____ \| ___ |    (_   _) ___ |/ ___)  _ \
00005  _____) ) ____| | | || |_| ____( (___| | | |
00006 (______/|_____)_|_|_| \__)_____)\____)_| |_|
00007     (C)2015 Semtech
00008 
00009 Description: MBED LoRaWAN example application
00010 
00011 License: Revised BSD License, see LICENSE.TXT file include in the project
00012 
00013 Maintainer: Miguel Luis and Gregory Cristian
00014 */
00015 #include "mbed.h"
00016 
00017 #include "lmic.h"
00018 #include "debug.h"
00019 
00020 /*!
00021  * When set to 1 the application uses the Over-the-Air activation procedure
00022  * When set to 0 the application uses the Personalization activation procedure
00023  */
00024 #define OVER_THE_AIR_ACTIVATION                     1
00025 
00026 #if( OVER_THE_AIR_ACTIVATION == 0 )
00027 
00028 /*!
00029  * Defines the network ID when using personalization activation procedure
00030  */
00031 #define LORAWAN_NET_ID                              ( uint32_t )0x00000000
00032 
00033 /*!
00034  * Defines the device address when using personalization activation procedure
00035  */
00036 #define LORAWAN_DEV_ADDR                            ( uint32_t )0x12345678
00037 
00038 #endif
00039 
00040 /*!
00041  * Defines the application data transmission duty cycle
00042  */
00043 #define APP_TX_DUTYCYCLE                            5000 // 5 [s] value in ms
00044 #define APP_TX_DUTYCYCLE_RND                        1000 // 1 [s] value in ms
00045 
00046 /*!
00047  * LoRaWAN Adaptative Data Rate
00048  */
00049 #define LORAWAN_ADR_ON                              1
00050 
00051 /*!
00052  * LoRaWAN confirmed messages
00053  */
00054 #define LORAWAN_CONFIRMED_MSG_ON                    1
00055 
00056 /*!
00057  * LoRaWAN application port
00058  */
00059 #define LORAWAN_APP_PORT                            15
00060 
00061 /*!
00062  * User application data buffer size
00063  */
00064 #if ( LORAWAN_CONFIRMED_MSG_ON == 1 )
00065 #define LORAWAN_APP_DATA_SIZE                       6
00066 
00067 #else
00068 #define LORAWAN_APP_DATA_SIZE                       1
00069 
00070 #endif
00071 Serial pc(PTE0, PTE1);
00072 #define LED_RED         PTA1
00073 #define LED_YEL         PTA2
00074 
00075 /* version history */
00076 /* version  date        comments */
00077 /* 0.1      02/26/16    first working join - no tx/rx */
00078 
00079 #define MAJOR           0
00080 #define MINOR           1
00081 
00082 DigitalOut led1(LED_RED);
00083 DigitalOut led2(LED_YEL);
00084 
00085 //////////////////////////////////////////////////
00086 // CONFIGURATION (FOR APPLICATION CALLBACKS BELOW)
00087 //////////////////////////////////////////////////
00088 // application router ID (LSBF)
00089 //static const u1_t AppEui[8]  = { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77 };
00090 static const u1_t AppEui[8]  = { 0x77, 0x66, 0x55, 0x44, 0x33, 0x22, 0x11, 0x00 };
00091 
00092 // unique device ID (LSBF)
00093 static const u1_t DevEui[8]  = { 0x02, 0x00, 0x00, 0x00, 0x00, 0xee, 0xff, 0xc0 };
00094 
00095 // device-specific AES key (derived from device EUI)
00096 static const u1_t DevKey[16] = { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF, };
00097                              //    E4   -72   -71   -C5   -F5   -30   -A9   -9F   -CF   -C4   -0E   -AB   -EA   -D7   -19   -42
00098 #if( OVER_THE_AIR_ACTIVATION == 0 )
00099 // network session key
00100 static uint8_t NwkSKey[] = 
00101 { 
00102     0x2B, 0x7E, 0x15, 0x16, 0x28, 0xAE, 0xD2, 0xA6,
00103     0xAB, 0xF7, 0x15, 0x88, 0x09, 0xCF, 0x4F, 0x3C
00104 };
00105 
00106 // application session key
00107 static uint8_t ArtSKey[] = 
00108 { 
00109     0x2B, 0x7E, 0x15, 0x16, 0x28, 0xAE, 0xD2, 0xA6,
00110     0xAB, 0xF7, 0x15, 0x88, 0x09, 0xCF, 0x4F, 0x3C
00111 };
00112 
00113 #endif
00114 
00115 // LEDs and Frame jobs
00116 osjob_t rxLedJob;
00117 osjob_t txLedJob;
00118 osjob_t sendFrameJob;
00119 
00120 // LED state
00121 static bool AppLedStateOn = false;
00122 
00123 //////////////////////////////////////////////////
00124 // Utility functions
00125 //////////////////////////////////////////////////
00126 /*!
00127  * \brief Computes a random number between min and max
00128  *
00129  * \param [IN] min range minimum value
00130  * \param [IN] max range maximum value
00131  * \retval random random value in range min..max
00132  */
00133 int32_t randr( int32_t min, int32_t max )
00134 {
00135     return ( int32_t )rand( ) % ( max - min + 1 ) + min;
00136 }
00137 
00138 //////////////////////////////////////////////////
00139 // APPLICATION CALLBACKS
00140 //////////////////////////////////////////////////
00141 
00142 // provide application router ID (8 bytes, LSBF)
00143 void os_getArtEui( uint8_t *buf )
00144 {
00145     memcpy( buf, AppEui, 8 );
00146     debug("os_getArtEui enter");
00147     for(int i=0;i<8;i++)
00148         debug(" %02X",buf[i]);
00149     debug("\r\n");
00150 }
00151 
00152 // provide device ID (8 bytes, LSBF)
00153 void os_getDevEui( uint8_t *buf )
00154 {
00155     memcpy( buf, DevEui, 8 );
00156     debug("os_getDevEui enter");
00157     for(int i=0;i<8;i++)
00158         debug(" %02X",buf[i]);
00159     debug("\r\n");
00160 }
00161 
00162 // provide device key (16 bytes)
00163 void os_getDevKey( uint8_t *buf )
00164 {
00165     memcpy( buf, DevKey, 16 );
00166     debug("os_getDevKey enter");
00167     for(int i=0;i<16;i++)
00168         debug(" %02X",buf[i]);
00169     debug("\r\n");
00170 }
00171 
00172 //////////////////////////////////////////////////
00173 // MAIN - INITIALIZATION AND STARTUP
00174 //////////////////////////////////////////////////
00175 
00176 static void onRxLed( osjob_t* j )
00177 {
00178     led2 = 0;
00179     debug_val("LED2 = ", 0 );
00180 }
00181 
00182 static void onTxLed( osjob_t* j )
00183 {
00184     led1 = 0;
00185     debug_val("LED1 = ", 0 );
00186 }
00187 
00188 static void prepareTxFrame( void )
00189 {
00190     LMIC.frame[0] = AppLedStateOn;
00191 #if ( LORAWAN_CONFIRMED_MSG_ON == 1 )
00192     LMIC.frame[1] = LMIC.seqnoDn >> 8;
00193     LMIC.frame[2] = LMIC.seqnoDn;
00194     LMIC.frame[3] = LMIC.rssi >> 8;
00195     LMIC.frame[4] = LMIC.rssi;
00196     LMIC.frame[5] = LMIC.snr;
00197 #endif    
00198 }
00199 
00200 void processRxFrame( void )
00201 {
00202     debug("processRxFrame enter\r\n");
00203    switch( LMIC.frame[LMIC.dataBeg - 1] ) // Check Rx port number
00204     {
00205         case 1: // The application LED can be controlled on port 1 or 2
00206         case 2:
00207             if( LMIC.dataLen == 1 )
00208             {
00209                 AppLedStateOn = LMIC.frame[LMIC.dataBeg] & 0x01;
00210                 debug_val( "LED3 = ", AppLedStateOn );
00211             }
00212             break;
00213         default:
00214             break;
00215     }
00216 }
00217 
00218 static void onSendFrame( osjob_t* j )
00219 {
00220    debug("onSendFrame enter\r\n");
00221     prepareTxFrame( );
00222     LMIC_setTxData2( LORAWAN_APP_PORT, LMIC.frame, LORAWAN_APP_DATA_SIZE, LORAWAN_CONFIRMED_MSG_ON );
00223 
00224     // Blink Tx LED
00225     led1 = 1;
00226     debug_val( "LED1 = ", 1 );
00227     os_setTimedCallback( &txLedJob, os_getTime( ) + ms2osticks( 25 ), onTxLed );
00228 }
00229 
00230 #if 1
00231 // Initialization job
00232 static void onInit( osjob_t* j )
00233 {
00234     debug("onInit enter\r\n");
00235     // reset MAC state
00236     LMIC_reset( );
00237     LMIC_setAdrMode( LORAWAN_ADR_ON );
00238 #if defined(CFG_eu868)
00239     LMIC_setDrTxpow( DR_SF12, 14 );
00240 #elif defined(CFG_us915)    
00241     LMIC_setDrTxpow( DR_SF10, 14 );
00242 #endif
00243 
00244     // start joining
00245 #if( OVER_THE_AIR_ACTIVATION != 0 )
00246     LMIC_startJoining( );
00247 #else
00248     LMIC_setSession( LORAWAN_NET_ID, LORAWAN_DEV_ADDR, NwkSKey, ArtSKey );
00249     onSendFrame( NULL );
00250 #endif
00251     // init done - onEvent( ) callback will be invoked...
00252 }
00253 #endif
00254 
00255 #if 0
00256 // counter static 
00257 int cnt = 0; 
00258 // log text to USART and toggle LED
00259 static void onInit (osjob_t* job) 
00260 { 
00261     // say hello 
00262     debug_str("Hello World!\r\n");
00263     // log counter 
00264     debug_val("cnt = ", cnt); 
00265     // toggle LED 
00266     if((cnt & 1) == 1)
00267     {
00268          led1 = 1;
00269     }
00270     else
00271      {
00272          led1 = 0;
00273     }
00274      debug_led(cnt & 1); 
00275     cnt++;
00276    // reschedule job every second 
00277     os_setTimedCallback(job, os_getTime()+sec2osticks(1), onInit);
00278 }
00279 #endif
00280 
00281 int main( void )
00282 {
00283     osjob_t initjob;
00284     
00285     led1=1;
00286     led2=1;
00287      pc.baud(115200);
00288     printf( "\r\nLoRaWan Demo Application TJM V %d.%d\r\n",MAJOR, MINOR );
00289     // initialize runtime env
00290     os_init( );
00291     // setup initial job
00292     os_setCallback( &initjob, onInit );
00293     // execute scheduled jobs and events
00294     os_runloop( );
00295     // (not reached)
00296 }
00297 
00298 //////////////////////////////////////////////////
00299 // LMIC EVENT CALLBACK
00300 //////////////////////////////////////////////////
00301 void onEvent( ev_t ev )
00302 {
00303    debug("onEvent enter %d\r\n",ev);
00304     bool txOn = false;
00305     debug_event( ev );
00306 
00307     switch( ev ) 
00308     {
00309     // network joined, session established
00310     case EV_JOINED:
00311         debug_val( "Net ID = ", LMIC.netid );
00312         txOn = true;
00313         break;
00314     // scheduled data sent (optionally data received)
00315     case EV_TXCOMPLETE:
00316         debug_val( "Datarate = ", LMIC.datarate );
00317         // Check if we have a downlink on either Rx1 or Rx2 windows
00318         if( ( LMIC.txrxFlags & ( TXRX_DNW1 | TXRX_DNW2 ) ) != 0 )
00319         {
00320             led2 = 1;
00321             debug_val( "LED2 = ", 1 );
00322             os_setTimedCallback( &rxLedJob, os_getTime( ) + ms2osticks( 25 ), onRxLed );
00323 
00324             if( LMIC.dataLen != 0 )
00325             { // data received in rx slot after tx
00326                 debug_buf( LMIC.frame + LMIC.dataBeg, LMIC.dataLen );
00327                 processRxFrame( );
00328             }
00329         }
00330         txOn = true;
00331         break;
00332     default:
00333         break;
00334     }
00335     if( txOn == true )
00336     {
00337         //Sends frame every APP_TX_DUTYCYCLE +/- APP_TX_DUTYCYCLE_RND random time (if not duty cycle limited)
00338         os_setTimedCallback( &sendFrameJob,
00339                              os_getTime( ) + ms2osticks( APP_TX_DUTYCYCLE + randr( -APP_TX_DUTYCYCLE_RND, APP_TX_DUTYCYCLE_RND ) ),
00340                              onSendFrame );
00341         
00342         ////Sends frame as soon as possible (duty cylce limitations)
00343         //onSendFrame( NULL );
00344     }
00345 }