James Coleman / Mbed 2 deprecated LoRaWAN-demo-72_jlc

Dependencies:   mbed LoRaWAN-lib SX1272Libjlc

Fork of LoRaWAN-demo-72_tjm by Timothy Mulrooney

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: LoRaMac classA device implementation
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 #include "board.h"
00017 #include "radio.h"
00018 
00019 #include "LoRaMac.h"
00020 #include "Comissioning.h"
00021 #include "SerialDisplay.h"
00022 
00023 /*!
00024  * Join requests trials duty cycle.
00025  */
00026 #define OVER_THE_AIR_ACTIVATION_DUTYCYCLE           10000000  // 10 [s] value in us
00027 
00028 /*!
00029  * Defines the application data transmission duty cycle. 5s, value in [us].
00030  */
00031 #define APP_TX_DUTYCYCLE                            5000000
00032 
00033 /*!
00034  * Defines a random delay for application data transmission duty cycle. 1s,
00035  * value in [us].
00036  */
00037 #define APP_TX_DUTYCYCLE_RND                        1000000
00038 
00039 /*!
00040  * Default mote datarate
00041  */
00042 #define LORAWAN_DEFAULT_DATARATE                    DR_0
00043 
00044 /*!
00045  * LoRaWAN confirmed messages
00046  */
00047 #define LORAWAN_CONFIRMED_MSG_ON                    true
00048 
00049 /*!
00050  * LoRaWAN Adaptive Data Rate
00051  *
00052  * \remark Please note that when ADR is enabled the end-device should be static
00053  */
00054 #define LORAWAN_ADR_ON                              1
00055 
00056 #if defined( USE_BAND_868 )
00057 
00058 #include "LoRaMacTest.h"
00059 
00060 /*!
00061  * LoRaWAN ETSI duty cycle control enable/disable
00062  *
00063  * \remark Please note that ETSI mandates duty cycled transmissions. Use only for test purposes
00064  */
00065 #define LORAWAN_DUTYCYCLE_ON                        true
00066 
00067 #endif
00068 
00069 /*!
00070  * LoRaWAN application port
00071  */
00072 #define LORAWAN_APP_PORT                            15
00073 
00074 /*!
00075  * User application data buffer size
00076  */
00077 #if ( LORAWAN_CONFIRMED_MSG_ON == 1 )
00078 //#define LORAWAN_APP_DATA_SIZE                       6
00079 #define LORAWAN_APP_DATA_SIZE                       12
00080 
00081 #else
00082 #define LORAWAN_APP_DATA_SIZE                       1
00083 
00084 #endif
00085 
00086 #if( OVER_THE_AIR_ACTIVATION != 0 )
00087 
00088 static uint8_t DevEui[] = LORAWAN_DEVICE_EUI;
00089 static uint8_t AppEui[] = LORAWAN_APPLICATION_EUI;
00090 static uint8_t AppKey[] = LORAWAN_APPLICATION_KEY;
00091 
00092 #else
00093 
00094 static uint8_t NwkSKey[] = LORAWAN_NWKSKEY;
00095 static uint8_t AppSKey[] = LORAWAN_APPSKEY;
00096 
00097 /*!
00098  * Device address
00099  */
00100 static uint32_t DevAddr = LORAWAN_DEVICE_ADDRESS;
00101 
00102 #endif
00103 
00104 /*!
00105  * Application port
00106  */
00107 static uint8_t AppPort = LORAWAN_APP_PORT;
00108 
00109 /*!
00110  * User application data size
00111  */
00112 static uint8_t AppDataSize = LORAWAN_APP_DATA_SIZE;
00113 
00114 /*!
00115  * User application data buffer size
00116  */
00117 #define LORAWAN_APP_DATA_MAX_SIZE                           64
00118 
00119 /*!
00120  * User application data
00121  */
00122 static uint8_t AppData[LORAWAN_APP_DATA_MAX_SIZE];
00123 
00124 /*!
00125  * Indicates if the node is sending confirmed or unconfirmed messages
00126  */
00127 static uint8_t IsTxConfirmed = LORAWAN_CONFIRMED_MSG_ON;
00128 
00129 /*!
00130  * Defines the application data transmission duty cycle
00131  */
00132 static uint32_t TxDutyCycleTime;
00133 
00134 /*!
00135  * Timer to handle the application data transmission duty cycle
00136  */
00137 static TimerEvent_t TxNextPacketTimer;
00138 
00139 #define LED_RED         PTA1
00140 #define LED_YEL         PTA2
00141 //DigitalOut led1(LED_RED);
00142 //DigitalOut led2(LED_YEL);
00143 DigitalOut led1(PTB0); //orange LED
00144 DigitalOut led2(PTC0); //yellow LED
00145 //DigitalIn powerOn(PTC1);        /* SW2 */
00146 //DigitalIn killStatus(PTB17);    /* SW3 */
00147 
00148 /*!
00149  * Specifies the state of the application LED
00150  */
00151 static bool AppLedStateOn = false;
00152 volatile bool Led3StateChanged = false;
00153 /*!
00154  * Timer to handle the state of LED1
00155  */
00156 static TimerEvent_t Led1Timer;
00157 volatile bool Led1State = false;
00158 volatile bool Led1StateChanged = false;
00159 /*!
00160  * Timer to handle the state of LED2
00161  */
00162 static TimerEvent_t Led2Timer;
00163 volatile bool Led2State = false;
00164 volatile bool Led2StateChanged = false;
00165 
00166 /*!
00167  * Indicates if a new packet can be sent
00168  */
00169 static bool NextTx = true;
00170 
00171 /*!
00172  * Device states
00173  */
00174 static enum eDevicState
00175 {
00176     DEVICE_STATE_INIT,
00177     DEVICE_STATE_JOIN,
00178     DEVICE_STATE_SEND,
00179     DEVICE_STATE_CYCLE,
00180     DEVICE_STATE_SLEEP
00181 }DeviceState;
00182 
00183 /*!
00184  * LoRaWAN compliance tests support data
00185  */
00186 struct ComplianceTest_s
00187 {
00188     bool Running;
00189     uint8_t State;
00190     bool IsTxConfirmed;
00191     uint8_t AppPort;
00192     uint8_t AppDataSize;
00193     uint8_t *AppDataBuffer;
00194     uint16_t DownLinkCounter;
00195     bool LinkCheck;
00196     uint8_t DemodMargin;
00197     uint8_t NbGateways;
00198 }ComplianceTest;
00199 
00200 /*
00201  * SerialDisplay managment variables
00202  */
00203 
00204 /*!
00205  * Indicates if the MAC layer network join status has changed.
00206  */
00207 static bool IsNetworkJoinedStatusUpdate = false;
00208 
00209 /*!
00210  * Strucure containing the Uplink status
00211  */
00212 struct sLoRaMacUplinkStatus
00213 {
00214     uint8_t Acked;
00215     int8_t Datarate;
00216     uint16_t UplinkCounter;
00217     uint8_t Port;
00218     uint8_t *Buffer;
00219     uint8_t BufferSize;
00220 }LoRaMacUplinkStatus;
00221 volatile bool UplinkStatusUpdated = false;
00222 
00223 /*!
00224  * Strucure containing the Downlink status
00225  */
00226 struct sLoRaMacDownlinkStatus
00227 {
00228     int16_t Rssi;
00229     int8_t Snr;
00230     uint16_t DownlinkCounter;
00231     bool RxData;
00232     uint8_t Port;
00233     uint8_t *Buffer;
00234     uint8_t BufferSize;
00235 }LoRaMacDownlinkStatus;
00236 volatile bool DownlinkStatusUpdated = false;
00237 
00238 void SerialDisplayRefresh( void )
00239 {
00240     MibRequestConfirm_t mibReq;
00241 
00242     SerialDisplayInit( );
00243     SerialDisplayUpdateActivationMode( OVER_THE_AIR_ACTIVATION );
00244 
00245 #if( OVER_THE_AIR_ACTIVATION == 0 )
00246     SerialDisplayUpdateNwkId( LORAWAN_NETWORK_ID );
00247     SerialDisplayUpdateDevAddr( DevAddr );
00248     SerialDisplayUpdateKey( 12, NwkSKey );
00249     SerialDisplayUpdateKey( 13, AppSKey );
00250 #else
00251     SerialDisplayUpdateEui( 5, DevEui );
00252     SerialDisplayUpdateEui( 6, AppEui );
00253     SerialDisplayUpdateKey( 7, AppKey );
00254 #endif
00255 
00256     mibReq.Type = MIB_NETWORK_JOINED;
00257     LoRaMacMibGetRequestConfirm( &mibReq );
00258     SerialDisplayUpdateNetworkIsJoined( mibReq.Param.IsNetworkJoined );
00259 
00260     SerialDisplayUpdateAdr( LORAWAN_ADR_ON );
00261 #if defined( USE_BAND_868 )
00262     SerialDisplayUpdateDutyCycle( LORAWAN_DUTYCYCLE_ON );
00263 #else
00264     SerialDisplayUpdateDutyCycle( false );
00265 #endif
00266     SerialDisplayUpdatePublicNetwork( LORAWAN_PUBLIC_NETWORK );
00267     
00268     SerialDisplayUpdateLedState( 3, AppLedStateOn );
00269 }
00270 
00271 void SerialRxProcess( void )
00272 {
00273     if( SerialDisplayReadable( ) == true )
00274     {
00275         switch( SerialDisplayGetChar( ) )
00276         {
00277             case 'R':
00278             case 'r':
00279                 // Refresh Serial screen
00280                 SerialDisplayRefresh( );
00281                 break;
00282             default:
00283                 break;
00284         }
00285     }
00286 }
00287 
00288 /*!
00289  * \brief   Prepares the payload of the frame
00290  */
00291 int randVoltage;
00292 static void PrepareTxFrame( uint8_t port )
00293 {
00294     char str[30];
00295     
00296     switch( port )
00297     {
00298     case 15:
00299         {
00300             switch(randVoltage%3)
00301             {
00302                 case 0:
00303                     sprintf(str,"Voltage %2.2f",2.30 + (randVoltage%10 * .1));
00304                     break;
00305                     
00306                 case 1:
00307                     sprintf(str,"KillStatus %d",(randVoltage & 0x04)?1:0);
00308                     break;
00309                     
00310                 case 2:
00311                     sprintf(str,"PowerOn %d",(randVoltage & 0x08)?1:0);
00312                      break;
00313             }
00314             randVoltage++;
00315             memcpy(AppData,str,strlen(str));
00316             AppDataSize = strlen(str);
00317             #if 0
00318             AppData[0] = AppLedStateOn;
00319             if( IsTxConfirmed == true )
00320             {
00321                 AppData[1] = LoRaMacDownlinkStatus.DownlinkCounter >> 8;
00322                 AppData[2] = LoRaMacDownlinkStatus.DownlinkCounter;
00323                 AppData[3] = LoRaMacDownlinkStatus.Rssi >> 8;
00324                 AppData[4] = LoRaMacDownlinkStatus.Rssi;
00325                 AppData[5] = LoRaMacDownlinkStatus.Snr;
00326             }
00327             #endif
00328         }
00329         break;
00330     case 224:
00331         if( ComplianceTest.LinkCheck == true )
00332         {
00333             ComplianceTest.LinkCheck = false;
00334             AppDataSize = 3;
00335             AppData[0] = 5;
00336             AppData[1] = ComplianceTest.DemodMargin;
00337             AppData[2] = ComplianceTest.NbGateways;
00338             ComplianceTest.State = 1;
00339         }
00340         else
00341         {
00342             switch( ComplianceTest.State )
00343             {
00344             case 4:
00345                 ComplianceTest.State = 1;
00346                 break;
00347             case 1:
00348                 AppDataSize = 2;
00349                 AppData[0] = ComplianceTest.DownLinkCounter >> 8;
00350                 AppData[1] = ComplianceTest.DownLinkCounter;
00351                 break;
00352             }
00353         }
00354         break;
00355     default:
00356         break;
00357     }
00358 }
00359 
00360 /*!
00361  * \brief   Prepares the payload of the frame
00362  *
00363  * \retval  [0: frame could be send, 1: error]
00364  */
00365 static bool SendFrame( void )
00366 {
00367     McpsReq_t mcpsReq;
00368     LoRaMacTxInfo_t txInfo;
00369     
00370     if( LoRaMacQueryTxPossible( AppDataSize, &txInfo ) != LORAMAC_STATUS_OK )
00371     {
00372         // Send empty frame in order to flush MAC commands
00373         mcpsReq.Type = MCPS_UNCONFIRMED;
00374         mcpsReq.Req.Unconfirmed.fBuffer = NULL;
00375         mcpsReq.Req.Unconfirmed.fBufferSize = 0;
00376         mcpsReq.Req.Unconfirmed.Datarate = LORAWAN_DEFAULT_DATARATE;
00377         
00378         LoRaMacUplinkStatus.Acked = false;
00379         LoRaMacUplinkStatus.Port = 0;
00380         LoRaMacUplinkStatus.Buffer = NULL;
00381         LoRaMacUplinkStatus.BufferSize = 0;
00382         SerialDisplayUpdateFrameType( false );
00383     }
00384     else
00385     {
00386         LoRaMacUplinkStatus.Acked = false;
00387         LoRaMacUplinkStatus.Port = AppPort;
00388         LoRaMacUplinkStatus.Buffer = AppData;
00389         LoRaMacUplinkStatus.BufferSize = AppDataSize;
00390         SerialDisplayUpdateFrameType( IsTxConfirmed );
00391 
00392         if( IsTxConfirmed == false )
00393         {
00394             mcpsReq.Type = MCPS_UNCONFIRMED;
00395             mcpsReq.Req.Unconfirmed.fPort = AppPort;
00396             mcpsReq.Req.Unconfirmed.fBuffer = AppData;
00397             mcpsReq.Req.Unconfirmed.fBufferSize = AppDataSize;
00398             mcpsReq.Req.Unconfirmed.Datarate = LORAWAN_DEFAULT_DATARATE;
00399         }
00400         else
00401         {
00402             mcpsReq.Type = MCPS_CONFIRMED;
00403             mcpsReq.Req.Confirmed.fPort = AppPort;
00404             mcpsReq.Req.Confirmed.fBuffer = AppData;
00405             mcpsReq.Req.Confirmed.fBufferSize = AppDataSize;
00406             mcpsReq.Req.Confirmed.nbRetries = 8;
00407             mcpsReq.Req.Confirmed.Datarate = LORAWAN_DEFAULT_DATARATE;
00408         }
00409     }
00410 
00411     if( LoRaMacMcpsRequest( &mcpsReq ) == LORAMAC_STATUS_OK )
00412     {
00413         return false;
00414     }
00415     return true;
00416 }
00417 
00418 /*!
00419  * \brief Function executed on TxNextPacket Timeout event
00420  */
00421 static void OnTxNextPacketTimerEvent( void )
00422 {
00423     MibRequestConfirm_t mibReq;
00424     LoRaMacStatus_t status;
00425 
00426     TimerStop( &TxNextPacketTimer );
00427 
00428     mibReq.Type = MIB_NETWORK_JOINED;
00429     status = LoRaMacMibGetRequestConfirm( &mibReq );
00430 
00431     if( status == LORAMAC_STATUS_OK )
00432     {
00433         if( mibReq.Param.IsNetworkJoined == true )
00434         {
00435             DeviceState = DEVICE_STATE_SEND;
00436             NextTx = true;
00437         }
00438         else
00439         {
00440             DeviceState = DEVICE_STATE_JOIN;
00441         }
00442     }
00443 }
00444 
00445 /*!
00446  * \brief Function executed on Led 1 Timeout event
00447  */
00448 static void OnLed1TimerEvent( void )
00449 {
00450     TimerStop( &Led1Timer );
00451     // Switch LED 1 OFF
00452     Led1State = false;
00453     Led1StateChanged = true;
00454 }
00455 
00456 /*!
00457  * \brief Function executed on Led 2 Timeout event
00458  */
00459 static void OnLed2TimerEvent( void )
00460 {
00461     TimerStop( &Led2Timer );
00462     // Switch LED 2 OFF
00463     Led2State = false;
00464     Led2StateChanged = true;
00465 }
00466 
00467 /*!
00468  * \brief   MCPS-Confirm event function
00469  *
00470  * \param   [IN] McpsConfirm - Pointer to the confirm structure,
00471  *               containing confirm attributes.
00472  */
00473 static void McpsConfirm( McpsConfirm_t *McpsConfirm )
00474 {
00475     if( McpsConfirm->Status == LORAMAC_EVENT_INFO_STATUS_OK )
00476     {
00477         switch( McpsConfirm->McpsRequest )
00478         {
00479             case MCPS_UNCONFIRMED:
00480             {
00481                 // Check Datarate
00482                 // Check TxPower
00483                 break;
00484             }
00485             case MCPS_CONFIRMED:
00486             {
00487                 // Check Datarate
00488                 // Check TxPower
00489                 // Check AckReceived
00490                 // Check NbRetries
00491                 LoRaMacUplinkStatus.Acked = McpsConfirm->AckReceived;
00492                 break;
00493             }
00494             case MCPS_PROPRIETARY:
00495             {
00496                 break;
00497             }
00498             default:
00499                 break;
00500         }
00501         LoRaMacUplinkStatus.Datarate = McpsConfirm->Datarate;
00502         LoRaMacUplinkStatus.UplinkCounter = McpsConfirm->UpLinkCounter;
00503     
00504         UplinkStatusUpdated = true;
00505     }
00506     NextTx = true;
00507 }
00508 
00509 /*!
00510  * \brief   MCPS-Indication event function
00511  *
00512  * \param   [IN] McpsIndication - Pointer to the indication structure,
00513  *               containing indication attributes.
00514  */
00515 static void McpsIndication( McpsIndication_t *McpsIndication )
00516 {
00517     if( McpsIndication->Status != LORAMAC_EVENT_INFO_STATUS_OK )
00518     {
00519         return;
00520     }
00521 
00522     switch( McpsIndication->McpsIndication )
00523     {
00524         case MCPS_UNCONFIRMED:
00525         {
00526             break;
00527         }
00528         case MCPS_CONFIRMED:
00529         {
00530             break;
00531         }
00532         case MCPS_PROPRIETARY:
00533         {
00534             break;
00535         }
00536         case MCPS_MULTICAST:
00537         {
00538             break;
00539         }
00540         default:
00541             break;
00542     }
00543 
00544     // Check Multicast
00545     // Check Port
00546     // Check Datarate
00547     // Check FramePending
00548     // Check Buffer
00549     // Check BufferSize
00550     // Check Rssi
00551     // Check Snr
00552     // Check RxSlot
00553     LoRaMacDownlinkStatus.Rssi = McpsIndication->Rssi;
00554     if( McpsIndication->Snr & 0x80 ) // The SNR sign bit is 1
00555     {
00556         // Invert and divide by 4
00557         LoRaMacDownlinkStatus.Snr = ( ( ~McpsIndication->Snr + 1 ) & 0xFF ) >> 2;
00558         LoRaMacDownlinkStatus.Snr = -LoRaMacDownlinkStatus.Snr;
00559     }
00560     else
00561     {
00562         // Divide by 4
00563         LoRaMacDownlinkStatus.Snr = ( McpsIndication->Snr & 0xFF ) >> 2;
00564     }
00565     LoRaMacDownlinkStatus.DownlinkCounter++;
00566     LoRaMacDownlinkStatus.RxData = McpsIndication->RxData;
00567     LoRaMacDownlinkStatus.Port = McpsIndication->Port;
00568     LoRaMacDownlinkStatus.Buffer = McpsIndication->Buffer;
00569     LoRaMacDownlinkStatus.BufferSize = McpsIndication->BufferSize;
00570 
00571     if( ComplianceTest.Running == true )
00572     {
00573         ComplianceTest.DownLinkCounter++;
00574     }
00575 
00576     if( McpsIndication->RxData == true )
00577     {
00578         switch( McpsIndication->Port )
00579         {
00580         case 1: // The application LED can be controlled on port 1 or 2
00581         case 2:
00582             if( McpsIndication->BufferSize == 1 )
00583             {
00584                 AppLedStateOn = McpsIndication->Buffer[0] & 0x01;
00585                 Led3StateChanged = true;
00586             }
00587             break;
00588         case 224:
00589             if( ComplianceTest.Running == false )
00590             {
00591                 // Check compliance test enable command (i)
00592                 if( ( McpsIndication->BufferSize == 4 ) && 
00593                     ( McpsIndication->Buffer[0] == 0x01 ) &&
00594                     ( McpsIndication->Buffer[1] == 0x01 ) &&
00595                     ( McpsIndication->Buffer[2] == 0x01 ) &&
00596                     ( McpsIndication->Buffer[3] == 0x01 ) )
00597                 {
00598                     IsTxConfirmed = false;
00599                     AppPort = 224;
00600                     AppDataSize = 2;
00601                     ComplianceTest.DownLinkCounter = 0;
00602                     ComplianceTest.LinkCheck = false;
00603                     ComplianceTest.DemodMargin = 0;
00604                     ComplianceTest.NbGateways = 0;
00605                     ComplianceTest.Running = true;
00606                     ComplianceTest.State = 1;
00607                     
00608                     MibRequestConfirm_t mibReq;
00609                     mibReq.Type = MIB_ADR;
00610                     mibReq.Param.AdrEnable = true;
00611                     LoRaMacMibSetRequestConfirm( &mibReq );
00612 
00613 #if defined( USE_BAND_868 )
00614                     LoRaMacTestSetDutyCycleOn( false );
00615 #endif
00616                 }
00617             }
00618             else
00619             {
00620                 ComplianceTest.State = McpsIndication->Buffer[0];
00621                 switch( ComplianceTest.State )
00622                 {
00623                 case 0: // Check compliance test disable command (ii)
00624                     IsTxConfirmed = LORAWAN_CONFIRMED_MSG_ON;
00625                     AppPort = LORAWAN_APP_PORT;
00626                     AppDataSize = LORAWAN_APP_DATA_SIZE;
00627                     ComplianceTest.DownLinkCounter = 0;
00628                     ComplianceTest.Running = false;
00629                     
00630                     MibRequestConfirm_t mibReq;
00631                     mibReq.Type = MIB_ADR;
00632                     mibReq.Param.AdrEnable = LORAWAN_ADR_ON;
00633                     LoRaMacMibSetRequestConfirm( &mibReq );
00634 #if defined( USE_BAND_868 )
00635                     LoRaMacTestSetDutyCycleOn( LORAWAN_DUTYCYCLE_ON );
00636 #endif
00637                     break;
00638                 case 1: // (iii, iv)
00639                     AppDataSize = 2;
00640                     break;
00641                 case 2: // Enable confirmed messages (v)
00642                     IsTxConfirmed = true;
00643                     ComplianceTest.State = 1;
00644                     break;
00645                 case 3:  // Disable confirmed messages (vi)
00646                     IsTxConfirmed = false;
00647                     ComplianceTest.State = 1;
00648                     break;
00649                 case 4: // (vii)
00650                     AppDataSize = McpsIndication->BufferSize;
00651 
00652                     AppData[0] = 4;
00653                     for( uint8_t i = 1; i < AppDataSize; i++ )
00654                     {
00655                         AppData[i] = McpsIndication->Buffer[i] + 1;
00656                     }
00657                     break;
00658                 case 5: // (viii)
00659                     {
00660                         MlmeReq_t mlmeReq;
00661                         mlmeReq.Type = MLME_LINK_CHECK;
00662                         LoRaMacMlmeRequest( &mlmeReq );
00663                     }
00664                     break;
00665                 default:
00666                     break;
00667                 }
00668             }
00669             break;
00670         default:
00671             break;
00672         }
00673     }
00674 
00675     // Switch LED 2 ON for each received downlink
00676     Led2State = true;
00677     Led2StateChanged = true;
00678     TimerStart( &Led2Timer );
00679     DownlinkStatusUpdated = true;
00680 }
00681 
00682 /*!
00683  * \brief   MLME-Confirm event function
00684  *
00685  * \param   [IN] MlmeConfirm - Pointer to the confirm structure,
00686  *               containing confirm attributes.
00687  */
00688 static void MlmeConfirm( MlmeConfirm_t *MlmeConfirm )
00689 {
00690     if( MlmeConfirm->Status == LORAMAC_EVENT_INFO_STATUS_OK )
00691     {
00692         switch( MlmeConfirm->MlmeRequest )
00693         {
00694             case MLME_JOIN:
00695             {
00696                 // Status is OK, node has joined the network
00697                 IsNetworkJoinedStatusUpdate = true;
00698                 break;
00699             }
00700             case MLME_LINK_CHECK:
00701             {
00702                 // Check DemodMargin
00703                 // Check NbGateways
00704                 if( ComplianceTest.Running == true )
00705                 {
00706                     ComplianceTest.LinkCheck = true;
00707                     ComplianceTest.DemodMargin = MlmeConfirm->DemodMargin;
00708                     ComplianceTest.NbGateways = MlmeConfirm->NbGateways;
00709                 }
00710                 break;
00711             }
00712             default:
00713                 break;
00714         }
00715     }
00716     NextTx = true;
00717     UplinkStatusUpdated = true;
00718 }
00719 
00720 /**
00721  * Main application entry point.
00722  */
00723 int main( void )
00724 {
00725     LoRaMacPrimitives_t LoRaMacPrimitives;
00726     LoRaMacCallback_t LoRaMacCallbacks;
00727     MibRequestConfirm_t mibReq;
00728 
00729     led1 = 1;
00730     led2 = 1;
00731     BoardInit( );
00732     SerialDisplayInit( );
00733  
00734     DeviceState = DEVICE_STATE_INIT;
00735 
00736     while( 1 )
00737     {
00738        SerialRxProcess( );
00739         if( IsNetworkJoinedStatusUpdate == true )
00740         {
00741             IsNetworkJoinedStatusUpdate = false;
00742             mibReq.Type = MIB_NETWORK_JOINED;
00743             LoRaMacMibGetRequestConfirm( &mibReq );
00744             SerialDisplayUpdateNetworkIsJoined( mibReq.Param.IsNetworkJoined );
00745         }
00746         if( Led1StateChanged == true )
00747         {
00748             Led1StateChanged = false;
00749             SerialDisplayUpdateLedState( 1, Led1State );
00750            led1 = !Led1State;
00751         }
00752         if( Led2StateChanged == true )
00753         {
00754             Led2StateChanged = false;
00755             SerialDisplayUpdateLedState( 2, Led2State );
00756             led2 = !Led2State;
00757        }
00758         if( Led3StateChanged == true )
00759         {
00760             Led3StateChanged = false;
00761             SerialDisplayUpdateLedState( 3, AppLedStateOn );
00762         }
00763         if( UplinkStatusUpdated == true )
00764         {
00765             UplinkStatusUpdated = false;
00766             SerialDisplayUpdateUplink( LoRaMacUplinkStatus.Acked, LoRaMacUplinkStatus.Datarate, LoRaMacUplinkStatus.UplinkCounter, LoRaMacUplinkStatus.Port, LoRaMacUplinkStatus.Buffer, LoRaMacUplinkStatus.BufferSize );
00767         }
00768         if( DownlinkStatusUpdated == true )
00769         {
00770             DownlinkStatusUpdated = false;
00771             SerialDisplayUpdateLedState( 2, Led2State );
00772             SerialDisplayUpdateDownlink( LoRaMacDownlinkStatus.RxData, LoRaMacDownlinkStatus.Rssi, LoRaMacDownlinkStatus.Snr, LoRaMacDownlinkStatus.DownlinkCounter, LoRaMacDownlinkStatus.Port, LoRaMacDownlinkStatus.Buffer, LoRaMacDownlinkStatus.BufferSize );
00773         }
00774         
00775         switch( DeviceState )
00776         {
00777             case DEVICE_STATE_INIT:
00778             {
00779                 LoRaMacPrimitives.MacMcpsConfirm = McpsConfirm;
00780                 LoRaMacPrimitives.MacMcpsIndication = McpsIndication;
00781                 LoRaMacPrimitives.MacMlmeConfirm = MlmeConfirm;
00782                 LoRaMacCallbacks.GetBatteryLevel = BoardGetBatteryLevel;
00783                 LoRaMacInitialization( &LoRaMacPrimitives, &LoRaMacCallbacks );
00784 
00785                 TimerInit( &TxNextPacketTimer, OnTxNextPacketTimerEvent );
00786 
00787                 TimerInit( &Led1Timer, OnLed1TimerEvent );
00788                 TimerSetValue( &Led1Timer, 25000 );
00789 
00790                 TimerInit( &Led2Timer, OnLed2TimerEvent );
00791                 TimerSetValue( &Led2Timer, 25000 );
00792 
00793                 mibReq.Type = MIB_ADR;
00794                 mibReq.Param.AdrEnable = LORAWAN_ADR_ON;
00795                 LoRaMacMibSetRequestConfirm( &mibReq );
00796 
00797                 mibReq.Type = MIB_PUBLIC_NETWORK;
00798                 mibReq.Param.EnablePublicNetwork = LORAWAN_PUBLIC_NETWORK;
00799                 LoRaMacMibSetRequestConfirm( &mibReq );
00800 
00801 #if defined( USE_BAND_868 )
00802                 LoRaMacTestSetDutyCycleOn( LORAWAN_DUTYCYCLE_ON );
00803                 SerialDisplayUpdateDutyCycle( LORAWAN_DUTYCYCLE_ON );
00804 #endif
00805                 SerialDisplayUpdateActivationMode( OVER_THE_AIR_ACTIVATION );
00806                 SerialDisplayUpdateAdr( LORAWAN_ADR_ON );
00807                 SerialDisplayUpdatePublicNetwork( LORAWAN_PUBLIC_NETWORK );
00808 
00809                 LoRaMacDownlinkStatus.DownlinkCounter = 0;
00810 
00811                 DeviceState = DEVICE_STATE_JOIN;
00812                 break;
00813             }
00814             case DEVICE_STATE_JOIN:
00815             {
00816 #if( OVER_THE_AIR_ACTIVATION != 0 )
00817                 MlmeReq_t mlmeReq;
00818 
00819                 mlmeReq.Type = MLME_JOIN;
00820 
00821                 mlmeReq.Req.Join.DevEui = DevEui;
00822                 mlmeReq.Req.Join.AppEui = AppEui;
00823                 mlmeReq.Req.Join.AppKey = AppKey;
00824 
00825                 if( NextTx == true )
00826                 {
00827                     LoRaMacMlmeRequest( &mlmeReq );
00828                 }
00829 
00830                 SerialDisplayUpdateEui( 5, DevEui );
00831                 SerialDisplayUpdateEui( 6, AppEui );
00832                 SerialDisplayUpdateKey( 7, AppKey );
00833 
00834                 // Schedule next packet transmission
00835                 TxDutyCycleTime = OVER_THE_AIR_ACTIVATION_DUTYCYCLE;
00836                 DeviceState = DEVICE_STATE_CYCLE;
00837 
00838 #else
00839                 mibReq.Type = MIB_NET_ID;
00840                 mibReq.Param.NetID = LORAWAN_NETWORK_ID;
00841                 LoRaMacMibSetRequestConfirm( &mibReq );
00842 
00843                 mibReq.Type = MIB_DEV_ADDR;
00844                 mibReq.Param.DevAddr = DevAddr;
00845                 LoRaMacMibSetRequestConfirm( &mibReq );
00846 
00847                 mibReq.Type = MIB_NWK_SKEY;
00848                 mibReq.Param.NwkSKey = NwkSKey;
00849                 LoRaMacMibSetRequestConfirm( &mibReq );
00850 
00851                 mibReq.Type = MIB_APP_SKEY;
00852                 mibReq.Param.AppSKey = AppSKey;
00853                 LoRaMacMibSetRequestConfirm( &mibReq );
00854 
00855                 mibReq.Type = MIB_NETWORK_JOINED;
00856                 mibReq.Param.IsNetworkJoined = true;
00857                 LoRaMacMibSetRequestConfirm( &mibReq );
00858 
00859                 SerialDisplayUpdateNwkId( LORAWAN_NETWORK_ID );
00860                 SerialDisplayUpdateDevAddr( DevAddr );
00861                 SerialDisplayUpdateKey( 12, NwkSKey );
00862                 SerialDisplayUpdateKey( 13, AppSKey );
00863 
00864                 DeviceState = DEVICE_STATE_SEND;
00865 #endif
00866                 IsNetworkJoinedStatusUpdate = true;
00867                 break;
00868             }
00869             case DEVICE_STATE_SEND:
00870             {
00871                 if( NextTx == true )
00872                 {
00873                     SerialDisplayUpdateUplinkAcked( false );
00874                     SerialDisplayUpdateDonwlinkRxData( false );
00875                     PrepareTxFrame( AppPort );
00876 
00877                     NextTx = SendFrame( );
00878 
00879                     // Switch LED 1 ON
00880                     Led1State = true;
00881                     Led1StateChanged = true;
00882                     TimerStart( &Led1Timer );
00883                 }
00884                 if( ComplianceTest.Running == true )
00885                 {
00886                     // Schedule next packet transmission as soon as possible
00887                     TxDutyCycleTime = 1000; // 1 ms
00888                 }
00889                 else
00890                 {
00891                     // Schedule next packet transmission
00892                     TxDutyCycleTime = APP_TX_DUTYCYCLE + randr( -APP_TX_DUTYCYCLE_RND, APP_TX_DUTYCYCLE_RND );
00893                 }
00894                 DeviceState = DEVICE_STATE_CYCLE;
00895                 break;
00896             }
00897             case DEVICE_STATE_CYCLE:
00898             {
00899                 // Schedule next packet transmission
00900                 TimerSetValue( &TxNextPacketTimer, TxDutyCycleTime );
00901                 TimerStart( &TxNextPacketTimer );
00902 
00903                 DeviceState = DEVICE_STATE_SLEEP;
00904                 break;
00905             }
00906             case DEVICE_STATE_SLEEP:
00907             {
00908                 // Wake up through events
00909                 break;
00910             }
00911             default:
00912             {
00913                 DeviceState = DEVICE_STATE_INIT;
00914                 break;
00915             }
00916         }
00917     }
00918 }