diff --git a/.vscode/settings.json b/.vscode/settings.json index e7611a6e7..66715a403 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -27,8 +27,8 @@ "APPLICATION":"LoRaMac", // Select LoRaMac sub project. You can choose between: - // periodic-uplink-lpp, fuota-test-01. - "SUB_PROJECT":"periodic-uplink-lpp", + // periodic-uplink-lpp, periodic-uplink-lpp-counter, fuota-test-01. + "SUB_PROJECT":"periodic-uplink-lpp-counter", // Switch for Class B support of LoRaMac: "CLASSB_ENABLED":"ON", @@ -87,6 +87,7 @@ "se-identity.h": "c", "githubversion.h": "c", "commissioning.h": "c", - "stm32l1xx_hal_rcc.h": "c" + "stm32l1xx_hal_rcc.h": "c", + "lpm-board.h": "c" } } diff --git a/src/apps/LoRaMac/CMakeLists.txt b/src/apps/LoRaMac/CMakeLists.txt index 90ec0ca6a..a5fc3e702 100644 --- a/src/apps/LoRaMac/CMakeLists.txt +++ b/src/apps/LoRaMac/CMakeLists.txt @@ -23,7 +23,7 @@ cmake_minimum_required(VERSION 3.6) #--------------------------------------------------------------------------------------- # Allow switching of sub projects -set(SUB_PROJECT_LIST periodic-uplink-lpp fuota-test-01) +set(SUB_PROJECT_LIST periodic-uplink-lpp periodic-uplink-lpp-counter fuota-test-01) set(SUB_PROJECT periodic-uplink-lpp CACHE STRING "Default sub project is periodic-uplink-lpp") set_property(CACHE SUB_PROJECT PROPERTY STRINGS ${SUB_PROJECT_LIST}) @@ -72,6 +72,36 @@ if(SUB_PROJECT STREQUAL periodic-uplink-lpp) "${CMAKE_CURRENT_LIST_DIR}/common/LmHandler/packages/LmhpRemoteMcastSetup.c" ) +elseif(SUB_PROJECT STREQUAL periodic-uplink-lpp-counter) + + #--------------------------------------------------------------------------------------- + # Application common features handling + #--------------------------------------------------------------------------------------- + list(APPEND ${PROJECT_NAME}_COMMON + "${CMAKE_CURRENT_LIST_DIR}/common/CayenneLpp.c" + "${CMAKE_CURRENT_LIST_DIR}/common/cli.c" + "${CMAKE_CURRENT_LIST_DIR}/common/LmHandlerMsgDisplay.c" + "${CMAKE_CURRENT_LIST_DIR}/common/NvmDataMgmt.c" + ) + + #--------------------------------------------------------------------------------------- + # Application LoRaMac handler + #--------------------------------------------------------------------------------------- + list(APPEND ${PROJECT_NAME}_LMH + "${CMAKE_CURRENT_LIST_DIR}/common/LmHandler/LmHandler.c" + ) + + #--------------------------------------------------------------------------------------- + # LoRaMac handler applicative packages + #--------------------------------------------------------------------------------------- + list(APPEND ${PROJECT_NAME}_LMHP + "${CMAKE_CURRENT_LIST_DIR}/common/LmHandler/packages/FragDecoder.c" + "${CMAKE_CURRENT_LIST_DIR}/common/LmHandler/packages/LmhpClockSync.c" + "${CMAKE_CURRENT_LIST_DIR}/common/LmHandler/packages/LmhpCompliance.c" + "${CMAKE_CURRENT_LIST_DIR}/common/LmHandler/packages/LmhpFragmentation.c" + "${CMAKE_CURRENT_LIST_DIR}/common/LmHandler/packages/LmhpRemoteMcastSetup.c" + ) + elseif(SUB_PROJECT STREQUAL fuota-test-01) #--------------------------------------------------------------------------------------- diff --git a/src/apps/LoRaMac/common/Commissioning.h b/src/apps/LoRaMac/common/Commissioning.h index ee16b16a4..e7a733080 100644 --- a/src/apps/LoRaMac/common/Commissioning.h +++ b/src/apps/LoRaMac/common/Commissioning.h @@ -40,7 +40,7 @@ * When set to 1 the application uses the Over-the-Air activation procedure * When set to 0 the application uses the Personalization activation procedure */ -#define OVER_THE_AIR_ACTIVATION 1 +#define OVER_THE_AIR_ACTIVATION 0 /*! * When using ABP activation the MAC layer must know in advance to which server diff --git a/src/apps/LoRaMac/common/NvmDataMgmt.c b/src/apps/LoRaMac/common/NvmDataMgmt.c index f9e820d14..ee1bda905 100644 --- a/src/apps/LoRaMac/common/NvmDataMgmt.c +++ b/src/apps/LoRaMac/common/NvmDataMgmt.c @@ -267,6 +267,12 @@ bool NvmDataMgmtFactoryReset( void ) return false; } offset += sizeof( LoRaMacClassBNvmData_t ); + + if( NvmmReset( 8U, 0x0FF8) == false ) + { + return false; + } + #endif return true; } diff --git a/src/apps/LoRaMac/periodic-uplink-lpp-counter/SKiM980A/main.c b/src/apps/LoRaMac/periodic-uplink-lpp-counter/SKiM980A/main.c new file mode 100644 index 000000000..5b64d4271 --- /dev/null +++ b/src/apps/LoRaMac/periodic-uplink-lpp-counter/SKiM980A/main.c @@ -0,0 +1,727 @@ +/*! + * \file main.c + * + * \brief Performs a periodic uplink + * + * \copyright Revised BSD License, see section \ref LICENSE. + * + * \code + * ______ _ + * / _____) _ | | + * ( (____ _____ ____ _| |_ _____ ____| |__ + * \____ \| ___ | (_ _) ___ |/ ___) _ \ + * _____) ) ____| | | || |_| ____( (___| | | | + * (______/|_____)_|_|_| \__)_____)\____)_| |_| + * (C)2013-2018 Semtech + * + * \endcode + * + * \author Miguel Luis ( Semtech ) + */ + +/*! \file periodic-uplink/SKiM980A/main.c */ + +#include +#include +#include +#include "../firmwareVersion.h" +#include "../../common/githubVersion.h" +#include "utilities.h" +#include "board.h" +#include "lpm-board.h" +#include "gpio.h" +#include "uart.h" +#include "RegionCommon.h" +#include "eeprom-board.h" +#include "nvmm.h" + +#include "cli.h" +#include "Commissioning.h" +#include "LmHandler.h" +#include "LmhpCompliance.h" +#include "CayenneLpp.h" +#include "LmHandlerMsgDisplay.h" + +static uint32_t in_cnt = 0U; +static uint32_t in_out_cnt = 0U; +const volatile uint32_t stop_mode_timer = 8000U; /* Test at 8 sec */ +static uint8_t uplink_buffer[8U] = { 0 }; +static uint8_t test_read_buffer[8U] = { 0 }; + +#ifndef ACTIVE_REGION + +#warning "No active region defined, LORAMAC_REGION_EU868 will be used as default." + +#define ACTIVE_REGION LORAMAC_REGION_EU868 + +#endif + +/*! + * LoRaWAN default end-device class + */ +#define LORAWAN_DEFAULT_CLASS CLASS_A + +/*! + * Defines the application data transmission duty cycle. 5s, value in [ms]. + */ +#define APP_TX_DUTYCYCLE 1000 * 60 * 5 + +/*! + * Defines a random delay for application data transmission duty cycle. 1s, + * value in [ms]. + */ +#define APP_TX_DUTYCYCLE_RND 1000 + +/*! + * LoRaWAN Adaptive Data Rate + * + * \remark Please note that when ADR is enabled the end-device should be static + */ +#define LORAWAN_ADR_STATE LORAMAC_HANDLER_ADR_ON + +/*! + * Default datarate + * + * \remark Please note that LORAWAN_DEFAULT_DATARATE is used only when ADR is disabled + */ +#define LORAWAN_DEFAULT_DATARATE DR_0 + +/*! + * LoRaWAN confirmed messages + */ +#define LORAWAN_DEFAULT_CONFIRMED_MSG_STATE LORAMAC_HANDLER_UNCONFIRMED_MSG + +/*! + * User application data buffer size + */ +#define LORAWAN_APP_DATA_BUFFER_MAX_SIZE 242 + +/*! + * LoRaWAN ETSI duty cycle control enable/disable + * + * \remark Please note that ETSI mandates duty cycled transmissions. Use only for test purposes + */ +#define LORAWAN_DUTYCYCLE_ON true + +/*! + * LoRaWAN application port + * @remark The allowed port range is from 1 up to 223. Other values are reserved. + */ +#define LORAWAN_APP_PORT 3 + +/*! + * + */ +typedef enum +{ + LORAMAC_HANDLER_TX_ON_TIMER, + LORAMAC_HANDLER_TX_ON_EVENT, +}LmHandlerTxEvents_t; + +/*! + * User application data + */ +static uint8_t AppDataBuffer[LORAWAN_APP_DATA_BUFFER_MAX_SIZE]; + +/*! + * User application data structure + */ +static LmHandlerAppData_t AppData = +{ + .Buffer = AppDataBuffer, + .BufferSize = 0, + .Port = 0, +}; + +/*! + * Specifies the state of the application LED + */ +static bool AppLedStateOn = false; + +/*! + * Timer to handle the application data transmission duty cycle + */ +static TimerEvent_t TxTimer; + +/*! + * Timer to handle the state of LED4 + */ +static TimerEvent_t Led4Timer; + +// /*! +// * Timer to handle the state of LED2 +// */ +// static TimerEvent_t Led2Timer; + +/*! + * Timer to handle the state of LED beacon indicator + */ +static TimerEvent_t LedBeaconTimer; + +static void OnMacProcessNotify( void ); +static void OnNvmDataChange( LmHandlerNvmContextStates_t state, uint16_t size ); +static void OnNetworkParametersChange( CommissioningParams_t* params ); +static void OnMacMcpsRequest( LoRaMacStatus_t status, McpsReq_t *mcpsReq, TimerTime_t nextTxIn ); +static void OnMacMlmeRequest( LoRaMacStatus_t status, MlmeReq_t *mlmeReq, TimerTime_t nextTxIn ); +static void OnJoinRequest( LmHandlerJoinParams_t* params ); +static void OnTxData( LmHandlerTxParams_t* params ); +static void OnRxData( LmHandlerAppData_t* appData, LmHandlerRxParams_t* params ); +static void OnClassChange( DeviceClass_t deviceClass ); +static void OnBeaconStatusChange( LoRaMacHandlerBeaconParams_t* params ); +#if( LMH_SYS_TIME_UPDATE_NEW_API == 1 ) +static void OnSysTimeUpdate( bool isSynchronized, int32_t timeCorrection ); +#else +static void OnSysTimeUpdate( void ); +#endif +static void PrepareTxFrame( void ); +static void StartTxProcess( LmHandlerTxEvents_t txEvent ); +static void UplinkProcess( void ); + +static void OnTxPeriodicityChanged( uint32_t periodicity ); +static void OnTxFrameCtrlChanged( LmHandlerMsgTypes_t isTxConfirmed ); +static void OnPingSlotPeriodicityChanged( uint8_t pingSlotPeriodicity ); + +/*! + * Function executed on TxTimer event + */ +static void OnTxTimerEvent( void* context ); + +/*! + * Function executed on Led 4 Timeout event + */ +static void OnLed4TimerEvent( void* context ); + +// /*! +// * Function executed on Led 2 Timeout event +// */ +// static void OnLed2TimerEvent( void* context ); + +/*! + * \brief Function executed on Beacon timer Timeout event + */ +static void OnLedBeaconTimerEvent( void* context ); + +// /*! +// * Timer to handle the state of WKUP indicator +// */ +// static TimerEvent_t WKUPTimer; + +// /*! +// * Function executed on Wakeup event +// */ +// static void OnWKUPTimerEvent(void *context); + +/*! + * Function executed on IO1 event + */ +void OnIO1Event(void *context); + +/*! + * Function executed on IO2 event + */ +void OnIO2Event(void *context); + +static LmHandlerCallbacks_t LmHandlerCallbacks = +{ + .GetBatteryLevel = BoardGetBatteryLevel, + .GetTemperature = NULL, + .GetRandomSeed = BoardGetRandomSeed, + .OnMacProcess = OnMacProcessNotify, + .OnNvmDataChange = OnNvmDataChange, + .OnNetworkParametersChange = OnNetworkParametersChange, + .OnMacMcpsRequest = OnMacMcpsRequest, + .OnMacMlmeRequest = OnMacMlmeRequest, + .OnJoinRequest = OnJoinRequest, + .OnTxData = OnTxData, + .OnRxData = OnRxData, + .OnClassChange= OnClassChange, + .OnBeaconStatusChange = OnBeaconStatusChange, + .OnSysTimeUpdate = OnSysTimeUpdate, +}; + +static LmHandlerParams_t LmHandlerParams = +{ + .Region = ACTIVE_REGION, + .AdrEnable = LORAWAN_ADR_STATE, + .IsTxConfirmed = LORAWAN_DEFAULT_CONFIRMED_MSG_STATE, + .TxDatarate = LORAWAN_DEFAULT_DATARATE, + .PublicNetworkEnable = LORAWAN_PUBLIC_NETWORK, + .DutyCycleEnabled = LORAWAN_DUTYCYCLE_ON, + .DataBufferMaxSize = LORAWAN_APP_DATA_BUFFER_MAX_SIZE, + .DataBuffer = AppDataBuffer, + .PingSlotPeriodicity = REGION_COMMON_DEFAULT_PING_SLOT_PERIODICITY, +}; + +static LmhpComplianceParams_t LmhpComplianceParams = +{ + .FwVersion.Value = FIRMWARE_VERSION, + .OnTxPeriodicityChanged = OnTxPeriodicityChanged, + .OnTxFrameCtrlChanged = OnTxFrameCtrlChanged, + .OnPingSlotPeriodicityChanged = OnPingSlotPeriodicityChanged, +}; + +/*! + * Indicates if LoRaMacProcess call is pending. + * + * \warning If variable is equal to 0 then the MCU can be set in low power mode + */ +static volatile uint8_t IsMacProcessPending = 0; + +static volatile uint8_t IsTxFramePending = 0; + +static volatile uint32_t TxPeriodicity = 0; + +static volatile uint8_t IsStopMode = 0; + +/*! + * LED GPIO pins objects + */ +extern Gpio_t Led4; // Tx +// extern Gpio_t Led2; // Rx and blinks every 5 seconds when beacon is acquired +extern Gpio_t Led3; // App +extern Gpio_t Wkup; +extern Gpio_t Io1; +extern Gpio_t Io2; +/*! + * UART object used for command line interface handling + */ +extern Uart_t Uart1; + +/*! + * Main application entry point. + */ +int main( void ) +{ + // uint16_t size = 0U; + // uint16_t i = 0U; + + BoardInitMcu( ); + BoardInitPeriph( ); + + NvmmRead(&test_read_buffer[0], 8U, 0x0FF8); + in_cnt |= test_read_buffer[0U] << 24; + in_cnt |= test_read_buffer[1U] << 16; + in_cnt |= test_read_buffer[2U] << 8; + in_cnt |= test_read_buffer[3U] << 0; + in_out_cnt |= test_read_buffer[4U] << 24; + in_out_cnt |= test_read_buffer[5U] << 16; + in_out_cnt |= test_read_buffer[6U] << 8; + in_out_cnt |= test_read_buffer[7U] << 0; + + TimerInit( &Led4Timer, OnLed4TimerEvent ); + TimerSetValue( &Led4Timer, 25 ); + + // TimerInit( &Led2Timer, OnLed2TimerEvent ); + // TimerSetValue( &Led2Timer, 25 ); + + TimerInit( &LedBeaconTimer, OnLedBeaconTimerEvent ); + TimerSetValue( &LedBeaconTimer, 5000 ); + + // TimerInit(&WKUPTimer, OnWKUPTimerEvent); + // TimerSetValue(&WKUPTimer, stop_mode_timer); + // TimerStart(&WKUPTimer); + // IsStopMode = 3U; + + // Initialize transmission periodicity variable + TxPeriodicity = APP_TX_DUTYCYCLE + randr( -APP_TX_DUTYCYCLE_RND, APP_TX_DUTYCYCLE_RND ); + + const Version_t appVersion = { .Value = FIRMWARE_VERSION }; + const Version_t gitHubVersion = { .Value = GITHUB_VERSION }; + DisplayAppInfo( "periodic-uplink-lpp", + &appVersion, + &gitHubVersion ); + + if ( LmHandlerInit( &LmHandlerCallbacks, &LmHandlerParams ) != LORAMAC_HANDLER_SUCCESS ) + { + printf( "LoRaMac wasn't properly initialized\n" ); + // Fatal error, endless loop. + while ( 1 ) + { + } + } + + // Set system maximum tolerated rx error in milliseconds + LmHandlerSetSystemMaxRxError( 20 ); + + // The LoRa-Alliance Compliance protocol package should always be + // initialized and activated. + LmHandlerPackageRegister( PACKAGE_ID_COMPLIANCE, &LmhpComplianceParams ); + + LmHandlerJoin( ); + + StartTxProcess( LORAMAC_HANDLER_TX_ON_TIMER ); + + while( 1 ) + { + // Process characters sent over the command line interface + CliProcess( &Uart1 ); + + // Processes the LoRaMac events + LmHandlerProcess( ); + + // Process application uplinks management + UplinkProcess( ); + + CRITICAL_SECTION_BEGIN( ); + if( IsMacProcessPending == 1 ) + { + // Clear flag and prevent MCU to go into low power modes. + IsMacProcessPending = 0; + } + else + { + // The MCU wakes up through events + BoardLowPowerHandler( ); + + } + + + CRITICAL_SECTION_END( ); + } +} + +static void OnMacProcessNotify( void ) +{ + IsMacProcessPending = 1; +} + +static void OnNvmDataChange( LmHandlerNvmContextStates_t state, uint16_t size ) +{ + DisplayNvmDataChange( state, size ); +} + +static void OnNetworkParametersChange( CommissioningParams_t* params ) +{ + DisplayNetworkParametersUpdate( params ); +} + +static void OnMacMcpsRequest( LoRaMacStatus_t status, McpsReq_t *mcpsReq, TimerTime_t nextTxIn ) +{ + DisplayMacMcpsRequestUpdate( status, mcpsReq, nextTxIn ); +} + +static void OnMacMlmeRequest( LoRaMacStatus_t status, MlmeReq_t *mlmeReq, TimerTime_t nextTxIn ) +{ + DisplayMacMlmeRequestUpdate( status, mlmeReq, nextTxIn ); +} + +static void OnJoinRequest( LmHandlerJoinParams_t* params ) +{ + DisplayJoinRequestUpdate( params ); + if( params->Status == LORAMAC_HANDLER_ERROR ) + { + LmHandlerJoin( ); + } + else + { + LmHandlerRequestClass( LORAWAN_DEFAULT_CLASS ); + } +} + +static void OnTxData( LmHandlerTxParams_t* params ) +{ + DisplayTxUpdate( params ); +} + +static void OnRxData( LmHandlerAppData_t* appData, LmHandlerRxParams_t* params ) +{ + DisplayRxUpdate( appData, params ); + + switch( appData->Port ) + { + case 1: // The application LED can be controlled on port 1 or 2 + case LORAWAN_APP_PORT: + { + AppLedStateOn = appData->Buffer[0] & 0x01; + GpioWrite( &Led3, ( ( AppLedStateOn & 0x01 ) != 0 ) ? 1 : 0 ); + } + break; + default: + break; + } + + // Switch LED 2 ON for each received downlink + // GpioWrite( &Led2, 1 ); + // TimerStart( &Led2Timer ); +} + +static void OnClassChange( DeviceClass_t deviceClass ) +{ + DisplayClassUpdate( deviceClass ); + + // Inform the server as soon as possible that the end-device has switched to ClassB + LmHandlerAppData_t appData = + { + .Buffer = NULL, + .BufferSize = 0, + .Port = 0, + }; + LmHandlerSend( &appData, LORAMAC_HANDLER_UNCONFIRMED_MSG ); +} + +static void OnBeaconStatusChange( LoRaMacHandlerBeaconParams_t* params ) +{ + switch( params->State ) + { + case LORAMAC_HANDLER_BEACON_RX: + { + TimerStart( &LedBeaconTimer ); + break; + } + case LORAMAC_HANDLER_BEACON_LOST: + case LORAMAC_HANDLER_BEACON_NRX: + { + TimerStop( &LedBeaconTimer ); + break; + } + default: + { + break; + } + } + + DisplayBeaconUpdate( params ); +} + +#if( LMH_SYS_TIME_UPDATE_NEW_API == 1 ) +static void OnSysTimeUpdate( bool isSynchronized, int32_t timeCorrection ) +{ + +} +#else +static void OnSysTimeUpdate( void ) +{ + +} +#endif + +/*! + * Prepares the payload of the frame and transmits it. + */ +static void PrepareTxFrame( void ) +{ + if( LmHandlerIsBusy( ) == true ) + { + return; + } + + // uint8_t channel = 0; + + AppData.Port = LORAWAN_APP_PORT; + + // CayenneLppReset( ); + + // uint8_t potiPercentage = 0; + // uint16_t vdd = 0; + + // // Read the current potentiometer setting in percent + // potiPercentage = BoardGetPotiLevel( ); + + // // Read the current voltage level + // BoardGetBatteryLevel( ); // Updates the value returned by BoardGetBatteryVoltage( ) function. + // vdd = BoardGetBatteryVoltage( ); + + // CayenneLppAddDigitalInput( channel++, AppLedStateOn ); + // CayenneLppAddAnalogInput( channel++, BoardGetBatteryLevel( ) * 100 / 254 ); + // CayenneLppAddAnalogInput( channel++, potiPercentage ); + // CayenneLppAddAnalogInput( channel++, vdd ); + + // CayenneLppCopy( AppData.Buffer ); + // AppData.BufferSize = CayenneLppGetSize( ); + + /* Test uplink WKUP and IO1 */ + uplink_buffer[0U] = in_cnt << 24U; + uplink_buffer[1U] = in_cnt << 16U; + uplink_buffer[2U] = in_cnt << 8U; + uplink_buffer[3U] = in_cnt & 0x00FF; + uplink_buffer[4U] = in_out_cnt << 24U; + uplink_buffer[5U] = in_out_cnt << 16U; + uplink_buffer[6U] = in_out_cnt << 8U; + uplink_buffer[7U] = in_out_cnt & 0x00FF; + + memcpy1(AppData.Buffer, uplink_buffer, 8U); + + if( LmHandlerSend( &AppData, LmHandlerParams.IsTxConfirmed ) == LORAMAC_HANDLER_SUCCESS ) + { + // Switch LED 4 ON + GpioWrite( &Led4, 1 ); + TimerStart( &Led4Timer ); + NvmmRead(&test_read_buffer[0], 8U, 0x0FF8); + if(memcmp(test_read_buffer, uplink_buffer, 8) < 0) + { + NvmmWrite(uplink_buffer, 8U, 0x0FF8); + } + + } +} + +static void StartTxProcess( LmHandlerTxEvents_t txEvent ) +{ + switch( txEvent ) + { + default: + // Intentional fall through + case LORAMAC_HANDLER_TX_ON_TIMER: + { + // Schedule 1st packet transmission + TimerInit( &TxTimer, OnTxTimerEvent ); + TimerSetValue( &TxTimer, TxPeriodicity ); + OnTxTimerEvent( NULL ); + } + break; + case LORAMAC_HANDLER_TX_ON_EVENT: + { + } + break; + } +} + +static void UplinkProcess( void ) +{ + uint8_t isPending = 0; + CRITICAL_SECTION_BEGIN( ); + isPending = IsTxFramePending; + IsTxFramePending = 0; + CRITICAL_SECTION_END( ); + if( isPending == 1 ) + { + PrepareTxFrame( ); + } +} + +static void OnTxPeriodicityChanged( uint32_t periodicity ) +{ + TxPeriodicity = periodicity; + + if( TxPeriodicity == 0 ) + { // Revert to application default periodicity + TxPeriodicity = APP_TX_DUTYCYCLE + randr( -APP_TX_DUTYCYCLE_RND, APP_TX_DUTYCYCLE_RND ); + } +} + +static void OnTxFrameCtrlChanged( LmHandlerMsgTypes_t isTxConfirmed ) +{ + LmHandlerParams.IsTxConfirmed = isTxConfirmed; +} + +static void OnPingSlotPeriodicityChanged( uint8_t pingSlotPeriodicity ) +{ + LmHandlerParams.PingSlotPeriodicity = pingSlotPeriodicity; +} + +/*! + * Function executed on TxTimer event + */ +static void OnTxTimerEvent( void* context ) +{ + TimerStop( &TxTimer ); + + IsTxFramePending = 1; + + // Schedule next transmission + TimerSetValue( &TxTimer, TxPeriodicity ); + TimerStart( &TxTimer ); +} + +/*! + * Function executed on Led 4 Timeout event + */ +static void OnLed4TimerEvent( void* context ) +{ + TimerStop( &Led4Timer ); + // Switch LED 4 OFF + GpioWrite( &Led4, 0 ); +} + +// /*! +// * Function executed on Led 2 Timeout event +// */ +// static void OnLed2TimerEvent( void* context ) +// { +// TimerStop( &Led2Timer ); +// // Switch LED 2 OFF +// GpioWrite( &Led2, 0 ); +// } + +/*! + * \brief Function executed on Beacon timer Timeout event + */ +static void OnLedBeaconTimerEvent( void* context ) +{ + // GpioWrite( &Led2, 1 ); + // TimerStart( &Led2Timer ); + + TimerStart( &LedBeaconTimer ); +} + +// /*! +// * Function executed on WKUP Timeout event +// */ +// static void OnWKUPTimerEvent(void *context) +// { +// IsStopMode = 0U; +// TimerStop(&WKUPTimer); +// } + +/*! + * Function executed on WKUP event + */ +void OnWKUPEvent(void *context) +{ + uint32_t timeout = 1000000 * 10; + + CRITICAL_SECTION_BEGIN( ); + + TimerStop( &TxTimer ); + IsStopMode = 1U; + + while (--timeout <= 0U) __NOP(); + + in_cnt++; + + printf("In : %ld\n", in_cnt); + + IsTxFramePending = 1; + + CRITICAL_SECTION_END( ) ; + + // Schedule next transmission + TimerSetValue( &TxTimer, TxPeriodicity ); + TimerStart( &TxTimer ); +} + +/*! + * Function executed on IO1 event + */ +void OnIO1Event(void *context) +{ + /* Do nothing */ +} + +/*! + * Function executed on IO2 event + */ +void OnIO2Event(void *context) +{ + uint32_t timeout = 1000000 * 10; + + CRITICAL_SECTION_BEGIN( ); + + TimerStop( &TxTimer ); + IsStopMode = 2U; + + while (--timeout <= 0U) __NOP(); + + in_out_cnt++; + + printf("In Out: %ld\n", in_out_cnt); + + // read/write input/output + IsTxFramePending = 1; + + CRITICAL_SECTION_END( ) ; + + // Schedule next transmission + TimerSetValue( &TxTimer, TxPeriodicity ); + TimerStart( &TxTimer ); +} \ No newline at end of file diff --git a/src/apps/LoRaMac/periodic-uplink-lpp-counter/eMOD-iMS62F/main.c b/src/apps/LoRaMac/periodic-uplink-lpp-counter/eMOD-iMS62F/main.c new file mode 100644 index 000000000..b850d3abd --- /dev/null +++ b/src/apps/LoRaMac/periodic-uplink-lpp-counter/eMOD-iMS62F/main.c @@ -0,0 +1,727 @@ +/*! + * \file main.c + * + * \brief Performs a periodic uplink + * + * \copyright Revised BSD License, see section \ref LICENSE. + * + * \code + * ______ _ + * / _____) _ | | + * ( (____ _____ ____ _| |_ _____ ____| |__ + * \____ \| ___ | (_ _) ___ |/ ___) _ \ + * _____) ) ____| | | || |_| ____( (___| | | | + * (______/|_____)_|_|_| \__)_____)\____)_| |_| + * (C)2013-2018 Semtech + * + * \endcode + * + * \author Miguel Luis ( Semtech ) + */ + +/*! \file periodic-uplink/eMOD-iMS62F/main.c */ + +#include +#include +#include +#include "../firmwareVersion.h" +#include "../../common/githubVersion.h" +#include "utilities.h" +#include "board.h" +#include "lpm-board.h" +#include "gpio.h" +#include "uart.h" +#include "RegionCommon.h" +#include "eeprom-board.h" +#include "nvmm.h" + +#include "cli.h" +#include "Commissioning.h" +#include "LmHandler.h" +#include "LmhpCompliance.h" +#include "CayenneLpp.h" +#include "LmHandlerMsgDisplay.h" + +static uint32_t in_cnt = 0U; +static uint32_t in_out_cnt = 0U; +const volatile uint32_t stop_mode_timer = 8000U; /* Test at 8 sec */ +static uint8_t uplink_buffer[8U] = { 0 }; +static uint8_t test_read_buffer[8U] = { 0 }; + +#ifndef ACTIVE_REGION + +#warning "No active region defined, LORAMAC_REGION_EU868 will be used as default." + +#define ACTIVE_REGION LORAMAC_REGION_EU868 + +#endif + +/*! + * LoRaWAN default end-device class + */ +#define LORAWAN_DEFAULT_CLASS CLASS_A + +/*! + * Defines the application data transmission duty cycle. 5s, value in [ms]. + */ +#define APP_TX_DUTYCYCLE 1000 * 60 * 5 + +/*! + * Defines a random delay for application data transmission duty cycle. 1s, + * value in [ms]. + */ +#define APP_TX_DUTYCYCLE_RND 1000 + +/*! + * LoRaWAN Adaptive Data Rate + * + * \remark Please note that when ADR is enabled the end-device should be static + */ +#define LORAWAN_ADR_STATE LORAMAC_HANDLER_ADR_ON + +/*! + * Default datarate + * + * \remark Please note that LORAWAN_DEFAULT_DATARATE is used only when ADR is disabled + */ +#define LORAWAN_DEFAULT_DATARATE DR_0 + +/*! + * LoRaWAN confirmed messages + */ +#define LORAWAN_DEFAULT_CONFIRMED_MSG_STATE LORAMAC_HANDLER_UNCONFIRMED_MSG + +/*! + * User application data buffer size + */ +#define LORAWAN_APP_DATA_BUFFER_MAX_SIZE 242 + +/*! + * LoRaWAN ETSI duty cycle control enable/disable + * + * \remark Please note that ETSI mandates duty cycled transmissions. Use only for test purposes + */ +#define LORAWAN_DUTYCYCLE_ON true + +/*! + * LoRaWAN application port + * @remark The allowed port range is from 1 up to 223. Other values are reserved. + */ +#define LORAWAN_APP_PORT 3 + +/*! + * + */ +typedef enum +{ + LORAMAC_HANDLER_TX_ON_TIMER, + LORAMAC_HANDLER_TX_ON_EVENT, +}LmHandlerTxEvents_t; + +/*! + * User application data + */ +static uint8_t AppDataBuffer[LORAWAN_APP_DATA_BUFFER_MAX_SIZE]; + +/*! + * User application data structure + */ +static LmHandlerAppData_t AppData = +{ + .Buffer = AppDataBuffer, + .BufferSize = 0, + .Port = 0, +}; + +/*! + * Specifies the state of the application LED + */ +static bool AppLedStateOn = false; + +/*! + * Timer to handle the application data transmission duty cycle + */ +static TimerEvent_t TxTimer; + +/*! + * Timer to handle the state of LED4 + */ +static TimerEvent_t Led4Timer; + +// /*! +// * Timer to handle the state of LED2 +// */ +// static TimerEvent_t Led2Timer; + +/*! + * Timer to handle the state of LED beacon indicator + */ +static TimerEvent_t LedBeaconTimer; + +static void OnMacProcessNotify( void ); +static void OnNvmDataChange( LmHandlerNvmContextStates_t state, uint16_t size ); +static void OnNetworkParametersChange( CommissioningParams_t* params ); +static void OnMacMcpsRequest( LoRaMacStatus_t status, McpsReq_t *mcpsReq, TimerTime_t nextTxIn ); +static void OnMacMlmeRequest( LoRaMacStatus_t status, MlmeReq_t *mlmeReq, TimerTime_t nextTxIn ); +static void OnJoinRequest( LmHandlerJoinParams_t* params ); +static void OnTxData( LmHandlerTxParams_t* params ); +static void OnRxData( LmHandlerAppData_t* appData, LmHandlerRxParams_t* params ); +static void OnClassChange( DeviceClass_t deviceClass ); +static void OnBeaconStatusChange( LoRaMacHandlerBeaconParams_t* params ); +#if( LMH_SYS_TIME_UPDATE_NEW_API == 1 ) +static void OnSysTimeUpdate( bool isSynchronized, int32_t timeCorrection ); +#else +static void OnSysTimeUpdate( void ); +#endif +static void PrepareTxFrame( void ); +static void StartTxProcess( LmHandlerTxEvents_t txEvent ); +static void UplinkProcess( void ); + +static void OnTxPeriodicityChanged( uint32_t periodicity ); +static void OnTxFrameCtrlChanged( LmHandlerMsgTypes_t isTxConfirmed ); +static void OnPingSlotPeriodicityChanged( uint8_t pingSlotPeriodicity ); + +/*! + * Function executed on TxTimer event + */ +static void OnTxTimerEvent( void* context ); + +/*! + * Function executed on Led 4 Timeout event + */ +static void OnLed4TimerEvent( void* context ); + +// /*! +// * Function executed on Led 2 Timeout event +// */ +// static void OnLed2TimerEvent( void* context ); + +/*! + * \brief Function executed on Beacon timer Timeout event + */ +static void OnLedBeaconTimerEvent( void* context ); + +// /*! +// * Timer to handle the state of WKUP indicator +// */ +// static TimerEvent_t WKUPTimer; + +// /*! +// * Function executed on Wakeup event +// */ +// static void OnWKUPTimerEvent(void *context); + +/*! + * Function executed on IO1 event + */ +void OnIO1Event(void *context); + +/*! + * Function executed on IO2 event + */ +void OnIO2Event(void *context); + +static LmHandlerCallbacks_t LmHandlerCallbacks = +{ + .GetBatteryLevel = BoardGetBatteryLevel, + .GetTemperature = NULL, + .GetRandomSeed = BoardGetRandomSeed, + .OnMacProcess = OnMacProcessNotify, + .OnNvmDataChange = OnNvmDataChange, + .OnNetworkParametersChange = OnNetworkParametersChange, + .OnMacMcpsRequest = OnMacMcpsRequest, + .OnMacMlmeRequest = OnMacMlmeRequest, + .OnJoinRequest = OnJoinRequest, + .OnTxData = OnTxData, + .OnRxData = OnRxData, + .OnClassChange= OnClassChange, + .OnBeaconStatusChange = OnBeaconStatusChange, + .OnSysTimeUpdate = OnSysTimeUpdate, +}; + +static LmHandlerParams_t LmHandlerParams = +{ + .Region = ACTIVE_REGION, + .AdrEnable = LORAWAN_ADR_STATE, + .IsTxConfirmed = LORAWAN_DEFAULT_CONFIRMED_MSG_STATE, + .TxDatarate = LORAWAN_DEFAULT_DATARATE, + .PublicNetworkEnable = LORAWAN_PUBLIC_NETWORK, + .DutyCycleEnabled = LORAWAN_DUTYCYCLE_ON, + .DataBufferMaxSize = LORAWAN_APP_DATA_BUFFER_MAX_SIZE, + .DataBuffer = AppDataBuffer, + .PingSlotPeriodicity = REGION_COMMON_DEFAULT_PING_SLOT_PERIODICITY, +}; + +static LmhpComplianceParams_t LmhpComplianceParams = +{ + .FwVersion.Value = FIRMWARE_VERSION, + .OnTxPeriodicityChanged = OnTxPeriodicityChanged, + .OnTxFrameCtrlChanged = OnTxFrameCtrlChanged, + .OnPingSlotPeriodicityChanged = OnPingSlotPeriodicityChanged, +}; + +/*! + * Indicates if LoRaMacProcess call is pending. + * + * \warning If variable is equal to 0 then the MCU can be set in low power mode + */ +static volatile uint8_t IsMacProcessPending = 0; + +static volatile uint8_t IsTxFramePending = 0; + +static volatile uint32_t TxPeriodicity = 0; + +static volatile uint8_t IsStopMode = 0; + +/*! + * LED GPIO pins objects + */ +extern Gpio_t Led4; // Tx +// extern Gpio_t Led2; // Rx and blinks every 5 seconds when beacon is acquired +extern Gpio_t Led3; // App +extern Gpio_t Wkup; +extern Gpio_t Io1; +extern Gpio_t Io2; +/*! + * UART object used for command line interface handling + */ +extern Uart_t Uart1; + +/*! + * Main application entry point. + */ +int main( void ) +{ + // uint16_t size = 0U; + // uint16_t i = 0U; + + BoardInitMcu( ); + BoardInitPeriph( ); + + NvmmRead(&test_read_buffer[0], 8U, 0x0FF8); + in_cnt |= test_read_buffer[0U] << 24; + in_cnt |= test_read_buffer[1U] << 16; + in_cnt |= test_read_buffer[2U] << 8; + in_cnt |= test_read_buffer[3U] << 0; + in_out_cnt |= test_read_buffer[4U] << 24; + in_out_cnt |= test_read_buffer[5U] << 16; + in_out_cnt |= test_read_buffer[6U] << 8; + in_out_cnt |= test_read_buffer[7U] << 0; + + TimerInit( &Led4Timer, OnLed4TimerEvent ); + TimerSetValue( &Led4Timer, 25 ); + + // TimerInit( &Led2Timer, OnLed2TimerEvent ); + // TimerSetValue( &Led2Timer, 25 ); + + TimerInit( &LedBeaconTimer, OnLedBeaconTimerEvent ); + TimerSetValue( &LedBeaconTimer, 5000 ); + + // TimerInit(&WKUPTimer, OnWKUPTimerEvent); + // TimerSetValue(&WKUPTimer, stop_mode_timer); + // TimerStart(&WKUPTimer); + // IsStopMode = 3U; + + // Initialize transmission periodicity variable + TxPeriodicity = APP_TX_DUTYCYCLE + randr( -APP_TX_DUTYCYCLE_RND, APP_TX_DUTYCYCLE_RND ); + + const Version_t appVersion = { .Value = FIRMWARE_VERSION }; + const Version_t gitHubVersion = { .Value = GITHUB_VERSION }; + DisplayAppInfo( "periodic-uplink-lpp", + &appVersion, + &gitHubVersion ); + + if ( LmHandlerInit( &LmHandlerCallbacks, &LmHandlerParams ) != LORAMAC_HANDLER_SUCCESS ) + { + printf( "LoRaMac wasn't properly initialized\n" ); + // Fatal error, endless loop. + while ( 1 ) + { + } + } + + // Set system maximum tolerated rx error in milliseconds + LmHandlerSetSystemMaxRxError( 20 ); + + // The LoRa-Alliance Compliance protocol package should always be + // initialized and activated. + LmHandlerPackageRegister( PACKAGE_ID_COMPLIANCE, &LmhpComplianceParams ); + + LmHandlerJoin( ); + + StartTxProcess( LORAMAC_HANDLER_TX_ON_TIMER ); + + while( 1 ) + { + // Process characters sent over the command line interface + CliProcess( &Uart1 ); + + // Processes the LoRaMac events + LmHandlerProcess( ); + + // Process application uplinks management + UplinkProcess( ); + + CRITICAL_SECTION_BEGIN( ); + if( IsMacProcessPending == 1 ) + { + // Clear flag and prevent MCU to go into low power modes. + IsMacProcessPending = 0; + } + else + { + // The MCU wakes up through events + BoardLowPowerHandler( ); + + } + + + CRITICAL_SECTION_END( ); + } +} + +static void OnMacProcessNotify( void ) +{ + IsMacProcessPending = 1; +} + +static void OnNvmDataChange( LmHandlerNvmContextStates_t state, uint16_t size ) +{ + DisplayNvmDataChange( state, size ); +} + +static void OnNetworkParametersChange( CommissioningParams_t* params ) +{ + DisplayNetworkParametersUpdate( params ); +} + +static void OnMacMcpsRequest( LoRaMacStatus_t status, McpsReq_t *mcpsReq, TimerTime_t nextTxIn ) +{ + DisplayMacMcpsRequestUpdate( status, mcpsReq, nextTxIn ); +} + +static void OnMacMlmeRequest( LoRaMacStatus_t status, MlmeReq_t *mlmeReq, TimerTime_t nextTxIn ) +{ + DisplayMacMlmeRequestUpdate( status, mlmeReq, nextTxIn ); +} + +static void OnJoinRequest( LmHandlerJoinParams_t* params ) +{ + DisplayJoinRequestUpdate( params ); + if( params->Status == LORAMAC_HANDLER_ERROR ) + { + LmHandlerJoin( ); + } + else + { + LmHandlerRequestClass( LORAWAN_DEFAULT_CLASS ); + } +} + +static void OnTxData( LmHandlerTxParams_t* params ) +{ + DisplayTxUpdate( params ); +} + +static void OnRxData( LmHandlerAppData_t* appData, LmHandlerRxParams_t* params ) +{ + DisplayRxUpdate( appData, params ); + + switch( appData->Port ) + { + case 1: // The application LED can be controlled on port 1 or 2 + case LORAWAN_APP_PORT: + { + AppLedStateOn = appData->Buffer[0] & 0x01; + GpioWrite( &Led3, ( ( AppLedStateOn & 0x01 ) != 0 ) ? 1 : 0 ); + } + break; + default: + break; + } + + // Switch LED 2 ON for each received downlink + // GpioWrite( &Led2, 1 ); + // TimerStart( &Led2Timer ); +} + +static void OnClassChange( DeviceClass_t deviceClass ) +{ + DisplayClassUpdate( deviceClass ); + + // Inform the server as soon as possible that the end-device has switched to ClassB + LmHandlerAppData_t appData = + { + .Buffer = NULL, + .BufferSize = 0, + .Port = 0, + }; + LmHandlerSend( &appData, LORAMAC_HANDLER_UNCONFIRMED_MSG ); +} + +static void OnBeaconStatusChange( LoRaMacHandlerBeaconParams_t* params ) +{ + switch( params->State ) + { + case LORAMAC_HANDLER_BEACON_RX: + { + TimerStart( &LedBeaconTimer ); + break; + } + case LORAMAC_HANDLER_BEACON_LOST: + case LORAMAC_HANDLER_BEACON_NRX: + { + TimerStop( &LedBeaconTimer ); + break; + } + default: + { + break; + } + } + + DisplayBeaconUpdate( params ); +} + +#if( LMH_SYS_TIME_UPDATE_NEW_API == 1 ) +static void OnSysTimeUpdate( bool isSynchronized, int32_t timeCorrection ) +{ + +} +#else +static void OnSysTimeUpdate( void ) +{ + +} +#endif + +/*! + * Prepares the payload of the frame and transmits it. + */ +static void PrepareTxFrame( void ) +{ + if( LmHandlerIsBusy( ) == true ) + { + return; + } + + // uint8_t channel = 0; + + AppData.Port = LORAWAN_APP_PORT; + + // CayenneLppReset( ); + + // uint8_t potiPercentage = 0; + // uint16_t vdd = 0; + + // // Read the current potentiometer setting in percent + // potiPercentage = BoardGetPotiLevel( ); + + // // Read the current voltage level + // BoardGetBatteryLevel( ); // Updates the value returned by BoardGetBatteryVoltage( ) function. + // vdd = BoardGetBatteryVoltage( ); + + // CayenneLppAddDigitalInput( channel++, AppLedStateOn ); + // CayenneLppAddAnalogInput( channel++, BoardGetBatteryLevel( ) * 100 / 254 ); + // CayenneLppAddAnalogInput( channel++, potiPercentage ); + // CayenneLppAddAnalogInput( channel++, vdd ); + + // CayenneLppCopy( AppData.Buffer ); + // AppData.BufferSize = CayenneLppGetSize( ); + + /* Test uplink WKUP and IO1 */ + uplink_buffer[0U] = in_cnt << 24U; + uplink_buffer[1U] = in_cnt << 16U; + uplink_buffer[2U] = in_cnt << 8U; + uplink_buffer[3U] = in_cnt & 0x00FF; + uplink_buffer[4U] = in_out_cnt << 24U; + uplink_buffer[5U] = in_out_cnt << 16U; + uplink_buffer[6U] = in_out_cnt << 8U; + uplink_buffer[7U] = in_out_cnt & 0x00FF; + + memcpy1(AppData.Buffer, uplink_buffer, 8U); + + if( LmHandlerSend( &AppData, LmHandlerParams.IsTxConfirmed ) == LORAMAC_HANDLER_SUCCESS ) + { + // Switch LED 4 ON + GpioWrite( &Led4, 1 ); + TimerStart( &Led4Timer ); + NvmmRead(&test_read_buffer[0], 8U, 0x0FF8); + if(memcmp(test_read_buffer, uplink_buffer, 8) < 0) + { + NvmmWrite(uplink_buffer, 8U, 0x0FF8); + } + + } +} + +static void StartTxProcess( LmHandlerTxEvents_t txEvent ) +{ + switch( txEvent ) + { + default: + // Intentional fall through + case LORAMAC_HANDLER_TX_ON_TIMER: + { + // Schedule 1st packet transmission + TimerInit( &TxTimer, OnTxTimerEvent ); + TimerSetValue( &TxTimer, TxPeriodicity ); + OnTxTimerEvent( NULL ); + } + break; + case LORAMAC_HANDLER_TX_ON_EVENT: + { + } + break; + } +} + +static void UplinkProcess( void ) +{ + uint8_t isPending = 0; + CRITICAL_SECTION_BEGIN( ); + isPending = IsTxFramePending; + IsTxFramePending = 0; + CRITICAL_SECTION_END( ); + if( isPending == 1 ) + { + PrepareTxFrame( ); + } +} + +static void OnTxPeriodicityChanged( uint32_t periodicity ) +{ + TxPeriodicity = periodicity; + + if( TxPeriodicity == 0 ) + { // Revert to application default periodicity + TxPeriodicity = APP_TX_DUTYCYCLE + randr( -APP_TX_DUTYCYCLE_RND, APP_TX_DUTYCYCLE_RND ); + } +} + +static void OnTxFrameCtrlChanged( LmHandlerMsgTypes_t isTxConfirmed ) +{ + LmHandlerParams.IsTxConfirmed = isTxConfirmed; +} + +static void OnPingSlotPeriodicityChanged( uint8_t pingSlotPeriodicity ) +{ + LmHandlerParams.PingSlotPeriodicity = pingSlotPeriodicity; +} + +/*! + * Function executed on TxTimer event + */ +static void OnTxTimerEvent( void* context ) +{ + TimerStop( &TxTimer ); + + IsTxFramePending = 1; + + // Schedule next transmission + TimerSetValue( &TxTimer, TxPeriodicity ); + TimerStart( &TxTimer ); +} + +/*! + * Function executed on Led 4 Timeout event + */ +static void OnLed4TimerEvent( void* context ) +{ + TimerStop( &Led4Timer ); + // Switch LED 4 OFF + GpioWrite( &Led4, 0 ); +} + +// /*! +// * Function executed on Led 2 Timeout event +// */ +// static void OnLed2TimerEvent( void* context ) +// { +// TimerStop( &Led2Timer ); +// // Switch LED 2 OFF +// GpioWrite( &Led2, 0 ); +// } + +/*! + * \brief Function executed on Beacon timer Timeout event + */ +static void OnLedBeaconTimerEvent( void* context ) +{ + // GpioWrite( &Led2, 1 ); + // TimerStart( &Led2Timer ); + + TimerStart( &LedBeaconTimer ); +} + +// /*! +// * Function executed on WKUP Timeout event +// */ +// static void OnWKUPTimerEvent(void *context) +// { +// IsStopMode = 0U; +// TimerStop(&WKUPTimer); +// } + +/*! + * Function executed on WKUP event + */ +void OnWKUPEvent(void *context) +{ + uint32_t timeout = 1000000 * 10; + + CRITICAL_SECTION_BEGIN( ); + + TimerStop( &TxTimer ); + IsStopMode = 1U; + + while (--timeout <= 0U) __NOP(); + + in_cnt++; + + printf("In : %ld\n", in_cnt); + + IsTxFramePending = 1; + + CRITICAL_SECTION_END( ) ; + + // Schedule next transmission + TimerSetValue( &TxTimer, TxPeriodicity ); + TimerStart( &TxTimer ); +} + +/*! + * Function executed on IO1 event + */ +void OnIO1Event(void *context) +{ + /* Do nothing */ +} + +/*! + * Function executed on IO2 event + */ +void OnIO2Event(void *context) +{ + uint32_t timeout = 1000000 * 10; + + CRITICAL_SECTION_BEGIN( ); + + TimerStop( &TxTimer ); + IsStopMode = 2U; + + while (--timeout <= 0U) __NOP(); + + in_out_cnt++; + + printf("In Out: %ld\n", in_out_cnt); + + // read/write input/output + IsTxFramePending = 1; + + CRITICAL_SECTION_END( ) ; + + // Schedule next transmission + TimerSetValue( &TxTimer, TxPeriodicity ); + TimerStart( &TxTimer ); +} \ No newline at end of file diff --git a/src/apps/LoRaMac/periodic-uplink-lpp-counter/firmwareVersion.h b/src/apps/LoRaMac/periodic-uplink-lpp-counter/firmwareVersion.h new file mode 100644 index 000000000..131714fec --- /dev/null +++ b/src/apps/LoRaMac/periodic-uplink-lpp-counter/firmwareVersion.h @@ -0,0 +1,33 @@ +/*! + * \file firmwareVersion.h + * + * \brief Firmware version definition + * + * \copyright Revised BSD License, see file LICENSE.txt + * + * \code + * ______ _ + * / _____) _ | | + * ( (____ _____ ____ _| |_ _____ ____| |__ + * \____ \| ___ | (_ _) ___ |/ ___) _ \ + * _____) ) ____| | | || |_| ____( (___| | | | + * (______/|_____)_|_|_| \__)_____)\____)_| |_| + * (C)2019-2020 Semtech + * + * \endcode + */ + +#ifndef __FIRMWARE_VERSION_H__ +#define __FIRMWARE_VERSION_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +#define FIRMWARE_VERSION 0x01020000 // 1.2.0.0 + +#ifdef __cplusplus +} +#endif + +#endif // __FIRMWARE_VERSION_H__ diff --git a/src/boards/SKiM980A/board-config.h b/src/boards/SKiM980A/board-config.h index ec282d156..448425538 100644 --- a/src/boards/SKiM980A/board-config.h +++ b/src/boards/SKiM980A/board-config.h @@ -102,7 +102,7 @@ extern "C" #else #define LED_1 PA_3 #endif -#define LED_2 PA_0 +// #define LED_2 PA_0 #define LED_3 PA_1 #define LED_4 PA_8 @@ -110,6 +110,11 @@ extern "C" #define RADIO_DBG_PIN_TX NC #define RADIO_DBG_PIN_RX NC +#define IO1 PA_8 +#define IO2 POTI //PB_7 + +#define WKUP PA_0 + #ifdef __cplusplus } #endif diff --git a/src/boards/SKiM980A/board.c b/src/boards/SKiM980A/board.c index 0e896b95a..21ca4fd47 100644 --- a/src/boards/SKiM980A/board.c +++ b/src/boards/SKiM980A/board.c @@ -50,9 +50,12 @@ #if ( USE_POTENTIOMETER == 0 ) Gpio_t Led1; #endif -Gpio_t Led2; +// Gpio_t Led2; Gpio_t Led3; Gpio_t Led4; +Gpio_t Wkup; +Gpio_t Io1; +Gpio_t Io2; /* * MCU objects @@ -86,6 +89,22 @@ static void SystemClockReConfig( void ); */ static TimerEvent_t CalibrateSystemWakeupTimeTimer; +/*! + * Function executed on IO1 event + */ +extern void OnWKUPEvent(void *context); + +/*! + * Function executed on IO1 event + */ +extern void OnIO1Event(void *context); + +/*! + * Function executed on IO2 event + */ +extern void OnIO2Event(void *context); + + /*! * Flag to indicate if the MCU is Initialized */ @@ -140,17 +159,24 @@ void BoardInitMcu( void ) #if ( USE_POTENTIOMETER == 0 ) GpioInit( &Led1, LED_1, PIN_OUTPUT, PIN_PUSH_PULL, PIN_NO_PULL, 1 ); #endif - GpioInit( &Led2, LED_2, PIN_OUTPUT, PIN_PUSH_PULL, PIN_NO_PULL, 1 ); + // GpioInit( &Led2, LED_2, PIN_OUTPUT, PIN_PUSH_PULL, PIN_NO_PULL, 1 ); GpioInit( &Led3, LED_3, PIN_OUTPUT, PIN_PUSH_PULL, PIN_NO_PULL, 1 ); GpioInit( &Led4, LED_4, PIN_OUTPUT, PIN_PUSH_PULL, PIN_NO_PULL, 1 ); + GpioInit( &Wkup, WKUP, PIN_INPUT, PIN_PUSH_PULL, PIN_PULL_UP, 1); + GpioSetInterrupt( &Wkup, IRQ_RISING_EDGE, IRQ_VERY_LOW_PRIORITY, &OnWKUPEvent ); + GpioInit( &Io1, IO1, PIN_OUTPUT , PIN_PUSH_PULL, PIN_NO_PULL, 0); + // GpioSetInterrupt( &Io1, IRQ_RISING_EDGE, IRQ_VERY_LOW_PRIORITY, &OnIO1Event ); + GpioInit( &Io2, IO2, PIN_INPUT , PIN_PUSH_PULL, PIN_PULL_UP, 1); + GpioSetInterrupt( &Io2, IRQ_RISING_EDGE, IRQ_VERY_LOW_PRIORITY, &OnIO2Event ); + SystemClockConfig( ); FifoInit( &Uart1.FifoTx, Uart1TxBuffer, UART1_FIFO_TX_SIZE ); FifoInit( &Uart1.FifoRx, Uart1RxBuffer, UART1_FIFO_RX_SIZE ); // Configure your terminal for 8 Bits data (7 data bit + 1 parity bit), no parity and no flow ctrl UartInit( &Uart1, UART_1, UART_TX, UART_RX ); - UartConfig( &Uart1, RX_TX, 921600, UART_8_BIT, UART_1_STOP_BIT, NO_PARITY, NO_FLOW_CTRL ); + UartConfig( &Uart1, RX_TX, 115200, UART_8_BIT, UART_1_STOP_BIT, NO_PARITY, NO_FLOW_CTRL ); RtcInit( ); @@ -158,7 +184,7 @@ void BoardInitMcu( void ) #if ( USE_POTENTIOMETER == 0 ) GpioWrite( &Led1, 0 ); #endif - GpioWrite( &Led2, 0 ); + // GpioWrite( &Led2, 0 ); GpioWrite( &Led3, 0 ); GpioWrite( &Led4, 0 ); @@ -174,7 +200,7 @@ void BoardInitMcu( void ) SystemClockReConfig( ); } - AdcInit( &Adc, POTI ); + // AdcInit( &Adc, POTI ); SpiInit( &SX1272.Spi, SPI_1, RADIO_MOSI, RADIO_MISO, RADIO_SCLK, NC ); SX1272IoInit( ); @@ -325,6 +351,7 @@ uint8_t BoardGetBatteryLevel( void ) // } // else // { + GpioWrite(&Io1, 0); if( BatteryVoltage >= BATTERY_MAX_LEVEL ) { batteryLevel = 254; @@ -332,6 +359,10 @@ uint8_t BoardGetBatteryLevel( void ) else if( ( BatteryVoltage > BATTERY_MIN_LEVEL ) && ( BatteryVoltage < BATTERY_MAX_LEVEL ) ) { batteryLevel = ( ( 253 * ( BatteryVoltage - BATTERY_MIN_LEVEL ) ) / ( BATTERY_MAX_LEVEL - BATTERY_MIN_LEVEL ) ) + 1; + if(batteryLevel < (255 / 4)) + { + GpioWrite(&Io1, 1); + } } else if( ( BatteryVoltage > BATTERY_SHUTDOWN_LEVEL ) && ( BatteryVoltage <= BATTERY_MIN_LEVEL ) ) {