The NSL01 library contains all functions for controlling the NSL01 LoRaWAN shield from mCloud System GmbH. The NSL01 is a professional plug & play LoRaWAN shield for a wide range of STM32 Nucleo-64 boards with Arduino Uno Rev 3 connectivity. For more information about the NSL01 LoRaWAN shield: http://www.mcloud-systems.com/nsl01-lorawan-nucleo-arduino-shield

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers NSL01.cpp Source File

NSL01.cpp

00001 /*******************************************************************************
00002 //  Class for controlling NSL01 LoRaWAN shield from mCloud Systems GmbH
00003 //
00004 //  For more information about the NSL01 LoRaWAN shield:
00005 //      http://www.mcloud-systems.com/nsl01-lorawan-nucleo-arduino-shield
00006 //
00007 //  @author  mCloud Systems Team
00008 //  @version 1.0
00009 //  @date    20-June-2018
00010 //
00011 //  @attention  
00012 //
00013 //  Copyright (c) 2018 mCloud Systems GmbH, MIT License
00014 //
00015 //  Permission is hereby granted, free of charge, to any person obtaining a copy 
00016 //  of this software and associated documentation files (the "Software"), to deal
00017 //  in the Software without restriction, including without limitation the rights 
00018 //  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
00019 //  copies of the Software, and to permit persons to whom the Software is
00020 //  furnished to do so, subject to the following conditions:
00021 //
00022 //  The above copyright notice and this permission notice shall be included in
00023 //  all copies or substantial portions of the Software.
00024 //
00025 //  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
00026 //  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
00027 //  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
00028 //  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
00029 //  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 
00030 //  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
00031 //  SOFTWARE.
00032 *******************************************************************************/
00033 
00034 //------------------------------------------------------------------------------
00035 //
00036 // Include Files
00037 //
00038 //------------------------------------------------------------------------------
00039 
00040 #include "mbed.h"
00041 #include "NSL01.h"
00042 #include <string.h>
00043 #include <stdio.h>
00044 
00045 #define MAKEWORD(lo,hi) ((lo)|((hi) << 8))
00046 #define MAKELONG(lo,hi) ((lo)|((hi) << 16))
00047 
00048 //------------------------------------------------------------------------------
00049 //
00050 // Initialize internal functions and variables
00051 //
00052 //------------------------------------------------------------------------------
00053 
00054 //--Flag to control response from LoRa module
00055 bool flag_LoRaWAN_response = false;
00056 
00057 //------------------------------------------------------------------------------
00058 //
00059 //  Section RAM
00060 //
00061 //------------------------------------------------------------------------------
00062 
00063 //--Reserve one Tx-Message
00064 TWiMOD_HCI_Message TxMessage;
00065 
00066 //--Reserve one Rx-Message
00067 TWiMOD_HCI_Message RxMessage;
00068 
00069 //------------------------------------------------------------------------------
00070 //
00071 //  Section Const
00072 //
00073 //------------------------------------------------------------------------------
00074 
00075 //--Status Codes for DeviceMgmt Response Messages
00076 static const TIDString DeviceMgmt_StatusStrings[] =
00077 {
00078     { DEVMGMT_STATUS_OK,                   "ok" },
00079     { DEVMGMT_STATUS_ERROR,                "error" } ,
00080     { DEVMGMT_STATUS_CMD_NOT_SUPPORTED,    "command not supported" },
00081     { DEVMGMT_STATUS_WRONG_PARAMETER,      "wrong parameter" },
00082     { DEVMGMT_STATUS_WRONG_DEVICE_MODE,    "wrong device mode" },
00083 
00084     //--End of table
00085     { 0, 0 }
00086 };
00087 
00088 //--Status Codes for LoRaWAN Response Messages
00089 static const TIDString LoRaWAN_StatusStrings[] =
00090 {
00091     { LORAWAN_STATUS_OK,                    "ok" },
00092     { LORAWAN_STATUS_ERROR,                 "error" } ,
00093     { LORAWAN_STATUS_CMD_NOT_SUPPORTED,     "command not supported" },
00094     { LORAWAN_STATUS_WRONG_PARAMETER,       "wrong parameter" },
00095     { LORAWAN_STATUS_WRONG_DEVICE_MODE,     "wrong device mode" },
00096     { LORAWAN_STATUS_NOT_ACTIVATED,         "device not activated" },
00097     { LORAWAN_STATUS_BUSY,                  "device busy - command rejected" },
00098     { LORAWAN_STATUS_QUEUE_FULL,            "message queue full - command rejected" },
00099     { LORAWAN_STATUS_LENGTH_ERROR,          "HCI message length error" },
00100     { LORAWAN_STATUS_NO_FACTORY_SETTINGS,   "no factory settings available" },
00101     { LORAWAN_STATUS_CHANNEL_BLOCKED_BY_DC, "channel blocked by duty cycle" },
00102     { LORAWAN_STATUS_CHANNEL_NOT_AVAILABLE, "channel not available" },
00103 
00104     // end of table
00105     { 0, 0 }
00106 };
00107 
00108 //------------------------------------------------------------------------------
00109 //
00110 //  Constructor of NSL01:
00111 //
00112 //  @brief  Create a NSL01 instance with the serial device objects specified in
00113 //          main.
00114 //
00115 //------------------------------------------------------------------------------
00116 
00117 NSL01::NSL01(void)
00118 {  
00119     //--Wait for power-up LoRa module
00120     wait(2.0);
00121     
00122     //--Initialize NSL01 and open serial (UART) device
00123     initialize();
00124 }
00125 
00126 //------------------------------------------------------------------------------
00127 //
00128 //  Destructor of NSL01:
00129 //
00130 //  @brief  Destroy instance
00131 //
00132 //------------------------------------------------------------------------------
00133 
00134 NSL01::~NSL01() {}
00135 
00136 //------------------------------------------------------------------------------
00137 //
00138 //  Public method for device management: ping
00139 //
00140 //  @brief  Ping NSL01 device.
00141 //
00142 //  @returns 1 on success, -1 on error
00143 //
00144 //------------------------------------------------------------------------------
00145 
00146 int NSL01::ping(void)
00147 {
00148     // 1. Init header
00149     TxMessage.SapID     = DEVMGMT_SAP_ID;
00150     TxMessage.MsgID     = DEVMGMT_MSG_PING_REQ;
00151     TxMessage.Length    = 0;
00152     
00153     comm_pc.printf("\r\nPing request: ");
00154     
00155     // 2. Send HCI message without payload
00156     int return_value = WiMOD_HCI_SendMessage(&TxMessage);
00157     
00158     // 3. Wait until any response from LoRa module
00159     LoRaWAN_wait();
00160     
00161     return return_value;
00162 }
00163 
00164 //------------------------------------------------------------------------------
00165 //
00166 //  Public method for device management: reset
00167 //
00168 //  @brief  Reset NSL01 device (Software reset).
00169 //
00170 //  @note  After executing this command the module will be restarted after
00171 //  approximately 200ms!
00172 //
00173 //  @returns 1 on success, -1 on error
00174 //
00175 //------------------------------------------------------------------------------
00176 
00177 int NSL01::reset(void)
00178 {
00179     // 1. Init header
00180     TxMessage.SapID     = DEVMGMT_SAP_ID;
00181     TxMessage.MsgID     = DEVMGMT_MSG_RESET_REQ;
00182     TxMessage.Length    = 0;
00183     
00184     comm_pc.printf("\r\nSoftware reset request: ");
00185     
00186     // 2. Send HCI message without payload
00187     int return_value = WiMOD_HCI_SendMessage(&TxMessage);
00188     
00189     // 3. Wait until any response from LoRa module
00190     LoRaWAN_wait();
00191     
00192     return return_value;    
00193 }
00194 
00195 //------------------------------------------------------------------------------
00196 //
00197 //  Public method for device management: get_device_info
00198 //
00199 //  @brief  Method to identify the local connected NSL01 device. As a result the
00200 //          device sends a response message which contains all necessary device 
00201 //          information.
00202 //
00203 //  @returns 1 on success, -1 on error
00204 //
00205 //------------------------------------------------------------------------------
00206 
00207 int NSL01::get_device_info(void)
00208 {
00209     // 1. Init header
00210     TxMessage.SapID     = DEVMGMT_SAP_ID;
00211     TxMessage.MsgID     = DEVMGMT_MSG_GET_DEVICE_INFO_REQ;
00212     TxMessage.Length    = 0;
00213 
00214     comm_pc.printf("\r\nGet device information: ");
00215 
00216     // 2. Send HCI message without payload
00217     int return_value = WiMOD_HCI_SendMessage(&TxMessage);
00218     
00219     // 3. Wait until any response from LoRa module
00220     LoRaWAN_wait();
00221     
00222     return return_value;
00223 }
00224 
00225 //------------------------------------------------------------------------------
00226 //
00227 //  Public method for device management: get_firmware_info
00228 //
00229 //  @brief  Method to identify the onboard radio firmware of NSL01. As a result
00230 //          the device sends a response message which contains all firmware 
00231 //          related data.
00232 //
00233 //  @returns 1 on success, -1 on error
00234 //
00235 //------------------------------------------------------------------------------
00236 
00237 int NSL01::get_firmware_info(void)
00238 {
00239     // 1. Init header
00240     TxMessage.SapID     = DEVMGMT_SAP_ID;
00241     TxMessage.MsgID     = DEVMGMT_MSG_GET_FW_VERSION_REQ;
00242     TxMessage.Length    = 0;
00243 
00244     comm_pc.printf("\r\nGet firmware information: ");
00245 
00246     // 2. Send HCI message without payload
00247     int return_value = WiMOD_HCI_SendMessage(&TxMessage);
00248     
00249     // 3. Wait until any response from LoRa module
00250     LoRaWAN_wait();
00251 
00252     return return_value;
00253 }
00254 
00255 //------------------------------------------------------------------------------
00256 //
00257 //  Public method for device management: get_device_status
00258 //
00259 //  @brief  Method to get the current device status of NSL01. As a result the
00260 //          device sends a response message which contains all device status
00261 //          information.
00262 //
00263 //  @returns 1 on success, -1 on error
00264 //
00265 //------------------------------------------------------------------------------
00266 
00267 int NSL01::get_device_status(void)
00268 {
00269     // 1. Init header
00270     TxMessage.SapID     = DEVMGMT_SAP_ID;
00271     TxMessage.MsgID     = DEVMGMT_MSG_GET_DEVICE_STATUS_REQ;
00272     TxMessage.Length    = 0;
00273 
00274     comm_pc.printf("\r\nGet device status: ");
00275 
00276     // 2. Send HCI message without payload
00277     int return_value = WiMOD_HCI_SendMessage(&TxMessage);
00278     
00279     // 3. Wait until any response from LoRa module
00280     LoRaWAN_wait();
00281 
00282     return return_value;
00283 }
00284 
00285 //------------------------------------------------------------------------------
00286 //
00287 //  Public method for device management: get_network_status
00288 //
00289 //  @brief  Method to read the current network / activation status of NSL01.
00290 //
00291 //  @returns 1 on success, -1 on error
00292 //
00293 //------------------------------------------------------------------------------
00294 
00295 int NSL01::get_network_status(void)
00296 {
00297     // 1. Init header
00298     TxMessage.SapID     = LORAWAN_SAP_ID;
00299     TxMessage.MsgID     = LORAWAN_MSG_GET_NWK_STATUS_REQ;
00300     TxMessage.Length    = 0;
00301 
00302     comm_pc.printf("\r\nGet network activation status: ");
00303 
00304     // 2. Send HCI message without payload
00305     int return_value = WiMOD_HCI_SendMessage(&TxMessage);
00306 
00307     // 3. Wait until any response from LoRa module
00308     LoRaWAN_wait();
00309 
00310     return return_value;
00311 }
00312 
00313 //------------------------------------------------------------------------------
00314 //
00315 //  Public method for device management: get_RTC_info
00316 //
00317 //  @brief  Method to read the current Real Time Clock (RTC) value of NSL01.
00318 //
00319 //  @returns 1 on success, -1 on error
00320 //
00321 //------------------------------------------------------------------------------
00322 
00323 int NSL01::get_RTC_info(void)
00324 {
00325     // 1. Init header
00326     TxMessage.SapID     = DEVMGMT_SAP_ID;
00327     TxMessage.MsgID     = DEVMGMT_MSG_GET_RTC_REQ;
00328     TxMessage.Length    = 0;
00329 
00330     comm_pc.printf("\r\nGet RTC info: ");
00331 
00332     // 2. Send HCI message without payload
00333     int return_value = WiMOD_HCI_SendMessage(&TxMessage);
00334 
00335     // 3. Wait until any response from LoRa module
00336     LoRaWAN_wait();
00337 
00338     return return_value;
00339 }
00340 
00341 //------------------------------------------------------------------------------
00342 //
00343 //  Public method for device management: set_RTC
00344 //
00345 //  @brief  Method to set the Real Time Clock (RTC) value of NSL01.
00346 //
00347 //  @param RTC_data defined in RTC_struct
00348 //
00349 //  @returns 1 on success, -1 on error
00350 //
00351 //------------------------------------------------------------------------------
00352 
00353 int NSL01::set_RTC(RTC_struct RTC_data)
00354 {
00355     //--Internal variables and constants
00356     UINT32 result_UINT32 = 0;
00357     
00358     // 1. Init header
00359     TxMessage.SapID     = DEVMGMT_SAP_ID;
00360     TxMessage.MsgID     = DEVMGMT_MSG_SET_RTC_REQ;
00361     TxMessage.Length    = 4;
00362 
00363     //--Prepare RTC info
00364     result_UINT32 = (UINT32)(((RTC_data.year - 2000) & 0x3f) << 26 | (RTC_data.day & 0x1f) << 21 | 
00365                               (RTC_data.hour & 0x1f) << 16 | (RTC_data.month & 0xf) << 12 | 
00366                               (RTC_data.minute & 0x3f) << 6 | (RTC_data.second & 0x1f));
00367 
00368     //--Convert RTC info (LSB first)     
00369     unsigned char *s = (unsigned char *)&result_UINT32;
00370     UINT32 result_conversion = (UINT32)(s[0] << 24 | s[1] << 16 | s[2] << 8 | s[3]);    
00371     TxMessage.Payload[0]= s[0];
00372     TxMessage.Payload[1]= s[1];
00373     TxMessage.Payload[2]= s[2];
00374     TxMessage.Payload[3]= s[3];    
00375     
00376     comm_pc.printf("\r\nSet RTC: ");
00377     
00378     // 2. Send HCI message with payload
00379     int return_value = WiMOD_HCI_SendMessage(&TxMessage);
00380     
00381     // 3. Wait until any response from LoRa module
00382     LoRaWAN_wait();
00383 
00384     return return_value;    
00385 }
00386 
00387 //------------------------------------------------------------------------------
00388 //
00389 //  Public method for device management: set_RTC_alarm
00390 //
00391 //  @brief  Method to set the Real Time Clock (RTC) alarm of NSL01.
00392 //
00393 //  @param RTC_alarm_data defined in RTC_alarm_struct
00394 //
00395 //  @returns 1 on success, -1 on error
00396 //
00397 //------------------------------------------------------------------------------
00398 
00399 int NSL01::set_RTC_alarm(RTC_alarm_struct RTC_alarm_data)
00400 {
00401     // 1. Init header
00402     TxMessage.SapID     = DEVMGMT_SAP_ID;
00403     TxMessage.MsgID     = DEVMGMT_MSG_SET_RTC_ALARM_REQ;
00404     TxMessage.Length    = 4;
00405     
00406     #ifdef DEBUG
00407         comm_pc.printf("\r\nAlarm period: %d\r\n",RTC_alarm_data.period);
00408         comm_pc.printf("Alarm hour: %u\r\n",RTC_alarm_data.hour);
00409         comm_pc.printf("Alarm minutes: %u\r\n",RTC_alarm_data.minute);
00410         comm_pc.printf("Alarm seconds: %u\r\n",RTC_alarm_data.second);
00411     #endif
00412     
00413     comm_pc.printf("\r\nSet RTC alarm: "); 
00414     
00415     //2. Check input parameters
00416     if (!((RTC_alarm_data.periodic == true) || (RTC_alarm_data.periodic == false)))
00417     {
00418         comm_pc.printf("Error - No valid data for alarm period\r\n");
00419         return -1;
00420     }
00421     
00422     if (((int)RTC_alarm_data.hour < 0) || (RTC_alarm_data.hour > 23))
00423     {
00424         comm_pc.printf("Error - No valid data for alarm hour\r\n");
00425         return -1;
00426     }
00427     
00428     if (((int)RTC_alarm_data.minute < 0) || (RTC_alarm_data.minute > 59))
00429     {
00430         comm_pc.printf("Error - No valid data for alarm minute\r\n");
00431         return -1;
00432     }
00433     
00434     if (((int)RTC_alarm_data.second < 0) || (RTC_alarm_data.second > 59))
00435     {
00436         comm_pc.printf("Error - No valid data for alarm second\r\n");
00437         return -1;
00438     }
00439     
00440     // 3. Prepare payload
00441     TxMessage.Payload[0] = RTC_alarm_data.periodic;
00442     TxMessage.Payload[1] = RTC_alarm_data.hour;
00443     TxMessage.Payload[2] = RTC_alarm_data.minute;
00444     TxMessage.Payload[3] = RTC_alarm_data.second;
00445     
00446     // 4. Send HCI message with payload
00447     int return_value = WiMOD_HCI_SendMessage(&TxMessage);
00448     
00449     // 5. Wait until any response from LoRa module
00450     LoRaWAN_wait();
00451 
00452     return return_value;
00453 }
00454 
00455 //------------------------------------------------------------------------------
00456 //
00457 //  Public method for device management: get_RTC_alarm
00458 //
00459 //  @brief  Method to get the Real Time Clock (RTC) alarm info of NSL01.
00460 //
00461 //  @returns 1 on success, -1 on error
00462 //
00463 //------------------------------------------------------------------------------
00464 
00465 int NSL01::get_RTC_alarm(void)
00466 {
00467     // 1. Init header
00468     TxMessage.SapID     = DEVMGMT_SAP_ID;
00469     TxMessage.MsgID     = DEVMGMT_MSG_GET_RTC_ALARM_REQ;
00470     TxMessage.Length    = 0;
00471     
00472     comm_pc.printf("\r\nGet RTC alarm: ");
00473         
00474     // 2. Send HCI message with payload
00475     int return_value = WiMOD_HCI_SendMessage(&TxMessage);
00476     
00477     // 3. Wait until any response from LoRa module
00478     LoRaWAN_wait();
00479 
00480     return return_value;
00481 }
00482 
00483 //------------------------------------------------------------------------------
00484 //
00485 //  Public method for device management: clear_RTC_alarm
00486 //
00487 //  @brief  Method to clear a pending Real Time Clock (RTC) alarm of NSL01.
00488 //
00489 //  @returns 1 on success, -1 on error
00490 //
00491 //------------------------------------------------------------------------------
00492 
00493 int NSL01::clear_RTC_alarm(void)
00494 {
00495     // 1. Init header
00496     TxMessage.SapID     = DEVMGMT_SAP_ID;
00497     TxMessage.MsgID     = DEVMGMT_MSG_CLEAR_RTC_ALARM_REQ;
00498     TxMessage.Length    = 0;
00499     
00500     comm_pc.printf("\r\nClear RTC alarm: ");
00501     
00502     // 2. Send HCI message without payload
00503     int return_value = WiMOD_HCI_SendMessage(&TxMessage);
00504     
00505     // 3. Wait until any response from LoRa module
00506     LoRaWAN_wait();
00507 
00508     return return_value;
00509 }
00510 
00511 //------------------------------------------------------------------------------
00512 //
00513 //  Public method for device management: get_system_operation_mode
00514 //
00515 //  @brief  Method to get the current system operation mode of NSL01.
00516 //
00517 //  @note  Two system operation modes are supported:
00518 //  - Standard / Application Mode
00519 //  - Customer Mode
00520 //
00521 //  @note  Some device functionality is only supported in customer mode!
00522 //
00523 //  @returns 1 on success, -1 on error
00524 //
00525 //------------------------------------------------------------------------------
00526 
00527 int NSL01::get_system_operation_mode(void)
00528 {
00529     // 1. Init header
00530     TxMessage.SapID     = DEVMGMT_SAP_ID;
00531     TxMessage.MsgID     = DEVMGMT_MSG_GET_OPMODE_REQ;
00532     TxMessage.Length    = 0;
00533 
00534     comm_pc.printf("\r\nGet system operation mode: ");
00535 
00536     // 2. Send HCI message without payload
00537     int return_value = WiMOD_HCI_SendMessage(&TxMessage);
00538     
00539     // 3. Wait until any response from LoRa module
00540     LoRaWAN_wait();
00541 
00542     return return_value;
00543 }
00544 
00545 //------------------------------------------------------------------------------
00546 //
00547 //  Public method for device management: set_system_operation_mode
00548 //
00549 //  @brief  Method to set the system operation mode of NSL01.
00550 //
00551 //  @note  After executing this command the module will be restarted after
00552 //  approximately 200ms!
00553 //
00554 //  @param system_mode 0 : Standard/Application mode
00555 //  @param system_mode 1 : Reserved/Not used
00556 //  @param system_mode 2 : Reserved/Not used
00557 //  @param system_mode 3 : Customer mode
00558 //
00559 //  @returns 1 on success, -1 on error
00560 //
00561 //------------------------------------------------------------------------------
00562 
00563 int NSL01::set_system_operation_mode(UINT8 system_mode)
00564 {
00565     // 1. Init header
00566     TxMessage.SapID     = DEVMGMT_SAP_ID;
00567     TxMessage.MsgID     = DEVMGMT_MSG_SET_OPMODE_REQ;
00568     TxMessage.Length    = 1;    
00569     
00570     comm_pc.printf("\r\nSet system operation mode: ");
00571             
00572     // 2. Check system mode
00573     if (!(system_mode == 0 || system_mode == 3))
00574     {
00575         comm_pc.printf("Error - Mode not supported!\r\n");
00576         return -1;
00577     }
00578         
00579     // 3. Prepare payload
00580     TxMessage.Payload[0] = system_mode;
00581     
00582     // 4. Send HCI message with payload
00583     int return_value = WiMOD_HCI_SendMessage(&TxMessage);
00584     
00585     // 5. Wait until any response from LoRa module
00586     LoRaWAN_wait();
00587 
00588     return return_value;
00589 }
00590 
00591 //------------------------------------------------------------------------------
00592 //
00593 //  Public method for LoRaWAN service: ABP_device_activation
00594 //
00595 //  @brief  Method to activate NSL01 in Activation by Personalization (ABP) mode
00596 //          and save parameters in non volatile memory.
00597 //
00598 //  @note  A device must be activated prior to any further data exchange with
00599 //         a network server!
00600 //
00601 //  @note  After a successful activation the NSL01 will automatically send an
00602 //         empty unconfirmed uplink message ("alive message") over the air!
00603 //
00604 //  @param deviceAddress  : unique 32-Bit Device Address
00605 //  @param *nwkSessionKey : device specific 128-Bit Network Session Key
00606 //  @param *appSessionKey : device specific 128-Bit Application Session Key
00607 //
00608 //  @returns 1 on success, -1 on error
00609 //
00610 //------------------------------------------------------------------------------
00611 
00612 int NSL01::ABP_device_activation(UINT32 deviceAddress,    //-Device address         
00613                                  UINT8* nwkSessionKey,    //-network session key
00614                                  UINT8* appSessionKey)    //-application session key
00615 {
00616     // 1. Init header
00617     TxMessage.SapID     = LORAWAN_SAP_ID;
00618     TxMessage.MsgID     = LORAWAN_MSG_ACTIVATE_DEVICE_REQ;
00619     TxMessage.Length    = 36;    
00620 
00621     // 2. Payload
00622     // 2.1 Device address: Payload[0...3]: LSB first            
00623 
00624     //--Convert device address (LSB first)     
00625     unsigned char *s = (unsigned char *)&deviceAddress;
00626     UINT32 result_conversion = (UINT32)(s[0] << 24 | s[1] << 16 | s[2] << 8 | s[3]);    
00627     TxMessage.Payload[0]= s[0];
00628     TxMessage.Payload[1]= s[1];
00629     TxMessage.Payload[2]= s[2];
00630     TxMessage.Payload[3]= s[3];
00631 
00632     //--Show result of conversion
00633     #ifdef DEBUG
00634         comm_pc.printf("\r\n ABP activation: - device address Payload 01: %02x, Payload 02: %02x, Payload 03: %02x, Payload 04: %02x\r\n", s[0], s[1], s[2], s[3]);
00635     #endif
00636 
00637     // 2.2 Network session key: Payload[4...19]: MSB first
00638     if(nwkSessionKey)
00639     {
00640         UINT8*  dstPtr  = TxMessage.Payload + DEVICE_ADDR_LEN;
00641         int     n       = KEY_LEN;
00642 
00643         // copy bytes
00644         while(n--)
00645             *dstPtr++ = *nwkSessionKey++;
00646     }
00647 
00648     // 2.3 Application session key: Payload[20...35]: MSB first
00649     if(appSessionKey)
00650     {
00651         UINT8*  dstPtr  = TxMessage.Payload + DEVICE_ADDR_LEN + KEY_LEN;
00652         int     n       = KEY_LEN;
00653 
00654         // copy bytes
00655         while(n--)
00656             *dstPtr++ = *appSessionKey++;
00657     }    
00658 
00659     comm_pc.printf("\r\nActivate device in ABP mode: ");
00660 
00661     // 3. send HCI message with payload
00662     int return_value = WiMOD_HCI_SendMessage(&TxMessage);
00663 
00664     // 4. Wait until any response from LoRa module
00665     LoRaWAN_wait();
00666     
00667     // 5. Wait an additional moment
00668     wait(2);
00669 
00670     return return_value;
00671 }
00672 
00673 //------------------------------------------------------------------------------
00674 //
00675 //  Public method for LoRaWAN service: ABP_device_reactivation
00676 //
00677 //  @brief  Method to reactivate NSL01 in Activation by Personalization (ABP)
00678 //          mode using the parameters previously stored in non-volatile memory.
00679 //
00680 //  @note  A device must be activated prior to any further data exchange with
00681 //         a network server!
00682 //
00683 //  @note  After a successful activation the NSL01 will automatically send an
00684 //         empty unconfirmed uplink message ("alive message") over the air!
00685 //
00686 //  @returns 1 on success, -1 on error
00687 //
00688 //------------------------------------------------------------------------------
00689 
00690 int NSL01::ABP_device_reactivation(void)
00691 {
00692     // 1. Init header
00693     TxMessage.SapID     = LORAWAN_SAP_ID;
00694     TxMessage.MsgID     = LORAWAN_MSG_REACTIVATE_DEVICE_REQ;
00695     TxMessage.Length    = 0;
00696 
00697     comm_pc.printf("\r\nReactivate device in ABP mode: ");    
00698 
00699     // 2. Send HCI message without payload
00700     int return_value = WiMOD_HCI_SendMessage(&TxMessage);
00701 
00702     // 3. Wait until any response from LoRa module
00703     LoRaWAN_wait();
00704     
00705     // 4. Wait an additional moment
00706     wait(2);
00707 
00708     return return_value;
00709 }
00710 
00711 //------------------------------------------------------------------------------
00712 //
00713 //  Public method for LoRaWAN service: deactivate NSL01
00714 //
00715 //  @brief  Method to deactivate the NSL01 LoRaWAN end-device, i.e. further data
00716 //          exchange over the air will be disabled.
00717 //
00718 //  @returns 1 on success, -1 on error
00719 //
00720 //------------------------------------------------------------------------------
00721 
00722 int NSL01::deactivate(void)
00723 {
00724     // 1. Init header
00725     TxMessage.SapID     = LORAWAN_SAP_ID;
00726     TxMessage.MsgID     = LORAWAN_MSG_DEACTIVATE_DEVICE_REQ;
00727     TxMessage.Length    = 0;            
00728 
00729     comm_pc.printf("\r\nDeactivate device: ");
00730 
00731     // 2. Send HCI message without payload
00732     int return_value = WiMOD_HCI_SendMessage(&TxMessage);
00733 
00734     // 3. Wait until any response from LoRa module
00735     LoRaWAN_wait();
00736 
00737     return return_value;
00738 }
00739 
00740 //------------------------------------------------------------------------------
00741 //
00742 //  Public method for LoRaWAN service: set_join_parameter
00743 //
00744 //  @brief  Method to configure the Over-the-Air Activation (OTTA) parameters of
00745 //          NSL01 which are used during the join network procedure 
00746 //          'join_network'.
00747 //
00748 //  @param *appEUI : globally unique 64-Bit Application EUI
00749 //  @param *appKey : device specific 128-Bit AES Application Key
00750 //
00751 //  @returns 1 on success, -1 on error
00752 //
00753 //------------------------------------------------------------------------------
00754 
00755 int NSL01::set_join_parameter(UINT8* appEUI, UINT8* appKey)
00756 {
00757    // 1. Init header
00758     TxMessage.SapID     = LORAWAN_SAP_ID;
00759     TxMessage.MsgID     = LORAWAN_MSG_SET_JOIN_PARAM_REQ;
00760     TxMessage.Length    = 24;
00761 
00762     // 2. Prepare payload
00763     // 2.1 64-Bit Application EUI: Payload[0...7]: MSB first            
00764     if (appEUI)
00765     {
00766         UINT8*  dstPtr  = TxMessage.Payload;
00767         int     n       = EUI_LEN;
00768 
00769         // copy bytes
00770         while(n--)
00771             *dstPtr++ = *appEUI++;
00772     }    
00773 
00774     // 2.2 128-Bit Application Key: Payload[8...23]: MSB first
00775     if(appKey)
00776     {
00777         UINT8*  dstPtr  = TxMessage.Payload + EUI_LEN;
00778         int     n       = KEY_LEN;
00779 
00780         // copy bytes
00781         while(n--)
00782             *dstPtr++ = *appKey++;
00783     }    
00784 
00785     comm_pc.printf("\r\nSet join parameter: ");
00786 
00787     // 3. Send HCI message with payload
00788     int return_value = WiMOD_HCI_SendMessage(&TxMessage);
00789 
00790     // 4. Wait until any response from LoRa module
00791     LoRaWAN_wait();
00792 
00793     return return_value;
00794 }
00795 
00796 //------------------------------------------------------------------------------
00797 //
00798 //  Public method for LoRaWAN service: join_network
00799 //
00800 //  @brief  Method to start the join network procedure of NSL01 in Over-the-Air
00801 //          Activation (OTTA) mode with previously defined parameters in 
00802 //          'set_join_parameter' method.
00803 //
00804 //  @note  Once the 'join_network' method is triggered an internal event
00805 //         method is invoked periodically to indicate the joining procedure.
00806 //
00807 //  @note  An internal join network indication event method is invoked after
00808 //         successful reception of a server join response packet or after the
00809 //         expiration of a complete join process without success (the join 
00810 //         request will be retransmitted changing the spreading factor from SF7
00811 //         till SF12, reusing each spreading factor twice).
00812 //
00813 //  @returns 1 on success, -1 on error
00814 //
00815 //------------------------------------------------------------------------------
00816 
00817 int NSL01::join_network(void)
00818 {
00819     // 1. Init header
00820     TxMessage.SapID     = LORAWAN_SAP_ID;
00821     TxMessage.MsgID     = LORAWAN_MSG_JOIN_NETWORK_REQ;
00822     TxMessage.Length    = 0;
00823 
00824     comm_pc.printf("\r\nJoin network request: ");
00825 
00826     // 2. Send HCI message with payload
00827     int return_value = WiMOD_HCI_SendMessage(&TxMessage);
00828 
00829     // 3. Wait until any response from LoRa module
00830     LoRaWAN_wait();
00831 
00832     return return_value;
00833 }
00834 
00835 //------------------------------------------------------------------------------
00836 //
00837 //  Public method for LoRaWAN service: send_Udata
00838 //
00839 //  @brief  Method to transmit data in an unreliable way to the network server,
00840 //          i.e. no acknowledgement will be sent from the network server and no
00841 //          retransmission method is available on the end-device (NSL01) side.
00842 //
00843 //  @note  An internal 'unreliable data transmit indication' event method is 
00844 //         invoked after the radio packet has been sent, containing information
00845 //         about the data transfer.
00846 //
00847 //  @param port      : LoRaWAN Port number (> 0)
00848 //  @param *srcData  : Application Payload (data which have to be transmitted)
00849 //  @param srcLength : Lenght of Application Payload data
00850 //
00851 //  @returns 1 on success, -1 on error
00852 //
00853 //------------------------------------------------------------------------------
00854 
00855 int NSL01::send_Udata(UINT8 port, UINT8* srcData, int srcLength)
00856 {
00857     comm_pc.printf("\r\nTransmit U-Data: ");
00858 
00859     // 1. Check length of application payload
00860     if (srcLength > (WIMOD_HCI_MSG_PAYLOAD_SIZE - 1))
00861     {
00862         //--Error
00863         comm_pc.printf("Error - transmit radio packet: Payload size exceeded!\r\n");
00864         return -1;
00865     }
00866 
00867     // 2. Check LoRAWAN port number range
00868     if (port <= 0)
00869     {
00870         //--Error
00871         comm_pc.printf("Error - transmit radio packet: Invalid port number!\r\n");
00872         return -1;        
00873     }
00874 
00875     // 3. Init header
00876     TxMessage.SapID     = LORAWAN_SAP_ID;
00877     TxMessage.MsgID     = LORAWAN_MSG_SEND_UDATA_REQ;
00878     TxMessage.Length    = 1 + srcLength;
00879 
00880     // 4.  Init payload
00881     // 4.1 Init port
00882     TxMessage.Payload[0] = port;
00883 
00884     // 4.2 Init radio message payload
00885     memcpy(&TxMessage.Payload[1], srcData, srcLength);
00886 
00887     // 5. Send HCI message with payload
00888     int return_value = WiMOD_HCI_SendMessage(&TxMessage);
00889 
00890     // 6. Wait until any response from LoRa module
00891     LoRaWAN_wait();
00892 
00893     return return_value;
00894 }
00895 
00896 //------------------------------------------------------------------------------
00897 //
00898 //  Public method for LoRaWAN service: send_Cdata
00899 //
00900 //  @brief  Method to transmit data in a reliable way to the network server,
00901 //          i.e. confirmed data transmission.
00902 //
00903 //  @note  An internal 'reliable data transmit indication' event method is 
00904 //         invoked after the radio packet has been sent, containing information
00905 //         about the data transfer.
00906 //
00907 //  @param port      : LoRaWAN Port number (> 0)
00908 //  @param *srcData  : Application Payload (data which have to be transmitted)
00909 //  @param srcLength : Lenght of Application Payload data
00910 //
00911 //  @returns 1 on success, -1 on error
00912 //
00913 //------------------------------------------------------------------------------
00914 
00915 int NSL01::send_Cdata(UINT8 port, UINT8* srcData, int srcLength)
00916 {
00917     comm_pc.printf("\r\nTransmit C-Data: ");
00918 
00919     // 1. Check length of application payload
00920     if (srcLength > (WIMOD_HCI_MSG_PAYLOAD_SIZE - 1))
00921     {
00922         //--Error
00923         comm_pc.printf("Error - transmit radio packet: Payload size exceeded!\r\n");
00924         return -1;
00925     }
00926 
00927     // 2. Check LoRAWAN port number range
00928     if (port <= 0)
00929     {
00930         //--Error
00931         comm_pc.printf("Error - transmit radio packet: Invalid port number!\r\n");
00932         return -1;        
00933     }
00934 
00935     // 3. Init header
00936     TxMessage.SapID     = LORAWAN_SAP_ID;
00937     TxMessage.MsgID     = LORAWAN_MSG_SEND_CDATA_REQ;
00938     TxMessage.Length    = 1 + srcLength;
00939 
00940     // 4.  Init payload
00941     // 4.1 Init port
00942     TxMessage.Payload[0] = port;
00943 
00944     // 4.2 Init radio message payload
00945     memcpy(&TxMessage.Payload[1], srcData, srcLength);
00946 
00947     // 5. Send HCI message with payload
00948     int return_value = WiMOD_HCI_SendMessage(&TxMessage);
00949 
00950     // 6. Wait until any response from LoRa module
00951     LoRaWAN_wait();
00952 
00953     return return_value;
00954 }
00955 
00956 //------------------------------------------------------------------------------
00957 //
00958 //  Public method for LoRaWAN service: set_radio_stack_config
00959 //
00960 //  @brief  Method to set/configure the internal radio stack configuration
00961 //          of NSL01 <=> main parameters for data transmission.
00962 //
00963 //  @param radio_stack : Radio stack config data defined in Radio_config_struct
00964 //
00965 //  @returns 1 on success, -1 on error
00966 //
00967 //------------------------------------------------------------------------------
00968 
00969 int NSL01::set_radio_stack_config(Radio_config_struct radio_stack)
00970 {
00971     // 1. Init header
00972     TxMessage.SapID     = LORAWAN_SAP_ID;
00973     TxMessage.MsgID     = LORAWAN_MSG_SET_RSTACK_CONFIG_REQ;
00974     TxMessage.Length    = 7;
00975 
00976     comm_pc.printf("\r\nSet radio stack config: ");
00977 
00978     //---------------------------
00979     // 2. Check input parameters
00980     //---------------------------
00981 
00982     // 2.1 Data rate index [0...6]
00983     if ((int)radio_stack.data_rate_index < 0 || radio_stack.data_rate_index > 6)
00984     {
00985         comm_pc.printf("Error - Data rate index is out of range!\r\n");
00986         comm_pc.printf("  Adapt parameter and try again!\r\n");
00987         return -1;
00988     }
00989 
00990     // 2.2 Tx power level (EIRP) [0...16]
00991     if ((int)radio_stack.Tx_power < 0 || radio_stack.Tx_power > 16)
00992     {
00993         comm_pc.printf("Error - Tx power level is out of range!\r\n");
00994         comm_pc.printf("  Adapt parameter and try again!\r\n");
00995         return -1;
00996     }
00997 
00998     // 2.3 Adaptive data rate [enabled/disabled]
00999     if (!(radio_stack.adaptive_data_rate == 0 || radio_stack.adaptive_data_rate == 1))
01000     {
01001         comm_pc.printf("Error - Adaptive data rate is out of range!\r\n");
01002         comm_pc.printf("  Adapt parameter and try again!\r\n");
01003         return -1;
01004     }
01005 
01006     // 2.4 Duty Cycle control [enabled/disabled]
01007     if (!(radio_stack.duty_cycle_control == 0 || radio_stack.duty_cycle_control == 1))
01008     {
01009         comm_pc.printf("Error - Duty Cycle mode is out of range!\r\n");
01010         comm_pc.printf("  Adapt parameter and try again!\r\n");
01011         return -1;
01012     }
01013 
01014     // 2.5 Class C support [enabled/disabled]
01015     if (!(radio_stack.class_C_support == 0 || radio_stack.class_C_support == 1))
01016     {
01017         comm_pc.printf("Error - Class A/C mode is out of range!\r\n");
01018         comm_pc.printf("  Adapt parameter and try again!\r\n");
01019         return -1;
01020     }
01021 
01022     // 2.6 RF packet output format [standard/extended]
01023     if (!(radio_stack.RF_packet_format == 0 || radio_stack.RF_packet_format == 1))
01024     {
01025         comm_pc.printf("Error - RF packet output format is out of range!\r\n");
01026         comm_pc.printf("  Adapt parameter and try again!\r\n");
01027         return -1;
01028     }
01029 
01030     // 2.7 Rx MAC command forwarding [enabled/disabled]
01031     if (!(radio_stack.forwarding == 0 || radio_stack.forwarding == 1))
01032     {
01033         comm_pc.printf("Error - Rx MAC command forwarding is out of range!\r\n");
01034         comm_pc.printf("  Adapt parameter and try again!\r\n");
01035         return -1;
01036     }
01037 
01038     // 2.8 Power saving mode [enabled/disabled]
01039     if (!(radio_stack.power_saving == 0 || radio_stack.power_saving == 1))
01040     {
01041         comm_pc.printf("Error - Power saving mode is out of range!\r\n");
01042         comm_pc.printf("  Adapt parameter and try again!\r\n");
01043         return -1;
01044     }
01045 
01046     // 2.9 Maximum number of retransmissions [0...254]
01047     if ((int)radio_stack.number_retransmissions < 0 || radio_stack.number_retransmissions > 254)
01048     {
01049         comm_pc.printf("Error - Maximum number of retransmissions is out of range!\r\n");
01050         comm_pc.printf("  Adapt parameter and try again!\r\n");
01051         return -1;
01052     }
01053 
01054     // 2.10 Radio band selection [1...3]
01055     if (radio_stack.band_index < 1 || radio_stack.band_index > 3)
01056     {
01057         comm_pc.printf("Error - Radio band selection is out of range!\r\n");
01058         comm_pc.printf("  Adapt parameter and try again!\r\n");
01059         return -1;
01060     }
01061 
01062     // 2.11 Header MAC Cmd capacity [0...15]
01063     if ((int)radio_stack.header_MAC_cmd_capacity < 0 || radio_stack.header_MAC_cmd_capacity > 15)
01064     {
01065         comm_pc.printf("Error - Header MAC Cmd capacity is out of range!\r\n");
01066         comm_pc.printf("  Adapt parameter and try again!\r\n");
01067         return -1;
01068     }
01069 
01070     //---------------------------
01071     // 3. Prepare payload
01072     //---------------------------
01073 
01074     // 3.1 Data rate index
01075     TxMessage.Payload[0] = radio_stack.data_rate_index;
01076 
01077     // 3.2 TX power level (EIRP) in dBm in 1dB steps
01078     TxMessage.Payload[1] = radio_stack.Tx_power;
01079 
01080     // 3.3 Options: Bit 0: adaptive data rate          (0:disabled, 1:enabled)
01081     //              Bit 1: duty cycle control          (0:disabled, 1:enabled)
01082     //              Bit 2: Class C support             (0:Class A, 1: Class C)
01083     //              Bit 6: RF packet output format     (0:standard format, 1:extended format)
01084     //              Bit 7: Rx MAC command forwarding   (0:disabled, 1:enabled)
01085     TxMessage.Payload[2] = (radio_stack.adaptive_data_rate & 0x01) | (radio_stack.duty_cycle_control << 1 & 0x02) |
01086                            (radio_stack.class_C_support << 2 & 0x04) | (radio_stack.RF_packet_format << 6 & 0x40) |
01087                            (radio_stack.forwarding << 7 & 0x80);
01088 
01089     // 3.4 Power saving mode (0:off, 1:automatic)
01090     TxMessage.Payload[3] = radio_stack.power_saving;
01091 
01092     // 3.5 Maximum number of retransmissions (0...254)
01093     TxMessage.Payload[4] = radio_stack.number_retransmissions;
01094 
01095     // 3.6 Radio band selection (1...3)
01096     TxMessage.Payload[5] = radio_stack.band_index;
01097 
01098     // 3.7 Header MAC Cmd capacity (0...15)
01099     TxMessage.Payload[6] = radio_stack.header_MAC_cmd_capacity;
01100 
01101     //--Show configuration for debugging
01102     #ifdef DEBUG
01103         comm_pc.printf("\r\n Radio Stack: 0x%08x\r\n",(radio_stack.adaptive_data_rate & 0x01));
01104         comm_pc.printf(" Duty Cycle: 0x%08x\r\n",(radio_stack.duty_cycle_control << 1 & 0x02));
01105         comm_pc.printf(" Class C: 0x%08x\r\n",(radio_stack.class_C_support << 2 & 0x04));
01106         comm_pc.printf(" RF Packet format: 0x%08x\r\n",(radio_stack.RF_packet_format << 6 & 0x40));
01107         comm_pc.printf(" Forwarding: 0x%08x\r\n",(radio_stack.forwarding << 7 & 0x80));
01108     #endif
01109 
01110     // 4. Send HCI message with payload
01111     int return_value = WiMOD_HCI_SendMessage(&TxMessage);
01112 
01113     // 5. Wait until any response from LoRa module
01114     LoRaWAN_wait();
01115 
01116     return return_value;
01117 }
01118 
01119 //------------------------------------------------------------------------------
01120 //
01121 //  Public method for LoRaWAN service: get_radio_stack_config
01122 //
01123 //  @brief  Method to read the current radio stack configuration of NSL01
01124 //          <=> main parameters for data transmission
01125 //
01126 //  @returns 1 on success, -1 on error
01127 //
01128 //------------------------------------------------------------------------------
01129 
01130 int NSL01::get_radio_stack_config(void)
01131 {
01132     // 1. Init header
01133     TxMessage.SapID     = LORAWAN_SAP_ID;
01134     TxMessage.MsgID     = LORAWAN_MSG_GET_RSTACK_CONFIG_REQ;
01135     TxMessage.Length    = 0;
01136 
01137     comm_pc.printf("\r\nGet radio stack config: ");
01138 
01139     // 2. Send HCI message without payload
01140     int return_value = WiMOD_HCI_SendMessage(&TxMessage);
01141 
01142     // 3. Wait until any response from LoRa module
01143     LoRaWAN_wait();
01144 
01145     return return_value;    
01146 }
01147 
01148 //------------------------------------------------------------------------------
01149 //
01150 //  Public method for LoRaWAN service: get_freqband_info
01151 //
01152 //  @brief  Method to get information related to the supported frequency bands 
01153 //          used by the firmware. Moreover, the maximum supported EIRP for each
01154 //          band is provided.
01155 //
01156 //  @returns 1 on success, -1 on error
01157 //
01158 //------------------------------------------------------------------------------
01159 
01160 int NSL01::get_freqband_info(void)
01161 {
01162     // 1. Init header
01163     TxMessage.SapID     = LORAWAN_SAP_ID;
01164     TxMessage.MsgID     = LORAWAN_MSG_GET_SUPPORTED_BANDS_REQ;
01165     TxMessage.Length    = 0;
01166 
01167     comm_pc.printf("\r\nGet frequency band information: ");
01168 
01169     // 2. Send HCI message without payload
01170     int return_value = WiMOD_HCI_SendMessage(&TxMessage);
01171 
01172     // 3. Wait until any response from LoRa module
01173     LoRaWAN_wait();
01174 
01175     return return_value;
01176 }
01177 
01178 //------------------------------------------------------------------------------
01179 //
01180 //  Public method for LoRaWAN service: get_EUI
01181 //
01182 //  @brief  Method to get/read the unique 64-bit device EUI.
01183 //
01184 //  @returns 1 on success, -1 on error
01185 //
01186 //------------------------------------------------------------------------------
01187 
01188 int NSL01::get_EUI(void)
01189 {
01190     // 1. Init header
01191     TxMessage.SapID     = LORAWAN_SAP_ID;
01192     TxMessage.MsgID     = LORAWAN_MSG_GET_DEVICE_EUI_REQ;
01193     TxMessage.Length    = 0;
01194 
01195     comm_pc.printf("\r\nDevice EUI request: ");
01196 
01197     // 2. Send HCI message without payload
01198     int return_value = WiMOD_HCI_SendMessage(&TxMessage);
01199 
01200     // 3. Wait until any response from LoRa module
01201     LoRaWAN_wait();
01202 
01203     return return_value;
01204 }
01205 
01206 //------------------------------------------------------------------------------
01207 //
01208 //  Public method for LoRaWAN service: set_EUI
01209 //
01210 //  @brief  Method to set/write the unique 64-bit device EUI.
01211 //
01212 //  @note  The device EUI can only be set in "customer mode"!
01213 //
01214 //  @param *device_EUI : Unique 64-bit device EUI (UINT8 array)
01215 //
01216 //  @returns 1 on success, -1 on error
01217 //
01218 //------------------------------------------------------------------------------
01219 
01220 int NSL01::set_EUI(UINT8 *device_EUI)
01221 {
01222     //--Internal variables and constants
01223     UINT8   index;
01224 
01225     // 1. Init header
01226     TxMessage.SapID     = LORAWAN_SAP_ID;
01227     TxMessage.MsgID     = LORAWAN_MSG_SET_DEVICE_EUI_REQ;
01228     TxMessage.Length    = EUI_LEN;
01229 
01230     // 2. Prepare payload
01231     index = 0;
01232 
01233     //--Copy bytes to array
01234     while(index < EUI_LEN)
01235     {
01236         TxMessage.Payload[index] = *device_EUI;
01237 
01238         //--Update pointer and indices
01239         device_EUI++;
01240         index++;
01241     }
01242 
01243     comm_pc.printf("\r\nSet device EUI: ");
01244 
01245     // 3. Send HCI message with payload
01246     int return_value = WiMOD_HCI_SendMessage(&TxMessage);
01247 
01248     // 4. Wait until any response from LoRa module
01249     LoRaWAN_wait();
01250 
01251     return return_value;
01252 }
01253 
01254 //------------------------------------------------------------------------------
01255 //
01256 //  Public method for LoRaWAN service: set_custom_configuration
01257 //
01258 //  @brief  Method to configure the custom parameters (RF gain offset to
01259 //          compensate possible transmission losses/gains including circuit
01260 //          matching, antennas, ...). This parameter should be rated in units of
01261 //          dBd (decibels relative to a half-wavelength dipole antenna, where
01262 //          0dBd = 2.15 dBi).
01263 //
01264 //  @note  This parameter can only be set in "customer mode"!
01265 //
01266 //  @param RF_gain_offset : RF gain offset in dBd
01267 //
01268 //  @returns 1 on success, -1 on error
01269 //
01270 //------------------------------------------------------------------------------
01271 
01272 int NSL01::set_custom_configuration(int RF_gain_offset)
01273 {
01274     // 1. Init header
01275     TxMessage.SapID     = LORAWAN_SAP_ID;
01276     TxMessage.MsgID     = LORAWAN_MSG_SET_CUSTOM_CFG_REQ;
01277     TxMessage.Length    = 1;
01278 
01279     comm_pc.printf("\r\nSet custom configuration: ");
01280 
01281     // 2. Check Tx power offset
01282     if (RF_gain_offset < -128 || RF_gain_offset > 127)
01283     {
01284         comm_pc.printf("Error - Tx power offset not supported!\r\n");
01285         return -1;
01286     }
01287 
01288     // 3. Prepare payload
01289     TxMessage.Payload[0] = (UINT8)RF_gain_offset;
01290 
01291     //--Display result for debugging
01292     #ifdef DEBUG
01293         UINT8 tmp_Tx_power_offset = (UINT8)RF_gain_offset;
01294         INT8  converted_Tx_power_offset = (INT8)tmp_Tx_power_offset;
01295         comm_pc.printf("RF gain offset: %d dBd\r\n", converted_Tx_power_offset);
01296     #endif
01297 
01298     // 4. Send HCI message with payload
01299     int return_value = WiMOD_HCI_SendMessage(&TxMessage);
01300 
01301     // 5. Wait until any response from LoRa module
01302     LoRaWAN_wait();
01303 
01304     return return_value;
01305 }
01306 
01307 //------------------------------------------------------------------------------
01308 //
01309 //  Public method for LoRaWAN service: get_custom_configuration
01310 //
01311 //  @brief  Method to get/read the custom configuration parameters
01312 //          (RF gain offset) of NSL01.
01313 //
01314 //  @returns 1 on success, -1 on error
01315 //
01316 //------------------------------------------------------------------------------
01317 
01318 int NSL01::get_custom_configuration(void)
01319 {
01320    // 1. Init header
01321     TxMessage.SapID     = LORAWAN_SAP_ID;
01322     TxMessage.MsgID     = LORAWAN_MSG_GET_CUSTOM_CFG_REQ;
01323     TxMessage.Length    = 0;
01324 
01325     comm_pc.printf("\r\nGet custom configuration: ");
01326 
01327     // 2. Send HCI message without payload
01328     int return_value = WiMOD_HCI_SendMessage(&TxMessage);
01329 
01330     // 3. Wait until any response from LoRa module
01331     LoRaWAN_wait();
01332 
01333     return return_value;
01334 }
01335 
01336 //------------------------------------------------------------------------------
01337 //
01338 //  Public method for LoRaWAN service: factory_reset
01339 //
01340 //  @brief  Method to restore the initial firmware settings, stored during
01341 //          production time (factory reset).
01342 //
01343 //  @returns 1 on success, -1 on error
01344 //
01345 //------------------------------------------------------------------------------
01346 
01347 int NSL01::factory_reset(void)
01348 {
01349     // 1. Init header
01350     TxMessage.SapID     = LORAWAN_SAP_ID;
01351     TxMessage.MsgID     = LORAWAN_MSG_FACTORY_RESET_REQ;
01352     TxMessage.Length    = 0;
01353 
01354     comm_pc.printf("\r\nApply factory reset: ");
01355 
01356     // 2. send HCI message without payload
01357     int return_value = WiMOD_HCI_SendMessage(&TxMessage);
01358 
01359     // 3. Wait until any response from LoRa module
01360     LoRaWAN_wait();
01361 
01362     return return_value;
01363 }
01364 
01365 //------------------------------------------------------------------------------
01366 //
01367 //  Public method for LoRaWAN service: get_PowerLimit_configuration
01368 //
01369 //  @brief  Method to read the transmit power limit configuration parameters of
01370 //          NSL01 for different frequency sub-bands.
01371 //
01372 //  @returns 1 on success, -1 on error
01373 //
01374 //------------------------------------------------------------------------------
01375 
01376 int NSL01::get_PowerLimit_configuration(void)
01377 {
01378     // 1. Init header
01379     TxMessage.SapID     = LORAWAN_SAP_ID;
01380     TxMessage.MsgID     = LORAWAN_MSG_GET_TXPOWER_LIMIT_CONFIG_REQ;
01381     TxMessage.Length    = 0;
01382 
01383     comm_pc.printf("\r\nGet Tx power limit configuration: ");
01384 
01385     // 2. Send HCI message without payload
01386     int return_value = WiMOD_HCI_SendMessage(&TxMessage);
01387 
01388     // 3. Wait until any response from LoRa module
01389     LoRaWAN_wait();
01390 
01391     return return_value;
01392 }
01393 
01394 //------------------------------------------------------------------------------
01395 //
01396 //  Public method for LoRaWAN service: set_PowerLimit_configuration
01397 //
01398 //  @brief  Method to set/configure the transmit power limit configuration
01399 //          parameters of NSL01 for a dedicated frequency sub-band.
01400 //
01401 //  @note  These parameters can only be written in "customer mode"!
01402 //
01403 //  @param sub_band : Sub-band index [0...5] according to specification
01404 //  @param power_limit_flag : Tx power limit flag for sub-band [enabled/disabled]
01405 //  @param power_limit : Tx power limit for sub-band in dBm [0...16]
01406 //
01407 //  @returns 1 on success, -1 on error
01408 //
01409 //------------------------------------------------------------------------------
01410 
01411 int NSL01::set_PowerLimit_configuration(UINT8 sub_band, UINT8 power_limit_flag, UINT8 power_limit)
01412 {
01413     // 1. Init header
01414     TxMessage.SapID     = LORAWAN_SAP_ID;
01415     TxMessage.MsgID     = LORAWAN_MSG_SET_TXPOWER_LIMIT_CONFIG_REQ;
01416     TxMessage.Length    = 3;
01417 
01418     comm_pc.printf("\r\nTx power limit configuration: ");
01419 
01420     // 2. check input parameters
01421     if (((int)sub_band < 0) || (sub_band > 5))
01422     {
01423         comm_pc.printf("Error - Sub-band index is out of range\r\n");
01424         return -1;
01425     }
01426 
01427     if (((int)power_limit_flag < 0) || (power_limit_flag > 1))
01428     {
01429         comm_pc.printf("Error - Power limit flag is out of range\r\n");
01430         return -1;
01431     }
01432 
01433     if (((int)power_limit < 0) || (power_limit > 16))
01434     {
01435         comm_pc.printf("Error - Power limit is out of range\r\n");
01436         return -1;
01437     }
01438 
01439     // 3. Parameters correct => prepare payload
01440     TxMessage.Payload[0] = sub_band;
01441     TxMessage.Payload[1] = power_limit_flag;
01442     TxMessage.Payload[2] = power_limit;
01443 
01444     // 4. Send HCI message without payload
01445     int return_value = WiMOD_HCI_SendMessage(&TxMessage);
01446 
01447     // 5. Wait until any response from LoRa module
01448     LoRaWAN_wait();
01449 
01450     return return_value;
01451 }
01452 
01453 //------------------------------------------------------------------------------
01454 //
01455 //  Private method: initialize
01456 //
01457 //  @brief  Internal method to initialize NSL01.
01458 //
01459 //  @note  This function is automatically invoked in constructor.
01460 //
01461 //------------------------------------------------------------------------------
01462 
01463 void NSL01::initialize()
01464 {    
01465     //--Init HCI layer
01466     WiMOD_HCI_Init(Process_RxMessage,    //-Receiver callback
01467                    &RxMessage);          //-Rx message
01468 }
01469 
01470 //------------------------------------------------------------------------------
01471 //
01472 //  Private method: LoRa_event
01473 //
01474 //  @brief  Internal callback method for event handling of NSL01.
01475 //
01476 //  @note  This method is invoked automatically whenever an event occurs.
01477 //
01478 //  @param Event_ID : Event message identifier defined in header of NSL01.h
01479 //
01480 //------------------------------------------------------------------------------
01481 
01482 void NSL01::LoRa_event(int Event_ID)
01483 {
01484     //--Event-handling
01485     switch(Event_ID)
01486     {
01487         case LORAWAN_EVENT_MSG_ALARM:
01488             comm_pc.printf("  RTC alarm event!\r\n");
01489             break;
01490 
01491         case LORAWAN_EVENT_MSG_JOIN_TIMEOUT:
01492             comm_pc.printf("  Join network timeout -> Please try again!\r\n");
01493             break;
01494 
01495         case LORAWAN_EVENT_MSG_CDATA_MAX_RETRANSMISSION:
01496             comm_pc.printf("  Maximum number of C-Data retransmissions reached!\r\n");
01497             break;
01498 
01499         case LORAWAN_EVENT_MSG_CDATA_PAYLOAD_EXCEEDED:
01500             comm_pc.printf("  Maximum C-Data payload size exceeded for current data rate!\r\n");
01501             break;
01502 
01503         default:
01504             comm_pc.printf("  Unspecified event callback received!\r\n");
01505             break;                   
01506     }
01507 }
01508 
01509 //------------------------------------------------------------------------------
01510 //
01511 //  Private method (internal callback): Process_RxMessage
01512 //
01513 //  @brief  Internal processing of received HCI messages of NSL01.
01514 //
01515 //  @param TWiMOD_HCI_Message* : Rx message struct in WiMOD_HCI_Layer.h
01516 //
01517 //  @returns TWiMOD_HCI_Message* struct
01518 //
01519 //------------------------------------------------------------------------------
01520 
01521 TWiMOD_HCI_Message* NSL01::Process_RxMessage(TWiMOD_HCI_Message*  rxMessage)
01522 {
01523     switch(rxMessage->SapID)
01524     {
01525         //--Device management message
01526         case DEVMGMT_SAP_ID:
01527             Process_DevMgmt_Message(rxMessage);
01528             break;
01529 
01530         //--LoRaWAN message
01531         case LORAWAN_SAP_ID:
01532             Process_LoRaWAN_Message(rxMessage);
01533             break;
01534     }
01535     return &RxMessage;
01536 }
01537 
01538 //------------------------------------------------------------------------------
01539 //
01540 //  Private method: Process_DevMgmt_Message
01541 //
01542 //  @brief  Internal processing of received device management messages.
01543 //
01544 //  @param TWiMOD_HCI_Message* : Rx message struct in WiMOD_HCI_Layer.h
01545 //
01546 //------------------------------------------------------------------------------
01547 
01548 void NSL01::Process_DevMgmt_Message(TWiMOD_HCI_Message*  rxMessage)
01549 {
01550     switch(rxMessage->MsgID)
01551     {
01552         case    DEVMGMT_MSG_PING_RSP:
01553                 LoRaWAN_ShowResponse("ping response", DeviceMgmt_StatusStrings, rxMessage->Payload[0]);
01554                 flag_LoRaWAN_response = true;
01555                 break;
01556 
01557         case    DEVMGMT_MSG_RESET_RSP:
01558                 LoRaWAN_ShowResponse("reset response", DeviceMgmt_StatusStrings, rxMessage->Payload[0]);
01559                 comm_pc.printf("  LoRaWAN module will be restarted in approx. 200ms!\r\n");
01560                 flag_LoRaWAN_response = true;
01561                 wait(0.5);
01562                 break;
01563 
01564         case    DEVMGMT_MSG_GET_DEVICE_INFO_RSP:
01565                 DevMgmt_DeviceInfo_Rsp(rxMessage);
01566                 break;                             
01567 
01568         case    DEVMGMT_MSG_GET_FW_VERSION_RSP:
01569                 DevMgmt_FirmwareVersion_Rsp(rxMessage);
01570                 break;
01571 
01572         case    DEVMGMT_MSG_GET_DEVICE_STATUS_RSP:
01573                 DevMgmt_DeviceStatus_Rsp(rxMessage);
01574                 break;
01575 
01576         case    DEVMGMT_MSG_GET_RTC_RSP:
01577                 DevMgmt_RTC_Rsp(rxMessage);
01578                 break;
01579 
01580         case    DEVMGMT_MSG_SET_RTC_RSP:
01581                 LoRaWAN_ShowResponse("RTC set response", DeviceMgmt_StatusStrings, rxMessage->Payload[0]);
01582                 flag_LoRaWAN_response = true;
01583                 break;
01584 
01585         case    DEVMGMT_MSG_SET_RTC_ALARM_RSP:                                                             
01586                 LoRaWAN_ShowResponse("RTC alarm set response", DeviceMgmt_StatusStrings, rxMessage->Payload[0]);
01587                 flag_LoRaWAN_response = true;
01588                 break;
01589 
01590         case    DEVMGMT_MSG_RTC_ALARM_IND:
01591                 LoRaWAN_ShowResponse("\r\nRTC alarm event", DeviceMgmt_StatusStrings, rxMessage->Payload[0]);
01592                 LoRa_event(LORAWAN_EVENT_MSG_ALARM);
01593                 break;
01594 
01595         case    DEVMGMT_MSG_GET_RTC_ALARM_RSP:
01596                 DevMgmt_Get_Alarm_Rsp(rxMessage);
01597                 break;                  
01598 
01599         case    DEVMGMT_MSG_CLEAR_RTC_ALARM_RSP:
01600                 LoRaWAN_ShowResponse("clear RTC alarm response", DeviceMgmt_StatusStrings, rxMessage->Payload[0]);
01601                 flag_LoRaWAN_response = true;
01602                 break;
01603 
01604         case    DEVMGMT_MSG_GET_OPMODE_RSP:
01605                 DevMgmt_OperationMode_Rsp(rxMessage);
01606                 break;                                            
01607 
01608         case    DEVMGMT_MSG_SET_OPMODE_RSP:
01609                 LoRaWAN_ShowResponse("Operation mode response", DeviceMgmt_StatusStrings, rxMessage->Payload[0]);
01610                 comm_pc.printf("  LoRaWAN module will be restarted in approx. 200ms!\r\n");
01611                 flag_LoRaWAN_response = true;
01612                 wait(0.5);
01613                 break;
01614 
01615         default:
01616                 comm_pc.printf("unhandled DeviceMgmt message received - MsgID : 0x%02X\n\r", (UINT8)rxMessage->MsgID);
01617                 break;
01618     }
01619 }
01620 
01621 //------------------------------------------------------------------------------
01622 //
01623 //  Private method: Process_LoRaWAN_Message
01624 //
01625 //  @brief  Internal processing of received LoRaWAN messages.
01626 //
01627 //  @param TWiMOD_HCI_Message* : Rx message struct in WiMOD_HCI_Layer.h
01628 //
01629 //------------------------------------------------------------------------------
01630 
01631 void NSL01::Process_LoRaWAN_Message(TWiMOD_HCI_Message*  rxMessage)
01632 {    
01633     switch(rxMessage->MsgID)
01634     {
01635         case    LORAWAN_MSG_ACTIVATE_DEVICE_RSP:
01636                 LoRaWAN_ShowResponse("device activation response", LoRaWAN_StatusStrings, rxMessage->Payload[0]);
01637                 break;        
01638 
01639         case    LORAWAN_MSG_REACTIVATE_DEVICE_RSP:
01640                 LoRaWAN_Reactivate_Device_Rsp(rxMessage);
01641                 break;  
01642 
01643         case    LORAWAN_MSG_DEACTIVATE_DEVICE_RSP:
01644                 LoRaWAN_ShowResponse("device deactivation response", LoRaWAN_StatusStrings, rxMessage->Payload[0]);
01645                 flag_LoRaWAN_response = true;
01646                 break;
01647 
01648         case    LORAWAN_MSG_SET_JOIN_PARAM_RSP:
01649                 LoRaWAN_ShowResponse("set join parameter response", LoRaWAN_StatusStrings, rxMessage->Payload[0]);
01650                 flag_LoRaWAN_response = true;
01651                 break;                        
01652 
01653         case    LORAWAN_MSG_JOIN_NETWORK_RSP:
01654                 LoRaWAN_ShowResponse("join network response", LoRaWAN_StatusStrings, rxMessage->Payload[0]);
01655                 break;
01656 
01657         case    LORAWAN_MSG_SEND_UDATA_RSP:
01658                 LoRaWAN_send_Udata_Rsp(rxMessage);                
01659                 break;
01660                 
01661         case    LORAWAN_MSG_SEND_UDATA_TX_IND:
01662                 LoRaWAN_Udata_Tx_Indication(rxMessage);
01663                 break;                
01664 
01665         case    LORAWAN_MSG_RECV_UDATA_RX_IND:
01666                 LoRaWAN_Udata_Rx_Indication(rxMessage);
01667                 break; 
01668 
01669         case    LORAWAN_MSG_SEND_CDATA_RSP:
01670                 LoRaWAN_send_Cdata_Rsp(rxMessage);                
01671                 break;
01672 
01673         case    LORAWAN_MSG_SEND_CDATA_TX_IND:
01674                 LoRaWAN_Cdata_Tx_Indication(rxMessage);
01675                 break;
01676 
01677         case    LORAWAN_MSG_RECV_CDATA_RX_IND:
01678                 LoRaWAN_Cdata_Rx_Indication(rxMessage);
01679                 break;                
01680 
01681         case    LORAWAN_MSG_RECV_NODATA_IND:
01682                 //--Method not used/necessary at the moment
01683                 //LoRaWAN_Rx_NoData_Indication(rxMessage);
01684                 break;
01685                 
01686         case    LORAWAN_MSG_SET_RSTACK_CONFIG_RSP:
01687                 LoRaWAN_Set_RadioStack_Config_Rsp(rxMessage);
01688                 break;
01689 
01690         case    LORAWAN_MSG_GET_RSTACK_CONFIG_RSP:
01691                 LoRaWAN_Get_RadioStack_Config_Rsp(rxMessage);
01692                 break;
01693 
01694         case    LORAWAN_MSG_GET_SUPPORTED_BANDS_RSP:
01695                 LoRaWAN_Get_FreqBand_Rsp(rxMessage);
01696                 break;
01697 
01698         case    LORAWAN_MSG_GET_DEVICE_EUI_RSP:
01699                 LoRaWAN_Get_DeviceEUI_Rsp(rxMessage);
01700                 break;
01701 
01702         case    LORAWAN_MSG_SET_DEVICE_EUI_RSP:
01703                 LoRaWAN_ShowResponse("device EUI response", LoRaWAN_StatusStrings, rxMessage->Payload[0]);
01704                 flag_LoRaWAN_response = true;
01705                 break;
01706 
01707         case    LORAWAN_MSG_SET_CUSTOM_CFG_RSP:
01708                 LoRaWAN_ShowResponse("set custom configuration response", LoRaWAN_StatusStrings, rxMessage->Payload[0]);
01709                 flag_LoRaWAN_response = true;
01710                 break;
01711 
01712         case    LORAWAN_MSG_GET_CUSTOM_CFG_RSP:
01713                 LoRaWAN_Get_Custom_Config_Rsp(rxMessage);
01714                 break;
01715 
01716         case    LORAWAN_MSG_FACTORY_RESET_RSP:
01717                 LoRaWAN_ShowResponse("factory reset response", LoRaWAN_StatusStrings, rxMessage->Payload[0]);
01718                 flag_LoRaWAN_response = true;
01719                 break;
01720 
01721         case    LORAWAN_MSG_GET_NWK_STATUS_RSP:
01722                 LoRaWAN_Network_Status_Rsp(rxMessage);
01723                 break;
01724 
01725         case    LORAWAN_MSG_GET_TXPOWER_LIMIT_CONFIG_RSP:
01726                 LoRaWAN_Get_TxPower_Limit_Config_Rsp(rxMessage);
01727                 break; 
01728 
01729         case    LORAWAN_MSG_SET_TXPOWER_LIMIT_CONFIG_RSP:
01730                 LoRaWAN_Set_TxPower_Limit_Config_Rsp(rxMessage);
01731                 break;
01732 
01733         case    LORAWAN_MSG_JOIN_TRANSMIT_IND:
01734                 LoRaWAN_Process_JoinTxIndication(rxMessage);
01735                 break;
01736 
01737         case    LORAWAN_MSG_JOIN_NETWORK_IND:
01738                 LoRaWAN_Process_JoinNetworkIndication(rxMessage);
01739                 break;
01740 
01741         default:
01742                 comm_pc.printf("unspecified LoRaWAN message received - MsgID : 0x%02X\r\n", (UINT8)rxMessage->MsgID);
01743                 break;
01744     }
01745 }
01746 
01747 //------------------------------------------------------------------------------
01748 //
01749 //  Private method: DevMgmt_DeviceInfo_Rsp
01750 //
01751 //  @brief  Internal method to show device information of NSL01
01752 //
01753 //  @param TWiMOD_HCI_Message* : Rx message struct in WiMOD_HCI_Layer.h
01754 //
01755 //------------------------------------------------------------------------------
01756 
01757 void NSL01::DevMgmt_DeviceInfo_Rsp(TWiMOD_HCI_Message*  rxMessage)
01758 {   
01759     //--Internal variables and constants
01760     UINT32 result_UINT32;    
01761 
01762     LoRaWAN_ShowResponse("device information response", DeviceMgmt_StatusStrings, rxMessage->Payload[0]);
01763 
01764     if (rxMessage->Payload[0] == DEVMGMT_STATUS_OK)
01765     {               
01766         //*******************************
01767         //--Get radio module identifier
01768         //*******************************
01769         UINT8 module_type = rxMessage->Payload[1];
01770 
01771         //--Show information
01772         switch (module_type)
01773         {
01774             case 144:
01775                 comm_pc.printf("  Module Type   : iM880A\r\n");
01776                 break;
01777 
01778             case 146:
01779                 comm_pc.printf("  Module Type   : iM880A-L\r\n");
01780                 break;
01781 
01782             case 147:
01783                 comm_pc.printf("  Module Type   : iU880A\r\n");
01784                 break;
01785 
01786             case 152:
01787                 comm_pc.printf("  Module Type   : iM880B-L\r\n");
01788                 break;
01789 
01790             case 153:
01791                 comm_pc.printf("  Module Type   : iU880B\r\n");
01792                 break;
01793 
01794             case 154:
01795                 comm_pc.printf("  Module Type   : iM980A\r\n");
01796                 break;                           
01797 
01798             case 160:
01799                 comm_pc.printf("  Module Type   : iM881A\r\n");
01800                 break;
01801 
01802             default:
01803                 comm_pc.printf("  Module Type   : not specivied\r\n");
01804                 break;                                        
01805         }
01806 
01807         //*******************************
01808         //--Get device address
01809         //*******************************
01810 
01811         //--Convert device address (ntohl-function)
01812         result_UINT32 = Convert_Payload_Data_UINT32(&(rxMessage->Payload[2]));        
01813         comm_pc.printf("  Device Address: 0x%08x\r\n",result_UINT32);
01814 
01815         //*******************************
01816         //--Get device ID
01817         //*******************************
01818 
01819         //--Convert device address (ntohl-function)
01820         result_UINT32 = Convert_Payload_Data_UINT32(&(rxMessage->Payload[6]));        
01821         comm_pc.printf("  Device ID     : 0x%08x\r\n",result_UINT32);
01822      }
01823 
01824      flag_LoRaWAN_response = true;         
01825 }
01826 
01827 //------------------------------------------------------------------------------
01828 //
01829 //  Private method: DevMgmt_FirmwareVersion_Rsp
01830 //
01831 //  @brief  Internal method to show firmware version of NSL01.
01832 //
01833 //  @param TWiMOD_HCI_Message* : Rx message struct in WiMOD_HCI_Layer.h
01834 //
01835 //------------------------------------------------------------------------------
01836 
01837 void NSL01::DevMgmt_FirmwareVersion_Rsp(TWiMOD_HCI_Message*  rxMessage)
01838 {
01839     //--Variables for string splitting
01840     char tmp[80];
01841     char info_1[30];
01842     char info_2[30];
01843     char info_3[30];
01844     char info_4[30];
01845     char cnt= 0;
01846     char delimiter[] = ",;";
01847     char *ptr;
01848 
01849     LoRaWAN_ShowResponse("firmware information response", DeviceMgmt_StatusStrings, rxMessage->Payload[0]);
01850 
01851     if (rxMessage->Payload[0] == DEVMGMT_STATUS_OK)
01852     {
01853         comm_pc.printf("  Firmware version: V%d.%d\n\r", (int)rxMessage->Payload[2], (int)rxMessage->Payload[1]);
01854         comm_pc.printf("  Build Count     : %d\n\r", (int)MAKEWORD(rxMessage->Payload[3], rxMessage->Payload[4]));
01855 
01856         memcpy(tmp, &rxMessage->Payload[5], 10);
01857         tmp[10] = 0;
01858         comm_pc.printf("  Build Date      : %s\n\r", tmp);
01859 
01860         //--More information attached?
01861         if (rxMessage->Length > 15)
01862         {
01863             //--Add string termination
01864             rxMessage->Payload[rxMessage->Length] = 0;
01865 
01866             //--Copy attached information to temporary string
01867             memcpy(tmp, &rxMessage->Payload[15], 40);
01868 
01869             //--Find first deliminator in string
01870             ptr = strtok(tmp, delimiter);
01871 
01872             //--Split information
01873             while(ptr != NULL) 
01874             {
01875                 //--Update counter
01876                 cnt++;
01877 
01878                 //--Split information
01879                 if (cnt == 1)
01880                 {
01881                     memcpy(info_1, ptr, 20);
01882                 }
01883                 else if (cnt == 2)
01884                 {
01885                     memcpy(info_2, ptr, 20);
01886                 }
01887                 else if (cnt == 3)
01888                 {
01889                     memcpy(info_3, ptr, 20);
01890                 }
01891                 else if (cnt == 4)
01892                 {
01893                     memcpy(info_4, ptr, 20);
01894                 }
01895 
01896                 //--Find next delimiter
01897                 ptr = strtok(NULL, delimiter);
01898             }
01899 
01900             //--Show information
01901             switch (cnt)
01902             {
01903                 case 0: 
01904                     return;
01905 
01906                 case 1:
01907                     comm_pc.printf("  Firmware Image  : %s\r\n", &info_1[0]);
01908                     break;
01909 
01910                 case 2:                    
01911                     comm_pc.printf("  Firmware Image  : %s\r\n", &info_1[0]);
01912                     comm_pc.printf("  Radio Stack     : %s\r\n", &info_2[0]);
01913                     break;
01914 
01915                 case 3:                    
01916                     comm_pc.printf("  Firmware Image  : %s\r\n", &info_1[0]);
01917                     comm_pc.printf("  Radio Stack     : %s\r\n", &info_2[0]);
01918                     comm_pc.printf("  RF Band         : %s\r\n", &info_3[0]);                
01919                     break;
01920 
01921                 case 4:                    
01922                     comm_pc.printf("  Firmware Image  : %s\r\n", &info_1[0]);
01923                     comm_pc.printf("  Radio Stack     : %s\r\n", &info_2[0]);
01924                     comm_pc.printf("  RF Band         : %s\r\n", &info_3[0]);
01925                     comm_pc.printf("  Application     : %s\r\n", &info_4[0]);
01926                     break;
01927 
01928                 default:
01929                     return;                                                                        
01930             }
01931 
01932         }
01933     }
01934 
01935     flag_LoRaWAN_response = true;
01936 }
01937 
01938 //------------------------------------------------------------------------------
01939 //
01940 //  Private method: DevMgmt_DeviceStatus_Rsp
01941 //
01942 //  @brief  Internal method to show device status of NSL01.
01943 //
01944 //  @param TWiMOD_HCI_Message* : Rx message struct in WiMOD_HCI_Layer.h
01945 //
01946 //------------------------------------------------------------------------------
01947 
01948 void NSL01::DevMgmt_DeviceStatus_Rsp(TWiMOD_HCI_Message*  rxMessage)
01949 {
01950     //--Internal variables and constants
01951     char RTC_string[20];
01952     UINT16 result_UINT16;
01953     UINT32 result_UINT32;
01954 
01955     LoRaWAN_ShowResponse("device status response", DeviceMgmt_StatusStrings, rxMessage->Payload[0]);
01956 
01957     if (rxMessage->Payload[0] == DEVMGMT_STATUS_OK)
01958     {                       
01959         //****************************************
01960         //--Get System Tick resolution
01961         //****************************************
01962         UINT8 system_tick_res = rxMessage->Payload[1];
01963         comm_pc.printf("  System Tick Res.: %u ms\r\n",system_tick_res);
01964 
01965         //****************************************
01966         //--Get System Ticks since last 
01967         //--start-up/reset
01968         //****************************************
01969 
01970         //--Convert system ticks (ntohl-function)        
01971         result_UINT32 = Convert_Payload_Data_UINT32(&(rxMessage->Payload[2]));        
01972         comm_pc.printf("  System Ticks    : %lu\r\n",result_UINT32);        
01973 
01974         //****************************************
01975         //--Get Target Time 
01976         //****************************************
01977 
01978         //--Convert target time (ntohl-function)        
01979         result_UINT32 = Convert_Payload_Data_UINT32(&(rxMessage->Payload[6]));                
01980         convert_RTC_message(result_UINT32,RTC_string);
01981         comm_pc.printf("  Target Time     : %s\r\n",RTC_string); 
01982 
01983         //****************************************
01984         //--Get NVM Status
01985         //****************************************
01986 
01987         //--Convert NVM status (ntohl-function)        
01988         result_UINT16 = Convert_Payload_Data_UINT16(&(rxMessage->Payload[10]));
01989         comm_pc.printf("  NVM Status      : 0x%04X\r\n",result_UINT16);
01990 
01991         //****************************************
01992         //--Get battery level
01993         //****************************************
01994 
01995         //--Convert battery level (ntohl-function)                        
01996         result_UINT16 = Convert_Payload_Data_UINT16(&(rxMessage->Payload[12]));                        
01997         comm_pc.printf("  Battery level   : %u mV\r\n",result_UINT16);
01998 
01999         //****************************************
02000         //--Get Extra Status (Reserved)
02001         //****************************************
02002 
02003         //--Convert extra status (ntohl-function)                        
02004         result_UINT16 = Convert_Payload_Data_UINT16(&(rxMessage->Payload[14]));                        
02005         comm_pc.printf("  Extra Status    : 0x%04x\r\n",result_UINT16);
02006 
02007         //****************************************
02008         //--Tx U-Data (# unreliable data
02009         //--packets transmitted)
02010         //****************************************
02011 
02012         //--Convert Tx U-data (ntohl-function)        
02013         result_UINT32 = Convert_Payload_Data_UINT32(&(rxMessage->Payload[16]));        
02014         comm_pc.printf("  Tx U-Data       : %lu\r\n", result_UINT32);                 
02015 
02016         //****************************************
02017         //--Tx C-Data (# reliable data
02018         //--packets transmitted)
02019         //****************************************
02020 
02021         //--Convert Tx C-data (ntohl-function)        
02022         result_UINT32 = Convert_Payload_Data_UINT32(&(rxMessage->Payload[20]));        
02023         comm_pc.printf("  Tx C-Data       : %lu\r\n", result_UINT32);                         
02024 
02025         //****************************************
02026         //--Tx Error (# of packets not
02027         //--transmitted due to an error)
02028         //****************************************
02029 
02030         //--Convert Tx error (ntohl-function)        
02031         result_UINT32 = Convert_Payload_Data_UINT32(&(rxMessage->Payload[24]));        
02032         comm_pc.printf("  Tx ERROR        : %lu\r\n", result_UINT32);
02033 
02034         //****************************************
02035         //--Rx1 U-Data (# of unreliable
02036         //--packets received in 1st window)
02037         //****************************************
02038 
02039         //--Convert Rx1 U-Data (ntohl-function)        
02040         result_UINT32 = Convert_Payload_Data_UINT32(&(rxMessage->Payload[28]));        
02041         comm_pc.printf("  Rx1 U-Data      : %lu\r\n", result_UINT32);
02042 
02043         //****************************************
02044         //--Rx1 C-Data (# of reliable
02045         //--packets received in 1st window)
02046         //****************************************
02047 
02048         //--Convert Rx1 C-Data (ntohl-function)        
02049         result_UINT32 = Convert_Payload_Data_UINT32(&(rxMessage->Payload[32]));        
02050         comm_pc.printf("  Rx1 C-Data      : %lu\r\n", result_UINT32);  
02051 
02052         //****************************************
02053         //--Rx1 MIC-Error (# of packets
02054         //--received with MIC error)
02055         //****************************************
02056 
02057         //--Convert Rx1 MIC-Error (ntohl-function)        
02058         result_UINT32 = Convert_Payload_Data_UINT32(&(rxMessage->Payload[36]));        
02059         comm_pc.printf("  Rx1 MIC-Error   : %lu\r\n", result_UINT32);  
02060 
02061         //****************************************
02062         //--Rx2 U-Data (# of unreliable
02063         //--packets received in 2nd window)
02064         //****************************************
02065 
02066         //--Convert Rx2 U-Data (ntohl-function)        
02067         result_UINT32 = Convert_Payload_Data_UINT32(&(rxMessage->Payload[40]));        
02068         comm_pc.printf("  Rx2 U-Data      : %lu\r\n", result_UINT32);
02069 
02070         //****************************************
02071         //--Rx2 C-Data (# of reliable
02072         //--packets received in 2nd window)
02073         //****************************************
02074 
02075         //--Convert Rx2 C-Data (ntohl-function)        
02076         result_UINT32 = Convert_Payload_Data_UINT32(&(rxMessage->Payload[44]));        
02077         comm_pc.printf("  Rx2 C-Data      : %lu\r\n", result_UINT32);
02078 
02079         //****************************************
02080         //--Rx2 MIC-Error (# of packets
02081         //--received in 2nd window with MIC error)
02082         //****************************************
02083 
02084         //--Convert Rx2 MIC-Error (ntohl-function)        
02085         result_UINT32 = Convert_Payload_Data_UINT32(&(rxMessage->Payload[48]));        
02086         comm_pc.printf("  Rx2 MIC-Error   : %lu\r\n", result_UINT32);                                      
02087 
02088         //****************************************
02089         //--Tx Join (# of join request
02090         //--radio packets transmitted)
02091         //****************************************
02092 
02093         //--Convert Tx Join (ntohl-function)        
02094         result_UINT32 = Convert_Payload_Data_UINT32(&(rxMessage->Payload[52]));        
02095         comm_pc.printf("  Tx Join         : %lu\r\n", result_UINT32);                                      
02096 
02097         //****************************************
02098         //--Rx Accept (# of join accept
02099         //--radio packets received)
02100         //****************************************
02101 
02102         //--Convert Rx Accept (ntohl-function)        
02103         result_UINT32 = Convert_Payload_Data_UINT32(&(rxMessage->Payload[56]));        
02104         comm_pc.printf("  Rx Accept       : %lu\r\n", result_UINT32);  
02105     }
02106 
02107     flag_LoRaWAN_response = true;  
02108 }
02109 
02110 //------------------------------------------------------------------------------
02111 //
02112 //  Private method: DevMgmt_RTC_Rsp
02113 //
02114 //  @brief  Internal method to show RTC information of NSL01
02115 //
02116 //  @param TWiMOD_HCI_Message* : Rx message struct in WiMOD_HCI_Layer.h
02117 //
02118 //------------------------------------------------------------------------------
02119 
02120 void NSL01::DevMgmt_RTC_Rsp(TWiMOD_HCI_Message*  rxMessage)
02121 {
02122     //--Internal variables and constants
02123     char RTC_string[20];
02124     UINT32 result_UINT32;
02125 
02126     LoRaWAN_ShowResponse("RTC get response", DeviceMgmt_StatusStrings, rxMessage->Payload[0]);
02127 
02128     if (rxMessage->Payload[0] == DEVMGMT_STATUS_OK)
02129     {                   
02130         //****************************************
02131         //--Get RTC info
02132         //****************************************
02133 
02134         //--Convert RTC time (ntohl-function)        
02135         result_UINT32 = Convert_Payload_Data_UINT32(&(rxMessage->Payload[1]));                
02136         convert_RTC_message(result_UINT32,RTC_string);
02137         comm_pc.printf("  RTC Time : %s\r\n",RTC_string);
02138     }
02139 
02140     flag_LoRaWAN_response = true;         
02141 }
02142 
02143 //------------------------------------------------------------------------------
02144 //
02145 //  Private method: DevMgmt_Get_Alarm_Rsp
02146 //
02147 //  @brief  Internal method to show RTC alarm information of NSL01.
02148 //
02149 //  @param TWiMOD_HCI_Message* : Rx message struct in WiMOD_HCI_Layer.h
02150 //
02151 //------------------------------------------------------------------------------
02152 
02153 void NSL01::DevMgmt_Get_Alarm_Rsp(TWiMOD_HCI_Message*  rxMessage)
02154 {
02155     //--Internal variables and constants
02156     UINT8   alarm_indicator;
02157     UINT8   periodical_alarm;
02158     UINT8   hour;
02159     UINT8   minutes;
02160     UINT8   seconds;  
02161 
02162     LoRaWAN_ShowResponse("RTC alarm get response", DeviceMgmt_StatusStrings, rxMessage->Payload[0]);
02163 
02164     if (rxMessage->Payload[0] == DEVMGMT_STATUS_OK)
02165     {                   
02166         //****************************************
02167         //--Get alarm data
02168         //****************************************
02169 
02170         //--Alarm set or not set
02171         alarm_indicator =  rxMessage->Payload[1];
02172 
02173         //--Periodical alarm
02174         periodical_alarm = rxMessage->Payload[2];
02175 
02176         //--Hour
02177         hour = rxMessage->Payload[3];
02178 
02179         //--Minutes
02180         minutes = rxMessage->Payload[4]; 
02181 
02182         //--Seconds
02183         seconds = rxMessage->Payload[5];
02184 
02185         //****************************************
02186         //--Show alarm data 
02187         //****************************************        
02188         if (alarm_indicator == 0x00)
02189         {
02190             comm_pc.printf("  Alarm status : No alarm set\r\n");
02191         }
02192         else if (alarm_indicator == 0x01)
02193         {
02194             comm_pc.printf("  Alarm status : Alarm set\r\n");       
02195         }
02196         else
02197         {
02198             comm_pc.printf("  Alarm status : No information\r\n");
02199         }
02200         
02201         if (periodical_alarm == 0x00)
02202         {
02203             comm_pc.printf("  Alarm option : Single alarm\r\n");
02204         }
02205         else if (periodical_alarm == 0x01)
02206         {
02207             comm_pc.printf("  Alarm option : Daily alarm\r\n");       
02208         }
02209         else
02210         {
02211             comm_pc.printf("  Alarm option : No information\r\n");
02212         }
02213         
02214         if (((int)hour >= 0) && (hour <= 23))
02215         {
02216             comm_pc.printf("  Hour         : %u\r\n",hour);
02217         }
02218         else
02219         {
02220             comm_pc.printf("  Hour         : Out of range!\r\n");
02221         }
02222         
02223         if (((int)minutes >= 0) && (minutes <= 59))
02224         {
02225             comm_pc.printf("  Minutes      : %u\r\n",minutes);
02226         }
02227         else
02228         {
02229             comm_pc.printf("  Minutes      : Out of range!\r\n");
02230         }        
02231                 
02232         if (((int)seconds >= 0) && (seconds <= 59))
02233         {
02234             comm_pc.printf("  Seconds      : %u\r\n",seconds);
02235         }
02236         else
02237         {
02238             comm_pc.printf("  Seconds      : Out of range!\r\n");
02239         }               
02240     }
02241 
02242     flag_LoRaWAN_response = true;
02243 }
02244 
02245 //------------------------------------------------------------------------------
02246 //
02247 //  Private method: DevMgmt_OperationMode_Rsp
02248 //
02249 //  @brief  Internal method to get the system operation mode of NSL01.
02250 //
02251 //  @param TWiMOD_HCI_Message* : Rx message struct in WiMOD_HCI_Layer.h
02252 //
02253 //------------------------------------------------------------------------------
02254 
02255 void NSL01::DevMgmt_OperationMode_Rsp(TWiMOD_HCI_Message*  rxMessage)
02256 {
02257    //--Internal variables and constants
02258     UINT8 op_mode;
02259 
02260     LoRaWAN_ShowResponse("Operation mode response", DeviceMgmt_StatusStrings, rxMessage->Payload[0]);
02261 
02262     //*******************************
02263     //--Operation system mode
02264     //*******************************    
02265     op_mode = rxMessage->Payload[1];
02266 
02267     comm_pc.printf("  System operation mode: ");
02268 
02269     switch (op_mode)
02270     {
02271         case 0:
02272             comm_pc.printf("Standard application mode / default mode\r\n");
02273             break;
02274 
02275         case 1:                            
02276             comm_pc.printf("Reserved\r\n");
02277             break;        
02278 
02279         case 2:                            
02280             comm_pc.printf("Reserved\r\n");
02281             break;               
02282 
02283         case 3:                            
02284             comm_pc.printf("Customer mode\r\n");
02285             break;                       
02286 
02287         default:
02288             comm_pc.printf("Not available\r\n");                      
02289     }
02290 
02291     flag_LoRaWAN_response = true;
02292 }
02293 
02294 //------------------------------------------------------------------------------
02295 //
02296 //  Private method: LoRaWAN_Reactivate_Device_Rsp
02297 //
02298 //  @brief  Internal method to get the status of NSL01 after reactivation in
02299 //          Activation by Personalization (ABP) mode with parameters in non- 
02300 //          volatile memory.
02301 //
02302 //  @param TWiMOD_HCI_Message* : Rx message struct in WiMOD_HCI_Layer.h
02303 //
02304 //------------------------------------------------------------------------------
02305 
02306 void NSL01::LoRaWAN_Reactivate_Device_Rsp(TWiMOD_HCI_Message*  rxMessage)
02307 {
02308     //****************************************
02309     //--Status byte
02310     //****************************************    
02311     LoRaWAN_ShowResponse("device reactivation response", LoRaWAN_StatusStrings, rxMessage->Payload[0]);
02312 
02313     //****************************************
02314     //--Get device address if status ok
02315     //****************************************    
02316     if (rxMessage->Payload[0] == 0)
02317     {
02318         UINT32 address = MAKELONG(MAKEWORD(rxMessage->Payload[1],rxMessage->Payload[2]),
02319                                   MAKEWORD(rxMessage->Payload[3],rxMessage->Payload[4]));
02320 
02321         comm_pc.printf("  DeviceAddress: 0x%08X\r\n", address);
02322     }
02323 }
02324 
02325 //------------------------------------------------------------------------------
02326 //
02327 //  Private method: LoRaWAN_Process_JoinTxIndication
02328 //
02329 //  @brief  Internal event method for join network transmit indication which is
02330 //          automatically invoked whenever the join radio message has been sent
02331 //          to the host.
02332 //
02333 //  @param TWiMOD_HCI_Message* : Rx message struct in WiMOD_HCI_Layer.h
02334 //
02335 //------------------------------------------------------------------------------
02336 
02337 void NSL01::LoRaWAN_Process_JoinTxIndication(TWiMOD_HCI_Message* rxMessage)
02338 {
02339     //--Check if channel info is attached
02340     if (rxMessage->Payload[0] == 0)
02341     {
02342         //--No channel info attached
02343         comm_pc.printf("\r\nJoin Tx event - Status : ok\r\n");
02344     }
02345     else if(rxMessage->Payload[0] == 1)
02346     {
02347         //--Channel info attached
02348         comm_pc.printf("\r\nJoin Tx event: %d with parameters:\r\n", (int)rxMessage->Payload[3]);
02349         comm_pc.printf("  Channel Index     : %d\r\n", (int)rxMessage->Payload[1]);
02350         comm_pc.printf("  Data Rate Index   : %d\r\n", (int)rxMessage->Payload[2]);
02351         comm_pc.printf("  TRX Power Level   : %d [dBm]\r\n", (int)rxMessage->Payload[4]);
02352 
02353         UINT8* rxInfo = &rxMessage->Payload[5];  
02354         UINT32 airtime = (UINT32)(rxInfo[3] << 24 | rxInfo[2] << 16 | rxInfo[1] << 8 | rxInfo[0]);
02355 
02356         comm_pc.printf("  RF message airtime: %lu [ms]\r\n", airtime);
02357     }
02358     else
02359     {
02360         //--Error: No joining Tx event triggered
02361         comm_pc.printf("\r\nJoin Tx event - Status : error\r\n");
02362     }  
02363 }
02364 
02365 //------------------------------------------------------------------------------
02366 //
02367 //  Private method: LoRaWAN_Process_JoinNetworkIndication
02368 //
02369 //  @brief  Internal event method to indicate the join network procedure which
02370 //          is automatically invoked after successful reception of a server
02371 //          join response or after expiration of a complete join process without
02372 //          success.
02373 //
02374 //  @param TWiMOD_HCI_Message* : Rx message struct in WiMOD_HCI_Layer.h
02375 //
02376 //------------------------------------------------------------------------------
02377 
02378 void NSL01::LoRaWAN_Process_JoinNetworkIndication(TWiMOD_HCI_Message* rxMessage)
02379 {
02380     //--Check if channel info is attached
02381     if (rxMessage->Payload[0] == 0)
02382     {
02383         //--Only device address attached
02384         UINT32 address = MAKELONG(MAKEWORD(rxMessage->Payload[1],rxMessage->Payload[2]),
02385                                   MAKEWORD(rxMessage->Payload[3],rxMessage->Payload[4]));
02386 
02387         comm_pc.printf("\r\nDevice activated with parameters:\r\n");
02388         comm_pc.printf("  New device address: 0x%08X\r\n", address);
02389     }
02390     else if (rxMessage->Payload[0] == 1)
02391     {
02392         //--Channel info attached
02393         UINT32 address = MAKELONG(MAKEWORD(rxMessage->Payload[1],rxMessage->Payload[2]),
02394                                   MAKEWORD(rxMessage->Payload[3],rxMessage->Payload[4]));
02395 
02396         comm_pc.printf("\r\nDevice activated with parameters:\r\n");
02397         comm_pc.printf("  New device address: 0x%08X\r\n", address);
02398         comm_pc.printf("  Channel Index     : %d\r\n", (int)rxMessage->Payload[5]);
02399         comm_pc.printf("  Data Rate Index   : %d\r\n", (int)rxMessage->Payload[6]);
02400         comm_pc.printf("  RSSI              : %d [dBm]\r\n", (int)rxMessage->Payload[7]);
02401         comm_pc.printf("  SNR               : %d [dB]\r\n", (int)rxMessage->Payload[8]);
02402         comm_pc.printf("  Rx Slot           : %d\r\n", (int)rxMessage->Payload[9]);
02403     }
02404     else
02405     {
02406         //--Error: Joining failed (Timeout)
02407         comm_pc.printf("\r\nTimout network joining:\n\r");
02408     }
02409 
02410     flag_LoRaWAN_response = true;
02411 
02412     //--Trigger event function
02413     LoRa_event(LORAWAN_EVENT_MSG_JOIN_TIMEOUT);
02414 }
02415 
02416 //------------------------------------------------------------------------------
02417 //
02418 //  Private method: LoRaWAN_send_Udata_Rsp
02419 //
02420 //  @brief  Internal method to evaluate response from 'send_Udata' method.
02421 //
02422 //  @param TWiMOD_HCI_Message* : Rx message struct in WiMOD_HCI_Layer.h
02423 //
02424 //------------------------------------------------------------------------------
02425 
02426 void NSL01::LoRaWAN_send_Udata_Rsp(TWiMOD_HCI_Message* rxMessage)
02427 {
02428     //--Evaluate status byte
02429     LoRaWAN_ShowResponse("transmit U-Data response", LoRaWAN_StatusStrings, rxMessage->Payload[0]);
02430 
02431     //--Check if additional payload data exist
02432     if (rxMessage->Length > 1)
02433     {
02434         //--Channel is blocked by Duty Cycle: Get time [ms] remaining till 
02435         //--channel is available
02436         UINT8* rxInfo = &rxMessage->Payload[1];
02437         UINT32 time = (UINT32)(rxInfo[3] << 24 | rxInfo[2] << 16 | rxInfo[1] << 8 | rxInfo[0]);
02438 
02439         comm_pc.printf("  Channel available in: %lu [ms]\r\n", time);
02440     }
02441 }
02442 
02443 //------------------------------------------------------------------------------
02444 //
02445 //  Private method: LoRaWAN_Udata_Tx_Indication
02446 //
02447 //  @brief  Internal event method which is triggered by the host after a radio
02448 //          packet has been sent
02449 //
02450 //  @param TWiMOD_HCI_Message* : Rx message struct in WiMOD_HCI_Layer.h
02451 //
02452 //------------------------------------------------------------------------------
02453 
02454 void NSL01::LoRaWAN_Udata_Tx_Indication(TWiMOD_HCI_Message* rxMessage)
02455 {
02456     //--Evaluation status and payload format
02457     if (rxMessage->Payload[0] == 0x00)
02458     {
02459         comm_pc.printf("\r\nU-Radio packet has been sent successfully\r\n");
02460         flag_LoRaWAN_response = true;
02461         return;
02462     }
02463     else if (rxMessage->Payload[0] == 0x01)
02464     {
02465         comm_pc.printf("\r\nU-Radio packet has been sent successfully with attached Tx channel info:\r\n");                    
02466     }
02467     else
02468     {
02469         comm_pc.printf("\r\nU-Radio packet has not been sent! Please try again\r\n");
02470         flag_LoRaWAN_response = true;
02471         return;
02472     }
02473 
02474     //--Evaluate channel info
02475     if (rxMessage->Length > 1)
02476     {
02477         UINT8* rxInfo = &rxMessage->Payload[1];
02478 
02479         comm_pc.printf("  Channel Index       : %d\r\n",rxInfo[0]);
02480         comm_pc.printf("  Data Rate Index     : %d\r\n",rxInfo[1]);
02481         comm_pc.printf("  Number of Tx packets: %d\r\n",rxInfo[2]);
02482         comm_pc.printf("  TRX Power Level     : %d [dBm]\r\n",rxInfo[3]);
02483 
02484         UINT32 airtime = (UINT32)(rxInfo[7] << 24 | rxInfo[6] << 16 | rxInfo[5] << 8 | rxInfo[4]); 
02485         comm_pc.printf("  RF message airtime  : %lu [ms]\r\n",airtime);                
02486     }
02487 
02488     flag_LoRaWAN_response = true;
02489 }
02490 
02491 //------------------------------------------------------------------------------
02492 //
02493 //  Private method: LoRaWAN_Udata_Rx_Indication
02494 //
02495 //  @brief  Internal event method which is sent to the host after reception of
02496 //          an unreliable radio packet containing application payload.
02497 //
02498 //  @param TWiMOD_HCI_Message* : Rx message struct in WiMOD_HCI_Layer.h
02499 //
02500 //------------------------------------------------------------------------------
02501 
02502 void NSL01::LoRaWAN_Udata_Rx_Indication(TWiMOD_HCI_Message* rxMessage)
02503 {
02504     int payloadSize = rxMessage->Length - 1;
02505 
02506     //--Determine payload size
02507     if (rxMessage->Payload[0] & 0x01)
02508         payloadSize -= 5;
02509 
02510     //--Show payload data and LoRaWAN port number
02511     if (payloadSize >= 1)
02512     {
02513         comm_pc.printf("\r\nU-Radio packet received at port 0x%02X with payload: ", rxMessage->Payload[1]);
02514 
02515         for(int i = 1; i < payloadSize; i++)
02516             comm_pc.printf("%02X ", rxMessage->Payload[1+i]);
02517 
02518         comm_pc.printf("\r\n");
02519     }
02520 
02521     //--Check if ACK for uplink packet was received
02522     if (rxMessage->Payload[0] & 0x02)
02523     {
02524         comm_pc.printf("  ACK for last uplink packet received: YES\r\n");
02525     }
02526     else
02527     {
02528         comm_pc.printf("  ACK for last uplink packet received: NO\r\n");
02529     }
02530 
02531     //--Check if downlink frame is pending
02532     if (rxMessage->Payload[0] & 0x04)
02533     {
02534         comm_pc.printf("  Downlink frame pending             : YES\r\n");
02535     }
02536     else
02537     {
02538         comm_pc.printf("  Downlink frame pending             : NO\r\n");
02539     }
02540 
02541     //--Check if Rx channel info is attached
02542     comm_pc.printf("  Received channel info:\r\n");
02543 
02544     if (rxMessage->Payload[0] & 0x01)
02545     {
02546         UINT8* rxInfo = &rxMessage->Payload[1 + payloadSize];
02547 
02548         comm_pc.printf("    Channel Index                    : %d\r\n",rxInfo[0]);
02549         comm_pc.printf("    Data Rate Index                  : %d\r\n",rxInfo[1]);
02550         comm_pc.printf("    RSSI                             : %d [dBm]\r\n",rxInfo[2]);
02551         comm_pc.printf("    SNR                              : %d [dB]\r\n",rxInfo[3]);
02552         comm_pc.printf("    Rx Slot                          : %d\r\n",rxInfo[4]);
02553     }
02554     else
02555     {
02556         comm_pc.printf("    No data available\r\n");
02557     }
02558 
02559     flag_LoRaWAN_response = true;
02560 }
02561 
02562 //------------------------------------------------------------------------------
02563 //
02564 //  Private method: LoRaWAN_send_Cdata_Rsp
02565 //
02566 //  @brief  Internal method to evaluate response from 'send_Cdata' method.
02567 //
02568 //  @param TWiMOD_HCI_Message* : Rx message struct in WiMOD_HCI_Layer.h
02569 //
02570 //------------------------------------------------------------------------------
02571 
02572 void NSL01::LoRaWAN_send_Cdata_Rsp(TWiMOD_HCI_Message* rxMessage)
02573 {
02574     //--Evaluate status byte
02575     LoRaWAN_ShowResponse("transmit C-Data response", LoRaWAN_StatusStrings, rxMessage->Payload[0]);
02576 
02577     //--Check if additional payload data exist
02578     if (rxMessage->Length > 1)
02579     {
02580         //--Channel is blocked by Duty Cycle: Get time [ms] remaining till 
02581         //--channel is available
02582         UINT8* rxInfo = &rxMessage->Payload[1];
02583         UINT32 time = (UINT32)(rxInfo[3] << 24 | rxInfo[2] << 16 | rxInfo[1] << 8 | rxInfo[0]);
02584 
02585         comm_pc.printf("  Channel available in: %lu [ms]\r\n", time);
02586     }
02587 }
02588 
02589 //------------------------------------------------------------------------------
02590 //
02591 //  Private method: LoRaWAN_Cdata_Tx_Indication
02592 //
02593 //  @brief  Internal event method which is invoked by the host after a radio
02594 //          packet has been sent or if the retransmission procedure finishes
02595 //          without success.
02596 //
02597 //  @param TWiMOD_HCI_Message* : Rx message struct in WiMOD_HCI_Layer.h
02598 //
02599 //------------------------------------------------------------------------------
02600 
02601 void NSL01::LoRaWAN_Cdata_Tx_Indication(TWiMOD_HCI_Message* rxMessage)
02602 {
02603    //--Evaluation status and payload format
02604     if (rxMessage->Payload[0] == 0x00)
02605     {
02606         comm_pc.printf("\r\nC-Radio packet has been sent successfully\r\n");
02607         return;
02608     }
02609     else if (rxMessage->Payload[0] == 0x01)
02610     {
02611         comm_pc.printf("\r\nC-Radio packet has been sent successfully with attached Tx channel info:\r\n");
02612     }
02613     else if (rxMessage->Payload[0] == 0x02)
02614     {
02615         comm_pc.printf("\r\nError: No ACK received and maximum number of retransmissions reached:\r\n");
02616         flag_LoRaWAN_response = true;
02617         
02618         //--Trigger event function
02619         LoRa_event(LORAWAN_EVENT_MSG_CDATA_MAX_RETRANSMISSION);
02620         return;
02621     }
02622     else if (rxMessage->Payload[0] == 0x04)
02623     {
02624         comm_pc.printf("\r\nError: Maximum payload size exceeded for current data rate\r\n");
02625         flag_LoRaWAN_response = true;
02626 
02627         //--Trigger callback function
02628         LoRa_event(LORAWAN_EVENT_MSG_CDATA_PAYLOAD_EXCEEDED);        
02629         return;
02630     }
02631     else
02632     {
02633         comm_pc.printf("\r\nC-Radio packet has not been sent! Please try again\r\n");
02634         flag_LoRaWAN_response = true;
02635         return;
02636     }        
02637 
02638     //--Evaluate channel info
02639     if (rxMessage->Length > 1)
02640     {
02641         UINT8* rxInfo = &rxMessage->Payload[1];
02642 
02643         comm_pc.printf("  Channel Index       : %d\r\n",rxInfo[0]);
02644         comm_pc.printf("  Data Rate Index     : %d\r\n",rxInfo[1]);
02645         comm_pc.printf("  Number of Tx packets: %d\r\n",rxInfo[2]);
02646         comm_pc.printf("  TRX Power Level     : %d [dBm]\r\n",rxInfo[3]);
02647 
02648         UINT32 airtime = (UINT32)(rxInfo[7] << 24 | rxInfo[6] << 16 | rxInfo[5] << 8 | rxInfo[4]); 
02649         comm_pc.printf("  RF message airtime  : %lu [ms]\r\n",airtime);                       
02650     }
02651 }
02652 
02653 //------------------------------------------------------------------------------
02654 //
02655 //  Private method: LoRaWAN_Cdata_Rx_Indication
02656 //
02657 //  @brief  Internal event message which is sent to the host after reception of
02658 //          a reliable radio packet containing application payload. The device
02659 //          will acknowledge the reception with a set Ack-Bit in the next
02660 //          reliable/unreliable uplink radio packet to the network server.
02661 //
02662 //  @param TWiMOD_HCI_Message* : Rx message struct in WiMOD_HCI_Layer.h
02663 //
02664 //------------------------------------------------------------------------------
02665 
02666 void NSL01::LoRaWAN_Cdata_Rx_Indication(TWiMOD_HCI_Message* rxMessage)
02667 {
02668     int payloadSize = rxMessage->Length - 1;
02669 
02670     //--Determine payload size
02671     if (rxMessage->Payload[0] & 0x01)
02672         payloadSize -= 5;
02673 
02674     //--Show payload data and LoRaWAN port number
02675     if (payloadSize >= 1)
02676     {
02677         comm_pc.printf("C-Radio packet received at port: 0x%02X with payload: ", rxMessage->Payload[1]);
02678         
02679         for(int i = 1; i < payloadSize; i++)
02680             comm_pc.printf("%02X ", rxMessage->Payload[1+i]);
02681         
02682         comm_pc.printf("\r\n");
02683     }
02684 
02685     //--Check if ACK for uplink packet was received
02686     if (rxMessage->Payload[0] & 0x02)
02687     {
02688         comm_pc.printf("  ACK for last uplink packet received: YES\r\n");
02689     }
02690     else
02691     {
02692         comm_pc.printf("  ACK for last uplink packet received: NO\r\n");
02693     }
02694 
02695     //--Check if downlink frame is pending
02696     if (rxMessage->Payload[0] & 0x04)
02697     {
02698         comm_pc.printf("  Downlink frame pending             : YES\r\n");
02699     }
02700     else
02701     {
02702         comm_pc.printf("  Downlink frame pending             : NO\r\n");
02703     }
02704 
02705     //--Check if Rx channel info is attached
02706     comm_pc.printf("  Received channel info:\r\n");
02707 
02708     if (rxMessage->Payload[0] & 0x01)
02709     {
02710         UINT8* rxInfo = &rxMessage->Payload[1 + payloadSize];
02711 
02712         comm_pc.printf("    Channel Index                    : %d\r\n",rxInfo[0]);
02713         comm_pc.printf("    Data Rate Index                  : %d\r\n",rxInfo[1]);
02714         comm_pc.printf("    RSSI                             : %d [dBm]\r\n",rxInfo[2]);
02715         comm_pc.printf("    SNR                              : %d [dB]\r\n",rxInfo[3]);
02716         comm_pc.printf("    Rx Slot                          : %d\r\n",rxInfo[4]);
02717     }
02718     else
02719     {
02720         comm_pc.printf("    No data available\r\n");
02721     }
02722 
02723     flag_LoRaWAN_response = true;
02724 }
02725 
02726 //------------------------------------------------------------------------------
02727 //
02728 //  Private method: LoRaWAN_Rx_NoData_Indication (not used at the moment)
02729 //
02730 //  @brief  Internal event method which is sent to the host in case no expected
02731 //          confirmation or data has been received as a result of prior reliable
02732 //          uplink radio packet.
02733 //
02734 //  @note  Method is not used at the moment!
02735 //
02736 //  @param TWiMOD_HCI_Message* : Rx message struct in WiMOD_HCI_Layer.h
02737 //
02738 //------------------------------------------------------------------------------
02739 
02740 void NSL01::LoRaWAN_Rx_NoData_Indication(TWiMOD_HCI_Message* rxMessage)
02741 {
02742     //--Check if error code is attached
02743     if (rxMessage->Payload[0] & 0x02)
02744     {
02745         comm_pc.printf("No Rx data indication event with error code:\r\n");
02746     }
02747     else
02748     {
02749         comm_pc.printf("No Rx data indication event without error code!\r\n");
02750         
02751         flag_LoRaWAN_response = true;
02752         return;
02753     }
02754 
02755     //--Show received error code
02756     if (rxMessage->Payload[1] & 0x01)
02757     {
02758         comm_pc.printf("  Wrong MType received\r\n");
02759     }
02760 
02761     if (rxMessage->Payload[1] & 0x02)
02762     {
02763         comm_pc.printf("  Wrong Device Address received\r\n");
02764     }
02765 
02766     if (rxMessage->Payload[1] & 0x04)
02767     {
02768         comm_pc.printf("  Wrong MIC received\r\n");
02769     }
02770 
02771     if (rxMessage->Payload[1] & 0x08)
02772     {
02773         comm_pc.printf("  Unexpected FCnt received\r\n");
02774     }
02775 
02776     if (rxMessage->Payload[1] & 0x10)
02777     {
02778         comm_pc.printf("  Wrong MAC commands received\r\n");
02779     }
02780 
02781     if (rxMessage->Payload[1] & 0x20)
02782     {
02783         comm_pc.printf("  Wrong downlink received\r\n");
02784     }
02785 
02786     if (rxMessage->Payload[1] & 0x40)
02787     {
02788         comm_pc.printf("  Expected ACK missing\r\n");
02789     }
02790 
02791     flag_LoRaWAN_response = true;
02792 }
02793 
02794 //------------------------------------------------------------------------------
02795 //
02796 //  Private method: LoRaWAN_Set_RadioStack_Config_Rsp
02797 //
02798 //  @brief  Internal method to evaluate response from 'set_radio_stack_config'
02799 //          method
02800 //
02801 //  @param TWiMOD_HCI_Message* : Rx message struct in WiMOD_HCI_Layer.h
02802 //
02803 //------------------------------------------------------------------------------
02804 
02805 void NSL01::LoRaWAN_Set_RadioStack_Config_Rsp(TWiMOD_HCI_Message* rxMessage)
02806 {
02807     //--Internal variables and constants
02808     UINT8   error_code;
02809     UINT8   flag_data_rate;
02810     UINT8   flag_Tx_power;
02811     UINT8   flag_band_index;
02812 
02813     //****************************************
02814     //--Status byte
02815     //****************************************
02816     LoRaWAN_ShowResponse("radio stack config response", LoRaWAN_StatusStrings, rxMessage->Payload[0]);
02817 
02818     //****************************************
02819     //--Optional Payload (Error Codes)
02820     //****************************************
02821     if (rxMessage->Length > 1)
02822     {
02823         //--Get complete error code
02824         error_code = rxMessage->Payload[1];
02825 
02826         //--Extract flag of data rate
02827         flag_data_rate = (error_code & 0x01);
02828 
02829         //--Flag correct TX power level
02830         flag_Tx_power = (error_code & 0x02);
02831 
02832         //--Flag correct band index
02833         flag_band_index = (error_code & 0x20);
02834 
02835         //--Show error codes
02836         comm_pc.printf("  Error code for current radio stack configuration:\r\n");
02837 
02838         if (flag_data_rate)
02839             comm_pc.printf("    Data Rate     : Wrong\r\n");
02840 
02841         if (flag_Tx_power)
02842             comm_pc.printf("    TX Power Level: Wrong\r\n");
02843 
02844         if (flag_band_index)
02845             comm_pc.printf("    Band Index    : Wrong\r\n");
02846     }
02847 
02848     flag_LoRaWAN_response = true;
02849 }
02850 
02851 //------------------------------------------------------------------------------
02852 //
02853 //  Private method: LoRaWAN_Get_RadioStack_Config_Rsp
02854 //
02855 //  @brief  Internal method to evaluate response from 'get_radio_stack_config'
02856 //          method.
02857 //
02858 //  @param TWiMOD_HCI_Message* : Rx message struct in WiMOD_HCI_Layer.h
02859 //
02860 //------------------------------------------------------------------------------
02861 
02862 void NSL01::LoRaWAN_Get_RadioStack_Config_Rsp(TWiMOD_HCI_Message* rxMessage)
02863 {
02864     //--Internal variables and constants
02865     UINT8   data_rate_index;
02866     UINT8   Tx_power;
02867     UINT8   options;
02868     UINT8   adaptive_data_rate;
02869     UINT8   duty_cycle_control;
02870     UINT8   class_C_support;
02871     UINT8   RF_packet_format;
02872     UINT8   forwarding;
02873     UINT8   power_saving;
02874     UINT8   number_retransmissions;
02875     UINT8   band_index;
02876     UINT8   header_MAC_cmd_capacity;
02877 
02878     //****************************************
02879     //--Status byte
02880     //****************************************
02881     LoRaWAN_ShowResponse("radio stack config response", DeviceMgmt_StatusStrings, rxMessage->Payload[0]);
02882 
02883     //****************************************
02884     //--Get data rate index
02885     //****************************************
02886     comm_pc.printf("  Modulation parameters      : ");
02887 
02888     data_rate_index = rxMessage->Payload[1];
02889 
02890     switch (data_rate_index)
02891     {
02892         case 0:
02893             comm_pc.printf("SF12 / 125 kHz / 250 bps\r\n");
02894             break;
02895 
02896         case 1:
02897             comm_pc.printf("SF11 / 125 kHz / 440 bps\r\n");
02898             break;
02899 
02900         case 2:
02901             comm_pc.printf("SF10 / 125 kHz / 980 bps\r\n");
02902             break;
02903 
02904         case 3:
02905             comm_pc.printf("SF9 / 125 kHz / 1760 bps\r\n");
02906             break;
02907 
02908         case 4:
02909             comm_pc.printf("SF8 / 125 kHz / 3125 bps\r\n");
02910             break;
02911 
02912         case 5:
02913             comm_pc.printf("SF7 / 125 kHz / 5470 bps\r\n");
02914             break;
02915 
02916         case 6:
02917             comm_pc.printf("SF7 / 250 kHz / 11000 bps\r\n");
02918             break;
02919 
02920         default:
02921             comm_pc.printf("Not specified!\r\n");
02922             break;     
02923     }
02924 
02925     //****************************************
02926     //--Get Tx power level (EIRP)
02927     //****************************************
02928     Tx_power = rxMessage->Payload[2];
02929     comm_pc.printf("  TX power (EIRP)            : %u dBm\r\n",Tx_power);
02930 
02931     //****************************************
02932     //--Options
02933     //****************************************
02934     options =  rxMessage->Payload[3];
02935 
02936     //--Adaptive data rate
02937     adaptive_data_rate = (options & 0x01);
02938 
02939     //--Duty cycle control
02940     duty_cycle_control = (options & 0x02);
02941 
02942     //--Class C support
02943     class_C_support = (options & 0x04);
02944 
02945     //--RF packet output format
02946     RF_packet_format = (options & 0x40);
02947 
02948     //--Rx MAC command forwarding
02949     forwarding = (options & 0x80);
02950 
02951     comm_pc.printf("  Options: \r\n");
02952 
02953     if (adaptive_data_rate)
02954         comm_pc.printf("    Adaptive Data Rate       : Enabled\r\n");
02955     else
02956         comm_pc.printf("    Adaptive Data Rate       : Disabled\r\n");
02957 
02958     if (duty_cycle_control)
02959         comm_pc.printf("    Duty Cycle Control       : Enabled\r\n");
02960     else
02961         comm_pc.printf("    Duty Cycle Control       : Disabled\r\n");
02962 
02963     if (class_C_support)
02964         comm_pc.printf("    Class C-Support          : Enabled\r\n");
02965     else
02966         comm_pc.printf("    Class C-Support          : Disabled\r\n");
02967 
02968     if (forwarding)
02969         comm_pc.printf("    Rx MAC command forwarding: Enabled\r\n");
02970     else
02971         comm_pc.printf("    Rx MAC command forwarding: Disabled\r\n");
02972 
02973     if (RF_packet_format)
02974         comm_pc.printf("    RF packet output format  : Extended\r\n");
02975     else
02976         comm_pc.printf("    RF packet output format  : Standard\r\n");
02977 
02978     //****************************************
02979     //--Power saving mode
02980     //****************************************
02981     power_saving =  rxMessage->Payload[4];
02982 
02983     if (power_saving == 0x00)
02984         comm_pc.printf("  Power saving mode          : OFF\r\n");
02985     else if (power_saving == 0x01)
02986         comm_pc.printf("  Power saving mode          : ON (Automatic)\r\n");
02987     else
02988         comm_pc.printf("  Power saving mode          : Not specified\r\n");
02989 
02990     //****************************************
02991     //--Number of retransmissions
02992     //****************************************
02993     number_retransmissions =  rxMessage->Payload[5];
02994     comm_pc.printf("  Number of retransmissions  : %u\r\n",number_retransmissions);
02995 
02996     //****************************************
02997     //--Band Index
02998     //****************************************
02999     band_index =  rxMessage->Payload[6];
03000 
03001     comm_pc.printf("  Band Selection             : ");
03002 
03003     switch (band_index)
03004     {
03005         case 1:
03006             comm_pc.printf("EU 868 MHz\r\n");
03007             break;
03008 
03009         case 2:
03010             comm_pc.printf("US 915 MHz\r\n");
03011             break;
03012 
03013         case 3:
03014             comm_pc.printf("IN 865 MHz\r\n");
03015             break;
03016 
03017         case 129:
03018             comm_pc.printf("EU 868 MHz (RX2: SF9)\r\n");
03019             break;
03020 
03021         case 131:
03022             comm_pc.printf("IN 865 MHz (RX2: SF8)\r\n");
03023             break;
03024 
03025         default:
03026             comm_pc.printf("Not supported\r\n");
03027     }
03028 
03029     //****************************************
03030     //--Header MAC command capacity
03031     //****************************************
03032     header_MAC_cmd_capacity =  rxMessage->Payload[7];
03033     comm_pc.printf("  Header MAC cmd capacity    : %u\r\n",header_MAC_cmd_capacity);
03034 
03035     flag_LoRaWAN_response = true;
03036 }
03037 
03038 //------------------------------------------------------------------------------
03039 //
03040 //  Private method: LoRaWAN_Get_FreqBand_Rsp
03041 //
03042 //  @brief  Internal method to evaluate response from 'get_freqband_info'
03043 //          method.
03044 //
03045 //  @param TWiMOD_HCI_Message* : Rx message struct in WiMOD_HCI_Layer.h
03046 //
03047 //------------------------------------------------------------------------------
03048 
03049 void NSL01::LoRaWAN_Get_FreqBand_Rsp(TWiMOD_HCI_Message* rxMessage)
03050 {
03051     //--Internal variables and constants
03052     int i = 0;
03053     UINT8   number_of_digits;
03054     UINT8   number_of_bands;
03055     UINT8   band_index;
03056     UINT8   EIRP_band_index;
03057 
03058    //****************************************
03059     //--Status byte
03060     //****************************************
03061     LoRaWAN_ShowResponse("frequency band response", DeviceMgmt_StatusStrings, rxMessage->Payload[0]);
03062 
03063     //--Check if additional payload data is available
03064     if (rxMessage->Length < 4)
03065     {
03066         flag_LoRaWAN_response = true;
03067         return;
03068     }
03069 
03070     //--Determine number of frequency bands
03071     number_of_bands = (rxMessage->Length - 3) / 2;
03072 
03073     //--Show frequency band and corresponding max. EIRP
03074     for (i= 0; i < number_of_bands+1; i++)
03075     {
03076         //****************************************
03077         //--Band Index n
03078         //****************************************
03079         band_index = rxMessage->Payload[1+2*i];
03080         number_of_digits = 0;
03081 
03082         //--Adapt string output length
03083         if (band_index < 10)
03084         {
03085             comm_pc.printf("  Band Index %u              : ",band_index);
03086             number_of_digits = 1;
03087         }
03088         else if (band_index >= 10 && band_index < 100)
03089         {
03090             comm_pc.printf("  Band Index %u             : ",band_index);
03091             number_of_digits = 2;
03092         }
03093         else if (band_index >= 100)
03094         {
03095             comm_pc.printf("  Band Index %u            : ",band_index);
03096             number_of_digits = 3;
03097         }
03098 
03099         switch (band_index)
03100         {
03101             case 1:
03102                 comm_pc.printf("EU 868 MHz\r\n");
03103                 break;
03104 
03105             case 2:
03106                 comm_pc.printf("US 915 MHz\r\n");
03107                 break;
03108 
03109             case 3:
03110                 comm_pc.printf("IN 865 MHz\r\n");
03111                 break;
03112 
03113             case 129:
03114                 comm_pc.printf("EU 868 MHz (RX2: SF9)\r\n");
03115                 break;
03116 
03117             case 131:
03118                 comm_pc.printf("IN 865 MHz (RX2: SF8)\r\n");
03119                 break;
03120 
03121             default:
03122                 comm_pc.printf("Not supported\r\n");
03123         }
03124 
03125         //****************************************
03126         //--Max. EIRP Band Index n
03127         //****************************************
03128         EIRP_band_index = rxMessage->Payload[2+2*i];
03129 
03130         //--Adapt string output length
03131         if ((EIRP_band_index < 10) && (number_of_digits == 1))
03132             comm_pc.printf("  Max. EIRP Band Index %u     : %u\r\n",band_index,EIRP_band_index);
03133         else if ((EIRP_band_index < 10) && (number_of_digits == 2))
03134             comm_pc.printf("  Max. EIRP Band Index %u    : %u\r\n",band_index,EIRP_band_index);
03135         else if ((EIRP_band_index < 10) && (number_of_digits == 3))
03136             comm_pc.printf("  Max. EIRP Band Index %u   : %u\r\n",band_index,EIRP_band_index);
03137         else if ((EIRP_band_index >= 10 && EIRP_band_index < 100) && (number_of_digits == 1))
03138             comm_pc.printf("  Max. EIRP Band Index %u    : %u\r\n",band_index,EIRP_band_index);
03139         else if ((EIRP_band_index >= 10 && EIRP_band_index < 100) && (number_of_digits == 2))
03140             comm_pc.printf("  Max. EIRP Band Index %u   : %u\r\n",band_index,EIRP_band_index);
03141         else if ((EIRP_band_index >= 10 && EIRP_band_index < 100) && (number_of_digits == 3))
03142             comm_pc.printf("  Max. EIRP Band Index %u  : %u\r\n",band_index,EIRP_band_index);
03143         else if ((EIRP_band_index >= 100) && (number_of_digits == 1))
03144             comm_pc.printf("  Max. EIRP Band Index %u   : %u\r\n",band_index,EIRP_band_index);
03145         else if ((EIRP_band_index >= 100) && (number_of_digits == 2))
03146             comm_pc.printf("  Max. EIRP Band Index %u  : %u\r\n",band_index,EIRP_band_index);
03147         else if ((EIRP_band_index >= 100) && (number_of_digits == 3))
03148             comm_pc.printf("  Max. EIRP Band Index %u : %u\r\n",band_index,EIRP_band_index);
03149     }
03150 
03151     flag_LoRaWAN_response = true;
03152 }
03153 
03154 //------------------------------------------------------------------------------
03155 //
03156 //  Private method: LoRaWAN_Get_DeviceEUI_Rsp
03157 //
03158 //  @brief  Internal method to evaluate response from 'get_EUI' method.
03159 //
03160 //  @param TWiMOD_HCI_Message* : Rx message struct in WiMOD_HCI_Layer.h
03161 //
03162 //------------------------------------------------------------------------------
03163 
03164 void NSL01::LoRaWAN_Get_DeviceEUI_Rsp(TWiMOD_HCI_Message* rxMessage)
03165 {
03166     //--Internal variables and constants
03167     UINT8*  dstPtr;
03168     UINT8   index;
03169     UINT8   device_EUI[EUI_LEN];
03170 
03171     //****************************************
03172     //--Status byte
03173     //****************************************
03174     LoRaWAN_ShowResponse("device EUI response", DeviceMgmt_StatusStrings, rxMessage->Payload[0]);
03175 
03176     //****************************************
03177     //--Device EUI
03178     //****************************************
03179     dstPtr  = &rxMessage->Payload[1];
03180     index   = 0;
03181 
03182     comm_pc.printf("  Device EUI: ");
03183 
03184     //--Copy bytes to array and show device EUI
03185     while(index < EUI_LEN)
03186     {
03187         device_EUI[index]= *dstPtr;
03188 
03189         if (index < EUI_LEN - 1)
03190             comm_pc.printf("%02X-",device_EUI[index]);
03191         else
03192             comm_pc.printf("%02X",device_EUI[index]);
03193 
03194         //--Update pointer and indices
03195         dstPtr++;
03196         index++;
03197     }
03198 
03199     comm_pc.printf("\r\n");
03200 
03201     flag_LoRaWAN_response = true;
03202 }
03203 
03204 //------------------------------------------------------------------------------
03205 //
03206 //  Private method: LoRaWAN_Get_Custom_Config_Rsp
03207 //
03208 //  @brief  Internal method to evaluate response from 'get_custom_configuration'
03209 //          method.
03210 //
03211 //  @param TWiMOD_HCI_Message* : Rx message struct in WiMOD_HCI_Layer.h
03212 //
03213 //------------------------------------------------------------------------------
03214 
03215 void NSL01::LoRaWAN_Get_Custom_Config_Rsp(TWiMOD_HCI_Message* rxMessage)
03216 {
03217     //--Internal variables and constants
03218     UINT8  RF_Gain;
03219 
03220     //****************************************
03221     //--Status byte
03222     //****************************************
03223     LoRaWAN_ShowResponse("get custom configuration response", DeviceMgmt_StatusStrings, rxMessage->Payload[0]);
03224 
03225     //****************************************
03226     //--Tx power offset
03227     //****************************************
03228     RF_Gain = rxMessage->Payload[1];
03229 
03230     //--Display result
03231     comm_pc.printf("  RF Gain: %d dBd\r\n", (INT8)RF_Gain);
03232 
03233     flag_LoRaWAN_response = true;
03234 }
03235 
03236 //------------------------------------------------------------------------------
03237 //
03238 //  Private method: LoRaWAN_Network_Status_Rsp
03239 //
03240 //  @brief  Internal method to evaluate response from 'get_network_status'
03241 //          method.
03242 //
03243 //  @param TWiMOD_HCI_Message* : Rx message struct in WiMOD_HCI_Layer.h
03244 //
03245 //------------------------------------------------------------------------------
03246 
03247 void NSL01::LoRaWAN_Network_Status_Rsp(TWiMOD_HCI_Message* rxMessage)
03248 {
03249     //--Internal variables and constants
03250     UINT8   network_status;
03251     UINT32  device_address;
03252     UINT8   data_rate_index;
03253     UINT8   Tx_power;
03254     UINT8   max_payload_size;
03255 
03256     //****************************************
03257     //--Status byte
03258     //****************************************
03259     LoRaWAN_ShowResponse("network status response", DeviceMgmt_StatusStrings, rxMessage->Payload[0]);
03260 
03261     //****************************************
03262     //--Network status
03263     //****************************************
03264     network_status = rxMessage->Payload[1];
03265 
03266     comm_pc.printf("  Network status      : ");
03267 
03268     switch (network_status)
03269     {
03270         case 0x00:
03271             comm_pc.printf("device inactive\r\n");
03272             break;
03273 
03274         case 0x01:
03275             comm_pc.printf("device active (ABP)\r\n");
03276             break;
03277 
03278         case 0x02:
03279             comm_pc.printf("device active (OTAA)\r\n");
03280             break;
03281 
03282         case 0x03:
03283             comm_pc.printf("device joining (OTAA)\r\n");
03284             break;
03285 
03286         default:
03287             comm_pc.printf("not specified\r\n");
03288             break;
03289     }
03290 
03291     //--Check if additional data is available
03292     if (rxMessage->Length < 3)
03293     {
03294         flag_LoRaWAN_response = true;
03295         return;
03296     }
03297 
03298     //****************************************
03299     //--Device Address
03300     //****************************************
03301 
03302     //--Convert device address (ntohl-function)
03303     device_address = Convert_Payload_Data_UINT32(&(rxMessage->Payload[2]));
03304     comm_pc.printf("  Device Address      : 0x%08x\r\n",device_address);
03305 
03306     //****************************************
03307     //--Data Rate Index
03308     //****************************************
03309     comm_pc.printf("  Data Rate Index     : ");
03310 
03311     data_rate_index = rxMessage->Payload[6];
03312 
03313     switch (data_rate_index)
03314     {
03315         case 0:
03316             comm_pc.printf("SF12 / 125 kHz / 250 bps\r\n");
03317             break;
03318 
03319         case 1:
03320             comm_pc.printf("SF11 / 125 kHz / 440 bps\r\n");
03321             break;
03322 
03323         case 2:
03324             comm_pc.printf("SF10 / 125 kHz / 980 bps\r\n");
03325             break;
03326 
03327         case 3:
03328             comm_pc.printf("SF9 / 125 kHz / 1760 bps\r\n");
03329             break;
03330 
03331         case 4:
03332             comm_pc.printf("SF8 / 125 kHz / 3125 bps\r\n");
03333             break;
03334 
03335         case 5:
03336             comm_pc.printf("SF7 / 125 kHz / 5740 bps\r\n");
03337             break;
03338 
03339         case 6:
03340             comm_pc.printf("SF7 / 250 kHz / 11000 bps\r\n");
03341             break;
03342 
03343         default:
03344             comm_pc.printf("Not specified!\r\n");
03345             break;
03346     }
03347 
03348     //****************************************
03349     //--Tx power level (EIRP)
03350     //****************************************
03351     Tx_power = rxMessage->Payload[7];
03352     comm_pc.printf("  Power level (EIRP)  : %u dBm\r\n",Tx_power);
03353 
03354     //****************************************
03355     //--Maximum payload size
03356     //****************************************
03357     max_payload_size = rxMessage->Payload[8];
03358     comm_pc.printf("  Maximum payload size: %u bytes\r\n",max_payload_size);
03359 
03360     flag_LoRaWAN_response = true;
03361 }
03362 
03363 //------------------------------------------------------------------------------
03364 //
03365 //  Private method: LoRaWAN_Get_TxPower_Limit_Config_Rsp
03366 //
03367 //  @brief  Internal method to evaluate response from
03368 //          'get_PowerLimit_configuration' method.
03369 //
03370 //  @param TWiMOD_HCI_Message* : Rx message struct in WiMOD_HCI_Layer.h
03371 //
03372 //------------------------------------------------------------------------------
03373 
03374 void NSL01::LoRaWAN_Get_TxPower_Limit_Config_Rsp(TWiMOD_HCI_Message* rxMessage)
03375 {
03376     //--Internal variables and constants
03377     int i = 0;
03378     UINT8   number_of_bands;
03379     UINT8   sub_band_index;
03380     UINT8   TxPower_limit_flag;
03381     UINT8   TxPower_limit;
03382 
03383     //****************************************
03384     //--Status byte
03385     //****************************************
03386     LoRaWAN_ShowResponse("Tx power limit configuration response", DeviceMgmt_StatusStrings, rxMessage->Payload[0]);
03387 
03388     //--Check if additional payload data is available
03389     if (rxMessage->Length < 2)
03390     {
03391         flag_LoRaWAN_response = true;
03392         return;
03393     }
03394 
03395     //--Determine number of frequency bands
03396     number_of_bands = (rxMessage->Length - 1) / 3;
03397 
03398    //--Show frequency sub-band and corresponding Tx power limit
03399     for (i= 0; i < number_of_bands; i++)
03400     {
03401         //****************************************
03402         //--Sub-Band Index n
03403         //****************************************
03404         sub_band_index = rxMessage->Payload[1+3*i];
03405 
03406         switch (sub_band_index)
03407         {
03408             case 0:
03409                 comm_pc.printf("  Sub-Band Index %u:\r\n",sub_band_index);
03410                 comm_pc.printf("    Frequency Range                    : 863 MHz to 865 MHz\r\n");
03411                 comm_pc.printf("    Duty Cycle                         : 0.1%%\r\n");
03412                 break;
03413 
03414             case 1:
03415                 comm_pc.printf("  Sub-Band Index %u:\r\n",sub_band_index);
03416                 comm_pc.printf("    Frequency Range                    : 865 MHz to 868 MHz\r\n");
03417                 comm_pc.printf("    Duty Cycle                         : 1%%\r\n");
03418                 break;
03419 
03420             case 2:
03421                 comm_pc.printf("  Sub-Band Index %u:\r\n",sub_band_index);
03422                 comm_pc.printf("    Frequency Range                    : 868 MHz to 868.6 MHz\r\n");
03423                 comm_pc.printf("    Duty Cycle                         : 1%%\r\n");
03424                 break;
03425 
03426             case 3:
03427                 comm_pc.printf("  Sub-Band Index %u:\r\n",sub_band_index);
03428                 comm_pc.printf("    Frequency Range                    : 868.7 MHz to 869.2 MHz\r\n");
03429                 comm_pc.printf("    Duty Cycle                         : 0.1%%\r\n");
03430                 break;
03431 
03432             case 4:
03433                 comm_pc.printf("  Sub-Band Index %u:\r\n",sub_band_index);
03434                 comm_pc.printf("    Frequency Range                    : 869.4 MHz to 869.65 MHz\r\n");
03435                 comm_pc.printf("    Duty Cycle                         : 10%%\r\n");
03436                 break;
03437 
03438             case 5:
03439                 comm_pc.printf("  Sub-Band Index %u:\r\n",sub_band_index);
03440                 comm_pc.printf("    Frequency Range                    : 869.7 MHz to 870 MHz\r\n");
03441                 comm_pc.printf("    Duty Cycle                         : 1%%\r\n");
03442                 break;
03443         }
03444 
03445         //****************************************
03446         //--Tx power limit flag for Sub-Band n
03447         //****************************************
03448         TxPower_limit_flag = rxMessage->Payload[2+3*i];
03449 
03450         if (TxPower_limit_flag == 0)
03451             comm_pc.printf("    Tx Power limit for sub-band %u      : deactivated\r\n",sub_band_index);
03452         else
03453             comm_pc.printf("    Tx Power limit for sub-band %u      : activated\r\n",sub_band_index);
03454 
03455         //****************************************
03456         //--Tx power limit for Sub-Band n
03457         //****************************************
03458         TxPower_limit = rxMessage->Payload[3+3*i];
03459 
03460         comm_pc.printf("    Tx Power limit value for sub-band %u: %u dBm\r\n",sub_band_index,TxPower_limit);
03461     }
03462 
03463     flag_LoRaWAN_response = true;
03464 }
03465 
03466 //------------------------------------------------------------------------------
03467 //
03468 //  Private method: LoRaWAN_Set_TxPower_Limit_Config_Rsp
03469 //
03470 //  @brief  Internal method to evaluate response from
03471 //          'set_PowerLimit_configuration' method.
03472 //
03473 //  @param TWiMOD_HCI_Message* : Rx message struct in WiMOD_HCI_Layer.h
03474 //
03475 //------------------------------------------------------------------------------
03476 
03477 void NSL01::LoRaWAN_Set_TxPower_Limit_Config_Rsp(TWiMOD_HCI_Message* rxMessage)
03478 {
03479     //****************************************
03480     //--Status byte
03481     //****************************************
03482     LoRaWAN_ShowResponse("Tx power limit configuration response", DeviceMgmt_StatusStrings, rxMessage->Payload[0]);
03483 
03484     //--Check if additional payload data is available
03485     if (rxMessage->Length < 2)
03486     {
03487         flag_LoRaWAN_response = true;
03488         return;
03489     }
03490 
03491     //****************************************
03492     //--Optional error code
03493     //****************************************
03494 
03495     //--Check if sub-band index was correct
03496     if (rxMessage->Payload[1] & 0x01)
03497     {
03498         comm_pc.printf("  Sub-Band index: wrong\r\n");
03499     }
03500     else
03501     {
03502         comm_pc.printf("  Sub-Band index: correct\r\n");
03503     }
03504 
03505     //--Check if Tx power limit was correct
03506     if (rxMessage->Payload[1] & 0x04)
03507     {
03508         comm_pc.printf("  Tx power value: wrong\r\n");
03509     }
03510     else
03511     {
03512         comm_pc.printf("  Tx power value: correct\r\n");
03513     }
03514 
03515     flag_LoRaWAN_response = true;
03516 }
03517 
03518 //------------------------------------------------------------------------------
03519 //
03520 //  Private method: LoRaWAN_ShowResponse
03521 //
03522 //  @brief  Internal method to show status response as human readable string.
03523 //
03524 //  @param message_string : Message string to display
03525 //  @param statusTable : Device management status strings
03526 //  @param statusID : Status identifier
03527 //
03528 //------------------------------------------------------------------------------
03529 
03530 void NSL01::LoRaWAN_ShowResponse(const char* message_string, const TIDString* statusTable, UINT8 statusID)
03531 {
03532     while(statusTable->String)
03533     {
03534         if (statusTable->ID == statusID)
03535         {
03536             //--Display status information
03537             comm_pc.printf(message_string);
03538             comm_pc.printf(" - Status(0x%02X) : ", statusID);
03539             comm_pc.printf(statusTable->String);
03540             comm_pc.printf("\n\r");
03541             
03542             //--Check status information
03543             if (statusID != DEVMGMT_STATUS_OK)
03544             {
03545                 //--Stop waiting process due to response from LoRa module
03546                 flag_LoRaWAN_response = true;
03547             }
03548             
03549             return;
03550         }
03551 
03552         statusTable++;
03553     }
03554 }
03555 
03556 //------------------------------------------------------------------------------
03557 //
03558 //  Private method: convert_RTC_message
03559 //
03560 //  @brief  Internal help method to convert RTC data.
03561 //
03562 //  @param RTC_data : RTC data in UINT32 format
03563 //  @param *RTC_string : RTC data as string
03564 //
03565 //------------------------------------------------------------------------------
03566 
03567 void NSL01::convert_RTC_message(UINT32 RTC_data, char *RTC_string)
03568 {
03569     //--Internal variables and constants
03570     char seconds_str[3];
03571     char minutes_str[3];
03572     char hours_str[3];
03573     char days_str[3];
03574     char months_str[3];
03575     UINT8 seconds, minutes, months, hours, days;
03576     UINT16 year;
03577     
03578     //--Get RTC data
03579     seconds = (RTC_data & 0x3f);                //0b00000000000000000000000000111111;
03580     minutes = (RTC_data & 0xfc0)      >> 6;     //0b00000000000000000000111111000000;        
03581     months  = (RTC_data & 0xf000)     >> 12;    //0b00000000000000001111000000000000;
03582     hours   = (RTC_data & 0x1f0000)   >> 16;    //0b00000000000111110000000000000000;
03583     days    = (RTC_data & 0x3e00000)  >> 21;    //0b00000011111000000000000000000000;
03584     year    = (RTC_data & 0xfc000000) >> 26;    //0b11111100000000000000000000000000; 
03585     
03586     //--Add 2000 to year according to specification
03587     year = year + 2000;
03588             
03589     //--Display information for debugging
03590     #ifdef DEBUG
03591         comm_pc.printf("\r\n Year: %u\r\n",year);    
03592         comm_pc.printf(" Month: %u\r\n",months);
03593         comm_pc.printf(" Day: %u\r\n",days);
03594         comm_pc.printf(" Hours: %u\r\n",hours);
03595         comm_pc.printf(" Minutes: %u\r\n",minutes);
03596         comm_pc.printf(" Seconds: %lu\r\n",seconds);
03597     #endif
03598     
03599     //--Convert seconds: UINT8 -> char
03600     if (seconds < 10)
03601     {
03602         //--Add a zero as first character
03603         sprintf(seconds_str, "0%u",seconds);
03604     }
03605     else
03606     {
03607         sprintf(seconds_str, "%u",seconds);
03608     }
03609     
03610     //--Convert minutes: UINT8 -> char
03611     if (minutes < 10)
03612     {
03613         //--Add a zero as first character
03614         sprintf(minutes_str, "0%u",minutes);
03615     }
03616     else
03617     {
03618         sprintf(minutes_str, "%u",minutes);
03619     }
03620     
03621     //--Convert hours: UINT8 -> char
03622     if (hours < 10)
03623     {
03624         //--Add a zero as first character
03625         sprintf(hours_str, "0%u",hours);
03626     }
03627     else
03628     {
03629         sprintf(hours_str, "%u",hours);
03630     }
03631     
03632     //--Convert days: UINT8 -> char
03633     if (days < 10)
03634     {
03635         //--Add a zero as first character
03636         sprintf(days_str, "0%u",days);
03637     }
03638     else
03639     {
03640         sprintf(days_str, "%u",days);
03641     }
03642     
03643     //--Convert months: UINT8 -> char
03644     if (months < 10)
03645     {
03646         //--Add a zero as first character
03647         sprintf(months_str, "0%u",months);
03648     }
03649     else
03650     {
03651         sprintf(months_str, "%u",months);
03652     }                 
03653     
03654     //--Convert data to a final string
03655     sprintf(RTC_string, "%u-%s-%s %s:%s:%s\0", year,months_str,days_str,hours_str,minutes_str,seconds_str);
03656     
03657     //--Show final string
03658     #ifdef DEBUG
03659         comm_pc.printf("RTC: %s\r\n",&RTC_string[0]); 
03660     #endif
03661 }
03662 
03663 //------------------------------------------------------------------------------
03664 //
03665 //  Private method: Convert_Payload_Data_UINT16
03666 //
03667 //  @brief  Internal help method for data conversion (UINT8 array in 
03668 //          UINT16 value).
03669 //
03670 //  @param *Payload : UINT8 array
03671 //
03672 //------------------------------------------------------------------------------
03673 
03674 UINT16 NSL01::Convert_Payload_Data_UINT16(UINT8 *Payload)
03675 {
03676     //--Temporary pointer
03677     UINT8 *dstPtr = Payload;
03678         
03679     //--Get first byte value from UINT8 array
03680     UINT8 tmp_data_0 = *dstPtr;
03681     
03682     //--Get second byte value from UINT8 array
03683     dstPtr++;
03684     UINT8 tmp_data_1 = *dstPtr;
03685     
03686     //--Convert data (LSB first)
03687     UINT16 result_conversion = (UINT16)(tmp_data_1 << 8 | tmp_data_0); 
03688                     
03689     return  result_conversion;    
03690 }
03691 
03692 //------------------------------------------------------------------------------
03693 //
03694 //  Private method: Convert_Payload_Data_UINT32
03695 //
03696 //  @brief  Internal help method for data conversion (UINT8 array in 
03697 //          UINT32 value).
03698 //
03699 //  @param *Payload : UINT8 array
03700 //
03701 //------------------------------------------------------------------------------
03702 
03703 UINT32 NSL01::Convert_Payload_Data_UINT32(UINT8 *Payload)
03704 {
03705     //--Temporary pointer
03706     UINT8 *dstPtr = Payload;
03707         
03708     //--Get first byte value from UINT8 array
03709     UINT8 tmp_data_0 = *dstPtr;
03710     
03711     //--Get second byte value from UINT8 array
03712     dstPtr++;
03713     UINT8 tmp_data_1 = *dstPtr;
03714     
03715     //--Get third byte value from UINT8 array
03716     dstPtr++;
03717     UINT8 tmp_data_2 = *dstPtr;    
03718     
03719     //--Get fourth byte value from UINT8 array
03720     dstPtr++;
03721     UINT8 tmp_data_3 = *dstPtr;    
03722     
03723     //--Convert data (LSB first)
03724     UINT32 result_conversion = (UINT32)(tmp_data_3 << 24 | tmp_data_2 << 16 | tmp_data_1 << 8 | tmp_data_0);      
03725                     
03726     return  result_conversion;    
03727 }
03728 
03729 //------------------------------------------------------------------------------
03730 //
03731 //  Private method: LoRaWAN_wait
03732 //
03733 //  @brief  Internal method to wait until response from LoRa module.
03734 //
03735 //------------------------------------------------------------------------------
03736 
03737 void NSL01::LoRaWAN_wait(void)
03738 {    
03739     while(1)
03740     {
03741         if (flag_LoRaWAN_response)
03742         {
03743             break;           
03744         }
03745         
03746         wait_us(100);
03747     }
03748     
03749     flag_LoRaWAN_response = false;
03750 }
03751 
03752 //------------------------------------------------------------------------------
03753 // end of file
03754 //------------------------------------------------------------------------------