inital draft

Dependencies:   mbed LoRaWAN-lib SX1272Liby

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