Amir Chaudhary / Mbed 2 deprecated Hexmodal-firmware_v3-1_hex_w_3d_14

Dependencies:   mbed

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                            5000
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                    true
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 #define LORAWAN_APP_DATA_SIZE                       41
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 #if( OVER_THE_AIR_ACTIVATION == 0 )
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 /*!
00140  * SOME APPLICATION PARAMETERS
00141  */
00142  
00143 DigitalOut myled(D7);
00144 
00145 DigitalOut relayPin(D6);
00146 AnalogIn BAT_PIN(A2);
00147 AnalogIn LIGHT_1_PIN(A1);
00148 AnalogIn LIGHT_2_PIN(A5);
00149 AnalogIn RH_PIN(PC_2);
00150 AnalogIn VCE_PIN(PB_1);
00151 
00152 /*
00153 D7 == Green
00154 D8 == Blue 
00155  */
00156 
00157 DigitalOut myGreenLed(D7); // ON = Lora Connected
00158 DigitalOut myBlueLed(D8);  // Blink twice = Sends data or increments counter value Pelase proceed
00159 
00160 InterruptIn button1(USER_BUTTON);
00161 volatile bool button1_pressed = false; // Used in the main loop
00162 volatile bool button1_enabled = true; // Used for debouncing
00163 Timeout button1_timeout; // Used for debouncing
00164 int press_count;
00165 Timeout buttonOptions_timeout; // Used for determining number of presses
00166 
00167 unsigned int time_window = 5; // Default 3600 seconds in an hour
00168 unsigned long long_interval = 31557600; // Default 31557600 seconds in a year
00169 unsigned int hb_interval = 43200; // Default 86400 seconds in a day
00170 unsigned long test_interval = 2592000; // Default 2592000 seconds in a month
00171 
00172 time_t next_stest;
00173 time_t next_ltest;
00174 
00175 uint8_t hb_data[5];
00176 uint8_t tdata[10];
00177 
00178 uint8_t *data;
00179 uint8_t data_len;
00180 
00181 bool running_test;
00182 bool joining;
00183 // bool received_downlink;
00184 
00185 time_t current_time;
00186 
00187 unsigned long last_hb;
00188 unsigned long test_start;
00189 
00190 uint8_t measurements[5];
00191 
00192 unsigned long test_duration;
00193 
00194 /*!
00195  * Specifies the state of the application LED
00196  */
00197 static bool AppLedStateOn = false;
00198 volatile bool Led3StateChanged = false;
00199 /*!
00200  * Timer to handle the state of LED1
00201  */
00202 static TimerEvent_t Led1Timer;
00203 volatile bool Led1State = false;
00204 volatile bool Led1StateChanged = false;
00205 /*!
00206  * Timer to handle the state of LED2
00207  */
00208 static TimerEvent_t Led2Timer;
00209 volatile bool Led2State = false;
00210 volatile bool Led2StateChanged = false;
00211 
00212 enum GreenLedState_e{
00213     GREEN_LED_STATE_INIT=0,
00214     GREEN_LED_STATE_JOINING,
00215     GREEN_LED_STATE_JOINED
00216 }GreenLedState;
00217 volatile uint32_t GreenLedTickCounter=0;
00218 
00219 volatile bool BatteryLowFlag = true;
00220 
00221 volatile uint32_t GreenLedJoiningCounter=0;
00222 
00223 static TimerEvent_t GreenLedTimer;
00224 static void OnGreenLedTimerEvent( void )
00225 {
00226     MibRequestConfirm_t  mibReq;
00227     LoRaMacStatus_t  status;
00228 
00229     if(BatteryLowFlag == true)
00230     {
00231         myGreenLed = 0; // OFF
00232     }
00233     else
00234     {
00235         // battery ok
00236         GreenLedTickCounter++;        
00237         switch(GreenLedState)
00238         {
00239             case GREEN_LED_STATE_INIT:
00240             {
00241                 GreenLedState = GREEN_LED_STATE_JOINING;
00242             }
00243             break;
00244             
00245             case GREEN_LED_STATE_JOINING:
00246             {
00247                 GreenLedJoiningCounter++;
00248                 if((GreenLedJoiningCounter % 2) == 0)
00249                 {
00250                     GreenLedJoiningCounter = 0;
00251                     myGreenLed = !myGreenLed; // toggle
00252                     
00253                     // check if we have joined the network
00254                     mibReq.Type  = MIB_NETWORK_JOINED ;
00255                     status = LoRaMacMibGetRequestConfirm( &mibReq );
00256                     if( status == LORAMAC_STATUS_OK  )
00257                     {
00258                         if( mibReq.Param .IsNetworkJoined  == true )
00259                         {
00260                             GreenLedState = GREEN_LED_STATE_JOINED;
00261                         }
00262                     }
00263                 }
00264             }
00265             break;
00266                     
00267             case GREEN_LED_STATE_JOINED:
00268             {
00269                 myGreenLed = 1;
00270             }
00271             break;
00272         }
00273     }
00274 }
00275 
00276 static TimerEvent_t BatteryCheckTimer;
00277 volatile bool BatteryCheckFlag=false;
00278 static void OnBatteryCheckTimerEvent( void )
00279 {
00280     BatteryCheckFlag = true;
00281 }
00282 
00283 /*!
00284  * Indicates if a new packet can be sent
00285  */
00286 static bool NextTx = true;
00287 
00288 /*!
00289  * Device states
00290  */
00291  
00292  
00293  // Application Globals
00294 
00295 
00296 
00297  
00298  
00299 static enum eDeviceState
00300 {
00301     DEVICE_STATE_INIT,
00302     DEVICE_STATE_JOIN,
00303     DEVICE_STATE_SEND,
00304     DEVICE_STATE_CYCLE,
00305     DEVICE_STATE_SLEEP
00306 }DeviceState;
00307 
00308 static enum eMessageType
00309 {
00310     MESSAGE_TYPE_HB,
00311     MESSAGE_TYPE_SHORT_TEST,
00312     MESSAGE_TYPE_LONG_TEST
00313 }MessageType;
00314 
00315 /*!
00316  * LoRaWAN compliance tests support data
00317  */
00318 struct ComplianceTest_s
00319 {
00320     bool Running;
00321     uint8_t State;
00322     bool IsTxConfirmed;
00323     uint8_t AppPort;
00324     uint8_t AppDataSize;
00325     uint8_t *AppDataBuffer;
00326     uint16_t DownLinkCounter;
00327     bool LinkCheck;
00328     uint8_t DemodMargin;
00329     uint8_t NbGateways;
00330 }ComplianceTest;
00331 
00332 /*
00333  * SerialDisplay managment variables
00334  */
00335 
00336 /*!
00337  * Indicates if the MAC layer network join status has changed.
00338  */
00339 static bool IsNetworkJoinedStatusUpdate = false;
00340 
00341 /*!
00342  * Strucure containing the Uplink status
00343  */
00344 struct sLoRaMacUplinkStatus
00345 {
00346     uint8_t Acked;
00347     int8_t Datarate;
00348     uint16_t UplinkCounter;
00349     uint8_t Port;
00350     uint8_t *Buffer;
00351     uint8_t BufferSize;
00352 }LoRaMacUplinkStatus;
00353 volatile bool UplinkStatusUpdated = false;
00354 
00355 /*!
00356  * Strucure containing the Downlink status
00357  */
00358 struct sLoRaMacDownlinkStatus
00359 {
00360     int16_t Rssi;
00361     int8_t Snr;
00362     uint16_t DownlinkCounter;
00363     bool RxData;
00364     uint8_t Port;
00365     uint8_t *Buffer;
00366     uint8_t BufferSize;
00367 }LoRaMacDownlinkStatus;
00368 volatile bool DownlinkStatusUpdated = false;
00369 
00370 void SerialDisplayRefresh( void )
00371 {
00372     MibRequestConfirm_t  mibReq;
00373 
00374     SerialDisplayInit( );
00375     SerialDisplayUpdateActivationMode( OVER_THE_AIR_ACTIVATION );
00376 
00377 #if( OVER_THE_AIR_ACTIVATION == 0 )
00378     SerialDisplayUpdateNwkId( LORAWAN_NETWORK_ID );
00379     SerialDisplayUpdateDevAddr( DevAddr );
00380     SerialDisplayUpdateKey( 12, NwkSKey );
00381     SerialDisplayUpdateKey( 13, AppSKey );
00382 #endif
00383     SerialDisplayUpdateEui( 5, DevEui );
00384     SerialDisplayUpdateEui( 6, AppEui );
00385     SerialDisplayUpdateKey( 7, AppKey );
00386 
00387     mibReq.Type  = MIB_NETWORK_JOINED ;
00388     LoRaMacMibGetRequestConfirm( &mibReq );
00389     SerialDisplayUpdateNetworkIsJoined( mibReq.Param .IsNetworkJoined  );
00390 
00391     SerialDisplayUpdateAdr( LORAWAN_ADR_ON );
00392 #if defined( USE_BAND_868 )
00393     SerialDisplayUpdateDutyCycle( LORAWAN_DUTYCYCLE_ON );
00394 #else
00395     SerialDisplayUpdateDutyCycle( false );
00396 #endif
00397     SerialDisplayUpdatePublicNetwork( LORAWAN_PUBLIC_NETWORK );
00398     
00399     SerialDisplayUpdateLedState( 3, AppLedStateOn );
00400 }
00401 
00402 void SerialRxProcess( void )
00403 {
00404     if( SerialDisplayReadable( ) == true )
00405     {
00406         switch( SerialDisplayGetChar( ) )
00407         {
00408             case 'R':
00409             case 'r':
00410                 // Refresh Serial screen
00411                 SerialDisplayRefresh( );
00412                 break;
00413             default:
00414                 break;
00415         }
00416     }
00417 }
00418 
00419 // Enables button when bouncing is over
00420 void button1_enabled_cb(void)
00421 {
00422     button1_enabled = true;
00423 }
00424 
00425 // ISR handling button pressed event
00426 void button1_onpressed_cb(void)
00427 {
00428     if (button1_enabled) { // Disabled while the button is bouncing
00429         button1_enabled = false;
00430         button1_pressed = true; // To be read by the main loop
00431         button1_timeout.attach(callback(button1_enabled_cb), 0.2); // Debounce time 200 ms
00432     }
00433 }
00434 
00435 // ****************************    COMMUNICATION PACKET DEFINITION METHODS   ********************************   //
00436 
00437 void heartbeat_message(uint8_t *hb_data, uint8_t *current_date) {
00438     hb_data[0] = 0xD2;
00439     memcpy(hb_data+1, current_date, 4);
00440 }
00441 
00442 void short_test_result(uint8_t *tdata, uint8_t *test_start_date, uint8_t *measurements) {
00443     tdata[0] = 0xD7;
00444     memcpy(tdata+1, test_start_date, 4);
00445     memcpy(tdata+5, measurements, 5);
00446 }
00447 
00448 void long_test_result(uint8_t *tdata, uint8_t *test_start_date, uint8_t *measurements) {
00449     tdata[0] = 0xD8;
00450     memcpy(tdata+1, test_start_date, 4);
00451     memcpy(tdata+5, measurements, 5);
00452 }
00453 
00454 /*!
00455  * \brief   Prepares the payload of the frame
00456  */
00457 static void PrepareTxFrame( uint8_t port )
00458 {
00459     switch( port )
00460     {
00461     case 15:
00462         {   
00463             switch ( MessageType ) 
00464             {
00465                 case MESSAGE_TYPE_HB:
00466                 {
00467                     AppDataSize = 5;
00468                     heartbeat_message(AppData, (uint8_t *)&current_time);
00469                     break;
00470                 }
00471                 case MESSAGE_TYPE_SHORT_TEST:
00472                 {
00473                     AppDataSize = 10;
00474                     short_test_result(AppData, (uint8_t *)&current_time, measurements);
00475                     break;
00476                 }
00477                 case MESSAGE_TYPE_LONG_TEST:
00478                 {
00479                     AppDataSize = 10;
00480                     long_test_result(AppData, (uint8_t *)&current_time, measurements);
00481                     break;
00482                 }
00483                 default:
00484                 {
00485                     AppDataSize = 5;
00486                     heartbeat_message(AppData, (uint8_t *)&current_time);
00487                     break;
00488                 }
00489             }
00490         }
00491         break;
00492     case 224:
00493         if( ComplianceTest.LinkCheck == true )
00494         {
00495             ComplianceTest.LinkCheck = false;
00496             AppDataSize = 3;
00497             AppData[0] = 5;
00498             AppData[1] = ComplianceTest.DemodMargin;
00499             AppData[2] = ComplianceTest.NbGateways;
00500             ComplianceTest.State = 1;
00501         }
00502         else
00503         {
00504             switch( ComplianceTest.State )
00505             {
00506             case 4:
00507                 ComplianceTest.State = 1;
00508                 break;
00509             case 1:
00510                 AppDataSize = 2;
00511                 AppData[0] = ComplianceTest.DownLinkCounter >> 8;
00512                 AppData[1] = ComplianceTest.DownLinkCounter;
00513                 break;
00514             }
00515         }
00516         break;
00517     default:
00518         break;
00519     }
00520 }
00521 
00522 /*!
00523  * \brief   Prepares the payload of the frame
00524  *
00525  * \retval  [0: frame could be send, 1: error]
00526  */
00527 static bool SendFrame( void )
00528 {
00529     McpsReq_t  mcpsReq;
00530     LoRaMacTxInfo_t  txInfo;
00531 
00532     if( LoRaMacQueryTxPossible( AppDataSize, &txInfo ) != LORAMAC_STATUS_OK  )
00533     {
00534         // Send empty frame in order to flush MAC commands
00535         mcpsReq.Type  = MCPS_UNCONFIRMED ;
00536         mcpsReq.Req.Unconfirmed .fBuffer  = NULL;
00537         mcpsReq.Req.Unconfirmed .fBufferSize  = 0;
00538         mcpsReq.Req.Unconfirmed .Datarate  = LORAWAN_DEFAULT_DATARATE;
00539 
00540         LoRaMacUplinkStatus.Acked = false;
00541         LoRaMacUplinkStatus.Port = 0;
00542         LoRaMacUplinkStatus.Buffer = NULL;
00543         LoRaMacUplinkStatus.BufferSize = 0;
00544         SerialDisplayUpdateFrameType( false );
00545         // SerialDisplayPrintDebugStatus( LoRaMacQueryTxPossible( AppDataSize, &txInfo ) );
00546         
00547     }
00548     else
00549     {
00550         LoRaMacUplinkStatus.Acked = false;
00551         LoRaMacUplinkStatus.Port = AppPort;
00552         LoRaMacUplinkStatus.Buffer = AppData;
00553         LoRaMacUplinkStatus.BufferSize = AppDataSize;
00554         SerialDisplayUpdateFrameType( IsTxConfirmed );
00555 
00556         if( IsTxConfirmed == false )
00557         {
00558             mcpsReq.Type  = MCPS_UNCONFIRMED ;
00559             mcpsReq.Req.Unconfirmed .fPort  = AppPort;
00560             mcpsReq.Req.Unconfirmed .fBuffer  = AppData;
00561             mcpsReq.Req.Unconfirmed .fBufferSize  = AppDataSize;
00562             mcpsReq.Req.Unconfirmed .Datarate  = LORAWAN_DEFAULT_DATARATE;
00563         }
00564         else
00565         {
00566             mcpsReq.Type  = MCPS_CONFIRMED ;
00567             mcpsReq.Req.Confirmed .fPort  = AppPort;
00568             mcpsReq.Req.Confirmed .fBuffer  = AppData;
00569             mcpsReq.Req.Confirmed .fBufferSize  = AppDataSize;
00570             mcpsReq.Req.Confirmed .NbTrials  = 8;
00571             mcpsReq.Req.Confirmed .Datarate  = LORAWAN_DEFAULT_DATARATE;
00572         }
00573     }
00574 
00575     if( LoRaMacMcpsRequest( &mcpsReq ) == LORAMAC_STATUS_OK  )
00576     {
00577         if( LoRaMacQueryTxPossible( AppDataSize, &txInfo ) != LORAMAC_STATUS_OK  )
00578         {
00579             return true;
00580         }
00581         return false;
00582     }
00583     return true;
00584 }
00585 
00586 /*!
00587  * \brief Function executed on TxNextPacket Timeout event
00588  */
00589 static void OnTxNextPacketTimerEvent( void )
00590 {
00591     MibRequestConfirm_t  mibReq;
00592     LoRaMacStatus_t  status;
00593 
00594     TimerStop( &TxNextPacketTimer );
00595 
00596     mibReq.Type  = MIB_NETWORK_JOINED ;
00597     status = LoRaMacMibGetRequestConfirm( &mibReq );
00598 
00599     if( status == LORAMAC_STATUS_OK  )
00600     {
00601         if( mibReq.Param .IsNetworkJoined  == true )
00602         {
00603             DeviceState = DEVICE_STATE_SEND;
00604             NextTx = true;
00605         }
00606         else
00607         {
00608             DeviceState = DEVICE_STATE_JOIN;
00609         }
00610     }
00611 }
00612 
00613 /*!
00614  * \brief Function executed on Led 1 Timeout event
00615  */
00616 static void OnLed1TimerEvent( void )
00617 {
00618     TimerStop( &Led1Timer );
00619     // Switch LED 1 OFF
00620     Led1State = false;
00621     Led1StateChanged = true;
00622 }
00623 
00624 /*!
00625  * \brief Function executed on Led 2 Timeout event
00626  */
00627 static void OnLed2TimerEvent( void )
00628 {
00629     TimerStop( &Led2Timer );
00630     // Switch LED 2 OFF
00631     Led2State = false;
00632     Led2StateChanged = true;
00633 }
00634 
00635 /*!
00636  * \brief   MCPS-Confirm event function
00637  *
00638  * \param   [IN] mcpsConfirm - Pointer to the confirm structure,
00639  *               containing confirm attributes.
00640  */
00641 static void McpsConfirm( McpsConfirm_t  *mcpsConfirm )
00642 {
00643     if( mcpsConfirm->Status  == LORAMAC_EVENT_INFO_STATUS_OK  )
00644     {
00645         switch( mcpsConfirm->McpsRequest  )
00646         {
00647             case MCPS_UNCONFIRMED :
00648             {
00649                 // Check Datarate
00650                 // Check TxPower
00651                 break;
00652             }
00653             case MCPS_CONFIRMED :
00654             {
00655                 // Check Datarate
00656                 // Check TxPower
00657                 // Check AckReceived
00658                 // Check NbTrials
00659                 LoRaMacUplinkStatus.Acked = mcpsConfirm->AckReceived ;
00660                 break;
00661             }
00662             case MCPS_PROPRIETARY :
00663             {
00664                 break;
00665             }
00666             default:
00667                 break;
00668         }
00669         LoRaMacUplinkStatus.Datarate = mcpsConfirm->Datarate ;
00670         LoRaMacUplinkStatus.UplinkCounter = mcpsConfirm->UpLinkCounter ;
00671 
00672         // Switch LED 1 ON
00673         Led1State = true;
00674         Led1StateChanged = true;
00675         TimerStart( &Led1Timer );
00676 
00677         UplinkStatusUpdated = true;
00678     }
00679     NextTx = true;
00680 }
00681 
00682 /*!
00683  * \brief   MCPS-Indication event function
00684  *
00685  * \param   [IN] mcpsIndication - Pointer to the indication structure,
00686  *               containing indication attributes.
00687  */
00688 static void McpsIndication( McpsIndication_t  *mcpsIndication )
00689 {
00690     if( mcpsIndication->Status  != LORAMAC_EVENT_INFO_STATUS_OK  )
00691     {
00692         return;
00693     }
00694 
00695     switch( mcpsIndication->McpsIndication  )
00696     {
00697         case MCPS_UNCONFIRMED :
00698         {
00699             break;
00700         }
00701         case MCPS_CONFIRMED :
00702         {
00703             break;
00704         }
00705         case MCPS_PROPRIETARY :
00706         {
00707             break;
00708         }
00709         case MCPS_MULTICAST :
00710         {
00711             break;
00712         }
00713         default:
00714             break;
00715     }
00716 
00717     // Check Multicast
00718     // Check Port
00719     // Check Datarate
00720     // Check FramePending
00721     // Check Buffer
00722     // Check BufferSize
00723     // Check Rssi
00724     // Check Snr
00725     // Check RxSlot
00726     LoRaMacDownlinkStatus.Rssi = mcpsIndication->Rssi ;
00727     if( mcpsIndication->Snr  & 0x80 ) // The SNR sign bit is 1
00728     {
00729         // Invert and divide by 4
00730         LoRaMacDownlinkStatus.Snr = ( ( ~mcpsIndication->Snr  + 1 ) & 0xFF ) >> 2;
00731         LoRaMacDownlinkStatus.Snr = -LoRaMacDownlinkStatus.Snr;
00732     }
00733     else
00734     {
00735         // Divide by 4
00736         LoRaMacDownlinkStatus.Snr = ( mcpsIndication->Snr  & 0xFF ) >> 2;
00737     }
00738     LoRaMacDownlinkStatus.DownlinkCounter++;
00739     LoRaMacDownlinkStatus.RxData = mcpsIndication->RxData ;
00740     LoRaMacDownlinkStatus.Port = mcpsIndication->Port ;
00741     LoRaMacDownlinkStatus.Buffer = mcpsIndication->Buffer ;
00742     LoRaMacDownlinkStatus.BufferSize = mcpsIndication->BufferSize ;
00743 
00744     if( ComplianceTest.Running == true )
00745     {
00746         ComplianceTest.DownLinkCounter++;
00747     }
00748 
00749     if( mcpsIndication->RxData  == true )
00750     {
00751         switch( mcpsIndication->Port  )
00752         {
00753         case 1: // The application LED can be controlled on port 1 or 2
00754         case 2:
00755             if( mcpsIndication->BufferSize  == 1 )
00756             {
00757                 AppLedStateOn = mcpsIndication->Buffer [0] & 0x01;
00758                 Led3StateChanged = true;
00759             }
00760             break;
00761         case 224:
00762             if( ComplianceTest.Running == false )
00763             {
00764                 // Check compliance test enable command (i)
00765                 if( ( mcpsIndication->BufferSize  == 4 ) &&
00766                     ( mcpsIndication->Buffer [0] == 0x01 ) &&
00767                     ( mcpsIndication->Buffer [1] == 0x01 ) &&
00768                     ( mcpsIndication->Buffer [2] == 0x01 ) &&
00769                     ( mcpsIndication->Buffer [3] == 0x01 ) )
00770                 {
00771                     IsTxConfirmed = false;
00772                     AppPort = 224;
00773                     AppDataSize = 2;
00774                     ComplianceTest.DownLinkCounter = 0;
00775                     ComplianceTest.LinkCheck = false;
00776                     ComplianceTest.DemodMargin = 0;
00777                     ComplianceTest.NbGateways = 0;
00778                     ComplianceTest.Running = true;
00779                     ComplianceTest.State = 1;
00780 
00781                     MibRequestConfirm_t  mibReq;
00782                     mibReq.Type  = MIB_ADR ;
00783                     mibReq.Param .AdrEnable  = true;
00784                     LoRaMacMibSetRequestConfirm( &mibReq );
00785 
00786 #if defined( USE_BAND_868 )
00787                     LoRaMacTestSetDutyCycleOn( false );
00788 #endif
00789                 }
00790             }
00791             else
00792             {
00793                 ComplianceTest.State = mcpsIndication->Buffer [0];
00794                 switch( ComplianceTest.State )
00795                 {
00796                 case 0: // Check compliance test disable command (ii)
00797                     IsTxConfirmed = LORAWAN_CONFIRMED_MSG_ON;
00798                     AppPort = LORAWAN_APP_PORT;
00799                     AppDataSize = LORAWAN_APP_DATA_SIZE;
00800                     ComplianceTest.DownLinkCounter = 0;
00801                     ComplianceTest.Running = false;
00802 
00803                     MibRequestConfirm_t  mibReq;
00804                     mibReq.Type  = MIB_ADR ;
00805                     mibReq.Param .AdrEnable  = LORAWAN_ADR_ON;
00806                     LoRaMacMibSetRequestConfirm( &mibReq );
00807 #if defined( USE_BAND_868 )
00808                     LoRaMacTestSetDutyCycleOn( LORAWAN_DUTYCYCLE_ON );
00809 #endif
00810                     break;
00811                 case 1: // (iii, iv)
00812                     AppDataSize = 2;
00813                     break;
00814                 case 2: // Enable confirmed messages (v)
00815                     IsTxConfirmed = true;
00816                     ComplianceTest.State = 1;
00817                     break;
00818                 case 3:  // Disable confirmed messages (vi)
00819                     IsTxConfirmed = false;
00820                     ComplianceTest.State = 1;
00821                     break;
00822                 case 4: // (vii)
00823                     AppDataSize = mcpsIndication->BufferSize ;
00824 
00825                     AppData[0] = 4;
00826                     for( uint8_t i = 1; i < AppDataSize; i++ )
00827                     {
00828                         AppData[i] = mcpsIndication->Buffer [i] + 1;
00829                     }
00830                     break;
00831                 case 5: // (viii)
00832                     {
00833                         MlmeReq_t  mlmeReq;
00834                         mlmeReq.Type  = MLME_LINK_CHECK ;
00835                         LoRaMacMlmeRequest( &mlmeReq );
00836                     }
00837                     break;
00838                 case 6: // (ix)
00839                     {
00840                         MlmeReq_t  mlmeReq;
00841 
00842                         // Disable TestMode and revert back to normal operation
00843                         IsTxConfirmed = LORAWAN_CONFIRMED_MSG_ON;
00844                         AppPort = LORAWAN_APP_PORT;
00845                         AppDataSize = LORAWAN_APP_DATA_SIZE;
00846                         ComplianceTest.DownLinkCounter = 0;
00847                         ComplianceTest.Running = false;
00848 
00849                         MibRequestConfirm_t  mibReq;
00850                         mibReq.Type  = MIB_ADR ;
00851                         mibReq.Param .AdrEnable  = LORAWAN_ADR_ON;
00852                         LoRaMacMibSetRequestConfirm( &mibReq );
00853 #if defined( USE_BAND_868 )
00854                         LoRaMacTestSetDutyCycleOn( LORAWAN_DUTYCYCLE_ON );
00855 #endif
00856 
00857                         mlmeReq.Type  = MLME_JOIN ;
00858 
00859                         mlmeReq.Req.Join .DevEui  = DevEui;
00860                         mlmeReq.Req.Join .AppEui  = AppEui;
00861                         mlmeReq.Req.Join .AppKey  = AppKey;
00862                         mlmeReq.Req.Join .NbTrials  = 3;
00863 
00864                         LoRaMacMlmeRequest( &mlmeReq );
00865                         DeviceState = DEVICE_STATE_SLEEP;
00866                     }
00867                     break;
00868                 case 7: // (x)
00869                     {
00870                         if( mcpsIndication->BufferSize  == 3 )
00871                         {
00872                             MlmeReq_t  mlmeReq;
00873                             mlmeReq.Type  = MLME_TXCW ;
00874                             mlmeReq.Req.TxCw .Timeout  = ( uint16_t )( ( mcpsIndication->Buffer [1] << 8 ) | mcpsIndication->Buffer [2] );
00875                             LoRaMacMlmeRequest( &mlmeReq );
00876                         }
00877                         else if( mcpsIndication->BufferSize  == 7 )
00878                         {
00879                             MlmeReq_t  mlmeReq;
00880                             mlmeReq.Type  = MLME_TXCW_1 ;
00881                             mlmeReq.Req.TxCw .Timeout  = ( uint16_t )( ( mcpsIndication->Buffer [1] << 8 ) | mcpsIndication->Buffer [2] );
00882                             mlmeReq.Req.TxCw .Frequency  = ( uint32_t )( ( mcpsIndication->Buffer [3] << 16 ) | ( mcpsIndication->Buffer [4] << 8 ) | mcpsIndication->Buffer [5] ) * 100;
00883                             mlmeReq.Req.TxCw .Power  = mcpsIndication->Buffer [6];
00884                             LoRaMacMlmeRequest( &mlmeReq );
00885                         }
00886                         ComplianceTest.State = 1;
00887                     }
00888                     break;
00889                 default:
00890                     break;
00891                 }
00892             }
00893             break;
00894         default:
00895             break;
00896         }
00897     }
00898 
00899     // Switch LED 2 ON for each received downlink
00900     Led2State = true;
00901     Led2StateChanged = true;
00902     TimerStart( &Led2Timer );
00903     DownlinkStatusUpdated = true;
00904 }
00905 
00906 /*!
00907  * \brief   MLME-Confirm event function
00908  *
00909  * \param   [IN] mlmeConfirm - Pointer to the confirm structure,
00910  *               containing confirm attributes.
00911  */
00912 static void MlmeConfirm( MlmeConfirm_t  *mlmeConfirm )
00913 {
00914     switch( mlmeConfirm->MlmeRequest  )
00915     {
00916         case MLME_JOIN :
00917         {
00918             if( mlmeConfirm->Status  == LORAMAC_EVENT_INFO_STATUS_OK  )
00919             {
00920                 // Status is OK, node has joined the network
00921                 IsNetworkJoinedStatusUpdate = true;
00922                 DeviceState = DEVICE_STATE_SEND;
00923                 
00924             
00925                 MessageType = MESSAGE_TYPE_HB;
00926                 joining = false;
00927                 next_stest = current_time + 5;
00928                 next_ltest = current_time + long_interval;
00929             }
00930             else
00931             {
00932                 // Join was not successful. Try to join again
00933                 DeviceState = DEVICE_STATE_JOIN;
00934             }
00935             break;
00936         }
00937         case MLME_LINK_CHECK :
00938         {
00939             if( mlmeConfirm->Status  == LORAMAC_EVENT_INFO_STATUS_OK  )
00940             {
00941                 // Check DemodMargin
00942                 // Check NbGateways
00943                 if( ComplianceTest.Running == true )
00944                 {
00945                     ComplianceTest.LinkCheck = true;
00946                     ComplianceTest.DemodMargin = mlmeConfirm->DemodMargin ;
00947                     ComplianceTest.NbGateways = mlmeConfirm->NbGateways ;
00948                 }
00949             }
00950             break;
00951         }
00952         default:
00953             break;
00954     }
00955     NextTx = true;
00956     UplinkStatusUpdated = true;
00957 }
00958 
00959 
00960 // ****************************    TEST METHODS   ********************************   //
00961 
00962 void startTest(uint8_t *measurements) {
00963     
00964     // Determine test length
00965     switch (MessageType)
00966     {
00967         case MESSAGE_TYPE_SHORT_TEST:
00968             test_duration = 30;
00969             break;
00970         case MESSAGE_TYPE_LONG_TEST:
00971             test_duration = 5400;
00972             break;
00973         default:
00974             test_duration = 0;
00975             break;
00976     }
00977     
00978     // Start test
00979     relayPin = 1;
00980     AppLedStateOn = 1;
00981     Led3StateChanged = true;
00982     
00983     // Measure voltage preval
00984     float battery_reading = BAT_PIN.read()*1000;
00985     measurements[0] = (uint8_t) rintf(battery_reading/10);
00986 }
00987 
00988 void endTest(uint8_t *measurements) {
00989     // Measure endvals
00990     float battery_reading = BAT_PIN.read()*1000;
00991     int vce_reading = VCE_PIN.read()*1000;
00992     int light_1_reading = LIGHT_1_PIN.read()*1000 - vce_reading;
00993     int light_2_reading = LIGHT_2_PIN.read()*1000 - vce_reading;
00994     int rh_reading = RH_PIN.read()*1000 - vce_reading;
00995     
00996     measurements[1] = (uint8_t) rintf(battery_reading/10);
00997     measurements[2] = (uint8_t) (light_1_reading/2);
00998     measurements[3] = (uint8_t) (light_2_reading/2);
00999     measurements[4] = (uint8_t) (rh_reading/2);
01000     
01001     // End test // 
01002     relayPin = 0;
01003     AppLedStateOn = 0;
01004     Led3StateChanged = true;
01005 }
01006 
01007 void button_options_handler(void)
01008 {
01009     if (press_count >= 4) {
01010         // Run long test if 4 or more clicks
01011         MessageType = MESSAGE_TYPE_LONG_TEST;
01012         
01013         startTest(measurements);
01014                     
01015         running_test = true;
01016         test_start = current_time;
01017     }
01018     if (press_count == 2 || press_count == 3) {
01019         // Run short test if 2 or 3 clicks
01020         MessageType = MESSAGE_TYPE_SHORT_TEST;
01021         
01022         startTest(measurements);
01023                     
01024         running_test = true;
01025         test_start = current_time;
01026     }
01027     
01028     // Reset count
01029     press_count = 0;
01030 }
01031 
01032 /**
01033  * Main application entry point.
01034  */
01035 Serial pc(SERIAL_TX, SERIAL_RX,115200);
01036 int MY_SetSysClock_PLL_HSE(void)
01037 {
01038     RCC_ClkInitTypeDef RCC_ClkInitStruct;
01039     RCC_OscInitTypeDef RCC_OscInitStruct;
01040 
01041     /* configure RTC clock for HSE */
01042     SET_BIT(PWR->CR, PWR_CR_DBP);   // enable RTC register access as they are in backup domain
01043     __HAL_RCC_BACKUPRESET_FORCE();  // force reset RTC subsystem
01044     __HAL_RCC_BACKUPRESET_RELEASE();
01045     __HAL_RCC_RTC_CONFIG(RCC_RTCCLKSOURCE_HSE_DIV8); // HSE=8MHZ and RTC clock input is 1MHz(when using HSE as source)
01046     
01047     /* Enable HSE and activate PLL with HSE as source */
01048     RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
01049     RCC_OscInitStruct.HSEState       = RCC_HSE_ON; /* External 8 MHz xtal on OSC_IN/OSC_OUT */
01050 
01051     // PLLCLK = (8 MHz * 8)/2 = 32 MHz
01052     RCC_OscInitStruct.PLL.PLLState        = RCC_PLL_ON;
01053     RCC_OscInitStruct.PLL.PLLSource       = RCC_PLLSOURCE_HSE;
01054     RCC_OscInitStruct.PLL.PLLMUL          = RCC_PLLMUL_8;
01055     RCC_OscInitStruct.PLL.PLLDIV          = RCC_PLLDIV_2;
01056     if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK) {
01057         return (-1); // FAIL
01058     }
01059 
01060     /* Select PLL as system clock source and configure the HCLK, PCLK1 and PCLK2 clocks dividers */
01061     RCC_ClkInitStruct.ClockType      = (RCC_CLOCKTYPE_SYSCLK | RCC_CLOCKTYPE_HCLK | RCC_CLOCKTYPE_PCLK1 | RCC_CLOCKTYPE_PCLK2);
01062     RCC_ClkInitStruct.SYSCLKSource   = RCC_SYSCLKSOURCE_PLLCLK; // 32 MHz
01063     RCC_ClkInitStruct.AHBCLKDivider  = RCC_SYSCLK_DIV1;         // 32 MHz
01064     RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1;           // 32 MHz
01065     RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;           // 32 MHz
01066     if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_1) != HAL_OK) {
01067         return (-2); // FAIL
01068     }
01069 
01070     /* Enable HSE and activate PLL with HSE as source */
01071     RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI48|RCC_OSCILLATORTYPE_HSI|RCC_OSCILLATORTYPE_MSI;
01072     RCC_OscInitStruct.HSIState       = RCC_HSI_OFF;
01073     RCC_OscInitStruct.MSIState       = RCC_MSI_OFF;
01074     RCC_OscInitStruct.HSI48State     = RCC_HSI48_OFF;
01075     RCC_OscInitStruct.PLL.PLLState   = RCC_PLL_NONE;
01076     if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK) {
01077         return (-3); // FAIL
01078     }
01079 
01080     // enable rtc hardware
01081     __HAL_RCC_RTC_ENABLE();
01082     wait(1.0);
01083 
01084     return 0; // OK
01085 }
01086 
01087 void my_patch(void)
01088 {
01089     int retVal;
01090     
01091     // Put device into default clock, i.e using MSI = 2MHz
01092     HAL_RCC_DeInit();
01093     
01094     // Enable HSE clock
01095     retVal = MY_SetSysClock_PLL_HSE();
01096     if(retVal< 0)
01097     {
01098         // fail
01099         //pc.printf("Failed to start HSE, ERR= %d\r\n", retVal);
01100         
01101         // indicate error
01102         while(1)
01103         {
01104             myled = 1;
01105             wait(0.2);
01106             myled = 0;
01107             wait(0.5);
01108         }
01109     }    
01110 }
01111 
01112 int main( void )
01113 {
01114     pc.printf("BUILD: %s mbed-os-rev: %d.%d.%d lib-rev: %d\r\n", \
01115             __TIME__, MBED_MAJOR_VERSION, MBED_MINOR_VERSION,MBED_PATCH_VERSION,MBED_LIBRARY_VERSION);
01116     pc.printf("OLD: SysClock= %d RCC= %08X CSR= %08X CIER= %08X\r\n", SystemCoreClock, RCC->CR, RCC->CSR, RCC->CIER);
01117     my_patch();
01118     pc.printf("\r\nNEW: SysClock= %d RCC= %08X CSR= %08X CIER= %08X\r\n", SystemCoreClock, RCC->CR, RCC->CSR, RCC->CIER);
01119     
01120     wait(3);
01121     LoRaMacPrimitives_t  LoRaMacPrimitives;
01122     LoRaMacCallback_t LoRaMacCallbacks;
01123     MibRequestConfirm_t  mibReq;
01124 
01125     BoardInit( );
01126     SerialDisplayInit( );
01127 
01128     SerialDisplayUpdateEui( 5, DevEui );
01129     SerialDisplayUpdateEui( 6, AppEui );
01130     SerialDisplayUpdateKey( 7, AppKey );
01131 
01132 #if( OVER_THE_AIR_ACTIVATION == 0 )
01133     SerialDisplayUpdateNwkId( LORAWAN_NETWORK_ID );
01134     SerialDisplayUpdateDevAddr( DevAddr );
01135     SerialDisplayUpdateKey( 12, NwkSKey );
01136     SerialDisplayUpdateKey( 13, AppSKey );
01137 #endif
01138 
01139     DeviceState = DEVICE_STATE_INIT;
01140     set_time(1514764800);
01141     relayPin = 0;
01142     
01143     running_test = false;
01144     joining = true;
01145     //received_downlink = false;
01146     time_t start_time = time(NULL);
01147   
01148     last_hb = start_time;
01149     
01150     //button1.mode(PullUp); // Activate pull-up
01151     button1.fall(callback(button1_onpressed_cb)); // Attach ISR to handle button press event
01152     AppLedStateOn = 0;
01153     Led3StateChanged = true;
01154     
01155     myGreenLed = 0; // INITIAL OFF
01156     GreenLedState = GREEN_LED_STATE_INIT;
01157     TimerInit( &GreenLedTimer, OnGreenLedTimerEvent );
01158     TimerSetValue( &GreenLedTimer, 100 );
01159     TimerStart( &GreenLedTimer );
01160     
01161     TimerInit( &BatteryCheckTimer, OnBatteryCheckTimerEvent );
01162     TimerSetValue( &BatteryCheckTimer, 100 ); // 100msec
01163     TimerStart( &BatteryCheckTimer );
01164 
01165     while( 1 )
01166     {
01167         current_time = time(NULL);
01168         SerialRxProcess( );
01169         if( IsNetworkJoinedStatusUpdate == true )
01170         {
01171             IsNetworkJoinedStatusUpdate = false;
01172             mibReq.Type  = MIB_NETWORK_JOINED ;
01173             LoRaMacMibGetRequestConfirm( &mibReq );
01174             SerialDisplayUpdateNetworkIsJoined( mibReq.Param .IsNetworkJoined  );
01175         }
01176         if( Led1StateChanged == true )
01177         {
01178             Led1StateChanged = false;
01179             SerialDisplayUpdateLedState( 1, Led1State );
01180         }
01181         if( Led2StateChanged == true )
01182         {
01183             Led2StateChanged = false;
01184             SerialDisplayUpdateLedState( 2, Led2State );
01185         }
01186         if( Led3StateChanged == true )
01187         {
01188             Led3StateChanged = false;
01189             SerialDisplayUpdateLedState( 3, AppLedStateOn );
01190         }
01191         if( UplinkStatusUpdated == true )
01192         {
01193             UplinkStatusUpdated = false;
01194             SerialDisplayUpdateUplink( LoRaMacUplinkStatus.Acked, LoRaMacUplinkStatus.Datarate, LoRaMacUplinkStatus.UplinkCounter, LoRaMacUplinkStatus.Port, LoRaMacUplinkStatus.Buffer, LoRaMacUplinkStatus.BufferSize );
01195         }
01196         if( DownlinkStatusUpdated == true )
01197         {
01198             DownlinkStatusUpdated = false;
01199             SerialDisplayUpdateLedState( 2, Led2State );
01200             SerialDisplayUpdateDownlink( LoRaMacDownlinkStatus.RxData, LoRaMacDownlinkStatus.Rssi, LoRaMacDownlinkStatus.Snr, LoRaMacDownlinkStatus.DownlinkCounter, LoRaMacDownlinkStatus.Port, LoRaMacDownlinkStatus.Buffer, LoRaMacDownlinkStatus.BufferSize );
01201         }
01202         
01203         if( BatteryCheckFlag == true)
01204         {
01205             BatteryCheckFlag = false;
01206 
01207             // Measure voltage preval
01208             float battery_reading = BAT_PIN.read()*3300*2;
01209  //           pc.printf("VBAT= %d", (int)battery_reading);
01210             
01211             // Setting min value 2.0V so if relay button is pressed without battery Green LED will be OFF.
01212             // Set max value 4.45V as this voltage is seen at the battery pin.
01213             if((battery_reading < 2000)||(battery_reading > 4450)) 
01214             {
01215                 BatteryLowFlag = true;
01216             }
01217             else
01218             {
01219                 BatteryLowFlag = false;
01220             }
01221         }
01222         
01223         switch( DeviceState )
01224         {
01225             case DEVICE_STATE_INIT:
01226             {
01227                 LoRaMacPrimitives.MacMcpsConfirm = McpsConfirm;
01228                 LoRaMacPrimitives.MacMcpsIndication = McpsIndication;
01229                 LoRaMacPrimitives.MacMlmeConfirm = MlmeConfirm;
01230                 LoRaMacCallbacks.GetBatteryLevel = BoardGetBatteryLevel;
01231                 LoRaMacInitialization( &LoRaMacPrimitives, &LoRaMacCallbacks );
01232 
01233                 TimerInit( &TxNextPacketTimer, OnTxNextPacketTimerEvent );
01234 
01235                 TimerInit( &Led1Timer, OnLed1TimerEvent );
01236                 TimerSetValue( &Led1Timer, 25 );
01237 
01238                 TimerInit( &Led2Timer, OnLed2TimerEvent );
01239                 TimerSetValue( &Led2Timer, 25 );
01240 
01241                 mibReq.Type  = MIB_ADR ;
01242                 mibReq.Param .AdrEnable  = LORAWAN_ADR_ON;
01243                 LoRaMacMibSetRequestConfirm( &mibReq );
01244 
01245                 mibReq.Type  = MIB_PUBLIC_NETWORK ;
01246                 mibReq.Param .EnablePublicNetwork  = LORAWAN_PUBLIC_NETWORK;
01247                 LoRaMacMibSetRequestConfirm( &mibReq );
01248 
01249                 // Limiting to just 2nd subband of 8 channels
01250                 static uint16_t GatewayChannelsMask[] = {0xFF00, 0x0000, 0x0000, 0x0000, 0x0002, 0x0000};
01251                 mibReq.Type  = MIB_CHANNELS_DEFAULT_MASK ;
01252                 mibReq.Param .ChannelsDefaultMask  = GatewayChannelsMask;
01253                 LoRaMacMibSetRequestConfirm( &mibReq );
01254 
01255                 mibReq.Type  = MIB_CHANNELS_MASK ;
01256                 mibReq.Param .ChannelsMask  = GatewayChannelsMask;
01257                 LoRaMacMibSetRequestConfirm( &mibReq );
01258                 
01259 
01260 #if defined( USE_BAND_868 )
01261                 LoRaMacTestSetDutyCycleOn( LORAWAN_DUTYCYCLE_ON );
01262                 SerialDisplayUpdateDutyCycle( LORAWAN_DUTYCYCLE_ON );
01263 
01264 #if( USE_SEMTECH_DEFAULT_CHANNEL_LINEUP == 1 )
01265                 LoRaMacChannelAdd( 3, ( ChannelParams_t  )LC4 );
01266                 LoRaMacChannelAdd( 4, ( ChannelParams_t  )LC5 );
01267                 LoRaMacChannelAdd( 5, ( ChannelParams_t  )LC6 );
01268                 LoRaMacChannelAdd( 6, ( ChannelParams_t  )LC7 );
01269                 LoRaMacChannelAdd( 7, ( ChannelParams_t  )LC8 );
01270                 LoRaMacChannelAdd( 8, ( ChannelParams_t  )LC9 );
01271                 LoRaMacChannelAdd( 9, ( ChannelParams_t  )LC10 );
01272 
01273                 mibReq.Type  = MIB_RX2_DEFAULT_CHANNEL ;
01274                 mibReq.Param .Rx2DefaultChannel  = ( Rx2ChannelParams_t  ){ 869525000, DR_3 };
01275                 LoRaMacMibSetRequestConfirm( &mibReq );
01276 
01277                 mibReq.Type  = MIB_RX2_CHANNEL ;
01278                 mibReq.Param .Rx2Channel  = ( Rx2ChannelParams_t  ){ 869525000, DR_3 };
01279                 LoRaMacMibSetRequestConfirm( &mibReq );
01280 #endif
01281 
01282 #endif
01283                 SerialDisplayUpdateActivationMode( OVER_THE_AIR_ACTIVATION );
01284                 SerialDisplayUpdateAdr( LORAWAN_ADR_ON );
01285                 SerialDisplayUpdatePublicNetwork( LORAWAN_PUBLIC_NETWORK );
01286 
01287                 LoRaMacDownlinkStatus.DownlinkCounter = 0;
01288 
01289                 DeviceState = DEVICE_STATE_JOIN;
01290                 break;
01291             }
01292             case DEVICE_STATE_JOIN:
01293             {
01294 #if( OVER_THE_AIR_ACTIVATION != 0 )
01295                 MlmeReq_t  mlmeReq;
01296 
01297                 mlmeReq.Type  = MLME_JOIN ;
01298 
01299                 mlmeReq.Req.Join .DevEui  = DevEui;
01300                 mlmeReq.Req.Join .AppEui  = AppEui;
01301                 mlmeReq.Req.Join .AppKey  = AppKey;
01302 
01303                 if( NextTx == true )
01304                 {
01305                     LoRaMacMlmeRequest( &mlmeReq );
01306                 }
01307                 DeviceState = DEVICE_STATE_SLEEP;
01308 #else
01309                 mibReq.Type  = MIB_NET_ID ;
01310                 mibReq.Param .NetID  = LORAWAN_NETWORK_ID;
01311                 LoRaMacMibSetRequestConfirm( &mibReq );
01312 
01313                 mibReq.Type  = MIB_DEV_ADDR ;
01314                 mibReq.Param .DevAddr  = DevAddr;
01315                 LoRaMacMibSetRequestConfirm( &mibReq );
01316 
01317                 mibReq.Type  = MIB_NWK_SKEY ;
01318                 mibReq.Param .NwkSKey  = NwkSKey;
01319                 LoRaMacMibSetRequestConfirm( &mibReq );
01320 
01321                 mibReq.Type  = MIB_APP_SKEY ;
01322                 mibReq.Param .AppSKey  = AppSKey;
01323                 LoRaMacMibSetRequestConfirm( &mibReq );
01324 
01325                 mibReq.Type  = MIB_NETWORK_JOINED ;
01326                 mibReq.Param .IsNetworkJoined  = true;
01327                 LoRaMacMibSetRequestConfirm( &mibReq );
01328 
01329                 DeviceState = DEVICE_STATE_SEND;
01330 #endif
01331                 IsNetworkJoinedStatusUpdate = true;
01332                 break;
01333             }
01334             case DEVICE_STATE_SEND:
01335             {
01336                 if( NextTx == true )
01337                 {
01338                     SerialDisplayUpdateUplinkAcked( false );
01339                     SerialDisplayUpdateDonwlinkRxData( false );
01340                     PrepareTxFrame( AppPort );
01341 
01342                     NextTx = SendFrame( );
01343                 }
01344                 if( ComplianceTest.Running == true )
01345                 {
01346                     // Schedule next packet transmission
01347                     TxDutyCycleTime = 5000; // 5000 ms
01348                 }
01349                 else
01350                 {
01351                     // Schedule next packet transmission
01352                     TxDutyCycleTime = APP_TX_DUTYCYCLE + randr( -APP_TX_DUTYCYCLE_RND, APP_TX_DUTYCYCLE_RND );
01353                 }
01354                 
01355                 if ( NextTx == true ) 
01356                 {
01357                     DeviceState = DEVICE_STATE_SLEEP;
01358 
01359                     // Schedule next packet transmission
01360                     TimerSetValue( &TxNextPacketTimer, TxDutyCycleTime );
01361                     TimerStart( &TxNextPacketTimer );
01362                     
01363                     // char my_str[17] = "Scheduled Resend";
01364                     // SerialDisplayPrintDebugLine( my_str, 17 );
01365                 }
01366                 else
01367                 {
01368                     DeviceState = DEVICE_STATE_CYCLE;
01369                 }
01370                 
01371                 break;
01372             }
01373             case DEVICE_STATE_CYCLE:
01374             {
01375                 // DeviceState = DEVICE_STATE_SLEEP;
01376 
01377                 // Schedule next packet transmission
01378                 // TimerSetValue( &TxNextPacketTimer, TxDutyCycleTime );
01379                 // TimerStart( &TxNextPacketTimer );
01380                 
01381                 
01382                 
01383                 // Is a test is running
01384                 if (running_test) {
01385                   // If it is 
01386               
01387                   //check if it's time to end the test
01388                   if (current_time - test_start >= test_duration) {
01389                     endTest(measurements);
01390                     // sendResult(measurements, ttype);
01391                     DeviceState = DEVICE_STATE_SEND;
01392                     last_hb = current_time;
01393               
01394                     // Set the times for the next tests
01395                     switch ( MessageType )
01396                     {
01397                         case MESSAGE_TYPE_SHORT_TEST:
01398                         {
01399                             next_stest = test_start + test_interval;
01400                             break;
01401                         }
01402                         default:
01403                         {
01404                             // If long test, reset both test types, 
01405                             // to prevent two tests at the same time
01406                             next_stest = test_start + test_interval;
01407                             next_ltest = test_start + long_interval;
01408                             break;
01409                         }  
01410                     }
01411                     
01412                     running_test = false;
01413                   }
01414                 } else {
01415                   // If it isn't
01416                   
01417                   // check if downlink action is required
01418             
01419                   //if (received_downlink == true) {
01420                   //  dl_handler(received_data);
01421                   //}
01422                   
01423                   //check if button is pressed
01424                     if (button1_pressed) { // Set when button is pressed
01425                         if (press_count == 0) {
01426                             buttonOptions_timeout.attach(callback(button_options_handler), 2); // Debounce time 300 ms
01427                         }
01428                         button1_pressed = false;
01429                         press_count++;
01430                     }
01431                   
01432                   //check if it's time to run a test
01433                   if (current_time >= next_stest || current_time >= next_ltest) {
01434               
01435                     // Check what kind of test to run
01436                     if (current_time >= next_ltest) {
01437                       MessageType = MESSAGE_TYPE_LONG_TEST;
01438                     } else {
01439                       MessageType = MESSAGE_TYPE_SHORT_TEST;
01440                     }
01441             
01442                     startTest(measurements);
01443                     
01444                     running_test = true;
01445                     test_start = current_time;
01446               
01447                     
01448                   //check if it's time for a heartbeat
01449                   } else if (current_time - last_hb >= hb_interval) { 
01450                     // sendHb();
01451                     DeviceState = DEVICE_STATE_SEND;
01452                     MessageType = MESSAGE_TYPE_HB;
01453                     last_hb = current_time;
01454                   }
01455                 }
01456                 
01457                 
01458                 break;
01459             }
01460             case DEVICE_STATE_SLEEP:
01461             {
01462                 // Wake up through events
01463                 break;
01464             }
01465             default:
01466             {
01467                 DeviceState = DEVICE_STATE_INIT;
01468                 break;
01469             }
01470         }
01471     }
01472 }