Node code for sx1272 LoRa transciever

Dependencies:   mbed BMP085 BufferedSerial DHT Sds021 Chainable_RGB_LED DigitDisplay LoRaWAN-lib SX1272Lib

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