Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Dependencies: BufferedSerial LoRaWAN-lib-st-murata ST-DEVKIT-LRWAN mbed
main.cpp
00001 /* 00002 * Copyright (c) 2017 Ivano Calabrese 00003 * Licensed under the Apache License, Version 2.0); 00004 */ 00005 00006 #include "mbed.h" 00007 #include "board.h" 00008 #include "radio.h" 00009 #include "LoRaMac.h" 00010 00011 #include "main.h" 00012 00013 00014 BufferedSerial *ser; 00015 00016 DigitalOut myled1(LED1); 00017 DigitalOut myled2(LED2); 00018 DigitalOut myled3(LED3); 00019 DigitalOut myled4(LED4); 00020 00021 /*! 00022 * Application port 00023 */ 00024 static uint8_t AppPort = LORAWAN_APP_PORT; 00025 00026 /*! 00027 * User application data size 00028 */ 00029 static uint8_t AppDataSize = LORAWAN_APP_DATA_SIZE; 00030 00031 /*! 00032 * Defines the application data transmission duty cycle 00033 */ 00034 static uint32_t TxDutyCycleTime; 00035 00036 /*! 00037 * User application data 00038 */ 00039 static uint8_t AppData[LORAWAN_APP_DATA_MAX_SIZE]; 00040 00041 static uint8_t DevEui[] = LORAWAN_DEVICE_EUI; 00042 static uint8_t AppEui[] = LORAWAN_APPLICATION_EUI; 00043 static uint8_t AppKey[] = LORAWAN_APPLICATION_KEY; 00044 00045 #if( OVER_THE_AIR_ACTIVATION == 0 ) 00046 00047 static uint8_t NwkSKey[] = LORAWAN_NWKSKEY; 00048 static uint8_t AppSKey[] = LORAWAN_APPSKEY; 00049 00050 /*! 00051 * Device address 00052 */ 00053 static uint32_t DevAddr = LORAWAN_DEVICE_ADDRESS; 00054 00055 #endif 00056 00057 /*! 00058 * Indicates if a new packet can be sent 00059 */ 00060 static bool NextTx = true; 00061 00062 /*! 00063 * Device states 00064 */ 00065 static enum eDeviceState { 00066 DEVICE_STATE_INIT, 00067 DEVICE_STATE_JOIN, 00068 DEVICE_STATE_SEND, 00069 DEVICE_STATE_CYCLE, 00070 DEVICE_STATE_SLEEP 00071 }DeviceState; 00072 00073 00074 /*! 00075 * LoRaWAN compliance tests support data 00076 */ 00077 struct ComplianceTest_s 00078 { 00079 bool Running; 00080 uint8_t State; 00081 bool IsTxConfirmed; 00082 uint8_t AppPort; 00083 uint8_t AppDataSize; 00084 uint8_t *AppDataBuffer; 00085 uint16_t DownLinkCounter; 00086 bool LinkCheck; 00087 uint8_t DemodMargin; 00088 uint8_t NbGateways; 00089 }ComplianceTest; 00090 00091 /*! 00092 * Strucure containing the Uplink status 00093 */ 00094 struct sLoRaMacUplinkStatus { 00095 uint8_t Acked; 00096 int8_t Datarate; 00097 uint16_t UplinkCounter; 00098 uint8_t Port; 00099 uint8_t *Buffer; 00100 uint8_t BufferSize; 00101 }LoRaMacUplinkStatus; 00102 volatile bool UplinkStatusUpdated = false; 00103 00104 /*! 00105 * Strucure containing the Downlink status 00106 */ 00107 struct sLoRaMacDownlinkStatus { 00108 int16_t Rssi; 00109 int8_t Snr; 00110 uint16_t DownlinkCounter; 00111 bool RxData; 00112 uint8_t Port; 00113 uint8_t *Buffer; 00114 uint8_t BufferSize; 00115 }LoRaMacDownlinkStatus; 00116 volatile bool DownlinkStatusUpdated = false; 00117 00118 /*! 00119 * Timer to handle the application data transmission duty cycle 00120 */ 00121 static TimerEvent_t TxNextPacketTimer; 00122 00123 00124 /*! 00125 * \brief Prepares the payload of the frame 00126 */ 00127 static void PrepareTxFrame( uint8_t port ) 00128 { 00129 switch( port ) { 00130 case 1: 00131 { 00132 AppData[0] = 0; 00133 AppData[1] = 1; 00134 AppData[2] = 1; 00135 AppData[3] = 1; 00136 AppData[4] = 1; 00137 AppData[5] = 1; 00138 } 00139 break; 00140 default: 00141 break; 00142 } 00143 } 00144 00145 00146 /*! 00147 * \brief Prepares the payload of the frame 00148 * 00149 * \retval [0: frame could be send, 1: error] 00150 */ 00151 static bool SendFrame( void ) 00152 { 00153 McpsReq_t mcpsReq; 00154 LoRaMacTxInfo_t txInfo; 00155 00156 mcpsReq.Type = MCPS_UNCONFIRMED; 00157 mcpsReq.Req.Unconfirmed.fPort = AppPort; 00158 mcpsReq.Req.Unconfirmed.fBuffer = AppData; 00159 mcpsReq.Req.Unconfirmed.fBufferSize = AppDataSize; 00160 mcpsReq.Req.Unconfirmed.Datarate = LORAWAN_DEFAULT_DATARATE; 00161 00162 if( LoRaMacMcpsRequest( &mcpsReq ) == LORAMAC_STATUS_OK ) 00163 { 00164 myled4 = 1; // LED4 is ON 00165 wait(0.3); // wait tempo 00166 myled4 = 0; // LED4 is OFF 00167 ser->printf("[MAIN] SendFrame == LORAMAC_STATUS_OK!! \n\r"); 00168 return false; 00169 } 00170 00171 ser->printf("[MAIN] SendFrame != LORAMAC_STATUS_OK!!\n\r"); 00172 return true; 00173 } 00174 00175 /*! 00176 * \brief Function executed on TxNextPacket Timeout event 00177 */ 00178 static void OnTxNextPacketTimerEvent( void ) 00179 { 00180 MibRequestConfirm_t mibReq; 00181 LoRaMacStatus_t status; 00182 00183 TimerStop( &TxNextPacketTimer ); 00184 00185 mibReq.Type = MIB_NETWORK_JOINED; 00186 status = LoRaMacMibGetRequestConfirm( &mibReq ); 00187 00188 if( status == LORAMAC_STATUS_OK ) 00189 { 00190 if( mibReq.Param.IsNetworkJoined == true ) 00191 { 00192 DeviceState = DEVICE_STATE_SEND; 00193 NextTx = true; 00194 } 00195 else 00196 { 00197 DeviceState = DEVICE_STATE_JOIN; 00198 } 00199 } 00200 } 00201 00202 /*! 00203 * \brief MCPS-Confirm event function 00204 * 00205 * \param [IN] mcpsConfirm - Pointer to the confirm structure, 00206 * containing confirm attributes. 00207 */ 00208 static void McpsConfirm( McpsConfirm_t *mcpsConfirm ) 00209 { 00210 if( mcpsConfirm->Status == LORAMAC_EVENT_INFO_STATUS_OK ) 00211 { 00212 switch( mcpsConfirm->McpsRequest ) 00213 { 00214 case MCPS_UNCONFIRMED: 00215 { 00216 // Check Datarate 00217 // Check TxPower 00218 break; 00219 } 00220 case MCPS_CONFIRMED: 00221 { 00222 // Check Datarate 00223 // Check TxPower 00224 // Check AckReceived 00225 // Check NbTrials 00226 LoRaMacUplinkStatus.Acked = mcpsConfirm->AckReceived; 00227 break; 00228 } 00229 case MCPS_PROPRIETARY: 00230 { 00231 break; 00232 } 00233 default: 00234 break; 00235 } 00236 LoRaMacUplinkStatus.Datarate = mcpsConfirm->Datarate; 00237 LoRaMacUplinkStatus.UplinkCounter = mcpsConfirm->UpLinkCounter; 00238 00239 UplinkStatusUpdated = true; 00240 } 00241 NextTx = true; 00242 } 00243 00244 /*! 00245 * \brief MLME-Confirm event function 00246 * 00247 * \param [IN] mlmeConfirm - Pointer to the confirm structure, 00248 * containing confirm attributes. 00249 */ 00250 static void MlmeConfirm( MlmeConfirm_t *mlmeConfirm ) 00251 { 00252 switch( mlmeConfirm->MlmeRequest ) 00253 { 00254 case MLME_JOIN: 00255 { 00256 if( mlmeConfirm->Status == LORAMAC_EVENT_INFO_STATUS_OK ) 00257 { 00258 // Status is OK, node has joined the network 00259 IsNetworkJoinedStatusUpdate = true; 00260 DeviceState = DEVICE_STATE_SEND; 00261 } 00262 else 00263 { 00264 // Join was not successful. Try to join again 00265 DeviceState = DEVICE_STATE_JOIN; 00266 } 00267 break; 00268 } 00269 case MLME_LINK_CHECK: 00270 { 00271 if( mlmeConfirm->Status == LORAMAC_EVENT_INFO_STATUS_OK ) 00272 { 00273 // Check DemodMargin 00274 // Check NbGateways 00275 if( ComplianceTest.Running == true ) 00276 { 00277 ComplianceTest.LinkCheck = true; 00278 ComplianceTest.DemodMargin = mlmeConfirm->DemodMargin; 00279 ComplianceTest.NbGateways = mlmeConfirm->NbGateways; 00280 } 00281 } 00282 break; 00283 } 00284 default: 00285 break; 00286 } 00287 NextTx = true; 00288 UplinkStatusUpdated = true; 00289 } 00290 00291 // MAIN ======================================================================== 00292 int main() { 00293 SystemClock_Config(); 00294 ser = new BufferedSerial(USBTX, USBRX); 00295 //ser->baud(115200*2); 00296 ser->baud(115200); 00297 ser->format(8); 00298 ser->printf("Hello World\n\r"); 00299 00300 00301 double tempo = 0.3; // LED blinking delay 00302 /** 00303 while(1) { 00304 myled2 = 1; // LED2 is ON 00305 wait(tempo); // wait tempo 00306 myled2 = 0; // LED2 is OFF 00307 myled1 = 1; // LED1 is ON 00308 wait(tempo); // wait tempo 00309 myled1 = 0; // LED1 is OFF 00310 myled3 = 1; // LED3 is ON 00311 wait(tempo); // wait tempo 00312 myled3 = 0; // LED3 is OFF 00313 myled4 = 1; // LED4 is ON 00314 wait(tempo); // wait tempo 00315 myled4 = 0; // LED4 is OFF 00316 } 00317 */ 00318 00319 // SX1276PingPong(); 00320 LoRaMacPrimitives_t LoRaMacPrimitives; 00321 LoRaMacCallback_t LoRaMacCallbacks; 00322 MibRequestConfirm_t mibReq; 00323 00324 BoardInit( ); 00325 00326 DeviceState = DEVICE_STATE_INIT; 00327 while( 1 ) { 00328 if( IsNetworkJoinedStatusUpdate == true ){ 00329 IsNetworkJoinedStatusUpdate = false; 00330 mibReq.Type = MIB_NETWORK_JOINED; 00331 LoRaMacMibGetRequestConfirm( &mibReq ); 00332 //SerialDisplayUpdateNetworkIsJoined( mibReq.Param.IsNetworkJoined ); 00333 } 00334 switch( DeviceState ) { 00335 case DEVICE_STATE_INIT: { 00336 LoRaMacPrimitives.MacMcpsConfirm = McpsConfirm; 00337 //LoRaMacPrimitives.MacMcpsIndication = McpsIndication; 00338 LoRaMacPrimitives.MacMlmeConfirm = MlmeConfirm; 00339 LoRaMacCallbacks.GetBatteryLevel = BoardGetBatteryLevel; 00340 LoRaMacInitialization( &LoRaMacPrimitives, &LoRaMacCallbacks ); 00341 00342 TimerInit( &TxNextPacketTimer, OnTxNextPacketTimerEvent ); 00343 00344 mibReq.Type = MIB_ADR; 00345 mibReq.Param.AdrEnable = LORAWAN_ADR_ON; 00346 LoRaMacMibSetRequestConfirm( &mibReq ); 00347 00348 mibReq.Type = MIB_PUBLIC_NETWORK; 00349 mibReq.Param.EnablePublicNetwork = LORAWAN_PUBLIC_NETWORK; 00350 LoRaMacMibSetRequestConfirm( &mibReq ); 00351 00352 mibReq.Type = MIB_DEVICE_CLASS; 00353 mibReq.Param.Class = CLASS_A; 00354 LoRaMacMibSetRequestConfirm( &mibReq ); 00355 00356 #if defined( USE_BAND_868 ) 00357 //LoRaMacTestSetDutyCycleOn( LORAWAN_DUTYCYCLE_ON ); 00358 ser->printf("USE_BAND_868 \n\r"); 00359 LoRaMacChannelAdd( 3, ( ChannelParams_t )LC4 ); 00360 LoRaMacChannelAdd( 4, ( ChannelParams_t )LC5 ); 00361 LoRaMacChannelAdd( 5, ( ChannelParams_t )LC6 ); 00362 LoRaMacChannelAdd( 6, ( ChannelParams_t )LC7 ); 00363 LoRaMacChannelAdd( 7, ( ChannelParams_t )LC8 ); 00364 LoRaMacChannelAdd( 8, ( ChannelParams_t )LC9 ); 00365 LoRaMacChannelAdd( 9, ( ChannelParams_t )LC10 ); 00366 00367 mibReq.Type = MIB_RX2_DEFAULT_CHANNEL; 00368 mibReq.Param.Rx2DefaultChannel = ( Rx2ChannelParams_t ){ 869525000, DR_3 }; 00369 LoRaMacMibSetRequestConfirm( &mibReq ); 00370 00371 mibReq.Type = MIB_RX2_CHANNEL; 00372 mibReq.Param.Rx2Channel = ( Rx2ChannelParams_t ){ 869525000, DR_3 }; 00373 LoRaMacMibSetRequestConfirm( &mibReq ); 00374 #endif 00375 LoRaMacDownlinkStatus.DownlinkCounter = 0; 00376 00377 DeviceState = DEVICE_STATE_JOIN; 00378 break; 00379 } 00380 case DEVICE_STATE_JOIN: { 00381 #if( OVER_THE_AIR_ACTIVATION != 0 ) 00382 00383 myled3 = 1; // LED2 is ON 00384 wait(tempo); // wait tempo 00385 myled3 = 0; // LED2 is OFF 00386 00387 MlmeReq_t mlmeReq; 00388 00389 mlmeReq.Type = MLME_JOIN; 00390 00391 mlmeReq.Req.Join.DevEui = DevEui; 00392 mlmeReq.Req.Join.AppEui = AppEui; 00393 mlmeReq.Req.Join.AppKey = AppKey; 00394 00395 ser->printf("DEVEUI "); 00396 for (int i = 0; i < 8; i++) { 00397 ser->printf("%02x", DevEui[i]); 00398 } 00399 ser->printf("\n\r"); 00400 00401 ser->printf("APPEUI "); 00402 for (int i = 0; i < 8; i++) { 00403 ser->printf("%02x", AppEui[i]); 00404 } 00405 ser->printf("\n\r"); 00406 00407 ser->printf("APPKEY "); 00408 for (int i = 0; i < 16; i++) { 00409 ser->printf("%02x", AppKey[i]); 00410 } 00411 ser->printf("\n\r"); 00412 00413 if( NextTx == true ) { 00414 LoRaMacMlmeRequest( &mlmeReq ); 00415 ser->printf("after LoRaMacMlmeRequest \n\r"); 00416 } 00417 DeviceState = DEVICE_STATE_SLEEP; 00418 #else 00419 mibReq.Type = MIB_NET_ID; 00420 mibReq.Param.NetID = LORAWAN_NETWORK_ID; 00421 LoRaMacMibSetRequestConfirm( &mibReq ); 00422 00423 mibReq.Type = MIB_DEV_ADDR; 00424 mibReq.Param.DevAddr = DevAddr; 00425 LoRaMacMibSetRequestConfirm( &mibReq ); 00426 00427 mibReq.Type = MIB_NWK_SKEY; 00428 mibReq.Param.NwkSKey = NwkSKey; 00429 LoRaMacMibSetRequestConfirm( &mibReq ); 00430 00431 mibReq.Type = MIB_APP_SKEY; 00432 mibReq.Param.AppSKey = AppSKey; 00433 LoRaMacMibSetRequestConfirm( &mibReq ); 00434 00435 mibReq.Type = MIB_NETWORK_JOINED; 00436 mibReq.Param.IsNetworkJoined = true; 00437 LoRaMacMibSetRequestConfirm( &mibReq ); 00438 00439 DeviceState = DEVICE_STATE_SEND; 00440 #endif 00441 IsNetworkJoinedStatusUpdate = true; 00442 break; 00443 } 00444 case DEVICE_STATE_SEND: 00445 { 00446 if( NextTx == true ) 00447 { 00448 PrepareTxFrame( AppPort ); 00449 00450 NextTx = SendFrame( ); 00451 } 00452 if( ComplianceTest.Running == true ) 00453 { 00454 // Schedule next packet transmission 00455 TxDutyCycleTime = 5000; // 5000 ms 00456 } 00457 else 00458 { 00459 // Schedule next packet transmission 00460 TxDutyCycleTime = APP_TX_DUTYCYCLE + randr( -APP_TX_DUTYCYCLE_RND, APP_TX_DUTYCYCLE_RND ); 00461 } 00462 DeviceState = DEVICE_STATE_CYCLE; 00463 break; 00464 } 00465 case DEVICE_STATE_CYCLE: { 00466 DeviceState = DEVICE_STATE_SLEEP; 00467 00468 // Schedule next packet transmission 00469 TimerSetValue( &TxNextPacketTimer, TxDutyCycleTime ); 00470 TimerStart( &TxNextPacketTimer ); 00471 break; 00472 } 00473 case DEVICE_STATE_SLEEP: { 00474 myled2 = 1; // LED2 is ON 00475 wait(tempo); // wait tempo 00476 myled2 = 0; // LED2 is OFF 00477 // Wake up through events 00478 break; 00479 } 00480 default: { 00481 DeviceState = DEVICE_STATE_INIT; 00482 break; 00483 } 00484 } 00485 } 00486 } 00487 00488 00489 00490 00491 void SystemClock_Config(void) 00492 { 00493 //#ifdef B_L072Z_LRWAN1_LORA 00494 /* 00495 * The L072Z_LRWAN1_LORA clock setup is somewhat differnt from the Nucleo board. 00496 * It has no LSE. 00497 */ 00498 RCC_ClkInitTypeDef RCC_ClkInitStruct = {0}; 00499 RCC_OscInitTypeDef RCC_OscInitStruct = {0}; 00500 00501 /* Enable HSE Oscillator and Activate PLL with HSE as source */ 00502 RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI; 00503 RCC_OscInitStruct.HSEState = RCC_HSE_OFF; 00504 RCC_OscInitStruct.HSIState = RCC_HSI_ON; 00505 RCC_OscInitStruct.HSICalibrationValue = RCC_HSICALIBRATION_DEFAULT; 00506 RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON; 00507 RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSI; 00508 RCC_OscInitStruct.PLL.PLLMUL = RCC_PLLMUL_6; 00509 RCC_OscInitStruct.PLL.PLLDIV = RCC_PLLDIV_3; 00510 00511 if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK) { 00512 // Error_Handler(); 00513 } 00514 00515 /* Set Voltage scale1 as MCU will run at 32MHz */ 00516 __HAL_RCC_PWR_CLK_ENABLE(); 00517 __HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1); 00518 00519 /* Poll VOSF bit of in PWR_CSR. Wait until it is reset to 0 */ 00520 while (__HAL_PWR_GET_FLAG(PWR_FLAG_VOS) != RESET) {}; 00521 00522 /* Select PLL as system clock source and configure the HCLK, PCLK1 and PCLK2 00523 clocks dividers */ 00524 RCC_ClkInitStruct.ClockType = (RCC_CLOCKTYPE_SYSCLK | RCC_CLOCKTYPE_HCLK | RCC_CLOCKTYPE_PCLK1 | RCC_CLOCKTYPE_PCLK2); 00525 RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK; 00526 RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1; 00527 RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1; 00528 RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1; 00529 if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_1) != HAL_OK) { 00530 // Error_Handler(); 00531 } 00532 //#endif 00533 } 00534 00535 void dump(const char *title, const void *data, int len, bool dwords) 00536 { 00537 dprintf("dump(\"%s\", 0x%x, %d bytes)", title, data, len); 00538 00539 int i, j, cnt; 00540 unsigned char *u; 00541 const int width = 16; 00542 const int seppos = 7; 00543 00544 cnt = 0; 00545 u = (unsigned char *)data; 00546 while (len > 0) { 00547 ser->printf("%08x: ", (unsigned int)data + cnt); 00548 if (dwords) { 00549 unsigned int *ip = ( unsigned int *)u; 00550 ser->printf(" 0x%08x\r\n", *ip); 00551 u+= 4; 00552 len -= 4; 00553 cnt += 4; 00554 continue; 00555 } 00556 cnt += width; 00557 j = len < width ? len : width; 00558 for (i = 0; i < j; i++) { 00559 ser->printf("%2.2x ", *(u + i)); 00560 if (i == seppos) 00561 ser->putc(' '); 00562 } 00563 ser->putc(' '); 00564 if (j < width) { 00565 i = width - j; 00566 if (i > seppos + 1) 00567 ser->putc(' '); 00568 while (i--) { 00569 printf("%s", " "); 00570 } 00571 } 00572 for (i = 0; i < j; i++) { 00573 int c = *(u + i); 00574 if (c >= ' ' && c <= '~') 00575 ser->putc(c); 00576 else 00577 ser->putc('.'); 00578 if (i == seppos) 00579 ser->putc(' '); 00580 } 00581 len -= width; 00582 u += width; 00583 ser->printf("\r\n"); 00584 } 00585 ser->printf("--\r\n"); 00586 }
Generated on Wed Jul 13 2022 13:15:10 by
1.7.2