The NSL01 library contains the software stack to control 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 have a look at: http://www.mcloud-systems.com/nsl01-lorawan-nucleo-arduino-shield
Fork of NSL01 by
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 //------------------------------------------------------------------------------
Generated on Tue Jul 12 2022 20:20:04 by
1.7.2
