Semtech stack for ELMO - ver. 4.1.0.
Fork of LoRaWAN_Semtech_stack_v4.1 by
Diff: main.cpp
- Revision:
- 1:2be292bd43f9
- Parent:
- 0:c58229885f95
- Child:
- 3:73c2fa59588c
diff -r c58229885f95 -r 2be292bd43f9 main.cpp --- a/main.cpp Wed Dec 16 14:25:16 2015 +0000 +++ b/main.cpp Tue Mar 15 23:27:24 2016 +0000 @@ -1,34 +1,28 @@ -/* - -Description: MBED LoRaWAN example application - +/* + / _____) _ | | +( (____ _____ ____ _| |_ _____ ____| |__ + \____ \| ___ | (_ _) ___ |/ ___) _ \ + _____) ) ____| | | || |_| ____( (___| | | | +(______/|_____)_|_|_| \__)_____)\____)_| |_| + (C)2013 Semtech +Description: LoRaMac classA device implementation License: Revised BSD License, see LICENSE.TXT file include in the project - -Maintainer: Espotel +Maintainer: Miguel Luis and Gregory Cristian */ -#include "mbed.h" +/*! \file classA/LoRaMote/main.c */ #include <string.h> #include <math.h> -//#include "board.h" - -#include "LoRaMac.h" -#include "utilities.h" +#include "mbed.h" -#define USE_BAND_868 -/*! - * When set to 1 the application uses the Over-the-Air activation procedure - * When set to 0 the application uses the Personalization activation procedure - */ -#define OVER_THE_AIR_ACTIVATION 1 +#include "utilities.h" +#include "LoRaMac.h" +#include "Comissioning.h" -/*! - * Indicates if the end-device is to be connected to a private or public network - */ -#define LORAWAN_PUBLIC_NETWORK true -#if( OVER_THE_AIR_ACTIVATION != 0 ) +DigitalOut Led1(LED1); +DigitalOut Led2(LED2); /*! * Join requests trials duty cycle. @@ -36,65 +30,15 @@ #define OVER_THE_AIR_ACTIVATION_DUTYCYCLE 10000000 // 10 [s] value in us /*! - * Mote device IEEE EUI - * - * \remark must be written as a little endian value (reverse order of normal reading) - * - * \remark In this application the value is automatically generated by calling - * BoardGetUniqueId function + * Defines the application data transmission duty cycle. 5s, value in [us]. */ -#define LORAWAN_DEVICE_EUI { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } - -/*! - * Application IEEE EUI - * - * \remark must be written as a little endian value (reverse order of normal reading) - */ -//#define LORAWAN_APPLICATION_EUI { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77 } -#define LORAWAN_APPLICATION_EUI { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } - -/*! - * AES encryption/decryption cipher application key - */ - -#define LORAWAN_APPLICATION_KEY { 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF, 0x00 } -//#define LORAWAN_APPLICATION_KEY { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } - -#else +#define APP_TX_DUTYCYCLE 5000000 /*! - * Current network ID - */ -#define LORAWAN_NETWORK_ID ( uint32_t )0 - -/*! - * Device address on the network - * - * \remark must be written as a big endian value (normal reading order) - * - * \remark In this application the value is automatically generated using - * a pseudo random generator seeded with a value derived from - * BoardUniqueId value + * Defines a random delay for application data transmission duty cycle. 1s, + * value in [us]. */ -#define LORAWAN_DEVICE_ADDRESS ( uint32_t )0x00000000 - -/*! - * AES encryption/decryption cipher network session key - */ -#define LORAWAN_NWKSKEY { 0x2B, 0x7E, 0x15, 0x16, 0x28, 0xAE, 0xD2, 0xA6, 0xAB, 0xF7, 0x15, 0x88, 0x09, 0xCF, 0x4F, 0x3C } - -/*! - * AES encryption/decryption cipher application session key - */ -#define LORAWAN_APPSKEY { 0x2B, 0x7E, 0x15, 0x16, 0x28, 0xAE, 0xD2, 0xA6, 0xAB, 0xF7, 0x15, 0x88, 0x09, 0xCF, 0x4F, 0x3C } - -#endif - -/*! - * Defines the application data transmission duty cycle - */ -#define APP_TX_DUTYCYCLE 5000000 // 5 [s] value in us -#define APP_TX_DUTYCYCLE_RND 1000000 // 1 [s] value in us +#define APP_TX_DUTYCYCLE_RND 1000000 /*! * LoRaWAN confirmed messages @@ -102,19 +46,37 @@ #define LORAWAN_CONFIRMED_MSG_ON false /*! - * LoRaWAN Adaptative Data Rate + * LoRaWAN Adaptive Data Rate * * \remark Please note that when ADR is enabled the end-device should be static */ #define LORAWAN_ADR_ON 1 +#if defined( USE_BAND_868 ) + +#include "LoRaMacTest.h" + /*! * LoRaWAN ETSI duty cycle control enable/disable * * \remark Please note that ETSI mandates duty cycled transmissions. Use only for test purposes */ #define LORAWAN_DUTYCYCLE_ON true -#define LORAWAN_DUTYCYCLE_OFF false + +#define USE_SEMTECH_DEFAULT_CHANNEL_LINEUP 1 + +#if( USE_SEMTECH_DEFAULT_CHANNEL_LINEUP == 1 ) + +#define LC4 { 867100000, { ( ( DR_5 << 4 ) | DR_0 ) }, 0 } +#define LC5 { 867300000, { ( ( DR_5 << 4 ) | DR_0 ) }, 0 } +#define LC6 { 867500000, { ( ( DR_5 << 4 ) | DR_0 ) }, 0 } +#define LC7 { 867700000, { ( ( DR_5 << 4 ) | DR_0 ) }, 0 } +#define LC8 { 867900000, { ( ( DR_5 << 4 ) | DR_0 ) }, 0 } +#define LC9 { 868800000, { ( ( DR_7 << 4 ) | DR_7 ) }, 2 } + +#endif + +#endif /*! * LoRaWAN application port @@ -124,8 +86,16 @@ /*! * User application data buffer size */ +#if defined( USE_BAND_868 ) + #define LORAWAN_APP_DATA_SIZE 16 +#elif defined( USE_BAND_915 ) || defined( USE_BAND_915_HYBRID ) + +#define LORAWAN_APP_DATA_SIZE 11 + +#endif + #if( OVER_THE_AIR_ACTIVATION != 0 ) static uint8_t DevEui[] = LORAWAN_DEVICE_EUI; @@ -145,11 +115,6 @@ #endif /*! - * Indicates if the MAC layer has already joined a network. - */ -static bool IsNetworkJoined = false; - -/*! * Application port */ static uint8_t AppPort = LORAWAN_APP_PORT; @@ -169,7 +134,6 @@ */ static uint8_t AppData[LORAWAN_APP_DATA_MAX_SIZE]; - /*! * Indicates if the node is sending confirmed or unconfirmed messages */ @@ -180,49 +144,62 @@ */ static uint32_t TxDutyCycleTime; +/*! + * Timer to handle the application data transmission duty cycle + */ +static Timeout TxNextPacketTimer; -static void OnTxNextPacketTimerEvent( void ); -static Timeout TxNextPacketTimer;//(OnTxNextPacketTimerEvent, osTimerOnce); - -#if( OVER_THE_AIR_ACTIVATION != 0 ) +/*! + * Specifies the state of the application LED + */ +static bool AppLedStateOn = false; -static void OnJoinReqTimerEvent( void ); /*! - * Defines the join request timer + * Timer to handle the state of LED1 */ -static Timeout JoinReqTimer;//(OnJoinReqTimerEvent, osTimerOnce); +static Timeout Led1Timer; -#endif +/*! + * Timer to handle the state of LED2 + */ +static Timeout Led2Timer; /*! * Indicates if a new packet can be sent */ -static bool TxNextPacket = true; -static bool ScheduleNextTx = false; -static bool DownlinkStatusUpdate = false; - -static bool AppLedStateOn = false; +static bool NextTx = true; -static LoRaMacCallbacks_t LoRaMacCallbacks; -/* -static TimerEvent_t Led1Timer; -volatile bool Led1StateChanged = false; -static TimerEvent_t Led2Timer; -volatile bool Led2StateChanged = false; -static TimerEvent_t Led4Timer; -volatile bool Led4StateChanged = false; - -volatile bool Led3StateChanged = false; -*/ -static bool ComplianceTestOn = false; -static uint8_t ComplianceTestState = 0; -static uint16_t ComplianceTestDownLinkCounter = 0; -static bool ComplianceTestLinkCheck = false; -static uint8_t ComplianceTestDemodMargin = 0; -static uint8_t ComplianceTestNbGateways = 0; +/*! + * Device states + */ +static enum eDevicState +{ + DEVICE_STATE_INIT, + DEVICE_STATE_JOIN, + DEVICE_STATE_SEND, + DEVICE_STATE_CYCLE, + DEVICE_STATE_SLEEP +}DeviceState; /*! - * Prepares the frame buffer to be sent + * LoRaWAN compliance tests support data + */ +struct ComplianceTest_s +{ + bool Running; + uint8_t State; + bool IsTxConfirmed; + uint8_t AppPort; + uint8_t AppDataSize; + uint8_t *AppDataBuffer; + uint16_t DownLinkCounter; + bool LinkCheck; + uint8_t DemodMargin; + uint8_t NbGateways; +}ComplianceTest; + +/*! + * \brief Prepares the payload of the frame */ static void PrepareTxFrame( uint8_t port ) { @@ -230,6 +207,7 @@ { case 2: { +#if defined( USE_BAND_868 ) uint16_t pressure = 0; int16_t altitudeBar = 0; int16_t temperature = 0; @@ -260,109 +238,334 @@ AppData[13] = longitude & 0xFF; AppData[14] = ( altitudeGps >> 8 ) & 0xFF; AppData[15] = altitudeGps & 0xFF; +#elif defined( USE_BAND_915 ) || defined( USE_BAND_915_HYBRID ) + int16_t temperature = 0; + int32_t latitude, longitude = 0; + uint16_t altitudeGps = 0xFFFF; + uint8_t batteryLevel = 0; + + temperature = ( int16_t )( MPL3115ReadTemperature( ) * 100 ); // in °C * 100 + + batteryLevel = BoardGetBatteryLevel( ); // 1 (very low) to 254 (fully charged) + GpsGetLatestGpsPositionBinary( &latitude, &longitude ); + altitudeGps = GpsGetLatestGpsAltitude( ); // in m + + AppData[0] = AppLedStateOn; + AppData[1] = temperature; + AppData[2] = batteryLevel; + AppData[3] = ( latitude >> 16 ) & 0xFF; + AppData[4] = ( latitude >> 8 ) & 0xFF; + AppData[5] = latitude & 0xFF; + AppData[6] = ( longitude >> 16 ) & 0xFF; + AppData[7] = ( longitude >> 8 ) & 0xFF; + AppData[8] = longitude & 0xFF; + AppData[9] = ( altitudeGps >> 8 ) & 0xFF; + AppData[10] = altitudeGps & 0xFF; +#endif } break; case 224: - if( ComplianceTestLinkCheck == true ) + if( ComplianceTest.LinkCheck == true ) { - printf("ComplianceTestLinkCheck\r\n"); - ComplianceTestLinkCheck = false; + ComplianceTest.LinkCheck = false; AppDataSize = 3; AppData[0] = 5; - AppData[1] = ComplianceTestDemodMargin; - AppData[2] = ComplianceTestNbGateways; - ComplianceTestState = 1; + AppData[1] = ComplianceTest.DemodMargin; + AppData[2] = ComplianceTest.NbGateways; + ComplianceTest.State = 1; } else { - if( ComplianceTestState == 1 ) + switch( ComplianceTest.State ) { - printf("Sending downlink COUNTER!!!!\r\n"); + case 4: + ComplianceTest.State = 1; + break; + case 1: AppDataSize = 2; - AppData[0] = ComplianceTestDownLinkCounter >> 8; - AppData[1] = ComplianceTestDownLinkCounter; + AppData[0] = ComplianceTest.DownLinkCounter >> 8; + AppData[1] = ComplianceTest.DownLinkCounter; + break; } } + break; default: break; } } -static void ProcessRxFrame( LoRaMacEventFlags_t *flags, LoRaMacEventInfo_t *info ) +/*! + * \brief Prepares the payload of the frame + * + * \retval [0: frame could be send, 1: error] + */ +static bool SendFrame( void ) { - switch( info->RxPort ) // Check Rx port number + McpsReq_t mcpsReq; + LoRaMacTxInfo_t txInfo; + + if( LoRaMacQueryTxPossible( AppDataSize, &txInfo ) != LORAMAC_STATUS_OK ) + { + // Send empty frame in order to flush MAC commands + mcpsReq.Type = MCPS_UNCONFIRMED; + mcpsReq.Req.Unconfirmed.fBuffer = NULL; + mcpsReq.Req.Unconfirmed.fBufferSize = 0; + mcpsReq.Req.Unconfirmed.Datarate = DR_0; + } + else + { + if( IsTxConfirmed == false ) + { + mcpsReq.Type = MCPS_UNCONFIRMED; + mcpsReq.Req.Unconfirmed.fPort = AppPort; + mcpsReq.Req.Unconfirmed.fBuffer = AppData; + mcpsReq.Req.Unconfirmed.fBufferSize = AppDataSize; + mcpsReq.Req.Unconfirmed.Datarate = DR_0; + } + else + { + mcpsReq.Type = MCPS_CONFIRMED; + mcpsReq.Req.Confirmed.fPort = AppPort; + mcpsReq.Req.Confirmed.fBuffer = AppData; + mcpsReq.Req.Confirmed.fBufferSize = AppDataSize; + mcpsReq.Req.Confirmed.NbTrials = 8; + mcpsReq.Req.Confirmed.Datarate = DR_0; + } + } + + if( LoRaMacMcpsRequest( &mcpsReq ) == LORAMAC_STATUS_OK ) + { + return false; + } + return true; +} + +/*! + * \brief Function executed on TxNextPacket Timeout event + */ +static void OnTxNextPacketTimerEvent( void ) +{ + MibRequestConfirm_t mibReq; + LoRaMacStatus_t status; + + TxNextPacketTimer.detach(); + + mibReq.Type = MIB_NETWORK_JOINED; + status = LoRaMacMibGetRequestConfirm( &mibReq ); + + if( status == LORAMAC_STATUS_OK ) { - case 1: // The application LED can be controlled on port 1 or 2 - case 2: - if( info->RxBufferSize == 1 ) + if( mibReq.Param.IsNetworkJoined == true ) + { + DeviceState = DEVICE_STATE_SEND; + NextTx = true; + } + else + { + DeviceState = DEVICE_STATE_JOIN; + } + } +} + +/*! + * \brief Function executed on Led 1 Timeout event + */ +static void OnLed1TimerEvent( void ) +{ + Led1Timer.detach(); + // Switch LED 1 OFF + Led1 = 1; +} + +/*! + * \brief Function executed on Led 2 Timeout event + */ +static void OnLed2TimerEvent( void ) +{ + Led2Timer.detach(); + // Switch LED 2 OFF + Led2 = 1; +} + +/*! + * \brief MCPS-Confirm event function + * + * \param [IN] McpsConfirm - Pointer to the confirm structure, + * containing confirm attributes. + */ +static void McpsConfirm( McpsConfirm_t *McpsConfirm ) +{ + if( McpsConfirm->Status == LORAMAC_EVENT_INFO_STATUS_OK ) + { + switch( McpsConfirm->McpsRequest ) { - AppLedStateOn = info->RxBuffer[0] & 0x01; - //Led3StateChanged = true; + case MCPS_UNCONFIRMED: + { + // Check Datarate + // Check TxPower + break; + } + case MCPS_CONFIRMED: + { + // Check Datarate + // Check TxPower + // Check AckReceived + // Check NbTrials + break; + } + case MCPS_PROPRIETARY: + { + break; + } + default: + break; } - break; + + // Switch LED 1 ON + Led1 = 0; + Led1Timer.attach_us(OnLed1TimerEvent, 25000); + } + NextTx = true; +} + +/*! + * \brief MCPS-Indication event function + * + * \param [IN] McpsIndication - Pointer to the indication structure, + * containing indication attributes. + */ +static void McpsIndication( McpsIndication_t *McpsIndication ) +{ + if( McpsIndication->Status != LORAMAC_EVENT_INFO_STATUS_OK ) + { + return; + } + + switch( McpsIndication->McpsIndication ) + { + case MCPS_UNCONFIRMED: + { + break; + } + case MCPS_CONFIRMED: + { + break; + } + case MCPS_PROPRIETARY: + { + break; + } + case MCPS_MULTICAST: + { + break; + } + default: + break; + } + + // Check Multicast + // Check Port + // Check Datarate + // Check FramePending + // Check Buffer + // Check BufferSize + // Check Rssi + // Check Snr + // Check RxSlot + + if( ComplianceTest.Running == true ) + { + ComplianceTest.DownLinkCounter++; + } + + if( McpsIndication->RxData == true ) + { + switch( McpsIndication->Port ) + { + case 1: // The application LED can be controlled on port 1 or 2 + case 2: + if( McpsIndication->BufferSize == 1 ) + { + AppLedStateOn = McpsIndication->Buffer[0] & 0x01; + //GpioWrite( &Led3, ( ( AppLedStateOn & 0x01 ) != 0 ) ? 0 : 1 ); + } + break; case 224: - if( ComplianceTestOn == false ) + if( ComplianceTest.Running == false ) { // Check compliance test enable command (i) - if( ( info->RxBufferSize == 4 ) && - ( info->RxBuffer[0] == 0x01 ) && - ( info->RxBuffer[1] == 0x01 ) && - ( info->RxBuffer[2] == 0x01 ) && - ( info->RxBuffer[3] == 0x01 ) ) + if( ( McpsIndication->BufferSize == 4 ) && + ( McpsIndication->Buffer[0] == 0x01 ) && + ( McpsIndication->Buffer[1] == 0x01 ) && + ( McpsIndication->Buffer[2] == 0x01 ) && + ( McpsIndication->Buffer[3] == 0x01 ) ) { IsTxConfirmed = false; AppPort = 224; AppDataSize = 2; - ComplianceTestDownLinkCounter = 0; - ComplianceTestLinkCheck = false; - ComplianceTestDemodMargin = 0; - ComplianceTestNbGateways = 0; - ComplianceTestOn = true; - ComplianceTestState = 1; + ComplianceTest.DownLinkCounter = 0; + ComplianceTest.LinkCheck = false; + ComplianceTest.DemodMargin = 0; + ComplianceTest.NbGateways = 0; + ComplianceTest.Running = true; + ComplianceTest.State = 1; - LoRaMacSetAdrOn( true ); - LoRaMacTestSetDutyCycleOn( LORAWAN_DUTYCYCLE_OFF ); + MibRequestConfirm_t mibReq; + mibReq.Type = MIB_ADR; + mibReq.Param.AdrEnable = true; + LoRaMacMibSetRequestConfirm( &mibReq ); + +#if defined( USE_BAND_868 ) + LoRaMacTestSetDutyCycleOn( false ); +#endif } } else { - ComplianceTestState = info->RxBuffer[0]; - switch( ComplianceTestState ) + ComplianceTest.State = McpsIndication->Buffer[0]; + switch( ComplianceTest.State ) { case 0: // Check compliance test disable command (ii) IsTxConfirmed = LORAWAN_CONFIRMED_MSG_ON; AppPort = LORAWAN_APP_PORT; AppDataSize = LORAWAN_APP_DATA_SIZE; - ComplianceTestDownLinkCounter = 0; - ComplianceTestOn = false; + ComplianceTest.DownLinkCounter = 0; + ComplianceTest.Running = false; - LoRaMacSetAdrOn( LORAWAN_ADR_ON ); + MibRequestConfirm_t mibReq; + mibReq.Type = MIB_ADR; + mibReq.Param.AdrEnable = LORAWAN_ADR_ON; + LoRaMacMibSetRequestConfirm( &mibReq ); +#if defined( USE_BAND_868 ) LoRaMacTestSetDutyCycleOn( LORAWAN_DUTYCYCLE_ON ); +#endif break; case 1: // (iii, iv) AppDataSize = 2; break; case 2: // Enable confirmed messages (v) IsTxConfirmed = true; - ComplianceTestState = 1; + ComplianceTest.State = 1; break; case 3: // Disable confirmed messages (vi) IsTxConfirmed = false; - ComplianceTestState = 1; + ComplianceTest.State = 1; break; case 4: // (vii) - AppDataSize = info->RxBufferSize; - printf("VII <------------------- rozmiar %i \r\n", AppDataSize); + AppDataSize = McpsIndication->BufferSize; + AppData[0] = 4; for( uint8_t i = 1; i < AppDataSize; i++ ) { - - printf("VII <-------------------dodaje \r\n"); - AppData[i] = info->RxBuffer[i] + 1; + AppData[i] = McpsIndication->Buffer[i] + 1; } break; case 5: // (viii) - LoRaMacLinkCheckReq( ); + { + MlmeReq_t mlmeReq; + mlmeReq.Type = MLME_LINK_CHECK; + LoRaMacMlmeRequest( &mlmeReq ); + } break; default: break; @@ -371,274 +574,196 @@ break; default: break; - } - - if( ( ComplianceTestOn == true ) && ( flags->Bits.LinkCheck == 1 ) ) - { - ComplianceTestLinkCheck = true; - ComplianceTestDemodMargin = info->DemodMargin; - ComplianceTestNbGateways = info->NbGateways; - } - - #warning needed extension to check counter scopes -} - -static bool SendFrame( void ) -{ - uint8_t sendFrameStatus = 0; - - if( IsTxConfirmed == false ) - { - sendFrameStatus = LoRaMacSendFrame( AppPort, AppData, AppDataSize ); - } - else - { - sendFrameStatus = LoRaMacSendConfirmedFrame( AppPort, AppData, AppDataSize, 8 ); + } } - switch( sendFrameStatus ) - { - case 5: // NO_FREE_CHANNEL - // Try again later - return true; - default: - return false; - } -} - -#if( OVER_THE_AIR_ACTIVATION != 0 ) - -/*! - * \brief Function executed on JoinReq Timeout event - */ -static void OnJoinReqTimerEvent( void ) -{ - JoinReqTimer.detach(); - TxNextPacket = true; -} - -#endif - -/*! - * \brief Function executed on TxNextPacket Timeout event - */ -static void OnTxNextPacketTimerEvent( void ) -{ - //TimerStop( &TxNextPacketTimer ); - //TxNextPacketTimer.stop(); - TxNextPacketTimer.detach(); - TxNextPacket = true; + // Switch LED 2 ON for each received downlink + Led2 = 0; + Led2Timer.attach_us(OnLed2TimerEvent, 25000); } /*! - * \brief Function executed on Led 1 Timeout event - */ -/*static void OnLed1TimerEvent( void ) -{ - TimerStop( &Led1Timer ); - Led1StateChanged = true; -}*/ - -/*! - * \brief Function executed on Led 2 Timeout event - */ -/*static void OnLed2TimerEvent( void ) -{ - TimerStop( &Led2Timer ); - Led2StateChanged = true; -}*/ - -/*! - * \brief Function executed on Led 4 Timeout event - */ -/*void OnLed4TimerEvent( void ) -{ - TimerStop( &Led4Timer ); - Led4StateChanged = true; -}*/ - -/*! - * \brief Function to be executed on MAC layer event + * \brief MLME-Confirm event function + * + * \param [IN] MlmeConfirm - Pointer to the confirm structure, + * containing confirm attributes. */ -static void OnMacEvent( LoRaMacEventFlags_t *flags, LoRaMacEventInfo_t *info ) +static void MlmeConfirm( MlmeConfirm_t *MlmeConfirm ) { - if( flags->Bits.JoinAccept == 1 ) + if( MlmeConfirm->Status == LORAMAC_EVENT_INFO_STATUS_OK ) { -#if( OVER_THE_AIR_ACTIVATION != 0 ) - JoinReqTimer.detach(); -#endif - IsNetworkJoined = true; - } - else - { - if( flags->Bits.Tx == 1 ) + switch( MlmeConfirm->MlmeRequest ) { - } - - if( flags->Bits.Rx == 1 ) - { - if( ComplianceTestOn == true ) + case MLME_JOIN: { - ComplianceTestDownLinkCounter++; + // Status is OK, node has joined the network + break; } - if( flags->Bits.RxData == true ) + case MLME_LINK_CHECK: { - ProcessRxFrame( flags, info ); + // Check DemodMargin + // Check NbGateways + if( ComplianceTest.Running == true ) + { + ComplianceTest.LinkCheck = true; + ComplianceTest.DemodMargin = MlmeConfirm->DemodMargin; + ComplianceTest.NbGateways = MlmeConfirm->NbGateways; + } + break; } - - DownlinkStatusUpdate = true; - //TimerStart( &Led2Timer ); + default: + break; } } - // Schedule a new transmission - ScheduleNextTx = true; + NextTx = true; } /** * Main application entry point. */ - int main( void ) { -#if( OVER_THE_AIR_ACTIVATION != 0 ) - uint8_t sendFrameStatus = 0; -#endif - bool trySendingFrameAgain = false; + LoRaMacPrimitives_t LoRaMacPrimitives; + LoRaMacCallback_t LoRaMacCallbacks; + MibRequestConfirm_t mibReq; -#warning HW and RADIO CHIP must be configured!!!! //BoardInitMcu( ); //BoardInitPeriph( ); - //hal_init(); - //radio_init(); - LoRaMacCallbacks.MacEvent = OnMacEvent; - //LoRaMacCallbacks.GetBatteryLevel = BoardGetBatteryLevel; - LoRaMacInit( &LoRaMacCallbacks ); - - IsNetworkJoined = false; - -#if( OVER_THE_AIR_ACTIVATION == 0 ) - // Random seed initialization - #warning seed initialization must be implemented - srand1( 1 ); - // Choose a random device address based on Board unique ID - // NwkAddr rand [0, 33554431] - DevAddr = randr( 0, 0x01FFFFFF ); - - LoRaMacInitNwkIds( LORAWAN_NETWORK_ID, DevAddr, NwkSKey, AppSKey ); - IsNetworkJoined = true; -#else - // Initialize LoRaMac device unique ID - //BoardGetUniqueId( DevEui ); -#endif - - TxNextPacket = true; - - //TimerInit( &Led1Timer, OnLed1TimerEvent ); - //TimerSetValue( &Led1Timer, 25000 ); - - //TimerInit( &Led2Timer, OnLed2TimerEvent ); - //TimerSetValue( &Led2Timer, 25000 ); - - //TimerInit( &Led4Timer, OnLed4TimerEvent ); - //TimerSetValue( &Led4Timer, 25000 ); - - LoRaMacSetAdrOn( LORAWAN_ADR_ON ); - #warning dutycycleON OFFFFFFFFFFFFF!!!!!!!!!!!!!!!!!!!!!!! -// LoRaMacTestSetDutyCycleOn( LORAWAN_DUTYCYCLE_ON ); - LoRaMacTestSetDutyCycleOn( 0 ); - LoRaMacSetPublicNetwork( LORAWAN_PUBLIC_NETWORK ); + DeviceState = DEVICE_STATE_INIT; while( 1 ) { - while( IsNetworkJoined == false ) - { -#if( OVER_THE_AIR_ACTIVATION != 0 ) - if( TxNextPacket == true ) - { - printf("Trial to join network... txnextpacket %i \r\n", TxNextPacket); - TxNextPacket = false; - - sendFrameStatus = LoRaMacJoinReq( DevEui, AppEui, AppKey ); - printf("status = %i\r\n", sendFrameStatus); - switch( sendFrameStatus ) - { - case 1: // BUSY - printf("busy...\r\n"); - break; - case 0: // OK - case 2: // NO_NETWORK_JOINED - case 3: // LENGTH_PORT_ERROR - case 4: // MAC_CMD_ERROR - case 6: // DEVICE_OFF - default: - // Relaunch timer for next trial - JoinReqTimer.attach_us(OnJoinReqTimerEvent, OVER_THE_AIR_ACTIVATION_DUTYCYCLE); - break; - } - } - //TimerLowPowerHandler( ); -#endif - } - -/* - if( Led1StateChanged == true ) - { - Led1StateChanged = false; - // Switch LED 1 OFF - GpioWrite( &Led1, 1 ); - } - if( Led2StateChanged == true ) - { - Led2StateChanged = false; - // Switch LED 2 OFF - GpioWrite( &Led2, 1 ); - } - if( Led3StateChanged == true ) + switch( DeviceState ) { - Led3StateChanged = false; - GpioWrite( &Led3, ( ( AppLedStateOn & 0x01 ) != 0 ) ? 0 : 1 ); - } - if( Led4StateChanged == true ) - { - Led4StateChanged = false; - // Switch LED 4 OFF - GpioWrite( &Led4, 1 ); - }*/ - if( DownlinkStatusUpdate == true ) - { - DownlinkStatusUpdate = false; - // Switch LED 2 ON for each received downlink - //GpioWrite( &Led2, 0 ); - } + case DEVICE_STATE_INIT: + { + LoRaMacPrimitives.MacMcpsConfirm = McpsConfirm; + LoRaMacPrimitives.MacMcpsIndication = McpsIndication; + LoRaMacPrimitives.MacMlmeConfirm = MlmeConfirm; + //LoRaMacCallbacks.GetBatteryLevel = BoardGetBatteryLevel; + LoRaMacInitialization( &LoRaMacPrimitives, &LoRaMacCallbacks ); + + mibReq.Type = MIB_ADR; + mibReq.Param.AdrEnable = LORAWAN_ADR_ON; + LoRaMacMibSetRequestConfirm( &mibReq ); + + mibReq.Type = MIB_PUBLIC_NETWORK; + mibReq.Param.EnablePublicNetwork = LORAWAN_PUBLIC_NETWORK; + LoRaMacMibSetRequestConfirm( &mibReq ); + +#if defined( USE_BAND_868 ) + LoRaMacTestSetDutyCycleOn( LORAWAN_DUTYCYCLE_ON ); + +#if( USE_SEMTECH_DEFAULT_CHANNEL_LINEUP == 1 ) + LoRaMacChannelAdd( 3, ( ChannelParams_t )LC4 ); + LoRaMacChannelAdd( 4, ( ChannelParams_t )LC5 ); + LoRaMacChannelAdd( 5, ( ChannelParams_t )LC6 ); + LoRaMacChannelAdd( 6, ( ChannelParams_t )LC7 ); + LoRaMacChannelAdd( 7, ( ChannelParams_t )LC8 ); + LoRaMacChannelAdd( 8, ( ChannelParams_t )LC9 ); +#endif - if( ScheduleNextTx == true ) - { - printf("Sending data..."); - ScheduleNextTx = false; +#endif + DeviceState = DEVICE_STATE_JOIN; + break; + } + case DEVICE_STATE_JOIN: + { +#if( OVER_THE_AIR_ACTIVATION != 0 ) + MlmeReq_t mlmeReq; + + #warning BoardGetUniqueId not needed in test software - commented out + // Initialize LoRaMac device unique ID + // BoardGetUniqueId( DevEui ); + + mlmeReq.Type = MLME_JOIN; + + mlmeReq.Req.Join.DevEui = DevEui; + mlmeReq.Req.Join.AppEui = AppEui; + mlmeReq.Req.Join.AppKey = AppKey; + + if( NextTx == true ) + { + LoRaMacMlmeRequest( &mlmeReq ); + } + + // Schedule next packet transmission + TxDutyCycleTime = OVER_THE_AIR_ACTIVATION_DUTYCYCLE; + DeviceState = DEVICE_STATE_CYCLE; + +#else + // Random seed initialization + srand1( BoardGetRandomSeed( ) ); + + // Choose a random device address + DevAddr = randr( 0, 0x01FFFFFF ); - // Schedule next packet transmission - TxDutyCycleTime = APP_TX_DUTYCYCLE + randr( -APP_TX_DUTYCYCLE_RND, APP_TX_DUTYCYCLE_RND ); - TxNextPacketTimer.attach_us(OnTxNextPacketTimerEvent, TxDutyCycleTime); - } + mibReq.Type = MIB_NET_ID; + mibReq.Param.NetID = LORAWAN_NETWORK_ID; + LoRaMacMibSetRequestConfirm( &mibReq ); + + mibReq.Type = MIB_DEV_ADDR; + mibReq.Param.DevAddr = DevAddr; + LoRaMacMibSetRequestConfirm( &mibReq ); + + mibReq.Type = MIB_NWK_SKEY; + mibReq.Param.NwkSKey = NwkSKey; + LoRaMacMibSetRequestConfirm( &mibReq ); + + mibReq.Type = MIB_APP_SKEY; + mibReq.Param.AppSKey = AppSKey; + LoRaMacMibSetRequestConfirm( &mibReq ); + + mibReq.Type = MIB_NETWORK_JOINED; + mibReq.Param.IsNetworkJoined = true; + LoRaMacMibSetRequestConfirm( &mibReq ); + + DeviceState = DEVICE_STATE_SEND; +#endif + break; + } + case DEVICE_STATE_SEND: + { + if( NextTx == true ) + { + PrepareTxFrame( AppPort ); - if( trySendingFrameAgain == true ) - { - trySendingFrameAgain = SendFrame( ); + NextTx = SendFrame( ); + } + if( ComplianceTest.Running == true ) + { + // Schedule next packet transmission as soon as possible + TxDutyCycleTime = 300000; // 300 ms + } + else + { + // Schedule next packet transmission + TxDutyCycleTime = APP_TX_DUTYCYCLE + randr( -APP_TX_DUTYCYCLE_RND, APP_TX_DUTYCYCLE_RND ); + } + DeviceState = DEVICE_STATE_CYCLE; + break; + } + case DEVICE_STATE_CYCLE: + { + DeviceState = DEVICE_STATE_SLEEP; + + // Schedule next packet transmission + TxNextPacketTimer.attach_us(OnTxNextPacketTimerEvent, TxDutyCycleTime); + break; + } + case DEVICE_STATE_SLEEP: + { + // Wake up through events + #warning TimerLowPowerHandler disabled + //TimerLowPowerHandler( ); + break; + } + default: + { + DeviceState = DEVICE_STATE_INIT; + break; + } } - if( TxNextPacket == true ) - { - TxNextPacket = false; - - PrepareTxFrame( AppPort ); - - // Switch LED 1 ON - //GpioWrite( &Led1, 0 ); - //TimerStart( &Led1Timer ); - - trySendingFrameAgain = SendFrame( ); - } - - //TimerLowPowerHandler( ); } -} +} \ No newline at end of file