April_12th_San_Jose_LoRa_Bootcamp

Dependencies:   lorawan1v1

Fork of LoRaWAN-grove-cayenne by wayne roberts

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers sensorDemoVT100.cpp Source File

sensorDemoVT100.cpp

00001 /*
00002  / _____)             _              | |
00003 ( (____  _____ ____ _| |_ _____  ____| |__
00004  \____ \| ___ |    (_   _) ___ |/ ___)  _ \
00005  _____) ) ____| | | || |_| ____( (___| | | |
00006 (______/|_____)_|_|_| \__)_____)\____)_| |_|
00007     (C)2018 Semtech
00008 
00009 Description: LoRaMac classB device implementation
00010 
00011 License: Revised BSD License, see LICENSE.TXT file include in the project
00012 
00013 */
00014 
00015 #include "LoRaMac1v1.h"
00016 #include "SerialDisplay.h"
00017 #include "LoRaMacString.h"
00018 #ifdef ENABLE_VT100
00019 
00020 /*!
00021  * Defines the application data transmission duty cycle. 5s, value in [ms].
00022  */
00023 #define APP_TX_DUTYCYCLE_us                            8000000
00024 
00025 /*!
00026  * Defines a random delay for application data transmission duty cycle. 1s,
00027  * value in [ms].
00028  */
00029 #define APP_TX_DUTYCYCLE_RND_us                        2000000
00030 
00031 /*!
00032  * Default datarate
00033  */
00034 
00035 #if defined( USE_BAND_ARIB_8CH )
00036     #define LORAWAN_DEFAULT_DATARATE                    DR_3
00037 #else
00038     #define LORAWAN_DEFAULT_DATARATE                    DR_0
00039 #endif
00040 
00041 /*!
00042  * LoRaWAN confirmed messages
00043  */
00044 #define LORAWAN_CONFIRMED_MSG_ON                    false
00045 
00046 /*!
00047  * LoRaWAN Adaptive Data Rate
00048  *
00049  * \remark Please note that when ADR is enabled the end-device should be static
00050  */
00051 #define LORAWAN_ADR_ON                              1
00052 
00053 #if defined( USE_BAND_868 )
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                            2
00082 
00083 /*!
00084  * User application data buffer size
00085  */
00086 #define LORAWAN_APP_DATA_SIZE                       3
00087 
00088 
00089 #ifdef LORAWAN_JOIN_EUI
00090     static uint8_t DevEui[] = LORAWAN_DEVICE_EUI;
00091     static const uint8_t JoinEui[] = LORAWAN_JOIN_EUI;
00092     static const uint8_t NwkKey[] = LORAWAN_ROOT_NWKKEY;
00093     #ifdef LORAWAN_ROOT_APPKEY
00094         static const uint8_t AppKey[] = LORAWAN_ROOT_APPKEY;
00095     #endif
00096 #else
00097     static const uint8_t FNwkSIntKey[] = LORAWAN_FNwkSIntKey;
00098     static const uint8_t AppSKey[] = LORAWAN_APPSKEY;
00099     static const uint32_t DevAddr = LORAWAN_DEVICE_ADDRESS;
00100     #if defined(LORAWAN_SNwkSIntKey) && defined(LORAWAN_NwkSEncKey)
00101         static const uint8_t SNwkSIntKey[] = LORAWAN_SNwkSIntKey;
00102         static const uint8_t NwkSEncKey[] = LORAWAN_NwkSEncKey;
00103     #endif
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 gAppDataSize = 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 gIsTxConfirmed = LORAWAN_CONFIRMED_MSG_ON;
00130 
00131 /*!
00132  * Timer to handle the application data transmission duty cycle
00133  *
00134  */
00135 LowPowerTimeout tx_timeout;
00136 
00137 /*!
00138  * Indicates if a new packet can be sent
00139  */
00140 static volatile struct {
00141     uint8_t gmi : 1;
00142     uint8_t gmc : 1;
00143 } flags;
00144 
00145 /*!
00146  * Device states
00147  */
00148 volatile enum eDevicState
00149 {
00150     /* 0 */ DEVICE_STATE_INIT = 0,
00151     /* 1 */ DEVICE_STATE_SEND, 
00152     /* 2 */ DEVICE_STATE_TRIGGER,
00153     /* 3 */ DEVICE_STATE_SLEEP,
00154 #ifdef LORAWAN_JOIN_EUI
00155     /* 4 */ DEVICE_STATE_JOIN,
00156     /* 5 */ DEVICE_STATE_JOIN_OK
00157 #endif /* LORAWAN_JOIN_EUI */
00158 } DeviceState, WakeUpState;
00159 
00160 #if defined(TARGET_MOTE_L152RC) && !defined(TARGET_FF_ARDUINO)
00161     #define TARGET_FF_ARDUINO
00162 #endif
00163 
00164 #if defined(TARGET_FF_ARDUINO)
00165 InterruptIn d8(D8);
00166 DigitalOut extLed(D15);
00167 #endif /* TARGET_FF_ARDUINO */
00168 
00169 #if defined(TARGET_FF_MORPHO) && !defined(TARGET_DISCO_L072CZ_LRWAN1)
00170     #define JUMPER_ENABLE
00171 #endif /* */
00172 
00173 #ifdef JUMPER_ENABLE
00174     #define TX_INTERVAL_US      15000000 
00175     DigitalOut jumper_out(PC_10);
00176     InterruptIn jumper_in(PC_12);
00177 #endif /* JUMPER_ENABLE */
00178 
00179 uint8_t c_ch;
00180 us_timestamp_t buttonStartAt;
00181 #ifdef TARGET_DISCO_L072CZ_LRWAN1
00182 PwmOut pwm(PA_0);
00183 #elif defined(TARGET_FF_ARDUINO)
00184 PwmOut pwm(PB_11);
00185 #endif /* TARGET_DISCO_L072CZ_LRWAN1 */
00186 volatile int cayenne_ack_ch;
00187 
00188 /*!
00189  * LoRaWAN compliance tests support data
00190  */
00191 struct ComplianceTest_s
00192 {
00193     bool Running;
00194     uint8_t State;
00195     bool IsTxConfirmed;
00196     uint8_t AppPort;
00197     uint8_t AppDataSize;
00198     uint8_t *AppDataBuffer;
00199     uint16_t DownLinkCounter;
00200     bool LinkCheck;
00201     uint8_t DemodMargin;
00202     uint8_t NbGateways;
00203 }ComplianceTest;
00204 
00205 McpsIndication_t gmi;
00206 
00207 McpsConfirm_t gmc;
00208 
00209 #ifdef JUMPER_ENABLE
00210 void autoUplink()
00211 {
00212     if (jumper_in.read() == 1) {
00213         tx_timeout.attach_us(autoUplink, TX_INTERVAL_US);
00214     }
00215 
00216     c_ch = 0xff;
00217     DeviceState = DEVICE_STATE_SEND;
00218 }
00219 
00220 void jumper_callback()
00221 {
00222     tx_timeout.attach_us(autoUplink, TX_INTERVAL_US);
00223 }
00224 #endif /* JUMPER_ENABLE */
00225 
00226 static void
00227 clearIndications()
00228 {
00229     vt.SetCursorPos(ROW_MCPS_CONF, 1);
00230     vt.printf("\e[K");
00231     vt.SetCursorPos(ROW_MCPS_IND, 1);
00232     vt.printf("\e[K");
00233     vt.SetCursorPos(ROW_MLME_IND, 1);
00234     vt.printf("\e[K");
00235     vt.SetCursorPos(ROW_MLME_CONF, 1);
00236     vt.printf("\e[K");
00237 
00238     vt.SetCursorPos(ROW_MIC+3, 1);
00239     vt.printf("\e[K");
00240 }
00241 
00242 #define LPP_DIGITAL_INPUT       0       // 1 byte
00243 #define LPP_DIGITAL_OUTPUT      1       // 1 byte
00244 #define LPP_ANALOG_INPUT        2       // 2 bytes, 0.01 signed
00245 #define LPP_ANALOG_OUTPUT       3       // 2 bytes, 0.01 signed
00246 #define LPP_LUMINOSITY          101     // 2 bytes, 1 lux unsigned
00247 #define LPP_PRESENCE            102     // 1 byte, 1
00248 #define LPP_TEMPERATURE         103     // 2 bytes, 0.1°C signed
00249 #define LPP_RELATIVE_HUMIDITY   104     // 1 byte, 0.5% unsigned
00250 #define LPP_ACCELEROMETER       113     // 2 bytes per axis, 0.001G
00251 #define LPP_BAROMETRIC_PRESSURE 115     // 2 bytes 0.1 hPa Unsigned
00252 #define LPP_GYROMETER           134     // 2 bytes per axis, 0.01 °/s
00253 #define LPP_GPS                 136     // 3 byte lon/lat 0.0001 °, 3 bytes alt 0.01m
00254 
00255 
00256 // Data ID + Data Type + Data Size
00257 #define LPP_DIGITAL_INPUT_SIZE       3
00258 #define LPP_DIGITAL_OUTPUT_SIZE      3
00259 #define LPP_ANALOG_INPUT_SIZE        4
00260 #define LPP_ANALOG_OUTPUT_SIZE       4
00261 #define LPP_LUMINOSITY_SIZE          4
00262 #define LPP_PRESENCE_SIZE            3
00263 #define LPP_TEMPERATURE_SIZE         4
00264 #define LPP_RELATIVE_HUMIDITY_SIZE   3
00265 #define LPP_ACCELEROMETER_SIZE       8
00266 #define LPP_BAROMETRIC_PRESSURE_SIZE 4
00267 #define LPP_GYROMETER_SIZE           8
00268 #define LPP_GPS_SIZE                 11
00269 
00270 #define CAYENNE_CH_DOUT     2
00271 #define CAYENNE_CH_AOUT     3
00272 #define CAYENNE_CH_TEMP     0
00273 #define CAYENNE_CH_POT      1
00274 #define CAYENNE_CH_DIN      4
00275 
00276 AnalogIn a1(A1);
00277 AnalogIn a3(A3);
00278 
00279 const unsigned R0 = 100000;
00280 const unsigned B = 4275;
00281 volatile bool dout_downlink;
00282 
00283 /*!
00284  * \brief   Prepares the payload of the frame
00285  */
00286 static void PrepareTxFrame( uint8_t port )
00287 {
00288     uint16_t u16, rot;
00289     float t, f, R;
00290     static uint8_t seq;
00291 
00292     if (c_ch != 0xff) {
00293         gAppDataSize = 0;
00294         AppData[gAppDataSize++] = c_ch;
00295         switch (c_ch) {
00296             case CAYENNE_CH_TEMP:
00297                 AppData[gAppDataSize++] = LPP_TEMPERATURE;
00298                 u16 = a3.read_u16() >> 4;
00299                 R = 4096.0 / u16 - 1.0;
00300                 R = R0 * R;
00301                 t = 1.0/(log(R/R0)/B+1/298.15)-273.15;
00302                 u16 = t * 10;  // 0.1C per bit
00303                 AppData[gAppDataSize++] = u16 >> 8;
00304                 AppData[gAppDataSize++] = u16;
00305                 break;
00306             case CAYENNE_CH_POT:
00307                 AppData[gAppDataSize++] = LPP_ANALOG_INPUT;
00308                 u16 = a1.read_u16();    // pot (rotary angle)
00309                 f = u16 / 198.6;    // scale 65535/3.3 to 0.01v per bit
00310                 rot = (uint16_t) f;
00311                 AppData[gAppDataSize++] = rot >> 8;
00312                 AppData[gAppDataSize++] = rot;
00313                 break;
00314             case CAYENNE_CH_DOUT:
00315                 AppData[gAppDataSize++] = LPP_DIGITAL_OUTPUT;
00316                 AppData[gAppDataSize++] = extLed.read();
00317                 break;
00318             case CAYENNE_CH_AOUT:
00319                 AppData[gAppDataSize++] = LPP_ANALOG_OUTPUT;
00320                 u16 = pwm.read() * 100;
00321                 AppData[gAppDataSize++] = u16 >> 8;
00322                 AppData[gAppDataSize++] = u16;
00323                 break;
00324         }
00325         return;
00326     } else if (cayenne_ack_ch != -1) {
00327         switch (cayenne_ack_ch) {
00328             case CAYENNE_CH_DOUT:
00329                 AppData[gAppDataSize++] = LPP_DIGITAL_OUTPUT;
00330                 AppData[gAppDataSize++] = extLed.read();
00331                 break;
00332             case CAYENNE_CH_AOUT:
00333                 AppData[gAppDataSize++] = LPP_ANALOG_OUTPUT;
00334                 u16 = pwm.read() * 100;
00335                 AppData[gAppDataSize++] = u16 >> 8;
00336                 AppData[gAppDataSize++] = u16;
00337                 break;
00338         }
00339         cayenne_ack_ch = -1;
00340     }
00341 
00342     while (d8.read() == 1) {
00343         us_timestamp_t duration = LoRaMacReadTimer() - buttonStartAt;
00344         if (duration > 1000000) {
00345             gAppDataSize = 0;
00346             AppData[gAppDataSize++] = CAYENNE_CH_DOUT;
00347             AppData[gAppDataSize++] = LPP_DIGITAL_OUTPUT;
00348             AppData[gAppDataSize++] = extLed.read();
00349             return;
00350         }
00351     }
00352 
00353     switch( port ) {
00354         case LORAWAN_APP_PORT:
00355             gAppDataSize = 0;
00356             AppData[gAppDataSize++] = CAYENNE_CH_TEMP;
00357             AppData[gAppDataSize++] = LPP_TEMPERATURE;
00358             u16 = a3.read_u16() >> 4;
00359             R = 4096.0 / u16 - 1.0;
00360             R = R0 * R;
00361             t = 1.0/(log(R/R0)/B+1/298.15)-273.15;
00362             u16 = t * 10;  // 0.1C per bit
00363             AppData[gAppDataSize++] = u16 >> 8;
00364             AppData[gAppDataSize++] = u16;
00365             AppData[gAppDataSize++] = CAYENNE_CH_POT;
00366             AppData[gAppDataSize++] = LPP_ANALOG_INPUT;
00367             u16 = a1.read_u16();    // pot (rotary angle)
00368             f = u16 / 198.6;    // scale 65535/3.3 to 0.01v per bit
00369             rot = (uint16_t) f;
00370             AppData[gAppDataSize++] = rot >> 8;
00371             AppData[gAppDataSize++] = rot;
00372 
00373             /* limited packet size: either ack downlink, or send sequence number */
00374             if (dout_downlink) {
00375                 AppData[gAppDataSize++] = CAYENNE_CH_DOUT;
00376                 AppData[gAppDataSize++] = LPP_DIGITAL_OUTPUT;
00377                 AppData[gAppDataSize++] = extLed.read();
00378                 dout_downlink = false;
00379             } else {
00380                 AppData[gAppDataSize++] = CAYENNE_CH_DIN;
00381                 AppData[gAppDataSize++] = LPP_DIGITAL_INPUT;
00382                 AppData[gAppDataSize++] = seq++;
00383             }
00384             break;
00385         case 224:
00386             if( ComplianceTest.LinkCheck == true ) {
00387                 ComplianceTest.LinkCheck = false;
00388                 gAppDataSize = 3;
00389                 AppData[0] = 5;
00390                 AppData[1] = ComplianceTest.DemodMargin;
00391                 AppData[2] = ComplianceTest.NbGateways;
00392                 ComplianceTest.State = 1;
00393             } else {
00394                 switch( ComplianceTest.State ) {
00395                     case 4:
00396                         ComplianceTest.State = 1;
00397                         break;
00398                     case 1:
00399                         gAppDataSize = 2;
00400                         AppData[0] = ComplianceTest.DownLinkCounter >> 8;
00401                         AppData[1] = ComplianceTest.DownLinkCounter;
00402                         break;
00403                 }
00404             }
00405             break;
00406         default:
00407             break;
00408     }
00409 }
00410 
00411 
00412 /*!
00413  * \brief   Prepares the payload of the frame
00414  *
00415  * \retval  [0: frame could be send, 1: error]
00416  */
00417 static LoRaMacStatus_t SendFrame(bool IsTxConfirmed, uint8_t AppDataSize)
00418 {
00419     LoRaMacStatus_t status;
00420     char str[64];
00421     McpsReq_t mcpsReq;
00422     LoRaMacTxInfo_t txInfo;
00423     
00424     if( LoRaMacQueryTxPossible( AppDataSize, &txInfo ) != LORAMAC_STATUS_OK )
00425     {
00426         // Send empty frame in order to flush MAC commands
00427         mcpsReq.Type = MCPS_UNCONFIRMED;
00428         mcpsReq.Req.fBuffer = NULL;
00429         mcpsReq.Req.fBufferSize = 0;
00430         mcpsReq.Req.Datarate = LORAWAN_DEFAULT_DATARATE;
00431     }
00432     else
00433     {
00434         SerialDisplayUpdateFrameType(IsTxConfirmed);
00435         if( IsTxConfirmed == false )
00436         {
00437             mcpsReq.Type = MCPS_UNCONFIRMED;
00438             mcpsReq.Req.fPort = AppPort;
00439             mcpsReq.Req.fBuffer = AppData;
00440             mcpsReq.Req.fBufferSize = AppDataSize;
00441             mcpsReq.Req.Datarate = LORAWAN_DEFAULT_DATARATE;
00442         }
00443         else
00444         {
00445             mcpsReq.Type = MCPS_CONFIRMED;
00446             mcpsReq.Req.fPort = AppPort;
00447             mcpsReq.Req.fBuffer = AppData;
00448             mcpsReq.Req.fBufferSize = AppDataSize;
00449             mcpsReq.Req.Datarate = LORAWAN_DEFAULT_DATARATE;
00450         }
00451     }
00452 
00453     clearIndications();
00454     status = LoRaMacMcpsRequest( &mcpsReq );
00455     if (status == LORAMAC_STATUS_OK) {
00456         SerialDisplayUplink(mcpsReq.Req.fPort, AppData, mcpsReq.Req.fBufferSize);
00457         vt.SetCursorPos( ROW_END, 1 );
00458         vt.printf("sendFrame() OK %u\e[K", AppDataSize);
00459     } else {
00460         LoRaMacStatus_to_string(status, str);
00461         vt.SetCursorPos( ROW_END, 1 );
00462         vt.printf("sendFrame() %s rx%d\e[K", str, LoRaMacGetRxSlot());
00463     }
00464 
00465     return status;
00466 } // ..SendFrame()
00467 
00468 /*!
00469  * \brief   MCPS-Confirm event function
00470  *
00471  * \param   [IN] mcpsConfirm - Pointer to the confirm structure,
00472  *               containing confirm attributes.
00473  */
00474 static void McpsConfirm( const McpsConfirm_t *mcpsConfirm )
00475 {
00476     char str[64];
00477 
00478     vt.SetCursorPos( ROW_MCPS_CONF, 1);
00479     vt.printf("McpsConfirm up:%uhz ", mcpsConfirm->UpLinkFreqHz);
00480     LoRaMacEventInfoStatus_to_string(mcpsConfirm->Status, str);
00481     if (mcpsConfirm->Status == LORAMAC_EVENT_INFO_STATUS_OK)
00482         vt.printf("%s \e[K", str);
00483     else
00484         vt.printf("\e[31m%s\e[0m \e[K", str);
00485 
00486     if (mcpsConfirm->Status == LORAMAC_EVENT_INFO_STATUS_OK)
00487     {
00488         switch( mcpsConfirm->McpsRequest )
00489         {
00490             case MCPS_UNCONFIRMED:
00491             {
00492                 // Check Datarate
00493                 // Check TxPower
00494                 break;
00495             }
00496             case MCPS_CONFIRMED:
00497             {
00498                 // Check Datarate
00499                 // Check TxPower
00500                 // Check AckReceived
00501                 // Check NbTrials
00502                 //LoRaMacUplinkStatus.Acked = mcpsConfirm->AckReceived;
00503                 break;
00504             }
00505             case MCPS_PROPRIETARY:
00506             {
00507                 break;
00508             }
00509             default:
00510                 break;
00511         }
00512     } else {
00513         /* fail */
00514     }
00515     memcpy(&gmc, mcpsConfirm, sizeof(McpsConfirm_t));
00516     flags.gmc = true;
00517 
00518     DeviceState = DEVICE_STATE_TRIGGER;
00519 } // ..McpsConfirm()
00520 
00521 
00522 /*!
00523  * \brief   MCPS-Indication event function
00524  *
00525  * \param   [IN] mcpsIndication - Pointer to the indication structure,
00526  *               containing indication attributes.
00527  */
00528 static void McpsIndication( const McpsIndication_t *mcpsIndication )
00529 {
00530     char str[64];
00531 
00532     memcpy(&gmi, mcpsIndication, sizeof(McpsIndication_t));
00533     flags.gmi = true;
00534 
00535     vt.SetCursorPos(ROW_MCPS_CONF, 1);
00536     vt.printf("\e[K");  // clear stale mcpsconf if retrying
00537 
00538     vt.SetCursorPos( ROW_MCPS_IND, 0);
00539     vt.printf("McpsIndication rx%d ADR_ACK_CNT:%u ", mcpsIndication->RxSlot, mcpsIndication->ADR_ACK_CNT);
00540     if (mcpsIndication->Status != LORAMAC_EVENT_INFO_STATUS_OK)
00541     {
00542         LoRaMacEventInfoStatus_to_string(mcpsIndication->Status, str);
00543         vt.printf("\e[31m%s\e[0m\e[K", str);
00544         return;
00545     }
00546     vt.printf("OK\e[K");
00547 
00548     switch( mcpsIndication->McpsIndication )
00549     {
00550         case MCPS_UNCONFIRMED:
00551         {
00552             break;
00553         }
00554         case MCPS_CONFIRMED:
00555         {
00556             /* ack sent by mac layer */
00557             break;
00558         }
00559         case MCPS_PROPRIETARY:
00560         {
00561             break;
00562         }
00563         case MCPS_MULTICAST:
00564         {
00565             break;
00566         }
00567         default:
00568             break;
00569     }
00570 
00571     // Check Multicast
00572     // Check Port
00573     // Check Datarate
00574     // Check FramePending
00575     // Check Buffer
00576     // Check BufferSize
00577     // Check Rssi
00578     // Check Snr
00579     // Check RxSlot
00580 
00581 
00582     if( ComplianceTest.Running == true )
00583     {
00584         ComplianceTest.DownLinkCounter++;
00585     }
00586 
00587     if( mcpsIndication->RxData == true )
00588     {
00589         unsigned n;
00590         for (n = 0; n < mcpsIndication->BufferSize; n += 4) {
00591             uint16_t val = mcpsIndication->Buffer[n+1] << 8;
00592             val += mcpsIndication->Buffer[n+2];
00593             cayenne_ack_ch = mcpsIndication->Buffer[n];
00594             switch (mcpsIndication->Buffer[n]) {
00595                 case CAYENNE_CH_DOUT:
00596                     extLed.write(val);
00597                     dout_downlink = true;
00598                     break;
00599                 case CAYENNE_CH_AOUT:
00600                     pwm.write(val / 100.0);
00601                     break;
00602                 default:
00603                     break;
00604             }
00605         }
00606 
00607         switch( mcpsIndication->Port )
00608         {
00609         case 1: // The application LED can be controlled on port 1 or 2
00610         case 2:
00611             break;
00612         case 224:
00613             if( ComplianceTest.Running == false )
00614             {
00615                 // Check compliance test enable command (i)
00616                 if( ( mcpsIndication->BufferSize == 4 ) &&
00617                     ( mcpsIndication->Buffer[0] == 0x01 ) &&
00618                     ( mcpsIndication->Buffer[1] == 0x01 ) &&
00619                     ( mcpsIndication->Buffer[2] == 0x01 ) &&
00620                     ( mcpsIndication->Buffer[3] == 0x01 ) )
00621                 {
00622                     gIsTxConfirmed = false;
00623                     AppPort = 224;
00624                     gAppDataSize = 2;
00625                     ComplianceTest.DownLinkCounter = 0;
00626                     ComplianceTest.LinkCheck = false;
00627                     ComplianceTest.DemodMargin = 0;
00628                     ComplianceTest.NbGateways = 0;
00629                     ComplianceTest.Running = true;
00630                     ComplianceTest.State = 1;
00631                     
00632                     MibRequestConfirm_t mibReq;
00633                     mibReq.Type = MIB_ADR;
00634                     mibReq.Param.AdrEnable = true;
00635                     LoRaMacMibSetRequestConfirm( &mibReq );
00636 
00637 #if defined( USE_BAND_868 )
00638                     DutyCycleOn = false;
00639 #endif
00640                 }
00641             }
00642             else
00643             {
00644                 ComplianceTest.State = mcpsIndication->Buffer[0];
00645                 switch( ComplianceTest.State )
00646                 {
00647                 case 0: // Check compliance test disable command (ii)
00648                     gIsTxConfirmed = LORAWAN_CONFIRMED_MSG_ON;
00649                     AppPort = LORAWAN_APP_PORT;
00650                     gAppDataSize = LORAWAN_APP_DATA_SIZE;
00651                     ComplianceTest.DownLinkCounter = 0;
00652                     ComplianceTest.Running = false;
00653 
00654                     MibRequestConfirm_t mibReq;
00655                     mibReq.Type = MIB_ADR;
00656                     mibReq.Param.AdrEnable = LORAWAN_ADR_ON;
00657                     LoRaMacMibSetRequestConfirm( &mibReq );
00658 #if defined( USE_BAND_868 )
00659                     DutyCycleOn = LORAWAN_DUTYCYCLE_ON;
00660 #endif
00661                     break;
00662                 case 1: // (iii, iv)
00663                     gAppDataSize = 2;
00664                     break;
00665                 case 2: // Enable confirmed messages (v)
00666                     gIsTxConfirmed = true;
00667                     ComplianceTest.State = 1;
00668                     break;
00669                 case 3:  // Disable confirmed messages (vi)
00670                     gIsTxConfirmed = false;
00671                     ComplianceTest.State = 1;
00672                     break;
00673                 case 4: // (vii)
00674                     gAppDataSize = mcpsIndication->BufferSize;
00675 
00676                     AppData[0] = 4;
00677                     for( uint8_t i = 1; i < gAppDataSize; i++ )
00678                     {
00679                         AppData[i] = mcpsIndication->Buffer[i] + 1;
00680                     }
00681                     break;
00682                 case 5: // (viii)
00683                     {
00684                         MlmeReq_t mlmeReq;
00685                         mlmeReq.Type = MLME_LINK_CHECK;
00686                         LoRaMacMlmeRequest( &mlmeReq );
00687                     }
00688                     break;
00689                 case 6: // (ix)
00690                     {
00691 #ifdef LORAWAN_JOIN_EUI
00692                         MlmeReq_t mlmeReq = {};
00693 
00694                         // Disable TestMode and revert back to normal operation
00695                         gIsTxConfirmed = LORAWAN_CONFIRMED_MSG_ON;
00696                         AppPort = LORAWAN_APP_PORT;
00697                         gAppDataSize = LORAWAN_APP_DATA_SIZE;
00698                         ComplianceTest.DownLinkCounter = 0;
00699                         ComplianceTest.Running = false;
00700 
00701                         MibRequestConfirm_t mibReq;
00702                         mibReq.Type = MIB_ADR;
00703                         mibReq.Param.AdrEnable = LORAWAN_ADR_ON;
00704                         LoRaMacMibSetRequestConfirm( &mibReq );
00705 #if defined( USE_BAND_868 )
00706                         DutyCycleOn = LORAWAN_DUTYCYCLE_ON;
00707 #endif
00708 
00709                         mlmeReq.Type = MLME_JOIN;
00710 
00711                         mlmeReq.Req.Join.DevEui = DevEui;
00712                         mlmeReq.Req.Join.JoinEui = JoinEui;
00713                         mlmeReq.Req.Join.NwkKey = NwkKey;
00714     #ifdef LORAWAN_ROOT_APPKEY
00715                         mlmeReq.Req.Join.AppKey = AppKey;
00716     #endif /* LORAWAN_ROOT_APPKEY */
00717 
00718                         LoRaMacMlmeRequest( &mlmeReq );
00719 #endif /* LORAWAN_JOIN_EUI */
00720                         DeviceState = DEVICE_STATE_SLEEP;
00721                     }
00722                     break;
00723                 case 7: // Switch end device Class
00724                     {
00725                         MlmeReq_t mlmeReq;
00726 
00727                         mlmeReq.Type = MLME_SWITCH_CLASS;
00728 
00729                         // CLASS_A = 0, CLASS_B = 1, CLASS_C = 2
00730                         mlmeReq.Req.SwitchClass.Class = ( DeviceClass_t )mcpsIndication->Buffer[1];
00731 
00732                         LoRaMacMlmeRequest( &mlmeReq );
00733 
00734                         PrepareTxFrame( AppPort );
00735                         /*status =*/ SendFrame(gIsTxConfirmed, gAppDataSize);
00736                     }
00737                     break;
00738                 case 8: // Send PingSlotInfoReq
00739                     {
00740                         MlmeReq_t mlmeReq;
00741 
00742                         mlmeReq.Type = MLME_PING_SLOT_INFO;
00743 
00744                         mlmeReq.Req.PingSlotInfo.Value = mcpsIndication->Buffer[1];
00745 
00746                         LoRaMacMlmeRequest( &mlmeReq );
00747                         PrepareTxFrame( AppPort );
00748                         /*status =*/ SendFrame(gIsTxConfirmed, gAppDataSize);
00749                     }
00750                     break;
00751                 case 9: // Send BeaconTimingReq
00752                     {
00753                         MlmeReq_t mlmeReq;
00754 
00755                         mlmeReq.Type = MLME_BEACON_TIMING;
00756 
00757                         LoRaMacMlmeRequest( &mlmeReq );
00758                         PrepareTxFrame( AppPort );
00759                         /*status =*/ SendFrame(gIsTxConfirmed, gAppDataSize);
00760                     }
00761                     break;
00762                 default:
00763                     break;
00764                 }
00765             }
00766             break;
00767         default:
00768             break;
00769         }
00770 
00771     }
00772 
00773 } // ..McpsIndication()
00774 
00775 #ifdef LORAWAN_JOIN_EUI 
00776 void
00777 join(uint8_t tries)
00778 {
00779     char str[64];
00780     LoRaMacStatus_t status;
00781     MlmeReq_t mlmeReq = { };
00782 
00783     mlmeReq.Type = MLME_JOIN;
00784 
00785     clearIndications();
00786 #ifdef LORAWAN_ROOT_APPKEY
00787     mlmeReq.Req.Join.AppKey = AppKey;
00788 #endif
00789     mlmeReq.Req.Join.DevEui = DevEui;
00790     mlmeReq.Req.Join.JoinEui = JoinEui;
00791     mlmeReq.Req.Join.NwkKey = NwkKey;
00792     mlmeReq.Req.Join.NbTrials = tries;
00793     status = LoRaMacMlmeRequest( &mlmeReq );
00794     if (status != LORAMAC_STATUS_OK) {
00795         LoRaMacStatus_to_string(status, str);
00796     } else
00797         extLed = 1;
00798 }
00799 #endif /* LORAWAN_JOIN_EUI */
00800 
00801 /*!
00802  * \brief   MLME-Confirm event function
00803  *
00804  * \param   [IN] mlmeConfirm - Pointer to the confirm structure,
00805  *               containing confirm attributes.
00806  */
00807 static void MlmeConfirm( const MlmeConfirm_t *mlmeConfirm )
00808 {
00809     char str[64];
00810     static uint8_t failCnt = 0;
00811 
00812     vt.SetCursorPos(ROW_MLME_CONF, 1);
00813     Mlme_to_string(mlmeConfirm->MlmeRequest, str);
00814     vt.printf("MlmeConfirm %s ", str);
00815     LoRaMacEventInfoStatus_to_string(mlmeConfirm->Status, str);
00816     if (mlmeConfirm->Status != LORAMAC_EVENT_INFO_STATUS_OK)
00817         vt.printf("\e[31m%s \e[0m \e[K", str);
00818     else
00819         vt.printf("%s \e[K", str);
00820 
00821 #if defined(LORAWAN_ROOT_APPKEY) && defined(LORAWAN_JOIN_EUI)
00822     /* 1v1 joinNonce is incrementing non-volatile value */
00823     if (mlmeConfirm->MlmeRequest == MLME_JOIN) {
00824         vt.printf(" rxJoinNonce:%u vs %u", 
00825             mlmeConfirm->fields.join.rxJoinNonce,
00826             mlmeConfirm->fields.join.myJoinNonce
00827         );
00828     }
00829 #endif /* LORAWAN_ROOT_APPKEY */
00830 
00831     if (mlmeConfirm->Status == LORAMAC_EVENT_INFO_STATUS_OK)
00832     {
00833         failCnt = 0;
00834         switch (mlmeConfirm->MlmeRequest)
00835         {
00836 #ifdef LORAWAN_JOIN_EUI
00837             case MLME_JOIN:
00838             {
00839                 // Status is OK, node has joined the network
00840                 /* collect any mac cmds from server until expected channel mask */
00841                 extLed = 0;
00842                 DeviceState = DEVICE_STATE_JOIN_OK;
00843                 break;
00844             }
00845 #endif /* LORAWAN_JOIN_EUI*/
00846             case MLME_LINK_CHECK:
00847             {
00848                 // Check DemodMargin
00849                 // Check NbGateways
00850                 if( ComplianceTest.Running == true )
00851                 {
00852                     ComplianceTest.LinkCheck = true;
00853                     ComplianceTest.DemodMargin = mlmeConfirm->fields.link.DemodMargin;
00854                     ComplianceTest.NbGateways = mlmeConfirm->fields.link.NbGateways;
00855                 }
00856                 break;
00857             }
00858             case MLME_TIME_REQ:
00859                 break;
00860             default:
00861                 /* TODO: handle unknown MLME request */
00862                 DeviceState = DEVICE_STATE_SLEEP;
00863                 break;
00864         }
00865     }
00866     else    // not ok...
00867     {
00868         failCnt++;
00869 
00870 #ifdef LORAWAN_JOIN_EUI
00871         if (failCnt > 5) {
00872             join(1);
00873             return;
00874         }
00875 #endif
00876 
00877         switch( mlmeConfirm->MlmeRequest )
00878         {
00879 #ifdef LORAWAN_JOIN_EUI
00880             case MLME_JOIN:
00881             {
00882                 // Join failed, restart join procedure
00883                 break;
00884             }
00885 #endif /* LORAWAN_JOIN_EUI */
00886             case MLME_LINK_CHECK:
00887                 DeviceState = DEVICE_STATE_SLEEP;
00888                 break;
00889 #ifdef LORAWAN_JOIN_EUI
00890             case MLME_REJOIN_0:
00891                 break;
00892             case MLME_REJOIN_2:
00893                 break;
00894             case MLME_TIME_REQ:
00895                 break;
00896 #endif /* LORAWAN_JOIN_EUI */
00897             default:
00898                 DeviceState = DEVICE_STATE_SLEEP;
00899                 break;
00900         }
00901     }
00902 } // ..MlmeConfirm
00903 
00904 static void MlmeIndication( const MlmeIndication_t *MlmeIndication )
00905 {
00906     char str[48];
00907     MibRequestConfirm_t mibReq;
00908 
00909     vt.SetCursorPos(ROW_MLME_IND, 1);
00910     Mlme_to_string(MlmeIndication->MlmeIndication, str);
00911     vt.printf("MlmeIndication %s %08x ", str, RCC->CSR);
00912     LoRaMacEventInfoStatus_to_string(MlmeIndication->Status, str);
00913     if (MlmeIndication->Status != LORAMAC_EVENT_INFO_STATUS_OK)
00914         vt.printf("\e[31m%s \e[0m \e[K", str);
00915     else
00916         vt.printf("%s \e[K", str);
00917 
00918     switch( MlmeIndication->MlmeIndication )
00919     {
00920         case MLME_SWITCH_CLASS:
00921         {
00922             /* mac gave up on beacon */
00923             mibReq.Type = MIB_DEVICE_CLASS;
00924             mibReq.Param.Class = CLASS_A;
00925             LoRaMacMibSetRequestConfirm( &mibReq );
00926 
00927             // Switch to class A again
00928             DeviceState = DEVICE_STATE_SLEEP;    // class-B manual switch
00929             break;
00930         }
00931         case MLME_BEACON:
00932         {
00933             LoRaMacEventInfoStatus_to_string(MlmeIndication->Status, str);
00934             break;
00935 
00936         }
00937 #ifdef LORAWAN_JOIN_EUI
00938         case MLME_JOIN:
00939             vt.printf("%uhz try%u", MlmeIndication->freqHz, MlmeIndication->JoinRequestTrials);
00940             break;
00941 #endif /* !LORAWAN_JOIN_EUI  */
00942         default:
00943             break;
00944     }
00945 
00946 } // ..MlmeIndication()
00947 
00948 uint8_t periodicity;
00949 
00950 void SerialDisplayRefresh( void )
00951 {
00952 #ifdef LORAWAN_JOIN_EUI
00953     MibRequestConfirm_t mibReq;
00954 #endif
00955 
00956     SerialDisplayInit( );
00957 #ifdef LORAWAN_JOIN_EUI
00958     SerialDisplayUpdateActivationMode(true);
00959     SerialDisplayUpdateEui( ROW_DEVEUI, DevEui);
00960     SerialDisplayUpdateEui( ROW_JOINEUI, JoinEui);
00961     SerialDisplayUpdateKey( ROW_NWKKEY, NwkKey);
00962 
00963     #ifdef LORAWAN_ROOT_APPKEY
00964     SerialDisplayUpdateKey(ROW_APPKEY, AppKey);
00965     #endif
00966 
00967     mibReq.Type = MIB_NETWORK_JOINED;
00968     LoRaMacMibGetRequestConfirm( &mibReq );
00969     SerialDisplayUpdateNetworkIsJoined( mibReq.Param.IsNetworkJoined );
00970 #else
00971     //SerialDisplayUpdateNwkId( LORAWAN_NETWORK_ID );
00972     SerialDisplayUpdateDevAddr( DevAddr );
00973     SerialDisplayUpdateKey( ROW_FNwkSIntKey, FNwkSIntKey);
00974     SerialDisplayUpdateKey( ROW_AppSKey, AppSKey );
00975     #if defined(LORAWAN_SNwkSIntKey) && defined(LORAWAN_NwkSEncKey)
00976     SerialDisplayUpdateKey(ROW_NwkSEncKey, NwkSEncKey);
00977     SerialDisplayUpdateKey(ROW_SNwkSIntKey, SNwkSIntKey);
00978     #endif /* 1v1 ABP */
00979 
00980     vt.SetCursorPos( ROW_END, 1 );
00981     vt.printf("FCntUp:%08x", eeprom_read(EEPROM_FCNTUP));
00982     vt.printf(" AFCntDown:%08x", get_fcntdwn(true));
00983     vt.printf(" NFCntDown:%08x", get_fcntdwn(false));
00984 #endif
00985 
00986 
00987     SerialDisplayUpdateAdr( LORAWAN_ADR_ON );
00988 #if defined( USE_BAND_868 )
00989     SerialDisplayUpdateDutyCycle( LORAWAN_DUTYCYCLE_ON );
00990 #else
00991     SerialDisplayUpdateDutyCycle( false );
00992 #endif
00993     SerialDisplayUpdatePublicNetwork( LORAWAN_PUBLIC_NETWORK );
00994 
00995     //SerialDisplayUpdateLedState( 3, AppLedStateOn );
00996 }
00997 
00998 void SerialRxProcess( void )
00999 {
01000     LoRaMacStatus_t status;
01001     MlmeReq_t mlmeReq;
01002 #ifndef LORAWAN_JOIN_EUI
01003     static uint8_t icnt = 0;
01004 #endif
01005     
01006     if( SerialDisplayReadable( ) == true ) {
01007         char ch = SerialDisplayGetChar();
01008 #ifndef LORAWAN_JOIN_EUI
01009         if (ch == 'I') {
01010             if (++icnt == 3) {
01011                 vt.SetCursorPos( ROW_END, 1 );
01012                 vt.printf("reset-fcnts\e[K");
01013                 eeprom_clear(EEPROM_AFCNTDWN);
01014                 eeprom_clear(EEPROM_NFCNTDWN);
01015                 eeprom_clear(EEPROM_FCNTUP);
01016             }
01017         } else
01018             icnt = 0;
01019 #endif /* !LORAWAN_JOIN_EUI */
01020 
01021         if ( ch >= '0' && ch <= '9') {
01022             c_ch = ch - '0';
01023             DeviceState = DEVICE_STATE_SEND;
01024             return;
01025         }
01026         switch( ch ) {
01027             case 'R':
01028             case 'r':
01029                 // Refresh Serial screen
01030                 SerialDisplayRefresh( );
01031                 break;
01032             case 'L':
01033                 clearIndications();
01034                 mlmeReq.Type = MLME_LINK_CHECK;
01035                 status = LoRaMacMlmeRequest( &mlmeReq );
01036                 if (status == LORAMAC_STATUS_OK)
01037                     SendFrame(0, false);
01038                 break;
01039 #ifdef LORAWAN_JOIN_EUI
01040             case 'j':
01041                 DeviceState = DEVICE_STATE_JOIN;
01042                 break;
01043 #endif
01044             default:
01045                 break;
01046         }
01047     }
01048 }
01049 
01050 static void d8isr()
01051 {
01052     c_ch = 0xff;
01053     DeviceState = DEVICE_STATE_SEND;
01054     buttonStartAt = LoRaMacReadTimer();
01055 }
01056 
01057 static const LoRaMacPrimitives_t LoRaMacPrimitives = {
01058     McpsConfirm,
01059     McpsIndication,
01060     MlmeConfirm,
01061     MlmeIndication
01062 };
01063 
01064 static const LoRaMacCallback_t LoRaMacCallbacks = {
01065     BoardGetBatteryLevel,
01066     NULL
01067 };
01068 
01069 /**
01070  * Main application entry point.
01071  */
01072 int main()
01073 {
01074     LoRaMacStatus_t status;
01075     MibRequestConfirm_t mibReq;
01076 
01077     DeviceState = DEVICE_STATE_INIT;
01078 
01079     if (sleep_manager_can_deep_sleep())
01080         sleep_manager_lock_deep_sleep();    // prevent deep sleep
01081 
01082 #ifdef JUMPER_ENABLE
01083     jumper_out = 1;
01084     jumper_in.mode(PullDown);
01085     jumper_in.rise(jumper_callback);
01086     // Q: does InterruptIn.rise() call immediately if already high?
01087     if (jumper_in.read())
01088         jumper_callback(); // A: probably not
01089 #endif /* JUMPER_ENABLE */
01090 
01091     while( 1 )
01092     {
01093         SerialRxProcess( );
01094 
01095         if (flags.gmi) {
01096             flags.gmi = false;
01097             SerialDisplayMcpsIndication(&gmi);
01098         }
01099 
01100         if (flags.gmc) {
01101             flags.gmc = false;
01102             SerialDisplayMcpsConfirm(&gmc);
01103         }
01104 
01105         switch( DeviceState )
01106         {
01107             case DEVICE_STATE_INIT:
01108             {
01109                 status = LoRaMacInitialization( &LoRaMacPrimitives, &LoRaMacCallbacks );
01110                 if (LORAMAC_STATUS_OK != status) {
01111                     char str[48];
01112                     LoRaMacStatus_to_string(status, str);
01113                     vt.SetCursorPos(1, 1);
01114                     vt.printf("MacInit: %s\e[K", str);
01115                     for (;;) asm("nop");
01116                 }
01117                 
01118                 pwm.period(1.0 / 60);
01119                 cayenne_ack_ch = -1;
01120                 c_ch = 0xff;
01121                 d8.mode(PullDown);                
01122                 d8.rise(d8isr);
01123 
01124                 mibReq.Type = MIB_ADR;
01125                 mibReq.Param.AdrEnable = LORAWAN_ADR_ON;
01126                 LoRaMacMibSetRequestConfirm( &mibReq );
01127 
01128                 mibReq.Type = MIB_PUBLIC_NETWORK;
01129                 mibReq.Param.EnablePublicNetwork = LORAWAN_PUBLIC_NETWORK;
01130                 LoRaMacMibSetRequestConfirm( &mibReq );
01131 
01132 #if defined( USE_BAND_868 )
01133                 DutyCycleOn = LORAWAN_DUTYCYCLE_ON ;
01134 #if( USE_SEMTECH_DEFAULT_CHANNEL_LINEUP == 1 ) 
01135                 LoRaMacChannelAdd( 3, ( ChannelParams_t )LC4 );
01136                 LoRaMacChannelAdd( 4, ( ChannelParams_t )LC5 );
01137                 LoRaMacChannelAdd( 5, ( ChannelParams_t )LC6 );
01138                 LoRaMacChannelAdd( 6, ( ChannelParams_t )LC7 );
01139                 LoRaMacChannelAdd( 7, ( ChannelParams_t )LC8 );
01140                 LoRaMacChannelAdd( 8, ( ChannelParams_t )LC9 );
01141                 LoRaMacChannelAdd( 9, ( ChannelParams_t )LC10 );
01142 
01143                 mibReq.Type = MIB_RX2_CHANNEL;
01144                 mibReq.Param.Rx2Channel = ( Rx2ChannelParams_t ){ 869525000, DR_3 };
01145                 LoRaMacMibSetRequestConfirm( &mibReq );
01146 #endif
01147 
01148 #endif
01149 
01150                 SerialDisplayRefresh();
01151 #ifdef LORAWAN_JOIN_EUI
01152 
01153     #ifndef SENETCO /* for senet, use network provided DevEUI */
01154                 // Initialize LoRaMac device unique ID
01155                 //HardwareIDtoDevEUI(DevEui);   Comment to assign your Own DevEUI, Uncomment to assign based on device serail number
01156     #ifdef LORAWAN_ROOT_APPKEY
01157                 // inverted DevEui provisioned as v1.1 on server (non-inv = lorawan1v0)
01158                 for (int i = 0; i < 8; i++)
01159                     DevEui[i] ^= 0xff;
01160     #endif /* LORAWAN_ROOT_APPKEY */
01161     #endif /* !SENETCO */
01162                 SerialDisplayUpdateEui( 5, DevEui );
01163                 DeviceState = DEVICE_STATE_JOIN;
01164 #else   /* ABP... */
01165 
01166                 mibReq.Type = MIB_DEV_ADDR;
01167                 mibReq.Param.DevAddr = DevAddr;
01168                 LoRaMacMibSetRequestConfirm( &mibReq );
01169                 SerialDisplayUpdateDevAddr(DevAddr);
01170 
01171                 mibReq.Type = MIB_APP_SKEY;
01172                 mibReq.Param.key = AppSKey;
01173                 LoRaMacMibSetRequestConfirm( &mibReq );
01174                 SerialDisplayUpdateKey(ROW_AppSKey, AppSKey);
01175 
01176     #if defined(LORAWAN_SNwkSIntKey) && defined(LORAWAN_NwkSEncKey)
01177                 /* lorawan 1v1 ABP */
01178                 mibReq.Type = MIB_NwkSEncKey;
01179                 mibReq.Param.key = NwkSEncKey;
01180                 LoRaMacMibSetRequestConfirm( &mibReq );
01181                 SerialDisplayUpdateKey(ROW_NwkSEncKey, NwkSEncKey);
01182 
01183                 mibReq.Type = MIB_SNwkSIntKey;
01184                 mibReq.Param.key = SNwkSIntKey;
01185                 LoRaMacMibSetRequestConfirm( &mibReq );
01186                 SerialDisplayUpdateKey(ROW_SNwkSIntKey, SNwkSIntKey);
01187 
01188                 mibReq.Type = MIB_FNwkSIntKey;
01189                 mibReq.Param.key = FNwkSIntKey;
01190                 LoRaMacMibSetRequestConfirm( &mibReq );
01191                 SerialDisplayUpdateKey(ROW_FNwkSIntKey, mibReq.Param.key);
01192     #else
01193                 /* lorawan 1v0 ABP */
01194                 mibReq.Type = MIB_NwkSKey;
01195                 mibReq.Param.key = FNwkSIntKey;
01196                 LoRaMacMibSetRequestConfirm( &mibReq );
01197                 SerialDisplayUpdateKey(ROW_FNwkSIntKey, mibReq.Param.key);
01198     #endif
01199 
01200                 DeviceState = DEVICE_STATE_TRIGGER;
01201 #endif /* !LORAWAN_JOIN_EUI */
01202                 break;
01203             }
01204 #ifdef LORAWAN_JOIN_EUI
01205             case DEVICE_STATE_JOIN:
01206             {
01207                 join(8);
01208                 DeviceState = DEVICE_STATE_SLEEP;
01209                 break;
01210             }
01211             case DEVICE_STATE_JOIN_OK:
01212                 MibRequestConfirm_t mibReq;
01213                 mibReq.Type = MIB_NETWORK_JOINED;
01214                 LoRaMacMibGetRequestConfirm( &mibReq );
01215                 SerialDisplayUpdateNetworkIsJoined( mibReq.Param.IsNetworkJoined );
01216                 mibReq.Type = MIB_DEV_ADDR;
01217                 LoRaMacMibGetRequestConfirm( &mibReq );
01218                 SerialDisplayUpdateDevAddr(mibReq.Param.DevAddr);
01219                 mibReq.Type = MIB_FNwkSIntKey;
01220                 LoRaMacMibGetRequestConfirm( &mibReq );
01221                 SerialDisplayUpdateKey( ROW_FNwkSIntKey, mibReq.Param.key );
01222                 mibReq.Type = MIB_APP_SKEY;
01223                 LoRaMacMibGetRequestConfirm( &mibReq );
01224                 SerialDisplayUpdateKey( ROW_AppSKey,  mibReq.Param.key );
01225 
01226     #ifdef LORAWAN_ROOT_APPKEY
01227                 mibReq.Type = MIB_SNwkSIntKey;
01228                 LoRaMacMibGetRequestConfirm( &mibReq );
01229                 SerialDisplayUpdateKey(ROW_SNwkSIntKey,  mibReq.Param.key);
01230                 mibReq.Type = MIB_NwkSEncKey;
01231                 LoRaMacMibGetRequestConfirm( &mibReq );
01232                 SerialDisplayUpdateKey(ROW_NwkSEncKey,  mibReq.Param.key);
01233     #endif /* LORAWAN_ROOT_APPKEY */
01234                 DeviceState = DEVICE_STATE_TRIGGER;
01235                 break;
01236 #endif /* LORAWAN_JOIN_EUI */
01237             case DEVICE_STATE_SEND:
01238                 SerialDisplayUpdateUplinkAcked( false );
01239                 SerialDisplayUpdateDonwlinkRxData( false );
01240                 PrepareTxFrame( AppPort );
01241                 status = SendFrame(gIsTxConfirmed, gAppDataSize);
01242                 if (status == LORAMAC_STATUS_OK) {
01243                     /* McpsConfirm or McpsIndication callback will continue */
01244                     DeviceState = DEVICE_STATE_SLEEP;
01245                 } else
01246                     DeviceState = DEVICE_STATE_TRIGGER;
01247                 break;
01248             case DEVICE_STATE_SLEEP:
01249             {
01250                 // Wake up through events
01251                 sleep_manager_sleep_auto();
01252                 break;
01253             }
01254             case DEVICE_STATE_TRIGGER:
01255                 /* wait button ISR */
01256                 sleep_manager_sleep_auto();
01257                 break;
01258             default:
01259                 DeviceState = DEVICE_STATE_INIT;
01260                 break;
01261         } // ..switch( DeviceState )
01262 
01263         LoRaMacUserContext();
01264     } // ..while( 1 )
01265 }
01266 #endif /* ENABLE_VT100 */