NAMote72 application example using LoRaWAN-lib MAC layer implementation

Dependencies:   LoRaWAN-lib SX1272Lib lib_gps lib_mpl3115a2 mbed

LoRaWAN-demo is a ClassA device example project using LoRaWAN-lib and SX1272Lib libraries.

This demo application sends a frame every 4 to 6 seconds (randomly) and displays its current status using a serial port as display(VT100).

The serial port settings are as shown in below image. To access the serial port settings please click on "Setup" menu and then "Serial port..."

/media/uploads/mluis/serial_port_settings.png

The terminal window should be setup as shown in below image. To access the terminal window settings please click on "Setup" menu and then "Terminal..."

/media/uploads/mluis/terminal_window_settings.png

The image below shows the VT100 application status.

Application main screen

The application gives the possibility to either activate the device using

  • Over The Air Activation (OTAA)
  • Personalization activation (PA)

The activation mode can be adjusted in Comissioning.h by changing the following parameter:

/*!
 * 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


The application gives the possibility to select which kind of network we are connecting to.

  • Public Network (true)
  • Private Network (false)

The netork type can be changed as follows:

/*!
 * Indicates if the end-device is to be connected to a private or public network
 */
#define LORAWAN_PUBLIC_NETWORK                      true


OTAA
When OTAA is selected the user must porvide a device EUI, an application EUI and an application key.
These can be adjusted by changing the following parameters:

/*!
 * Mote device IEEE EUI (big endian)
 *
 * \remark In this application the value is automatically generated by calling
 *         BoardGetUniqueId function
 */
#define LORAWAN_DEVICE_EUI                          { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }

/*!
 * Application IEEE EUI (big endian)
 */
#define LORAWAN_APPLICATION_EUI                     { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }

/*!
 * AES encryption/decryption cipher application key
 */
#define LORAWAN_APPLICATION_KEY                     { 0x2B, 0x7E, 0x15, 0x16, 0x28, 0xAE, 0xD2, 0xA6, 0xAB, 0xF7, 0x15, 0x88, 0x09, 0xCF, 0x4F, 0x3C }


PA
When PA is selected the user must porvide a network ID, a device address, a network session key and an application session key.
These can be adjusted by changing the following parameters:

/*!
 * Current network ID
 */
#define LORAWAN_NETWORK_ID                          ( uint32_t )0

/*!
 * Device address on the network (big endian)
 *
 * \remark In this application the value is automatically generated using
 *         a pseudo random generator seeded with a value derived from
 *         BoardUniqueId value
 */
#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 }


On top of main.c the user has the possibility to tweak some application settings such as:

  • Join requests transmission frequency
  • Frames transmission frequency
  • Application default datarate
  • Confirmed or Unconfirmed frames transmission
  • ADR (Adaptive Datarate) ON/OFF
  • Application port to be used by the transmitted frames

The join requests transmission frequency can be adjusted by changing the follwoing parameter:

/*!
 * Join requests trials duty cycle.
 */
#define OVER_THE_AIR_ACTIVATION_DUTYCYCLE           10000000  // 10 [s] value in us


The frame transmission frequency can be adjusted by changing the follwoing parameters:

/*!
 * Defines the application data transmission duty cycle. 5s, value in [us].
 */
#define APP_TX_DUTYCYCLE                            5000000

/*!
 * Defines a random delay for application data transmission duty cycle. 1s,
 * value in [us].
 */
#define APP_TX_DUTYCYCLE_RND                        1000000


The frame transmission scheduling is then executed as follows:

        if( ScheduleNextTx == true )
        {
            ScheduleNextTx = false;
            // Schedule next packet transmission
            TxDutyCycleTime = APP_TX_DUTYCYCLE + randr( -APP_TX_DUTYCYCLE_RND, APP_TX_DUTYCYCLE_RND );
            TimerSetValue( &TxNextPacketTimer, TxDutyCycleTime );
            TimerStart( &TxNextPacketTimer );
        }


The application default datarate can be adjusted by changing the following parameter:

Quote:

When ADR is off this setting is the fixed datarate that will be used by the application.
When ADR is on this setting is the initial datarate used by the application.

/*!
 * Default mote datarate
 */
#define LORAWAN_DEFAULT_DATARATE                    DR_0


The transmitted frame contents will depend on LORAWAN_CONFIRMED_MSG_ON value.

/*!
 * LoRaWAN confirmed messages
 */
#define LORAWAN_CONFIRMED_MSG_ON                    true
  • If LORAWAN_CONFIRMED_MSG_ON equals false then the application payload is one byte corresponding to the AppLed state.
  • If LORAWAN_CONFIRMED_MSG_ON equals true then the application payload is six bytes corresponding to the AppLed state, Downlink counter (unsigned 16 bits), received RSSI (signed 16 bits) and received SNR (signed 8 bits).

/*!
 * \brief   Prepares the payload of the frame
 */
static void PrepareTxFrame( uint8_t port )
{
...
    switch( port )
    {
    case 5:
        {
            Gps.service( );
            Mpl3115a2.ReadTemperature( );
            AppData[0] = AppLedStateOn;                        // (bit 0 == 1) => LED on
            AppData[1] = ( int32_t )Mpl3115a2.Temperature;     // Signed degrees Celcius in half degree units. So, +/-63 °C
            AppData[2] = BoardGetBatteryLevel( );              // Per LoRaWAN spec; 0 = Charging; 1...254 = level, 255 = N/A
            AppData[3] = ( Gps.LatitudeBinary >> 16 ) & 0xFF;
            AppData[4] = ( Gps.LatitudeBinary >> 8 ) & 0xFF;
            AppData[5] = Gps.LatitudeBinary & 0xFF;
            AppData[6] = ( Gps.LongitudeBinary >> 16 ) & 0xFF;
            AppData[7] = ( Gps.LongitudeBinary >> 8 ) & 0xFF;
            AppData[8] = Gps.LongitudeBinary & 0xFF;

            uint16_t altitudeGps = atoi( Gps.NmeaGpsData.NmeaAltitude );
            AppData[9] = ( altitudeGps >> 8 ) & 0xFF;
            AppData[10] = altitudeGps & 0xFF;
        }
        break;
    case 224:
...
}


The ADR enabling/disabling can be adjusted by changing the following parameter:

/*!
 * LoRaWAN Adaptive Data Rate
 *
 * \remark Please note that when ADR is enabled the end-device should be static
 */
#define LORAWAN_ADR_ON                              1


The application port can be adjusted by changing the following parameter:

/*!
 * LoRaWAN application port
 */
#define LORAWAN_APP_PORT                            5
Committer:
mluis
Date:
Thu Jan 07 15:19:23 2016 +0000
Revision:
0:8e36e3d5d706
Child:
4:406d10ff5371
Initial commit

Who changed what in which revision?

UserRevisionLine numberNew contents of line
mluis 0:8e36e3d5d706 1 /*
mluis 0:8e36e3d5d706 2 / _____) _ | |
mluis 0:8e36e3d5d706 3 ( (____ _____ ____ _| |_ _____ ____| |__
mluis 0:8e36e3d5d706 4 \____ \| ___ | (_ _) ___ |/ ___) _ \
mluis 0:8e36e3d5d706 5 _____) ) ____| | | || |_| ____( (___| | | |
mluis 0:8e36e3d5d706 6 (______/|_____)_|_|_| \__)_____)\____)_| |_|
mluis 0:8e36e3d5d706 7 (C)2015 Semtech
mluis 0:8e36e3d5d706 8
mluis 0:8e36e3d5d706 9 Description: LoRaMac classA device implementation
mluis 0:8e36e3d5d706 10
mluis 0:8e36e3d5d706 11 License: Revised BSD License, see LICENSE.TXT file include in the project
mluis 0:8e36e3d5d706 12
mluis 0:8e36e3d5d706 13 Maintainer: Miguel Luis and Gregory Cristian
mluis 0:8e36e3d5d706 14 */
mluis 0:8e36e3d5d706 15 #include "mbed.h"
mluis 0:8e36e3d5d706 16 #include "board.h"
mluis 0:8e36e3d5d706 17 #include "radio.h"
mluis 0:8e36e3d5d706 18
mluis 0:8e36e3d5d706 19 #include "LoRaMac.h"
mluis 0:8e36e3d5d706 20 #include "Comissioning.h"
mluis 0:8e36e3d5d706 21 #include "SerialDisplay.h"
mluis 0:8e36e3d5d706 22
mluis 0:8e36e3d5d706 23 /*!
mluis 0:8e36e3d5d706 24 * Join requests trials duty cycle.
mluis 0:8e36e3d5d706 25 */
mluis 0:8e36e3d5d706 26 #define OVER_THE_AIR_ACTIVATION_DUTYCYCLE 10000000 // 10 [s] value in us
mluis 0:8e36e3d5d706 27
mluis 0:8e36e3d5d706 28 /*!
mluis 0:8e36e3d5d706 29 * Defines the application data transmission duty cycle. 5s, value in [us].
mluis 0:8e36e3d5d706 30 */
mluis 0:8e36e3d5d706 31 #define APP_TX_DUTYCYCLE 5000000
mluis 0:8e36e3d5d706 32
mluis 0:8e36e3d5d706 33 /*!
mluis 0:8e36e3d5d706 34 * Defines a random delay for application data transmission duty cycle. 1s,
mluis 0:8e36e3d5d706 35 * value in [us].
mluis 0:8e36e3d5d706 36 */
mluis 0:8e36e3d5d706 37 #define APP_TX_DUTYCYCLE_RND 1000000
mluis 0:8e36e3d5d706 38
mluis 0:8e36e3d5d706 39 /*!
mluis 0:8e36e3d5d706 40 * Default mote datarate
mluis 0:8e36e3d5d706 41 */
mluis 0:8e36e3d5d706 42 #define LORAWAN_DEFAULT_DATARATE DR_0
mluis 0:8e36e3d5d706 43
mluis 0:8e36e3d5d706 44 /*!
mluis 0:8e36e3d5d706 45 * LoRaWAN confirmed messages
mluis 0:8e36e3d5d706 46 */
mluis 0:8e36e3d5d706 47 #define LORAWAN_CONFIRMED_MSG_ON true
mluis 0:8e36e3d5d706 48
mluis 0:8e36e3d5d706 49 /*!
mluis 0:8e36e3d5d706 50 * LoRaWAN Adaptive Data Rate
mluis 0:8e36e3d5d706 51 *
mluis 0:8e36e3d5d706 52 * \remark Please note that when ADR is enabled the end-device should be static
mluis 0:8e36e3d5d706 53 */
mluis 0:8e36e3d5d706 54 #define LORAWAN_ADR_ON 1
mluis 0:8e36e3d5d706 55
mluis 0:8e36e3d5d706 56 /*!
mluis 0:8e36e3d5d706 57 * LoRaWAN application port
mluis 0:8e36e3d5d706 58 */
mluis 0:8e36e3d5d706 59 #define LORAWAN_APP_PORT 5
mluis 0:8e36e3d5d706 60
mluis 0:8e36e3d5d706 61 /*!
mluis 0:8e36e3d5d706 62 * User application data buffer size
mluis 0:8e36e3d5d706 63 */
mluis 0:8e36e3d5d706 64 #define LORAWAN_APP_DATA_SIZE 11
mluis 0:8e36e3d5d706 65
mluis 0:8e36e3d5d706 66 #if( OVER_THE_AIR_ACTIVATION != 0 )
mluis 0:8e36e3d5d706 67
mluis 0:8e36e3d5d706 68 static uint8_t DevEui[] = LORAWAN_DEVICE_EUI;
mluis 0:8e36e3d5d706 69 static uint8_t AppEui[] = LORAWAN_APPLICATION_EUI;
mluis 0:8e36e3d5d706 70 static uint8_t AppKey[] = LORAWAN_APPLICATION_KEY;
mluis 0:8e36e3d5d706 71
mluis 0:8e36e3d5d706 72 #else
mluis 0:8e36e3d5d706 73
mluis 0:8e36e3d5d706 74 static uint8_t NwkSKey[] = LORAWAN_NWKSKEY;
mluis 0:8e36e3d5d706 75 static uint8_t AppSKey[] = LORAWAN_APPSKEY;
mluis 0:8e36e3d5d706 76
mluis 0:8e36e3d5d706 77 /*!
mluis 0:8e36e3d5d706 78 * Device address
mluis 0:8e36e3d5d706 79 */
mluis 0:8e36e3d5d706 80 static uint32_t DevAddr = LORAWAN_DEVICE_ADDRESS;
mluis 0:8e36e3d5d706 81
mluis 0:8e36e3d5d706 82 #endif
mluis 0:8e36e3d5d706 83
mluis 0:8e36e3d5d706 84 /*!
mluis 0:8e36e3d5d706 85 * Application port
mluis 0:8e36e3d5d706 86 */
mluis 0:8e36e3d5d706 87 static uint8_t AppPort = LORAWAN_APP_PORT;
mluis 0:8e36e3d5d706 88
mluis 0:8e36e3d5d706 89 /*!
mluis 0:8e36e3d5d706 90 * User application data size
mluis 0:8e36e3d5d706 91 */
mluis 0:8e36e3d5d706 92 static uint8_t AppDataSize = LORAWAN_APP_DATA_SIZE;
mluis 0:8e36e3d5d706 93
mluis 0:8e36e3d5d706 94 /*!
mluis 0:8e36e3d5d706 95 * User application data buffer size
mluis 0:8e36e3d5d706 96 */
mluis 0:8e36e3d5d706 97 #define LORAWAN_APP_DATA_MAX_SIZE 64
mluis 0:8e36e3d5d706 98
mluis 0:8e36e3d5d706 99 /*!
mluis 0:8e36e3d5d706 100 * User application data
mluis 0:8e36e3d5d706 101 */
mluis 0:8e36e3d5d706 102 static uint8_t AppData[LORAWAN_APP_DATA_MAX_SIZE];
mluis 0:8e36e3d5d706 103
mluis 0:8e36e3d5d706 104 /*!
mluis 0:8e36e3d5d706 105 * Indicates if the node is sending confirmed or unconfirmed messages
mluis 0:8e36e3d5d706 106 */
mluis 0:8e36e3d5d706 107 static uint8_t IsTxConfirmed = LORAWAN_CONFIRMED_MSG_ON;
mluis 0:8e36e3d5d706 108
mluis 0:8e36e3d5d706 109 /*!
mluis 0:8e36e3d5d706 110 * Defines the application data transmission duty cycle
mluis 0:8e36e3d5d706 111 */
mluis 0:8e36e3d5d706 112 static uint32_t TxDutyCycleTime;
mluis 0:8e36e3d5d706 113
mluis 0:8e36e3d5d706 114 /*!
mluis 0:8e36e3d5d706 115 * Timer to handle the application data transmission duty cycle
mluis 0:8e36e3d5d706 116 */
mluis 0:8e36e3d5d706 117 static TimerEvent_t TxNextPacketTimer;
mluis 0:8e36e3d5d706 118
mluis 0:8e36e3d5d706 119 /*!
mluis 0:8e36e3d5d706 120 * Specifies the state of the application LED
mluis 0:8e36e3d5d706 121 */
mluis 0:8e36e3d5d706 122 static bool AppLedStateOn = false;
mluis 0:8e36e3d5d706 123 volatile bool UsrLedStateChanged = false;
mluis 0:8e36e3d5d706 124
mluis 0:8e36e3d5d706 125 /*!
mluis 0:8e36e3d5d706 126 * Timer to handle the state of LED1
mluis 0:8e36e3d5d706 127 */
mluis 0:8e36e3d5d706 128 static TimerEvent_t RedLedTimer;
mluis 0:8e36e3d5d706 129 volatile bool RedLedState = false;
mluis 0:8e36e3d5d706 130 volatile bool RedLedStateChanged = false;
mluis 0:8e36e3d5d706 131 /*!
mluis 0:8e36e3d5d706 132 * Timer to handle the state of LED2
mluis 0:8e36e3d5d706 133 */
mluis 0:8e36e3d5d706 134 static TimerEvent_t YellowLedTimer;
mluis 0:8e36e3d5d706 135 volatile bool YellowLedState = false;
mluis 0:8e36e3d5d706 136 volatile bool YellowLedStateChanged = false;
mluis 0:8e36e3d5d706 137
mluis 0:8e36e3d5d706 138 /*!
mluis 0:8e36e3d5d706 139 * Indicates if a new packet can be sent
mluis 0:8e36e3d5d706 140 */
mluis 0:8e36e3d5d706 141 static bool NextTx = true;
mluis 0:8e36e3d5d706 142
mluis 0:8e36e3d5d706 143 /*!
mluis 0:8e36e3d5d706 144 * Device states
mluis 0:8e36e3d5d706 145 */
mluis 0:8e36e3d5d706 146 static enum eDevicState
mluis 0:8e36e3d5d706 147 {
mluis 0:8e36e3d5d706 148 DEVICE_STATE_INIT,
mluis 0:8e36e3d5d706 149 DEVICE_STATE_JOIN,
mluis 0:8e36e3d5d706 150 DEVICE_STATE_SEND,
mluis 0:8e36e3d5d706 151 DEVICE_STATE_CYCLE,
mluis 0:8e36e3d5d706 152 DEVICE_STATE_SLEEP
mluis 0:8e36e3d5d706 153 }DeviceState;
mluis 0:8e36e3d5d706 154
mluis 0:8e36e3d5d706 155 /*!
mluis 0:8e36e3d5d706 156 * LoRaWAN compliance tests support data
mluis 0:8e36e3d5d706 157 */
mluis 0:8e36e3d5d706 158 struct ComplianceTest_s
mluis 0:8e36e3d5d706 159 {
mluis 0:8e36e3d5d706 160 bool Running;
mluis 0:8e36e3d5d706 161 uint8_t State;
mluis 0:8e36e3d5d706 162 bool IsTxConfirmed;
mluis 0:8e36e3d5d706 163 uint8_t AppPort;
mluis 0:8e36e3d5d706 164 uint8_t AppDataSize;
mluis 0:8e36e3d5d706 165 uint8_t *AppDataBuffer;
mluis 0:8e36e3d5d706 166 uint16_t DownLinkCounter;
mluis 0:8e36e3d5d706 167 bool LinkCheck;
mluis 0:8e36e3d5d706 168 uint8_t DemodMargin;
mluis 0:8e36e3d5d706 169 uint8_t NbGateways;
mluis 0:8e36e3d5d706 170 }ComplianceTest;
mluis 0:8e36e3d5d706 171
mluis 0:8e36e3d5d706 172 /*
mluis 0:8e36e3d5d706 173 * SerialDisplay managment variables
mluis 0:8e36e3d5d706 174 */
mluis 0:8e36e3d5d706 175
mluis 0:8e36e3d5d706 176 /*!
mluis 0:8e36e3d5d706 177 * Indicates if the MAC layer network join status has changed.
mluis 0:8e36e3d5d706 178 */
mluis 0:8e36e3d5d706 179 static bool IsNetworkJoinedStatusUpdate = false;
mluis 0:8e36e3d5d706 180
mluis 0:8e36e3d5d706 181 /*!
mluis 0:8e36e3d5d706 182 * Strucure containing the Uplink status
mluis 0:8e36e3d5d706 183 */
mluis 0:8e36e3d5d706 184 struct sLoRaMacUplinkStatus
mluis 0:8e36e3d5d706 185 {
mluis 0:8e36e3d5d706 186 uint8_t Acked;
mluis 0:8e36e3d5d706 187 int8_t Datarate;
mluis 0:8e36e3d5d706 188 uint16_t UplinkCounter;
mluis 0:8e36e3d5d706 189 uint8_t Port;
mluis 0:8e36e3d5d706 190 uint8_t *Buffer;
mluis 0:8e36e3d5d706 191 uint8_t BufferSize;
mluis 0:8e36e3d5d706 192 }LoRaMacUplinkStatus;
mluis 0:8e36e3d5d706 193 volatile bool UplinkStatusUpdated = false;
mluis 0:8e36e3d5d706 194
mluis 0:8e36e3d5d706 195 /*!
mluis 0:8e36e3d5d706 196 * Strucure containing the Downlink status
mluis 0:8e36e3d5d706 197 */
mluis 0:8e36e3d5d706 198 struct sLoRaMacDownlinkStatus
mluis 0:8e36e3d5d706 199 {
mluis 0:8e36e3d5d706 200 int16_t Rssi;
mluis 0:8e36e3d5d706 201 int8_t Snr;
mluis 0:8e36e3d5d706 202 uint16_t DownlinkCounter;
mluis 0:8e36e3d5d706 203 bool RxData;
mluis 0:8e36e3d5d706 204 uint8_t Port;
mluis 0:8e36e3d5d706 205 uint8_t *Buffer;
mluis 0:8e36e3d5d706 206 uint8_t BufferSize;
mluis 0:8e36e3d5d706 207 }LoRaMacDownlinkStatus;
mluis 0:8e36e3d5d706 208 volatile bool DownlinkStatusUpdated = false;
mluis 0:8e36e3d5d706 209
mluis 0:8e36e3d5d706 210 void SerialDisplayRefresh( void )
mluis 0:8e36e3d5d706 211 {
mluis 0:8e36e3d5d706 212 MibRequestConfirm_t mibReq;
mluis 0:8e36e3d5d706 213
mluis 0:8e36e3d5d706 214 SerialDisplayInit( );
mluis 0:8e36e3d5d706 215 SerialDisplayUpdateActivationMode( OVER_THE_AIR_ACTIVATION );
mluis 0:8e36e3d5d706 216
mluis 0:8e36e3d5d706 217 #if( OVER_THE_AIR_ACTIVATION == 0 )
mluis 0:8e36e3d5d706 218 SerialDisplayUpdateNwkId( LORAWAN_NETWORK_ID );
mluis 0:8e36e3d5d706 219 SerialDisplayUpdateDevAddr( DevAddr );
mluis 0:8e36e3d5d706 220 SerialDisplayUpdateKey( 12, NwkSKey );
mluis 0:8e36e3d5d706 221 SerialDisplayUpdateKey( 13, AppSKey );
mluis 0:8e36e3d5d706 222 #else
mluis 0:8e36e3d5d706 223 SerialDisplayUpdateEui( 5, DevEui );
mluis 0:8e36e3d5d706 224 SerialDisplayUpdateEui( 6, AppEui );
mluis 0:8e36e3d5d706 225 SerialDisplayUpdateKey( 7, AppKey );
mluis 0:8e36e3d5d706 226 #endif
mluis 0:8e36e3d5d706 227
mluis 0:8e36e3d5d706 228 mibReq.Type = MIB_NETWORK_JOINED;
mluis 0:8e36e3d5d706 229 LoRaMacMibGetRequestConfirm( &mibReq );
mluis 0:8e36e3d5d706 230 SerialDisplayUpdateNetworkIsJoined( mibReq.Param.IsNetworkJoined );
mluis 0:8e36e3d5d706 231
mluis 0:8e36e3d5d706 232 SerialDisplayUpdateAdr( LORAWAN_ADR_ON );
mluis 0:8e36e3d5d706 233
mluis 0:8e36e3d5d706 234 SerialDisplayUpdatePublicNetwork( LORAWAN_PUBLIC_NETWORK );
mluis 0:8e36e3d5d706 235
mluis 0:8e36e3d5d706 236 SerialDisplayUpdateLedState( 3, AppLedStateOn );
mluis 0:8e36e3d5d706 237 }
mluis 0:8e36e3d5d706 238
mluis 0:8e36e3d5d706 239 void SerialRxProcess( void )
mluis 0:8e36e3d5d706 240 {
mluis 0:8e36e3d5d706 241 if( SerialDisplayReadable( ) == true )
mluis 0:8e36e3d5d706 242 {
mluis 0:8e36e3d5d706 243 switch( SerialDisplayGetChar( ) )
mluis 0:8e36e3d5d706 244 {
mluis 0:8e36e3d5d706 245 case 'R':
mluis 0:8e36e3d5d706 246 case 'r':
mluis 0:8e36e3d5d706 247 // Refresh Serial screen
mluis 0:8e36e3d5d706 248 SerialDisplayRefresh( );
mluis 0:8e36e3d5d706 249 break;
mluis 0:8e36e3d5d706 250 default:
mluis 0:8e36e3d5d706 251 break;
mluis 0:8e36e3d5d706 252 }
mluis 0:8e36e3d5d706 253 }
mluis 0:8e36e3d5d706 254 }
mluis 0:8e36e3d5d706 255
mluis 0:8e36e3d5d706 256 /*!
mluis 0:8e36e3d5d706 257 * \brief Prepares the payload of the frame
mluis 0:8e36e3d5d706 258 */
mluis 0:8e36e3d5d706 259 static void PrepareTxFrame( uint8_t port )
mluis 0:8e36e3d5d706 260 {
mluis 0:8e36e3d5d706 261 MibRequestConfirm_t mibReq;
mluis 0:8e36e3d5d706 262
mluis 0:8e36e3d5d706 263 if( BoardGetBatteryVoltage( ) < LOW_BAT_THRESHOLD )
mluis 0:8e36e3d5d706 264 {
mluis 0:8e36e3d5d706 265 mibReq.Type = MIB_CHANNELS_TX_POWER;
mluis 0:8e36e3d5d706 266 LoRaMacMibGetRequestConfirm( &mibReq );
mluis 0:8e36e3d5d706 267 // TX_POWER_30_DBM = 0, TX_POWER_28_DBM = 1, ..., TX_POWER_20_DBM = 5, ..., TX_POWER_10_DBM = 10
mluis 0:8e36e3d5d706 268 // The if condition is then "less than" to check if the power is greater than 20 dBm
mluis 0:8e36e3d5d706 269 if( mibReq.Param.ChannelsTxPower < TX_POWER_20_DBM )
mluis 0:8e36e3d5d706 270 {
mluis 0:8e36e3d5d706 271 mibReq.Param.ChannelsTxPower = TX_POWER_20_DBM;
mluis 0:8e36e3d5d706 272 LoRaMacMibSetRequestConfirm( &mibReq );
mluis 0:8e36e3d5d706 273 }
mluis 0:8e36e3d5d706 274 }
mluis 0:8e36e3d5d706 275 switch( port )
mluis 0:8e36e3d5d706 276 {
mluis 0:8e36e3d5d706 277 case 5:
mluis 0:8e36e3d5d706 278 {
mluis 0:8e36e3d5d706 279 Gps.service( );
mluis 0:8e36e3d5d706 280 Mpl3115a2.ReadTemperature( );
mluis 0:8e36e3d5d706 281 AppData[0] = AppLedStateOn; // (bit 0 == 1) => LED on
mluis 0:8e36e3d5d706 282 AppData[1] = ( int32_t )Mpl3115a2.Temperature; // Signed degrees Celcius in half degree units. So, +/-63 °C
mluis 0:8e36e3d5d706 283 AppData[2] = BoardGetBatteryLevel( ); // Per LoRaWAN spec; 0 = Charging; 1...254 = level, 255 = N/A
mluis 0:8e36e3d5d706 284 AppData[3] = ( Gps.LatitudeBinary >> 16 ) & 0xFF;
mluis 0:8e36e3d5d706 285 AppData[4] = ( Gps.LatitudeBinary >> 8 ) & 0xFF;
mluis 0:8e36e3d5d706 286 AppData[5] = Gps.LatitudeBinary & 0xFF;
mluis 0:8e36e3d5d706 287 AppData[6] = ( Gps.LongitudeBinary >> 16 ) & 0xFF;
mluis 0:8e36e3d5d706 288 AppData[7] = ( Gps.LongitudeBinary >> 8 ) & 0xFF;
mluis 0:8e36e3d5d706 289 AppData[8] = Gps.LongitudeBinary & 0xFF;
mluis 0:8e36e3d5d706 290
mluis 0:8e36e3d5d706 291 uint16_t altitudeGps = atoi( Gps.NmeaGpsData.NmeaAltitude );
mluis 0:8e36e3d5d706 292 AppData[9] = ( altitudeGps >> 8 ) & 0xFF;
mluis 0:8e36e3d5d706 293 AppData[10] = altitudeGps & 0xFF;
mluis 0:8e36e3d5d706 294 }
mluis 0:8e36e3d5d706 295 break;
mluis 0:8e36e3d5d706 296 case 224:
mluis 0:8e36e3d5d706 297 if( ComplianceTest.LinkCheck == true )
mluis 0:8e36e3d5d706 298 {
mluis 0:8e36e3d5d706 299 ComplianceTest.LinkCheck = false;
mluis 0:8e36e3d5d706 300 AppDataSize = 3;
mluis 0:8e36e3d5d706 301 AppData[0] = 5;
mluis 0:8e36e3d5d706 302 AppData[1] = ComplianceTest.DemodMargin;
mluis 0:8e36e3d5d706 303 AppData[2] = ComplianceTest.NbGateways;
mluis 0:8e36e3d5d706 304 ComplianceTest.State = 1;
mluis 0:8e36e3d5d706 305 }
mluis 0:8e36e3d5d706 306 else
mluis 0:8e36e3d5d706 307 {
mluis 0:8e36e3d5d706 308 switch( ComplianceTest.State )
mluis 0:8e36e3d5d706 309 {
mluis 0:8e36e3d5d706 310 case 4:
mluis 0:8e36e3d5d706 311 ComplianceTest.State = 1;
mluis 0:8e36e3d5d706 312 break;
mluis 0:8e36e3d5d706 313 case 1:
mluis 0:8e36e3d5d706 314 AppDataSize = 2;
mluis 0:8e36e3d5d706 315 AppData[0] = ComplianceTest.DownLinkCounter >> 8;
mluis 0:8e36e3d5d706 316 AppData[1] = ComplianceTest.DownLinkCounter;
mluis 0:8e36e3d5d706 317 break;
mluis 0:8e36e3d5d706 318 }
mluis 0:8e36e3d5d706 319 }
mluis 0:8e36e3d5d706 320 break;
mluis 0:8e36e3d5d706 321 default:
mluis 0:8e36e3d5d706 322 break;
mluis 0:8e36e3d5d706 323 }
mluis 0:8e36e3d5d706 324 }
mluis 0:8e36e3d5d706 325
mluis 0:8e36e3d5d706 326 /*!
mluis 0:8e36e3d5d706 327 * \brief Prepares the payload of the frame
mluis 0:8e36e3d5d706 328 *
mluis 0:8e36e3d5d706 329 * \retval [0: frame could be send, 1: error]
mluis 0:8e36e3d5d706 330 */
mluis 0:8e36e3d5d706 331 static bool SendFrame( void )
mluis 0:8e36e3d5d706 332 {
mluis 0:8e36e3d5d706 333 McpsReq_t mcpsReq;
mluis 0:8e36e3d5d706 334 LoRaMacTxInfo_t txInfo;
mluis 0:8e36e3d5d706 335
mluis 0:8e36e3d5d706 336 if( LoRaMacQueryTxPossible( AppDataSize, &txInfo ) != LORAMAC_STATUS_OK )
mluis 0:8e36e3d5d706 337 {
mluis 0:8e36e3d5d706 338 // Send empty frame in order to flush MAC commands
mluis 0:8e36e3d5d706 339 mcpsReq.Type = MCPS_UNCONFIRMED;
mluis 0:8e36e3d5d706 340 mcpsReq.Req.Unconfirmed.fBuffer = NULL;
mluis 0:8e36e3d5d706 341 mcpsReq.Req.Unconfirmed.fBufferSize = 0;
mluis 0:8e36e3d5d706 342 mcpsReq.Req.Unconfirmed.Datarate = LORAWAN_DEFAULT_DATARATE;
mluis 0:8e36e3d5d706 343
mluis 0:8e36e3d5d706 344 LoRaMacUplinkStatus.Acked = false;
mluis 0:8e36e3d5d706 345 LoRaMacUplinkStatus.Port = 0;
mluis 0:8e36e3d5d706 346 LoRaMacUplinkStatus.Buffer = NULL;
mluis 0:8e36e3d5d706 347 LoRaMacUplinkStatus.BufferSize = 0;
mluis 0:8e36e3d5d706 348 SerialDisplayUpdateFrameType( false );
mluis 0:8e36e3d5d706 349 }
mluis 0:8e36e3d5d706 350 else
mluis 0:8e36e3d5d706 351 {
mluis 0:8e36e3d5d706 352 LoRaMacUplinkStatus.Acked = false;
mluis 0:8e36e3d5d706 353 LoRaMacUplinkStatus.Port = AppPort;
mluis 0:8e36e3d5d706 354 LoRaMacUplinkStatus.Buffer = AppData;
mluis 0:8e36e3d5d706 355 LoRaMacUplinkStatus.BufferSize = AppDataSize;
mluis 0:8e36e3d5d706 356 SerialDisplayUpdateFrameType( IsTxConfirmed );
mluis 0:8e36e3d5d706 357
mluis 0:8e36e3d5d706 358 if( IsTxConfirmed == false )
mluis 0:8e36e3d5d706 359 {
mluis 0:8e36e3d5d706 360 mcpsReq.Type = MCPS_UNCONFIRMED;
mluis 0:8e36e3d5d706 361 mcpsReq.Req.Unconfirmed.fPort = AppPort;
mluis 0:8e36e3d5d706 362 mcpsReq.Req.Unconfirmed.fBuffer = AppData;
mluis 0:8e36e3d5d706 363 mcpsReq.Req.Unconfirmed.fBufferSize = AppDataSize;
mluis 0:8e36e3d5d706 364 mcpsReq.Req.Unconfirmed.Datarate = LORAWAN_DEFAULT_DATARATE;
mluis 0:8e36e3d5d706 365 }
mluis 0:8e36e3d5d706 366 else
mluis 0:8e36e3d5d706 367 {
mluis 0:8e36e3d5d706 368 mcpsReq.Type = MCPS_CONFIRMED;
mluis 0:8e36e3d5d706 369 mcpsReq.Req.Confirmed.fPort = AppPort;
mluis 0:8e36e3d5d706 370 mcpsReq.Req.Confirmed.fBuffer = AppData;
mluis 0:8e36e3d5d706 371 mcpsReq.Req.Confirmed.fBufferSize = AppDataSize;
mluis 0:8e36e3d5d706 372 mcpsReq.Req.Confirmed.nbRetries = 8;
mluis 0:8e36e3d5d706 373 mcpsReq.Req.Confirmed.Datarate = LORAWAN_DEFAULT_DATARATE;
mluis 0:8e36e3d5d706 374 }
mluis 0:8e36e3d5d706 375 }
mluis 0:8e36e3d5d706 376
mluis 0:8e36e3d5d706 377 if( LoRaMacMcpsRequest( &mcpsReq ) == LORAMAC_STATUS_OK )
mluis 0:8e36e3d5d706 378 {
mluis 0:8e36e3d5d706 379 return false;
mluis 0:8e36e3d5d706 380 }
mluis 0:8e36e3d5d706 381 return true;
mluis 0:8e36e3d5d706 382 }
mluis 0:8e36e3d5d706 383
mluis 0:8e36e3d5d706 384 /*!
mluis 0:8e36e3d5d706 385 * \brief Function executed on TxNextPacket Timeout event
mluis 0:8e36e3d5d706 386 */
mluis 0:8e36e3d5d706 387 static void OnTxNextPacketTimerEvent( void )
mluis 0:8e36e3d5d706 388 {
mluis 0:8e36e3d5d706 389 MibRequestConfirm_t mibReq;
mluis 0:8e36e3d5d706 390 LoRaMacStatus_t status;
mluis 0:8e36e3d5d706 391
mluis 0:8e36e3d5d706 392 TimerStop( &TxNextPacketTimer );
mluis 0:8e36e3d5d706 393
mluis 0:8e36e3d5d706 394 mibReq.Type = MIB_NETWORK_JOINED;
mluis 0:8e36e3d5d706 395 status = LoRaMacMibGetRequestConfirm( &mibReq );
mluis 0:8e36e3d5d706 396
mluis 0:8e36e3d5d706 397 if( status == LORAMAC_STATUS_OK )
mluis 0:8e36e3d5d706 398 {
mluis 0:8e36e3d5d706 399 if( mibReq.Param.IsNetworkJoined == true )
mluis 0:8e36e3d5d706 400 {
mluis 0:8e36e3d5d706 401 DeviceState = DEVICE_STATE_SEND;
mluis 0:8e36e3d5d706 402 NextTx = true;
mluis 0:8e36e3d5d706 403 }
mluis 0:8e36e3d5d706 404 else
mluis 0:8e36e3d5d706 405 {
mluis 0:8e36e3d5d706 406 DeviceState = DEVICE_STATE_JOIN;
mluis 0:8e36e3d5d706 407 }
mluis 0:8e36e3d5d706 408 }
mluis 0:8e36e3d5d706 409 }
mluis 0:8e36e3d5d706 410
mluis 0:8e36e3d5d706 411 /*!
mluis 0:8e36e3d5d706 412 * \brief Function executed on Led 1 Timeout event
mluis 0:8e36e3d5d706 413 */
mluis 0:8e36e3d5d706 414 static void OnRedLedTimerEvent( void )
mluis 0:8e36e3d5d706 415 {
mluis 0:8e36e3d5d706 416 TimerStop( &RedLedTimer );
mluis 0:8e36e3d5d706 417 RedLedState = false;
mluis 0:8e36e3d5d706 418 RedLedStateChanged = true;
mluis 0:8e36e3d5d706 419 }
mluis 0:8e36e3d5d706 420
mluis 0:8e36e3d5d706 421 /*!
mluis 0:8e36e3d5d706 422 * \brief Function executed on Led 2 Timeout event
mluis 0:8e36e3d5d706 423 */
mluis 0:8e36e3d5d706 424 static void OnYellowLedTimerEvent( void )
mluis 0:8e36e3d5d706 425 {
mluis 0:8e36e3d5d706 426 TimerStop( &YellowLedTimer );
mluis 0:8e36e3d5d706 427 YellowLedState = false;
mluis 0:8e36e3d5d706 428 YellowLedStateChanged = true;
mluis 0:8e36e3d5d706 429 }
mluis 0:8e36e3d5d706 430
mluis 0:8e36e3d5d706 431 /*!
mluis 0:8e36e3d5d706 432 * \brief MCPS-Confirm event function
mluis 0:8e36e3d5d706 433 *
mluis 0:8e36e3d5d706 434 * \param [IN] McpsConfirm - Pointer to the confirm structure,
mluis 0:8e36e3d5d706 435 * containing confirm attributes.
mluis 0:8e36e3d5d706 436 */
mluis 0:8e36e3d5d706 437 static void McpsConfirm( McpsConfirm_t *McpsConfirm )
mluis 0:8e36e3d5d706 438 {
mluis 0:8e36e3d5d706 439 if( McpsConfirm->Status == LORAMAC_EVENT_INFO_STATUS_OK )
mluis 0:8e36e3d5d706 440 {
mluis 0:8e36e3d5d706 441 switch( McpsConfirm->McpsRequest )
mluis 0:8e36e3d5d706 442 {
mluis 0:8e36e3d5d706 443 case MCPS_UNCONFIRMED:
mluis 0:8e36e3d5d706 444 {
mluis 0:8e36e3d5d706 445 // Check Datarate
mluis 0:8e36e3d5d706 446 // Check TxPower
mluis 0:8e36e3d5d706 447 break;
mluis 0:8e36e3d5d706 448 }
mluis 0:8e36e3d5d706 449 case MCPS_CONFIRMED:
mluis 0:8e36e3d5d706 450 {
mluis 0:8e36e3d5d706 451 // Check Datarate
mluis 0:8e36e3d5d706 452 // Check TxPower
mluis 0:8e36e3d5d706 453 // Check AckReceived
mluis 0:8e36e3d5d706 454 // Check NbRetries
mluis 0:8e36e3d5d706 455 LoRaMacUplinkStatus.Acked = McpsConfirm->AckReceived;
mluis 0:8e36e3d5d706 456 break;
mluis 0:8e36e3d5d706 457 }
mluis 0:8e36e3d5d706 458 case MCPS_PROPRIETARY:
mluis 0:8e36e3d5d706 459 {
mluis 0:8e36e3d5d706 460 break;
mluis 0:8e36e3d5d706 461 }
mluis 0:8e36e3d5d706 462 default:
mluis 0:8e36e3d5d706 463 break;
mluis 0:8e36e3d5d706 464 }
mluis 0:8e36e3d5d706 465 LoRaMacUplinkStatus.Datarate = McpsConfirm->Datarate;
mluis 0:8e36e3d5d706 466 LoRaMacUplinkStatus.UplinkCounter = McpsConfirm->UpLinkCounter;
mluis 0:8e36e3d5d706 467
mluis 0:8e36e3d5d706 468 UplinkStatusUpdated = true;
mluis 0:8e36e3d5d706 469 }
mluis 0:8e36e3d5d706 470 NextTx = true;
mluis 0:8e36e3d5d706 471 }
mluis 0:8e36e3d5d706 472
mluis 0:8e36e3d5d706 473 /*!
mluis 0:8e36e3d5d706 474 * \brief MCPS-Indication event function
mluis 0:8e36e3d5d706 475 *
mluis 0:8e36e3d5d706 476 * \param [IN] McpsIndication - Pointer to the indication structure,
mluis 0:8e36e3d5d706 477 * containing indication attributes.
mluis 0:8e36e3d5d706 478 */
mluis 0:8e36e3d5d706 479 static void McpsIndication( McpsIndication_t *McpsIndication )
mluis 0:8e36e3d5d706 480 {
mluis 0:8e36e3d5d706 481 Gps.service( );
mluis 0:8e36e3d5d706 482
mluis 0:8e36e3d5d706 483 if( McpsIndication->Status != LORAMAC_EVENT_INFO_STATUS_OK )
mluis 0:8e36e3d5d706 484 {
mluis 0:8e36e3d5d706 485 return;
mluis 0:8e36e3d5d706 486 }
mluis 0:8e36e3d5d706 487
mluis 0:8e36e3d5d706 488 switch( McpsIndication->McpsIndication )
mluis 0:8e36e3d5d706 489 {
mluis 0:8e36e3d5d706 490 case MCPS_UNCONFIRMED:
mluis 0:8e36e3d5d706 491 {
mluis 0:8e36e3d5d706 492 break;
mluis 0:8e36e3d5d706 493 }
mluis 0:8e36e3d5d706 494 case MCPS_CONFIRMED:
mluis 0:8e36e3d5d706 495 {
mluis 0:8e36e3d5d706 496 break;
mluis 0:8e36e3d5d706 497 }
mluis 0:8e36e3d5d706 498 case MCPS_PROPRIETARY:
mluis 0:8e36e3d5d706 499 {
mluis 0:8e36e3d5d706 500 break;
mluis 0:8e36e3d5d706 501 }
mluis 0:8e36e3d5d706 502 case MCPS_MULTICAST:
mluis 0:8e36e3d5d706 503 {
mluis 0:8e36e3d5d706 504 break;
mluis 0:8e36e3d5d706 505 }
mluis 0:8e36e3d5d706 506 default:
mluis 0:8e36e3d5d706 507 break;
mluis 0:8e36e3d5d706 508 }
mluis 0:8e36e3d5d706 509
mluis 0:8e36e3d5d706 510 // Check Multicast
mluis 0:8e36e3d5d706 511 // Check Port
mluis 0:8e36e3d5d706 512 // Check Datarate
mluis 0:8e36e3d5d706 513 // Check FramePending
mluis 0:8e36e3d5d706 514 // Check Buffer
mluis 0:8e36e3d5d706 515 // Check BufferSize
mluis 0:8e36e3d5d706 516 // Check Rssi
mluis 0:8e36e3d5d706 517 // Check Snr
mluis 0:8e36e3d5d706 518 // Check RxSlot
mluis 0:8e36e3d5d706 519 LoRaMacDownlinkStatus.Rssi = McpsIndication->Rssi;
mluis 0:8e36e3d5d706 520 if( McpsIndication->Snr & 0x80 ) // The SNR sign bit is 1
mluis 0:8e36e3d5d706 521 {
mluis 0:8e36e3d5d706 522 // Invert and divide by 4
mluis 0:8e36e3d5d706 523 LoRaMacDownlinkStatus.Snr = ( ( ~McpsIndication->Snr + 1 ) & 0xFF ) >> 2;
mluis 0:8e36e3d5d706 524 LoRaMacDownlinkStatus.Snr = -LoRaMacDownlinkStatus.Snr;
mluis 0:8e36e3d5d706 525 }
mluis 0:8e36e3d5d706 526 else
mluis 0:8e36e3d5d706 527 {
mluis 0:8e36e3d5d706 528 // Divide by 4
mluis 0:8e36e3d5d706 529 LoRaMacDownlinkStatus.Snr = ( McpsIndication->Snr & 0xFF ) >> 2;
mluis 0:8e36e3d5d706 530 }
mluis 0:8e36e3d5d706 531 LoRaMacDownlinkStatus.DownlinkCounter++;
mluis 0:8e36e3d5d706 532 LoRaMacDownlinkStatus.RxData = McpsIndication->RxData;
mluis 0:8e36e3d5d706 533 LoRaMacDownlinkStatus.Port = McpsIndication->Port;
mluis 0:8e36e3d5d706 534 LoRaMacDownlinkStatus.Buffer = McpsIndication->Buffer;
mluis 0:8e36e3d5d706 535 LoRaMacDownlinkStatus.BufferSize = McpsIndication->BufferSize;
mluis 0:8e36e3d5d706 536
mluis 0:8e36e3d5d706 537 if( ComplianceTest.Running == true )
mluis 0:8e36e3d5d706 538 {
mluis 0:8e36e3d5d706 539 ComplianceTest.DownLinkCounter++;
mluis 0:8e36e3d5d706 540 }
mluis 0:8e36e3d5d706 541
mluis 0:8e36e3d5d706 542 if( McpsIndication->RxData == true )
mluis 0:8e36e3d5d706 543 {
mluis 0:8e36e3d5d706 544 switch( McpsIndication->Port )
mluis 0:8e36e3d5d706 545 {
mluis 0:8e36e3d5d706 546 case 1: // The application LED can be controlled on port 1 or 2
mluis 0:8e36e3d5d706 547 case 2:
mluis 0:8e36e3d5d706 548 if( McpsIndication->BufferSize == 1 )
mluis 0:8e36e3d5d706 549 {
mluis 0:8e36e3d5d706 550 AppLedStateOn = McpsIndication->Buffer[0] & 0x01;
mluis 0:8e36e3d5d706 551 UsrLedStateChanged = true;
mluis 0:8e36e3d5d706 552 }
mluis 0:8e36e3d5d706 553 break;
mluis 0:8e36e3d5d706 554 case 224:
mluis 0:8e36e3d5d706 555 if( ComplianceTest.Running == false )
mluis 0:8e36e3d5d706 556 {
mluis 0:8e36e3d5d706 557 // Check compliance test enable command (i)
mluis 0:8e36e3d5d706 558 if( ( McpsIndication->BufferSize == 4 ) &&
mluis 0:8e36e3d5d706 559 ( McpsIndication->Buffer[0] == 0x01 ) &&
mluis 0:8e36e3d5d706 560 ( McpsIndication->Buffer[1] == 0x01 ) &&
mluis 0:8e36e3d5d706 561 ( McpsIndication->Buffer[2] == 0x01 ) &&
mluis 0:8e36e3d5d706 562 ( McpsIndication->Buffer[3] == 0x01 ) )
mluis 0:8e36e3d5d706 563 {
mluis 0:8e36e3d5d706 564 IsTxConfirmed = false;
mluis 0:8e36e3d5d706 565 AppPort = 224;
mluis 0:8e36e3d5d706 566 AppDataSize = 2;
mluis 0:8e36e3d5d706 567 ComplianceTest.DownLinkCounter = 0;
mluis 0:8e36e3d5d706 568 ComplianceTest.LinkCheck = false;
mluis 0:8e36e3d5d706 569 ComplianceTest.DemodMargin = 0;
mluis 0:8e36e3d5d706 570 ComplianceTest.NbGateways = 0;
mluis 0:8e36e3d5d706 571 ComplianceTest.Running = true;
mluis 0:8e36e3d5d706 572 ComplianceTest.State = 1;
mluis 0:8e36e3d5d706 573
mluis 0:8e36e3d5d706 574 MibRequestConfirm_t mibReq;
mluis 0:8e36e3d5d706 575 mibReq.Type = MIB_ADR;
mluis 0:8e36e3d5d706 576 mibReq.Param.AdrEnable = true;
mluis 0:8e36e3d5d706 577 LoRaMacMibSetRequestConfirm( &mibReq );
mluis 0:8e36e3d5d706 578
mluis 0:8e36e3d5d706 579 #if defined( USE_BAND_868 )
mluis 0:8e36e3d5d706 580 LoRaMacTestSetDutyCycleOn( false );
mluis 0:8e36e3d5d706 581 #endif
mluis 0:8e36e3d5d706 582 }
mluis 0:8e36e3d5d706 583 }
mluis 0:8e36e3d5d706 584 else
mluis 0:8e36e3d5d706 585 {
mluis 0:8e36e3d5d706 586 ComplianceTest.State = McpsIndication->Buffer[0];
mluis 0:8e36e3d5d706 587 switch( ComplianceTest.State )
mluis 0:8e36e3d5d706 588 {
mluis 0:8e36e3d5d706 589 case 0: // Check compliance test disable command (ii)
mluis 0:8e36e3d5d706 590 IsTxConfirmed = LORAWAN_CONFIRMED_MSG_ON;
mluis 0:8e36e3d5d706 591 AppPort = LORAWAN_APP_PORT;
mluis 0:8e36e3d5d706 592 AppDataSize = LORAWAN_APP_DATA_SIZE;
mluis 0:8e36e3d5d706 593 ComplianceTest.DownLinkCounter = 0;
mluis 0:8e36e3d5d706 594 ComplianceTest.Running = false;
mluis 0:8e36e3d5d706 595
mluis 0:8e36e3d5d706 596 MibRequestConfirm_t mibReq;
mluis 0:8e36e3d5d706 597 mibReq.Type = MIB_ADR;
mluis 0:8e36e3d5d706 598 mibReq.Param.AdrEnable = LORAWAN_ADR_ON;
mluis 0:8e36e3d5d706 599 LoRaMacMibSetRequestConfirm( &mibReq );
mluis 0:8e36e3d5d706 600 #if defined( USE_BAND_868 )
mluis 0:8e36e3d5d706 601 LoRaMacTestSetDutyCycleOn( LORAWAN_DUTYCYCLE_ON );
mluis 0:8e36e3d5d706 602 #endif
mluis 0:8e36e3d5d706 603 break;
mluis 0:8e36e3d5d706 604 case 1: // (iii, iv)
mluis 0:8e36e3d5d706 605 AppDataSize = 2;
mluis 0:8e36e3d5d706 606 break;
mluis 0:8e36e3d5d706 607 case 2: // Enable confirmed messages (v)
mluis 0:8e36e3d5d706 608 IsTxConfirmed = true;
mluis 0:8e36e3d5d706 609 ComplianceTest.State = 1;
mluis 0:8e36e3d5d706 610 break;
mluis 0:8e36e3d5d706 611 case 3: // Disable confirmed messages (vi)
mluis 0:8e36e3d5d706 612 IsTxConfirmed = false;
mluis 0:8e36e3d5d706 613 ComplianceTest.State = 1;
mluis 0:8e36e3d5d706 614 break;
mluis 0:8e36e3d5d706 615 case 4: // (vii)
mluis 0:8e36e3d5d706 616 AppDataSize = McpsIndication->BufferSize;
mluis 0:8e36e3d5d706 617
mluis 0:8e36e3d5d706 618 AppData[0] = 4;
mluis 0:8e36e3d5d706 619 for( uint8_t i = 1; i < AppDataSize; i++ )
mluis 0:8e36e3d5d706 620 {
mluis 0:8e36e3d5d706 621 AppData[i] = McpsIndication->Buffer[i] + 1;
mluis 0:8e36e3d5d706 622 }
mluis 0:8e36e3d5d706 623 break;
mluis 0:8e36e3d5d706 624 case 5: // (viii)
mluis 0:8e36e3d5d706 625 {
mluis 0:8e36e3d5d706 626 MlmeReq_t mlmeReq;
mluis 0:8e36e3d5d706 627 mlmeReq.Type = MLME_LINK_CHECK;
mluis 0:8e36e3d5d706 628 LoRaMacMlmeRequest( &mlmeReq );
mluis 0:8e36e3d5d706 629 }
mluis 0:8e36e3d5d706 630 break;
mluis 0:8e36e3d5d706 631 default:
mluis 0:8e36e3d5d706 632 break;
mluis 0:8e36e3d5d706 633 }
mluis 0:8e36e3d5d706 634 }
mluis 0:8e36e3d5d706 635 break;
mluis 0:8e36e3d5d706 636 default:
mluis 0:8e36e3d5d706 637 break;
mluis 0:8e36e3d5d706 638 }
mluis 0:8e36e3d5d706 639 }
mluis 0:8e36e3d5d706 640
mluis 0:8e36e3d5d706 641 // Switch Yellow LED ON for each received downlink
mluis 0:8e36e3d5d706 642 YellowLedState = true;
mluis 0:8e36e3d5d706 643 YellowLedStateChanged = true;
mluis 0:8e36e3d5d706 644 TimerStart( &YellowLedTimer );
mluis 0:8e36e3d5d706 645 DownlinkStatusUpdated = true;
mluis 0:8e36e3d5d706 646 }
mluis 0:8e36e3d5d706 647
mluis 0:8e36e3d5d706 648 /*!
mluis 0:8e36e3d5d706 649 * \brief MLME-Confirm event function
mluis 0:8e36e3d5d706 650 *
mluis 0:8e36e3d5d706 651 * \param [IN] MlmeConfirm - Pointer to the confirm structure,
mluis 0:8e36e3d5d706 652 * containing confirm attributes.
mluis 0:8e36e3d5d706 653 */
mluis 0:8e36e3d5d706 654 static void MlmeConfirm( MlmeConfirm_t *MlmeConfirm )
mluis 0:8e36e3d5d706 655 {
mluis 0:8e36e3d5d706 656 if( MlmeConfirm->Status == LORAMAC_EVENT_INFO_STATUS_OK )
mluis 0:8e36e3d5d706 657 {
mluis 0:8e36e3d5d706 658 switch( MlmeConfirm->MlmeRequest )
mluis 0:8e36e3d5d706 659 {
mluis 0:8e36e3d5d706 660 case MLME_JOIN:
mluis 0:8e36e3d5d706 661 {
mluis 0:8e36e3d5d706 662 // Status is OK, node has joined the network
mluis 0:8e36e3d5d706 663 IsNetworkJoinedStatusUpdate = true;
mluis 0:8e36e3d5d706 664 break;
mluis 0:8e36e3d5d706 665 }
mluis 0:8e36e3d5d706 666 case MLME_LINK_CHECK:
mluis 0:8e36e3d5d706 667 {
mluis 0:8e36e3d5d706 668 // Check DemodMargin
mluis 0:8e36e3d5d706 669 // Check NbGateways
mluis 0:8e36e3d5d706 670 if( ComplianceTest.Running == true )
mluis 0:8e36e3d5d706 671 {
mluis 0:8e36e3d5d706 672 ComplianceTest.LinkCheck = true;
mluis 0:8e36e3d5d706 673 ComplianceTest.DemodMargin = MlmeConfirm->DemodMargin;
mluis 0:8e36e3d5d706 674 ComplianceTest.NbGateways = MlmeConfirm->NbGateways;
mluis 0:8e36e3d5d706 675 }
mluis 0:8e36e3d5d706 676 break;
mluis 0:8e36e3d5d706 677 }
mluis 0:8e36e3d5d706 678 default:
mluis 0:8e36e3d5d706 679 break;
mluis 0:8e36e3d5d706 680 }
mluis 0:8e36e3d5d706 681 }
mluis 0:8e36e3d5d706 682 NextTx = true;
mluis 0:8e36e3d5d706 683 UplinkStatusUpdated = true;
mluis 0:8e36e3d5d706 684 }
mluis 0:8e36e3d5d706 685
mluis 0:8e36e3d5d706 686 /**
mluis 0:8e36e3d5d706 687 * Main application entry point.
mluis 0:8e36e3d5d706 688 */
mluis 0:8e36e3d5d706 689 int main( void )
mluis 0:8e36e3d5d706 690 {
mluis 0:8e36e3d5d706 691 LoRaMacPrimitives_t LoRaMacPrimitives;
mluis 0:8e36e3d5d706 692 LoRaMacCallback_t LoRaMacCallbacks;
mluis 0:8e36e3d5d706 693 MibRequestConfirm_t mibReq;
mluis 0:8e36e3d5d706 694
mluis 0:8e36e3d5d706 695 BoardInit( );
mluis 0:8e36e3d5d706 696 SerialDisplayInit( );
mluis 0:8e36e3d5d706 697
mluis 0:8e36e3d5d706 698 DeviceState = DEVICE_STATE_INIT;
mluis 0:8e36e3d5d706 699
mluis 0:8e36e3d5d706 700 while( 1 )
mluis 0:8e36e3d5d706 701 {
mluis 0:8e36e3d5d706 702 SerialRxProcess( );
mluis 0:8e36e3d5d706 703 Gps.service( );
mluis 0:8e36e3d5d706 704 if( IsNetworkJoinedStatusUpdate == true )
mluis 0:8e36e3d5d706 705 {
mluis 0:8e36e3d5d706 706 IsNetworkJoinedStatusUpdate = false;
mluis 0:8e36e3d5d706 707 mibReq.Type = MIB_NETWORK_JOINED;
mluis 0:8e36e3d5d706 708 LoRaMacMibGetRequestConfirm( &mibReq );
mluis 0:8e36e3d5d706 709 SerialDisplayUpdateNetworkIsJoined( mibReq.Param.IsNetworkJoined );
mluis 0:8e36e3d5d706 710 }
mluis 0:8e36e3d5d706 711 if( RedLedStateChanged == true )
mluis 0:8e36e3d5d706 712 {
mluis 0:8e36e3d5d706 713 RedLedStateChanged = false;
mluis 0:8e36e3d5d706 714 RedLed = ( RedLedState == true ) ? 0 : 1;
mluis 0:8e36e3d5d706 715 SerialDisplayUpdateLedState( 1, RedLedState );
mluis 0:8e36e3d5d706 716 }
mluis 0:8e36e3d5d706 717 if( YellowLedStateChanged == true )
mluis 0:8e36e3d5d706 718 {
mluis 0:8e36e3d5d706 719 YellowLedStateChanged = false;
mluis 0:8e36e3d5d706 720 YellowLed = ( YellowLedState == true ) ? 0 : 1;
mluis 0:8e36e3d5d706 721 SerialDisplayUpdateLedState( 2, YellowLedState );
mluis 0:8e36e3d5d706 722 }
mluis 0:8e36e3d5d706 723 if( UsrLedStateChanged == true )
mluis 0:8e36e3d5d706 724 {
mluis 0:8e36e3d5d706 725 UsrLedStateChanged = false;
mluis 0:8e36e3d5d706 726 UsrLed = AppLedStateOn;
mluis 0:8e36e3d5d706 727 SerialDisplayUpdateLedState( 3, AppLedStateOn );
mluis 0:8e36e3d5d706 728 }
mluis 0:8e36e3d5d706 729 if( UplinkStatusUpdated == true )
mluis 0:8e36e3d5d706 730 {
mluis 0:8e36e3d5d706 731 UplinkStatusUpdated = false;
mluis 0:8e36e3d5d706 732 SerialDisplayUpdateUplink( LoRaMacUplinkStatus.Acked, LoRaMacUplinkStatus.Datarate, LoRaMacUplinkStatus.UplinkCounter, LoRaMacUplinkStatus.Port, LoRaMacUplinkStatus.Buffer, LoRaMacUplinkStatus.BufferSize );
mluis 0:8e36e3d5d706 733 }
mluis 0:8e36e3d5d706 734 if( DownlinkStatusUpdated == true )
mluis 0:8e36e3d5d706 735 {
mluis 0:8e36e3d5d706 736 DownlinkStatusUpdated = false;
mluis 0:8e36e3d5d706 737 YellowLed = ( YellowLedState == true ) ? 0 : 1;
mluis 0:8e36e3d5d706 738 SerialDisplayUpdateLedState( 2, YellowLedState );
mluis 0:8e36e3d5d706 739 SerialDisplayUpdateDownlink( LoRaMacDownlinkStatus.RxData, LoRaMacDownlinkStatus.Rssi, LoRaMacDownlinkStatus.Snr, LoRaMacDownlinkStatus.DownlinkCounter, LoRaMacDownlinkStatus.Port, LoRaMacDownlinkStatus.Buffer, LoRaMacDownlinkStatus.BufferSize );
mluis 0:8e36e3d5d706 740 }
mluis 0:8e36e3d5d706 741
mluis 0:8e36e3d5d706 742 switch( DeviceState )
mluis 0:8e36e3d5d706 743 {
mluis 0:8e36e3d5d706 744 case DEVICE_STATE_INIT:
mluis 0:8e36e3d5d706 745 {
mluis 0:8e36e3d5d706 746 LoRaMacPrimitives.MacMcpsConfirm = McpsConfirm;
mluis 0:8e36e3d5d706 747 LoRaMacPrimitives.MacMcpsIndication = McpsIndication;
mluis 0:8e36e3d5d706 748 LoRaMacPrimitives.MacMlmeConfirm = MlmeConfirm;
mluis 0:8e36e3d5d706 749 LoRaMacCallbacks.GetBatteryLevel = BoardGetBatteryLevel;
mluis 0:8e36e3d5d706 750 LoRaMacInitialization( &LoRaMacPrimitives, &LoRaMacCallbacks );
mluis 0:8e36e3d5d706 751
mluis 0:8e36e3d5d706 752 TimerInit( &TxNextPacketTimer, OnTxNextPacketTimerEvent );
mluis 0:8e36e3d5d706 753
mluis 0:8e36e3d5d706 754 TimerInit( &RedLedTimer, OnRedLedTimerEvent );
mluis 0:8e36e3d5d706 755 TimerSetValue( &RedLedTimer, 25000 );
mluis 0:8e36e3d5d706 756
mluis 0:8e36e3d5d706 757 TimerInit( &YellowLedTimer, OnYellowLedTimerEvent );
mluis 0:8e36e3d5d706 758 TimerSetValue( &YellowLedTimer, 25000 );
mluis 0:8e36e3d5d706 759
mluis 0:8e36e3d5d706 760 mibReq.Type = MIB_ADR;
mluis 0:8e36e3d5d706 761 mibReq.Param.AdrEnable = LORAWAN_ADR_ON;
mluis 0:8e36e3d5d706 762 LoRaMacMibSetRequestConfirm( &mibReq );
mluis 0:8e36e3d5d706 763
mluis 0:8e36e3d5d706 764 mibReq.Type = MIB_PUBLIC_NETWORK;
mluis 0:8e36e3d5d706 765 mibReq.Param.EnablePublicNetwork = LORAWAN_PUBLIC_NETWORK;
mluis 0:8e36e3d5d706 766 LoRaMacMibSetRequestConfirm( &mibReq );
mluis 0:8e36e3d5d706 767
mluis 0:8e36e3d5d706 768 SerialDisplayUpdateDutyCycle( false );
mluis 0:8e36e3d5d706 769 SerialDisplayUpdateActivationMode( OVER_THE_AIR_ACTIVATION );
mluis 0:8e36e3d5d706 770 SerialDisplayUpdateAdr( LORAWAN_ADR_ON );
mluis 0:8e36e3d5d706 771 SerialDisplayUpdatePublicNetwork( LORAWAN_PUBLIC_NETWORK );
mluis 0:8e36e3d5d706 772
mluis 0:8e36e3d5d706 773 LoRaMacDownlinkStatus.DownlinkCounter = 0;
mluis 0:8e36e3d5d706 774
mluis 0:8e36e3d5d706 775 DeviceState = DEVICE_STATE_JOIN;
mluis 0:8e36e3d5d706 776 break;
mluis 0:8e36e3d5d706 777 }
mluis 0:8e36e3d5d706 778 case DEVICE_STATE_JOIN:
mluis 0:8e36e3d5d706 779 {
mluis 0:8e36e3d5d706 780 #if( OVER_THE_AIR_ACTIVATION != 0 )
mluis 0:8e36e3d5d706 781 MlmeReq_t mlmeReq;
mluis 0:8e36e3d5d706 782
mluis 0:8e36e3d5d706 783 // Initialize LoRaMac device unique ID
mluis 0:8e36e3d5d706 784 BoardGetUniqueId( DevEui );
mluis 0:8e36e3d5d706 785
mluis 0:8e36e3d5d706 786 mlmeReq.Type = MLME_JOIN;
mluis 0:8e36e3d5d706 787
mluis 0:8e36e3d5d706 788 mlmeReq.Req.Join.DevEui = DevEui;
mluis 0:8e36e3d5d706 789 mlmeReq.Req.Join.AppEui = AppEui;
mluis 0:8e36e3d5d706 790 mlmeReq.Req.Join.AppKey = AppKey;
mluis 0:8e36e3d5d706 791
mluis 0:8e36e3d5d706 792 if( NextTx == true )
mluis 0:8e36e3d5d706 793 {
mluis 0:8e36e3d5d706 794 LoRaMacMlmeRequest( &mlmeReq );
mluis 0:8e36e3d5d706 795 }
mluis 0:8e36e3d5d706 796
mluis 0:8e36e3d5d706 797 SerialDisplayUpdateEui( 5, DevEui );
mluis 0:8e36e3d5d706 798 SerialDisplayUpdateEui( 6, AppEui );
mluis 0:8e36e3d5d706 799 SerialDisplayUpdateKey( 7, AppKey );
mluis 0:8e36e3d5d706 800
mluis 0:8e36e3d5d706 801 // Schedule next packet transmission
mluis 0:8e36e3d5d706 802 TxDutyCycleTime = OVER_THE_AIR_ACTIVATION_DUTYCYCLE;
mluis 0:8e36e3d5d706 803 DeviceState = DEVICE_STATE_CYCLE;
mluis 0:8e36e3d5d706 804
mluis 0:8e36e3d5d706 805 #else
mluis 0:8e36e3d5d706 806 // Random seed initialization
mluis 0:8e36e3d5d706 807 srand1( BoardGetRandomSeed( ) );
mluis 0:8e36e3d5d706 808
mluis 0:8e36e3d5d706 809 // Choose a random device address
mluis 0:8e36e3d5d706 810 DevAddr = randr( 0, 0x01FFFFFF );
mluis 0:8e36e3d5d706 811
mluis 0:8e36e3d5d706 812 mibReq.Type = MIB_NET_ID;
mluis 0:8e36e3d5d706 813 mibReq.Param.NetID = LORAWAN_NETWORK_ID;
mluis 0:8e36e3d5d706 814 LoRaMacMibSetRequestConfirm( &mibReq );
mluis 0:8e36e3d5d706 815
mluis 0:8e36e3d5d706 816 mibReq.Type = MIB_DEV_ADDR;
mluis 0:8e36e3d5d706 817 mibReq.Param.DevAddr = DevAddr;
mluis 0:8e36e3d5d706 818 LoRaMacMibSetRequestConfirm( &mibReq );
mluis 0:8e36e3d5d706 819
mluis 0:8e36e3d5d706 820 mibReq.Type = MIB_NWK_SKEY;
mluis 0:8e36e3d5d706 821 mibReq.Param.NwkSKey = NwkSKey;
mluis 0:8e36e3d5d706 822 LoRaMacMibSetRequestConfirm( &mibReq );
mluis 0:8e36e3d5d706 823
mluis 0:8e36e3d5d706 824 mibReq.Type = MIB_APP_SKEY;
mluis 0:8e36e3d5d706 825 mibReq.Param.AppSKey = AppSKey;
mluis 0:8e36e3d5d706 826 LoRaMacMibSetRequestConfirm( &mibReq );
mluis 0:8e36e3d5d706 827
mluis 0:8e36e3d5d706 828 mibReq.Type = MIB_NETWORK_JOINED;
mluis 0:8e36e3d5d706 829 mibReq.Param.IsNetworkJoined = true;
mluis 0:8e36e3d5d706 830 LoRaMacMibSetRequestConfirm( &mibReq );
mluis 0:8e36e3d5d706 831
mluis 0:8e36e3d5d706 832 SerialDisplayUpdateNwkId( LORAWAN_NETWORK_ID );
mluis 0:8e36e3d5d706 833 SerialDisplayUpdateDevAddr( DevAddr );
mluis 0:8e36e3d5d706 834 SerialDisplayUpdateKey( 12, NwkSKey );
mluis 0:8e36e3d5d706 835 SerialDisplayUpdateKey( 13, AppSKey );
mluis 0:8e36e3d5d706 836
mluis 0:8e36e3d5d706 837 DeviceState = DEVICE_STATE_SEND;
mluis 0:8e36e3d5d706 838 #endif
mluis 0:8e36e3d5d706 839 IsNetworkJoinedStatusUpdate = true;
mluis 0:8e36e3d5d706 840 break;
mluis 0:8e36e3d5d706 841 }
mluis 0:8e36e3d5d706 842 case DEVICE_STATE_SEND:
mluis 0:8e36e3d5d706 843 {
mluis 0:8e36e3d5d706 844 if( NextTx == true )
mluis 0:8e36e3d5d706 845 {
mluis 0:8e36e3d5d706 846 SerialDisplayUpdateUplinkAcked( false );
mluis 0:8e36e3d5d706 847 SerialDisplayUpdateDonwlinkRxData( false );
mluis 0:8e36e3d5d706 848 PrepareTxFrame( AppPort );
mluis 0:8e36e3d5d706 849
mluis 0:8e36e3d5d706 850 NextTx = SendFrame( );
mluis 0:8e36e3d5d706 851
mluis 0:8e36e3d5d706 852 // Switch Red LED ON
mluis 0:8e36e3d5d706 853 RedLedState = true;
mluis 0:8e36e3d5d706 854 RedLedStateChanged = true;
mluis 0:8e36e3d5d706 855 TimerStart( &RedLedTimer );
mluis 0:8e36e3d5d706 856 }
mluis 0:8e36e3d5d706 857 if( ComplianceTest.Running == true )
mluis 0:8e36e3d5d706 858 {
mluis 0:8e36e3d5d706 859 // Schedule next packet transmission as soon as possible
mluis 0:8e36e3d5d706 860 TxDutyCycleTime = 1000; // 1 ms
mluis 0:8e36e3d5d706 861 }
mluis 0:8e36e3d5d706 862 else
mluis 0:8e36e3d5d706 863 {
mluis 0:8e36e3d5d706 864 // Schedule next packet transmission
mluis 0:8e36e3d5d706 865 TxDutyCycleTime = APP_TX_DUTYCYCLE + randr( -APP_TX_DUTYCYCLE_RND, APP_TX_DUTYCYCLE_RND );
mluis 0:8e36e3d5d706 866 }
mluis 0:8e36e3d5d706 867 DeviceState = DEVICE_STATE_CYCLE;
mluis 0:8e36e3d5d706 868 break;
mluis 0:8e36e3d5d706 869 }
mluis 0:8e36e3d5d706 870 case DEVICE_STATE_CYCLE:
mluis 0:8e36e3d5d706 871 {
mluis 0:8e36e3d5d706 872 // Schedule next packet transmission
mluis 0:8e36e3d5d706 873 TimerSetValue( &TxNextPacketTimer, TxDutyCycleTime );
mluis 0:8e36e3d5d706 874 TimerStart( &TxNextPacketTimer );
mluis 0:8e36e3d5d706 875
mluis 0:8e36e3d5d706 876 DeviceState = DEVICE_STATE_SLEEP;
mluis 0:8e36e3d5d706 877 break;
mluis 0:8e36e3d5d706 878 }
mluis 0:8e36e3d5d706 879 case DEVICE_STATE_SLEEP:
mluis 0:8e36e3d5d706 880 {
mluis 0:8e36e3d5d706 881 // Wake up through events
mluis 0:8e36e3d5d706 882 break;
mluis 0:8e36e3d5d706 883 }
mluis 0:8e36e3d5d706 884 default:
mluis 0:8e36e3d5d706 885 {
mluis 0:8e36e3d5d706 886 DeviceState = DEVICE_STATE_INIT;
mluis 0:8e36e3d5d706 887 break;
mluis 0:8e36e3d5d706 888 }
mluis 0:8e36e3d5d706 889 }
mluis 0:8e36e3d5d706 890 }
mluis 0:8e36e3d5d706 891 }