Amir Chaudhary / Mbed 2 deprecated LoRaWAN-hello-world_new_mcu_Anish

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 
00089 
00090 static uint8_t DevEui[] = LORAWAN_DEVICE_EUI;
00091 static uint8_t AppEui[] = LORAWAN_APPLICATION_EUI;
00092 static uint8_t AppKey[] = LORAWAN_APPLICATION_KEY;
00093 
00094 #if( OVER_THE_AIR_ACTIVATION == 0 )
00095 
00096 static uint8_t NwkSKey[] = LORAWAN_NWKSKEY;
00097 static uint8_t AppSKey[] = LORAWAN_APPSKEY;
00098 
00099 /*!
00100  * Device address
00101  */
00102 static uint32_t DevAddr = LORAWAN_DEVICE_ADDRESS;
00103 
00104 #endif
00105 
00106 /*!
00107  * Application port
00108  */
00109 static uint8_t AppPort = LORAWAN_APP_PORT;
00110 
00111 /*!
00112  * User application data size
00113  */
00114 static uint8_t AppDataSize = LORAWAN_APP_DATA_SIZE;
00115 
00116 /*!
00117  * User application data buffer size
00118  */
00119 #define LORAWAN_APP_DATA_MAX_SIZE                           64
00120 
00121 /*!
00122  * User application data
00123  */
00124 static uint8_t AppData[LORAWAN_APP_DATA_MAX_SIZE];
00125 
00126 /*!
00127  * Indicates if the node is sending confirmed or unconfirmed messages
00128  */
00129 static uint8_t IsTxConfirmed = LORAWAN_CONFIRMED_MSG_ON;
00130 
00131 /*!
00132  * Defines the application data transmission duty cycle
00133  */
00134 static uint32_t TxDutyCycleTime;
00135 
00136 /*!
00137  * Timer to handle the application data transmission duty cycle
00138  */
00139 static TimerEvent_t TxNextPacketTimer;
00140 
00141 /*!
00142  * Indicates if a new packet can be sent
00143  */
00144 static bool NextTx = true;
00145 
00146 /*!
00147  * Device states
00148  */
00149 static enum eDeviceState
00150 {
00151     DEVICE_STATE_INIT,
00152     DEVICE_STATE_JOIN,
00153     DEVICE_STATE_SEND,
00154     DEVICE_STATE_CYCLE,
00155     DEVICE_STATE_SLEEP
00156 }DeviceState;
00157 
00158 /*!
00159  * LoRaWAN compliance tests support data
00160  */
00161 struct ComplianceTest_s
00162 {
00163     bool Running;
00164     uint8_t State;
00165     bool IsTxConfirmed;
00166     uint8_t AppPort;
00167     uint8_t AppDataSize;
00168     uint8_t *AppDataBuffer;
00169     uint16_t DownLinkCounter;
00170     bool LinkCheck;
00171     uint8_t DemodMargin;
00172     uint8_t NbGateways;
00173 }ComplianceTest;
00174 
00175 /*
00176  * SerialDisplay managment variables
00177  */
00178 
00179 /*!
00180  * Indicates if the MAC layer network join status has changed.
00181  */
00182 static bool IsNetworkJoinedStatusUpdate = false;
00183 
00184 /*!
00185  * Strucure containing the Uplink status
00186  */
00187 struct sLoRaMacUplinkStatus
00188 {
00189     uint8_t Acked;
00190     int8_t Datarate;
00191     uint16_t UplinkCounter;
00192     uint8_t Port;
00193     uint8_t *Buffer;
00194     uint8_t BufferSize;
00195 }LoRaMacUplinkStatus;
00196 volatile bool UplinkStatusUpdated = false;
00197 
00198 /*!
00199  * Strucure containing the Downlink status
00200  */
00201 struct sLoRaMacDownlinkStatus
00202 {
00203     int16_t Rssi;
00204     int8_t Snr;
00205     uint16_t DownlinkCounter;
00206     bool RxData;
00207     uint8_t Port;
00208     uint8_t *Buffer;
00209     uint8_t BufferSize;
00210 }LoRaMacDownlinkStatus;
00211 volatile bool DownlinkStatusUpdated = false;
00212 
00213 
00214 // Application Globals
00215 DigitalOut myled(D7);
00216 
00217 
00218 
00219 void SerialDisplayRefresh( void )
00220 {
00221     MibRequestConfirm_t  mibReq;
00222 
00223     SerialDisplayInit( );
00224     SerialDisplayUpdateActivationMode( OVER_THE_AIR_ACTIVATION );
00225 
00226 #if( OVER_THE_AIR_ACTIVATION == 0 )
00227     SerialDisplayUpdateNwkId( LORAWAN_NETWORK_ID );
00228     SerialDisplayUpdateDevAddr( DevAddr );
00229     SerialDisplayUpdateKey( 12, NwkSKey );
00230     SerialDisplayUpdateKey( 13, AppSKey );
00231 #endif
00232     SerialDisplayUpdateEui( 5, DevEui );
00233     SerialDisplayUpdateEui( 6, AppEui );
00234     SerialDisplayUpdateKey( 7, AppKey );
00235 
00236     mibReq.Type  = MIB_NETWORK_JOINED ;
00237     LoRaMacMibGetRequestConfirm( &mibReq );
00238     SerialDisplayUpdateNetworkIsJoined( mibReq.Param .IsNetworkJoined  );
00239 
00240     SerialDisplayUpdateAdr( LORAWAN_ADR_ON );
00241 #if defined( USE_BAND_868 )
00242     SerialDisplayUpdateDutyCycle( LORAWAN_DUTYCYCLE_ON );
00243 #else
00244     SerialDisplayUpdateDutyCycle( false );
00245 #endif
00246     SerialDisplayUpdatePublicNetwork( LORAWAN_PUBLIC_NETWORK );
00247 }
00248 
00249 void SerialRxProcess( void )
00250 {
00251     if( SerialDisplayReadable( ) == true )
00252     {
00253         switch( SerialDisplayGetChar( ) )
00254         {
00255             case 'R':
00256             case 'r':
00257                 // Refresh Serial screen
00258                 SerialDisplayRefresh( );
00259                 break;
00260             default:
00261                 break;
00262         }
00263     }
00264 }
00265 
00266 /*!
00267  * \brief   Prepares the payload of the frame
00268  */
00269 static void PrepareTxFrame( uint8_t port )
00270 {
00271     switch( port )
00272     {
00273     case 15:
00274         {
00275             AppData[0] = 0;
00276             if( IsTxConfirmed == true )
00277             {
00278                 AppData[1] = LoRaMacDownlinkStatus.DownlinkCounter >> 8;
00279                 AppData[2] = LoRaMacDownlinkStatus.DownlinkCounter;
00280                 AppData[3] = LoRaMacDownlinkStatus.Rssi >> 8;
00281                 AppData[4] = LoRaMacDownlinkStatus.Rssi;
00282                 AppData[5] = LoRaMacDownlinkStatus.Snr;
00283             }
00284         }
00285         break;
00286     case 224:
00287         if( ComplianceTest.LinkCheck == true )
00288         {
00289             ComplianceTest.LinkCheck = false;
00290             AppDataSize = 3;
00291             AppData[0] = 5;
00292             AppData[1] = ComplianceTest.DemodMargin;
00293             AppData[2] = ComplianceTest.NbGateways;
00294             ComplianceTest.State = 1;
00295         }
00296         else
00297         {
00298             switch( ComplianceTest.State )
00299             {
00300             case 4:
00301                 ComplianceTest.State = 1;
00302                 break;
00303             case 1:
00304                 AppDataSize = 2;
00305                 AppData[0] = ComplianceTest.DownLinkCounter >> 8;
00306                 AppData[1] = ComplianceTest.DownLinkCounter;
00307                 break;
00308             }
00309         }
00310         break;
00311     default:
00312         break;
00313     }
00314 }
00315 
00316 /*!
00317  * \brief   Prepares the payload of the frame
00318  *
00319  * \retval  [0: frame could be send, 1: error]
00320  */
00321 static bool SendFrame( void )
00322 {
00323     McpsReq_t  mcpsReq;
00324     LoRaMacTxInfo_t  txInfo;
00325 
00326     if( LoRaMacQueryTxPossible( AppDataSize, &txInfo ) != LORAMAC_STATUS_OK  )
00327     {
00328         // Send empty frame in order to flush MAC commands
00329         mcpsReq.Type  = MCPS_UNCONFIRMED ;
00330         mcpsReq.Req.Unconfirmed .fBuffer  = NULL;
00331         mcpsReq.Req.Unconfirmed .fBufferSize  = 0;
00332         mcpsReq.Req.Unconfirmed .Datarate  = LORAWAN_DEFAULT_DATARATE;
00333 
00334         LoRaMacUplinkStatus.Acked = false;
00335         LoRaMacUplinkStatus.Port = 0;
00336         LoRaMacUplinkStatus.Buffer = NULL;
00337         LoRaMacUplinkStatus.BufferSize = 0;
00338         SerialDisplayUpdateFrameType( false );
00339     }
00340     else
00341     {
00342         LoRaMacUplinkStatus.Acked = false;
00343         LoRaMacUplinkStatus.Port = AppPort;
00344         LoRaMacUplinkStatus.Buffer = AppData;
00345         LoRaMacUplinkStatus.BufferSize = AppDataSize;
00346         SerialDisplayUpdateFrameType( IsTxConfirmed );
00347 
00348         if( IsTxConfirmed == false )
00349         {
00350             mcpsReq.Type  = MCPS_UNCONFIRMED ;
00351             mcpsReq.Req.Unconfirmed .fPort  = AppPort;
00352             mcpsReq.Req.Unconfirmed .fBuffer  = AppData;
00353             mcpsReq.Req.Unconfirmed .fBufferSize  = AppDataSize;
00354             mcpsReq.Req.Unconfirmed .Datarate  = LORAWAN_DEFAULT_DATARATE;
00355         }
00356         else
00357         {
00358             mcpsReq.Type  = MCPS_CONFIRMED ;
00359             mcpsReq.Req.Confirmed .fPort  = AppPort;
00360             mcpsReq.Req.Confirmed .fBuffer  = AppData;
00361             mcpsReq.Req.Confirmed .fBufferSize  = AppDataSize;
00362             mcpsReq.Req.Confirmed .NbTrials  = 8;
00363             mcpsReq.Req.Confirmed .Datarate  = LORAWAN_DEFAULT_DATARATE;
00364         }
00365     }
00366 
00367     if( LoRaMacMcpsRequest( &mcpsReq ) == LORAMAC_STATUS_OK  )
00368     {
00369         return false;
00370     }
00371     return true;
00372 }
00373 
00374 /*!
00375  * \brief Function executed on TxNextPacket Timeout event
00376  */
00377 static void OnTxNextPacketTimerEvent( void )
00378 {
00379     MibRequestConfirm_t  mibReq;
00380     LoRaMacStatus_t  status;
00381 
00382     TimerStop( &TxNextPacketTimer );
00383 
00384     mibReq.Type  = MIB_NETWORK_JOINED ;
00385     status = LoRaMacMibGetRequestConfirm( &mibReq );
00386 
00387     if( status == LORAMAC_STATUS_OK  )
00388     {
00389         if( mibReq.Param .IsNetworkJoined  == true )
00390         {
00391             DeviceState = DEVICE_STATE_SEND;
00392             NextTx = true;
00393         }
00394         else
00395         {
00396             DeviceState = DEVICE_STATE_JOIN;
00397         }
00398     }
00399 }
00400 
00401 
00402 /*!
00403  * \brief   MCPS-Confirm event function
00404  *
00405  * \param   [IN] mcpsConfirm - Pointer to the confirm structure,
00406  *               containing confirm attributes.
00407  */
00408 static void McpsConfirm( McpsConfirm_t  *mcpsConfirm )
00409 {
00410     if( mcpsConfirm->Status  == LORAMAC_EVENT_INFO_STATUS_OK  )
00411     {
00412         switch( mcpsConfirm->McpsRequest  )
00413         {
00414             case MCPS_UNCONFIRMED :
00415             {
00416                 // Check Datarate
00417                 // Check TxPower
00418                 break;
00419             }
00420             case MCPS_CONFIRMED :
00421             {
00422                 // Check Datarate
00423                 // Check TxPower
00424                 // Check AckReceived
00425                 // Check NbTrials
00426                 LoRaMacUplinkStatus.Acked = mcpsConfirm->AckReceived ;
00427                 break;
00428             }
00429             case MCPS_PROPRIETARY :
00430             {
00431                 break;
00432             }
00433             default:
00434                 break;
00435         }
00436         LoRaMacUplinkStatus.Datarate = mcpsConfirm->Datarate ;
00437         LoRaMacUplinkStatus.UplinkCounter = mcpsConfirm->UpLinkCounter ;
00438 
00439         UplinkStatusUpdated = true;
00440     }
00441     NextTx = true;
00442 }
00443 
00444 /*!
00445  * \brief   MCPS-Indication event function
00446  *
00447  * \param   [IN] mcpsIndication - Pointer to the indication structure,
00448  *               containing indication attributes.
00449  */
00450 static void McpsIndication( McpsIndication_t  *mcpsIndication )
00451 {
00452     if( mcpsIndication->Status  != LORAMAC_EVENT_INFO_STATUS_OK  )
00453     {
00454         return;
00455     }
00456 
00457     switch( mcpsIndication->McpsIndication  )
00458     {
00459         case MCPS_UNCONFIRMED :
00460         {
00461             break;
00462         }
00463         case MCPS_CONFIRMED :
00464         {
00465             break;
00466         }
00467         case MCPS_PROPRIETARY :
00468         {
00469             break;
00470         }
00471         case MCPS_MULTICAST :
00472         {
00473             break;
00474         }
00475         default:
00476             break;
00477     }
00478 
00479     // Check Multicast
00480     // Check Port
00481     // Check Datarate
00482     // Check FramePending
00483     // Check Buffer
00484     // Check BufferSize
00485     // Check Rssi
00486     // Check Snr
00487     // Check RxSlot
00488     LoRaMacDownlinkStatus.Rssi = mcpsIndication->Rssi ;
00489     if( mcpsIndication->Snr  & 0x80 ) // The SNR sign bit is 1
00490     {
00491         // Invert and divide by 4
00492         LoRaMacDownlinkStatus.Snr = ( ( ~mcpsIndication->Snr  + 1 ) & 0xFF ) >> 2;
00493         LoRaMacDownlinkStatus.Snr = -LoRaMacDownlinkStatus.Snr;
00494     }
00495     else
00496     {
00497         // Divide by 4
00498         LoRaMacDownlinkStatus.Snr = ( mcpsIndication->Snr  & 0xFF ) >> 2;
00499     }
00500     LoRaMacDownlinkStatus.DownlinkCounter++;
00501     LoRaMacDownlinkStatus.RxData = mcpsIndication->RxData ;
00502     LoRaMacDownlinkStatus.Port = mcpsIndication->Port ;
00503     LoRaMacDownlinkStatus.Buffer = mcpsIndication->Buffer ;
00504     LoRaMacDownlinkStatus.BufferSize = mcpsIndication->BufferSize ;
00505 
00506     if( ComplianceTest.Running == true )
00507     {
00508         ComplianceTest.DownLinkCounter++;
00509     }
00510 
00511     if( mcpsIndication->RxData  == true )
00512     {
00513         switch( mcpsIndication->Port  )
00514         {
00515         case 1: // The application LED can be controlled on port 1 or 2
00516         case 2:
00517             break;
00518         case 224:
00519             if( ComplianceTest.Running == false )
00520             {
00521                 // Check compliance test enable command (i)
00522                 if( ( mcpsIndication->BufferSize  == 4 ) &&
00523                     ( mcpsIndication->Buffer [0] == 0x01 ) &&
00524                     ( mcpsIndication->Buffer [1] == 0x01 ) &&
00525                     ( mcpsIndication->Buffer [2] == 0x01 ) &&
00526                     ( mcpsIndication->Buffer [3] == 0x01 ) )
00527                 {
00528                     IsTxConfirmed = false;
00529                     AppPort = 224;
00530                     AppDataSize = 2;
00531                     ComplianceTest.DownLinkCounter = 0;
00532                     ComplianceTest.LinkCheck = false;
00533                     ComplianceTest.DemodMargin = 0;
00534                     ComplianceTest.NbGateways = 0;
00535                     ComplianceTest.Running = true;
00536                     ComplianceTest.State = 1;
00537 
00538                     MibRequestConfirm_t  mibReq;
00539                     mibReq.Type  = MIB_ADR ;
00540                     mibReq.Param .AdrEnable  = true;
00541                     LoRaMacMibSetRequestConfirm( &mibReq );
00542                     
00543                   // Limiting to just 2nd subband of 8 channels
00544                 static uint16_t GatewayChannelsMask[] = {0xFF00, 0x0000, 0x0000, 0x0000, 0x0002, 0x0000};
00545                 mibReq.Type  = MIB_CHANNELS_DEFAULT_MASK ;
00546                 mibReq.Param .ChannelsDefaultMask  = GatewayChannelsMask;
00547                 LoRaMacMibSetRequestConfirm( &mibReq );
00548  
00549                 mibReq.Type  = MIB_CHANNELS_MASK ;
00550                 mibReq.Param .ChannelsMask  = GatewayChannelsMask;
00551                 LoRaMacMibSetRequestConfirm( &mibReq );
00552                     
00553                     
00554 
00555 #if defined( USE_BAND_868 )
00556                     LoRaMacTestSetDutyCycleOn( false );
00557 #endif
00558                 }
00559             }
00560             else
00561             {
00562                 ComplianceTest.State = mcpsIndication->Buffer [0];
00563                 switch( ComplianceTest.State )
00564                 {
00565                 case 0: // Check compliance test disable command (ii)
00566                     IsTxConfirmed = LORAWAN_CONFIRMED_MSG_ON;
00567                     AppPort = LORAWAN_APP_PORT;
00568                     AppDataSize = LORAWAN_APP_DATA_SIZE;
00569                     ComplianceTest.DownLinkCounter = 0;
00570                     ComplianceTest.Running = false;
00571 
00572                     MibRequestConfirm_t  mibReq;
00573                     mibReq.Type  = MIB_ADR ;
00574                     mibReq.Param .AdrEnable  = LORAWAN_ADR_ON;
00575                     LoRaMacMibSetRequestConfirm( &mibReq );
00576 #if defined( USE_BAND_868 )
00577                     LoRaMacTestSetDutyCycleOn( LORAWAN_DUTYCYCLE_ON );
00578 #endif
00579                     break;
00580                 case 1: // (iii, iv)
00581                     AppDataSize = 2;
00582                     break;
00583                 case 2: // Enable confirmed messages (v)
00584                     IsTxConfirmed = true;
00585                     ComplianceTest.State = 1;
00586                     break;
00587                 case 3:  // Disable confirmed messages (vi)
00588                     IsTxConfirmed = false;
00589                     ComplianceTest.State = 1;
00590                     break;
00591                 case 4: // (vii)
00592                     AppDataSize = mcpsIndication->BufferSize ;
00593 
00594                     AppData[0] = 4;
00595                     for( uint8_t i = 1; i < AppDataSize; i++ )
00596                     {
00597                         AppData[i] = mcpsIndication->Buffer [i] + 1;
00598                     }
00599                     break;
00600                 case 5: // (viii)
00601                     {
00602                         MlmeReq_t  mlmeReq;
00603                         mlmeReq.Type  = MLME_LINK_CHECK ;
00604                         LoRaMacMlmeRequest( &mlmeReq );
00605                     }
00606                     break;
00607                 case 6: // (ix)
00608                     {
00609                         MlmeReq_t  mlmeReq;
00610 
00611                         // Disable TestMode and revert back to normal operation
00612                         IsTxConfirmed = LORAWAN_CONFIRMED_MSG_ON;
00613                         AppPort = LORAWAN_APP_PORT;
00614                         AppDataSize = LORAWAN_APP_DATA_SIZE;
00615                         ComplianceTest.DownLinkCounter = 0;
00616                         ComplianceTest.Running = false;
00617 
00618                         MibRequestConfirm_t  mibReq;
00619                         mibReq.Type  = MIB_ADR ;
00620                         mibReq.Param .AdrEnable  = LORAWAN_ADR_ON;
00621                         LoRaMacMibSetRequestConfirm( &mibReq );
00622 #if defined( USE_BAND_868 )
00623                         LoRaMacTestSetDutyCycleOn( LORAWAN_DUTYCYCLE_ON );
00624 #endif
00625 
00626                         mlmeReq.Type  = MLME_JOIN ;
00627 
00628                         mlmeReq.Req.Join .DevEui  = DevEui;
00629                         mlmeReq.Req.Join .AppEui  = AppEui;
00630                         mlmeReq.Req.Join .AppKey  = AppKey;
00631                         mlmeReq.Req.Join .NbTrials  = 3;
00632 
00633                         LoRaMacMlmeRequest( &mlmeReq );
00634                         DeviceState = DEVICE_STATE_SLEEP;
00635                     }
00636                     break;
00637                 case 7: // (x)
00638                     {
00639                         if( mcpsIndication->BufferSize  == 3 )
00640                         {
00641                             MlmeReq_t  mlmeReq;
00642                             mlmeReq.Type  = MLME_TXCW ;
00643                             mlmeReq.Req.TxCw .Timeout  = ( uint16_t )( ( mcpsIndication->Buffer [1] << 8 ) | mcpsIndication->Buffer [2] );
00644                             LoRaMacMlmeRequest( &mlmeReq );
00645                         }
00646                         else if( mcpsIndication->BufferSize  == 7 )
00647                         {
00648                             MlmeReq_t  mlmeReq;
00649                             mlmeReq.Type  = MLME_TXCW_1 ;
00650                             mlmeReq.Req.TxCw .Timeout  = ( uint16_t )( ( mcpsIndication->Buffer [1] << 8 ) | mcpsIndication->Buffer [2] );
00651                             mlmeReq.Req.TxCw .Frequency  = ( uint32_t )( ( mcpsIndication->Buffer [3] << 16 ) | ( mcpsIndication->Buffer [4] << 8 ) | mcpsIndication->Buffer [5] ) * 100;
00652                             mlmeReq.Req.TxCw .Power  = mcpsIndication->Buffer [6];
00653                             LoRaMacMlmeRequest( &mlmeReq );
00654                         }
00655                         ComplianceTest.State = 1;
00656                     }
00657                     break;
00658                 default:
00659                     break;
00660                 }
00661             }
00662             break;
00663         default:
00664             break;
00665         }
00666     }
00667 
00668     DownlinkStatusUpdated = true;
00669 }
00670 
00671 /*!
00672  * \brief   MLME-Confirm event function
00673  *
00674  * \param   [IN] mlmeConfirm - Pointer to the confirm structure,
00675  *               containing confirm attributes.
00676  */
00677 static void MlmeConfirm( MlmeConfirm_t  *mlmeConfirm )
00678 {
00679     switch( mlmeConfirm->MlmeRequest  )
00680     {
00681         case MLME_JOIN :
00682         {
00683             if( mlmeConfirm->Status  == LORAMAC_EVENT_INFO_STATUS_OK  )
00684             {
00685                 // Status is OK, node has joined the network
00686                 IsNetworkJoinedStatusUpdate = true;
00687                 DeviceState = DEVICE_STATE_SEND;
00688             }
00689             else
00690             {
00691                 // Join was not successful. Try to join again
00692                 DeviceState = DEVICE_STATE_JOIN;
00693             }
00694             break;
00695         }
00696         case MLME_LINK_CHECK :
00697         {
00698             if( mlmeConfirm->Status  == LORAMAC_EVENT_INFO_STATUS_OK  )
00699             {
00700                 // Check DemodMargin
00701                 // Check NbGateways
00702                 if( ComplianceTest.Running == true )
00703                 {
00704                     ComplianceTest.LinkCheck = true;
00705                     ComplianceTest.DemodMargin = mlmeConfirm->DemodMargin ;
00706                     ComplianceTest.NbGateways = mlmeConfirm->NbGateways ;
00707                 }
00708             }
00709             break;
00710         }
00711         default:
00712             break;
00713     }
00714     NextTx = true;
00715     UplinkStatusUpdated = true;
00716 }
00717 
00718 void flash_builtin() {
00719     myled = 1;   // turn the LED on (HIGH is the voltage level)
00720     wait(2);                       // wait for 2 second
00721     myled = 0;    // turn the LED off by making the voltage LOW
00722     wait(1);    // wait for 1 second
00723 }
00724 
00725 /**
00726  * Main application entry point.
00727  */
00728 Serial pc(SERIAL_TX, SERIAL_RX,115200);
00729 
00730 int sysclk_hse_pll_patch(void)
00731 {
00732   RCC_ClkInitTypeDef RCC_ClkInitStruct;
00733   RCC_OscInitTypeDef RCC_OscInitStruct;
00734 
00735     HAL_StatusTypeDef status;
00736 
00737 #if defined(TARGET_NUCLEO_F411RE)
00738     /* Start HSE first */
00739     RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
00740     RCC_OscInitStruct.HSEState       = RCC_HSE_ON; 
00741     RCC_OscInitStruct.PLL.PLLState   = RCC_PLL_NONE;
00742     
00743     
00744     
00745 
00746     
00747     
00748     
00749 #elif defined(TARGET_NUCLEO_L073RZ) || defined(TARGET_NUCLEO_L152RE)
00750     /* To clear HSE_BYPASS, we need to stop HSE first */
00751     RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
00752     RCC_OscInitStruct.HSEState       = RCC_HSE_OFF;
00753     RCC_OscInitStruct.PLL.PLLState   = RCC_PLL_NONE;
00754     
00755     
00756     
00757 #else
00758 #error "!! Target not supported.";
00759 #endif
00760     status = HAL_RCC_OscConfig(&RCC_OscInitStruct);
00761     if (status != HAL_OK) {
00762         return (-1); // FAIL
00763     }
00764 
00765     /* To disable PLL, change SYSCLK to HSI without PLL */
00766     RCC_ClkInitStruct.ClockType      = RCC_CLOCKTYPE_SYSCLK;
00767     RCC_ClkInitStruct.SYSCLKSource   = RCC_SYSCLKSOURCE_HSI; // 16 MHz
00768 #if defined(TARGET_NUCLEO_L073RZ) || defined(TARGET_NUCLEO_L152RE)
00769     status = HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_1);
00770 #elif defined(TARGET_NUCLEO_F411RE)
00771     status = HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_3);
00772 #else
00773 #error "!! Target not supported.";
00774 #endif
00775     if (status != HAL_OK) {
00776         return (-2); // FAIL
00777     }
00778     
00779     /* Disable PLL */
00780     RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_NONE;
00781     RCC_OscInitStruct.PLL.PLLState   = RCC_PLL_OFF;
00782     status = HAL_RCC_OscConfig(&RCC_OscInitStruct);
00783     if (status != HAL_OK) {
00784         return (-3); // FAIL
00785     }
00786 
00787     /* Enable HSE and activate PLL with HSE as source */
00788     RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
00789     RCC_OscInitStruct.HSEState       = RCC_HSE_ON; // External 8 MHz xtal on OSC_IN/OSC_OUT
00790     RCC_OscInitStruct.PLL.PLLState   = RCC_PLL_ON;
00791     RCC_OscInitStruct.PLL.PLLSource  = RCC_PLLSOURCE_HSE;
00792 #if defined(TARGET_NUCLEO_L073RZ) || defined(TARGET_NUCLEO_L152RE)
00793     RCC_OscInitStruct.PLL.PLLMUL     = RCC_PLL_MUL12;
00794     RCC_OscInitStruct.PLL.PLLDIV     = RCC_PLL_DIV3;
00795 #elif defined(TARGET_NUCLEO_F411RE)
00796     RCC_OscInitStruct.PLL.PLLM       = 4; /* config for 8MHz */
00797     RCC_OscInitStruct.PLL.PLLN       = 200;
00798     RCC_OscInitStruct.PLL.PLLP       = RCC_PLLP_DIV4;
00799     RCC_OscInitStruct.PLL.PLLQ       = 8;
00800 #else
00801 #error "!! Target not supported.";
00802 #endif
00803     status = HAL_RCC_OscConfig(&RCC_OscInitStruct);
00804     if (status != HAL_OK) {
00805         return (-4); // FAIL
00806     }
00807 
00808     /* Select PLL as system clock source and configure the PCLK1 and PCLK2 clocks dividers */
00809     RCC_ClkInitStruct.ClockType      = (RCC_CLOCKTYPE_SYSCLK | RCC_CLOCKTYPE_PCLK1 | RCC_CLOCKTYPE_PCLK2);
00810     RCC_ClkInitStruct.SYSCLKSource   = RCC_SYSCLKSOURCE_PLLCLK;
00811     RCC_ClkInitStruct.AHBCLKDivider  = RCC_SYSCLK_DIV1;          
00812     RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;
00813 #if defined(TARGET_NUCLEO_L073RZ) || defined(TARGET_NUCLEO_L152RE)
00814     RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1;
00815     status = HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_1);
00816 #elif defined(TARGET_NUCLEO_F411RE)
00817     RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV2;
00818     status = HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_3);
00819 #else
00820 #error "!! Target not supported.";
00821 #endif
00822     if (status != HAL_OK) {
00823         return (-5); // FAIL
00824     }
00825     
00826     /* Turn off unused clocks */
00827 #if defined(TARGET_NUCLEO_L073RZ) || defined(TARGET_NUCLEO_L152RE)
00828     RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI|RCC_OSCILLATORTYPE_MSI;
00829     RCC_OscInitStruct.MSIState       = RCC_MSI_OFF;
00830 #elif defined(TARGET_NUCLEO_F411RE)
00831     RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI;
00832 #else
00833 #error "!! Target not supported.";
00834 #endif
00835     RCC_OscInitStruct.HSIState       = RCC_HSI_OFF;
00836     RCC_OscInitStruct.PLL.PLLState   = RCC_PLL_NONE;
00837     status = HAL_RCC_OscConfig(&RCC_OscInitStruct);
00838     if (status != HAL_OK) {
00839         return (-6); // FAIL
00840     }
00841     
00842     return 0; // OK
00843 }
00844 
00845 void ConfigureSystemClockForHSE_PLL(void)
00846 {
00847     int retVal = 0;
00848 
00849     RCC_OscInitTypeDef RCC_OscInitStruct;
00850     RCC_ClkInitTypeDef RCC_ClkInitStruct;
00851     uint32_t pFLatency;
00852     
00853     HAL_RCC_GetOscConfig( &RCC_OscInitStruct);
00854     HAL_RCC_GetClockConfig( &RCC_ClkInitStruct, &pFLatency);
00855 
00856     printf("\r\n==> mbed-os-rev=%d.%d.%d lib-rev=%d AppBuild=%s %s <==\r\n", \
00857             MBED_MAJOR_VERSION, MBED_MINOR_VERSION,MBED_PATCH_VERSION,\
00858             MBED_LIBRARY_VERSION, __TIME__, __DATE__);
00859 
00860     printf(">>>>  Current  <<<< \r\n");
00861     printf("> SysClock= %d Hz \r\n",SystemCoreClock);
00862 #if defined(TARGET_NUCLEO_L073RZ) || defined(TARGET_NUCLEO_L152RE)
00863     printf("> CR=%08X CFGR=%08X CSR=%08X ICSCR=%08X \r\n",\
00864         RCC->CR, RCC->CFGR, RCC->CSR, RCC->ICSCR);
00865     
00866     printf("> PLLSRC=%s PLLMUL=%u PLLDIV=%u \r\n",\
00867         ((RCC->CFGR & (1UL<<16))?"HSE":"HSI"),\
00868         RCC_OscInitStruct.PLL.PLLMUL, RCC_OscInitStruct.PLL.PLLDIV);
00869         
00870     printf("> AHB=%d APB1=%d APB2=%d Latency=%u \r\n",\
00871         RCC_ClkInitStruct.AHBCLKDivider, RCC_ClkInitStruct.APB1CLKDivider,\
00872         RCC_ClkInitStruct.APB2CLKDivider,pFLatency);
00873     wait(0.1); // wait for printf to finish
00874     
00875 #elif defined(TARGET_NUCLEO_F411RE)
00876     printf("> CR=%08X CFGR=%08X CSR=%08X PLLCFGR=%08X \r\n",\
00877         RCC->CR, RCC->CFGR, RCC->CSR, RCC->PLLCFGR);
00878     
00879     printf("> PLLSRC=%s PLLM=%d PLLN=%d PLLP=%d PLLQ=%d \r\n",
00880         ((RCC->PLLCFGR & (1UL<<22))?"HSE":"HSI"),\
00881         RCC_OscInitStruct.PLL.PLLM, RCC_OscInitStruct.PLL.PLLN,\
00882         RCC_OscInitStruct.PLL.PLLP, RCC_OscInitStruct.PLL.PLLQ);
00883         
00884     printf("> AHB=%d APB1=%d APB2=%d Latency=%u \r\n",\
00885         RCC_ClkInitStruct.AHBCLKDivider, RCC_ClkInitStruct.APB1CLKDivider,\
00886         RCC_ClkInitStruct.APB2CLKDivider,pFLatency);
00887     wait(0.1); // wait for print to finish
00888     
00889 #else
00890 #error "!! Target not supported.";
00891 #endif
00892     
00893     /* setup hse */
00894     retVal = sysclk_hse_pll_patch();
00895     
00896     printf(">>>>  NEW  <<<< \r\n");
00897     printf("> SysClock= %d Hz, retVal= %d \r\n",SystemCoreClock, retVal);
00898 #if defined(TARGET_NUCLEO_L073RZ) || defined(TARGET_NUCLEO_L152RE)
00899     printf("> CR=%08X CFGR=%08X CSR=%08X ICSCR=%08X \r\n",\
00900         RCC->CR, RCC->CFGR, RCC->CSR, RCC->ICSCR);
00901     
00902     printf("> PLLSRC=%s PLLMUL=%u PLLDIV=%u \r\n",\
00903         ((RCC->CFGR & (1UL<<16))?"HSE":"HSI"),\
00904         RCC_OscInitStruct.PLL.PLLMUL, RCC_OscInitStruct.PLL.PLLDIV);
00905     
00906     printf("> AHB=%d APB1=%d APB2=%d Latency=%u \r\n",\
00907         RCC_ClkInitStruct.AHBCLKDivider, RCC_ClkInitStruct.APB1CLKDivider,\
00908         RCC_ClkInitStruct.APB2CLKDivider, pFLatency);
00909 
00910 #elif defined(TARGET_NUCLEO_F411RE)
00911     printf("> CR=%08X CFGR=%08X CSR=%08X PLLCFGR=%08X \r\n",\
00912         RCC->CR, RCC->CFGR, RCC->CSR, RCC->PLLCFGR);
00913     
00914     printf("> PLLSRC=%s PLLM=%d PLLN=%d PLLP=%d PLLQ=%d \r\n",\
00915         ((RCC->PLLCFGR & (1UL<<22))?"HSE":"HSI"),\
00916         RCC_OscInitStruct.PLL.PLLM, RCC_OscInitStruct.PLL.PLLN,\
00917         RCC_OscInitStruct.PLL.PLLP, RCC_OscInitStruct.PLL.PLLQ);
00918     
00919     printf("> AHB=%d APB1=%d APB2=%d Latency=%u \r\n",\
00920         RCC_ClkInitStruct.AHBCLKDivider, RCC_ClkInitStruct.APB1CLKDivider,\
00921         RCC_ClkInitStruct.APB2CLKDivider, pFLatency);
00922 
00923 #else
00924 #error "!! Target not supported.";
00925 #endif
00926     
00927     if(retVal < 0)
00928     {        
00929         /* indicate error i.e failed to set HSE_PLL */
00930         while(1)
00931         {
00932             myled = 1;
00933             wait(0.2);
00934             myled = 0;
00935             wait(0.5);
00936         }
00937     }
00938 }
00939 
00940 int main( void )
00941 {
00942     ConfigureSystemClockForHSE_PLL();
00943    
00944     flash_builtin();
00945     flash_builtin();
00946     flash_builtin();
00947     flash_builtin();
00948     
00949     LoRaMacPrimitives_t  LoRaMacPrimitives;
00950     LoRaMacCallback_t LoRaMacCallbacks;
00951     MibRequestConfirm_t  mibReq;
00952 
00953     BoardInit( );
00954     SerialDisplayInit( );
00955 
00956     SerialDisplayUpdateEui( 5, DevEui );
00957     SerialDisplayUpdateEui( 6, AppEui );
00958     SerialDisplayUpdateKey( 7, AppKey );
00959 
00960 #if( OVER_THE_AIR_ACTIVATION == 0 )
00961     SerialDisplayUpdateNwkId( LORAWAN_NETWORK_ID );
00962     SerialDisplayUpdateDevAddr( DevAddr );
00963     SerialDisplayUpdateKey( 12, NwkSKey );
00964     SerialDisplayUpdateKey( 13, AppSKey );
00965 #endif
00966 
00967     DeviceState = DEVICE_STATE_INIT;
00968 
00969     while( 1 )
00970     {
00971         SerialRxProcess( );
00972         flash_builtin();
00973         if( IsNetworkJoinedStatusUpdate == true )
00974         {
00975             IsNetworkJoinedStatusUpdate = false;
00976             mibReq.Type  = MIB_NETWORK_JOINED ;
00977             LoRaMacMibGetRequestConfirm( &mibReq );
00978             SerialDisplayUpdateNetworkIsJoined( mibReq.Param .IsNetworkJoined  );
00979         }
00980         if( UplinkStatusUpdated == true )
00981         {
00982             UplinkStatusUpdated = false;
00983             SerialDisplayUpdateUplink( LoRaMacUplinkStatus.Acked, LoRaMacUplinkStatus.Datarate, LoRaMacUplinkStatus.UplinkCounter, LoRaMacUplinkStatus.Port, LoRaMacUplinkStatus.Buffer, LoRaMacUplinkStatus.BufferSize );
00984         }
00985         if( DownlinkStatusUpdated == true )
00986         {
00987             DownlinkStatusUpdated = false;
00988             SerialDisplayUpdateDownlink( LoRaMacDownlinkStatus.RxData, LoRaMacDownlinkStatus.Rssi, LoRaMacDownlinkStatus.Snr, LoRaMacDownlinkStatus.DownlinkCounter, LoRaMacDownlinkStatus.Port, LoRaMacDownlinkStatus.Buffer, LoRaMacDownlinkStatus.BufferSize );
00989         }
00990         
00991         switch( DeviceState )
00992         {
00993             case DEVICE_STATE_INIT:
00994             {
00995                 LoRaMacPrimitives.MacMcpsConfirm = McpsConfirm;
00996                 LoRaMacPrimitives.MacMcpsIndication = McpsIndication;
00997                 LoRaMacPrimitives.MacMlmeConfirm = MlmeConfirm;
00998                 LoRaMacCallbacks.GetBatteryLevel = BoardGetBatteryLevel;
00999                 LoRaMacInitialization( &LoRaMacPrimitives, &LoRaMacCallbacks );
01000 
01001                 TimerInit( &TxNextPacketTimer, OnTxNextPacketTimerEvent );
01002 
01003                 mibReq.Type  = MIB_ADR ;
01004                 mibReq.Param .AdrEnable  = LORAWAN_ADR_ON;
01005                 LoRaMacMibSetRequestConfirm( &mibReq );
01006 
01007                 mibReq.Type  = MIB_PUBLIC_NETWORK ;
01008                 mibReq.Param .EnablePublicNetwork  = LORAWAN_PUBLIC_NETWORK;
01009                 LoRaMacMibSetRequestConfirm( &mibReq );
01010                 
01011                 
01012              // Limiting to just 2nd subband of 8 channels
01013                 static uint16_t GatewayChannelsMask[] = {0xFF00, 0x0000, 0x0000, 0x0000, 0x0002, 0x0000};
01014                 mibReq.Type  = MIB_CHANNELS_DEFAULT_MASK ;
01015                 mibReq.Param .ChannelsDefaultMask  = GatewayChannelsMask;
01016                 LoRaMacMibSetRequestConfirm( &mibReq );
01017  
01018                 mibReq.Type  = MIB_CHANNELS_MASK ;
01019                 mibReq.Param .ChannelsMask  = GatewayChannelsMask;
01020                 LoRaMacMibSetRequestConfirm( &mibReq );
01021                 
01022                 
01023                 
01024 
01025 #if defined( USE_BAND_868 )
01026                 LoRaMacTestSetDutyCycleOn( LORAWAN_DUTYCYCLE_ON );
01027                 SerialDisplayUpdateDutyCycle( LORAWAN_DUTYCYCLE_ON );
01028 
01029 #if( USE_SEMTECH_DEFAULT_CHANNEL_LINEUP == 1 )
01030                 LoRaMacChannelAdd( 3, ( ChannelParams_t  )LC4 );
01031                 LoRaMacChannelAdd( 4, ( ChannelParams_t  )LC5 );
01032                 LoRaMacChannelAdd( 5, ( ChannelParams_t  )LC6 );
01033                 LoRaMacChannelAdd( 6, ( ChannelParams_t  )LC7 );
01034                 LoRaMacChannelAdd( 7, ( ChannelParams_t  )LC8 );
01035                 LoRaMacChannelAdd( 8, ( ChannelParams_t  )LC9 );
01036                 LoRaMacChannelAdd( 9, ( ChannelParams_t  )LC10 );
01037 
01038                 mibReq.Type  = MIB_RX2_DEFAULT_CHANNEL ;
01039                 mibReq.Param .Rx2DefaultChannel  = ( Rx2ChannelParams_t  ){ 869525000, DR_3 };
01040                 LoRaMacMibSetRequestConfirm( &mibReq );
01041 
01042                 mibReq.Type  = MIB_RX2_CHANNEL ;
01043                 mibReq.Param .Rx2Channel  = ( Rx2ChannelParams_t  ){ 869525000, DR_3 };
01044                 LoRaMacMibSetRequestConfirm( &mibReq );
01045 #endif
01046 
01047 #endif
01048                 SerialDisplayUpdateActivationMode( OVER_THE_AIR_ACTIVATION );
01049                 SerialDisplayUpdateAdr( LORAWAN_ADR_ON );
01050                 SerialDisplayUpdatePublicNetwork( LORAWAN_PUBLIC_NETWORK );
01051 
01052                 LoRaMacDownlinkStatus.DownlinkCounter = 0;
01053 
01054                 DeviceState = DEVICE_STATE_JOIN;
01055                 break;
01056             }
01057             case DEVICE_STATE_JOIN:
01058             {
01059 #if( OVER_THE_AIR_ACTIVATION != 0 )
01060                 MlmeReq_t  mlmeReq;
01061 
01062                 mlmeReq.Type  = MLME_JOIN ;
01063 
01064                 mlmeReq.Req.Join .DevEui  = DevEui;
01065                 mlmeReq.Req.Join .AppEui  = AppEui;
01066                 mlmeReq.Req.Join .AppKey  = AppKey;
01067 
01068                 if( NextTx == true )
01069                 {
01070                     LoRaMacMlmeRequest( &mlmeReq );
01071                 }
01072                 DeviceState = DEVICE_STATE_SLEEP;
01073 #else
01074                 mibReq.Type  = MIB_NET_ID ;
01075                 mibReq.Param .NetID  = LORAWAN_NETWORK_ID;
01076                 LoRaMacMibSetRequestConfirm( &mibReq );
01077 
01078                 mibReq.Type  = MIB_DEV_ADDR ;
01079                 mibReq.Param .DevAddr  = DevAddr;
01080                 LoRaMacMibSetRequestConfirm( &mibReq );
01081 
01082                 mibReq.Type  = MIB_NWK_SKEY ;
01083                 mibReq.Param .NwkSKey  = NwkSKey;
01084                 LoRaMacMibSetRequestConfirm( &mibReq );
01085 
01086                 mibReq.Type  = MIB_APP_SKEY ;
01087                 mibReq.Param .AppSKey  = AppSKey;
01088                 LoRaMacMibSetRequestConfirm( &mibReq );
01089 
01090                 mibReq.Type  = MIB_NETWORK_JOINED ;
01091                 mibReq.Param .IsNetworkJoined  = true;
01092                 LoRaMacMibSetRequestConfirm( &mibReq );
01093 
01094                 DeviceState = DEVICE_STATE_SEND;
01095 #endif
01096                 IsNetworkJoinedStatusUpdate = true;
01097                 break;
01098             }
01099             case DEVICE_STATE_SEND:
01100             {
01101                 if( NextTx == true )
01102                 {
01103                     SerialDisplayUpdateUplinkAcked( false );
01104                     SerialDisplayUpdateDonwlinkRxData( false );
01105                     PrepareTxFrame( AppPort );
01106 
01107                     NextTx = SendFrame( );
01108                 }
01109                 if( ComplianceTest.Running == true )
01110                 {
01111                     // Schedule next packet transmission
01112                     TxDutyCycleTime = 5000; // 5000 ms
01113                 }
01114                 else
01115                 {
01116                     // Schedule next packet transmission
01117                     TxDutyCycleTime = APP_TX_DUTYCYCLE + randr( -APP_TX_DUTYCYCLE_RND, APP_TX_DUTYCYCLE_RND );
01118                 }
01119                 DeviceState = DEVICE_STATE_CYCLE;
01120                 break;
01121             }
01122             case DEVICE_STATE_CYCLE:
01123             {
01124                 DeviceState = DEVICE_STATE_SLEEP;
01125 
01126                 // Schedule next packet transmission
01127                 TimerSetValue( &TxNextPacketTimer, TxDutyCycleTime );
01128                 TimerStart( &TxNextPacketTimer );
01129                 break;
01130             }
01131             case DEVICE_STATE_SLEEP:
01132             {
01133                 // Wake up through events
01134                 break;
01135             }
01136             default:
01137             {
01138                 DeviceState = DEVICE_STATE_INIT;
01139                 break;
01140             }
01141         }
01142     }
01143 }