Semtech LoRaWAN-demo configured for 915MHz operation and multi-radio support (SX1276/SX1272)

Dependencies:   mbed LoRaWAN-lib SX1272Lib SX1276Lib

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