Publish Grove Cayenne Spider Test

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