Ivano Calabrese / Mbed 2 deprecated DISCO-L072CZ-LRWAN1-base

Dependencies:   BufferedSerial LoRaWAN-lib-st-murata ST-DEVKIT-LRWAN mbed

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers main.cpp Source File

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 }