Bootcamp_Final

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