DISCO-L072CZ-LRWAN1-base
Dependencies: BufferedSerial LoRaWAN-lib-st-murata ST-DEVKIT-LRWAN mbed
main.cpp
- Committer:
- alphaemmeo
- Date:
- 2017-12-04
- Revision:
- 1:dcf49b02bfd9
- Parent:
- 0:60680ad16314
File content as of revision 1:dcf49b02bfd9:
/* * Copyright (c) 2017 Ivano Calabrese * Licensed under the Apache License, Version 2.0); */ #include "mbed.h" #include "board.h" #include "radio.h" #include "LoRaMac.h" #include "main.h" BufferedSerial *ser; DigitalOut myled1(LED1); DigitalOut myled2(LED2); DigitalOut myled3(LED3); DigitalOut myled4(LED4); /*! * Application port */ static uint8_t AppPort = LORAWAN_APP_PORT; /*! * User application data size */ static uint8_t AppDataSize = LORAWAN_APP_DATA_SIZE; /*! * Defines the application data transmission duty cycle */ static uint32_t TxDutyCycleTime; /*! * User application data */ static uint8_t AppData[LORAWAN_APP_DATA_MAX_SIZE]; static uint8_t DevEui[] = LORAWAN_DEVICE_EUI; static uint8_t AppEui[] = LORAWAN_APPLICATION_EUI; static uint8_t AppKey[] = LORAWAN_APPLICATION_KEY; #if( OVER_THE_AIR_ACTIVATION == 0 ) static uint8_t NwkSKey[] = LORAWAN_NWKSKEY; static uint8_t AppSKey[] = LORAWAN_APPSKEY; /*! * Device address */ static uint32_t DevAddr = LORAWAN_DEVICE_ADDRESS; #endif /*! * Indicates if a new packet can be sent */ static bool NextTx = true; /*! * Device states */ static enum eDeviceState { DEVICE_STATE_INIT, DEVICE_STATE_JOIN, DEVICE_STATE_SEND, DEVICE_STATE_CYCLE, DEVICE_STATE_SLEEP }DeviceState; /*! * LoRaWAN compliance tests support data */ struct ComplianceTest_s { bool Running; uint8_t State; bool IsTxConfirmed; uint8_t AppPort; uint8_t AppDataSize; uint8_t *AppDataBuffer; uint16_t DownLinkCounter; bool LinkCheck; uint8_t DemodMargin; uint8_t NbGateways; }ComplianceTest; /*! * Strucure containing the Uplink status */ struct sLoRaMacUplinkStatus { uint8_t Acked; int8_t Datarate; uint16_t UplinkCounter; uint8_t Port; uint8_t *Buffer; uint8_t BufferSize; }LoRaMacUplinkStatus; volatile bool UplinkStatusUpdated = false; /*! * Strucure containing the Downlink status */ struct sLoRaMacDownlinkStatus { int16_t Rssi; int8_t Snr; uint16_t DownlinkCounter; bool RxData; uint8_t Port; uint8_t *Buffer; uint8_t BufferSize; }LoRaMacDownlinkStatus; volatile bool DownlinkStatusUpdated = false; /*! * Timer to handle the application data transmission duty cycle */ static TimerEvent_t TxNextPacketTimer; /*! * \brief Prepares the payload of the frame */ static void PrepareTxFrame( uint8_t port ) { switch( port ) { case 1: { AppData[0] = 0; AppData[1] = 1; AppData[2] = 1; AppData[3] = 1; AppData[4] = 1; AppData[5] = 1; } break; default: break; } } /*! * \brief Prepares the payload of the frame * * \retval [0: frame could be send, 1: error] */ static bool SendFrame( void ) { McpsReq_t mcpsReq; LoRaMacTxInfo_t txInfo; mcpsReq.Type = MCPS_UNCONFIRMED; mcpsReq.Req.Unconfirmed.fPort = AppPort; mcpsReq.Req.Unconfirmed.fBuffer = AppData; mcpsReq.Req.Unconfirmed.fBufferSize = AppDataSize; mcpsReq.Req.Unconfirmed.Datarate = LORAWAN_DEFAULT_DATARATE; if( LoRaMacMcpsRequest( &mcpsReq ) == LORAMAC_STATUS_OK ) { myled4 = 1; // LED4 is ON wait(0.3); // wait tempo myled4 = 0; // LED4 is OFF ser->printf("[MAIN] SendFrame == LORAMAC_STATUS_OK!! \n\r"); return false; } ser->printf("[MAIN] SendFrame != LORAMAC_STATUS_OK!!\n\r"); return true; } /*! * \brief Function executed on TxNextPacket Timeout event */ static void OnTxNextPacketTimerEvent( void ) { MibRequestConfirm_t mibReq; LoRaMacStatus_t status; TimerStop( &TxNextPacketTimer ); mibReq.Type = MIB_NETWORK_JOINED; status = LoRaMacMibGetRequestConfirm( &mibReq ); if( status == LORAMAC_STATUS_OK ) { if( mibReq.Param.IsNetworkJoined == true ) { DeviceState = DEVICE_STATE_SEND; NextTx = true; } else { DeviceState = DEVICE_STATE_JOIN; } } } /*! * \brief MCPS-Confirm event function * * \param [IN] mcpsConfirm - Pointer to the confirm structure, * containing confirm attributes. */ static void McpsConfirm( McpsConfirm_t *mcpsConfirm ) { if( mcpsConfirm->Status == LORAMAC_EVENT_INFO_STATUS_OK ) { switch( mcpsConfirm->McpsRequest ) { case MCPS_UNCONFIRMED: { // Check Datarate // Check TxPower break; } case MCPS_CONFIRMED: { // Check Datarate // Check TxPower // Check AckReceived // Check NbTrials LoRaMacUplinkStatus.Acked = mcpsConfirm->AckReceived; break; } case MCPS_PROPRIETARY: { break; } default: break; } LoRaMacUplinkStatus.Datarate = mcpsConfirm->Datarate; LoRaMacUplinkStatus.UplinkCounter = mcpsConfirm->UpLinkCounter; UplinkStatusUpdated = true; } NextTx = true; } /*! * \brief MLME-Confirm event function * * \param [IN] mlmeConfirm - Pointer to the confirm structure, * containing confirm attributes. */ static void MlmeConfirm( MlmeConfirm_t *mlmeConfirm ) { switch( mlmeConfirm->MlmeRequest ) { case MLME_JOIN: { if( mlmeConfirm->Status == LORAMAC_EVENT_INFO_STATUS_OK ) { // Status is OK, node has joined the network IsNetworkJoinedStatusUpdate = true; DeviceState = DEVICE_STATE_SEND; } else { // Join was not successful. Try to join again DeviceState = DEVICE_STATE_JOIN; } break; } case MLME_LINK_CHECK: { if( mlmeConfirm->Status == LORAMAC_EVENT_INFO_STATUS_OK ) { // Check DemodMargin // Check NbGateways if( ComplianceTest.Running == true ) { ComplianceTest.LinkCheck = true; ComplianceTest.DemodMargin = mlmeConfirm->DemodMargin; ComplianceTest.NbGateways = mlmeConfirm->NbGateways; } } break; } default: break; } NextTx = true; UplinkStatusUpdated = true; } // MAIN ======================================================================== int main() { SystemClock_Config(); ser = new BufferedSerial(USBTX, USBRX); //ser->baud(115200*2); ser->baud(115200); ser->format(8); ser->printf("Hello World\n\r"); double tempo = 0.3; // LED blinking delay /** while(1) { myled2 = 1; // LED2 is ON wait(tempo); // wait tempo myled2 = 0; // LED2 is OFF myled1 = 1; // LED1 is ON wait(tempo); // wait tempo myled1 = 0; // LED1 is OFF myled3 = 1; // LED3 is ON wait(tempo); // wait tempo myled3 = 0; // LED3 is OFF myled4 = 1; // LED4 is ON wait(tempo); // wait tempo myled4 = 0; // LED4 is OFF } */ // SX1276PingPong(); LoRaMacPrimitives_t LoRaMacPrimitives; LoRaMacCallback_t LoRaMacCallbacks; MibRequestConfirm_t mibReq; BoardInit( ); DeviceState = DEVICE_STATE_INIT; while( 1 ) { if( IsNetworkJoinedStatusUpdate == true ){ IsNetworkJoinedStatusUpdate = false; mibReq.Type = MIB_NETWORK_JOINED; LoRaMacMibGetRequestConfirm( &mibReq ); //SerialDisplayUpdateNetworkIsJoined( mibReq.Param.IsNetworkJoined ); } switch( DeviceState ) { case DEVICE_STATE_INIT: { LoRaMacPrimitives.MacMcpsConfirm = McpsConfirm; //LoRaMacPrimitives.MacMcpsIndication = McpsIndication; LoRaMacPrimitives.MacMlmeConfirm = MlmeConfirm; LoRaMacCallbacks.GetBatteryLevel = BoardGetBatteryLevel; LoRaMacInitialization( &LoRaMacPrimitives, &LoRaMacCallbacks ); TimerInit( &TxNextPacketTimer, OnTxNextPacketTimerEvent ); mibReq.Type = MIB_ADR; mibReq.Param.AdrEnable = LORAWAN_ADR_ON; LoRaMacMibSetRequestConfirm( &mibReq ); mibReq.Type = MIB_PUBLIC_NETWORK; mibReq.Param.EnablePublicNetwork = LORAWAN_PUBLIC_NETWORK; LoRaMacMibSetRequestConfirm( &mibReq ); mibReq.Type = MIB_DEVICE_CLASS; mibReq.Param.Class = CLASS_A; LoRaMacMibSetRequestConfirm( &mibReq ); #if defined( USE_BAND_868 ) //LoRaMacTestSetDutyCycleOn( LORAWAN_DUTYCYCLE_ON ); ser->printf("USE_BAND_868 \n\r"); LoRaMacChannelAdd( 3, ( ChannelParams_t )LC4 ); LoRaMacChannelAdd( 4, ( ChannelParams_t )LC5 ); LoRaMacChannelAdd( 5, ( ChannelParams_t )LC6 ); LoRaMacChannelAdd( 6, ( ChannelParams_t )LC7 ); LoRaMacChannelAdd( 7, ( ChannelParams_t )LC8 ); LoRaMacChannelAdd( 8, ( ChannelParams_t )LC9 ); LoRaMacChannelAdd( 9, ( ChannelParams_t )LC10 ); mibReq.Type = MIB_RX2_DEFAULT_CHANNEL; mibReq.Param.Rx2DefaultChannel = ( Rx2ChannelParams_t ){ 869525000, DR_3 }; LoRaMacMibSetRequestConfirm( &mibReq ); mibReq.Type = MIB_RX2_CHANNEL; mibReq.Param.Rx2Channel = ( Rx2ChannelParams_t ){ 869525000, DR_3 }; LoRaMacMibSetRequestConfirm( &mibReq ); #endif LoRaMacDownlinkStatus.DownlinkCounter = 0; DeviceState = DEVICE_STATE_JOIN; break; } case DEVICE_STATE_JOIN: { #if( OVER_THE_AIR_ACTIVATION != 0 ) myled3 = 1; // LED2 is ON wait(tempo); // wait tempo myled3 = 0; // LED2 is OFF MlmeReq_t mlmeReq; mlmeReq.Type = MLME_JOIN; mlmeReq.Req.Join.DevEui = DevEui; mlmeReq.Req.Join.AppEui = AppEui; mlmeReq.Req.Join.AppKey = AppKey; ser->printf("DEVEUI "); for (int i = 0; i < 8; i++) { ser->printf("%02x", DevEui[i]); } ser->printf("\n\r"); ser->printf("APPEUI "); for (int i = 0; i < 8; i++) { ser->printf("%02x", AppEui[i]); } ser->printf("\n\r"); ser->printf("APPKEY "); for (int i = 0; i < 16; i++) { ser->printf("%02x", AppKey[i]); } ser->printf("\n\r"); if( NextTx == true ) { LoRaMacMlmeRequest( &mlmeReq ); ser->printf("after LoRaMacMlmeRequest \n\r"); } DeviceState = DEVICE_STATE_SLEEP; #else mibReq.Type = MIB_NET_ID; mibReq.Param.NetID = LORAWAN_NETWORK_ID; LoRaMacMibSetRequestConfirm( &mibReq ); mibReq.Type = MIB_DEV_ADDR; mibReq.Param.DevAddr = DevAddr; LoRaMacMibSetRequestConfirm( &mibReq ); mibReq.Type = MIB_NWK_SKEY; mibReq.Param.NwkSKey = NwkSKey; LoRaMacMibSetRequestConfirm( &mibReq ); mibReq.Type = MIB_APP_SKEY; mibReq.Param.AppSKey = AppSKey; LoRaMacMibSetRequestConfirm( &mibReq ); mibReq.Type = MIB_NETWORK_JOINED; mibReq.Param.IsNetworkJoined = true; LoRaMacMibSetRequestConfirm( &mibReq ); DeviceState = DEVICE_STATE_SEND; #endif IsNetworkJoinedStatusUpdate = true; break; } case DEVICE_STATE_SEND: { if( NextTx == true ) { PrepareTxFrame( AppPort ); NextTx = SendFrame( ); } if( ComplianceTest.Running == true ) { // Schedule next packet transmission TxDutyCycleTime = 5000; // 5000 ms } else { // Schedule next packet transmission TxDutyCycleTime = APP_TX_DUTYCYCLE + randr( -APP_TX_DUTYCYCLE_RND, APP_TX_DUTYCYCLE_RND ); } DeviceState = DEVICE_STATE_CYCLE; break; } case DEVICE_STATE_CYCLE: { DeviceState = DEVICE_STATE_SLEEP; // Schedule next packet transmission TimerSetValue( &TxNextPacketTimer, TxDutyCycleTime ); TimerStart( &TxNextPacketTimer ); break; } case DEVICE_STATE_SLEEP: { myled2 = 1; // LED2 is ON wait(tempo); // wait tempo myled2 = 0; // LED2 is OFF // Wake up through events break; } default: { DeviceState = DEVICE_STATE_INIT; break; } } } } void SystemClock_Config(void) { //#ifdef B_L072Z_LRWAN1_LORA /* * The L072Z_LRWAN1_LORA clock setup is somewhat differnt from the Nucleo board. * It has no LSE. */ RCC_ClkInitTypeDef RCC_ClkInitStruct = {0}; RCC_OscInitTypeDef RCC_OscInitStruct = {0}; /* Enable HSE Oscillator and Activate PLL with HSE as source */ RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI; RCC_OscInitStruct.HSEState = RCC_HSE_OFF; RCC_OscInitStruct.HSIState = RCC_HSI_ON; RCC_OscInitStruct.HSICalibrationValue = RCC_HSICALIBRATION_DEFAULT; RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON; RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSI; RCC_OscInitStruct.PLL.PLLMUL = RCC_PLLMUL_6; RCC_OscInitStruct.PLL.PLLDIV = RCC_PLLDIV_3; if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK) { // Error_Handler(); } /* Set Voltage scale1 as MCU will run at 32MHz */ __HAL_RCC_PWR_CLK_ENABLE(); __HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1); /* Poll VOSF bit of in PWR_CSR. Wait until it is reset to 0 */ while (__HAL_PWR_GET_FLAG(PWR_FLAG_VOS) != RESET) {}; /* Select PLL as system clock source and configure the HCLK, PCLK1 and PCLK2 clocks dividers */ RCC_ClkInitStruct.ClockType = (RCC_CLOCKTYPE_SYSCLK | RCC_CLOCKTYPE_HCLK | RCC_CLOCKTYPE_PCLK1 | RCC_CLOCKTYPE_PCLK2); RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK; RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1; RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1; RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1; if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_1) != HAL_OK) { // Error_Handler(); } //#endif } void dump(const char *title, const void *data, int len, bool dwords) { dprintf("dump(\"%s\", 0x%x, %d bytes)", title, data, len); int i, j, cnt; unsigned char *u; const int width = 16; const int seppos = 7; cnt = 0; u = (unsigned char *)data; while (len > 0) { ser->printf("%08x: ", (unsigned int)data + cnt); if (dwords) { unsigned int *ip = ( unsigned int *)u; ser->printf(" 0x%08x\r\n", *ip); u+= 4; len -= 4; cnt += 4; continue; } cnt += width; j = len < width ? len : width; for (i = 0; i < j; i++) { ser->printf("%2.2x ", *(u + i)); if (i == seppos) ser->putc(' '); } ser->putc(' '); if (j < width) { i = width - j; if (i > seppos + 1) ser->putc(' '); while (i--) { printf("%s", " "); } } for (i = 0; i < j; i++) { int c = *(u + i); if (c >= ' ' && c <= '~') ser->putc(c); else ser->putc('.'); if (i == seppos) ser->putc(' '); } len -= width; u += width; ser->printf("\r\n"); } ser->printf("--\r\n"); }