Europalab Devices produces a LoRaWAN transmitting client node, specialised for higher research of actuator and sensor assisted IoT networks. https://dev.europalab.com/nlnet/20200000/
25개 이상의 토픽을 선택하실 수 없습니다. Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

376 lines
12KB

  1. /**
  2. * \file p2p_demo.c
  3. *
  4. * \brief Demo Application for MiWi P2P Implementation
  5. *
  6. * Copyright (c) 2019 Microchip Technology Inc. and its subsidiaries.
  7. *
  8. * \asf_license_start
  9. *
  10. * \page License
  11. *
  12. * Subject to your compliance with these terms, you may use Microchip
  13. * software and any derivatives exclusively with Microchip products.
  14. * It is your responsibility to comply with third party license terms applicable
  15. * to your use of third party software (including open source software) that
  16. * may accompany Microchip software.
  17. *
  18. * THIS SOFTWARE IS SUPPLIED BY MICROCHIP "AS IS". NO WARRANTIES,
  19. * WHETHER EXPRESS, IMPLIED OR STATUTORY, APPLY TO THIS SOFTWARE,
  20. * INCLUDING ANY IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY,
  21. * AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT WILL MICROCHIP BE
  22. * LIABLE FOR ANY INDIRECT, SPECIAL, PUNITIVE, INCIDENTAL OR CONSEQUENTIAL
  23. * LOSS, DAMAGE, COST OR EXPENSE OF ANY KIND WHATSOEVER RELATED TO THE
  24. * SOFTWARE, HOWEVER CAUSED, EVEN IF MICROCHIP HAS BEEN ADVISED OF THE
  25. * POSSIBILITY OR THE DAMAGES ARE FORESEEABLE. TO THE FULLEST EXTENT
  26. * ALLOWED BY LAW, MICROCHIP'S TOTAL LIABILITY ON ALL CLAIMS IN ANY WAY
  27. * RELATED TO THIS SOFTWARE WILL NOT EXCEED THE AMOUNT OF FEES, IF ANY,
  28. * THAT YOU HAVE PAID DIRECTLY TO MICROCHIP FOR THIS SOFTWARE.
  29. *
  30. * \asf_license_stop
  31. *
  32. */
  33. /************************ HEADERS ****************************************/
  34. #include "miwi_api.h"
  35. #include "miwi_p2p.h"
  36. #include "task.h"
  37. #include "p2p_demo.h"
  38. #include "mimem.h"
  39. #include "asf.h"
  40. #if defined(ENABLE_SLEEP_FEATURE)
  41. #include "sleep_mgr.h"
  42. #endif
  43. #if defined (ENABLE_CONSOLE)
  44. #include "sio2host.h"
  45. #endif
  46. #include "phy.h"
  47. #include "sw_timer.h"
  48. #if defined(PROTOCOL_P2P)
  49. uint8_t i;
  50. uint8_t TxSynCount = 0;
  51. uint8_t TxSynCount2 = 0;
  52. uint8_t TxNum = 0;
  53. uint8_t RxNum = 0;
  54. bool chk_sel_status = true; // Check _select_Status
  55. uint8_t NumOfActiveScanResponse;
  56. bool update_ed;
  57. uint8_t select_ed;
  58. uint8_t msghandledemo = 0;
  59. #if defined(ENABLE_SLEEP_FEATURE)
  60. volatile uint8_t send_data = 0; // Flag used to put a sleeping device(RFD) in sleep - wakeup - transmit cycle
  61. #endif // #if defined(ENABLE_SLEEP_FEATURE)
  62. #if defined(PERIODIC_TX)
  63. #define PERIODIC_TX_TIMER 20000
  64. void PeriodicTxCallback(void)
  65. {
  66. uint8_t dr ;
  67. RADIO_GetAttr(SPREADING_FACTOR, &dr) ;
  68. printf("Current SF = %d\r\n", dr) ;
  69. p2p_demo_unicast_to_parent() ;
  70. if(TxNum < 100000)
  71. {
  72. SwTimerStart (PeriodicTxTimerId, MS_TO_US(PERIODIC_TX_TIMER) , 0/*SW_TIMEOUT_RELATIVE*/, (void *)PeriodicTxCallback, NULL) ;
  73. }
  74. else
  75. {
  76. SwTimerStop(PeriodicTxTimerId) ;
  77. TxNum = 0 ;
  78. }
  79. }
  80. #endif // #if defined(PERIODIC_TX)
  81. void TxToutCallback(void)
  82. {
  83. #if defined(ENABLE_SLEEP_FEATURE)
  84. send_data = 0;
  85. #endif // #if defined(ENABLE_SLEEP_FEATURE)
  86. /* That bring the node back to continuous transaction cycle */
  87. PHY_DataConf(TRANSACTION_EXPIRED);
  88. SwTimerStop(TxTimerId);
  89. }
  90. void dataConfcb(uint8_t handle, miwi_status_t status, uint8_t* msgPointer)
  91. {
  92. #if defined (ENABLE_CONSOLE)
  93. printf("\nData Confirm: Handle: %d status:%d \r\n", handle, status);
  94. #endif // #if defined (ENABLE_CONSOLE)
  95. #if defined(ENABLE_SLEEP_FEATURE)
  96. send_data = 0;
  97. #endif // #if defined(ENABLE_SLEEP_FEATURE)
  98. /* Stop transmission timeout timer */
  99. SwTimerStop(TxTimerId);
  100. /* Free payload buffer allocated */
  101. MiMem_Free(msgPointer);
  102. }
  103. void run_p2p_demo(void)
  104. {
  105. #if defined(ENABLE_SLEEP_FEATURE)
  106. if (Total_Connections())
  107. {
  108. /* At least device is connected to one peer device */
  109. if(!(P2PStatus.bits.DataRequesting || P2PStatus.bits.RxHasUserData || send_data))
  110. {
  111. /* Put the transceiver into sleep */
  112. MiApp_TransceiverPowerState(POWER_STATE_SLEEP);
  113. #if defined (ENABLE_CONSOLE)
  114. printf("\r\nDevice is sleeping");
  115. /* Disable UART */
  116. sio2host_disable();
  117. #endif // #if defined (ENABLE_CONSOLE)
  118. // Turned OFF RF Switch
  119. struct port_config pin_conf;
  120. port_get_config_defaults(&pin_conf);
  121. pin_conf.direction = PORT_PIN_DIR_OUTPUT;
  122. port_pin_set_config(RF_SWITCH_PIN, &pin_conf);
  123. port_pin_set_output_level(RF_SWITCH_PIN, RF_SWITCH_INACTIVE);
  124. /* Put the MCU into sleep */
  125. sm_sleep((RFD_WAKEUP_INTERVAL - 2));
  126. #if defined (ENABLE_CONSOLE)
  127. /* Enable UART */
  128. sio2host_enable();
  129. printf("\r\nDevice WokeUp");
  130. #endif // #if defined (ENABLE_CONSOLE)
  131. /* Wakeup the transceiver and send data request*/
  132. MiApp_TransceiverPowerState(POWER_STATE_WAKEUP_DR);
  133. }
  134. }
  135. #endif // #if defined(ENABLE_SLEEP_FEATURE)
  136. {
  137. /*******************************************************************/
  138. // If no packet received, now we can check if we want to send out
  139. // any information.
  140. // Function ButtonPressed will return if any of the two buttons
  141. // has been pushed.
  142. /*******************************************************************/
  143. /* Read the button */
  144. uint8_t PressedButton = ButtonPressed();
  145. switch( PressedButton )
  146. {
  147. case 1:
  148. {
  149. /*******************************************************************/
  150. // Button 1 pressed. We need to send out the bitmap of word "MiWi".
  151. // First call MiApp_FlushTx to reset the Transmit buffer. Then fill
  152. // the buffer one byte by one byte by calling function
  153. // MiApp_WriteData
  154. /*******************************************************************/
  155. uint8_t* dataPtr = NULL;
  156. uint8_t dataLen = 0;
  157. uint16_t broadcastAddress = 0xFFFF;
  158. #if defined(ENABLE_SECURITY)
  159. /* Allocate buffer for secured payload */
  160. dataPtr = MiMem_Alloc(CALC_SEC_PAYLOAD_SIZE(MAX_SEC_BCAST_PAYLOAD));
  161. if (NULL == dataPtr)
  162. return;
  163. for(i = 0; i < MAX_SEC_BCAST_PAYLOAD; i++)
  164. #else
  165. /* Allocate buffer for non-secured payload */
  166. dataPtr = MiMem_Alloc(CALC_SEC_PAYLOAD_SIZE(MAX_NSEC_BCAST_PAYLOAD));
  167. if (NULL == dataPtr)
  168. return;
  169. for(i = 0; i < MAX_NSEC_BCAST_PAYLOAD; i++)
  170. #endif // #if defined(ENABLE_SECURITY)
  171. {
  172. // Fill TX buffer User DATA
  173. dataPtr[dataLen++] = 0x42; // 'B'
  174. }
  175. TxSynCount++;
  176. #if defined(ENABLE_SLEEP_FEATURE)
  177. send_data = 1;
  178. #endif // #if defined(ENABLE_SLEEP_FEATURE)
  179. /* Broadcast the message */
  180. if(MiApp_SendData(SHORT_ADDR_LEN, (uint8_t *)&broadcastAddress, dataLen, dataPtr, msghandledemo++, true, dataConfcb)== false)
  181. {
  182. #if defined(ENABLE_SLEEP_FEATURE)
  183. PHY_DataConf(FAILURE);
  184. #endif // #if defined(ENABLE_SLEEP_FEATURE)
  185. DemoOutput_BroadcastFail();
  186. }
  187. else
  188. {
  189. /* Start timer for transmission timeout */
  190. SwTimerStart (TxTimerId, MS_TO_US(5000), 0/*SW_TIMEOUT_RELATIVE*/, (void *)TxToutCallback, NULL);
  191. }
  192. /* Update display/console */
  193. DemoOutput_UpdateTxRx(++TxNum, RxNum);
  194. DemoOutput_Instruction();
  195. }
  196. break;
  197. case 2:
  198. /* Button 2 pressed */
  199. chk_sel_status = true;
  200. select_ed = 0;
  201. update_ed = true;
  202. while(update_ed == true)
  203. {
  204. // Peer Device Info
  205. #if defined (ENABLE_LCD)
  206. LCD_Erase();
  207. snprintf(LCDText, sizeof(LCDText),(char*)"SW:%02d-%02x%02x%02x \nBUTTON1: Change node",select_ed,ConnectionTable[select_ed].Address[0],
  208. ConnectionTable[select_ed].Address[1],ConnectionTable[select_ed].Address[2]);
  209. LCD_Update();
  210. #endif // #if defined (ENABLE_LCD)
  211. // Display another Peer Device Address
  212. chk_sel_status = true;
  213. while(chk_sel_status)
  214. {
  215. uint8_t switch_val = ButtonPressed();
  216. // While waiting in TX , RX will process if any message was available
  217. if(switch_val == 1)
  218. {
  219. uint8_t* dataPtr = NULL;
  220. uint8_t dataLen = 0;
  221. update_ed = false;
  222. chk_sel_status = false;
  223. #if defined(ENABLE_SECURITY)
  224. /* Allocate buffer for secured payload */
  225. dataPtr = MiMem_Alloc(CALC_SEC_PAYLOAD_SIZE(MAX_SEC_UCAST_PAYLOAD));
  226. if (NULL == dataPtr)
  227. return;
  228. for(i = 0; i < MAX_SEC_UCAST_PAYLOAD; i++)
  229. #else
  230. /* Allocate buffer for non-secured payload */
  231. dataPtr = MiMem_Alloc(CALC_SEC_PAYLOAD_SIZE(MAX_NSEC_UCAST_PAYLOAD));
  232. if (NULL == dataPtr)
  233. return;
  234. for(i = 0; i < MAX_NSEC_UCAST_PAYLOAD; i++)
  235. #endif // #if defined(ENABLE_SECURITY)
  236. {
  237. // Fill TX buffer User DATA
  238. dataPtr[dataLen++] = 0x55; // 'U'
  239. }
  240. TxSynCount2++;
  241. #if defined(ENABLE_SLEEP_FEATURE)
  242. send_data = 1;
  243. #endif // #if defined(ENABLE_SLEEP_FEATURE)
  244. /* Unicast the message to select_ed node */
  245. if (MiApp_SendData(LONG_ADDR_LEN, ConnectionTable[select_ed].Address, dataLen, dataPtr, msghandledemo++, 1, dataConfcb) == false)
  246. {
  247. /* That bring the node back to continuous transaction cycle */
  248. #if defined(ENABLE_SLEEP_FEATURE)
  249. PHY_DataConf(FAILURE);
  250. #endif // #if defined(ENABLE_SLEEP_FEATURE)
  251. DemoOutput_UnicastFail();
  252. }
  253. else
  254. {
  255. // Successful Transmission
  256. TxNum++;
  257. /* Start timer for transmission timeout */
  258. SwTimerStart (TxTimerId, MS_TO_US(5000), 0/*SW_TIMEOUT_RELATIVE*/, (void *)TxToutCallback, NULL);
  259. }
  260. // Update the display/console
  261. DemoOutput_UpdateTxRx(TxNum, RxNum);
  262. DemoOutput_Instruction();
  263. break;
  264. } // if(switch_val == 1)
  265. else if(switch_val == 2)
  266. {
  267. if (select_ed > conn_size-2)
  268. {
  269. // Last Peer Device
  270. select_ed = 0;
  271. }
  272. else
  273. {
  274. // Update the Display
  275. select_ed = select_ed+1;
  276. }
  277. chk_sel_status = false;
  278. } // else if(switch_val == 2)
  279. } // while(chk_sel_status), end of Peer Device selection
  280. } // while(update_ed == true), end of Display
  281. break;
  282. default:
  283. break;
  284. }
  285. }
  286. }
  287. void ReceivedDataIndication (RECEIVED_MESSAGE *ind)
  288. {
  289. /*******************************************************************/
  290. // If a packet has been received, handle the information available
  291. // in rxMessage.
  292. /*******************************************************************/
  293. if ((myPANID.v[1] == ind->SourcePANID.v[1]) && (myPANID.v[0] == ind->SourcePANID.v[0]))
  294. {
  295. #if defined(ENABLE_CONSOLE)
  296. DemoOutput_HandleMessage();
  297. #endif
  298. DemoOutput_UpdateTxRx(TxNum, ++RxNum);
  299. // Toggle LED2 to indicate receiving a packet.
  300. LED_Toggle(LED0);
  301. DemoOutput_Instruction();
  302. }
  303. else
  304. {
  305. printf("Packet received from other Source PAN ID : 0x%x%x\r\n",ind->SourcePANID.v[1],ind->SourcePANID.v[0]);
  306. }
  307. }
  308. void p2p_demo_unicast_to_parent(void)
  309. {
  310. uint8_t* dataPtr = NULL;
  311. uint8_t dataLen = 0;
  312. update_ed = false;
  313. chk_sel_status = false;
  314. #if defined(ENABLE_SECURITY)
  315. dataPtr = MiMem_Alloc(CALC_SEC_PAYLOAD_SIZE(MAX_SEC_UCAST_PAYLOAD));
  316. if (NULL == dataPtr)
  317. return;
  318. for(i = 0; i < MAX_SEC_UCAST_PAYLOAD; i++)
  319. #else
  320. dataPtr = MiMem_Alloc(CALC_SEC_PAYLOAD_SIZE(MAX_NSEC_UCAST_PAYLOAD));
  321. if (NULL == dataPtr)
  322. return;
  323. for(i = 0; i < MAX_NSEC_UCAST_PAYLOAD; i++)
  324. #endif
  325. {
  326. // Tx Buffer User Data
  327. dataPtr[dataLen++] = 0x55;
  328. }
  329. TxSynCount2++;
  330. #if defined(ENABLE_SLEEP_FEATURE)
  331. // to not enter to the sleep loop until data has been sent
  332. send_data = 1;
  333. #endif // #if defined(ENABLE_SLEEP_FEATURE)
  334. select_ed = 0 ; // parent addr: ConnectionTable[0].Address
  335. printf("\r\nTry to unicast to %02d-%02x%02x%02x\r\n", select_ed, ConnectionTable[select_ed].Address[0], ConnectionTable[select_ed].Address[1], ConnectionTable[select_ed].Address[2]) ;
  336. if( MiApp_SendData(LONG_ADDR_LEN, ConnectionTable[select_ed].Address, dataLen, dataPtr, msghandledemo++, 1, dataConfcb) == false)
  337. {
  338. #if defined(ENABLE_SLEEP_FEATURE)
  339. PHY_DataConf(FAILURE);
  340. #endif // #if defined(ENABLE_SLEEP_FEATURE)
  341. DemoOutput_UnicastFail();
  342. }
  343. else
  344. {
  345. // Successful Transmission
  346. TxNum++;
  347. SwTimerStart (TxTimerId, MS_TO_US(5000), 0/*SW_TIMEOUT_RELATIVE*/, (void *)TxToutCallback, NULL);
  348. }
  349. // Update the LCD
  350. DemoOutput_UpdateTxRx(TxNum, RxNum);
  351. DemoOutput_Instruction();
  352. printf("Tx Messages: %d - Rx Messages: %d\r\n", TxNum, RxNum) ;
  353. }
  354. #endif // #if defined(PROTOCOL_P2P)