Update LoRaMac-node to Version 4.4.4,fix Security breach found by Tencent Blade Team please refer to security advisory - CVE-2020-11068
fix Security breach found by Tencent Blade Team please refer to security advisory - CVE-2020-11068
This commit is contained in:
@@ -103,7 +103,7 @@
|
||||
<bEvRecOn>1</bEvRecOn>
|
||||
<bSchkAxf>0</bSchkAxf>
|
||||
<bTchkAxf>0</bTchkAxf>
|
||||
<nTsel>0</nTsel>
|
||||
<nTsel>6</nTsel>
|
||||
<sDll></sDll>
|
||||
<sDllPa></sDllPa>
|
||||
<sDlgDll></sDlgDll>
|
||||
@@ -114,9 +114,34 @@
|
||||
<tDlgDll></tDlgDll>
|
||||
<tDlgPa></tDlgPa>
|
||||
<tIfile></tIfile>
|
||||
<pMon>BIN\UL2CM3.DLL</pMon>
|
||||
<pMon>STLink\ST-LINKIII-KEIL_SWO.dll</pMon>
|
||||
</DebugOpt>
|
||||
<TargetDriverDllRegistry>
|
||||
<SetRegEntry>
|
||||
<Number>0</Number>
|
||||
<Key>ARMRTXEVENTFLAGS</Key>
|
||||
<Name>-L70 -Z18 -C0 -M0 -T1</Name>
|
||||
</SetRegEntry>
|
||||
<SetRegEntry>
|
||||
<Number>0</Number>
|
||||
<Key>DLGTARM</Key>
|
||||
<Name>(1010=-1,-1,-1,-1,0)(1007=-1,-1,-1,-1,0)(1008=-1,-1,-1,-1,0)(1012=-1,-1,-1,-1,0)(1009=-1,-1,-1,-1,0)</Name>
|
||||
</SetRegEntry>
|
||||
<SetRegEntry>
|
||||
<Number>0</Number>
|
||||
<Key>ARMDBGFLAGS</Key>
|
||||
<Name></Name>
|
||||
</SetRegEntry>
|
||||
<SetRegEntry>
|
||||
<Number>0</Number>
|
||||
<Key>DLGUARM</Key>
|
||||
<Name>(105=-1,-1,-1,-1,0)</Name>
|
||||
</SetRegEntry>
|
||||
<SetRegEntry>
|
||||
<Number>0</Number>
|
||||
<Key>ST-LINKIII-KEIL_SWO</Key>
|
||||
<Name>-U066DFF495056805087213734 -O206 -SF4000 -C0 -A0 -I0 -HNlocalhost -HP7184 -P1 -N00("ARM CoreSight SW-DP") -D00(0BC11477) -L00(0) -TO18 -TC10000000 -TP21 -TDS8007 -TDT0 -TDC1F -TIEFFFFFFFF -TIP8 -FO7 -FD20000000 -FC1000 -FN1 -FF0STM32L0xx_128.FLM -FS08000000 -FL020000 -FP0($$Device:STM32L072CBTx$CMSIS\Flash\STM32L0xx_128.FLM)</Name>
|
||||
</SetRegEntry>
|
||||
<SetRegEntry>
|
||||
<Number>0</Number>
|
||||
<Key>UL2CM3</Key>
|
||||
@@ -130,12 +155,12 @@
|
||||
<DebugFlag>
|
||||
<trace>0</trace>
|
||||
<periodic>0</periodic>
|
||||
<aLwin>0</aLwin>
|
||||
<aLwin>1</aLwin>
|
||||
<aCover>0</aCover>
|
||||
<aSer1>0</aSer1>
|
||||
<aSer2>0</aSer2>
|
||||
<aPa>0</aPa>
|
||||
<viewmode>0</viewmode>
|
||||
<viewmode>1</viewmode>
|
||||
<vrSel>0</vrSel>
|
||||
<aSym>0</aSym>
|
||||
<aTbox>0</aTbox>
|
||||
@@ -198,7 +223,7 @@
|
||||
|
||||
<Group>
|
||||
<GroupName>Application/User</GroupName>
|
||||
<tvExp>1</tvExp>
|
||||
<tvExp>0</tvExp>
|
||||
<tvExpOptDlg>0</tvExpOptDlg>
|
||||
<cbSel>0</cbSel>
|
||||
<RteFlg>0</RteFlg>
|
||||
@@ -1002,7 +1027,7 @@
|
||||
|
||||
<Group>
|
||||
<GroupName>lorawan/mac</GroupName>
|
||||
<tvExp>0</tvExp>
|
||||
<tvExp>1</tvExp>
|
||||
<tvExpOptDlg>0</tvExpOptDlg>
|
||||
<cbSel>0</cbSel>
|
||||
<RteFlg>0</RteFlg>
|
||||
@@ -1085,18 +1110,6 @@
|
||||
<tvExp>0</tvExp>
|
||||
<tvExpOptDlg>0</tvExpOptDlg>
|
||||
<bDave2>0</bDave2>
|
||||
<PathWithFileName>..\..\..\components\connectivity\LoraWAN\mac\LoRaMacFCntHandler.c</PathWithFileName>
|
||||
<FilenameWithoutPath>LoRaMacFCntHandler.c</FilenameWithoutPath>
|
||||
<RteFlg>0</RteFlg>
|
||||
<bShared>0</bShared>
|
||||
</File>
|
||||
<File>
|
||||
<GroupNumber>5</GroupNumber>
|
||||
<FileNumber>74</FileNumber>
|
||||
<FileType>1</FileType>
|
||||
<tvExp>0</tvExp>
|
||||
<tvExpOptDlg>0</tvExpOptDlg>
|
||||
<bDave2>0</bDave2>
|
||||
<PathWithFileName>..\..\..\components\connectivity\LoraWAN\mac\LoRaMacParser.c</PathWithFileName>
|
||||
<FilenameWithoutPath>LoRaMacParser.c</FilenameWithoutPath>
|
||||
<RteFlg>0</RteFlg>
|
||||
@@ -1104,7 +1117,7 @@
|
||||
</File>
|
||||
<File>
|
||||
<GroupNumber>5</GroupNumber>
|
||||
<FileNumber>75</FileNumber>
|
||||
<FileNumber>74</FileNumber>
|
||||
<FileType>1</FileType>
|
||||
<tvExp>0</tvExp>
|
||||
<tvExpOptDlg>0</tvExpOptDlg>
|
||||
@@ -1116,7 +1129,7 @@
|
||||
</File>
|
||||
<File>
|
||||
<GroupNumber>5</GroupNumber>
|
||||
<FileNumber>76</FileNumber>
|
||||
<FileNumber>75</FileNumber>
|
||||
<FileType>1</FileType>
|
||||
<tvExp>0</tvExp>
|
||||
<tvExpOptDlg>0</tvExpOptDlg>
|
||||
@@ -1128,7 +1141,7 @@
|
||||
</File>
|
||||
<File>
|
||||
<GroupNumber>5</GroupNumber>
|
||||
<FileNumber>77</FileNumber>
|
||||
<FileNumber>76</FileNumber>
|
||||
<FileType>1</FileType>
|
||||
<tvExp>0</tvExp>
|
||||
<tvExpOptDlg>0</tvExpOptDlg>
|
||||
@@ -1140,7 +1153,7 @@
|
||||
</File>
|
||||
<File>
|
||||
<GroupNumber>5</GroupNumber>
|
||||
<FileNumber>78</FileNumber>
|
||||
<FileNumber>77</FileNumber>
|
||||
<FileType>1</FileType>
|
||||
<tvExp>0</tvExp>
|
||||
<tvExpOptDlg>0</tvExpOptDlg>
|
||||
@@ -1150,6 +1163,18 @@
|
||||
<RteFlg>0</RteFlg>
|
||||
<bShared>0</bShared>
|
||||
</File>
|
||||
<File>
|
||||
<GroupNumber>5</GroupNumber>
|
||||
<FileNumber>78</FileNumber>
|
||||
<FileType>1</FileType>
|
||||
<tvExp>0</tvExp>
|
||||
<tvExpOptDlg>0</tvExpOptDlg>
|
||||
<bDave2>0</bDave2>
|
||||
<PathWithFileName>..\..\..\components\connectivity\LoraWAN\peripherals\soft-se\soft-se-hal.c</PathWithFileName>
|
||||
<FilenameWithoutPath>soft-se-hal.c</FilenameWithoutPath>
|
||||
<RteFlg>0</RteFlg>
|
||||
<bShared>0</bShared>
|
||||
</File>
|
||||
</Group>
|
||||
|
||||
<Group>
|
||||
|
@@ -762,11 +762,6 @@
|
||||
<FileType>1</FileType>
|
||||
<FilePath>..\..\..\components\connectivity\LoraWAN\mac\LoRaMacCrypto.c</FilePath>
|
||||
</File>
|
||||
<File>
|
||||
<FileName>LoRaMacFCntHandler.c</FileName>
|
||||
<FileType>1</FileType>
|
||||
<FilePath>..\..\..\components\connectivity\LoraWAN\mac\LoRaMacFCntHandler.c</FilePath>
|
||||
</File>
|
||||
<File>
|
||||
<FileName>LoRaMacParser.c</FileName>
|
||||
<FileType>1</FileType>
|
||||
@@ -792,6 +787,11 @@
|
||||
<FileType>1</FileType>
|
||||
<FilePath>..\..\..\components\connectivity\LoraWAN\peripherals\soft-se\soft-se.c</FilePath>
|
||||
</File>
|
||||
<File>
|
||||
<FileName>soft-se-hal.c</FileName>
|
||||
<FileType>1</FileType>
|
||||
<FilePath>..\..\..\components\connectivity\LoraWAN\peripherals\soft-se\soft-se-hal.c</FilePath>
|
||||
</File>
|
||||
</Files>
|
||||
</Group>
|
||||
<Group>
|
||||
|
84
board/RHF76_STM32L072CBxx_Lora/Src/CMakeLists.txt
Normal file
84
board/RHF76_STM32L072CBxx_Lora/Src/CMakeLists.txt
Normal file
@@ -0,0 +1,84 @@
|
||||
##
|
||||
## ______ _
|
||||
## / _____) _ | |
|
||||
## ( (____ _____ ____ _| |_ _____ ____| |__
|
||||
## \____ \| ___ | (_ _) ___ |/ ___) _ \
|
||||
## _____) ) ____| | | || |_| ____( (___| | | |
|
||||
## (______/|_____)_|_|_| \__)_____)\____)_| |_|
|
||||
## (C)2013-2017 Semtech
|
||||
## ___ _____ _ ___ _ _____ ___ ___ ___ ___
|
||||
## / __|_ _/_\ / __| |/ / __/ _ \| _ \/ __| __|
|
||||
## \__ \ | |/ _ \ (__| ' <| _| (_) | / (__| _|
|
||||
## |___/ |_/_/ \_\___|_|\_\_| \___/|_|_\\___|___|
|
||||
## embedded.connectivity.solutions.==============
|
||||
##
|
||||
## License: Revised BSD License, see LICENSE.TXT file included in the project
|
||||
## Authors: Johannes Bruder (STACKFORCE), Miguel Luis (Semtech)
|
||||
##
|
||||
project(B-L072Z-LRWAN1)
|
||||
cmake_minimum_required(VERSION 3.6)
|
||||
enable_language(ASM)
|
||||
|
||||
#---------------------------------------------------------------------------------------
|
||||
# Target
|
||||
#---------------------------------------------------------------------------------------
|
||||
|
||||
list(APPEND ${PROJECT_NAME}_SOURCES
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/adc-board.c"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/board.c"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/delay-board.c"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/eeprom-board.c"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/gpio-board.c"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/lpm-board.c"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/rtc-board.c"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/spi-board.c"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/sx1276-board.c"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/uart-board.c"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/../mcu/stm32/sysIrqHandlers.c"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/../mcu/utilities.c"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/cmsis/arm-gcc/startup_stm32l072xx.s"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/cmsis/system_stm32l0xx.c"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/../mcu/stm32/STM32L0xx_HAL_Driver/Src/stm32l0xx_hal.c"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/../mcu/stm32/STM32L0xx_HAL_Driver/Src/stm32l0xx_hal_adc.c"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/../mcu/stm32/STM32L0xx_HAL_Driver/Src/stm32l0xx_hal_adc_ex.c"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/../mcu/stm32/STM32L0xx_HAL_Driver/Src/stm32l0xx_hal_cortex.c"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/../mcu/stm32/STM32L0xx_HAL_Driver/Src/stm32l0xx_hal_dma.c"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/../mcu/stm32/STM32L0xx_HAL_Driver/Src/stm32l0xx_hal_flash.c"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/../mcu/stm32/STM32L0xx_HAL_Driver/Src/stm32l0xx_hal_flash_ex.c"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/../mcu/stm32/STM32L0xx_HAL_Driver/Src/stm32l0xx_hal_gpio.c"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/../mcu/stm32/STM32L0xx_HAL_Driver/Src/stm32l0xx_hal_i2c.c"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/../mcu/stm32/STM32L0xx_HAL_Driver/Src/stm32l0xx_hal_i2c_ex.c"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/../mcu/stm32/STM32L0xx_HAL_Driver/Src/stm32l0xx_hal_pwr.c"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/../mcu/stm32/STM32L0xx_HAL_Driver/Src/stm32l0xx_hal_pwr_ex.c"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/../mcu/stm32/STM32L0xx_HAL_Driver/Src/stm32l0xx_hal_rcc.c"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/../mcu/stm32/STM32L0xx_HAL_Driver/Src/stm32l0xx_hal_rcc_ex.c"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/../mcu/stm32/STM32L0xx_HAL_Driver/Src/stm32l0xx_hal_rtc.c"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/../mcu/stm32/STM32L0xx_HAL_Driver/Src/stm32l0xx_hal_rtc_ex.c"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/../mcu/stm32/STM32L0xx_HAL_Driver/Src/stm32l0xx_hal_spi.c"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/../mcu/stm32/STM32L0xx_HAL_Driver/Src/stm32l0xx_hal_uart.c"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/../mcu/stm32/STM32L0xx_HAL_Driver/Src/stm32l0xx_hal_uart_ex.c"
|
||||
)
|
||||
|
||||
add_library(${PROJECT_NAME} OBJECT EXCLUDE_FROM_ALL ${${PROJECT_NAME}_SOURCES})
|
||||
|
||||
target_compile_definitions(${PROJECT_NAME} PUBLIC -DUSE_HAL_DRIVER -DSTM32L072xx)
|
||||
|
||||
# Add define if debbuger support is enabled
|
||||
target_compile_definitions(${PROJECT_NAME} PUBLIC $<$<BOOL:${USE_DEBUGGER}>:USE_DEBUGGER>)
|
||||
|
||||
# Add define if radio debug pins support is enabled
|
||||
target_compile_definitions(${PROJECT_NAME} PUBLIC $<$<BOOL:${USE_RADIO_DEBUG}>:USE_RADIO_DEBUG>)
|
||||
|
||||
target_include_directories(${PROJECT_NAME} PUBLIC
|
||||
${CMAKE_CURRENT_SOURCE_DIR}
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/cmsis
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/../mcu/stm32
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/../mcu/stm32/cmsis
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/../mcu/stm32/STM32L0xx_HAL_Driver/Inc
|
||||
$<TARGET_PROPERTY:board,INTERFACE_INCLUDE_DIRECTORIES>
|
||||
$<TARGET_PROPERTY:system,INTERFACE_INCLUDE_DIRECTORIES>
|
||||
$<TARGET_PROPERTY:radio,INTERFACE_INCLUDE_DIRECTORIES>
|
||||
$<TARGET_PROPERTY:peripherals,INTERFACE_INCLUDE_DIRECTORIES>
|
||||
)
|
||||
|
||||
set_property(TARGET ${PROJECT_NAME} PROPERTY C_STANDARD 11)
|
@@ -20,6 +20,8 @@
|
||||
*
|
||||
* \author Gregory Cristian ( Semtech )
|
||||
*/
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include "stm32l0xx.h"
|
||||
#include "board-config.h"
|
||||
#include "adc-board.h"
|
||||
@@ -70,6 +72,8 @@ uint16_t AdcMcuReadChannel( Adc_t *obj, uint32_t channel )
|
||||
{
|
||||
ADC_ChannelConfTypeDef adcConf = { 0 };
|
||||
uint16_t adcData = 0;
|
||||
uint32_t tickStart = 0;
|
||||
bool isAdcReady = true;
|
||||
|
||||
// Enable HSI
|
||||
__HAL_RCC_HSI_ENABLE( );
|
||||
@@ -83,18 +87,31 @@ uint16_t AdcMcuReadChannel( Adc_t *obj, uint32_t channel )
|
||||
|
||||
adcConf.Channel = channel;
|
||||
adcConf.Rank = ADC_RANK_CHANNEL_NUMBER;
|
||||
|
||||
HAL_ADC_ConfigChannel( &AdcHandle, &adcConf );
|
||||
|
||||
// Enable ADC1
|
||||
__HAL_ADC_ENABLE( &AdcHandle );
|
||||
|
||||
// Start ADC Software Conversion
|
||||
HAL_ADC_Start( &AdcHandle );
|
||||
// Wait for ADC to effectively be enabled
|
||||
tickStart = HAL_GetTick( );
|
||||
while( __HAL_ADC_GET_FLAG( &AdcHandle, ADC_FLAG_RDY ) == RESET )
|
||||
{
|
||||
if( ( HAL_GetTick( ) - tickStart ) > ADC_ENABLE_TIMEOUT )
|
||||
{
|
||||
isAdcReady = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
HAL_ADC_PollForConversion( &AdcHandle, HAL_MAX_DELAY );
|
||||
if( isAdcReady != false )
|
||||
{
|
||||
// Start ADC Software Conversion
|
||||
HAL_ADC_Start( &AdcHandle );
|
||||
|
||||
adcData = HAL_ADC_GetValue( &AdcHandle );
|
||||
HAL_ADC_PollForConversion( &AdcHandle, HAL_MAX_DELAY );
|
||||
|
||||
adcData = HAL_ADC_GetValue( &AdcHandle );
|
||||
}
|
||||
|
||||
__HAL_ADC_DISABLE( &AdcHandle );
|
||||
|
||||
|
@@ -185,8 +185,8 @@ void RtcInit( void )
|
||||
time.Seconds = 0;
|
||||
time.SubSeconds = 0;
|
||||
time.TimeFormat = 0;
|
||||
time.StoreOperation = RTC_DAYLIGHTSAVING_NONE;
|
||||
time.DayLightSaving = RTC_STOREOPERATION_RESET;
|
||||
time.StoreOperation = RTC_STOREOPERATION_RESET;
|
||||
time.DayLightSaving = RTC_DAYLIGHTSAVING_NONE;
|
||||
HAL_RTC_SetTime( &RtcHandle, &time, RTC_FORMAT_BIN );
|
||||
|
||||
// Enable Direct Read of the calendar registers (not through Shadow registers)
|
||||
@@ -469,7 +469,7 @@ void RtcSetMcuWakeUpTime( void )
|
||||
|
||||
mcuWakeUpTime = ( int16_t )( ( now - hit ) );
|
||||
McuWakeUpTimeCal += mcuWakeUpTime;
|
||||
//PRINTF( 3, "Cal=%d, %d\n\r", McuWakeUpTimeCal, mcuWakeUpTime);
|
||||
//PRINTF( 3, "Cal=%d, %d\n", McuWakeUpTimeCal, mcuWakeUpTime);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -485,16 +485,13 @@ static uint64_t RtcGetCalendarValue( RTC_DateTypeDef* date, RTC_TimeTypeDef* tim
|
||||
uint32_t correction;
|
||||
uint32_t seconds;
|
||||
|
||||
// Get Time and Date
|
||||
HAL_RTC_GetTime( &RtcHandle, time, RTC_FORMAT_BIN );
|
||||
|
||||
// Make sure it is correct due to asynchronus nature of RTC
|
||||
do
|
||||
{
|
||||
firstRead = time->SubSeconds;
|
||||
firstRead = RTC->SSR;
|
||||
HAL_RTC_GetDate( &RtcHandle, date, RTC_FORMAT_BIN );
|
||||
HAL_RTC_GetTime( &RtcHandle, time, RTC_FORMAT_BIN );
|
||||
}while( firstRead != time->SubSeconds );
|
||||
}while( firstRead != RTC->SSR );
|
||||
|
||||
// Calculte amount of elapsed days since 01/01/2000
|
||||
seconds = DIVC( ( DAYS_IN_YEAR * 3 + DAYS_IN_LEAP_YEAR ) * date->Year , 4 );
|
||||
@@ -525,7 +522,7 @@ uint32_t RtcGetCalendarTime( uint16_t *milliseconds )
|
||||
|
||||
uint64_t calendarValue = RtcGetCalendarValue( &date, &time );
|
||||
|
||||
uint32_t seconds = ( uint32_t )calendarValue >> N_PREDIV_S;
|
||||
uint32_t seconds = ( uint32_t )( calendarValue >> N_PREDIV_S );
|
||||
|
||||
ticks = ( uint32_t )calendarValue & PREDIV_S;
|
||||
|
||||
@@ -594,10 +591,10 @@ TimerTime_t RtcTempCompensation( TimerTime_t period, float temperature )
|
||||
float kDev = RTC_TEMP_DEV_COEFFICIENT;
|
||||
float t = RTC_TEMP_TURNOVER;
|
||||
float tDev = RTC_TEMP_DEV_TURNOVER;
|
||||
float interim = 0.0;
|
||||
float ppm = 0.0;
|
||||
float interim = 0.0f;
|
||||
float ppm = 0.0f;
|
||||
|
||||
if( k < 0.0 )
|
||||
if( k < 0.0f )
|
||||
{
|
||||
ppm = ( k - kDev );
|
||||
}
|
||||
@@ -609,12 +606,12 @@ TimerTime_t RtcTempCompensation( TimerTime_t period, float temperature )
|
||||
ppm *= interim * interim;
|
||||
|
||||
// Calculate the drift in time
|
||||
interim = ( ( float ) period * ppm ) / 1e6;
|
||||
interim = ( ( float ) period * ppm ) / 1000000.0f;
|
||||
// Calculate the resulting time period
|
||||
interim += period;
|
||||
interim = floor( interim );
|
||||
|
||||
if( interim < 0.0 )
|
||||
if( interim < 0.0f )
|
||||
{
|
||||
interim = ( float )period;
|
||||
}
|
||||
|
@@ -140,12 +140,24 @@ void SX1276IoDeInit( void )
|
||||
GpioInit( &SX1276.DIO5, RADIO_DIO_5, PIN_INPUT, PIN_PUSH_PULL, PIN_NO_PULL, 0 );
|
||||
}
|
||||
|
||||
void SX1276IoDbgInit( void )
|
||||
{
|
||||
#if defined( USE_RADIO_DEBUG )
|
||||
GpioInit( &DbgPinTx, RADIO_DBG_PIN_TX, PIN_OUTPUT, PIN_PUSH_PULL, PIN_NO_PULL, 0 );
|
||||
GpioInit( &DbgPinRx, RADIO_DBG_PIN_RX, PIN_OUTPUT, PIN_PUSH_PULL, PIN_NO_PULL, 0 );
|
||||
#endif
|
||||
}
|
||||
|
||||
void SX1276IoTcxoInit( void )
|
||||
{
|
||||
GpioInit( &TcxoPower, RADIO_TCXO_POWER, PIN_OUTPUT, PIN_PUSH_PULL, PIN_NO_PULL, 0 );
|
||||
}
|
||||
/*!
|
||||
* \brief Enables/disables the TCXO if available on board design.
|
||||
*
|
||||
* \param [IN] state TCXO enabled when true and disabled when false.
|
||||
*/
|
||||
static void SX1276SetBoardTcxo( uint8_t state )
|
||||
void SX1276SetBoardTcxo( uint8_t state )
|
||||
{
|
||||
if( state == true )
|
||||
{
|
||||
|
@@ -22,6 +22,7 @@ uint8_t NwkSEncKey[] = { 0x2B, 0x7E, 0x15, 0x16, 0x28, 0xAE, 0xD2, 0xA6, 0xAB, 0
|
||||
uint8_t AppSKey[] = { 0x2B, 0x7E, 0x15, 0x16, 0x28, 0xAE, 0xD2, 0xA6, 0xAB, 0xF7, 0x15, 0x88, 0x09, 0xCF, 0x4F, 0x3C };
|
||||
#endif
|
||||
|
||||
|
||||
bool NextTx = true;
|
||||
uint8_t IsTxConfirmed = false;
|
||||
TimerEvent_t TxNextPacketTimer;
|
||||
@@ -318,8 +319,6 @@ void LoRa_JoinNetwork(uint8_t jointype)
|
||||
{
|
||||
MlmeReq_t mlmeReq;
|
||||
mlmeReq.Type = MLME_JOIN;
|
||||
mlmeReq.Req.Join.DevEui = DevEui;
|
||||
mlmeReq.Req.Join.JoinEui = JoinEui;
|
||||
mlmeReq.Req.Join.Datarate = LORAWAN_DEFAULT_DATARATE;
|
||||
LoRaMacMlmeRequest( &mlmeReq );
|
||||
}
|
||||
|
@@ -9,6 +9,47 @@
|
||||
#include "LoRaMac.h"
|
||||
#include "NvmCtxMgmt.h"
|
||||
|
||||
#define ACTIVE_REGION LORAMAC_REGION_CN470
|
||||
|
||||
#ifndef ACTIVE_REGION
|
||||
|
||||
#warning "No active region defined, LORAMAC_REGION_EU868 will be used as default."
|
||||
|
||||
#define ACTIVE_REGION LORAMAC_REGION_EU868
|
||||
|
||||
#endif
|
||||
|
||||
/*!
|
||||
* Defines the application data transmission duty cycle. 5s, value in [ms].
|
||||
*/
|
||||
#define APP_TX_DUTYCYCLE 5000
|
||||
|
||||
/*!
|
||||
* Defines a random delay for application data transmission duty cycle. 1s,
|
||||
* value in [ms].
|
||||
*/
|
||||
#define APP_TX_DUTYCYCLE_RND 1000
|
||||
|
||||
/*!
|
||||
* Default datarate
|
||||
*/
|
||||
#define LORAWAN_DEFAULT_DATARATE DR_0
|
||||
|
||||
/*!
|
||||
* LoRaWAN confirmed messages
|
||||
*/
|
||||
#define LORAWAN_CONFIRMED_MSG_ON false
|
||||
|
||||
/*!
|
||||
* LoRaWAN Adaptive Data Rate
|
||||
*
|
||||
* \remark Please note that when ADR is enabled the end-device should be static
|
||||
*/
|
||||
#define LORAWAN_ADR_ON 1
|
||||
|
||||
#define LORAWAN_DUTYCYCLE_ON false
|
||||
|
||||
|
||||
#define OVER_THE_AIR_ACTIVATION 0
|
||||
|
||||
#define ABP_ACTIVATION_LRWAN_VERSION_V10x 0x01000300 // 1.0.3.0
|
||||
@@ -19,16 +60,13 @@
|
||||
|
||||
#define LORAWAN_NETWORK_ID ( uint32_t )0
|
||||
|
||||
#define ACTIVE_REGION LORAMAC_REGION_CN470
|
||||
|
||||
#define LORAWAN_APP_DATA_MAX_SIZE 64
|
||||
|
||||
#define LORAWAN_DEFAULT_DATARATE DR_0
|
||||
|
||||
|
||||
#define LORAWAN_ADR_ON 1
|
||||
|
||||
#define LORAWAN_DUTYCYCLE_ON false
|
||||
|
||||
|
||||
|
||||
extern bool NextTx;
|
||||
|
@@ -23,6 +23,11 @@
|
||||
#ifndef __ADC_BOARD_H__
|
||||
#define __ADC_BOARD_H__
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
#include "adc.h"
|
||||
|
||||
/*!
|
||||
@@ -46,4 +51,8 @@ void AdcMcuConfig( void );
|
||||
*/
|
||||
uint16_t AdcMcuReadChannel( Adc_t *obj, uint32_t channel );
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // __ADC_BOARD_H__
|
||||
|
@@ -23,6 +23,11 @@
|
||||
#ifndef __BOARD_H__
|
||||
#define __BOARD_H__
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
#include <stdint.h>
|
||||
#include "utilities.h"
|
||||
/*!
|
||||
@@ -113,4 +118,8 @@ uint8_t GetBoardPowerSource( void );
|
||||
*/
|
||||
Version_t BoardGetVersion( void );
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // __BOARD_H__
|
||||
|
@@ -25,6 +25,11 @@
|
||||
#ifndef __DELAY_BOARD_H__
|
||||
#define __DELAY_BOARD_H__
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
/*!
|
||||
@@ -34,4 +39,8 @@
|
||||
*/
|
||||
void DelayMsMcu( uint32_t ms );
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // __DELAY_BOARD_H__
|
||||
|
@@ -28,6 +28,11 @@
|
||||
#ifndef __DISPLAY_BOARD_H__
|
||||
#define __DISPLAY_BOARD_H__
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
@@ -290,4 +295,8 @@ void DisplayPrint( const char *string );
|
||||
*/
|
||||
void DisplayPrintf( const char *format, ... );
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // __DISPLAY_BOARD_H__
|
||||
|
@@ -23,6 +23,11 @@
|
||||
#ifndef __EEPROM_BOARD_H__
|
||||
#define __EEPROM_BOARD_H__
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
/*!
|
||||
@@ -31,7 +36,7 @@
|
||||
* \param[IN] addr EEPROM address to write to
|
||||
* \param[IN] buffer Pointer to the buffer to be written.
|
||||
* \param[IN] size Size of the buffer to be written.
|
||||
* \retval status [LORA_SUCCESS, LORA_FAIL]
|
||||
* \retval status [SUCCESS, FAIL]
|
||||
*/
|
||||
uint8_t EepromMcuWriteBuffer( uint16_t addr, uint8_t *buffer, uint16_t size );
|
||||
|
||||
@@ -41,7 +46,7 @@ uint8_t EepromMcuWriteBuffer( uint16_t addr, uint8_t *buffer, uint16_t size );
|
||||
* \param[IN] addr EEPROM address to read from
|
||||
* \param[OUT] buffer Pointer to the buffer to be written with read data.
|
||||
* \param[IN] size Size of the buffer to be read.
|
||||
* \retval status [LORA_SUCCESS, LORA_FAIL]
|
||||
* \retval status [SUCCESS, FAIL]
|
||||
*/
|
||||
uint8_t EepromMcuReadBuffer( uint16_t addr, uint8_t *buffer, uint16_t size );
|
||||
|
||||
@@ -63,4 +68,8 @@ void EepromMcuSetDeviceAddr( uint8_t addr );
|
||||
*/
|
||||
uint8_t EepromMcuGetDeviceAddr( void );
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // __EEPROM_BOARD_H__
|
||||
|
@@ -23,6 +23,11 @@
|
||||
#ifndef __GPIO_BOARD_H__
|
||||
#define __GPIO_BOARD_H__
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
#include "gpio.h"
|
||||
|
||||
/*!
|
||||
@@ -89,4 +94,8 @@ void GpioMcuToggle( Gpio_t *obj );
|
||||
*/
|
||||
uint32_t GpioMcuRead( Gpio_t *obj );
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // __GPIO_BOARD_H__
|
||||
|
@@ -23,6 +23,11 @@
|
||||
#ifndef __GPS_BOARD_H__
|
||||
#define __GPS_BOARD_H__
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
#include "uart.h"
|
||||
|
||||
/*!
|
||||
@@ -71,4 +76,8 @@ void GpsMcuProcess( void );
|
||||
*/
|
||||
void GpsMcuIrqNotify( UartNotifyId_t id );
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // __GPS_BOARD_H__
|
||||
|
@@ -23,6 +23,11 @@
|
||||
#ifndef __I2C_BOARD_H__
|
||||
#define __I2C_BOARD_H__
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include "i2c.h"
|
||||
@@ -137,4 +142,8 @@ uint8_t I2cMcuWaitStandbyState( I2c_t *obj, uint8_t deviceAddr );
|
||||
*/
|
||||
void I2cSetAddrSize( I2c_t *obj, I2cAddrSize addrSize );
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // __I2C_BOARD_H__
|
||||
|
@@ -25,8 +25,10 @@
|
||||
#ifndef __LPM_BOARD_H__
|
||||
#define __LPM_BOARD_H__
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
#include "board-config.h"
|
||||
|
74
components/connectivity/LoraWAN/boards_common/lr1110-board.h
Normal file
74
components/connectivity/LoraWAN/boards_common/lr1110-board.h
Normal file
@@ -0,0 +1,74 @@
|
||||
/*!
|
||||
* \file lr1110-board.h
|
||||
*
|
||||
* \brief Target board LR1110 driver implementation
|
||||
*
|
||||
* \copyright Revised BSD License, see section \ref LICENSE.
|
||||
*
|
||||
* \code
|
||||
* ______ _
|
||||
* / _____) _ | |
|
||||
* ( (____ _____ ____ _| |_ _____ ____| |__
|
||||
* \____ \| ___ | (_ _) ___ |/ ___) _ \
|
||||
* _____) ) ____| | | || |_| ____( (___| | | |
|
||||
* (______/|_____)_|_|_| \__)_____)\____)_| |_|
|
||||
* (C)2013-2017 Semtech
|
||||
*
|
||||
* \endcode
|
||||
*
|
||||
* \author Miguel Luis ( Semtech )
|
||||
*
|
||||
* \author Gregory Cristian ( Semtech )
|
||||
*/
|
||||
#ifndef __LR1110_BOARD_H__
|
||||
#define __LR1110_BOARD_H__
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include "lr1110.h"
|
||||
|
||||
/*!
|
||||
* \brief Initializes the radio I/Os pins interface
|
||||
*/
|
||||
void lr1110_board_init_io( const void* context );
|
||||
|
||||
/*!
|
||||
* \brief De-initializes the radio I/Os pins interface.
|
||||
*
|
||||
* \remark Useful when going in MCU low power modes
|
||||
*/
|
||||
void lr1110_board_deinit_io( const void* context );
|
||||
|
||||
/*!
|
||||
* \brief Initializes the radio debug pins.
|
||||
*/
|
||||
void lr1110_board_init_dbg_io( const void* context );
|
||||
|
||||
/*!
|
||||
* \brief Sets the radio output power.
|
||||
*
|
||||
* \param [IN] power Sets the RF output power
|
||||
*/
|
||||
void lr1110_board_set_rf_tx_power( const void* context, int8_t power );
|
||||
|
||||
/*!
|
||||
* \brief Gets the Defines the time required for the TCXO to wakeup [ms].
|
||||
*
|
||||
* \retval time Board TCXO wakeup time in ms.
|
||||
*/
|
||||
uint32_t lr1110_board_get_tcxo_wakeup_time( const void* context );
|
||||
|
||||
/*!
|
||||
* \brief Initializes the radio driver
|
||||
*/
|
||||
void lr1110_board_init( const void* context, lr1110_dio_irq_handler dio_irq );
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // __LR1110_BOARD_H__
|
@@ -23,6 +23,11 @@
|
||||
#ifndef __PIN_NAME_BOARD_H__
|
||||
#define __PIN_NAME_BOARD_H__
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
/*!
|
||||
* STM32 Pin Names
|
||||
*/
|
||||
@@ -35,4 +40,8 @@
|
||||
PF_0, PF_1, PF_2, PF_3, PF_4, PF_5, PF_6, PF_7, PF_8, PF_9, PF_10, PF_11, PF_12, PF_13, PF_14, PF_15, \
|
||||
PH_0, PH_1, PH_2, PH_3, PH_4, PH_5, PH_6, PH_7, PH_8, PH_9, PH_10, PH_11, PH_12, PH_13, PH_14, PH_15
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // __PIN_NAME_BOARD_H__
|
||||
|
@@ -23,8 +23,18 @@
|
||||
#ifndef __PIN_NAME_IOE_H__
|
||||
#define __PIN_NAME_IOE_H__
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
// SX1509 Pin Names
|
||||
#define IOE_PINS \
|
||||
IOE_0, IOE_1, IOE_2, IOE_3, IOE_4, IOE_5, IOE_6, IOE_7, \
|
||||
IOE_8, IOE_9, IOE_10, IOE_11, IOE_12, IOE_13, IOE_14, IOE_15
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // __PIN_NAME_IOE_H__
|
||||
|
@@ -23,6 +23,11 @@
|
||||
#ifndef __RTC_BOARD_H__
|
||||
#define __RTC_BOARD_H__
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include "timer.h"
|
||||
@@ -30,22 +35,22 @@
|
||||
/*!
|
||||
* \brief Temperature coefficient of the clock source
|
||||
*/
|
||||
#define RTC_TEMP_COEFFICIENT ( -0.035 )
|
||||
#define RTC_TEMP_COEFFICIENT ( -0.035f )
|
||||
|
||||
/*!
|
||||
* \brief Temperature coefficient deviation of the clock source
|
||||
*/
|
||||
#define RTC_TEMP_DEV_COEFFICIENT ( 0.0035 )
|
||||
#define RTC_TEMP_DEV_COEFFICIENT ( 0.0035f )
|
||||
|
||||
/*!
|
||||
* \brief Turnover temperature of the clock source
|
||||
*/
|
||||
#define RTC_TEMP_TURNOVER ( 25.0 )
|
||||
#define RTC_TEMP_TURNOVER ( 25.0f )
|
||||
|
||||
/*!
|
||||
* \brief Turnover temperature deviation of the clock source
|
||||
*/
|
||||
#define RTC_TEMP_DEV_TURNOVER ( 5.0 )
|
||||
#define RTC_TEMP_DEV_TURNOVER ( 5.0f )
|
||||
|
||||
/*!
|
||||
* \brief Initializes the RTC timer
|
||||
@@ -189,4 +194,8 @@ void RtcProcess( void );
|
||||
*/
|
||||
TimerTime_t RtcTempCompensation( TimerTime_t period, float temperature );
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // __RTC_BOARD_H__
|
||||
|
@@ -23,8 +23,17 @@
|
||||
#ifndef __SPI_BOARD_H__
|
||||
#define __SPI_BOARD_H__
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
#include "spi.h"
|
||||
|
||||
// An Spi.c file has to be implmented under system directory.
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // __SPI_BOARD_H__
|
||||
|
@@ -23,6 +23,11 @@
|
||||
#ifndef __SX126x_BOARD_H__
|
||||
#define __SX126x_BOARD_H__
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include "sx126x/sx126x.h"
|
||||
@@ -46,6 +51,16 @@ void SX126xIoIrqInit( DioIrqHandler dioIrq );
|
||||
*/
|
||||
void SX126xIoDeInit( void );
|
||||
|
||||
/*!
|
||||
* \brief Initializes the TCXO power pin.
|
||||
*/
|
||||
void SX126xIoTcxoInit( void );
|
||||
|
||||
/*!
|
||||
* \brief Initializes the radio debug pins.
|
||||
*/
|
||||
void SX126xIoDbgInit( void );
|
||||
|
||||
/*!
|
||||
* \brief HW Reset of the radio
|
||||
*/
|
||||
@@ -76,8 +91,10 @@ void SX126xWriteCommand( RadioCommands_t opcode, uint8_t *buffer, uint16_t size
|
||||
* \param [in] opcode Opcode of the command
|
||||
* \param [out] buffer Buffer holding data from the radio
|
||||
* \param [in] size Size of the buffer
|
||||
*
|
||||
* \retval status Return command radio status
|
||||
*/
|
||||
void SX126xReadCommand( RadioCommands_t opcode, uint8_t *buffer, uint16_t size );
|
||||
uint8_t SX126xReadCommand( RadioCommands_t opcode, uint8_t *buffer, uint16_t size );
|
||||
|
||||
/*!
|
||||
* \brief Write a single byte of data to the radio memory
|
||||
@@ -156,4 +173,8 @@ void SX126xDbgPinRxWrite( uint8_t state );
|
||||
*/
|
||||
extern SX126x_t SX126x;
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // __SX126x_BOARD_H__
|
||||
|
@@ -23,6 +23,11 @@
|
||||
#ifndef __SX1272_BOARD_H__
|
||||
#define __SX1272_BOARD_H__
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include "sx1272/sx1272.h"
|
||||
@@ -72,6 +77,16 @@ void SX1272IoIrqInit( DioIrqHandler **irqHandlers );
|
||||
*/
|
||||
void SX1272IoDeInit( void );
|
||||
|
||||
/*!
|
||||
* \brief Initializes the TCXO power pin.
|
||||
*/
|
||||
void SX1272IoTcxoInit( void );
|
||||
|
||||
/*!
|
||||
* \brief Initializes the radio debug pins.
|
||||
*/
|
||||
void SX1272IoDbgInit( void );
|
||||
|
||||
/*!
|
||||
* \brief Resets the radio
|
||||
*/
|
||||
@@ -120,6 +135,13 @@ void SX1272SetAntSw( uint8_t opMode );
|
||||
*/
|
||||
bool SX1272CheckRfFrequency( uint32_t frequency );
|
||||
|
||||
/*!
|
||||
* \brief Enables/disables the TCXO if available on board design.
|
||||
*
|
||||
* \param [IN] state TCXO enabled when true and disabled when false.
|
||||
*/
|
||||
void SX1272SetBoardTcxo( uint8_t state );
|
||||
|
||||
/*!
|
||||
* \brief Gets the Defines the time required for the TCXO to wakeup [ms].
|
||||
*
|
||||
@@ -146,4 +168,8 @@ void SX1272DbgPinRxWrite( uint8_t state );
|
||||
*/
|
||||
extern SX1272_t SX1272;
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // __SX1272_BOARD_H__
|
||||
|
@@ -23,6 +23,11 @@
|
||||
#ifndef __SX1276_BOARD_H__
|
||||
#define __SX1276_BOARD_H__
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include "sx1276/sx1276.h"
|
||||
@@ -73,6 +78,16 @@ void SX1276IoIrqInit( DioIrqHandler **irqHandlers );
|
||||
*/
|
||||
void SX1276IoDeInit( void );
|
||||
|
||||
/*!
|
||||
* \brief Initializes the TCXO power pin.
|
||||
*/
|
||||
void SX1276IoTcxoInit( void );
|
||||
|
||||
/*!
|
||||
* \brief Initializes the radio debug pins.
|
||||
*/
|
||||
void SX1276IoDbgInit( void );
|
||||
|
||||
/*!
|
||||
* \brief Resets the radio
|
||||
*/
|
||||
@@ -121,6 +136,13 @@ void SX1276SetAntSw( uint8_t opMode );
|
||||
*/
|
||||
bool SX1276CheckRfFrequency( uint32_t frequency );
|
||||
|
||||
/*!
|
||||
* \brief Enables/disables the TCXO if available on board design.
|
||||
*
|
||||
* \param [IN] state TCXO enabled when true and disabled when false.
|
||||
*/
|
||||
void SX1276SetBoardTcxo( uint8_t state );
|
||||
|
||||
/*!
|
||||
* \brief Gets the Defines the time required for the TCXO to wakeup [ms].
|
||||
*
|
||||
@@ -147,4 +169,8 @@ void SX1276DbgPinRxWrite( uint8_t state );
|
||||
*/
|
||||
extern SX1276_t SX1276;
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // __SX1276_BOARD_H__
|
||||
|
@@ -23,6 +23,11 @@
|
||||
#ifndef __UART_BOARD_H__
|
||||
#define __UART_BOARD_H__
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
#include <stdint.h>
|
||||
#include "uart.h"
|
||||
|
||||
@@ -96,4 +101,8 @@ uint8_t UartMcuGetChar( Uart_t *obj, uint8_t *data );
|
||||
*/
|
||||
uint8_t UartMcuGetBuffer( Uart_t *obj, uint8_t *buffer, uint16_t size, uint16_t *nbReadBytes );
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // __UART_BOARD_H__
|
||||
|
@@ -23,6 +23,11 @@
|
||||
#ifndef __UART_USB_BOARD_H__
|
||||
#define __UART_USB_BOARD_H__
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
#include <stdint.h>
|
||||
#include "uart.h"
|
||||
|
||||
@@ -90,4 +95,8 @@ uint8_t UartUsbPutChar( Uart_t *obj, uint8_t data );
|
||||
*/
|
||||
uint8_t UartUsbGetChar( Uart_t *obj, uint8_t *data );
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // __UART_USB_BOARD_H__
|
||||
|
@@ -23,6 +23,11 @@
|
||||
#ifndef __UTILITIES_H__
|
||||
#define __UTILITIES_H__
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
/*!
|
||||
@@ -43,7 +48,9 @@
|
||||
* \param [IN] b 2nd value
|
||||
* \retval minValue Minimum value
|
||||
*/
|
||||
#ifndef MIN
|
||||
#define MIN( a, b ) ( ( ( a ) < ( b ) ) ? ( a ) : ( b ) )
|
||||
#endif
|
||||
|
||||
/*!
|
||||
* \brief Returns the maximum value between a and b
|
||||
@@ -52,7 +59,9 @@
|
||||
* \param [IN] b 2nd value
|
||||
* \retval maxValue Maximum value
|
||||
*/
|
||||
#ifndef MAX
|
||||
#define MAX( a, b ) ( ( ( a ) > ( b ) ) ? ( a ) : ( b ) )
|
||||
#endif
|
||||
|
||||
/*!
|
||||
* \brief Returns 2 raised to the power of n
|
||||
@@ -69,8 +78,8 @@ typedef union Version_u
|
||||
{
|
||||
struct Version_s
|
||||
{
|
||||
uint8_t Rfu;
|
||||
uint8_t Revision;
|
||||
uint8_t Patch;
|
||||
uint8_t Minor;
|
||||
uint8_t Major;
|
||||
}Fields;
|
||||
@@ -162,4 +171,8 @@ void BoardCriticalSectionBegin( uint32_t *mask );
|
||||
*/
|
||||
void BoardCriticalSectionEnd( uint32_t *mask );
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // __UTILITIES_H__
|
||||
|
File diff suppressed because it is too large
Load Diff
@@ -36,6 +36,15 @@
|
||||
* layer and the supported features.
|
||||
* \{
|
||||
*
|
||||
* \example classA/B-L072Z-LRWAN1/main.c
|
||||
* LoRaWAN class A application example for the B-L072Z-LRWAN1.
|
||||
*
|
||||
* \example classB/B-L072Z-LRWAN1/main.c
|
||||
* LoRaWAN class B application example for the B-L072Z-LRWAN1.
|
||||
*
|
||||
* \example classC/B-L072Z-LRWAN1/main.c
|
||||
* LoRaWAN class C application example for the B-L072Z-LRWAN1.
|
||||
*
|
||||
* \example classA/NAMote72/main.c
|
||||
* LoRaWAN class A application example for the NAMote72.
|
||||
*
|
||||
@@ -63,10 +72,60 @@
|
||||
* \example classC/NucleoL152/main.c
|
||||
* LoRaWAN class C application example for the NucleoL152.
|
||||
*
|
||||
* \example classA/NucleoL476/main.c
|
||||
* LoRaWAN class A application example for the NucleoL476.
|
||||
*
|
||||
* \example classB/NucleoL476/main.c
|
||||
* LoRaWAN class B application example for the NucleoL476.
|
||||
*
|
||||
* \example classC/NucleoL476/main.c
|
||||
* LoRaWAN class C application example for the NucleoL476.
|
||||
*
|
||||
* \example classA/SAMR34/main.c
|
||||
* LoRaWAN class A application example for the SAMR34.
|
||||
*
|
||||
* \example classB/SAMR34/main.c
|
||||
* LoRaWAN class B application example for the SAMR34.
|
||||
*
|
||||
* \example classC/SAMR34/main.c
|
||||
* LoRaWAN class C application example for the SAMR34.
|
||||
*
|
||||
* \example classA/SKiM880B/main.c
|
||||
* LoRaWAN class A application example for the SKiM880B.
|
||||
*
|
||||
* \example classB/SKiM880B/main.c
|
||||
* LoRaWAN class B application example for the SKiM880B.
|
||||
*
|
||||
* \example classC/SKiM880B/main.c
|
||||
* LoRaWAN class C application example for the SKiM880B.
|
||||
*
|
||||
* \example classA/SKiM881AXL/main.c
|
||||
* LoRaWAN class A application example for the SKiM881AXL.
|
||||
*
|
||||
* \example classB/SKiM881AXL/main.c
|
||||
* LoRaWAN class B application example for the SKiM881AXL.
|
||||
*
|
||||
* \example classC/SKiM881AXL/main.c
|
||||
* LoRaWAN class C application example for the SKiM881AXL.
|
||||
*
|
||||
* \example classA/SKiM980A/main.c
|
||||
* LoRaWAN class A application example for the SKiM980A.
|
||||
*
|
||||
* \example classB/SKiM980A/main.c
|
||||
* LoRaWAN class B application example for the SKiM980A.
|
||||
*
|
||||
* \example classC/SKiM980A/main.c
|
||||
* LoRaWAN class C application example for the SKiM980A.
|
||||
*
|
||||
*/
|
||||
#ifndef __LORAMAC_H__
|
||||
#define __LORAMAC_H__
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include "utilities.h"
|
||||
@@ -90,24 +149,11 @@
|
||||
*/
|
||||
#define DOWN_LINK 1
|
||||
|
||||
/*!
|
||||
* Sets the length of the LoRaMAC footer field.
|
||||
* Mainly indicates the MIC field length
|
||||
*/
|
||||
#define LORAMAC_MFR_LEN 4
|
||||
|
||||
/*!
|
||||
* LoRaMac MLME-Confirm queue length
|
||||
*/
|
||||
#define LORA_MAC_MLME_CONFIRM_QUEUE_LEN 5
|
||||
|
||||
/*!
|
||||
* FRMPayload overhead to be used when setting the Radio.SetMaxPayloadLength
|
||||
* in RxWindowSetup function.
|
||||
* Maximum PHYPayload = MaxPayloadOfDatarate/MaxPayloadOfDatarateRepeater + LORA_MAC_FRMPAYLOAD_OVERHEAD
|
||||
*/
|
||||
#define LORA_MAC_FRMPAYLOAD_OVERHEAD 13 // MHDR(1) + FHDR(7) + Port(1) + MIC(4)
|
||||
|
||||
/*!
|
||||
* Maximum number of multicast context
|
||||
*/
|
||||
@@ -116,34 +162,7 @@
|
||||
/*!
|
||||
* Start value for multicast keys enumeration
|
||||
*/
|
||||
#define LORAMAC_CRYPTO_MULITCAST_KEYS 127
|
||||
|
||||
/*!
|
||||
* LoRaWAN devices classes definition
|
||||
*
|
||||
* LoRaWAN Specification V1.0.2, chapter 2.1
|
||||
*/
|
||||
typedef enum eDeviceClass
|
||||
{
|
||||
/*!
|
||||
* LoRaWAN device class A
|
||||
*
|
||||
* LoRaWAN Specification V1.0.2, chapter 3
|
||||
*/
|
||||
CLASS_A = 0x00,
|
||||
/*!
|
||||
* LoRaWAN device class B
|
||||
*
|
||||
* LoRaWAN Specification V1.0.2, chapter 8
|
||||
*/
|
||||
CLASS_B = 0x01,
|
||||
/*!
|
||||
* LoRaWAN device class C
|
||||
*
|
||||
* LoRaWAN Specification V1.0.2, chapter 17
|
||||
*/
|
||||
CLASS_C = 0x02,
|
||||
}DeviceClass_t;
|
||||
#define LORAMAC_CRYPTO_MULTICAST_KEYS 127
|
||||
|
||||
/*!
|
||||
* End-Device activation type
|
||||
@@ -164,7 +183,6 @@ typedef enum eActivationType
|
||||
ACTIVATION_TYPE_OTAA = 2,
|
||||
}ActivationType_t;
|
||||
|
||||
|
||||
/*!
|
||||
* LoRaMAC channels parameters definition
|
||||
*/
|
||||
@@ -222,9 +240,9 @@ typedef struct sChannelParams
|
||||
}ChannelParams_t;
|
||||
|
||||
/*!
|
||||
* LoRaMAC receive window 2 channel parameters
|
||||
* LoRaMAC receive window channel parameters
|
||||
*/
|
||||
typedef struct sRx2ChannelParams
|
||||
typedef struct sRxChannelParams
|
||||
{
|
||||
/*!
|
||||
* Frequency in Hz
|
||||
@@ -238,7 +256,7 @@ typedef struct sRx2ChannelParams
|
||||
* The allowed ranges are region specific. Please refer to \ref DR_0 to \ref DR_15 for details.
|
||||
*/
|
||||
uint8_t Datarate;
|
||||
}Rx2ChannelParams_t;
|
||||
}RxChannelParams_t;
|
||||
|
||||
/*!
|
||||
* LoRaMAC receive window enumeration
|
||||
@@ -257,14 +275,22 @@ typedef enum eLoRaMacRxSlot
|
||||
* LoRaMAC receive window 2 for class c - continuous listening
|
||||
*/
|
||||
RX_SLOT_WIN_CLASS_C,
|
||||
/*!
|
||||
* LoRaMAC class c multicast downlink
|
||||
*/
|
||||
RX_SLOT_WIN_CLASS_C_MULTICAST,
|
||||
/*!
|
||||
* LoRaMAC class b ping slot window
|
||||
*/
|
||||
RX_SLOT_WIN_PING_SLOT,
|
||||
RX_SLOT_WIN_CLASS_B_PING_SLOT,
|
||||
/*!
|
||||
* LoRaMAC class b multicast slot window
|
||||
*/
|
||||
RX_SLOT_WIN_MULTICAST_SLOT,
|
||||
RX_SLOT_WIN_CLASS_B_MULTICAST_SLOT,
|
||||
/*!
|
||||
* LoRaMAC no active receive window
|
||||
*/
|
||||
RX_SLOT_NONE,
|
||||
}LoRaMacRxSlot_t;
|
||||
|
||||
/*!
|
||||
@@ -328,14 +354,6 @@ typedef struct sLoRaMacCtxs
|
||||
* \brief Size of MLME Confirm queue module context
|
||||
*/
|
||||
size_t ConfirmQueueNvmCtxSize;
|
||||
/*!
|
||||
* \brief Pointer to FCnt handler module context
|
||||
*/
|
||||
void* FCntHandlerNvmCtx;
|
||||
/*!
|
||||
* \brief Size of FCnt handler module context
|
||||
*/
|
||||
size_t FCntHandlerNvmCtxSize;
|
||||
}LoRaMacCtxs_t;
|
||||
|
||||
/*!
|
||||
@@ -393,7 +411,11 @@ typedef struct sLoRaMacParams
|
||||
/*!
|
||||
* LoRaMAC 2nd reception window settings
|
||||
*/
|
||||
Rx2ChannelParams_t Rx2Channel;
|
||||
RxChannelParams_t Rx2Channel;
|
||||
/*!
|
||||
* LoRaMAC continuous reception window settings
|
||||
*/
|
||||
RxChannelParams_t RxCChannel;
|
||||
/*!
|
||||
* Uplink dwell time configuration. 0: No limit, 1: 400ms
|
||||
*/
|
||||
@@ -410,44 +432,8 @@ typedef struct sLoRaMacParams
|
||||
* Antenna gain of the node
|
||||
*/
|
||||
float AntennaGain;
|
||||
/*!
|
||||
* Indicates if the node supports repeaters
|
||||
*/
|
||||
bool RepeaterSupport;
|
||||
}LoRaMacParams_t;
|
||||
|
||||
/*!
|
||||
* Multicast channel
|
||||
*/
|
||||
typedef struct sMulticastChannel
|
||||
{
|
||||
/*
|
||||
* Address identifier
|
||||
*/
|
||||
AddressIdentifier_t AddrID;
|
||||
/*!
|
||||
* Address
|
||||
*/
|
||||
uint32_t Address;
|
||||
/*!
|
||||
* True if the entry is active
|
||||
*/
|
||||
bool IsEnabled;
|
||||
/*!
|
||||
* Reception frequency of the ping slot windows
|
||||
*/
|
||||
uint32_t Frequency;
|
||||
/*!
|
||||
* Datarate of the ping slot
|
||||
*/
|
||||
int8_t Datarate;
|
||||
/*!
|
||||
* This parameter is necessary for class b operation. It defines the
|
||||
* periodicity of the multicast downlink slots
|
||||
*/
|
||||
uint16_t Periodicity;
|
||||
}MulticastChannel_t;
|
||||
|
||||
/*!
|
||||
* LoRaMAC data structure for a PingSlotInfoReq \ref MLME_PING_SLOT_INFO
|
||||
*
|
||||
@@ -487,7 +473,7 @@ typedef struct sBeaconInfo
|
||||
* Timestamp in seconds since 00:00:00, Sunday 6th of January 1980
|
||||
* (start of the GPS epoch) modulo 2^32
|
||||
*/
|
||||
uint32_t Time;
|
||||
SysTime_t Time;
|
||||
/*!
|
||||
* Frequency
|
||||
*/
|
||||
@@ -616,23 +602,27 @@ typedef union eLoRaMacFlags_t
|
||||
/*!
|
||||
* MCPS-Req pending
|
||||
*/
|
||||
uint8_t McpsReq : 1;
|
||||
uint8_t McpsReq : 1;
|
||||
/*!
|
||||
* MCPS-Ind pending
|
||||
*/
|
||||
uint8_t McpsInd : 1;
|
||||
uint8_t McpsInd : 1;
|
||||
/*!
|
||||
* MLME-Req pending
|
||||
*/
|
||||
uint8_t MlmeReq : 1;
|
||||
uint8_t MlmeReq : 1;
|
||||
/*!
|
||||
* MLME-Ind pending
|
||||
*/
|
||||
uint8_t MlmeInd : 1;
|
||||
uint8_t MlmeInd : 1;
|
||||
/*!
|
||||
* MLME-Ind to schedule an uplink pending
|
||||
*/
|
||||
uint8_t MlmeSchedUplinkInd : 1;
|
||||
/*!
|
||||
* MAC cycle done
|
||||
*/
|
||||
uint8_t MacDone : 1;
|
||||
uint8_t MacDone : 1;
|
||||
}Bits;
|
||||
}LoRaMacFlags_t;
|
||||
|
||||
@@ -679,6 +669,19 @@ typedef enum eMcps
|
||||
MCPS_PROPRIETARY,
|
||||
}Mcps_t;
|
||||
|
||||
/*!
|
||||
* Structure which defines return parameters for requests.
|
||||
*/
|
||||
typedef struct sRequestReturnParam
|
||||
{
|
||||
/*!
|
||||
* This value reports the time in milliseconds which
|
||||
* an application must wait before its possible to send
|
||||
* the next uplink.
|
||||
*/
|
||||
TimerTime_t DutyCycleWaitTime;
|
||||
}RequestReturnParam_t;
|
||||
|
||||
/*!
|
||||
* LoRaMAC MCPS-Request for an unconfirmed frame
|
||||
*/
|
||||
@@ -799,6 +802,11 @@ typedef struct sMcpsReq
|
||||
*/
|
||||
McpsReqProprietary_t Proprietary;
|
||||
}Req;
|
||||
|
||||
/*!
|
||||
* MCPS-Request return parameters
|
||||
*/
|
||||
RequestReturnParam_t ReqReturn;
|
||||
}McpsReq_t;
|
||||
|
||||
/*!
|
||||
@@ -909,6 +917,10 @@ typedef struct sMcpsIndication
|
||||
* The device address of the frame
|
||||
*/
|
||||
uint32_t DevAddress;
|
||||
/*!
|
||||
* Set if a DeviceTimeAns MAC command was received.
|
||||
*/
|
||||
bool DeviceTimeAnsReceived;
|
||||
}McpsIndication_t;
|
||||
|
||||
/*!
|
||||
@@ -937,6 +949,10 @@ typedef struct sMcpsIndication
|
||||
*/
|
||||
typedef enum eMlme
|
||||
{
|
||||
/*!
|
||||
* An unknown MLME service
|
||||
*/
|
||||
MLME_UNKNOWN,
|
||||
/*!
|
||||
* Initiates the Over-the-Air activation
|
||||
*
|
||||
@@ -1033,18 +1049,6 @@ typedef enum eMlme
|
||||
*/
|
||||
typedef struct sMlmeReqJoin
|
||||
{
|
||||
/*!
|
||||
* Globally unique end-device identifier
|
||||
*
|
||||
* LoRaWAN Specification V1.1.0, chapter 6.1.1.2
|
||||
*/
|
||||
uint8_t* DevEui;
|
||||
/*!
|
||||
* Join Sever identifier
|
||||
*
|
||||
* LoRaWAN Specification V1.1.0, chapter 6.1.1.1
|
||||
*/
|
||||
uint8_t* JoinEui;
|
||||
/*!
|
||||
* Datarate used for join request.
|
||||
*/
|
||||
@@ -1105,7 +1109,7 @@ typedef struct sMlmeReqDeriveMcSessionKeyPair
|
||||
/*!
|
||||
* Address identifier to select the multicast group
|
||||
*/
|
||||
AddressIdentifier_t AddrID;
|
||||
AddressIdentifier_t GroupID;
|
||||
}MlmeReqDeriveMcSessionKeyPair_t;
|
||||
|
||||
/*!
|
||||
@@ -1144,6 +1148,11 @@ typedef struct sMlmeReq
|
||||
*/
|
||||
MlmeReqDeriveMcSessionKeyPair_t DeriveMcSessionKeyPair;
|
||||
}Req;
|
||||
|
||||
/*!
|
||||
* MLME-Request return parameters
|
||||
*/
|
||||
RequestReturnParam_t ReqReturn;
|
||||
}MlmeReq_t;
|
||||
|
||||
/*!
|
||||
@@ -1216,6 +1225,9 @@ typedef struct sMlmeIndication
|
||||
* ----------------------------------------------| :-: | :-:
|
||||
* \ref MIB_DEVICE_CLASS | YES | YES
|
||||
* \ref MIB_NETWORK_ACTIVATION | YES | YES
|
||||
* \ref MIB_DEV_EUI | YES | YES
|
||||
* \ref MIB_JOIN_EUI | YES | YES
|
||||
* \ref MIB_SE_PIN | YES | YES
|
||||
* \ref MIB_ADR | YES | YES
|
||||
* \ref MIB_NET_ID | YES | YES
|
||||
* \ref MIB_DEV_ADDR | YES | YES
|
||||
@@ -1241,9 +1253,11 @@ typedef struct sMlmeIndication
|
||||
* \ref MIB_MC_APP_S_KEY_3 | NO | YES
|
||||
* \ref MIB_MC_NWK_S_KEY_3 | NO | YES
|
||||
* \ref MIB_PUBLIC_NETWORK | YES | YES
|
||||
* \ref MIB_REPEATER_SUPPORT | YES | YES
|
||||
* \ref MIB_CHANNELS | YES | NO
|
||||
* \ref MIB_RX2_CHANNEL | YES | YES
|
||||
* \ref MIB_RX2_DFAULT_CHANNEL | YES | YES
|
||||
* \ref MIB_RXC_CHANNEL | YES | YES
|
||||
* \ref MIB_RXC_DFAULT_CHANNEL | YES | YES
|
||||
* \ref MIB_CHANNELS_MASK | YES | YES
|
||||
* \ref MIB_CHANNELS_DEFAULT_MASK | YES | YES
|
||||
* \ref MIB_CHANNELS_NB_TRANS | YES | YES
|
||||
@@ -1273,7 +1287,8 @@ typedef struct sMlmeIndication
|
||||
* \ref MIB_ANTENNA_GAIN | YES | YES
|
||||
* \ref MIB_DEFAULT_ANTENNA_GAIN | YES | YES
|
||||
* \ref MIB_NVM_CTXS | YES | YES
|
||||
* \ref MIB_ABP_LORAWAN_VERSION | YES | YES
|
||||
* \ref MIB_ABP_LORAWAN_VERSION | NO | YES
|
||||
* \ref MIB_LORAWAN_VERSION | YES | NO
|
||||
*
|
||||
* The following table provides links to the function implementations of the
|
||||
* related MIB primitives:
|
||||
@@ -1297,6 +1312,22 @@ typedef enum eMib
|
||||
* LoRaWAN Specification V1.0.2
|
||||
*/
|
||||
MIB_NETWORK_ACTIVATION,
|
||||
/*!
|
||||
* LoRaWAN device EUI
|
||||
*
|
||||
* LoRaWAN Specification V1.0.2
|
||||
*/
|
||||
MIB_DEV_EUI,
|
||||
/*!
|
||||
* LoRaWAN join EUI
|
||||
*
|
||||
* LoRaWAN Specification V1.0.2
|
||||
*/
|
||||
MIB_JOIN_EUI,
|
||||
/*!
|
||||
* Secure-element pin
|
||||
*/
|
||||
MIB_SE_PIN,
|
||||
/*!
|
||||
* Adaptive data rate
|
||||
*
|
||||
@@ -1451,14 +1482,6 @@ typedef enum eMib
|
||||
* [true: public network, false: private network]
|
||||
*/
|
||||
MIB_PUBLIC_NETWORK,
|
||||
/*!
|
||||
* Support the operation with repeaters
|
||||
*
|
||||
* LoRaWAN Regional Parameters V1.0.2rB
|
||||
*
|
||||
* [true: repeater support enabled, false: repeater support disabled]
|
||||
*/
|
||||
MIB_REPEATER_SUPPORT,
|
||||
/*!
|
||||
* Communication channels. A get request will return a
|
||||
* pointer which references the first entry of the channel list. The
|
||||
@@ -1479,6 +1502,18 @@ typedef enum eMib
|
||||
* LoRaWAN Specification V1.0.2, chapter 3.3.2
|
||||
*/
|
||||
MIB_RX2_DEFAULT_CHANNEL,
|
||||
/*!
|
||||
* Set receive window C channel
|
||||
*
|
||||
* LoRaWAN Specification V1.0.2, chapter 3.3.1
|
||||
*/
|
||||
MIB_RXC_CHANNEL,
|
||||
/*!
|
||||
* Set receive window C channel
|
||||
*
|
||||
* LoRaWAN Specification V1.0.2, chapter 3.3.2
|
||||
*/
|
||||
MIB_RXC_DEFAULT_CHANNEL,
|
||||
/*!
|
||||
* LoRaWAN channels mask
|
||||
*
|
||||
@@ -1575,7 +1610,7 @@ typedef enum eMib
|
||||
* The antenna gain is used to calculate the TX power of the node.
|
||||
* The formula is:
|
||||
* radioTxPower = ( int8_t )floor( maxEirp - antennaGain )
|
||||
*
|
||||
*
|
||||
* \remark The antenna gain value is referenced to the isotropic antenna.
|
||||
* The value is in dBi.
|
||||
* MIB_ANTENNA_GAIN[dBi] = measuredAntennaGain[dBd] + 2.15
|
||||
@@ -1586,7 +1621,7 @@ typedef enum eMib
|
||||
* The antenna gain is used to calculate the TX power of the node.
|
||||
* The formula is:
|
||||
* radioTxPower = ( int8_t )floor( maxEirp - antennaGain )
|
||||
*
|
||||
*
|
||||
* \remark The antenna gain value is referenced to the isotropic antenna.
|
||||
* The value is in dBi.
|
||||
* MIB_DEFAULT_ANTENNA_GAIN[dBi] = measuredAntennaGain[dBd] + 2.15
|
||||
@@ -1600,6 +1635,10 @@ typedef enum eMib
|
||||
* LoRaWAN MAC layer operating version when activated by ABP.
|
||||
*/
|
||||
MIB_ABP_LORAWAN_VERSION,
|
||||
/*!
|
||||
* LoRaWAN MAC and regional parameter version.
|
||||
*/
|
||||
MIB_LORAWAN_VERSION,
|
||||
/*!
|
||||
* Beacon interval in ms
|
||||
*/
|
||||
@@ -1677,6 +1716,24 @@ typedef union uMibParam
|
||||
* Related MIB type: \ref MIB_NETWORK_ACTIVATION
|
||||
*/
|
||||
ActivationType_t NetworkActivation;
|
||||
/*!
|
||||
* LoRaWAN device EUI
|
||||
*
|
||||
* Related MIB type: \ref MIB_DEV_EUI
|
||||
*/
|
||||
uint8_t* DevEui;
|
||||
/*!
|
||||
* LoRaWAN Join server EUI
|
||||
*
|
||||
* Related MIB type: \ref MIB_JOIN_EUI
|
||||
*/
|
||||
uint8_t* JoinEui;
|
||||
/*!
|
||||
* Secure-element pin
|
||||
*
|
||||
* Related MIB type: \ref MIB_SE_PIN
|
||||
*/
|
||||
uint8_t* SePin;
|
||||
/*!
|
||||
* Activation state of ADR
|
||||
*
|
||||
@@ -1827,12 +1884,6 @@ typedef union uMibParam
|
||||
* Related MIB type: \ref MIB_PUBLIC_NETWORK
|
||||
*/
|
||||
bool EnablePublicNetwork;
|
||||
/*!
|
||||
* Enable or disable repeater support
|
||||
*
|
||||
* Related MIB type: \ref MIB_REPEATER_SUPPORT
|
||||
*/
|
||||
bool EnableRepeaterSupport;
|
||||
/*!
|
||||
* LoRaWAN Channel
|
||||
*
|
||||
@@ -1844,13 +1895,25 @@ typedef union uMibParam
|
||||
*
|
||||
* Related MIB type: \ref MIB_RX2_CHANNEL
|
||||
*/
|
||||
Rx2ChannelParams_t Rx2Channel;
|
||||
RxChannelParams_t Rx2Channel;
|
||||
/*!
|
||||
* Channel for the receive window 2
|
||||
*
|
||||
* Related MIB type: \ref MIB_RX2_DEFAULT_CHANNEL
|
||||
*/
|
||||
Rx2ChannelParams_t Rx2DefaultChannel;
|
||||
RxChannelParams_t Rx2DefaultChannel;
|
||||
/*!
|
||||
* Channel for the receive window C
|
||||
*
|
||||
* Related MIB type: \ref MIB_RXC_CHANNEL
|
||||
*/
|
||||
RxChannelParams_t RxCChannel;
|
||||
/*!
|
||||
* Channel for the receive window C
|
||||
*
|
||||
* Related MIB type: \ref MIB_RXC_DEFAULT_CHANNEL
|
||||
*/
|
||||
RxChannelParams_t RxCDefaultChannel;
|
||||
/*!
|
||||
* Channel mask
|
||||
*
|
||||
@@ -1928,7 +1991,7 @@ typedef union uMibParam
|
||||
*
|
||||
* Related MIB type: \ref MIB_MULTICAST_CHANNEL
|
||||
*/
|
||||
MulticastChannel_t MulticastChannel;
|
||||
McChannelParams_t MulticastChannel;
|
||||
/*!
|
||||
* System overall timing error in milliseconds.
|
||||
*
|
||||
@@ -1965,6 +2028,16 @@ typedef union uMibParam
|
||||
* Related MIB type: \ref MIB_ABP_LORAWAN_VERSION
|
||||
*/
|
||||
Version_t AbpLrWanVersion;
|
||||
/*
|
||||
* LoRaWAN MAC regional parameter version.
|
||||
*
|
||||
* Related MIB type: \ref MIB_LORAWAN_VERSION
|
||||
*/
|
||||
struct sLrWanVersion
|
||||
{
|
||||
Version_t LoRaWan;
|
||||
Version_t LoRaWanRegion;
|
||||
}LrWanVersion;
|
||||
/*!
|
||||
* Beacon interval in ms
|
||||
*
|
||||
@@ -2131,7 +2204,17 @@ typedef enum eLoRaMacStatus
|
||||
*/
|
||||
LORAMAC_STATUS_SKIPPED_APP_DATA,
|
||||
/*!
|
||||
* ToDo
|
||||
* An MCPS or MLME request can return this status. In this case,
|
||||
* the MAC cannot send the frame, as the duty cycle limits all
|
||||
* available bands. When a request returns this value, the
|
||||
* variable "DutyCycleWaitTime" in "ReqReturn" of the input
|
||||
* parameters contains the remaining time to wait. If the
|
||||
* value is constant and does not change, the expected time
|
||||
* on air for this frame is exceeding the maximum permitted
|
||||
* time according to the duty cycle time period, defined
|
||||
* in Region.h, DUTY_CYCLE_TIME_PERIOD. By default this time
|
||||
* is 1 hour, and a band with 1% duty cycle is then allowed
|
||||
* to use an air time of 36 seconds.
|
||||
*/
|
||||
LORAMAC_STATUS_DUTYCYCLE_RESTRICTED,
|
||||
/*!
|
||||
@@ -2175,7 +2258,11 @@ typedef enum eLoRaMacStatus
|
||||
*/
|
||||
LORAMAC_STATUS_CONFIRM_QUEUE_ERROR,
|
||||
/*!
|
||||
* Undefined error occured
|
||||
* The multicast group doesn't exist
|
||||
*/
|
||||
LORAMAC_STATUS_MC_GROUP_UNDEFINED,
|
||||
/*!
|
||||
* Undefined error occurred
|
||||
*/
|
||||
LORAMAC_STATUS_ERROR
|
||||
}LoRaMacStatus_t;
|
||||
@@ -2260,10 +2347,6 @@ typedef enum LoRaMacNvmCtxModule_e
|
||||
* Context for the confirm queue
|
||||
*/
|
||||
LORAMAC_NVMCTXMODULE_CONFIRM_QUEUE,
|
||||
/*!
|
||||
* Context for the frame count handler
|
||||
*/
|
||||
LORAMAC_NVMCTXMODULE_FCNT_HANDLER
|
||||
}LoRaMacNvmCtxModule_t;
|
||||
|
||||
|
||||
@@ -2328,7 +2411,7 @@ typedef struct sLoRaMacCallback
|
||||
/*!
|
||||
*\brief Will be called each time a Radio IRQ is handled by the MAC
|
||||
* layer.
|
||||
*
|
||||
*
|
||||
*\warning Runs in a IRQ context. Should only change variables state.
|
||||
*/
|
||||
void ( *MacProcessNotify )( void );
|
||||
@@ -2382,6 +2465,13 @@ LoRaMacStatus_t LoRaMacStart( void );
|
||||
*/
|
||||
LoRaMacStatus_t LoRaMacStop( void );
|
||||
|
||||
/*!
|
||||
* \brief Returns a value indicating if the MAC layer is busy or not.
|
||||
*
|
||||
* \retval isBusy Mac layer is busy.
|
||||
*/
|
||||
bool LoRaMacIsBusy( void );
|
||||
|
||||
/*!
|
||||
* Processes the LoRaMac events.
|
||||
*
|
||||
@@ -2449,18 +2539,60 @@ LoRaMacStatus_t LoRaMacChannelAdd( uint8_t id, ChannelParams_t params );
|
||||
LoRaMacStatus_t LoRaMacChannelRemove( uint8_t id );
|
||||
|
||||
/*!
|
||||
* \brief LoRaMAC multicast channel setting service
|
||||
* \brief LoRaMAC multicast channel setup service
|
||||
*
|
||||
* \details Sets a multicast channel.
|
||||
* \details Sets up a multicast channel.
|
||||
*
|
||||
* \param [IN] channel - Multicast channel to set.
|
||||
*
|
||||
* \retval LoRaMacStatus_t Status of the operation. Possible returns are:
|
||||
* \ref LORAMAC_STATUS_OK,
|
||||
* \ref LORAMAC_STATUS_BUSY,
|
||||
* \ref LORAMAC_STATUS_PARAMETER_INVALID.
|
||||
* \ref LORAMAC_STATUS_PARAMETER_INVALID,
|
||||
* \ref LORAMAC_STATUS_MC_GROUP_UNDEFINED.
|
||||
*/
|
||||
LoRaMacStatus_t LoRaMacMulticastChannelSet( MulticastChannel_t channel );
|
||||
LoRaMacStatus_t LoRaMacMcChannelSetup( McChannelParams_t *channel );
|
||||
|
||||
/*!
|
||||
* \brief LoRaMAC multicast channel removal service
|
||||
*
|
||||
* \details Removes/Disables a multicast channel.
|
||||
*
|
||||
* \param [IN] groupID - Multicast channel ID to be removed/disabled
|
||||
*
|
||||
* \retval LoRaMacStatus_t Status of the operation. Possible returns are:
|
||||
* \ref LORAMAC_STATUS_OK,
|
||||
* \ref LORAMAC_STATUS_BUSY,
|
||||
* \ref LORAMAC_STATUS_MC_GROUP_UNDEFINED.
|
||||
*/
|
||||
LoRaMacStatus_t LoRaMacMcChannelDelete( AddressIdentifier_t groupID );
|
||||
|
||||
/*!
|
||||
* \brief LoRaMAC multicast channel get groupId from MC address.
|
||||
*
|
||||
* \param [IN] mcAddress - Multicast address to be checked
|
||||
*
|
||||
* \retval groupID Multicast channel ID associated to the address.
|
||||
* Returns 0xFF if the address isn't found.
|
||||
*/
|
||||
uint8_t LoRaMacMcChannelGetGroupId( uint32_t mcAddress );
|
||||
|
||||
/*!
|
||||
* \brief LoRaMAC multicast channel Rx parameters setup service
|
||||
*
|
||||
* \details Sets up a multicast channel reception parameters.
|
||||
*
|
||||
* \param [IN] groupID - Multicast channel ID
|
||||
* \param [IN] rxParams - Reception parameters
|
||||
* \param [OUT] status - Status mask [UNDEF_ID | FREQ_ERR | DR_ERR | GROUP_ID]
|
||||
*
|
||||
* \retval LoRaMacStatus_t Status of the operation. Possible returns are:
|
||||
* \ref LORAMAC_STATUS_OK,
|
||||
* \ref LORAMAC_STATUS_BUSY,
|
||||
* \ref LORAMAC_STATUS_PARAMETER_INVALID,
|
||||
* \ref LORAMAC_STATUS_MC_GROUP_UNDEFINED.
|
||||
*/
|
||||
LoRaMacStatus_t LoRaMacMcChannelSetupRxParams( AddressIdentifier_t groupID, McRxParams_t *rxParams, uint8_t *status );
|
||||
|
||||
/*!
|
||||
* \brief LoRaMAC MIB-Get
|
||||
@@ -2526,32 +2658,15 @@ LoRaMacStatus_t LoRaMacMibSetRequestConfirm( MibRequestConfirm_t* mibSet );
|
||||
*
|
||||
* \details The Mac layer management entity handles management services. The
|
||||
* following code-snippet shows how to use the API to perform a
|
||||
* network join request.
|
||||
* network join request. Please note that for a join request, the
|
||||
* DevEUI and the JoinEUI must be set previously via the MIB. Please
|
||||
* also refer to the sample implementations.
|
||||
*
|
||||
* \code
|
||||
* static uint8_t DevEui[] =
|
||||
* {
|
||||
* 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
|
||||
* };
|
||||
* static uint8_t JoinEui[] =
|
||||
* {
|
||||
* 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
|
||||
* };
|
||||
* static uint8_t NwkKey[] =
|
||||
* {
|
||||
* 0x2B, 0x7E, 0x15, 0x16, 0x28, 0xAE, 0xD2, 0xA6,
|
||||
* 0xAB, 0xF7, 0x15, 0x88, 0x09, 0xCF, 0x4F, 0x3C
|
||||
* };
|
||||
* static uint8_t AppKey[] =
|
||||
* {
|
||||
* 0x2B, 0x7E, 0x15, 0x16, 0x28, 0xAE, 0xD2, 0xA6,
|
||||
* 0xAB, 0xF7, 0x15, 0x88, 0x09, 0xCF, 0x4F, 0x3C
|
||||
* };
|
||||
*
|
||||
* MlmeReq_t mlmeReq;
|
||||
* mlmeReq.Type = MLME_JOIN;
|
||||
* mlmeReq.Req.Join.DevEui = DevEui;
|
||||
* mlmeReq.Req.Join.JoinEui = JoinEui;
|
||||
* mlmeReq.Req.Join.Datarate = LORAWAN_DEFAULT_DATARATE;
|
||||
*
|
||||
* if( LoRaMacMlmeRequest( &mlmeReq ) == LORAMAC_STATUS_OK )
|
||||
* {
|
||||
@@ -2605,6 +2720,18 @@ LoRaMacStatus_t LoRaMacMlmeRequest( MlmeReq_t* mlmeRequest );
|
||||
*/
|
||||
LoRaMacStatus_t LoRaMacMcpsRequest( McpsReq_t* mcpsRequest );
|
||||
|
||||
/*!
|
||||
* \brief LoRaMAC deinitialization
|
||||
*
|
||||
* \details This function stops the timers, re-initializes MAC & regional parameters to default
|
||||
* and sets radio into sleep state.
|
||||
*
|
||||
* \retval LoRaMacStatus_t Status of the operation. Possible returns are:
|
||||
* \ref LORAMAC_STATUS_OK,
|
||||
* \ref LORAMAC_STATUS_BUSY
|
||||
*/
|
||||
LoRaMacStatus_t LoRaMacDeInitialization( void );
|
||||
|
||||
/*!
|
||||
* Automatically add the Region.h file at the end of LoRaMac.h file.
|
||||
* This is required because Region.h uses definitions from LoRaMac.h
|
||||
@@ -2613,4 +2740,8 @@ LoRaMacStatus_t LoRaMacMcpsRequest( McpsReq_t* mcpsRequest );
|
||||
|
||||
/*! \} defgroup LORAMAC */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // __LORAMAC_H__
|
||||
|
@@ -65,10 +65,6 @@ static bool CalcNextV10X( CalcNextAdrParams_t* adrNext, int8_t* drOut, int8_t* t
|
||||
if( adrNext->AdrAckCounter >= adrNext->AdrAckLimit )
|
||||
{
|
||||
adrAckReq = true;
|
||||
// Set TX Power to maximum
|
||||
getPhy.Attribute = PHY_MAX_TX_POWER;
|
||||
phyParam = RegionGetPhyParam( adrNext->Region, &getPhy );
|
||||
txPower = phyParam.Value;
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -76,6 +72,11 @@ static bool CalcNextV10X( CalcNextAdrParams_t* adrNext, int8_t* drOut, int8_t* t
|
||||
}
|
||||
if( adrNext->AdrAckCounter >= ( adrNext->AdrAckLimit + adrNext->AdrAckDelay ) )
|
||||
{
|
||||
// Set TX Power to maximum
|
||||
getPhy.Attribute = PHY_MAX_TX_POWER;
|
||||
phyParam = RegionGetPhyParam( adrNext->Region, &getPhy );
|
||||
txPower = phyParam.Value;
|
||||
|
||||
if( ( adrNext->AdrAckCounter % adrNext->AdrAckDelay ) == 1 )
|
||||
{
|
||||
// Decrease the datarate
|
||||
|
@@ -37,6 +37,11 @@
|
||||
#ifndef __LORAMACADR_H__
|
||||
#define __LORAMACADR_H__
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
/*! \} defgroup LORAMACADR */
|
||||
|
||||
/*
|
||||
@@ -101,4 +106,8 @@ typedef struct sCalcNextAdrParams
|
||||
*/
|
||||
bool LoRaMacAdrCalcNext( CalcNextAdrParams_t* adrNext, int8_t* drOut, int8_t* txPowOut, uint32_t* adrAckCounter );
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // __LORAMACADR_H__
|
||||
|
File diff suppressed because it is too large
Load Diff
@@ -37,6 +37,11 @@
|
||||
#ifndef __LORAMACCLASSB_H__
|
||||
#define __LORAMACCLASSB_H__
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
#include "systime.h"
|
||||
#include "LoRaMacTypes.h"
|
||||
|
||||
@@ -121,42 +126,15 @@ typedef enum ePingSlotState
|
||||
*/
|
||||
typedef struct sPingSlotContext
|
||||
{
|
||||
struct sPingSlotCtrl
|
||||
{
|
||||
/*!
|
||||
* Set when the server assigned a ping slot to the node
|
||||
*/
|
||||
uint8_t Assigned : 1;
|
||||
/*!
|
||||
* Set when a custom frequency is used
|
||||
*/
|
||||
uint8_t CustomFreq : 1;
|
||||
}Ctrl;
|
||||
|
||||
/*!
|
||||
* Ping slot length time in ms
|
||||
*/
|
||||
uint32_t PingSlotWindow;
|
||||
/*!
|
||||
* Number of ping slots
|
||||
*/
|
||||
uint8_t PingNb;
|
||||
/*!
|
||||
* Period of the ping slots
|
||||
*/
|
||||
uint16_t PingPeriod;
|
||||
/*!
|
||||
* Ping offset
|
||||
*/
|
||||
uint16_t PingOffset;
|
||||
/*!
|
||||
* Reception frequency of the ping slot windows
|
||||
*/
|
||||
uint32_t Frequency;
|
||||
/*!
|
||||
* Datarate of the ping slot
|
||||
*/
|
||||
int8_t Datarate;
|
||||
/*!
|
||||
* Current symbol timeout. The node enlarges this variable in case of beacon
|
||||
* loss.
|
||||
@@ -184,10 +162,6 @@ typedef struct sBeaconContext
|
||||
* Set if the node has acquired the beacon
|
||||
*/
|
||||
uint8_t BeaconAcquired : 1;
|
||||
/*!
|
||||
* Set if the node has a custom frequency for beaconing and ping slots
|
||||
*/
|
||||
uint8_t CustomFreq : 1;
|
||||
/*!
|
||||
* Set if a beacon delay was set for the beacon acquisition
|
||||
*/
|
||||
@@ -205,10 +179,7 @@ typedef struct sBeaconContext
|
||||
*/
|
||||
uint8_t ResumeBeaconing : 1;
|
||||
}Ctrl;
|
||||
/*!
|
||||
* Beacon reception frequency
|
||||
*/
|
||||
uint32_t Frequency;
|
||||
|
||||
/*!
|
||||
* Current temperature
|
||||
*/
|
||||
@@ -216,15 +187,15 @@ typedef struct sBeaconContext
|
||||
/*!
|
||||
* Beacon time received with the beacon frame
|
||||
*/
|
||||
TimerTime_t BeaconTime;
|
||||
SysTime_t BeaconTime;
|
||||
/*!
|
||||
* Time when the last beacon was received
|
||||
*/
|
||||
TimerTime_t LastBeaconRx;
|
||||
SysTime_t LastBeaconRx;
|
||||
/*!
|
||||
* Time when the next beacon will be received
|
||||
*/
|
||||
TimerTime_t NextBeaconRx;
|
||||
SysTime_t NextBeaconRx;
|
||||
/*!
|
||||
* This is the time where the RX window will be opened.
|
||||
* Its base is NextBeaconRx with temperature compensations
|
||||
@@ -265,7 +236,7 @@ typedef struct sLoRaMacClassBCallback
|
||||
/*!
|
||||
*\brief Will be called each time a Radio IRQ is handled by the MAC
|
||||
* layer.
|
||||
*
|
||||
*
|
||||
*\warning Runs in a IRQ context. Should only change variables state.
|
||||
*/
|
||||
void ( *MacProcessNotify )( void );
|
||||
@@ -314,7 +285,7 @@ typedef struct sLoRaMacClassBParams
|
||||
* Signature of callback function to be called by this module when the
|
||||
* non-volatile needs to be saved.
|
||||
*/
|
||||
typedef void ( *EventNvmCtxChanged )( void );
|
||||
typedef void ( *LoRaMacClassBNvmEvent )( void );
|
||||
|
||||
/*!
|
||||
* \brief Initialize LoRaWAN Class B
|
||||
@@ -323,7 +294,7 @@ typedef void ( *EventNvmCtxChanged )( void );
|
||||
* \param [IN] callbacks Contains the callback which the Class B implementation needs
|
||||
* \param [IN] callback function which will be called when the non-volatile context needs to be saved.
|
||||
*/
|
||||
void LoRaMacClassBInit( LoRaMacClassBParams_t *classBParams, LoRaMacClassBCallback_t *callbacks, EventNvmCtxChanged classBNvmCtxChanged );
|
||||
void LoRaMacClassBInit( LoRaMacClassBParams_t *classBParams, LoRaMacClassBCallback_t *callbacks, LoRaMacClassBNvmEvent classBNvmCtxChanged );
|
||||
|
||||
/*!
|
||||
* Restores the internal non-volatile context from passed pointer.
|
||||
@@ -561,4 +532,8 @@ void LoRaMacClassBSetMulticastPeriodicity( MulticastCtx_t* multicastChannel );
|
||||
|
||||
void LoRaMacClassBProcess( void );
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // __LORAMACCLASSB_H__
|
||||
|
@@ -36,6 +36,11 @@
|
||||
#ifndef __LORAMACCLASSBCONFIG_H__
|
||||
#define __LORAMACCLASSBCONFIG_H__
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
/*!
|
||||
* Defines the beacon interval in ms
|
||||
*/
|
||||
@@ -112,4 +117,8 @@
|
||||
*/
|
||||
#define CLASSB_WINDOW_MOVE_EXPANSION_FACTOR 2
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // __LORAMACCLASSBCONFIG_H__
|
||||
|
@@ -17,27 +17,23 @@ License: Revised BSD License, see LICENSE.TXT file include in the project
|
||||
|
||||
Maintainer: Miguel Luis ( Semtech ), Daniel Jaeckle ( STACKFORCE ), Johannes Bruder ( STACKFORCE )
|
||||
*/
|
||||
#include <stddef.h>
|
||||
|
||||
#include "utilities.h"
|
||||
#include "LoRaMacCommands.h"
|
||||
#include "LoRaMacConfirmQueue.h"
|
||||
|
||||
/*
|
||||
/*!
|
||||
* Number of MAC Command slots
|
||||
*/
|
||||
#define NUM_OF_MAC_COMMANDS 15
|
||||
|
||||
/*
|
||||
/*!
|
||||
* Size of the CID field of MAC commands
|
||||
*/
|
||||
#define CID_FIELD_SIZE 1
|
||||
#define CID_FIELD_SIZE 1
|
||||
|
||||
/*
|
||||
* List of all stick MAC command answers which will be deleted after a receiving downlink
|
||||
*/
|
||||
const uint8_t CIDsStickyAnsCmds[] = { MOTE_MAC_DL_CHANNEL_ANS, MOTE_MAC_RX_PARAM_SETUP_ANS, MOTE_MAC_RX_TIMING_SETUP_ANS };
|
||||
|
||||
/*
|
||||
/*!
|
||||
* Mac Commands list structure
|
||||
*/
|
||||
typedef struct sMacCommandsList
|
||||
@@ -52,7 +48,7 @@ typedef struct sMacCommandsList
|
||||
MacCommand_t* Last;
|
||||
} MacCommandsList_t;
|
||||
|
||||
/*
|
||||
/*!
|
||||
* LoRaMac Commands Context structure
|
||||
*/
|
||||
typedef struct sLoRaMacCommandsCtx
|
||||
@@ -71,27 +67,27 @@ typedef struct sLoRaMacCommandsCtx
|
||||
size_t SerializedCmdsSize;
|
||||
} LoRaMacCommandsCtx_t;
|
||||
|
||||
/*
|
||||
/*!
|
||||
* Callback function to notify the upper layer about context change
|
||||
*/
|
||||
static EventNvmCtxChanged CommandsNvmCtxChanged;
|
||||
static LoRaMacCommandsNvmEvent CommandsNvmCtxChanged;
|
||||
|
||||
/*
|
||||
/*!
|
||||
* Non-volatile module context.
|
||||
*/
|
||||
static LoRaMacCommandsCtx_t NvmCtx;
|
||||
|
||||
/* Memory management functions */
|
||||
|
||||
/*
|
||||
/*!
|
||||
* \brief Determines if a MAC command slot is free
|
||||
*
|
||||
* \param[IN] slot - Slot to check
|
||||
* \retval - Status of the operation
|
||||
*/
|
||||
bool isSlotFree( const MacCommand_t* slot )
|
||||
static bool IsSlotFree( const MacCommand_t* slot )
|
||||
{
|
||||
uint8_t* mem = (uint8_t*) slot;
|
||||
uint8_t* mem = ( uint8_t* )slot;
|
||||
|
||||
for( uint16_t size = 0; size < sizeof( MacCommand_t ); size++ )
|
||||
{
|
||||
@@ -103,114 +99,112 @@ bool isSlotFree( const MacCommand_t* slot )
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
/*!
|
||||
* \brief Allocates a new MAC command memory slot
|
||||
*
|
||||
* \retval - Pointer to slot
|
||||
*/
|
||||
MacCommand_t* mallocNewMacCommandSlot( )
|
||||
static MacCommand_t* MallocNewMacCommandSlot( void )
|
||||
{
|
||||
uint8_t itr = 0;
|
||||
|
||||
while( isSlotFree( ( const MacCommand_t* ) &NvmCtx.MacCommandSlots[itr]) == false )
|
||||
while( IsSlotFree( ( const MacCommand_t* )&NvmCtx.MacCommandSlots[itr] ) == false )
|
||||
{
|
||||
itr++;
|
||||
if( itr == NUM_OF_MAC_COMMANDS )
|
||||
{
|
||||
return 0;
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
return &NvmCtx.MacCommandSlots[itr];
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
/*!
|
||||
* \brief Free memory slot
|
||||
*
|
||||
* \param[IN] slot - Slot to free
|
||||
*
|
||||
* \retval - Status of the operation
|
||||
*/
|
||||
bool freeMacCommandSlot( MacCommand_t* slot )
|
||||
static bool FreeMacCommandSlot( MacCommand_t* slot )
|
||||
{
|
||||
if( slot == 0 )
|
||||
if( slot == NULL )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
memset1( (uint8_t*) slot, 0x00, sizeof( MacCommand_t ));
|
||||
memset1( ( uint8_t* )slot, 0x00, sizeof( MacCommand_t ) );
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/* Linked list functions */
|
||||
|
||||
/*
|
||||
/*!
|
||||
* \brief Initialize list
|
||||
*
|
||||
* \param[IN] list - List that shall be initialized
|
||||
* \retval - Status of the operation
|
||||
*/
|
||||
static bool linkedListInit( MacCommandsList_t* list )
|
||||
static bool LinkedListInit( MacCommandsList_t* list )
|
||||
{
|
||||
if( list == 0 )
|
||||
if( list == NULL )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
list->First = 0;
|
||||
list->Last = 0;
|
||||
list->First = NULL;
|
||||
list->Last = NULL;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
/*!
|
||||
* \brief Add an element to the list
|
||||
*
|
||||
* \param[IN] list - List where the element shall be added.
|
||||
* \param[IN] element - Element to add
|
||||
* \retval - Status of the operation
|
||||
*/
|
||||
static bool linkedListAdd( MacCommandsList_t* list, MacCommand_t* element )
|
||||
static bool LinkedListAdd( MacCommandsList_t* list, MacCommand_t* element )
|
||||
{
|
||||
if( ( list == 0 ) && ( element == 0 ) )
|
||||
if( ( list == NULL ) || ( element == NULL ) )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Check if this is the first entry to enter the list. */
|
||||
if( list->First == 0 )
|
||||
// Check if this is the first entry to enter the list.
|
||||
if( list->First == NULL )
|
||||
{
|
||||
list->First = element;
|
||||
}
|
||||
|
||||
/* Check if the last entry exists and update its next point. */
|
||||
// Check if the last entry exists and update its next point.
|
||||
if( list->Last )
|
||||
{
|
||||
list->Last->Next = element;
|
||||
}
|
||||
|
||||
/* Update the next point of this entry. */
|
||||
element->Next = 0;
|
||||
// Update the next point of this entry.
|
||||
element->Next = NULL;
|
||||
|
||||
/* Update the last entry of the list. */
|
||||
// Update the last entry of the list.
|
||||
list->Last = element;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
/*!
|
||||
* \brief Return the previous element in the list.
|
||||
*
|
||||
* \param[IN] list - List
|
||||
* \param[IN] element - Element where the previous element shall be searched
|
||||
* \retval - Status of the operation
|
||||
*/
|
||||
static MacCommand_t* linkedListGetPrevious( MacCommandsList_t* list, MacCommand_t* element )
|
||||
static MacCommand_t* LinkedListGetPrevious( MacCommandsList_t* list, MacCommand_t* element )
|
||||
{
|
||||
if( ( list == 0 ) && ( element == 0 ) )
|
||||
if( ( list == NULL ) || ( element == NULL ) )
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
@@ -220,14 +214,11 @@ static MacCommand_t* linkedListGetPrevious( MacCommandsList_t* list, MacCommand_
|
||||
// Start at the head of the list
|
||||
curElement = list->First;
|
||||
|
||||
/*
|
||||
* When current element is the first of the list, there's no previous element so we can return NULL immediately.
|
||||
*/
|
||||
if( element != curElement)
|
||||
// When current element is the first of the list, there's no previous element so we can return NULL immediately.
|
||||
if( element != curElement )
|
||||
{
|
||||
|
||||
// Loop through all elements until the end is reached or the next of current is the current element.
|
||||
while(curElement && (curElement->Next != element))
|
||||
while( ( curElement != NULL ) && ( curElement->Next != element ) )
|
||||
{
|
||||
curElement = curElement->Next;
|
||||
}
|
||||
@@ -240,21 +231,21 @@ static MacCommand_t* linkedListGetPrevious( MacCommandsList_t* list, MacCommand_
|
||||
return curElement;
|
||||
}
|
||||
|
||||
/*
|
||||
/*!
|
||||
* \brief Remove an element from the list
|
||||
*
|
||||
* \param[IN] list - List where the element shall be removed from.
|
||||
* \param[IN] element - Element to remove
|
||||
* \retval - Status of the operation
|
||||
*/
|
||||
static bool linkedListRemove( MacCommandsList_t* list, MacCommand_t* element )
|
||||
static bool LinkedListRemove( MacCommandsList_t* list, MacCommand_t* element )
|
||||
{
|
||||
if( ( list == 0 ) && ( element == 0 ) )
|
||||
if( ( list == NULL ) || ( element == NULL ) )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
MacCommand_t* PrevElement = linkedListGetPrevious( list, element );
|
||||
MacCommand_t* PrevElement = LinkedListGetPrevious( list, element );
|
||||
|
||||
if( list->First == element )
|
||||
{
|
||||
@@ -266,12 +257,12 @@ static bool linkedListRemove( MacCommandsList_t* list, MacCommand_t* element )
|
||||
list->Last = PrevElement;
|
||||
}
|
||||
|
||||
if( PrevElement )
|
||||
if( PrevElement != NULL )
|
||||
{
|
||||
PrevElement->Next = element->Next;
|
||||
}
|
||||
|
||||
element->Next = 0;
|
||||
element->Next = NULL;
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -290,6 +281,7 @@ static bool IsSticky( uint8_t cid )
|
||||
case MOTE_MAC_DL_CHANNEL_ANS:
|
||||
case MOTE_MAC_RX_PARAM_SETUP_ANS:
|
||||
case MOTE_MAC_RX_TIMING_SETUP_ANS:
|
||||
case MOTE_MAC_TX_PARAM_SETUP_ANS:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
@@ -307,13 +299,12 @@ static void NvmCtxCallback( void )
|
||||
}
|
||||
}
|
||||
|
||||
LoRaMacCommandStatus_t LoRaMacCommandsInit( EventNvmCtxChanged commandsNvmCtxChanged )
|
||||
LoRaMacCommandStatus_t LoRaMacCommandsInit( LoRaMacCommandsNvmEvent commandsNvmCtxChanged )
|
||||
{
|
||||
|
||||
// Initialize with default
|
||||
memset1( (uint8_t*)&NvmCtx, 0, sizeof( NvmCtx ) );
|
||||
memset1( ( uint8_t* )&NvmCtx, 0, sizeof( NvmCtx ) );
|
||||
|
||||
linkedListInit( &NvmCtx.MacCommandList );
|
||||
LinkedListInit( &NvmCtx.MacCommandList );
|
||||
|
||||
// Assign callback
|
||||
CommandsNvmCtxChanged = commandsNvmCtxChanged;
|
||||
@@ -326,7 +317,7 @@ LoRaMacCommandStatus_t LoRaMacCommandsRestoreNvmCtx( void* commandsNvmCtx )
|
||||
// Restore module context
|
||||
if( commandsNvmCtx != NULL )
|
||||
{
|
||||
memcpy1( ( uint8_t* ) &NvmCtx, ( uint8_t* ) commandsNvmCtx, sizeof( NvmCtx ) );
|
||||
memcpy1( ( uint8_t* )&NvmCtx, ( uint8_t* )commandsNvmCtx, sizeof( NvmCtx ) );
|
||||
return LORAMAC_COMMANDS_SUCCESS;
|
||||
}
|
||||
else
|
||||
@@ -341,24 +332,24 @@ void* LoRaMacCommandsGetNvmCtx( size_t* commandsNvmCtxSize )
|
||||
return &NvmCtx;
|
||||
}
|
||||
|
||||
LoRaMacCommandStatus_t LoRaMacCommandsAddCmd( uint8_t cid, uint8_t* payload, size_t payloadSize )
|
||||
LoRaMacCommandStatus_t LoRaMacCommandsAddCmd( uint8_t cid, uint8_t* payload, size_t payloadSize )
|
||||
{
|
||||
if( payload == 0 )
|
||||
if( payload == NULL )
|
||||
{
|
||||
return LORAMAC_COMMANDS_ERROR_NPE;
|
||||
}
|
||||
MacCommand_t* newCmd;
|
||||
|
||||
// Allocate a memory slot
|
||||
newCmd = mallocNewMacCommandSlot( );
|
||||
newCmd = MallocNewMacCommandSlot( );
|
||||
|
||||
if( newCmd == 0 )
|
||||
if( newCmd == NULL )
|
||||
{
|
||||
return LORAMAC_COMMANDS_ERROR_MEMORY;
|
||||
}
|
||||
|
||||
// Add it to the list of Mac commands
|
||||
if( linkedListAdd( &NvmCtx.MacCommandList, newCmd ) == false )
|
||||
if( LinkedListAdd( &NvmCtx.MacCommandList, newCmd ) == false )
|
||||
{
|
||||
return LORAMAC_COMMANDS_ERROR;
|
||||
}
|
||||
@@ -366,7 +357,7 @@ LoRaMacCommandStatus_t LoRaMacCommandsAddCmd( uint8_t cid, uint8_t* payload, si
|
||||
// Set Values
|
||||
newCmd->CID = cid;
|
||||
newCmd->PayloadSize = payloadSize;
|
||||
memcpy1( ( uint8_t* ) newCmd->Payload, payload, payloadSize );
|
||||
memcpy1( ( uint8_t* )newCmd->Payload, payload, payloadSize );
|
||||
newCmd->IsSticky = IsSticky( cid );
|
||||
|
||||
NvmCtx.SerializedCmdsSize += ( CID_FIELD_SIZE + payloadSize );
|
||||
@@ -384,7 +375,7 @@ LoRaMacCommandStatus_t LoRaMacCommandsRemoveCmd( MacCommand_t* macCmd )
|
||||
}
|
||||
|
||||
// Remove the Mac command element from MacCommandList
|
||||
if( linkedListRemove( &NvmCtx.MacCommandList, macCmd ) == false )
|
||||
if( LinkedListRemove( &NvmCtx.MacCommandList, macCmd ) == false )
|
||||
{
|
||||
return LORAMAC_COMMANDS_ERROR_CMD_NOT_FOUND;
|
||||
}
|
||||
@@ -392,7 +383,7 @@ LoRaMacCommandStatus_t LoRaMacCommandsRemoveCmd( MacCommand_t* macCmd )
|
||||
NvmCtx.SerializedCmdsSize -= ( CID_FIELD_SIZE + macCmd->PayloadSize );
|
||||
|
||||
// Free the MacCommand Slot
|
||||
if( freeMacCommandSlot( macCmd ) == false )
|
||||
if( FreeMacCommandSlot( macCmd ) == false )
|
||||
{
|
||||
return LORAMAC_COMMANDS_ERROR;
|
||||
}
|
||||
@@ -410,19 +401,19 @@ LoRaMacCommandStatus_t LoRaMacCommandsGetCmd( uint8_t cid, MacCommand_t** macCmd
|
||||
curElement = NvmCtx.MacCommandList.First;
|
||||
|
||||
// Loop through all elements until we find the element with the given CID
|
||||
while(curElement && ( curElement->CID != cid ) )
|
||||
while( ( curElement != NULL ) && ( curElement->CID != cid ) )
|
||||
{
|
||||
curElement = curElement->Next;
|
||||
}
|
||||
|
||||
// Update the pointer anyway
|
||||
*macCmd = curElement;
|
||||
|
||||
// Handle error in case if we reached the end without finding it.
|
||||
if( curElement == NULL )
|
||||
{
|
||||
return LORAMAC_COMMANDS_ERROR_CMD_NOT_FOUND;
|
||||
}
|
||||
|
||||
*macCmd = curElement;
|
||||
|
||||
return LORAMAC_COMMANDS_SUCCESS;
|
||||
}
|
||||
|
||||
@@ -435,7 +426,7 @@ LoRaMacCommandStatus_t LoRaMacCommandsRemoveNoneStickyCmds( void )
|
||||
curElement = NvmCtx.MacCommandList.First;
|
||||
|
||||
// Loop through all elements
|
||||
while( curElement )
|
||||
while( curElement != NULL )
|
||||
{
|
||||
if( curElement->IsSticky == false )
|
||||
{
|
||||
@@ -466,16 +457,9 @@ LoRaMacCommandStatus_t LoRaMacCommandsRemoveStickyAnsCmds( void )
|
||||
while( curElement != NULL )
|
||||
{
|
||||
nexElement = curElement->Next;
|
||||
if( curElement->IsSticky == true )
|
||||
if( IsSticky( curElement->CID ) == true )
|
||||
{
|
||||
for( uint8_t i = 0; i < sizeof( CIDsStickyAnsCmds ); i++)
|
||||
{
|
||||
if( curElement->CID == CIDsStickyAnsCmds[i] )
|
||||
{
|
||||
LoRaMacCommandsRemoveCmd( curElement );
|
||||
break;
|
||||
}
|
||||
}
|
||||
LoRaMacCommandsRemoveCmd( curElement );
|
||||
}
|
||||
curElement = nexElement;
|
||||
}
|
||||
@@ -493,28 +477,28 @@ LoRaMacCommandStatus_t LoRaMacCommandsGetSizeSerializedCmds( size_t* size )
|
||||
}
|
||||
*size = NvmCtx.SerializedCmdsSize;
|
||||
return LORAMAC_COMMANDS_SUCCESS;
|
||||
|
||||
}
|
||||
|
||||
LoRaMacCommandStatus_t LoRaMacCommandsSerializeCmds( size_t availableSize, size_t* effectiveSize, uint8_t* buffer )
|
||||
LoRaMacCommandStatus_t LoRaMacCommandsSerializeCmds( size_t availableSize, size_t* effectiveSize, uint8_t* buffer )
|
||||
{
|
||||
MacCommand_t* curElement = NvmCtx.MacCommandList.First;
|
||||
MacCommand_t* nextElement;
|
||||
uint8_t itr = 0;
|
||||
|
||||
if( ( buffer == NULL ) || ( effectiveSize == NULL ) )
|
||||
{
|
||||
return LORAMAC_COMMANDS_ERROR_NPE;
|
||||
}
|
||||
MacCommand_t* curElement;
|
||||
curElement = NvmCtx.MacCommandList.First;
|
||||
uint8_t itr = 0;
|
||||
|
||||
// Loop through all elements
|
||||
while( curElement )
|
||||
// Loop through all elements which fits into the buffer
|
||||
while( curElement != NULL )
|
||||
{
|
||||
// If the next MAC command still fits into the buffer, add it.
|
||||
if( ( availableSize - itr ) >= ( CID_FIELD_SIZE + curElement->PayloadSize ) )
|
||||
{
|
||||
buffer[itr++] = curElement->CID;
|
||||
memcpy1( &buffer[itr], curElement->Payload, curElement->PayloadSize );
|
||||
itr = itr + curElement->PayloadSize;
|
||||
itr += curElement->PayloadSize;
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -523,6 +507,18 @@ LoRaMacCommandStatus_t LoRaMacCommandsSerializeCmds( size_t availableSize, size_
|
||||
curElement = curElement->Next;
|
||||
}
|
||||
|
||||
// Remove all commands which do not fit into the buffer
|
||||
while( curElement != NULL )
|
||||
{
|
||||
// Store the next element before removing the current one
|
||||
nextElement = curElement->Next;
|
||||
LoRaMacCommandsRemoveCmd( curElement );
|
||||
curElement = nextElement;
|
||||
}
|
||||
|
||||
// Fetch the effective size of the mac commands
|
||||
LoRaMacCommandsGetSizeSerializedCmds( effectiveSize );
|
||||
|
||||
return LORAMAC_COMMANDS_SUCCESS;
|
||||
}
|
||||
|
||||
@@ -538,7 +534,7 @@ LoRaMacCommandStatus_t LoRaMacCommandsStickyCmdsPending( bool* cmdsPending )
|
||||
*cmdsPending = false;
|
||||
|
||||
// Loop through all elements
|
||||
while( curElement )
|
||||
while( curElement != NULL )
|
||||
{
|
||||
if( curElement->IsSticky == true )
|
||||
{
|
||||
@@ -551,3 +547,103 @@ LoRaMacCommandStatus_t LoRaMacCommandsStickyCmdsPending( bool* cmdsPending )
|
||||
|
||||
return LORAMAC_COMMANDS_SUCCESS;
|
||||
}
|
||||
|
||||
uint8_t LoRaMacCommandsGetCmdSize( uint8_t cid )
|
||||
{
|
||||
uint8_t cidSize = 0;
|
||||
|
||||
// Decode Frame MAC commands
|
||||
switch( cid )
|
||||
{
|
||||
case SRV_MAC_LINK_CHECK_ANS:
|
||||
{
|
||||
// cid + Margin + GwCnt
|
||||
cidSize = 3;
|
||||
break;
|
||||
}
|
||||
case SRV_MAC_LINK_ADR_REQ:
|
||||
{
|
||||
// cid + DataRate_TXPower + ChMask (2) + Redundancy
|
||||
cidSize = 5;
|
||||
break;
|
||||
}
|
||||
case SRV_MAC_DUTY_CYCLE_REQ:
|
||||
{
|
||||
// cid + DutyCyclePL
|
||||
cidSize = 2;
|
||||
break;
|
||||
}
|
||||
case SRV_MAC_RX_PARAM_SETUP_REQ:
|
||||
{
|
||||
// cid + DLsettings + Frequency (3)
|
||||
cidSize = 5;
|
||||
break;
|
||||
}
|
||||
case SRV_MAC_DEV_STATUS_REQ:
|
||||
{
|
||||
// cid
|
||||
cidSize = 1;
|
||||
break;
|
||||
}
|
||||
case SRV_MAC_NEW_CHANNEL_REQ:
|
||||
{
|
||||
// cid + ChIndex + Frequency (3) + DrRange
|
||||
cidSize = 6;
|
||||
break;
|
||||
}
|
||||
case SRV_MAC_RX_TIMING_SETUP_REQ:
|
||||
{
|
||||
// cid + Settings
|
||||
cidSize = 2;
|
||||
break;
|
||||
}
|
||||
case SRV_MAC_TX_PARAM_SETUP_REQ:
|
||||
{
|
||||
// cid + EIRP_DwellTime
|
||||
cidSize = 2;
|
||||
break;
|
||||
}
|
||||
case SRV_MAC_DL_CHANNEL_REQ:
|
||||
{
|
||||
// cid + ChIndex + Frequency (3)
|
||||
cidSize = 5;
|
||||
break;
|
||||
}
|
||||
case SRV_MAC_DEVICE_TIME_ANS:
|
||||
{
|
||||
// cid + Seconds (4) + Fractional seconds (1)
|
||||
cidSize = 6;
|
||||
break;
|
||||
}
|
||||
case SRV_MAC_PING_SLOT_INFO_ANS:
|
||||
{
|
||||
// cid
|
||||
cidSize = 1;
|
||||
break;
|
||||
}
|
||||
case SRV_MAC_PING_SLOT_CHANNEL_REQ:
|
||||
{
|
||||
// cid + Frequency (3) + DR
|
||||
cidSize = 5;
|
||||
break;
|
||||
}
|
||||
case SRV_MAC_BEACON_TIMING_ANS:
|
||||
{
|
||||
// cid + TimingDelay (2) + Channel
|
||||
cidSize = 4;
|
||||
break;
|
||||
}
|
||||
case SRV_MAC_BEACON_FREQ_REQ:
|
||||
{
|
||||
// cid + Frequency (3)
|
||||
cidSize = 4;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
// Unknown command. ABORT MAC commands processing
|
||||
break;
|
||||
}
|
||||
}
|
||||
return cidSize;
|
||||
}
|
||||
|
@@ -35,6 +35,11 @@
|
||||
#ifndef __LORAMAC_COMMANDS_H__
|
||||
#define __LORAMAC_COMMANDS_H__
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
#include "LoRaMacTypes.h"
|
||||
@@ -109,7 +114,7 @@ typedef enum eLoRaMacCommandsStatus
|
||||
* Signature of callback function to be called by this module when the
|
||||
* non-volatile needs to be saved.
|
||||
*/
|
||||
typedef void ( *EventNvmCtxChanged )( void );
|
||||
typedef void ( *LoRaMacCommandsNvmEvent )( void );
|
||||
|
||||
/*!
|
||||
* \brief Initialization of LoRaMac MAC commands module
|
||||
@@ -119,7 +124,7 @@ typedef void ( *EventNvmCtxChanged )( void );
|
||||
*
|
||||
* \retval - Status of the operation
|
||||
*/
|
||||
LoRaMacCommandStatus_t LoRaMacCommandsInit( EventNvmCtxChanged commandsNvmCtxChanged );
|
||||
LoRaMacCommandStatus_t LoRaMacCommandsInit( LoRaMacCommandsNvmEvent commandsNvmCtxChanged );
|
||||
|
||||
/*!
|
||||
* Restores the internal non-volatile context from passed pointer.
|
||||
@@ -212,7 +217,20 @@ LoRaMacCommandStatus_t LoRaMacCommandsSerializeCmds( size_t availableSize, size_
|
||||
*/
|
||||
LoRaMacCommandStatus_t LoRaMacCommandsStickyCmdsPending( bool* cmdsPending );
|
||||
|
||||
/*!
|
||||
* \brief Get the MAC command size with corresponding CID.
|
||||
*
|
||||
* \param[IN] cid - MAC command identifier
|
||||
*
|
||||
* \retval Size of the command.
|
||||
*/
|
||||
uint8_t LoRaMacCommandsGetCmdSize( uint8_t cid );
|
||||
|
||||
/*! \} addtogroup LORAMAC */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // __LORAMAC_COMMANDS_H__
|
||||
|
||||
|
@@ -66,7 +66,7 @@ typedef struct sLoRaMacConfirmQueueCtx
|
||||
/*
|
||||
* Callback function to notify the upper layer about context change
|
||||
*/
|
||||
EventNvmCtxChanged EventNvmCtxChanged;
|
||||
LoRaMacConfirmQueueNvmEvent LoRaMacConfirmQueueNvmEvent;
|
||||
/*!
|
||||
* Non-volatile module context.
|
||||
*/
|
||||
@@ -112,26 +112,47 @@ static MlmeConfirmQueue_t* DecreaseBufferPointer( MlmeConfirmQueue_t* bufferPoin
|
||||
return bufferPointer;
|
||||
}
|
||||
|
||||
static bool IsListEmpty( uint8_t count )
|
||||
{
|
||||
if( count == 0 )
|
||||
{
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool IsListFull( uint8_t count )
|
||||
{
|
||||
if( count >= LORA_MAC_MLME_CONFIRM_QUEUE_LEN )
|
||||
{
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static MlmeConfirmQueue_t* GetElement( Mlme_t request, MlmeConfirmQueue_t* bufferStart, MlmeConfirmQueue_t* bufferEnd )
|
||||
{
|
||||
MlmeConfirmQueue_t* element = bufferStart;
|
||||
|
||||
while( element != bufferEnd )
|
||||
if( IsListEmpty( ConfirmQueueCtx.ConfirmQueueNvmCtx->MlmeConfirmQueueCnt ) == true )
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
for( uint8_t elementCnt = 0; elementCnt < ConfirmQueueCtx.ConfirmQueueNvmCtx->MlmeConfirmQueueCnt; elementCnt++ )
|
||||
{
|
||||
if( element->Request == request )
|
||||
{
|
||||
// We have found the element
|
||||
return element;
|
||||
}
|
||||
else
|
||||
{
|
||||
element = IncreaseBufferPointer( element );
|
||||
}
|
||||
element = IncreaseBufferPointer( element );
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void LoRaMacConfirmQueueInit( LoRaMacPrimitives_t* primitives, EventNvmCtxChanged confirmQueueNvmCtxChanged )
|
||||
void LoRaMacConfirmQueueInit( LoRaMacPrimitives_t* primitives, LoRaMacConfirmQueueNvmEvent confirmQueueNvmCtxChanged )
|
||||
{
|
||||
ConfirmQueueCtx.Primitives = primitives;
|
||||
|
||||
@@ -151,7 +172,7 @@ void LoRaMacConfirmQueueInit( LoRaMacPrimitives_t* primitives, EventNvmCtxChange
|
||||
ConfirmQueueCtx.ConfirmQueueNvmCtx->CommonStatus = LORAMAC_EVENT_INFO_STATUS_ERROR;
|
||||
|
||||
// Assign callback
|
||||
ConfirmQueueCtx.EventNvmCtxChanged = confirmQueueNvmCtxChanged;
|
||||
ConfirmQueueCtx.LoRaMacConfirmQueueNvmEvent = confirmQueueNvmCtxChanged;
|
||||
}
|
||||
|
||||
bool LoRaMacConfirmQueueRestoreNvmCtx( void* confirmQueueNvmCtx )
|
||||
@@ -176,7 +197,7 @@ void* LoRaMacConfirmQueueGetNvmCtx( size_t* confirmQueueNvmCtxSize )
|
||||
|
||||
bool LoRaMacConfirmQueueAdd( MlmeConfirmQueue_t* mlmeConfirm )
|
||||
{
|
||||
if( ConfirmQueueCtx.ConfirmQueueNvmCtx->MlmeConfirmQueueCnt >= LORA_MAC_MLME_CONFIRM_QUEUE_LEN )
|
||||
if( IsListFull( ConfirmQueueCtx.ConfirmQueueNvmCtx->MlmeConfirmQueueCnt ) == true )
|
||||
{
|
||||
// Protect the buffer against overwrites
|
||||
return false;
|
||||
@@ -197,7 +218,7 @@ bool LoRaMacConfirmQueueAdd( MlmeConfirmQueue_t* mlmeConfirm )
|
||||
|
||||
bool LoRaMacConfirmQueueRemoveLast( void )
|
||||
{
|
||||
if( ConfirmQueueCtx.ConfirmQueueNvmCtx->MlmeConfirmQueueCnt == 0 )
|
||||
if( IsListEmpty( ConfirmQueueCtx.ConfirmQueueNvmCtx->MlmeConfirmQueueCnt ) == true )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
@@ -212,7 +233,7 @@ bool LoRaMacConfirmQueueRemoveLast( void )
|
||||
|
||||
bool LoRaMacConfirmQueueRemoveFirst( void )
|
||||
{
|
||||
if( ConfirmQueueCtx.ConfirmQueueNvmCtx->MlmeConfirmQueueCnt == 0 )
|
||||
if( IsListEmpty( ConfirmQueueCtx.ConfirmQueueNvmCtx->MlmeConfirmQueueCnt ) == true )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
@@ -229,7 +250,7 @@ void LoRaMacConfirmQueueSetStatus( LoRaMacEventInfoStatus_t status, Mlme_t reque
|
||||
{
|
||||
MlmeConfirmQueue_t* element = NULL;
|
||||
|
||||
if( ConfirmQueueCtx.ConfirmQueueNvmCtx->MlmeConfirmQueueCnt > 0 )
|
||||
if( IsListEmpty( ConfirmQueueCtx.ConfirmQueueNvmCtx->MlmeConfirmQueueCnt ) == false )
|
||||
{
|
||||
element = GetElement( request, ConfirmQueueCtx.BufferStart, ConfirmQueueCtx.BufferEnd );
|
||||
if( element != NULL )
|
||||
@@ -244,7 +265,7 @@ LoRaMacEventInfoStatus_t LoRaMacConfirmQueueGetStatus( Mlme_t request )
|
||||
{
|
||||
MlmeConfirmQueue_t* element = NULL;
|
||||
|
||||
if( ConfirmQueueCtx.ConfirmQueueNvmCtx->MlmeConfirmQueueCnt > 0 )
|
||||
if( IsListEmpty( ConfirmQueueCtx.ConfirmQueueNvmCtx->MlmeConfirmQueueCnt ) == false )
|
||||
{
|
||||
element = GetElement( request, ConfirmQueueCtx.BufferStart, ConfirmQueueCtx.BufferEnd );
|
||||
if( element != NULL )
|
||||
@@ -261,7 +282,7 @@ void LoRaMacConfirmQueueSetStatusCmn( LoRaMacEventInfoStatus_t status )
|
||||
|
||||
ConfirmQueueCtx.ConfirmQueueNvmCtx->CommonStatus = status;
|
||||
|
||||
if( ConfirmQueueCtx.ConfirmQueueNvmCtx->MlmeConfirmQueueCnt > 0 )
|
||||
if( IsListEmpty( ConfirmQueueCtx.ConfirmQueueNvmCtx->MlmeConfirmQueueCnt ) == false )
|
||||
{
|
||||
do
|
||||
{
|
||||
@@ -333,7 +354,7 @@ uint8_t LoRaMacConfirmQueueGetCnt( void )
|
||||
|
||||
bool LoRaMacConfirmQueueIsFull( void )
|
||||
{
|
||||
if( ConfirmQueueCtx.ConfirmQueueNvmCtx->MlmeConfirmQueueCnt >= LORA_MAC_MLME_CONFIRM_QUEUE_LEN )
|
||||
if( IsListFull( ConfirmQueueCtx.ConfirmQueueNvmCtx->MlmeConfirmQueueCnt ) == true )
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
@@ -39,6 +39,11 @@
|
||||
#ifndef __LORAMAC_CONFIRMQUEUE_H__
|
||||
#define __LORAMAC_CONFIRMQUEUE_H__
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
|
||||
@@ -77,7 +82,7 @@ typedef struct sMlmeConfirmQueue
|
||||
* Signature of callback function to be called by this module when the
|
||||
* non-volatile needs to be saved.
|
||||
*/
|
||||
typedef void ( *EventNvmCtxChanged )( void );
|
||||
typedef void ( *LoRaMacConfirmQueueNvmEvent )( void );
|
||||
|
||||
/*!
|
||||
* \brief Initializes the confirm queue
|
||||
@@ -87,7 +92,7 @@ typedef void ( *EventNvmCtxChanged )( void );
|
||||
* \param [IN] confirmQueueNvmCtxChanged - Callback function which will be called when the
|
||||
* non-volatile context needs to be saved.
|
||||
*/
|
||||
void LoRaMacConfirmQueueInit( LoRaMacPrimitives_t* primitives, EventNvmCtxChanged confirmQueueNvmCtxChanged );
|
||||
void LoRaMacConfirmQueueInit( LoRaMacPrimitives_t* primitives, LoRaMacConfirmQueueNvmEvent confirmQueueNvmCtxChanged );
|
||||
|
||||
/*!
|
||||
* Restores the internal non-volatile context from passed pointer.
|
||||
@@ -192,4 +197,8 @@ uint8_t LoRaMacConfirmQueueGetCnt( void );
|
||||
*/
|
||||
bool LoRaMacConfirmQueueIsFull( void );
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // __LORAMAC_CONFIRMQUEUE_H__
|
||||
|
File diff suppressed because it is too large
Load Diff
@@ -37,6 +37,11 @@
|
||||
#ifndef __LORAMAC_CRYPTO_H__
|
||||
#define __LORAMAC_CRYPTO_H__
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
@@ -44,6 +49,26 @@
|
||||
#include "LoRaMacTypes.h"
|
||||
#include "LoRaMacMessageTypes.h"
|
||||
|
||||
/*!
|
||||
* Indicates if LoRaWAN 1.1.x crypto scheme is enabled
|
||||
*/
|
||||
#define USE_LRWAN_1_1_X_CRYPTO 0
|
||||
|
||||
/*!
|
||||
* Indicates if a random devnonce must be used or not
|
||||
*/
|
||||
#define USE_RANDOM_DEV_NONCE 1
|
||||
|
||||
/*!
|
||||
* Indicates if JoinNonce is counter based and requires to be checked
|
||||
*/
|
||||
#define USE_JOIN_NONCE_COUNTER_CHECK 0
|
||||
|
||||
/*!
|
||||
* Initial value of the frame counters
|
||||
*/
|
||||
#define FCNT_DOWN_INITAL_VALUE 0xFFFFFFFF
|
||||
|
||||
/*!
|
||||
* LoRaMac Cryto Status
|
||||
*/
|
||||
@@ -70,9 +95,21 @@ typedef enum eLoRaMacCryptoStatus
|
||||
*/
|
||||
LORAMAC_CRYPTO_FAIL_RJCOUNT0_OVERFLOW,
|
||||
/*!
|
||||
* FCntUp/Down check failed
|
||||
* FCNT_ID is not supported
|
||||
*/
|
||||
LORAMAC_CRYPTO_FAIL_FCNT,
|
||||
LORAMAC_CRYPTO_FAIL_FCNT_ID,
|
||||
/*!
|
||||
* FCntUp/Down check failed (new FCnt is smaller than previous one)
|
||||
*/
|
||||
LORAMAC_CRYPTO_FAIL_FCNT_SMALLER,
|
||||
/*!
|
||||
* FCntUp/Down check failed (duplicated)
|
||||
*/
|
||||
LORAMAC_CRYPTO_FAIL_FCNT_DUPLICATED,
|
||||
/*!
|
||||
* MAX_GAP_FCNT check failed
|
||||
*/
|
||||
LORAMAC_CRYPTO_FAIL_MAX_GAP_FCNT,
|
||||
/*!
|
||||
* Not allowed parameter value
|
||||
*/
|
||||
@@ -125,7 +162,7 @@ typedef enum eLoRaMacCryptoStatus
|
||||
* crypto module context.
|
||||
*
|
||||
*/
|
||||
typedef void ( *EventNvmCtxChanged )( void );
|
||||
typedef void ( *LoRaMacCryptoNvmEvent )( void );
|
||||
|
||||
/*!
|
||||
* Initialization of LoRaMac Crypto module
|
||||
@@ -135,11 +172,11 @@ typedef void ( *EventNvmCtxChanged )( void );
|
||||
* non-volatile context have to be stored.
|
||||
* \retval - Status of the operation
|
||||
*/
|
||||
LoRaMacCryptoStatus_t LoRaMacCryptoInit( EventNvmCtxChanged cryptoNvmCtxChanged );
|
||||
LoRaMacCryptoStatus_t LoRaMacCryptoInit( LoRaMacCryptoNvmEvent cryptoNvmCtxChanged );
|
||||
|
||||
/*!
|
||||
* Sets the LoRaWAN specification version to be used.
|
||||
*
|
||||
*
|
||||
* \warning This function should be used for ABP only. In case of OTA the version will be set automatically.
|
||||
*
|
||||
* \param[IN] version - LoRaWAN specification version to be used.
|
||||
@@ -164,6 +201,34 @@ LoRaMacCryptoStatus_t LoRaMacCryptoRestoreNvmCtx( void* cryptoNvmCtx );
|
||||
*/
|
||||
void* LoRaMacCryptoGetNvmCtx( size_t* cryptoNvmCtxSize );
|
||||
|
||||
/*!
|
||||
* Returns updated fCntID downlink counter value.
|
||||
*
|
||||
* \param[IN] fCntID - Frame counter identifier
|
||||
* \param[IN] maxFcntGap - Maximum allowed frame counter difference (only necessary for L2 LW1.0.x)
|
||||
* \param[IN] frameFcnt - Received frame counter (used to update current counter value)
|
||||
* \param[OUT] currentDown - Current downlink counter value
|
||||
* \retval - Status of the operation
|
||||
*/
|
||||
LoRaMacCryptoStatus_t LoRaMacCryptoGetFCntDown( FCntIdentifier_t fCntID, uint16_t maxFCntGap, uint32_t frameFcnt, uint32_t* currentDown );
|
||||
|
||||
/*!
|
||||
* Returns updated fCntUp uplink counter value.
|
||||
*
|
||||
* \param[IN] currentUp - Uplink counter value
|
||||
* \retval - Status of the operation
|
||||
*/
|
||||
LoRaMacCryptoStatus_t LoRaMacCryptoGetFCntUp( uint32_t* currentUp );
|
||||
|
||||
/*!
|
||||
* Provides multicast context.
|
||||
*
|
||||
* \param[IN] multicastList - Pointer to the multicast context list
|
||||
*
|
||||
* \retval - Status of the operation
|
||||
*/
|
||||
LoRaMacCryptoStatus_t LoRaMacCryptoSetMulticastReference( MulticastCtx_t* multicastList );
|
||||
|
||||
/*!
|
||||
* Sets a key
|
||||
*
|
||||
@@ -235,16 +300,28 @@ LoRaMacCryptoStatus_t LoRaMacCryptoSecureMessage( uint32_t fCntUp, uint8_t txDr,
|
||||
LoRaMacCryptoStatus_t LoRaMacCryptoUnsecureMessage( AddressIdentifier_t addrID, uint32_t address, FCntIdentifier_t fCntID, uint32_t fCntDown, LoRaMacMessageData_t* macMsg );
|
||||
|
||||
/*!
|
||||
* Derives the McKEKey from the AppKey or NwkKey.
|
||||
* Derives the McRootKey from the AppKey.
|
||||
*
|
||||
* McKEKey = aes128_encrypt(NwkKey or AppKey , nonce | DevEUI | pad16)
|
||||
* 1.0.x
|
||||
* McRootKey = aes128_encrypt(AppKey, 0x00 | pad16)
|
||||
*
|
||||
* \param[IN] keyID - Key identifier of the root key to use to perform the derivation ( NwkKey or AppKey )
|
||||
* \param[IN] nonce - Nonce value ( nonce <= 15)
|
||||
* \param[IN] devEUI - DevEUI Value
|
||||
* 1.1.x
|
||||
* McRootKey = aes128_encrypt(AppKey, 0x20 | pad16)
|
||||
*
|
||||
* \param[IN] keyID - Key identifier of the root key to use to perform the derivation ( AppKey )
|
||||
* \retval - Status of the operation
|
||||
*/
|
||||
LoRaMacCryptoStatus_t LoRaMacCryptoDeriveMcKEKey( KeyIdentifier_t keyID, uint16_t nonce, uint8_t* devEUI );
|
||||
LoRaMacCryptoStatus_t LoRaMacCryptoDeriveMcRootKey( KeyIdentifier_t keyID );
|
||||
|
||||
/*!
|
||||
* Derives the McKEKey from the McRootKey.
|
||||
*
|
||||
* McKEKey = aes128_encrypt(McRootKey , 0x00 | pad16)
|
||||
*
|
||||
* \param[IN] keyID - Key identifier of the root key to use to perform the derivation ( McRootKey )
|
||||
* \retval - Status of the operation
|
||||
*/
|
||||
LoRaMacCryptoStatus_t LoRaMacCryptoDeriveMcKEKey( KeyIdentifier_t keyID );
|
||||
|
||||
/*!
|
||||
* Derives a Multicast group key pair ( McAppSKey, McNwkSKey ) from McKey
|
||||
@@ -260,4 +337,8 @@ LoRaMacCryptoStatus_t LoRaMacCryptoDeriveMcSessionKeyPair( AddressIdentifier_t a
|
||||
|
||||
/*! \} addtogroup LORAMAC */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // __LORAMAC_CRYPTO_H__
|
||||
|
@@ -1,319 +0,0 @@
|
||||
/*
|
||||
/ _____) _ | |
|
||||
( (____ _____ ____ _| |_ _____ ____| |__
|
||||
\____ \| ___ | (_ _) ___ |/ ___) _ \
|
||||
_____) ) ____| | | || |_| ____( (___| | | |
|
||||
(______/|_____)_|_|_| \__)_____)\____)_| |_|
|
||||
(C)2013 Semtech
|
||||
___ _____ _ ___ _ _____ ___ ___ ___ ___
|
||||
/ __|_ _/_\ / __| |/ / __/ _ \| _ \/ __| __|
|
||||
\__ \ | |/ _ \ (__| ' <| _| (_) | / (__| _|
|
||||
|___/ |_/_/ \_\___|_|\_\_| \___/|_|_\\___|___|
|
||||
embedded.connectivity.solutions===============
|
||||
|
||||
Description: LoRa MAC layer frame counter handling implementation
|
||||
|
||||
License: Revised BSD License, see LICENSE.TXT file include in the project
|
||||
|
||||
Maintainer: Miguel Luis ( Semtech ), Daniel Jaeckle ( STACKFORCE ), Johannes Bruder ( STACKFORCE )
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
#include "utilities.h"
|
||||
#include "LoRaMacFCntHandler.h"
|
||||
|
||||
/*
|
||||
* Initial value of the frame counters
|
||||
*/
|
||||
#define FCNT_DOWN_INITAL_VALUE 0xFFFFFFFF
|
||||
|
||||
|
||||
/*!
|
||||
* LoRaWAN Frame counter list.
|
||||
*/
|
||||
typedef struct sFCntList
|
||||
{
|
||||
/*
|
||||
* Uplink frame counter which is incremented with each uplink.
|
||||
*/
|
||||
uint32_t FCntUp;
|
||||
/*
|
||||
* Network downlink frame counter which is incremented with each downlink on FPort 0
|
||||
* or when the FPort field is missing.
|
||||
*/
|
||||
uint32_t NFCntDown;
|
||||
/*
|
||||
* Application downlink frame counter which is incremented with each downlink
|
||||
* on a port different than 0.
|
||||
*/
|
||||
uint32_t AFCntDown;
|
||||
/*
|
||||
* In case if the device is connected to a LoRaWAN 1.0 Server,
|
||||
* this counter is used for every kind of downlink frame.
|
||||
*/
|
||||
uint32_t FCntDown;
|
||||
/*!
|
||||
* Multicast downlink counter for index 0
|
||||
*/
|
||||
uint32_t McFCntDown0;
|
||||
/*!
|
||||
* Multicast downlink counter for index 1
|
||||
*/
|
||||
uint32_t McFCntDown1;
|
||||
/*!
|
||||
* Multicast downlink counter for index 2
|
||||
*/
|
||||
uint32_t McFCntDown2;
|
||||
/*!
|
||||
* Multicast downlink counter for index 3
|
||||
*/
|
||||
uint32_t McFCntDown3;
|
||||
}FCntList_t;
|
||||
|
||||
|
||||
/*
|
||||
* LoRaMac Commands Context structure
|
||||
*/
|
||||
typedef struct sLoRaMacFCntHandlerNvmCtx
|
||||
{
|
||||
/*
|
||||
* Frame counter list
|
||||
*/
|
||||
FCntList_t FCntList;
|
||||
} LoRaMacFCntHandlerNvmCtx_t;
|
||||
|
||||
/*
|
||||
* Non-volatile module context.
|
||||
*/
|
||||
static LoRaMacFCntHandlerNvmCtx_t FCntHandlerNvmCtx;
|
||||
|
||||
/*
|
||||
* Callback function to notify the upper layer about context change
|
||||
*/
|
||||
static EventNvmCtxChanged FCntHandlerNvmCtxChanged;
|
||||
|
||||
/*
|
||||
* \brief Wrapper function for the NvmCtx
|
||||
*/
|
||||
static void NvmCtxChanged( void )
|
||||
{
|
||||
if( FCntHandlerNvmCtxChanged != NULL )
|
||||
{
|
||||
FCntHandlerNvmCtxChanged( );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
LoRaMacFCntHandlerStatus_t LoRaMacFCntHandlerInit( EventNvmCtxChanged fCntHandlerNvmCtxChanged )
|
||||
{
|
||||
// Initialize with default
|
||||
LoRaMacResetFCnts( );
|
||||
|
||||
// Assign callback
|
||||
FCntHandlerNvmCtxChanged = fCntHandlerNvmCtxChanged;
|
||||
|
||||
return LORAMAC_FCNT_HANDLER_SUCCESS;
|
||||
}
|
||||
|
||||
LoRaMacFCntHandlerStatus_t LoRaMacFCntHandlerRestoreNvmCtx( void* fCntHandlerNvmCtx )
|
||||
{
|
||||
// Restore module context
|
||||
if( fCntHandlerNvmCtx != NULL )
|
||||
{
|
||||
memcpy1( ( uint8_t* ) &FCntHandlerNvmCtx, ( uint8_t* ) fCntHandlerNvmCtx, sizeof( FCntHandlerNvmCtx ) );
|
||||
return LORAMAC_FCNT_HANDLER_SUCCESS;
|
||||
}
|
||||
else
|
||||
{
|
||||
return LORAMAC_FCNT_HANDLER_ERROR_NPE;
|
||||
}
|
||||
}
|
||||
|
||||
void* LoRaMacFCntHandlerGetNvmCtx( size_t* fCntHandlerNvmCtxSize )
|
||||
{
|
||||
*fCntHandlerNvmCtxSize = sizeof( FCntHandlerNvmCtx );
|
||||
return &FCntHandlerNvmCtx;
|
||||
}
|
||||
|
||||
LoRaMacFCntHandlerStatus_t LoRaMacGetFCntDown( AddressIdentifier_t addrID, FType_t fType, LoRaMacMessageData_t* macMsg, Version_t lrWanVersion,
|
||||
uint16_t maxFCntGap, FCntIdentifier_t* fCntID, uint32_t* currentDown )
|
||||
{
|
||||
uint32_t previousDown = 0;
|
||||
int32_t fCntDiff = 0;
|
||||
|
||||
if( ( macMsg == NULL ) || ( fCntID == NULL ) ||
|
||||
( currentDown == NULL ) )
|
||||
{
|
||||
return LORAMAC_FCNT_HANDLER_ERROR_NPE;
|
||||
}
|
||||
|
||||
// Determine the frame counter identifier and choose counter from FCntList
|
||||
switch( addrID )
|
||||
{
|
||||
case UNICAST_DEV_ADDR:
|
||||
if( lrWanVersion.Fields.Minor == 1 )
|
||||
{
|
||||
if( ( fType == FRAME_TYPE_A ) || ( fType == FRAME_TYPE_D ) )
|
||||
{
|
||||
*fCntID = A_FCNT_DOWN;
|
||||
previousDown = FCntHandlerNvmCtx.FCntList.AFCntDown;
|
||||
}
|
||||
else
|
||||
{
|
||||
*fCntID = N_FCNT_DOWN;
|
||||
previousDown = FCntHandlerNvmCtx.FCntList.NFCntDown;
|
||||
}
|
||||
}
|
||||
else
|
||||
{ // For LoRaWAN 1.0.X
|
||||
*fCntID = FCNT_DOWN;
|
||||
previousDown = FCntHandlerNvmCtx.FCntList.FCntDown;
|
||||
}
|
||||
break;
|
||||
case MULTICAST_0_ADDR:
|
||||
*fCntID = MC_FCNT_DOWN_0;
|
||||
previousDown = FCntHandlerNvmCtx.FCntList.McFCntDown0;
|
||||
break;
|
||||
case MULTICAST_1_ADDR:
|
||||
*fCntID = MC_FCNT_DOWN_1;
|
||||
previousDown = FCntHandlerNvmCtx.FCntList.McFCntDown1;
|
||||
break;
|
||||
case MULTICAST_2_ADDR:
|
||||
*fCntID = MC_FCNT_DOWN_2;
|
||||
previousDown = FCntHandlerNvmCtx.FCntList.McFCntDown3;
|
||||
break;
|
||||
case MULTICAST_3_ADDR:
|
||||
*fCntID = MC_FCNT_DOWN_3;
|
||||
previousDown = FCntHandlerNvmCtx.FCntList.McFCntDown3;
|
||||
break;
|
||||
default:
|
||||
return LORAMAC_FCNT_HANDLER_ERROR;
|
||||
}
|
||||
|
||||
// For LoRaWAN 1.0.X only, allow downlink frames of 0
|
||||
if( previousDown == FCNT_DOWN_INITAL_VALUE )
|
||||
{
|
||||
*currentDown = macMsg->FHDR.FCnt;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Add difference, consider roll-over
|
||||
fCntDiff = ( int32_t )macMsg->FHDR.FCnt - ( int32_t )( previousDown & 0x0000FFFF );
|
||||
|
||||
if( fCntDiff > 0 )
|
||||
{ // Positive difference
|
||||
*currentDown = previousDown + fCntDiff;
|
||||
}
|
||||
else if( fCntDiff == 0 )
|
||||
{ // Duplicate FCnt value, keep the current value.
|
||||
*currentDown = previousDown;
|
||||
return LORAMAC_FCNT_HANDLER_CHECK_FAIL;
|
||||
}
|
||||
else
|
||||
{ // Negative difference, assume a roll-over of one uint16_t
|
||||
*currentDown = ( previousDown & 0xFFFF0000 ) + 0x10000 + macMsg->FHDR.FCnt;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// For LoRaWAN 1.0.X only, check maxFCntGap
|
||||
if( lrWanVersion.Fields.Minor == 0 )
|
||||
{
|
||||
if( ( ( int32_t )*currentDown - ( int32_t )previousDown ) >= maxFCntGap )
|
||||
{
|
||||
return LORAMAC_FCNT_HANDLER_MAX_GAP_FAIL;
|
||||
}
|
||||
}
|
||||
|
||||
return LORAMAC_FCNT_HANDLER_SUCCESS;
|
||||
}
|
||||
|
||||
LoRaMacFCntHandlerStatus_t LoRaMacSetFCntDown( FCntIdentifier_t fCntID, uint32_t currentDown )
|
||||
{
|
||||
switch( fCntID )
|
||||
{
|
||||
case FCNT_UP:
|
||||
return LORAMAC_FCNT_HANDLER_ERROR_INVALID_FCNT_ID;
|
||||
case N_FCNT_DOWN:
|
||||
FCntHandlerNvmCtx.FCntList.NFCntDown = currentDown;
|
||||
break;
|
||||
case A_FCNT_DOWN:
|
||||
FCntHandlerNvmCtx.FCntList.AFCntDown = currentDown;
|
||||
break;
|
||||
case FCNT_DOWN:
|
||||
FCntHandlerNvmCtx.FCntList.FCntDown = currentDown;
|
||||
break;
|
||||
case MC_FCNT_DOWN_0:
|
||||
FCntHandlerNvmCtx.FCntList.McFCntDown0 = currentDown;
|
||||
break;
|
||||
case MC_FCNT_DOWN_1:
|
||||
FCntHandlerNvmCtx.FCntList.McFCntDown1 = currentDown;
|
||||
break;
|
||||
case MC_FCNT_DOWN_2:
|
||||
FCntHandlerNvmCtx.FCntList.McFCntDown2 = currentDown;
|
||||
break;
|
||||
case MC_FCNT_DOWN_3:
|
||||
FCntHandlerNvmCtx.FCntList.McFCntDown3 = currentDown;
|
||||
break;
|
||||
default:
|
||||
return LORAMAC_FCNT_HANDLER_ERROR;
|
||||
}
|
||||
|
||||
NvmCtxChanged( );
|
||||
|
||||
return LORAMAC_FCNT_HANDLER_SUCCESS;
|
||||
}
|
||||
|
||||
LoRaMacFCntHandlerStatus_t LoRaMacGetFCntUp( uint32_t* currentUp )
|
||||
{
|
||||
if( currentUp == NULL )
|
||||
{
|
||||
return LORAMAC_FCNT_HANDLER_ERROR_NPE;
|
||||
}
|
||||
|
||||
*currentUp = FCntHandlerNvmCtx.FCntList.FCntUp + 1;
|
||||
|
||||
return LORAMAC_FCNT_HANDLER_SUCCESS;
|
||||
}
|
||||
|
||||
LoRaMacFCntHandlerStatus_t LoRaMacSetFCntUp( uint32_t currentUp )
|
||||
{
|
||||
FCntHandlerNvmCtx.FCntList.FCntUp = currentUp;
|
||||
|
||||
NvmCtxChanged( );
|
||||
|
||||
return LORAMAC_FCNT_HANDLER_SUCCESS;
|
||||
}
|
||||
|
||||
LoRaMacFCntHandlerStatus_t LoRaMacResetFCnts( void )
|
||||
{
|
||||
|
||||
FCntHandlerNvmCtx.FCntList.FCntUp = 0;
|
||||
FCntHandlerNvmCtx.FCntList.NFCntDown = FCNT_DOWN_INITAL_VALUE;
|
||||
FCntHandlerNvmCtx.FCntList.AFCntDown = FCNT_DOWN_INITAL_VALUE;
|
||||
FCntHandlerNvmCtx.FCntList.FCntDown = FCNT_DOWN_INITAL_VALUE;
|
||||
|
||||
FCntHandlerNvmCtx.FCntList.McFCntDown0 = FCNT_DOWN_INITAL_VALUE;
|
||||
FCntHandlerNvmCtx.FCntList.McFCntDown1 = FCNT_DOWN_INITAL_VALUE;
|
||||
FCntHandlerNvmCtx.FCntList.McFCntDown2 = FCNT_DOWN_INITAL_VALUE;
|
||||
FCntHandlerNvmCtx.FCntList.McFCntDown3 = FCNT_DOWN_INITAL_VALUE;
|
||||
|
||||
NvmCtxChanged( );
|
||||
|
||||
return LORAMAC_FCNT_HANDLER_SUCCESS;
|
||||
}
|
||||
|
||||
LoRaMacFCntHandlerStatus_t LoRaMacFCntHandlerSetMulticastReference( MulticastCtx_t* multicastList )
|
||||
{
|
||||
if( multicastList == NULL )
|
||||
{
|
||||
return LORAMAC_FCNT_HANDLER_ERROR_NPE;
|
||||
}
|
||||
|
||||
multicastList[0].DownLinkCounter = &FCntHandlerNvmCtx.FCntList.McFCntDown0;
|
||||
multicastList[1].DownLinkCounter = &FCntHandlerNvmCtx.FCntList.McFCntDown1;
|
||||
multicastList[2].DownLinkCounter = &FCntHandlerNvmCtx.FCntList.McFCntDown2;
|
||||
multicastList[3].DownLinkCounter = &FCntHandlerNvmCtx.FCntList.McFCntDown3;
|
||||
|
||||
return LORAMAC_FCNT_HANDLER_SUCCESS;
|
||||
}
|
@@ -1,170 +0,0 @@
|
||||
/*!
|
||||
* \file LoRaMacFCntHandler.h
|
||||
*
|
||||
* \brief LoRa MAC layer frame counter handling
|
||||
*
|
||||
* \copyright Revised BSD License, see section \ref LICENSE.
|
||||
*
|
||||
* \code
|
||||
* ______ _
|
||||
* / _____) _ | |
|
||||
* ( (____ _____ ____ _| |_ _____ ____| |__
|
||||
* \____ \| ___ | (_ _) ___ |/ ___) _ \
|
||||
* _____) ) ____| | | || |_| ____( (___| | | |
|
||||
* (______/|_____)_|_|_| \__)_____)\____)_| |_|
|
||||
* (C)2013 Semtech
|
||||
*
|
||||
* ___ _____ _ ___ _ _____ ___ ___ ___ ___
|
||||
* / __|_ _/_\ / __| |/ / __/ _ \| _ \/ __| __|
|
||||
* \__ \ | |/ _ \ (__| ' <| _| (_) | / (__| _|
|
||||
* |___/ |_/_/ \_\___|_|\_\_| \___/|_|_\\___|___|
|
||||
* embedded.connectivity.solutions===============
|
||||
*
|
||||
* \endcode
|
||||
*
|
||||
* \author Miguel Luis ( Semtech )
|
||||
*
|
||||
* \author Daniel Jaeckle ( STACKFORCE )
|
||||
*
|
||||
* \author Johannes Bruder ( STACKFORCE )
|
||||
*
|
||||
* addtogroup LORAMAC
|
||||
* \{
|
||||
*
|
||||
*/
|
||||
#ifndef __LORAMAC_FCNT_HANDLER_H__
|
||||
#define __LORAMAC_FCNT_HANDLER_H__
|
||||
|
||||
#include <stdint.h>
|
||||
#include "LoRaMacTypes.h"
|
||||
#include "LoRaMacMessageTypes.h"
|
||||
|
||||
/*!
|
||||
* LoRaMac FCnt Handler Status
|
||||
*/
|
||||
typedef enum eLoRaMacFCntHandlerStatus
|
||||
{
|
||||
/*!
|
||||
* No error occurred
|
||||
*/
|
||||
LORAMAC_FCNT_HANDLER_SUCCESS = 0,
|
||||
/*!
|
||||
* FCntUp/Down check failed
|
||||
*/
|
||||
LORAMAC_FCNT_HANDLER_CHECK_FAIL,
|
||||
/*!
|
||||
* The status idicates that the node has lost MAX_FCNT_GAP or more frames
|
||||
*/
|
||||
LORAMAC_FCNT_HANDLER_MAX_GAP_FAIL,
|
||||
/*!
|
||||
* Invalid frame counter identifier exception
|
||||
*/
|
||||
LORAMAC_FCNT_HANDLER_ERROR_INVALID_FCNT_ID,
|
||||
/*!
|
||||
* Null pointer exception
|
||||
*/
|
||||
LORAMAC_FCNT_HANDLER_ERROR_NPE,
|
||||
/*!
|
||||
* Undefined Error occurred
|
||||
*/
|
||||
LORAMAC_FCNT_HANDLER_ERROR,
|
||||
}LoRaMacFCntHandlerStatus_t;
|
||||
|
||||
/*!
|
||||
* Signature of callback function to be called by this module when the
|
||||
* non-volatile needs to be saved.
|
||||
*/
|
||||
typedef void ( *EventNvmCtxChanged )( void );
|
||||
|
||||
/*!
|
||||
* \brief Initialization of LoRaMac FCnt Handler module
|
||||
*
|
||||
* \param[IN] fCntHandlerNvmCtxChanged - Callback function which will be called when the
|
||||
* non-volatile context needs to be saved.
|
||||
*
|
||||
* \retval - Status of the operation
|
||||
*/
|
||||
LoRaMacFCntHandlerStatus_t LoRaMacFCntHandlerInit( EventNvmCtxChanged fCntHandlerNvmCtxChanged );
|
||||
|
||||
/*!
|
||||
* Restores the internal non-volatile context from passed pointer.
|
||||
*
|
||||
* \param[IN] fCntHandlerNvmCtx - Pointer to non-volatile FCnt handler module context to be restored.
|
||||
*
|
||||
* \retval - Status of the operation
|
||||
*/
|
||||
LoRaMacFCntHandlerStatus_t LoRaMacFCntHandlerRestoreNvmCtx( void* fCntHandlerNvmCtx );
|
||||
|
||||
/*!
|
||||
* Returns a pointer to the internal non-volatile context.
|
||||
*
|
||||
* \param[IN] fCntHandlerNvmCtxSize - Size of the module non-volatile context
|
||||
*
|
||||
* \retval - Points to a structure where the module store its non-volatile context
|
||||
*/
|
||||
void* LoRaMacFCntHandlerGetNvmCtx( size_t* fCntHandlerNvmCtxSize );
|
||||
|
||||
/*!
|
||||
* Computes next 32 bit downlink counter value and determines the frame counter ID.
|
||||
*
|
||||
* \param[IN] addrID - Address identifier
|
||||
* \param[IN] fType - Frame type
|
||||
* \param[IN] macMsg - Data message object, holding the current 16 bit transmitted frame counter
|
||||
* \param[IN] lrWanVersion - LoRaWAN version
|
||||
* \param[IN] maxFCntGap - Maximum allowed frame counter difference (only for 1.0.X necessary)
|
||||
* \param[OUT] fCntID - Frame counter identifier
|
||||
* \param[OUT] currentDown - Current downlink counter value
|
||||
*
|
||||
* \retval - Status of the operation
|
||||
*/
|
||||
LoRaMacFCntHandlerStatus_t LoRaMacGetFCntDown( AddressIdentifier_t addrID, FType_t fType, LoRaMacMessageData_t* macMsg, Version_t lrWanVersion,
|
||||
uint16_t maxFCntGap, FCntIdentifier_t* fCntID, uint32_t* currentDown );
|
||||
|
||||
/*!
|
||||
* Sets the downlink counter value according to the counter ID.
|
||||
*
|
||||
* \param[IN] fCntID - Frame counter identifier
|
||||
* \param[IN] currentDown - Current downlink counter value
|
||||
*
|
||||
* \retval - Status of the operation
|
||||
*/
|
||||
LoRaMacFCntHandlerStatus_t LoRaMacSetFCntDown( FCntIdentifier_t fCntID, uint32_t currentDown );
|
||||
|
||||
/*!
|
||||
* Computes next uplink counter value.
|
||||
*
|
||||
* \param[OUT] currentUp - Current uplink counter value
|
||||
*
|
||||
* \retval - Status of the operation
|
||||
*/
|
||||
LoRaMacFCntHandlerStatus_t LoRaMacGetFCntUp( uint32_t* currentUp );
|
||||
|
||||
/*!
|
||||
* Sets the uplink counter value according to the counter ID.
|
||||
*
|
||||
* \param[IN] currentUp - Current uplink counter value
|
||||
*
|
||||
* \retval - Status of the operation
|
||||
*/
|
||||
LoRaMacFCntHandlerStatus_t LoRaMacSetFCntUp( uint32_t currentUp );
|
||||
|
||||
/*!
|
||||
* Resets the value of FCntUp, NFCntDown, AFCntDown and FCntDown to zero
|
||||
*
|
||||
* \retval - Status of the operation
|
||||
*/
|
||||
LoRaMacFCntHandlerStatus_t LoRaMacResetFCnts( void );
|
||||
|
||||
/*!
|
||||
* Sets the reference to the multicast downlink counter
|
||||
*
|
||||
* \param[IN] multicastList Pointer to the multicast list
|
||||
*
|
||||
* \retval - Status of the operation
|
||||
*/
|
||||
LoRaMacFCntHandlerStatus_t LoRaMacFCntHandlerSetMulticastReference( MulticastCtx_t* multicastList );
|
||||
|
||||
/*! \} addtogroup LORAMAC */
|
||||
|
||||
#endif // __LORAMAC_FCNT_HANDLER_H__
|
||||
|
@@ -37,23 +37,160 @@
|
||||
#ifndef __LORAMAC_HEADER_TYPES_H__
|
||||
#define __LORAMAC_HEADER_TYPES_H__
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
/*! Frame header (FHDR) maximum field size */
|
||||
#define LORAMAC_FHDR_MAX_FIELD_SIZE 22
|
||||
/*! MAC header field size */
|
||||
#define LORAMAC_MHDR_FIELD_SIZE 1
|
||||
|
||||
/*! ReJoinType field size */
|
||||
#define LORAMAC_JOIN_TYPE_FIELD_SIZE 1
|
||||
|
||||
/*! Join EUI field size */
|
||||
#define LORAMAC_JOIN_EUI_FIELD_SIZE 8
|
||||
|
||||
/*! Device EUI field size */
|
||||
#define LORAMAC_DEV_EUI_FIELD_SIZE 8
|
||||
|
||||
/*! End-device nonce field size */
|
||||
#define LORAMAC_DEV_NONCE_FIELD_SIZE 2
|
||||
|
||||
/*! Join-server nonce field size */
|
||||
#define LORAMAC_JOIN_NONCE_FIELD_SIZE 3
|
||||
|
||||
/*! RJcount0 field size */
|
||||
#define LORAMAC_RJCOUNT_0_FIELD_SIZE 2
|
||||
|
||||
/*! RJcount1 field size */
|
||||
#define LORAMAC_RJCOUNT_1_FIELD_SIZE 2
|
||||
|
||||
/*! Network ID field size */
|
||||
#define LORAMAC_NET_ID_FIELD_SIZE 3
|
||||
|
||||
/*! Device address field size */
|
||||
#define LORAMAC_DEV_ADDR_FIELD_SIZE 4
|
||||
|
||||
/*! DLSettings field size */
|
||||
#define LORAMAC_DL_SETTINGS_FIELD_SIZE 1
|
||||
|
||||
/*! RxDelay field size */
|
||||
#define LORAMAC_RX_DELAY_FIELD_SIZE 1
|
||||
|
||||
/*! CFList field size */
|
||||
#define LORAMAC_CF_LIST_FIELD_SIZE 16
|
||||
|
||||
/*! FHDR Device address field size */
|
||||
#define LORAMAC_FHDR_DEV_ADD_FIELD_SIZE 4
|
||||
#define LORAMAC_FHDR_DEV_ADDR_FIELD_SIZE LORAMAC_DEV_ADDR_FIELD_SIZE
|
||||
|
||||
/*! FHDR Frame control field size */
|
||||
#define LORAMAC_FHDR_F_CTRL_FIELD_SIZE 1
|
||||
#define LORAMAC_FHDR_F_CTRL_FIELD_SIZE 1
|
||||
|
||||
/*! FHDR Frame control field size */
|
||||
#define LORAMAC_FHDR_F_CNT_FIELD_SIZE 2
|
||||
#define LORAMAC_FHDR_F_CNT_FIELD_SIZE 2
|
||||
|
||||
/*! FOpts maximum field size */
|
||||
#define LORAMAC_FHDR_F_OPTS_MAX_FIELD_SIZE 15
|
||||
#define LORAMAC_FHDR_F_OPTS_MAX_FIELD_SIZE 15
|
||||
|
||||
/*! Port field size */
|
||||
#define LORAMAC_F_PORT_FIELD_SIZE 1
|
||||
|
||||
/*! Port field size */
|
||||
#define LORAMAC_MAC_PAYLOAD_FIELD_MAX_SIZE 242
|
||||
|
||||
/*! MIC field size */
|
||||
#define LORAMAC_MIC_FIELD_SIZE 4
|
||||
|
||||
/*!
|
||||
* JoinRequest frame size
|
||||
*
|
||||
* MHDR(1) + JoinEUI(8) + DevEUI(8) + DevNonce(2) + MIC(4)
|
||||
*/
|
||||
#define LORAMAC_JOIN_REQ_MSG_SIZE ( LORAMAC_MHDR_FIELD_SIZE + LORAMAC_JOIN_EUI_FIELD_SIZE + \
|
||||
LORAMAC_DEV_EUI_FIELD_SIZE + LORAMAC_DEV_NONCE_FIELD_SIZE + \
|
||||
LORAMAC_MIC_FIELD_SIZE )
|
||||
|
||||
/*!
|
||||
* ReJoinRequest type 1 frame size
|
||||
*
|
||||
* MHDR(1) + ReJoinType(1) + JoinEUI(8) + DevEUI(8) + RJcount1(2) + MIC(4)
|
||||
*/
|
||||
#define LORAMAC_RE_JOIN_1_MSG_SIZE ( LORAMAC_MHDR_FIELD_SIZE + LORAMAC_JOIN_TYPE_FIELD_SIZE + \
|
||||
LORAMAC_JOIN_EUI_FIELD_SIZE + LORAMAC_DEV_EUI_FIELD_SIZE + \
|
||||
LORAMAC_RJCOUNT_1_FIELD_SIZE + \
|
||||
LORAMAC_MIC_FIELD_SIZE )
|
||||
|
||||
/*!
|
||||
* ReJoinRequest type 0 or 2 frame size
|
||||
*
|
||||
* MHDR(1) + ReJoinType(1) + NetID(3) + DevEUI(8) + RJcount0(2) + MIC(4)
|
||||
*/
|
||||
#define LORAMAC_RE_JOIN_0_2_MSG_SIZE ( LORAMAC_MHDR_FIELD_SIZE + LORAMAC_JOIN_TYPE_FIELD_SIZE + \
|
||||
LORAMAC_NET_ID_FIELD_SIZE + LORAMAC_DEV_EUI_FIELD_SIZE + \
|
||||
LORAMAC_RJCOUNT_0_FIELD_SIZE + \
|
||||
LORAMAC_MIC_FIELD_SIZE )
|
||||
|
||||
/*!
|
||||
* JoinAccept frame minimum size
|
||||
*
|
||||
* MHDR(1) + AppNonce(3) + NetID(3) + DevAddr(4) + DLSettings(1) + RxDelay(1) + MIC(4)
|
||||
*/
|
||||
#define LORAMAC_JOIN_ACCEPT_FRAME_MIN_SIZE ( LORAMAC_MHDR_FIELD_SIZE + LORAMAC_JOIN_NONCE_FIELD_SIZE + \
|
||||
LORAMAC_NET_ID_FIELD_SIZE + LORAMAC_DEV_ADDR_FIELD_SIZE + \
|
||||
LORAMAC_DL_SETTINGS_FIELD_SIZE + LORAMAC_RX_DELAY_FIELD_SIZE + \
|
||||
LORAMAC_MIC_FIELD_SIZE )
|
||||
|
||||
/*!
|
||||
* JoinAccept frame maximum size
|
||||
*
|
||||
* MHDR(1) + AppNonce(3) + NetID(3) + DevAddr(4) + DLSettings(1) + RxDelay(1) + CFList(16) + MIC(4)
|
||||
*/
|
||||
#define LORAMAC_JOIN_ACCEPT_FRAME_MAX_SIZE ( LORAMAC_MHDR_FIELD_SIZE + LORAMAC_JOIN_NONCE_FIELD_SIZE + \
|
||||
LORAMAC_NET_ID_FIELD_SIZE + LORAMAC_DEV_ADDR_FIELD_SIZE + \
|
||||
LORAMAC_DL_SETTINGS_FIELD_SIZE + LORAMAC_RX_DELAY_FIELD_SIZE + \
|
||||
LORAMAC_CF_LIST_FIELD_SIZE + LORAMAC_MIC_FIELD_SIZE )
|
||||
|
||||
/*!
|
||||
* MIC computation offset
|
||||
* \remark required for 1.1.x support
|
||||
*/
|
||||
#define JOIN_ACCEPT_MIC_COMPUTATION_OFFSET \
|
||||
( LORAMAC_MHDR_FIELD_SIZE + LORAMAC_JOIN_TYPE_FIELD_SIZE + LORAMAC_JOIN_EUI_FIELD_SIZE + \
|
||||
LORAMAC_DEV_NONCE_FIELD_SIZE )
|
||||
|
||||
/*!
|
||||
* FRMPayload overhead to be used when setting the Radio.SetMaxPayloadLength
|
||||
*
|
||||
* Overhead to be used when setting the Radio.SetMaxPayloadLength in RxWindowSetup function.
|
||||
*
|
||||
* MHDR(1) + FHDR(7) + Port(1) + MIC(4)
|
||||
*
|
||||
* Maximum PHYPayload = MaxPayloadOfDatarate + LORAMAC_FRAME_PAYLOAD_OVERHEAD_SIZE
|
||||
*/
|
||||
#define LORAMAC_FRAME_PAYLOAD_OVERHEAD_SIZE ( LORAMAC_MHDR_FIELD_SIZE + ( LORAMAC_FHDR_DEV_ADDR_FIELD_SIZE + \
|
||||
LORAMAC_FHDR_F_CTRL_FIELD_SIZE + LORAMAC_FHDR_F_CNT_FIELD_SIZE ) + \
|
||||
LORAMAC_F_PORT_FIELD_SIZE + LORAMAC_MIC_FIELD_SIZE )
|
||||
|
||||
/*!
|
||||
* FRMPayload minimum size
|
||||
*
|
||||
* MHDR(1) + FHDR(7) + MIC(4)
|
||||
*/
|
||||
#define LORAMAC_FRAME_PAYLOAD_MIN_SIZE ( LORAMAC_MHDR_FIELD_SIZE + ( LORAMAC_FHDR_DEV_ADDR_FIELD_SIZE + \
|
||||
LORAMAC_FHDR_F_CTRL_FIELD_SIZE + LORAMAC_FHDR_F_CNT_FIELD_SIZE ) + \
|
||||
LORAMAC_MIC_FIELD_SIZE )
|
||||
/*!
|
||||
* FRMPayload maximum possible size
|
||||
*
|
||||
* MHDR(1) + FHDR(7) + Port(1) + MACPayload(242) + MIC(4)
|
||||
*/
|
||||
#define LORAMAC_FRAME_PAYLOAD_MAX_SIZE ( LORAMAC_MHDR_FIELD_SIZE + ( LORAMAC_FHDR_DEV_ADDR_FIELD_SIZE + \
|
||||
LORAMAC_FHDR_F_CTRL_FIELD_SIZE + LORAMAC_FHDR_F_CNT_FIELD_SIZE ) + \
|
||||
LORAMAC_F_PORT_FIELD_SIZE + LORAMAC_MAC_PAYLOAD_FIELD_MAX_SIZE + \
|
||||
LORAMAC_MIC_FIELD_SIZE )
|
||||
|
||||
/*!
|
||||
* LoRaMAC field definition of DLSettings
|
||||
@@ -183,4 +320,8 @@ typedef struct sLoRaMacFrameHeader
|
||||
|
||||
/*! \} addtogroup LORAMAC */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // __LORAMAC_HEADER_TYPES_H__
|
||||
|
@@ -37,43 +37,14 @@
|
||||
#ifndef __LORAMAC_MESSAGE_TYPES_H__
|
||||
#define __LORAMAC_MESSAGE_TYPES_H__
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
#include <stdint.h>
|
||||
#include "LoRaMacHeaderTypes.h"
|
||||
|
||||
|
||||
/*! MAC header field size */
|
||||
#define LORAMAC_MHDR_FIELD_SIZE 1
|
||||
|
||||
/*! Join EUI field size */
|
||||
#define LORAMAC_JOIN_EUI_FIELD_SIZE 8
|
||||
|
||||
/*! Device EUI field size */
|
||||
#define LORAMAC_DEV_EUI_FIELD_SIZE 8
|
||||
|
||||
/*! Join-server nonce field size */
|
||||
#define LORAMAC_JOIN_NONCE_FIELD_SIZE 3
|
||||
|
||||
/*! Network ID field size */
|
||||
#define LORAMAC_NET_ID_FIELD_SIZE 3
|
||||
|
||||
/*! Port field size */
|
||||
#define LORAMAC_F_PORT_FIELD_SIZE 1
|
||||
|
||||
/*! CFList field size */
|
||||
#define LORAMAC_C_FLIST_FIELD_SIZE 16
|
||||
|
||||
/*! MIC field size */
|
||||
#define LORAMAC_MIC_FIELD_SIZE 4
|
||||
|
||||
/*! Join-request message size */
|
||||
#define LORAMAC_JOIN_REQ_MSG_SIZE 23
|
||||
|
||||
/*! ReJoin-request type 1 message size */
|
||||
#define LORAMAC_RE_JOIN_1_MSG_SIZE 24
|
||||
|
||||
/*! ReJoin-request type 0 or 2 message size */
|
||||
#define LORAMAC_RE_JOIN_0_2_MSG_SIZE 19
|
||||
|
||||
/*!
|
||||
* LoRaMac type for Join-request message
|
||||
*/
|
||||
@@ -324,4 +295,8 @@ typedef struct sLoRaMacMessage
|
||||
|
||||
/*! \} addtogroup LORAMAC */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // __LORAMAC_MESSAGE_TYPES_H__
|
||||
|
@@ -47,10 +47,10 @@ LoRaMacParserStatus_t LoRaMacParserJoinAccept( LoRaMacMessageJoinAccept_t* macMs
|
||||
|
||||
macMsg->RxDelay = macMsg->Buffer[bufItr++];
|
||||
|
||||
if( ( macMsg->BufSize - LORAMAC_MIC_FIELD_SIZE - bufItr ) == LORAMAC_C_FLIST_FIELD_SIZE )
|
||||
if( ( macMsg->BufSize - LORAMAC_MIC_FIELD_SIZE - bufItr ) == LORAMAC_CF_LIST_FIELD_SIZE )
|
||||
{
|
||||
memcpy1( macMsg->CFList, &macMsg->Buffer[bufItr], LORAMAC_C_FLIST_FIELD_SIZE );
|
||||
bufItr = bufItr + LORAMAC_C_FLIST_FIELD_SIZE;
|
||||
memcpy1( macMsg->CFList, &macMsg->Buffer[bufItr], LORAMAC_CF_LIST_FIELD_SIZE );
|
||||
bufItr = bufItr + LORAMAC_CF_LIST_FIELD_SIZE;
|
||||
}
|
||||
else if( ( macMsg->BufSize - LORAMAC_MIC_FIELD_SIZE - bufItr ) > 0 )
|
||||
{
|
||||
|
@@ -37,6 +37,11 @@
|
||||
#ifndef __LORAMAC_PARSER_H__
|
||||
#define __LORAMAC_PARSER_H__
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
#include <stdint.h>
|
||||
#include "LoRaMacMessageTypes.h"
|
||||
|
||||
@@ -82,5 +87,9 @@ LoRaMacParserStatus_t LoRaMacParserData( LoRaMacMessageData_t *macMsg );
|
||||
|
||||
/*! \} addtogroup LORAMAC */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // __LORAMAC_PARSER_H__
|
||||
|
||||
|
@@ -107,7 +107,7 @@ LoRaMacSerializerStatus_t LoRaMacSerializerReJoinType0or2( LoRaMacMessageReJoinT
|
||||
|
||||
macMsg->Buffer[bufItr++] = macMsg->ReJoinType;
|
||||
|
||||
memcpyr( &macMsg->Buffer[bufItr], macMsg->NetID, LORAMAC_NET_ID_FIELD_SIZE );
|
||||
memcpy1( &macMsg->Buffer[bufItr], macMsg->NetID, LORAMAC_NET_ID_FIELD_SIZE );
|
||||
bufItr += LORAMAC_NET_ID_FIELD_SIZE;
|
||||
|
||||
memcpyr( &macMsg->Buffer[bufItr], macMsg->DevEUI, LORAMAC_DEV_EUI_FIELD_SIZE );
|
||||
@@ -130,23 +130,23 @@ LoRaMacSerializerStatus_t LoRaMacSerializerData( LoRaMacMessageData_t* macMsg )
|
||||
|
||||
// Check macMsg->BufSize
|
||||
uint16_t computedBufSize = LORAMAC_MHDR_FIELD_SIZE
|
||||
+ LORAMAC_FHDR_DEV_ADD_FIELD_SIZE
|
||||
+ LORAMAC_FHDR_DEV_ADDR_FIELD_SIZE
|
||||
+ LORAMAC_FHDR_F_CTRL_FIELD_SIZE
|
||||
+ LORAMAC_FHDR_F_CNT_FIELD_SIZE;
|
||||
|
||||
if( macMsg->FRMPayloadSize == 0 )
|
||||
computedBufSize += macMsg->FHDR.FCtrl.Bits.FOptsLen;
|
||||
|
||||
if( macMsg->FRMPayloadSize > 0 )
|
||||
{
|
||||
if( macMsg->BufSize < computedBufSize )
|
||||
{
|
||||
return LORAMAC_SERIALIZER_ERROR_BUF_SIZE;
|
||||
}
|
||||
computedBufSize += LORAMAC_F_PORT_FIELD_SIZE;
|
||||
}
|
||||
else
|
||||
{ //If FRMPayload >0, FPort field is present.
|
||||
if( macMsg->BufSize < computedBufSize + macMsg->FHDR.FCtrl.Bits.FOptsLen + macMsg->FRMPayloadSize + LORAMAC_F_PORT_FIELD_SIZE )
|
||||
{
|
||||
return LORAMAC_SERIALIZER_ERROR_BUF_SIZE;
|
||||
}
|
||||
|
||||
computedBufSize += macMsg->FRMPayloadSize;
|
||||
computedBufSize += LORAMAC_MIC_FIELD_SIZE;
|
||||
|
||||
if( macMsg->BufSize < computedBufSize )
|
||||
{
|
||||
return LORAMAC_SERIALIZER_ERROR_BUF_SIZE;
|
||||
}
|
||||
|
||||
macMsg->Buffer[bufItr++] = macMsg->MHDR.Value;
|
||||
|
@@ -36,6 +36,11 @@
|
||||
*/
|
||||
#ifndef __LORAMAC_SERIALIZER_H__
|
||||
#define __LORAMAC_SERIALIZER_H__
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
#include <stdint.h>
|
||||
#include "LoRaMacMessageTypes.h"
|
||||
|
||||
@@ -97,5 +102,9 @@ LoRaMacSerializerStatus_t LoRaMacSerializerData( LoRaMacMessageData_t* macMsg );
|
||||
|
||||
/*! \} addtogroup LORAMAC */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // __LORAMAC_SERIALIZER_H__
|
||||
|
||||
|
@@ -36,6 +36,11 @@
|
||||
#ifndef __LORAMACTEST_H__
|
||||
#define __LORAMACTEST_H__
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
/*!
|
||||
* \brief Enabled or disables the duty cycle
|
||||
*
|
||||
@@ -48,4 +53,8 @@ void LoRaMacTestSetDutyCycleOn( bool enable );
|
||||
|
||||
/*! \} defgroup LORAMACTEST */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // __LORAMACTEST_H__
|
||||
|
@@ -35,6 +35,11 @@
|
||||
#ifndef __LORAMAC_TYPES_H__
|
||||
#define __LORAMAC_TYPES_H__
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include "timer.h"
|
||||
@@ -47,7 +52,34 @@
|
||||
/*!
|
||||
* Start value for multicast keys enumeration
|
||||
*/
|
||||
#define LORAMAC_CRYPTO_MULITCAST_KEYS 127
|
||||
#define LORAMAC_CRYPTO_MULTICAST_KEYS 127
|
||||
|
||||
/*!
|
||||
* LoRaWAN devices classes definition
|
||||
*
|
||||
* LoRaWAN Specification V1.0.2, chapter 2.1
|
||||
*/
|
||||
typedef enum DeviceClass_e
|
||||
{
|
||||
/*!
|
||||
* LoRaWAN device class A
|
||||
*
|
||||
* LoRaWAN Specification V1.0.2, chapter 3
|
||||
*/
|
||||
CLASS_A = 0x00,
|
||||
/*!
|
||||
* LoRaWAN device class B
|
||||
*
|
||||
* LoRaWAN Specification V1.0.2, chapter 8
|
||||
*/
|
||||
CLASS_B = 0x01,
|
||||
/*!
|
||||
* LoRaWAN device class C
|
||||
*
|
||||
* LoRaWAN Specification V1.0.2, chapter 17
|
||||
*/
|
||||
CLASS_C = 0x02,
|
||||
}DeviceClass_t;
|
||||
|
||||
/*!
|
||||
* LoRaWAN Frame type enumeration to differ between the possible data up/down frame configurations.
|
||||
@@ -162,10 +194,14 @@ typedef enum eKeyIdentifier
|
||||
* Application session key
|
||||
*/
|
||||
APP_S_KEY,
|
||||
/*!
|
||||
* Multicast root key
|
||||
*/
|
||||
MC_ROOT_KEY,
|
||||
/*!
|
||||
* Multicast key encryption key
|
||||
*/
|
||||
MC_KE_KEY = LORAMAC_CRYPTO_MULITCAST_KEYS,
|
||||
MC_KE_KEY = LORAMAC_CRYPTO_MULTICAST_KEYS,
|
||||
/*!
|
||||
* Multicast root key index 0
|
||||
*/
|
||||
@@ -251,40 +287,121 @@ typedef enum eAddressIdentifier
|
||||
UNICAST_DEV_ADDR = 4,
|
||||
}AddressIdentifier_t;
|
||||
|
||||
/*!
|
||||
* Multicast context
|
||||
/*
|
||||
* Multicast Rx window parameters
|
||||
*/
|
||||
typedef struct sMulticastCtx
|
||||
typedef union uMcRxParams
|
||||
{
|
||||
struct
|
||||
{
|
||||
/*!
|
||||
* Reception frequency of the ping slot windows
|
||||
*/
|
||||
uint32_t Frequency;
|
||||
/*!
|
||||
* Datarate of the ping slot
|
||||
*/
|
||||
int8_t Datarate;
|
||||
/*!
|
||||
* This parameter is necessary for class B operation. It defines the
|
||||
* periodicity of the multicast downlink slots
|
||||
*/
|
||||
uint16_t Periodicity;
|
||||
}ClassB;
|
||||
struct
|
||||
{
|
||||
/*!
|
||||
* Reception frequency of the ping slot windows
|
||||
*/
|
||||
uint32_t Frequency;
|
||||
/*!
|
||||
* Datarate of the ping slot
|
||||
*/
|
||||
int8_t Datarate;
|
||||
}ClassC;
|
||||
}McRxParams_t;
|
||||
|
||||
/*!
|
||||
* Multicast channel
|
||||
*/
|
||||
typedef struct sMcChannelParams
|
||||
{
|
||||
/*!
|
||||
* Indicate if the multicast channel is being setup remotely or locally.
|
||||
* Indicates which set of keys are to be used. \ref uMcKeys
|
||||
*/
|
||||
bool IsRemotelySetup;
|
||||
/*!
|
||||
* Multicats channel LoRaWAN class B or C
|
||||
*/
|
||||
DeviceClass_t Class;
|
||||
/*!
|
||||
* True if the entry is active
|
||||
*/
|
||||
bool IsEnabled;
|
||||
/*
|
||||
* Address identifier
|
||||
*/
|
||||
AddressIdentifier_t AddrID;
|
||||
AddressIdentifier_t GroupID;
|
||||
/*!
|
||||
* Address
|
||||
*/
|
||||
uint32_t Address;
|
||||
/*!
|
||||
* Multicast keys
|
||||
*/
|
||||
union uMcKeys
|
||||
{
|
||||
/*!
|
||||
* Encrypted multicast key - Used when IsRemotelySetup equals `true`.
|
||||
* MC_KEY is decrypted and then the session keys ar derived.
|
||||
*/
|
||||
uint8_t *McKeyE;
|
||||
/*!
|
||||
* Multicast Session keys - Used when IsRemotelySetup equals `false`
|
||||
*/
|
||||
struct
|
||||
{
|
||||
/*!
|
||||
* Multicast application session key
|
||||
*/
|
||||
uint8_t *McAppSKey;
|
||||
/*!
|
||||
* Multicast network session key
|
||||
*/
|
||||
uint8_t *McNwkSKey;
|
||||
}Session;
|
||||
}McKeys;
|
||||
/*!
|
||||
* Minimum multicast frame counter value
|
||||
*/
|
||||
uint32_t FCountMin;
|
||||
/*!
|
||||
* Maximum multicast frame counter value
|
||||
*/
|
||||
uint32_t FCountMax;
|
||||
/*!
|
||||
* Multicast reception parameters
|
||||
*/
|
||||
McRxParams_t RxParams;
|
||||
}McChannelParams_t;
|
||||
|
||||
/*!
|
||||
* Multicast context
|
||||
*/
|
||||
typedef struct sMulticastCtx
|
||||
{
|
||||
/*!
|
||||
* Multicast channel parameters
|
||||
*/
|
||||
McChannelParams_t ChannelParams;
|
||||
/*!
|
||||
* Downlink counter
|
||||
*/
|
||||
uint32_t* DownLinkCounter;
|
||||
/*!
|
||||
* True if the entry is active
|
||||
/*
|
||||
* Following parameters are only used for ClassB multicast channels
|
||||
*/
|
||||
bool IsEnabled;
|
||||
/*!
|
||||
* Reception frequency of the ping slot windows
|
||||
*/
|
||||
uint32_t Frequency;
|
||||
/*!
|
||||
* Datarate of the ping slot
|
||||
*/
|
||||
int8_t Datarate;
|
||||
/*!
|
||||
* This parameter is necessary for class b operation. It defines the
|
||||
* periodicity of the multicast downlink slots
|
||||
*/
|
||||
uint16_t Periodicity;
|
||||
/*!
|
||||
* Number of multicast slots. The variable can be
|
||||
* calculated as follows:
|
||||
@@ -475,17 +592,24 @@ typedef struct sBand
|
||||
*/
|
||||
int8_t TxMaxPower;
|
||||
/*!
|
||||
* Time stamp of the last JoinReq Tx frame.
|
||||
* The last time the band has been
|
||||
* synchronized with the current time
|
||||
*/
|
||||
TimerTime_t LastJoinTxDoneTime;
|
||||
TimerTime_t LastBandUpdateTime;
|
||||
/*!
|
||||
* Time stamp of the last Tx frame
|
||||
* Current time credits which are available. This
|
||||
* is a value in ms
|
||||
*/
|
||||
TimerTime_t LastTxDoneTime;
|
||||
TimerTime_t TimeCredits;
|
||||
/*!
|
||||
* Holds the time where the device is off
|
||||
* Maximum time credits which are available. This
|
||||
* is a value in ms
|
||||
*/
|
||||
TimerTime_t TimeOff;
|
||||
TimerTime_t MaxTimeCredits;
|
||||
/*!
|
||||
* Set to true when the band is ready for use.
|
||||
*/
|
||||
bool ReadyForTransmission;
|
||||
}Band_t;
|
||||
|
||||
/*!
|
||||
@@ -548,5 +672,9 @@ typedef enum eLoRaMacBatteryLevel
|
||||
BAT_LEVEL_NO_MEASURE = 0xFF,
|
||||
}LoRaMacBatteryLevel_t;
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // __LORAMAC_TYPES_H__
|
||||
|
||||
|
@@ -51,7 +51,6 @@
|
||||
#define AS923_TX_PARAM_SETUP_REQ( ) AS923_CASE { return RegionAS923TxParamSetupReq( txParamSetupReq ); }
|
||||
#define AS923_DL_CHANNEL_REQ( ) AS923_CASE { return RegionAS923DlChannelReq( dlChannelReq ); }
|
||||
#define AS923_ALTERNATE_DR( ) AS923_CASE { return RegionAS923AlternateDr( currentDr, type ); }
|
||||
#define AS923_CALC_BACKOFF( ) AS923_CASE { RegionAS923CalcBackOff( calcBackOff ); break; }
|
||||
#define AS923_NEXT_CHANNEL( ) AS923_CASE { return RegionAS923NextChannel( nextChanParams, channel, time, aggregatedTimeOff ); }
|
||||
#define AS923_CHANNEL_ADD( ) AS923_CASE { return RegionAS923ChannelAdd( channelAdd ); }
|
||||
#define AS923_CHANNEL_REMOVE( ) AS923_CASE { return RegionAS923ChannelsRemove( channelRemove ); }
|
||||
@@ -76,7 +75,6 @@
|
||||
#define AS923_TX_PARAM_SETUP_REQ( )
|
||||
#define AS923_DL_CHANNEL_REQ( )
|
||||
#define AS923_ALTERNATE_DR( )
|
||||
#define AS923_CALC_BACKOFF( )
|
||||
#define AS923_NEXT_CHANNEL( )
|
||||
#define AS923_CHANNEL_ADD( )
|
||||
#define AS923_CHANNEL_REMOVE( )
|
||||
@@ -105,7 +103,6 @@
|
||||
#define AU915_TX_PARAM_SETUP_REQ( ) AU915_CASE { return RegionAU915TxParamSetupReq( txParamSetupReq ); }
|
||||
#define AU915_DL_CHANNEL_REQ( ) AU915_CASE { return RegionAU915DlChannelReq( dlChannelReq ); }
|
||||
#define AU915_ALTERNATE_DR( ) AU915_CASE { return RegionAU915AlternateDr( currentDr, type ); }
|
||||
#define AU915_CALC_BACKOFF( ) AU915_CASE { RegionAU915CalcBackOff( calcBackOff ); break; }
|
||||
#define AU915_NEXT_CHANNEL( ) AU915_CASE { return RegionAU915NextChannel( nextChanParams, channel, time, aggregatedTimeOff ); }
|
||||
#define AU915_CHANNEL_ADD( ) AU915_CASE { return RegionAU915ChannelAdd( channelAdd ); }
|
||||
#define AU915_CHANNEL_REMOVE( ) AU915_CASE { return RegionAU915ChannelsRemove( channelRemove ); }
|
||||
@@ -130,7 +127,6 @@
|
||||
#define AU915_TX_PARAM_SETUP_REQ( )
|
||||
#define AU915_DL_CHANNEL_REQ( )
|
||||
#define AU915_ALTERNATE_DR( )
|
||||
#define AU915_CALC_BACKOFF( )
|
||||
#define AU915_NEXT_CHANNEL( )
|
||||
#define AU915_CHANNEL_ADD( )
|
||||
#define AU915_CHANNEL_REMOVE( )
|
||||
@@ -159,7 +155,6 @@
|
||||
#define CN470_TX_PARAM_SETUP_REQ( ) CN470_CASE { return RegionCN470TxParamSetupReq( txParamSetupReq ); }
|
||||
#define CN470_DL_CHANNEL_REQ( ) CN470_CASE { return RegionCN470DlChannelReq( dlChannelReq ); }
|
||||
#define CN470_ALTERNATE_DR( ) CN470_CASE { return RegionCN470AlternateDr( currentDr, type ); }
|
||||
#define CN470_CALC_BACKOFF( ) CN470_CASE { RegionCN470CalcBackOff( calcBackOff ); break; }
|
||||
#define CN470_NEXT_CHANNEL( ) CN470_CASE { return RegionCN470NextChannel( nextChanParams, channel, time, aggregatedTimeOff ); }
|
||||
#define CN470_CHANNEL_ADD( ) CN470_CASE { return RegionCN470ChannelAdd( channelAdd ); }
|
||||
#define CN470_CHANNEL_REMOVE( ) CN470_CASE { return RegionCN470ChannelsRemove( channelRemove ); }
|
||||
@@ -184,7 +179,6 @@
|
||||
#define CN470_TX_PARAM_SETUP_REQ( )
|
||||
#define CN470_DL_CHANNEL_REQ( )
|
||||
#define CN470_ALTERNATE_DR( )
|
||||
#define CN470_CALC_BACKOFF( )
|
||||
#define CN470_NEXT_CHANNEL( )
|
||||
#define CN470_CHANNEL_ADD( )
|
||||
#define CN470_CHANNEL_REMOVE( )
|
||||
@@ -213,7 +207,6 @@
|
||||
#define CN779_TX_PARAM_SETUP_REQ( ) CN779_CASE { return RegionCN779TxParamSetupReq( txParamSetupReq ); }
|
||||
#define CN779_DL_CHANNEL_REQ( ) CN779_CASE { return RegionCN779DlChannelReq( dlChannelReq ); }
|
||||
#define CN779_ALTERNATE_DR( ) CN779_CASE { return RegionCN779AlternateDr( currentDr, type ); }
|
||||
#define CN779_CALC_BACKOFF( ) CN779_CASE { RegionCN779CalcBackOff( calcBackOff ); break; }
|
||||
#define CN779_NEXT_CHANNEL( ) CN779_CASE { return RegionCN779NextChannel( nextChanParams, channel, time, aggregatedTimeOff ); }
|
||||
#define CN779_CHANNEL_ADD( ) CN779_CASE { return RegionCN779ChannelAdd( channelAdd ); }
|
||||
#define CN779_CHANNEL_REMOVE( ) CN779_CASE { return RegionCN779ChannelsRemove( channelRemove ); }
|
||||
@@ -238,7 +231,6 @@
|
||||
#define CN779_TX_PARAM_SETUP_REQ( )
|
||||
#define CN779_DL_CHANNEL_REQ( )
|
||||
#define CN779_ALTERNATE_DR( )
|
||||
#define CN779_CALC_BACKOFF( )
|
||||
#define CN779_NEXT_CHANNEL( )
|
||||
#define CN779_CHANNEL_ADD( )
|
||||
#define CN779_CHANNEL_REMOVE( )
|
||||
@@ -267,7 +259,6 @@
|
||||
#define EU433_TX_PARAM_SETUP_REQ( ) EU433_CASE { return RegionEU433TxParamSetupReq( txParamSetupReq ); }
|
||||
#define EU433_DL_CHANNEL_REQ( ) EU433_CASE { return RegionEU433DlChannelReq( dlChannelReq ); }
|
||||
#define EU433_ALTERNATE_DR( ) EU433_CASE { return RegionEU433AlternateDr( currentDr, type ); }
|
||||
#define EU433_CALC_BACKOFF( ) EU433_CASE { RegionEU433CalcBackOff( calcBackOff ); break; }
|
||||
#define EU433_NEXT_CHANNEL( ) EU433_CASE { return RegionEU433NextChannel( nextChanParams, channel, time, aggregatedTimeOff ); }
|
||||
#define EU433_CHANNEL_ADD( ) EU433_CASE { return RegionEU433ChannelAdd( channelAdd ); }
|
||||
#define EU433_CHANNEL_REMOVE( ) EU433_CASE { return RegionEU433ChannelsRemove( channelRemove ); }
|
||||
@@ -292,7 +283,6 @@
|
||||
#define EU433_TX_PARAM_SETUP_REQ( )
|
||||
#define EU433_DL_CHANNEL_REQ( )
|
||||
#define EU433_ALTERNATE_DR( )
|
||||
#define EU433_CALC_BACKOFF( )
|
||||
#define EU433_NEXT_CHANNEL( )
|
||||
#define EU433_CHANNEL_ADD( )
|
||||
#define EU433_CHANNEL_REMOVE( )
|
||||
@@ -321,7 +311,6 @@
|
||||
#define EU868_TX_PARAM_SETUP_REQ( ) EU868_CASE { return RegionEU868TxParamSetupReq( txParamSetupReq ); }
|
||||
#define EU868_DL_CHANNEL_REQ( ) EU868_CASE { return RegionEU868DlChannelReq( dlChannelReq ); }
|
||||
#define EU868_ALTERNATE_DR( ) EU868_CASE { return RegionEU868AlternateDr( currentDr, type ); }
|
||||
#define EU868_CALC_BACKOFF( ) EU868_CASE { RegionEU868CalcBackOff( calcBackOff ); break; }
|
||||
#define EU868_NEXT_CHANNEL( ) EU868_CASE { return RegionEU868NextChannel( nextChanParams, channel, time, aggregatedTimeOff ); }
|
||||
#define EU868_CHANNEL_ADD( ) EU868_CASE { return RegionEU868ChannelAdd( channelAdd ); }
|
||||
#define EU868_CHANNEL_REMOVE( ) EU868_CASE { return RegionEU868ChannelsRemove( channelRemove ); }
|
||||
@@ -346,7 +335,6 @@
|
||||
#define EU868_TX_PARAM_SETUP_REQ( )
|
||||
#define EU868_DL_CHANNEL_REQ( )
|
||||
#define EU868_ALTERNATE_DR( )
|
||||
#define EU868_CALC_BACKOFF( )
|
||||
#define EU868_NEXT_CHANNEL( )
|
||||
#define EU868_CHANNEL_ADD( )
|
||||
#define EU868_CHANNEL_REMOVE( )
|
||||
@@ -375,7 +363,6 @@
|
||||
#define KR920_TX_PARAM_SETUP_REQ( ) KR920_CASE { return RegionKR920TxParamSetupReq( txParamSetupReq ); }
|
||||
#define KR920_DL_CHANNEL_REQ( ) KR920_CASE { return RegionKR920DlChannelReq( dlChannelReq ); }
|
||||
#define KR920_ALTERNATE_DR( ) KR920_CASE { return RegionKR920AlternateDr( currentDr, type ); }
|
||||
#define KR920_CALC_BACKOFF( ) KR920_CASE { RegionKR920CalcBackOff( calcBackOff ); break; }
|
||||
#define KR920_NEXT_CHANNEL( ) KR920_CASE { return RegionKR920NextChannel( nextChanParams, channel, time, aggregatedTimeOff ); }
|
||||
#define KR920_CHANNEL_ADD( ) KR920_CASE { return RegionKR920ChannelAdd( channelAdd ); }
|
||||
#define KR920_CHANNEL_REMOVE( ) KR920_CASE { return RegionKR920ChannelsRemove( channelRemove ); }
|
||||
@@ -400,7 +387,6 @@
|
||||
#define KR920_TX_PARAM_SETUP_REQ( )
|
||||
#define KR920_DL_CHANNEL_REQ( )
|
||||
#define KR920_ALTERNATE_DR( )
|
||||
#define KR920_CALC_BACKOFF( )
|
||||
#define KR920_NEXT_CHANNEL( )
|
||||
#define KR920_CHANNEL_ADD( )
|
||||
#define KR920_CHANNEL_REMOVE( )
|
||||
@@ -429,7 +415,6 @@
|
||||
#define IN865_TX_PARAM_SETUP_REQ( ) IN865_CASE { return RegionIN865TxParamSetupReq( txParamSetupReq ); }
|
||||
#define IN865_DL_CHANNEL_REQ( ) IN865_CASE { return RegionIN865DlChannelReq( dlChannelReq ); }
|
||||
#define IN865_ALTERNATE_DR( ) IN865_CASE { return RegionIN865AlternateDr( currentDr, type ); }
|
||||
#define IN865_CALC_BACKOFF( ) IN865_CASE { RegionIN865CalcBackOff( calcBackOff ); break; }
|
||||
#define IN865_NEXT_CHANNEL( ) IN865_CASE { return RegionIN865NextChannel( nextChanParams, channel, time, aggregatedTimeOff ); }
|
||||
#define IN865_CHANNEL_ADD( ) IN865_CASE { return RegionIN865ChannelAdd( channelAdd ); }
|
||||
#define IN865_CHANNEL_REMOVE( ) IN865_CASE { return RegionIN865ChannelsRemove( channelRemove ); }
|
||||
@@ -454,7 +439,6 @@
|
||||
#define IN865_TX_PARAM_SETUP_REQ( )
|
||||
#define IN865_DL_CHANNEL_REQ( )
|
||||
#define IN865_ALTERNATE_DR( )
|
||||
#define IN865_CALC_BACKOFF( )
|
||||
#define IN865_NEXT_CHANNEL( )
|
||||
#define IN865_CHANNEL_ADD( )
|
||||
#define IN865_CHANNEL_REMOVE( )
|
||||
@@ -483,7 +467,6 @@
|
||||
#define US915_TX_PARAM_SETUP_REQ( ) US915_CASE { return RegionUS915TxParamSetupReq( txParamSetupReq ); }
|
||||
#define US915_DL_CHANNEL_REQ( ) US915_CASE { return RegionUS915DlChannelReq( dlChannelReq ); }
|
||||
#define US915_ALTERNATE_DR( ) US915_CASE { return RegionUS915AlternateDr( currentDr, type ); }
|
||||
#define US915_CALC_BACKOFF( ) US915_CASE { RegionUS915CalcBackOff( calcBackOff ); break; }
|
||||
#define US915_NEXT_CHANNEL( ) US915_CASE { return RegionUS915NextChannel( nextChanParams, channel, time, aggregatedTimeOff ); }
|
||||
#define US915_CHANNEL_ADD( ) US915_CASE { return RegionUS915ChannelAdd( channelAdd ); }
|
||||
#define US915_CHANNEL_REMOVE( ) US915_CASE { return RegionUS915ChannelsRemove( channelRemove ); }
|
||||
@@ -508,7 +491,6 @@
|
||||
#define US915_TX_PARAM_SETUP_REQ( )
|
||||
#define US915_DL_CHANNEL_REQ( )
|
||||
#define US915_ALTERNATE_DR( )
|
||||
#define US915_CALC_BACKOFF( )
|
||||
#define US915_NEXT_CHANNEL( )
|
||||
#define US915_CHANNEL_ADD( )
|
||||
#define US915_CHANNEL_REMOVE( )
|
||||
@@ -537,7 +519,6 @@
|
||||
#define RU864_TX_PARAM_SETUP_REQ( ) RU864_CASE { return RegionRU864TxParamSetupReq( txParamSetupReq ); }
|
||||
#define RU864_DL_CHANNEL_REQ( ) RU864_CASE { return RegionRU864DlChannelReq( dlChannelReq ); }
|
||||
#define RU864_ALTERNATE_DR( ) RU864_CASE { return RegionRU864AlternateDr( currentDr, type ); }
|
||||
#define RU864_CALC_BACKOFF( ) RU864_CASE { RegionRU864CalcBackOff( calcBackOff ); break; }
|
||||
#define RU864_NEXT_CHANNEL( ) RU864_CASE { return RegionRU864NextChannel( nextChanParams, channel, time, aggregatedTimeOff ); }
|
||||
#define RU864_CHANNEL_ADD( ) RU864_CASE { return RegionRU864ChannelAdd( channelAdd ); }
|
||||
#define RU864_CHANNEL_REMOVE( ) RU864_CASE { return RegionRU864ChannelsRemove( channelRemove ); }
|
||||
@@ -562,7 +543,6 @@
|
||||
#define RU864_TX_PARAM_SETUP_REQ( )
|
||||
#define RU864_DL_CHANNEL_REQ( )
|
||||
#define RU864_ALTERNATE_DR( )
|
||||
#define RU864_CALC_BACKOFF( )
|
||||
#define RU864_NEXT_CHANNEL( )
|
||||
#define RU864_CHANNEL_ADD( )
|
||||
#define RU864_CHANNEL_REMOVE( )
|
||||
@@ -929,27 +909,6 @@ int8_t RegionAlternateDr( LoRaMacRegion_t region, int8_t currentDr, AlternateDrT
|
||||
}
|
||||
}
|
||||
|
||||
void RegionCalcBackOff( LoRaMacRegion_t region, CalcBackOffParams_t* calcBackOff )
|
||||
{
|
||||
switch( region )
|
||||
{
|
||||
AS923_CALC_BACKOFF( );
|
||||
AU915_CALC_BACKOFF( );
|
||||
CN470_CALC_BACKOFF( );
|
||||
CN779_CALC_BACKOFF( );
|
||||
EU433_CALC_BACKOFF( );
|
||||
EU868_CALC_BACKOFF( );
|
||||
KR920_CALC_BACKOFF( );
|
||||
IN865_CALC_BACKOFF( );
|
||||
US915_CALC_BACKOFF( );
|
||||
RU864_CALC_BACKOFF( );
|
||||
default:
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
LoRaMacStatus_t RegionNextChannel( LoRaMacRegion_t region, NextChanParams_t* nextChanParams, uint8_t* channel, TimerTime_t* time, TimerTime_t* aggregatedTimeOff )
|
||||
{
|
||||
switch( region )
|
||||
@@ -1075,3 +1034,13 @@ void RegionRxBeaconSetup( LoRaMacRegion_t region, RxBeaconSetup_t* rxBeaconSetup
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Version_t RegionGetVersion( void )
|
||||
{
|
||||
Version_t version;
|
||||
|
||||
version.Value = REGION_VERSION;
|
||||
|
||||
return version;
|
||||
}
|
||||
|
||||
|
@@ -52,17 +52,32 @@
|
||||
#ifndef __REGION_H__
|
||||
#define __REGION_H__
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include "utilities.h"
|
||||
#include "LoRaMac.h"
|
||||
#include "timer.h"
|
||||
#include "RegionCommon.h"
|
||||
|
||||
/*!
|
||||
* Macro to compute bit of a channel index.
|
||||
*/
|
||||
#define LC( channelIndex ) ( uint16_t )( 1 << ( channelIndex - 1 ) )
|
||||
|
||||
#ifndef REGION_VERSION
|
||||
/*!
|
||||
* Regional parameters version definition.
|
||||
*/
|
||||
#define REGION_VERSION 0x00010003
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
/*!
|
||||
* Region | SF
|
||||
* ------------ | :-----:
|
||||
@@ -476,7 +491,7 @@
|
||||
* EU868 | -
|
||||
* IN865 | Max EIRP - 18
|
||||
* KR920 | -
|
||||
* US915 | Max ERP - 16
|
||||
* US915 | Max ERP - 18
|
||||
* RU864 | -
|
||||
*/
|
||||
#define TX_POWER_9 9
|
||||
@@ -492,28 +507,72 @@
|
||||
* EU868 | -
|
||||
* IN865 | Max EIRP - 20
|
||||
* KR920 | -
|
||||
* US915 | Max ERP - 10
|
||||
* US915 | Max ERP - 20
|
||||
* RU864 | -
|
||||
*/
|
||||
#define TX_POWER_10 10
|
||||
|
||||
/*!
|
||||
* RFU
|
||||
* Region | dBM
|
||||
* ------------ | :-----:
|
||||
* AS923 | -
|
||||
* AU915 | Max EIRP - 22
|
||||
* CN470 | -
|
||||
* CN779 | -
|
||||
* EU433 | -
|
||||
* EU868 | -
|
||||
* IN865 | -
|
||||
* KR920 | -
|
||||
* US915 | Max ERP - 22
|
||||
* RU864 | -
|
||||
*/
|
||||
#define TX_POWER_11 11
|
||||
|
||||
/*!
|
||||
* RFU
|
||||
* Region | dBM
|
||||
* ------------ | :-----:
|
||||
* AS923 | -
|
||||
* AU915 | Max EIRP - 24
|
||||
* CN470 | -
|
||||
* CN779 | -
|
||||
* EU433 | -
|
||||
* EU868 | -
|
||||
* IN865 | -
|
||||
* KR920 | -
|
||||
* US915 | Max ERP - 24
|
||||
* RU864 | -
|
||||
*/
|
||||
#define TX_POWER_12 12
|
||||
|
||||
/*!
|
||||
* RFU
|
||||
* Region | dBM
|
||||
* ------------ | :-----:
|
||||
* AS923 | -
|
||||
* AU915 | Max EIRP - 26
|
||||
* CN470 | -
|
||||
* CN779 | -
|
||||
* EU433 | -
|
||||
* EU868 | -
|
||||
* IN865 | -
|
||||
* KR920 | -
|
||||
* US915 | Max ERP - 26
|
||||
* RU864 | -
|
||||
*/
|
||||
#define TX_POWER_13 13
|
||||
|
||||
/*!
|
||||
* RFU
|
||||
* Region | dBM
|
||||
* ------------ | :-----:
|
||||
* AS923 | -
|
||||
* AU915 | Max EIRP - 28
|
||||
* CN470 | -
|
||||
* CN779 | -
|
||||
* EU433 | -
|
||||
* EU868 | -
|
||||
* IN865 | -
|
||||
* KR920 | -
|
||||
* US915 | Max ERP - 28
|
||||
* RU864 | -
|
||||
*/
|
||||
#define TX_POWER_14 14
|
||||
|
||||
@@ -529,6 +588,11 @@
|
||||
*/
|
||||
typedef enum ePhyAttribute
|
||||
{
|
||||
/*!
|
||||
* Frequency. It is available
|
||||
* to perform a verification with RegionVerify().
|
||||
*/
|
||||
PHY_FREQUENCY,
|
||||
/*!
|
||||
* Minimum RX datarate.
|
||||
*/
|
||||
@@ -585,10 +649,6 @@ typedef enum ePhyAttribute
|
||||
* Maximum payload possible.
|
||||
*/
|
||||
PHY_MAX_PAYLOAD,
|
||||
/*!
|
||||
* Maximum payload possible when repeater support is enabled.
|
||||
*/
|
||||
PHY_MAX_PAYLOAD_REPEATER,
|
||||
/*!
|
||||
* Duty cycle.
|
||||
*/
|
||||
@@ -743,10 +803,26 @@ typedef enum ePhyAttribute
|
||||
* The number of channels for the beacon reception.
|
||||
*/
|
||||
PHY_BEACON_NB_CHANNELS,
|
||||
/*!
|
||||
* Ping slot channel frequency.
|
||||
*/
|
||||
PHY_PING_SLOT_CHANNEL_FREQ,
|
||||
/*!
|
||||
* The datarate of a ping slot channel.
|
||||
*/
|
||||
PHY_PING_SLOT_CHANNEL_DR
|
||||
PHY_PING_SLOT_CHANNEL_DR,
|
||||
/*
|
||||
* The number of channels for the ping slot reception.
|
||||
*/
|
||||
PHY_PING_SLOT_NB_CHANNELS,
|
||||
/*!
|
||||
* The equivalent spreading factor value from datarate
|
||||
*/
|
||||
PHY_SF_FROM_DR,
|
||||
/*!
|
||||
* The equivalent bandwith index from datarate
|
||||
*/
|
||||
PHY_BW_FROM_DR,
|
||||
}PhyAttribute_t;
|
||||
|
||||
/*!
|
||||
@@ -754,6 +830,10 @@ typedef enum ePhyAttribute
|
||||
*/
|
||||
typedef enum eInitType
|
||||
{
|
||||
/*!
|
||||
* Initializes the band definitions.
|
||||
*/
|
||||
INIT_TYPE_BANDS,
|
||||
/*!
|
||||
* Initializes the region specific data to defaults, according to the
|
||||
* LoRaWAN specification.
|
||||
@@ -825,6 +905,10 @@ typedef union uPhyParam
|
||||
* Beacon format
|
||||
*/
|
||||
BeaconFormat_t BeaconFormat;
|
||||
/*!
|
||||
* Duty Cycle Period
|
||||
*/
|
||||
TimerTime_t DutyCycleTimePeriod;
|
||||
}PhyParam_t;
|
||||
|
||||
/*!
|
||||
@@ -839,23 +923,29 @@ typedef struct sGetPhyParams
|
||||
/*!
|
||||
* Datarate.
|
||||
* The parameter is needed for the following queries:
|
||||
* PHY_MAX_PAYLOAD, PHY_MAX_PAYLOAD_REPEATER, PHY_NEXT_LOWER_TX_DR.
|
||||
* PHY_MAX_PAYLOAD, PHY_NEXT_LOWER_TX_DR, PHY_SF_FROM_DR, PHY_BW_FROM_DR.
|
||||
*/
|
||||
int8_t Datarate;
|
||||
/*!
|
||||
* Uplink dwell time. This parameter must be set to query:
|
||||
* PHY_MAX_PAYLOAD, PHY_MAX_PAYLOAD_REPEATER, PHY_MIN_TX_DR.
|
||||
* PHY_MAX_PAYLOAD, PHY_MIN_TX_DR.
|
||||
* The parameter is needed for the following queries:
|
||||
* PHY_MIN_TX_DR, PHY_MAX_PAYLOAD, PHY_MAX_PAYLOAD_REPEATER, PHY_NEXT_LOWER_TX_DR.
|
||||
* PHY_MIN_TX_DR, PHY_MAX_PAYLOAD, PHY_NEXT_LOWER_TX_DR.
|
||||
*/
|
||||
uint8_t UplinkDwellTime;
|
||||
/*!
|
||||
* Downlink dwell time. This parameter must be set to query:
|
||||
* PHY_MAX_PAYLOAD, PHY_MAX_PAYLOAD_REPEATER, PHY_MIN_RX_DR.
|
||||
* PHY_MAX_PAYLOAD, PHY_MIN_RX_DR.
|
||||
* The parameter is needed for the following queries:
|
||||
* PHY_MIN_RX_DR, PHY_MAX_PAYLOAD, PHY_MAX_PAYLOAD_REPEATER.
|
||||
* PHY_MIN_RX_DR, PHY_MAX_PAYLOAD.
|
||||
*/
|
||||
uint8_t DownlinkDwellTime;
|
||||
/*!
|
||||
* Specification of the downlink channel. Used in Class B only.
|
||||
* The parameter is needed for the following queries:
|
||||
* PHY_BEACON_CHANNEL_FREQ, PHY_PING_SLOT_CHANNEL_FREQ
|
||||
*/
|
||||
uint8_t Channel;
|
||||
}GetPhyParams_t;
|
||||
|
||||
/*!
|
||||
@@ -875,6 +965,14 @@ typedef struct sSetBandTxDoneParams
|
||||
* Last TX done time.
|
||||
*/
|
||||
TimerTime_t LastTxDoneTime;
|
||||
/*!
|
||||
* Time-on-air of the last transmission.
|
||||
*/
|
||||
TimerTime_t LastTxAirTime;
|
||||
/*!
|
||||
* Elapsed time since initialization.
|
||||
*/
|
||||
SysTime_t ElapsedTimeSinceStartUp;
|
||||
}SetBandTxDoneParams_t;
|
||||
|
||||
/*!
|
||||
@@ -909,6 +1007,10 @@ typedef struct sGetNvmCtxParams
|
||||
*/
|
||||
typedef union uVerifyParams
|
||||
{
|
||||
/*!
|
||||
* Channel frequency to verify
|
||||
*/
|
||||
uint32_t Frequency;
|
||||
/*!
|
||||
* TX power to verify.
|
||||
*/
|
||||
@@ -1004,10 +1106,6 @@ typedef struct sRxConfigParams
|
||||
* Downlink dwell time.
|
||||
*/
|
||||
uint8_t DownlinkDwellTime;
|
||||
/*!
|
||||
* Set to true, if a repeater is supported.
|
||||
*/
|
||||
bool RepeaterSupport;
|
||||
/*!
|
||||
* Set to true, if RX should be continuous.
|
||||
*/
|
||||
@@ -1171,37 +1269,6 @@ typedef enum eAlternateDrType
|
||||
ALTERNATE_DR_RESTORE
|
||||
}AlternateDrType_t;
|
||||
|
||||
/*!
|
||||
* Parameter structure for the function RegionCalcBackOff.
|
||||
*/
|
||||
typedef struct sCalcBackOffParams
|
||||
{
|
||||
/*!
|
||||
* Set to true, if the node has already joined a network, otherwise false.
|
||||
*/
|
||||
bool Joined;
|
||||
/*!
|
||||
* Joined Set to true, if the last uplink was a join request
|
||||
*/
|
||||
bool LastTxIsJoinRequest;
|
||||
/*!
|
||||
* Set to true, if the duty cycle is enabled, otherwise false.
|
||||
*/
|
||||
bool DutyCycleEnabled;
|
||||
/*!
|
||||
* Current channel index.
|
||||
*/
|
||||
uint8_t Channel;
|
||||
/*!
|
||||
* Elapsed time since the start of the node.
|
||||
*/
|
||||
SysTime_t ElapsedTime;
|
||||
/*!
|
||||
* Time-on-air of the last transmission.
|
||||
*/
|
||||
TimerTime_t TxTimeOnAir;
|
||||
}CalcBackOffParams_t;
|
||||
|
||||
/*!
|
||||
* Parameter structure for the function RegionNextChannel.
|
||||
*/
|
||||
@@ -1227,6 +1294,18 @@ typedef struct sNextChanParams
|
||||
* Set to true, if the duty cycle is enabled, otherwise false.
|
||||
*/
|
||||
bool DutyCycleEnabled;
|
||||
/*!
|
||||
* Elapsed time since the start of the node.
|
||||
*/
|
||||
SysTime_t ElapsedTimeSinceStartUp;
|
||||
/*!
|
||||
* Joined Set to true, if the last uplink was a join request
|
||||
*/
|
||||
bool LastTxIsJoinRequest;
|
||||
/*!
|
||||
* Payload length of the next frame
|
||||
*/
|
||||
uint16_t PktLen;
|
||||
}NextChanParams_t;
|
||||
|
||||
/*!
|
||||
@@ -1552,15 +1631,6 @@ uint8_t RegionDlChannelReq( LoRaMacRegion_t region, DlChannelReqParams_t* dlChan
|
||||
*/
|
||||
int8_t RegionAlternateDr( LoRaMacRegion_t region, int8_t currentDr, AlternateDrType_t type );
|
||||
|
||||
/*!
|
||||
* \brief Calculates the back-off time.
|
||||
*
|
||||
* \param [IN] region LoRaWAN region.
|
||||
*
|
||||
* \param [IN] calcBackOff Pointer to the function parameters.
|
||||
*/
|
||||
void RegionCalcBackOff( LoRaMacRegion_t region, CalcBackOffParams_t* calcBackOff );
|
||||
|
||||
/*!
|
||||
* \brief Searches and set the next random available channel
|
||||
*
|
||||
@@ -1630,6 +1700,17 @@ uint8_t RegionApplyDrOffset( LoRaMacRegion_t region, uint8_t downlinkDwellTime,
|
||||
*/
|
||||
void RegionRxBeaconSetup( LoRaMacRegion_t region, RxBeaconSetup_t* rxBeaconSetup, uint8_t* outDr );
|
||||
|
||||
/*!
|
||||
* \brief Gets the version of the regional parameters implementation.
|
||||
*
|
||||
* \retval Version of the regional parameters.
|
||||
*/
|
||||
Version_t RegionGetVersion( void );
|
||||
|
||||
/*! \} defgroup REGION */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // __REGION_H__
|
||||
|
@@ -119,45 +119,21 @@ static bool VerifyRfFreq( uint32_t freq )
|
||||
return true;
|
||||
}
|
||||
|
||||
static uint8_t CountNbOfEnabledChannels( bool joined, uint8_t datarate, uint16_t* channelsMask, ChannelParams_t* channels, Band_t* bands, uint8_t* enabledChannels, uint8_t* delayTx )
|
||||
static TimerTime_t GetTimeOnAir( int8_t datarate, uint16_t pktLen )
|
||||
{
|
||||
uint8_t nbEnabledChannels = 0;
|
||||
uint8_t delayTransmission = 0;
|
||||
int8_t phyDr = DataratesAS923[datarate];
|
||||
uint32_t bandwidth = GetBandwidth( datarate );
|
||||
TimerTime_t timeOnAir = 0;
|
||||
|
||||
for( uint8_t i = 0, k = 0; i < AS923_MAX_NB_CHANNELS; i += 16, k++ )
|
||||
{
|
||||
for( uint8_t j = 0; j < 16; j++ )
|
||||
{
|
||||
if( ( channelsMask[k] & ( 1 << j ) ) != 0 )
|
||||
{
|
||||
if( channels[i + j].Frequency == 0 )
|
||||
{ // Check if the channel is enabled
|
||||
continue;
|
||||
}
|
||||
if( joined == false )
|
||||
{
|
||||
if( ( AS923_JOIN_CHANNELS & ( 1 << j ) ) == 0 )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
}
|
||||
if( RegionCommonValueInRange( datarate, channels[i + j].DrRange.Fields.Min,
|
||||
channels[i + j].DrRange.Fields.Max ) == false )
|
||||
{ // Check if the current channel selection supports the given datarate
|
||||
continue;
|
||||
}
|
||||
if( bands[channels[i + j].Band].TimeOff > 0 )
|
||||
{ // Check if the band is available for transmission
|
||||
delayTransmission++;
|
||||
continue;
|
||||
}
|
||||
enabledChannels[nbEnabledChannels++] = i + j;
|
||||
}
|
||||
}
|
||||
if( datarate == DR_7 )
|
||||
{ // High Speed FSK channel
|
||||
timeOnAir = Radio.TimeOnAir( MODEM_FSK, bandwidth, phyDr * 1000, 0, 5, false, pktLen, true );
|
||||
}
|
||||
|
||||
*delayTx = delayTransmission;
|
||||
return nbEnabledChannels;
|
||||
else
|
||||
{
|
||||
timeOnAir = Radio.TimeOnAir( MODEM_LORA, bandwidth, phyDr, 1, 8, false, pktLen, true );
|
||||
}
|
||||
return timeOnAir;
|
||||
}
|
||||
|
||||
PhyParam_t RegionAS923GetPhyParam( GetPhyParams_t* getPhy )
|
||||
@@ -239,18 +215,6 @@ PhyParam_t RegionAS923GetPhyParam( GetPhyParams_t* getPhy )
|
||||
}
|
||||
break;
|
||||
}
|
||||
case PHY_MAX_PAYLOAD_REPEATER:
|
||||
{
|
||||
if( getPhy->UplinkDwellTime == 0 )
|
||||
{
|
||||
phyParam.Value = MaxPayloadOfDatarateRepeaterDwell0AS923[getPhy->Datarate];
|
||||
}
|
||||
else
|
||||
{
|
||||
phyParam.Value = MaxPayloadOfDatarateDwell1UpAS923[getPhy->Datarate];
|
||||
}
|
||||
break;
|
||||
}
|
||||
case PHY_DUTY_CYCLE:
|
||||
{
|
||||
phyParam.Value = AS923_DUTY_CYCLE_ENABLED;
|
||||
@@ -363,11 +327,26 @@ PhyParam_t RegionAS923GetPhyParam( GetPhyParams_t* getPhy )
|
||||
phyParam.Value = AS923_BEACON_CHANNEL_DR;
|
||||
break;
|
||||
}
|
||||
case PHY_PING_SLOT_CHANNEL_FREQ:
|
||||
{
|
||||
phyParam.Value = AS923_PING_SLOT_CHANNEL_FREQ;
|
||||
break;
|
||||
}
|
||||
case PHY_PING_SLOT_CHANNEL_DR:
|
||||
{
|
||||
phyParam.Value = AS923_PING_SLOT_CHANNEL_DR;
|
||||
break;
|
||||
}
|
||||
case PHY_SF_FROM_DR:
|
||||
{
|
||||
phyParam.Value = DataratesAS923[getPhy->Datarate];
|
||||
break;
|
||||
}
|
||||
case PHY_BW_FROM_DR:
|
||||
{
|
||||
phyParam.Value = GetBandwidth( getPhy->Datarate );
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
break;
|
||||
@@ -379,7 +358,8 @@ PhyParam_t RegionAS923GetPhyParam( GetPhyParams_t* getPhy )
|
||||
|
||||
void RegionAS923SetBandTxDone( SetBandTxDoneParams_t* txDone )
|
||||
{
|
||||
RegionCommonSetBandTxDone( txDone->Joined, &NvmCtx.Bands[NvmCtx.Channels[txDone->Channel].Band], txDone->LastTxDoneTime );
|
||||
RegionCommonSetBandTxDone( &NvmCtx.Bands[NvmCtx.Channels[txDone->Channel].Band],
|
||||
txDone->LastTxAirTime, txDone->Joined, txDone->ElapsedTimeSinceStartUp );
|
||||
}
|
||||
|
||||
void RegionAS923InitDefaults( InitDefaultsParams_t* params )
|
||||
@@ -391,10 +371,14 @@ void RegionAS923InitDefaults( InitDefaultsParams_t* params )
|
||||
|
||||
switch( params->Type )
|
||||
{
|
||||
case INIT_TYPE_INIT:
|
||||
case INIT_TYPE_BANDS:
|
||||
{
|
||||
// Initialize bands
|
||||
memcpy1( ( uint8_t* )NvmCtx.Bands, ( uint8_t* )bands, sizeof( Band_t ) * AS923_MAX_NB_BANDS );
|
||||
break;
|
||||
}
|
||||
case INIT_TYPE_INIT:
|
||||
{
|
||||
|
||||
// Channels
|
||||
NvmCtx.Channels[0] = ( ChannelParams_t ) AS923_LC1;
|
||||
@@ -402,6 +386,7 @@ void RegionAS923InitDefaults( InitDefaultsParams_t* params )
|
||||
|
||||
// Initialize the channels default mask
|
||||
NvmCtx.ChannelsDefaultMask[0] = LC( 1 ) + LC( 2 );
|
||||
|
||||
// Update the channels mask
|
||||
RegionCommonChanMaskCopy( NvmCtx.ChannelsMask, NvmCtx.ChannelsDefaultMask, 1 );
|
||||
break;
|
||||
@@ -418,6 +403,10 @@ void RegionAS923InitDefaults( InitDefaultsParams_t* params )
|
||||
{
|
||||
// Restore channels default mask
|
||||
NvmCtx.ChannelsMask[0] |= NvmCtx.ChannelsDefaultMask[0];
|
||||
|
||||
// Channels
|
||||
NvmCtx.Channels[0] = ( ChannelParams_t ) AS923_LC1;
|
||||
NvmCtx.Channels[1] = ( ChannelParams_t ) AS923_LC2;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
@@ -437,6 +426,10 @@ bool RegionAS923Verify( VerifyParams_t* verify, PhyAttribute_t phyAttribute )
|
||||
{
|
||||
switch( phyAttribute )
|
||||
{
|
||||
case PHY_FREQUENCY:
|
||||
{
|
||||
return VerifyRfFreq( verify->Frequency );
|
||||
}
|
||||
case PHY_TX_DR:
|
||||
{
|
||||
if( verify->DatarateParams.UplinkDwellTime == 0 )
|
||||
@@ -581,7 +574,6 @@ bool RegionAS923RxConfig( RxConfigParams_t* rxConfig, int8_t* datarate )
|
||||
{
|
||||
RadioModems_t modem;
|
||||
int8_t dr = rxConfig->Datarate;
|
||||
uint8_t maxPayload = 0;
|
||||
int8_t phyDr = 0;
|
||||
uint32_t frequency = rxConfig->Frequency;
|
||||
|
||||
@@ -618,17 +610,7 @@ bool RegionAS923RxConfig( RxConfigParams_t* rxConfig, int8_t* datarate )
|
||||
Radio.SetRxConfig( modem, rxConfig->Bandwidth, phyDr, 1, 0, 8, rxConfig->WindowTimeout, false, 0, false, 0, 0, true, rxConfig->RxContinuous );
|
||||
}
|
||||
|
||||
// Check for repeater support
|
||||
if( rxConfig->RepeaterSupport == true )
|
||||
{
|
||||
maxPayload = MaxPayloadOfDatarateRepeaterDwell0AS923[dr];
|
||||
}
|
||||
else
|
||||
{
|
||||
maxPayload = MaxPayloadOfDatarateDwell0AS923[dr];
|
||||
}
|
||||
|
||||
Radio.SetMaxPayloadLength( modem, maxPayload + LORA_MAC_FRMPAYLOAD_OVERHEAD );
|
||||
Radio.SetMaxPayloadLength( modem, MaxPayloadOfDatarateDwell0AS923[dr] + LORAMAC_FRAME_PAYLOAD_OVERHEAD_SIZE );
|
||||
|
||||
*datarate = (uint8_t) dr;
|
||||
return true;
|
||||
@@ -651,18 +633,19 @@ bool RegionAS923TxConfig( TxConfigParams_t* txConfig, int8_t* txPower, TimerTime
|
||||
if( txConfig->Datarate == DR_7 )
|
||||
{ // High Speed FSK channel
|
||||
modem = MODEM_FSK;
|
||||
Radio.SetTxConfig( modem, phyTxPower, 25000, bandwidth, phyDr * 1000, 0, 5, false, true, 0, 0, false, 3000 );
|
||||
Radio.SetTxConfig( modem, phyTxPower, 25000, bandwidth, phyDr * 1000, 0, 5, false, true, 0, 0, false, 4000 );
|
||||
}
|
||||
else
|
||||
{
|
||||
modem = MODEM_LORA;
|
||||
Radio.SetTxConfig( modem, phyTxPower, 0, bandwidth, phyDr, 1, 8, false, true, 0, 0, false, 3000 );
|
||||
Radio.SetTxConfig( modem, phyTxPower, 0, bandwidth, phyDr, 1, 8, false, true, 0, 0, false, 4000 );
|
||||
}
|
||||
|
||||
// Update time-on-air
|
||||
*txTimeOnAir = GetTimeOnAir( txConfig->Datarate, txConfig->PktLen );
|
||||
|
||||
// Setup maximum payload lenght of the radio driver
|
||||
Radio.SetMaxPayloadLength( modem, txConfig->PktLen );
|
||||
// Get the time-on-air of the next tx frame
|
||||
*txTimeOnAir = Radio.TimeOnAir( modem, txConfig->PktLen );
|
||||
|
||||
*txPower = txPowerLimited;
|
||||
return true;
|
||||
@@ -888,55 +871,45 @@ int8_t RegionAS923AlternateDr( int8_t currentDr, AlternateDrType_t type )
|
||||
return AS923_DWELL_LIMIT_DATARATE;
|
||||
}
|
||||
|
||||
void RegionAS923CalcBackOff( CalcBackOffParams_t* calcBackOff )
|
||||
{
|
||||
RegionCommonCalcBackOffParams_t calcBackOffParams;
|
||||
|
||||
calcBackOffParams.Channels = NvmCtx.Channels;
|
||||
calcBackOffParams.Bands = NvmCtx.Bands;
|
||||
calcBackOffParams.LastTxIsJoinRequest = calcBackOff->LastTxIsJoinRequest;
|
||||
calcBackOffParams.Joined = calcBackOff->Joined;
|
||||
calcBackOffParams.DutyCycleEnabled = calcBackOff->DutyCycleEnabled;
|
||||
calcBackOffParams.Channel = calcBackOff->Channel;
|
||||
calcBackOffParams.ElapsedTime = calcBackOff->ElapsedTime;
|
||||
calcBackOffParams.TxTimeOnAir = calcBackOff->TxTimeOnAir;
|
||||
|
||||
RegionCommonCalcBackOff( &calcBackOffParams );
|
||||
}
|
||||
|
||||
LoRaMacStatus_t RegionAS923NextChannel( NextChanParams_t* nextChanParams, uint8_t* channel, TimerTime_t* time, TimerTime_t* aggregatedTimeOff )
|
||||
{
|
||||
uint8_t channelNext = 0;
|
||||
uint8_t nbEnabledChannels = 0;
|
||||
uint8_t delayTx = 0;
|
||||
uint8_t nbRestrictedChannels = 0;
|
||||
uint8_t enabledChannels[AS923_MAX_NB_CHANNELS] = { 0 };
|
||||
TimerTime_t nextTxDelay = 0;
|
||||
RegionCommonIdentifyChannelsParam_t identifyChannelsParam;
|
||||
RegionCommonCountNbOfEnabledChannelsParams_t countChannelsParams;
|
||||
LoRaMacStatus_t status = LORAMAC_STATUS_NO_CHANNEL_FOUND;
|
||||
|
||||
if( RegionCommonCountChannels( NvmCtx.ChannelsMask, 0, 1 ) == 0 )
|
||||
{ // Reactivate default channels
|
||||
NvmCtx.ChannelsMask[0] |= LC( 1 ) + LC( 2 );
|
||||
}
|
||||
|
||||
if( nextChanParams->AggrTimeOff <= TimerGetElapsedTime( nextChanParams->LastAggrTx ) )
|
||||
{
|
||||
// Reset Aggregated time off
|
||||
*aggregatedTimeOff = 0;
|
||||
// Search how many channels are enabled
|
||||
countChannelsParams.Joined = nextChanParams->Joined;
|
||||
countChannelsParams.Datarate = nextChanParams->Datarate;
|
||||
countChannelsParams.ChannelsMask = NvmCtx.ChannelsMask;
|
||||
countChannelsParams.Channels = NvmCtx.Channels;
|
||||
countChannelsParams.Bands = NvmCtx.Bands;
|
||||
countChannelsParams.MaxNbChannels = AS923_MAX_NB_CHANNELS;
|
||||
countChannelsParams.JoinChannels = AS923_JOIN_CHANNELS;
|
||||
|
||||
// Update bands Time OFF
|
||||
nextTxDelay = RegionCommonUpdateBandTimeOff( nextChanParams->Joined, nextChanParams->DutyCycleEnabled, NvmCtx.Bands, AS923_MAX_NB_BANDS );
|
||||
identifyChannelsParam.AggrTimeOff = nextChanParams->AggrTimeOff;
|
||||
identifyChannelsParam.LastAggrTx = nextChanParams->LastAggrTx;
|
||||
identifyChannelsParam.DutyCycleEnabled = nextChanParams->DutyCycleEnabled;
|
||||
identifyChannelsParam.MaxBands = AS923_MAX_NB_BANDS;
|
||||
|
||||
// Search how many channels are enabled
|
||||
nbEnabledChannels = CountNbOfEnabledChannels( nextChanParams->Joined, nextChanParams->Datarate,
|
||||
NvmCtx.ChannelsMask, NvmCtx.Channels,
|
||||
NvmCtx.Bands, enabledChannels, &delayTx );
|
||||
}
|
||||
else
|
||||
{
|
||||
delayTx++;
|
||||
nextTxDelay = nextChanParams->AggrTimeOff - TimerGetElapsedTime( nextChanParams->LastAggrTx );
|
||||
}
|
||||
identifyChannelsParam.ElapsedTimeSinceStartUp = nextChanParams->ElapsedTimeSinceStartUp;
|
||||
identifyChannelsParam.LastTxIsJoinRequest = nextChanParams->LastTxIsJoinRequest;
|
||||
identifyChannelsParam.ExpectedTimeOnAir = GetTimeOnAir( nextChanParams->Datarate, nextChanParams->PktLen );
|
||||
|
||||
if( nbEnabledChannels > 0 )
|
||||
identifyChannelsParam.CountNbOfEnabledChannelsParam = &countChannelsParams;
|
||||
|
||||
status = RegionCommonIdentifyChannels( &identifyChannelsParam, aggregatedTimeOff, enabledChannels,
|
||||
&nbEnabledChannels, &nbRestrictedChannels, time );
|
||||
|
||||
if( status == LORAMAC_STATUS_OK )
|
||||
{
|
||||
for( uint8_t i = 0, j = randr( 0, nbEnabledChannels - 1 ); i < AS923_MAX_NB_CHANNELS; i++ )
|
||||
{
|
||||
@@ -949,25 +922,19 @@ LoRaMacStatus_t RegionAS923NextChannel( NextChanParams_t* nextChanParams, uint8_
|
||||
{
|
||||
// Free channel found
|
||||
*channel = channelNext;
|
||||
*time = 0;
|
||||
return LORAMAC_STATUS_OK;
|
||||
}
|
||||
}
|
||||
return LORAMAC_STATUS_NO_FREE_CHANNEL_FOUND;
|
||||
// Even if one or more channels are available according to the channel plan, no free channel
|
||||
// was found during the LBT procedure.
|
||||
status = LORAMAC_STATUS_NO_FREE_CHANNEL_FOUND;
|
||||
}
|
||||
else
|
||||
else if( status == LORAMAC_STATUS_NO_CHANNEL_FOUND )
|
||||
{
|
||||
if( delayTx > 0 )
|
||||
{
|
||||
// Delay transmission due to AggregatedTimeOff or to a band time off
|
||||
*time = nextTxDelay;
|
||||
return LORAMAC_STATUS_DUTYCYCLE_RESTRICTED;
|
||||
}
|
||||
// Datarate not supported by any channel, restore defaults
|
||||
NvmCtx.ChannelsMask[0] |= LC( 1 ) + LC( 2 );
|
||||
*time = 0;
|
||||
return LORAMAC_STATUS_NO_CHANNEL_FOUND;
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
LoRaMacStatus_t RegionAS923ChannelAdd( ChannelAddParams_t* channelAdd )
|
||||
|
@@ -37,6 +37,11 @@
|
||||
#ifndef __REGION_AS923_H__
|
||||
#define __REGION_AS923_H__
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
#include "region/Region.h"
|
||||
|
||||
/*!
|
||||
@@ -212,6 +217,11 @@
|
||||
*/
|
||||
#define AS923_BEACON_CHANNEL_FREQ 923400000
|
||||
|
||||
/*!
|
||||
* Ping slot channel frequency
|
||||
*/
|
||||
#define AS923_PING_SLOT_CHANNEL_FREQ 923400000
|
||||
|
||||
/*!
|
||||
* Payload size of a beacon frame
|
||||
*/
|
||||
@@ -249,9 +259,9 @@
|
||||
|
||||
/*!
|
||||
* Band 0 definition
|
||||
* { DutyCycle, TxMaxPower, LastJoinTxDoneTime, LastTxDoneTime, TimeOff }
|
||||
* Band = { DutyCycle, TxMaxPower, LastBandUpdateTime, TimeCredits, MaxTimeCredits, ReadyForTransmission }
|
||||
*/
|
||||
#define AS923_BAND0 { 100, AS923_MAX_TX_POWER, 0, 0, 0 } // 1.0 %
|
||||
#define AS923_BAND0 { 100, AS923_MAX_TX_POWER, 0, 0, 0, 0 } // 1.0 %
|
||||
|
||||
/*!
|
||||
* LoRaMac default channel 1
|
||||
@@ -291,27 +301,20 @@ static const uint8_t DataratesAS923[] = { 12, 11, 10, 9, 8, 7, 7, 50 };
|
||||
static const uint32_t BandwidthsAS923[] = { 125000, 125000, 125000, 125000, 125000, 125000, 250000, 0 };
|
||||
|
||||
/*!
|
||||
* Maximum payload with respect to the datarate index. Cannot operate with repeater.
|
||||
* Maximum payload with respect to the datarate index.
|
||||
* The table is valid for the dwell time configuration of 0 for uplinks and downlinks.
|
||||
*/
|
||||
static const uint8_t MaxPayloadOfDatarateDwell0AS923[] = { 51, 51, 51, 115, 242, 242, 242, 242 };
|
||||
|
||||
/*!
|
||||
* Maximum payload with respect to the datarate index. Can operate with repeater.
|
||||
* The table is valid for the dwell time configuration of 0 for uplinks and downlinks. The table provides
|
||||
* repeater support.
|
||||
*/
|
||||
static const uint8_t MaxPayloadOfDatarateRepeaterDwell0AS923[] = { 51, 51, 51, 115, 222, 222, 222, 222 };
|
||||
|
||||
/*!
|
||||
* Maximum payload with respect to the datarate index. Can operate with and without repeater.
|
||||
* The table proides repeater support. The table is only valid for uplinks.
|
||||
* Maximum payload with respect to the datarate index.
|
||||
* The table is only valid for uplinks.
|
||||
*/
|
||||
static const uint8_t MaxPayloadOfDatarateDwell1UpAS923[] = { 0, 0, 11, 53, 125, 242, 242, 242 };
|
||||
|
||||
/*!
|
||||
* Maximum payload with respect to the datarate index. Can operate with and without repeater.
|
||||
* The table proides repeater support. The table is only valid for downlinks.
|
||||
* Maximum payload with respect to the datarate index.
|
||||
* The table is only valid for downlinks.
|
||||
*/
|
||||
static const uint8_t MaxPayloadOfDatarateDwell1DownAS923[] = { 0, 0, 11, 53, 126, 242, 242, 242 };
|
||||
|
||||
@@ -475,13 +478,6 @@ uint8_t RegionAS923DlChannelReq( DlChannelReqParams_t* dlChannelReq );
|
||||
*/
|
||||
int8_t RegionAS923AlternateDr( int8_t currentDr, AlternateDrType_t type );
|
||||
|
||||
/*!
|
||||
* \brief Calculates the back-off time.
|
||||
*
|
||||
* \param [IN] calcBackOff Pointer to the function parameters.
|
||||
*/
|
||||
void RegionAS923CalcBackOff( CalcBackOffParams_t* calcBackOff );
|
||||
|
||||
/*!
|
||||
* \brief Searches and set the next random available channel
|
||||
*
|
||||
@@ -543,4 +539,8 @@ uint8_t RegionAS923ApplyDrOffset( uint8_t downlinkDwellTime, int8_t dr, int8_t d
|
||||
|
||||
/*! \} defgroup REGIONAS923 */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // __REGION_AS923_H__
|
||||
|
@@ -140,38 +140,12 @@ static bool VerifyRfFreq( uint32_t freq )
|
||||
return true;
|
||||
}
|
||||
|
||||
static uint8_t CountNbOfEnabledChannels( uint8_t datarate, uint16_t* channelsMask, ChannelParams_t* channels, Band_t* bands, uint8_t* enabledChannels, uint8_t* delayTx )
|
||||
static TimerTime_t GetTimeOnAir( int8_t datarate, uint16_t pktLen )
|
||||
{
|
||||
uint8_t nbEnabledChannels = 0;
|
||||
uint8_t delayTransmission = 0;
|
||||
int8_t phyDr = DataratesAU915[datarate];
|
||||
uint32_t bandwidth = GetBandwidth( datarate );
|
||||
|
||||
for( uint8_t i = 0, k = 0; i < AU915_MAX_NB_CHANNELS; i += 16, k++ )
|
||||
{
|
||||
for( uint8_t j = 0; j < 16; j++ )
|
||||
{
|
||||
if( ( channelsMask[k] & ( 1 << j ) ) != 0 )
|
||||
{
|
||||
if( channels[i + j].Frequency == 0 )
|
||||
{ // Check if the channel is enabled
|
||||
continue;
|
||||
}
|
||||
if( RegionCommonValueInRange( datarate, channels[i + j].DrRange.Fields.Min,
|
||||
channels[i + j].DrRange.Fields.Max ) == false )
|
||||
{ // Check if the current channel selection supports the given datarate
|
||||
continue;
|
||||
}
|
||||
if( bands[channels[i + j].Band].TimeOff > 0 )
|
||||
{ // Check if the band is available for transmission
|
||||
delayTransmission++;
|
||||
continue;
|
||||
}
|
||||
enabledChannels[nbEnabledChannels++] = i + j;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
*delayTx = delayTransmission;
|
||||
return nbEnabledChannels;
|
||||
return Radio.TimeOnAir( MODEM_LORA, bandwidth, phyDr, 1, 8, false, pktLen, true );
|
||||
}
|
||||
|
||||
PhyParam_t RegionAU915GetPhyParam( GetPhyParams_t* getPhy )
|
||||
@@ -253,18 +227,6 @@ PhyParam_t RegionAU915GetPhyParam( GetPhyParams_t* getPhy )
|
||||
}
|
||||
break;
|
||||
}
|
||||
case PHY_MAX_PAYLOAD_REPEATER:
|
||||
{
|
||||
if( getPhy->UplinkDwellTime == 0)
|
||||
{
|
||||
phyParam.Value = MaxPayloadOfDatarateRepeaterDwell0AU915[getPhy->Datarate];
|
||||
}
|
||||
else
|
||||
{
|
||||
phyParam.Value = MaxPayloadOfDatarateRepeaterDwell1AU915[getPhy->Datarate];
|
||||
}
|
||||
break;
|
||||
}
|
||||
case PHY_DUTY_CYCLE:
|
||||
{
|
||||
phyParam.Value = AU915_DUTY_CYCLE_ENABLED;
|
||||
@@ -360,6 +322,11 @@ PhyParam_t RegionAU915GetPhyParam( GetPhyParams_t* getPhy )
|
||||
phyParam.fValue = AU915_DEFAULT_ANTENNA_GAIN;
|
||||
break;
|
||||
}
|
||||
case PHY_BEACON_CHANNEL_FREQ:
|
||||
{
|
||||
phyParam.Value = AU915_BEACON_CHANNEL_FREQ + ( getPhy->Channel * AU915_BEACON_CHANNEL_STEPWIDTH );
|
||||
break;
|
||||
}
|
||||
case PHY_BEACON_FORMAT:
|
||||
{
|
||||
phyParam.BeaconFormat.BeaconSize = AU915_BEACON_SIZE;
|
||||
@@ -382,11 +349,26 @@ PhyParam_t RegionAU915GetPhyParam( GetPhyParams_t* getPhy )
|
||||
phyParam.Value = AU915_BEACON_NB_CHANNELS;
|
||||
break;
|
||||
}
|
||||
case PHY_PING_SLOT_CHANNEL_FREQ:
|
||||
{
|
||||
phyParam.Value = AU915_PING_SLOT_CHANNEL_FREQ + ( getPhy->Channel * AU915_BEACON_CHANNEL_STEPWIDTH );
|
||||
break;
|
||||
}
|
||||
case PHY_PING_SLOT_CHANNEL_DR:
|
||||
{
|
||||
phyParam.Value = AU915_PING_SLOT_CHANNEL_DR;
|
||||
break;
|
||||
}
|
||||
case PHY_SF_FROM_DR:
|
||||
{
|
||||
phyParam.Value = DataratesAU915[getPhy->Datarate];
|
||||
break;
|
||||
}
|
||||
case PHY_BW_FROM_DR:
|
||||
{
|
||||
phyParam.Value = GetBandwidth( getPhy->Datarate );
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
break;
|
||||
@@ -398,7 +380,8 @@ PhyParam_t RegionAU915GetPhyParam( GetPhyParams_t* getPhy )
|
||||
|
||||
void RegionAU915SetBandTxDone( SetBandTxDoneParams_t* txDone )
|
||||
{
|
||||
RegionCommonSetBandTxDone( txDone->Joined, &NvmCtx.Bands[NvmCtx.Channels[txDone->Channel].Band], txDone->LastTxDoneTime );
|
||||
RegionCommonSetBandTxDone( &NvmCtx.Bands[NvmCtx.Channels[txDone->Channel].Band],
|
||||
txDone->LastTxAirTime, txDone->Joined, txDone->ElapsedTimeSinceStartUp );
|
||||
}
|
||||
|
||||
void RegionAU915InitDefaults( InitDefaultsParams_t* params )
|
||||
@@ -410,11 +393,28 @@ void RegionAU915InitDefaults( InitDefaultsParams_t* params )
|
||||
|
||||
switch( params->Type )
|
||||
{
|
||||
case INIT_TYPE_INIT:
|
||||
case INIT_TYPE_BANDS:
|
||||
{
|
||||
// Initialize bands
|
||||
memcpy1( ( uint8_t* )NvmCtx.Bands, ( uint8_t* )bands, sizeof( Band_t ) * AU915_MAX_NB_BANDS );
|
||||
|
||||
// Initialize channels default mask
|
||||
NvmCtx.ChannelsDefaultMask[0] = 0xFFFF;
|
||||
NvmCtx.ChannelsDefaultMask[1] = 0xFFFF;
|
||||
NvmCtx.ChannelsDefaultMask[2] = 0xFFFF;
|
||||
NvmCtx.ChannelsDefaultMask[3] = 0xFFFF;
|
||||
NvmCtx.ChannelsDefaultMask[4] = 0x00FF;
|
||||
NvmCtx.ChannelsDefaultMask[5] = 0x0000;
|
||||
|
||||
// Copy channels default mask
|
||||
RegionCommonChanMaskCopy( NvmCtx.ChannelsMask, NvmCtx.ChannelsDefaultMask, 6 );
|
||||
|
||||
// Copy into channels mask remaining
|
||||
RegionCommonChanMaskCopy( NvmCtx.ChannelsMaskRemaining, NvmCtx.ChannelsMask, 6 );
|
||||
break;
|
||||
}
|
||||
case INIT_TYPE_INIT:
|
||||
{
|
||||
// Channels
|
||||
// 125 kHz channels
|
||||
for( uint8_t i = 0; i < AU915_MAX_NB_CHANNELS - 8; i++ )
|
||||
@@ -430,20 +430,6 @@ void RegionAU915InitDefaults( InitDefaultsParams_t* params )
|
||||
NvmCtx.Channels[i].DrRange.Value = ( DR_6 << 4 ) | DR_6;
|
||||
NvmCtx.Channels[i].Band = 0;
|
||||
}
|
||||
|
||||
// Initialize channels default mask
|
||||
NvmCtx.ChannelsDefaultMask[0] = 0xFFFF;
|
||||
NvmCtx.ChannelsDefaultMask[1] = 0xFFFF;
|
||||
NvmCtx.ChannelsDefaultMask[2] = 0xFFFF;
|
||||
NvmCtx.ChannelsDefaultMask[3] = 0xFFFF;
|
||||
NvmCtx.ChannelsDefaultMask[4] = 0x00FF;
|
||||
NvmCtx.ChannelsDefaultMask[5] = 0x0000;
|
||||
|
||||
// Copy channels default mask
|
||||
RegionCommonChanMaskCopy( NvmCtx.ChannelsMask, NvmCtx.ChannelsDefaultMask, 6 );
|
||||
|
||||
// Copy into channels mask remaining
|
||||
RegionCommonChanMaskCopy( NvmCtx.ChannelsMaskRemaining, NvmCtx.ChannelsMask, 6 );
|
||||
break;
|
||||
}
|
||||
case INIT_TYPE_RESTORE_CTX:
|
||||
@@ -482,6 +468,10 @@ bool RegionAU915Verify( VerifyParams_t* verify, PhyAttribute_t phyAttribute )
|
||||
{
|
||||
switch( phyAttribute )
|
||||
{
|
||||
case PHY_FREQUENCY:
|
||||
{
|
||||
return VerifyRfFreq( verify->Frequency );
|
||||
}
|
||||
case PHY_TX_DR:
|
||||
case PHY_DEF_TX_DR:
|
||||
{
|
||||
@@ -592,7 +582,6 @@ void RegionAU915ComputeRxWindowParameters( int8_t datarate, uint8_t minRxSymbols
|
||||
bool RegionAU915RxConfig( RxConfigParams_t* rxConfig, int8_t* datarate )
|
||||
{
|
||||
int8_t dr = rxConfig->Datarate;
|
||||
uint8_t maxPayload = 0;
|
||||
int8_t phyDr = 0;
|
||||
uint32_t frequency = rxConfig->Frequency;
|
||||
|
||||
@@ -615,15 +604,7 @@ bool RegionAU915RxConfig( RxConfigParams_t* rxConfig, int8_t* datarate )
|
||||
// Radio configuration
|
||||
Radio.SetRxConfig( MODEM_LORA, rxConfig->Bandwidth, phyDr, 1, 0, 8, rxConfig->WindowTimeout, false, 0, false, 0, 0, true, rxConfig->RxContinuous );
|
||||
|
||||
if( rxConfig->RepeaterSupport == true )
|
||||
{
|
||||
maxPayload = MaxPayloadOfDatarateRepeaterDwell0AU915[dr];
|
||||
}
|
||||
else
|
||||
{
|
||||
maxPayload = MaxPayloadOfDatarateDwell0AU915[dr];
|
||||
}
|
||||
Radio.SetMaxPayloadLength( MODEM_LORA, maxPayload + LORA_MAC_FRMPAYLOAD_OVERHEAD );
|
||||
Radio.SetMaxPayloadLength( MODEM_LORA, MaxPayloadOfDatarateDwell0AU915[dr] + LORAMAC_FRAME_PAYLOAD_OVERHEAD_SIZE );
|
||||
|
||||
*datarate = (uint8_t) dr;
|
||||
return true;
|
||||
@@ -642,14 +623,14 @@ bool RegionAU915TxConfig( TxConfigParams_t* txConfig, int8_t* txPower, TimerTime
|
||||
// Setup the radio frequency
|
||||
Radio.SetChannel( NvmCtx.Channels[txConfig->Channel].Frequency );
|
||||
|
||||
Radio.SetTxConfig( MODEM_LORA, phyTxPower, 0, bandwidth, phyDr, 1, 8, false, true, 0, 0, false, 3000 );
|
||||
Radio.SetTxConfig( MODEM_LORA, phyTxPower, 0, bandwidth, phyDr, 1, 8, false, true, 0, 0, false, 4000 );
|
||||
|
||||
// Setup maximum payload lenght of the radio driver
|
||||
Radio.SetMaxPayloadLength( MODEM_LORA, txConfig->PktLen );
|
||||
// Update time-on-air
|
||||
*txTimeOnAir = GetTimeOnAir( txConfig->Datarate, txConfig->PktLen );
|
||||
|
||||
*txTimeOnAir = Radio.TimeOnAir( MODEM_LORA, txConfig->PktLen );
|
||||
*txPower = txPowerLimited;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -880,28 +861,14 @@ int8_t RegionAU915AlternateDr( int8_t currentDr, AlternateDrType_t type )
|
||||
return currentDr;
|
||||
}
|
||||
|
||||
void RegionAU915CalcBackOff( CalcBackOffParams_t* calcBackOff )
|
||||
{
|
||||
RegionCommonCalcBackOffParams_t calcBackOffParams;
|
||||
|
||||
calcBackOffParams.Channels = NvmCtx.Channels;
|
||||
calcBackOffParams.Bands = NvmCtx.Bands;
|
||||
calcBackOffParams.LastTxIsJoinRequest = calcBackOff->LastTxIsJoinRequest;
|
||||
calcBackOffParams.Joined = calcBackOff->Joined;
|
||||
calcBackOffParams.DutyCycleEnabled = calcBackOff->DutyCycleEnabled;
|
||||
calcBackOffParams.Channel = calcBackOff->Channel;
|
||||
calcBackOffParams.ElapsedTime = calcBackOff->ElapsedTime;
|
||||
calcBackOffParams.TxTimeOnAir = calcBackOff->TxTimeOnAir;
|
||||
|
||||
RegionCommonCalcBackOff( &calcBackOffParams );
|
||||
}
|
||||
|
||||
LoRaMacStatus_t RegionAU915NextChannel( NextChanParams_t* nextChanParams, uint8_t* channel, TimerTime_t* time, TimerTime_t* aggregatedTimeOff )
|
||||
{
|
||||
uint8_t nbEnabledChannels = 0;
|
||||
uint8_t delayTx = 0;
|
||||
uint8_t nbRestrictedChannels = 0;
|
||||
uint8_t enabledChannels[AU915_MAX_NB_CHANNELS] = { 0 };
|
||||
TimerTime_t nextTxDelay = 0;
|
||||
RegionCommonIdentifyChannelsParam_t identifyChannelsParam;
|
||||
RegionCommonCountNbOfEnabledChannelsParams_t countChannelsParams;
|
||||
LoRaMacStatus_t status = LORAMAC_STATUS_NO_CHANNEL_FOUND;
|
||||
|
||||
// Count 125kHz channels
|
||||
if( RegionCommonCountChannels( NvmCtx.ChannelsMaskRemaining, 0, 4 ) == 0 )
|
||||
@@ -917,47 +884,37 @@ LoRaMacStatus_t RegionAU915NextChannel( NextChanParams_t* nextChanParams, uint8_
|
||||
}
|
||||
}
|
||||
|
||||
if( nextChanParams->AggrTimeOff <= TimerGetElapsedTime( nextChanParams->LastAggrTx ) )
|
||||
{
|
||||
// Reset Aggregated time off
|
||||
*aggregatedTimeOff = 0;
|
||||
// Search how many channels are enabled
|
||||
countChannelsParams.Joined = nextChanParams->Joined;
|
||||
countChannelsParams.Datarate = nextChanParams->Datarate;
|
||||
countChannelsParams.ChannelsMask = NvmCtx.ChannelsMaskRemaining;
|
||||
countChannelsParams.Channels = NvmCtx.Channels;
|
||||
countChannelsParams.Bands = NvmCtx.Bands;
|
||||
countChannelsParams.MaxNbChannels = AU915_MAX_NB_CHANNELS;
|
||||
countChannelsParams.JoinChannels = 0;
|
||||
|
||||
// Update bands Time OFF
|
||||
nextTxDelay = RegionCommonUpdateBandTimeOff( nextChanParams->Joined, nextChanParams->DutyCycleEnabled, NvmCtx.Bands, AU915_MAX_NB_BANDS );
|
||||
identifyChannelsParam.AggrTimeOff = nextChanParams->AggrTimeOff;
|
||||
identifyChannelsParam.LastAggrTx = nextChanParams->LastAggrTx;
|
||||
identifyChannelsParam.DutyCycleEnabled = nextChanParams->DutyCycleEnabled;
|
||||
identifyChannelsParam.MaxBands = AU915_MAX_NB_BANDS;
|
||||
|
||||
// Search how many channels are enabled
|
||||
nbEnabledChannels = CountNbOfEnabledChannels( nextChanParams->Datarate,
|
||||
NvmCtx.ChannelsMaskRemaining, NvmCtx.Channels,
|
||||
NvmCtx.Bands, enabledChannels, &delayTx );
|
||||
}
|
||||
else
|
||||
{
|
||||
delayTx++;
|
||||
nextTxDelay = nextChanParams->AggrTimeOff - TimerGetElapsedTime( nextChanParams->LastAggrTx );
|
||||
}
|
||||
identifyChannelsParam.ElapsedTimeSinceStartUp = nextChanParams->ElapsedTimeSinceStartUp;
|
||||
identifyChannelsParam.LastTxIsJoinRequest = nextChanParams->LastTxIsJoinRequest;
|
||||
identifyChannelsParam.ExpectedTimeOnAir = GetTimeOnAir( nextChanParams->Datarate, nextChanParams->PktLen );
|
||||
|
||||
if( nbEnabledChannels > 0 )
|
||||
identifyChannelsParam.CountNbOfEnabledChannelsParam = &countChannelsParams;
|
||||
|
||||
status = RegionCommonIdentifyChannels( &identifyChannelsParam, aggregatedTimeOff, enabledChannels,
|
||||
&nbEnabledChannels, &nbRestrictedChannels, time );
|
||||
|
||||
if( status == LORAMAC_STATUS_OK )
|
||||
{
|
||||
// We found a valid channel
|
||||
*channel = enabledChannels[randr( 0, nbEnabledChannels - 1 )];
|
||||
// Disable the channel in the mask
|
||||
RegionCommonChanDisable( NvmCtx.ChannelsMaskRemaining, *channel, AU915_MAX_NB_CHANNELS - 8 );
|
||||
|
||||
*time = 0;
|
||||
return LORAMAC_STATUS_OK;
|
||||
}
|
||||
else
|
||||
{
|
||||
if( delayTx > 0 )
|
||||
{
|
||||
// Delay transmission due to AggregatedTimeOff or to a band time off
|
||||
*time = nextTxDelay;
|
||||
return LORAMAC_STATUS_DUTYCYCLE_RESTRICTED;
|
||||
}
|
||||
// Datarate not supported by any channel
|
||||
*time = 0;
|
||||
return LORAMAC_STATUS_NO_CHANNEL_FOUND;
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
LoRaMacStatus_t RegionAU915ChannelAdd( ChannelAddParams_t* channelAdd )
|
||||
|
@@ -37,6 +37,11 @@
|
||||
#ifndef __REGION_AU915_H__
|
||||
#define __REGION_AU915_H__
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
#include "region/Region.h"
|
||||
|
||||
/*!
|
||||
@@ -93,7 +98,7 @@
|
||||
/*!
|
||||
* Minimal Tx output power that can be used by the node
|
||||
*/
|
||||
#define AU915_MIN_TX_POWER TX_POWER_10
|
||||
#define AU915_MIN_TX_POWER TX_POWER_14
|
||||
|
||||
/*!
|
||||
* Maximal Tx output power that can be used by the node
|
||||
@@ -203,6 +208,11 @@
|
||||
*/
|
||||
#define AU915_BEACON_CHANNEL_STEPWIDTH 600000
|
||||
|
||||
/*!
|
||||
* Ping slot channel frequency
|
||||
*/
|
||||
#define AU915_PING_SLOT_CHANNEL_FREQ 923300000
|
||||
|
||||
/*!
|
||||
* Number of possible beacon channels
|
||||
*/
|
||||
@@ -226,7 +236,7 @@
|
||||
/*!
|
||||
* Datarate of the beacon channel
|
||||
*/
|
||||
#define AU915_BEACON_CHANNEL_DR DR_10
|
||||
#define AU915_BEACON_CHANNEL_DR DR_8
|
||||
|
||||
/*!
|
||||
* Bandwith of the beacon channel
|
||||
@@ -236,7 +246,7 @@
|
||||
/*!
|
||||
* Ping slot channel datarate
|
||||
*/
|
||||
#define AU915_PING_SLOT_CHANNEL_DR DR_10
|
||||
#define AU915_PING_SLOT_CHANNEL_DR DR_8
|
||||
|
||||
/*!
|
||||
* LoRaMac maximum number of bands
|
||||
@@ -245,9 +255,9 @@
|
||||
|
||||
/*!
|
||||
* Band 0 definition
|
||||
* { DutyCycle, TxMaxPower, LastJoinTxDoneTime, LastTxDoneTime, TimeOff }
|
||||
* Band = { DutyCycle, TxMaxPower, LastBandUpdateTime, TimeCredits, MaxTimeCredits, ReadyForTransmission }
|
||||
*/
|
||||
#define AU915_BAND0 { 1, AU915_MAX_TX_POWER, 0, 0, 0 } // 100.0 %
|
||||
#define AU915_BAND0 { 1, AU915_MAX_TX_POWER, 0, 0, 0, 0 } // 100.0 %
|
||||
|
||||
/*!
|
||||
* Defines the first channel for RX window 1 for US band
|
||||
@@ -289,30 +299,16 @@ static const int8_t DatarateOffsetsAU915[7][6] =
|
||||
};
|
||||
|
||||
/*!
|
||||
* Maximum payload with respect to the datarate index. Cannot operate with repeater.
|
||||
* Maximum payload with respect to the datarate index.
|
||||
* The table is valid for the dwell time configuration of 0 for uplinks.
|
||||
*/
|
||||
static const uint8_t MaxPayloadOfDatarateDwell0AU915[] = { 51, 51, 51, 115, 242, 242, 242, 242, 0, 53, 129, 242, 242, 242, 242 };
|
||||
static const uint8_t MaxPayloadOfDatarateDwell0AU915[] = { 51, 51, 51, 115, 242, 242, 242, 0, 53, 129, 242, 242, 242, 242 };
|
||||
|
||||
/*!
|
||||
* Maximum payload with respect to the datarate index. Can operate with repeater.
|
||||
* The table is valid for the dwell time configuration of 0 for uplinks. The table provides
|
||||
* repeater support.
|
||||
*/
|
||||
static const uint8_t MaxPayloadOfDatarateRepeaterDwell0AU915[] = { 51, 51, 51, 115, 222, 222, 222, 0, 33, 109, 222, 222, 222, 222 };
|
||||
|
||||
/*!
|
||||
* Maximum payload with respect to the datarate index. Cannot operate with repeater.
|
||||
* Maximum payload with respect to the datarate index.
|
||||
* The table is valid for the dwell time configuration of 1 for uplinks.
|
||||
*/
|
||||
static const uint8_t MaxPayloadOfDatarateDwell1AU915[] = { 0, 0, 11, 53, 125, 242, 242, 0, 53, 129, 129, 242, 242, 242, 242 };
|
||||
|
||||
/*!
|
||||
* Maximum payload with respect to the datarate index. Can operate with repeater.
|
||||
* The table is valid for the dwell time configuration of 1 for uplinks. The table provides
|
||||
* repeater support.
|
||||
*/
|
||||
static const uint8_t MaxPayloadOfDatarateRepeaterDwell1AU915[] = { 0, 0, 11, 53, 125, 242, 242, 0, 33, 119, 129, 242, 242, 242, 242 };
|
||||
static const uint8_t MaxPayloadOfDatarateDwell1AU915[] = { 0, 0, 11, 53, 125, 242, 242, 0, 53, 129, 242, 242, 242, 242 };
|
||||
|
||||
/*!
|
||||
* \brief The function gets a value of a specific phy attribute.
|
||||
@@ -469,13 +465,6 @@ uint8_t RegionAU915DlChannelReq( DlChannelReqParams_t* dlChannelReq );
|
||||
*/
|
||||
int8_t RegionAU915AlternateDr( int8_t currentDr, AlternateDrType_t type );
|
||||
|
||||
/*!
|
||||
* \brief Calculates the back-off time.
|
||||
*
|
||||
* \param [IN] calcBackOff Pointer to the function parameters.
|
||||
*/
|
||||
void RegionAU915CalcBackOff( CalcBackOffParams_t* calcBackOff );
|
||||
|
||||
/*!
|
||||
* \brief Searches and set the next random available channel
|
||||
*
|
||||
@@ -537,4 +526,8 @@ uint8_t RegionAU915ApplyDrOffset( uint8_t downlinkDwellTime, int8_t dr, int8_t d
|
||||
|
||||
/*! \} defgroup REGIONAU915 */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // __REGION_AU915_H__
|
||||
|
@@ -128,38 +128,12 @@ static bool VerifyRfFreq( uint32_t freq )
|
||||
return true;
|
||||
}
|
||||
|
||||
static uint8_t CountNbOfEnabledChannels( uint8_t datarate, uint16_t* channelsMask, ChannelParams_t* channels, Band_t* bands, uint8_t* enabledChannels, uint8_t* delayTx )
|
||||
static TimerTime_t GetTimeOnAir( int8_t datarate, uint16_t pktLen )
|
||||
{
|
||||
uint8_t nbEnabledChannels = 0;
|
||||
uint8_t delayTransmission = 0;
|
||||
int8_t phyDr = DataratesCN470[datarate];
|
||||
uint32_t bandwidth = GetBandwidth( datarate );
|
||||
|
||||
for( uint8_t i = 0, k = 0; i < CN470_MAX_NB_CHANNELS; i += 16, k++ )
|
||||
{
|
||||
for( uint8_t j = 0; j < 16; j++ )
|
||||
{
|
||||
if( ( channelsMask[k] & ( 1 << j ) ) != 0 )
|
||||
{
|
||||
if( channels[i + j].Frequency == 0 )
|
||||
{ // Check if the channel is enabled
|
||||
continue;
|
||||
}
|
||||
if( RegionCommonValueInRange( datarate, channels[i + j].DrRange.Fields.Min,
|
||||
channels[i + j].DrRange.Fields.Max ) == false )
|
||||
{ // Check if the current channel selection supports the given datarate
|
||||
continue;
|
||||
}
|
||||
if( bands[channels[i + j].Band].TimeOff > 0 )
|
||||
{ // Check if the band is available for transmission
|
||||
delayTransmission++;
|
||||
continue;
|
||||
}
|
||||
enabledChannels[nbEnabledChannels++] = i + j;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
*delayTx = delayTransmission;
|
||||
return nbEnabledChannels;
|
||||
return Radio.TimeOnAir( MODEM_LORA, bandwidth, phyDr, 1, 8, false, pktLen, true );
|
||||
}
|
||||
|
||||
PhyParam_t RegionCN470GetPhyParam( GetPhyParams_t* getPhy )
|
||||
@@ -213,11 +187,6 @@ PhyParam_t RegionCN470GetPhyParam( GetPhyParams_t* getPhy )
|
||||
phyParam.Value = MaxPayloadOfDatarateCN470[getPhy->Datarate];
|
||||
break;
|
||||
}
|
||||
case PHY_MAX_PAYLOAD_REPEATER:
|
||||
{
|
||||
phyParam.Value = MaxPayloadOfDatarateRepeaterCN470[getPhy->Datarate];
|
||||
break;
|
||||
}
|
||||
case PHY_DUTY_CYCLE:
|
||||
{
|
||||
phyParam.Value = CN470_DUTY_CYCLE_ENABLED;
|
||||
@@ -309,6 +278,11 @@ PhyParam_t RegionCN470GetPhyParam( GetPhyParams_t* getPhy )
|
||||
phyParam.fValue = CN470_DEFAULT_ANTENNA_GAIN;
|
||||
break;
|
||||
}
|
||||
case PHY_BEACON_CHANNEL_FREQ:
|
||||
{
|
||||
phyParam.Value = CN470_BEACON_CHANNEL_FREQ;
|
||||
break;
|
||||
}
|
||||
case PHY_BEACON_FORMAT:
|
||||
{
|
||||
phyParam.BeaconFormat.BeaconSize = CN470_BEACON_SIZE;
|
||||
@@ -331,11 +305,26 @@ PhyParam_t RegionCN470GetPhyParam( GetPhyParams_t* getPhy )
|
||||
phyParam.Value = CN470_BEACON_NB_CHANNELS;
|
||||
break;
|
||||
}
|
||||
case PHY_PING_SLOT_CHANNEL_FREQ:
|
||||
{
|
||||
phyParam.Value = CN470_PING_SLOT_CHANNEL_FREQ;
|
||||
break;
|
||||
}
|
||||
case PHY_PING_SLOT_CHANNEL_DR:
|
||||
{
|
||||
phyParam.Value = CN470_PING_SLOT_CHANNEL_DR;
|
||||
break;
|
||||
}
|
||||
case PHY_SF_FROM_DR:
|
||||
{
|
||||
phyParam.Value = DataratesCN470[getPhy->Datarate];
|
||||
break;
|
||||
}
|
||||
case PHY_BW_FROM_DR:
|
||||
{
|
||||
phyParam.Value = GetBandwidth( getPhy->Datarate );
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
break;
|
||||
@@ -347,7 +336,8 @@ PhyParam_t RegionCN470GetPhyParam( GetPhyParams_t* getPhy )
|
||||
|
||||
void RegionCN470SetBandTxDone( SetBandTxDoneParams_t* txDone )
|
||||
{
|
||||
RegionCommonSetBandTxDone( txDone->Joined, &NvmCtx.Bands[NvmCtx.Channels[txDone->Channel].Band], txDone->LastTxDoneTime );
|
||||
RegionCommonSetBandTxDone( &NvmCtx.Bands[NvmCtx.Channels[txDone->Channel].Band],
|
||||
txDone->LastTxAirTime, txDone->Joined, txDone->ElapsedTimeSinceStartUp );
|
||||
}
|
||||
|
||||
void RegionCN470InitDefaults( InitDefaultsParams_t* params )
|
||||
@@ -359,11 +349,14 @@ void RegionCN470InitDefaults( InitDefaultsParams_t* params )
|
||||
|
||||
switch( params->Type )
|
||||
{
|
||||
case INIT_TYPE_INIT:
|
||||
case INIT_TYPE_BANDS:
|
||||
{
|
||||
// Initialize bands
|
||||
memcpy1( ( uint8_t* )NvmCtx.Bands, ( uint8_t* )bands, sizeof( Band_t ) * CN470_MAX_NB_BANDS );
|
||||
|
||||
break;
|
||||
}
|
||||
case INIT_TYPE_INIT:
|
||||
{
|
||||
// Channels
|
||||
// 125 kHz channels
|
||||
for( uint8_t i = 0; i < CN470_MAX_NB_CHANNELS; i++ )
|
||||
@@ -374,21 +367,13 @@ void RegionCN470InitDefaults( InitDefaultsParams_t* params )
|
||||
}
|
||||
|
||||
// Initialize the channels default mask
|
||||
#if 0
|
||||
NvmCtx.ChannelsDefaultMask[0] = 0xFFFF;
|
||||
NvmCtx.ChannelsDefaultMask[1] = 0xFFFF;
|
||||
NvmCtx.ChannelsDefaultMask[2] = 0xFFFF;
|
||||
NvmCtx.ChannelsDefaultMask[3] = 0xFFFF;
|
||||
NvmCtx.ChannelsDefaultMask[4] = 0xFFFF;
|
||||
NvmCtx.ChannelsDefaultMask[5] = 0xFFFF;
|
||||
#else
|
||||
NvmCtx.ChannelsDefaultMask[0] = 0x00FF;
|
||||
NvmCtx.ChannelsDefaultMask[1] = 0x0000;
|
||||
NvmCtx.ChannelsDefaultMask[2] = 0x0000;
|
||||
NvmCtx.ChannelsDefaultMask[3] = 0x0000;
|
||||
NvmCtx.ChannelsDefaultMask[4] = 0x0000;
|
||||
NvmCtx.ChannelsDefaultMask[5] = 0x0000;
|
||||
#endif
|
||||
|
||||
// Update the channels mask
|
||||
RegionCommonChanMaskCopy( NvmCtx.ChannelsMask, NvmCtx.ChannelsDefaultMask, 6 );
|
||||
break;
|
||||
@@ -424,6 +409,10 @@ bool RegionCN470Verify( VerifyParams_t* verify, PhyAttribute_t phyAttribute )
|
||||
{
|
||||
switch( phyAttribute )
|
||||
{
|
||||
case PHY_FREQUENCY:
|
||||
{
|
||||
return VerifyRfFreq( verify->Frequency );
|
||||
}
|
||||
case PHY_TX_DR:
|
||||
case PHY_DEF_TX_DR:
|
||||
{
|
||||
@@ -506,7 +495,6 @@ void RegionCN470ComputeRxWindowParameters( int8_t datarate, uint8_t minRxSymbols
|
||||
bool RegionCN470RxConfig( RxConfigParams_t* rxConfig, int8_t* datarate )
|
||||
{
|
||||
int8_t dr = rxConfig->Datarate;
|
||||
uint8_t maxPayload = 0;
|
||||
int8_t phyDr = 0;
|
||||
uint32_t frequency = rxConfig->Frequency;
|
||||
|
||||
@@ -529,15 +517,7 @@ bool RegionCN470RxConfig( RxConfigParams_t* rxConfig, int8_t* datarate )
|
||||
// Radio configuration
|
||||
Radio.SetRxConfig( MODEM_LORA, rxConfig->Bandwidth, phyDr, 1, 0, 8, rxConfig->WindowTimeout, false, 0, false, 0, 0, true, rxConfig->RxContinuous );
|
||||
|
||||
if( rxConfig->RepeaterSupport == true )
|
||||
{
|
||||
maxPayload = MaxPayloadOfDatarateRepeaterCN470[dr];
|
||||
}
|
||||
else
|
||||
{
|
||||
maxPayload = MaxPayloadOfDatarateCN470[dr];
|
||||
}
|
||||
Radio.SetMaxPayloadLength( MODEM_LORA, maxPayload + LORA_MAC_FRMPAYLOAD_OVERHEAD );
|
||||
Radio.SetMaxPayloadLength( MODEM_LORA, MaxPayloadOfDatarateCN470[dr] + LORAMAC_FRAME_PAYLOAD_OVERHEAD_SIZE );
|
||||
|
||||
*datarate = (uint8_t) dr;
|
||||
return true;
|
||||
@@ -555,11 +535,11 @@ bool RegionCN470TxConfig( TxConfigParams_t* txConfig, int8_t* txPower, TimerTime
|
||||
// Setup the radio frequency
|
||||
Radio.SetChannel( NvmCtx.Channels[txConfig->Channel].Frequency );
|
||||
|
||||
Radio.SetTxConfig( MODEM_LORA, phyTxPower, 0, 0, phyDr, 1, 8, false, true, 0, 0, false, 3000 );
|
||||
Radio.SetTxConfig( MODEM_LORA, phyTxPower, 0, 0, phyDr, 1, 8, false, true, 0, 0, false, 4000 );
|
||||
// Setup maximum payload lenght of the radio driver
|
||||
Radio.SetMaxPayloadLength( MODEM_LORA, txConfig->PktLen );
|
||||
// Get the time-on-air of the next tx frame
|
||||
*txTimeOnAir = Radio.TimeOnAir( MODEM_LORA, txConfig->PktLen );
|
||||
// Update time-on-air
|
||||
*txTimeOnAir = GetTimeOnAir( txConfig->Datarate, txConfig->PktLen );
|
||||
*txPower = txPowerLimited;
|
||||
|
||||
return true;
|
||||
@@ -708,28 +688,14 @@ int8_t RegionCN470AlternateDr( int8_t currentDr, AlternateDrType_t type )
|
||||
return currentDr;
|
||||
}
|
||||
|
||||
void RegionCN470CalcBackOff( CalcBackOffParams_t* calcBackOff )
|
||||
{
|
||||
RegionCommonCalcBackOffParams_t calcBackOffParams;
|
||||
|
||||
calcBackOffParams.Channels = NvmCtx.Channels;
|
||||
calcBackOffParams.Bands = NvmCtx.Bands;
|
||||
calcBackOffParams.LastTxIsJoinRequest = calcBackOff->LastTxIsJoinRequest;
|
||||
calcBackOffParams.Joined = calcBackOff->Joined;
|
||||
calcBackOffParams.DutyCycleEnabled = calcBackOff->DutyCycleEnabled;
|
||||
calcBackOffParams.Channel = calcBackOff->Channel;
|
||||
calcBackOffParams.ElapsedTime = calcBackOff->ElapsedTime;
|
||||
calcBackOffParams.TxTimeOnAir = calcBackOff->TxTimeOnAir;
|
||||
|
||||
RegionCommonCalcBackOff( &calcBackOffParams );
|
||||
}
|
||||
|
||||
LoRaMacStatus_t RegionCN470NextChannel( NextChanParams_t* nextChanParams, uint8_t* channel, TimerTime_t* time, TimerTime_t* aggregatedTimeOff )
|
||||
{
|
||||
uint8_t nbEnabledChannels = 0;
|
||||
uint8_t delayTx = 0;
|
||||
uint8_t nbRestrictedChannels = 0;
|
||||
uint8_t enabledChannels[CN470_MAX_NB_CHANNELS] = { 0 };
|
||||
TimerTime_t nextTxDelay = 0;
|
||||
RegionCommonIdentifyChannelsParam_t identifyChannelsParam;
|
||||
RegionCommonCountNbOfEnabledChannelsParams_t countChannelsParams;
|
||||
LoRaMacStatus_t status = LORAMAC_STATUS_NO_CHANNEL_FOUND;
|
||||
|
||||
// Count 125kHz channels
|
||||
if( RegionCommonCountChannels( NvmCtx.ChannelsMask, 0, 6 ) == 0 )
|
||||
@@ -742,45 +708,35 @@ LoRaMacStatus_t RegionCN470NextChannel( NextChanParams_t* nextChanParams, uint8_
|
||||
NvmCtx.ChannelsMask[5] = 0xFFFF;
|
||||
}
|
||||
|
||||
if( nextChanParams->AggrTimeOff <= TimerGetElapsedTime( nextChanParams->LastAggrTx ) )
|
||||
{
|
||||
// Reset Aggregated time off
|
||||
*aggregatedTimeOff = 0;
|
||||
// Search how many channels are enabled
|
||||
countChannelsParams.Joined = nextChanParams->Joined;
|
||||
countChannelsParams.Datarate = nextChanParams->Datarate;
|
||||
countChannelsParams.ChannelsMask = NvmCtx.ChannelsMask;
|
||||
countChannelsParams.Channels = NvmCtx.Channels;
|
||||
countChannelsParams.Bands = NvmCtx.Bands;
|
||||
countChannelsParams.MaxNbChannels = CN470_MAX_NB_CHANNELS;
|
||||
countChannelsParams.JoinChannels = 0;
|
||||
|
||||
// Update bands Time OFF
|
||||
nextTxDelay = RegionCommonUpdateBandTimeOff( nextChanParams->Joined, nextChanParams->DutyCycleEnabled, NvmCtx.Bands, CN470_MAX_NB_BANDS );
|
||||
identifyChannelsParam.AggrTimeOff = nextChanParams->AggrTimeOff;
|
||||
identifyChannelsParam.LastAggrTx = nextChanParams->LastAggrTx;
|
||||
identifyChannelsParam.DutyCycleEnabled = nextChanParams->DutyCycleEnabled;
|
||||
identifyChannelsParam.MaxBands = CN470_MAX_NB_BANDS;
|
||||
|
||||
// Search how many channels are enabled
|
||||
nbEnabledChannels = CountNbOfEnabledChannels( nextChanParams->Datarate,
|
||||
NvmCtx.ChannelsMask, NvmCtx.Channels,
|
||||
NvmCtx.Bands, enabledChannels, &delayTx );
|
||||
}
|
||||
else
|
||||
{
|
||||
delayTx++;
|
||||
nextTxDelay = nextChanParams->AggrTimeOff - TimerGetElapsedTime( nextChanParams->LastAggrTx );
|
||||
}
|
||||
identifyChannelsParam.ElapsedTimeSinceStartUp = nextChanParams->ElapsedTimeSinceStartUp;
|
||||
identifyChannelsParam.LastTxIsJoinRequest = nextChanParams->LastTxIsJoinRequest;
|
||||
identifyChannelsParam.ExpectedTimeOnAir = GetTimeOnAir( nextChanParams->Datarate, nextChanParams->PktLen );
|
||||
|
||||
if( nbEnabledChannels > 0 )
|
||||
identifyChannelsParam.CountNbOfEnabledChannelsParam = &countChannelsParams;
|
||||
|
||||
status = RegionCommonIdentifyChannels( &identifyChannelsParam, aggregatedTimeOff, enabledChannels,
|
||||
&nbEnabledChannels, &nbRestrictedChannels, time );
|
||||
|
||||
if( status == LORAMAC_STATUS_OK )
|
||||
{
|
||||
// We found a valid channel
|
||||
*channel = enabledChannels[randr( 0, nbEnabledChannels - 1 )];
|
||||
|
||||
*time = 0;
|
||||
return LORAMAC_STATUS_OK;
|
||||
}
|
||||
else
|
||||
{
|
||||
if( delayTx > 0 )
|
||||
{
|
||||
// Delay transmission due to AggregatedTimeOff or to a band time off
|
||||
*time = nextTxDelay;
|
||||
return LORAMAC_STATUS_DUTYCYCLE_RESTRICTED;
|
||||
}
|
||||
// Datarate not supported by any channel
|
||||
*time = 0;
|
||||
return LORAMAC_STATUS_NO_CHANNEL_FOUND;
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
LoRaMacStatus_t RegionCN470ChannelAdd( ChannelAddParams_t* channelAdd )
|
||||
|
@@ -37,6 +37,11 @@
|
||||
#ifndef __REGION_CN470_H__
|
||||
#define __REGION_CN470_H__
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
#include "region/Region.h"
|
||||
|
||||
/*!
|
||||
@@ -187,6 +192,11 @@
|
||||
*/
|
||||
#define CN470_BEACON_CHANNEL_STEPWIDTH 200000
|
||||
|
||||
/*!
|
||||
* Ping slot channel frequency
|
||||
*/
|
||||
#define CN470_PING_SLOT_CHANNEL_FREQ 508300000
|
||||
|
||||
/*!
|
||||
* Number of possible beacon channels
|
||||
*/
|
||||
@@ -229,9 +239,9 @@
|
||||
|
||||
/*!
|
||||
* Band 0 definition
|
||||
* { DutyCycle, TxMaxPower, LastJoinTxDoneTime, LastTxDoneTime, TimeOff }
|
||||
* Band = { DutyCycle, TxMaxPower, LastBandUpdateTime, TimeCredits, MaxTimeCredits, ReadyForTransmission }
|
||||
*/
|
||||
#define CN470_BAND0 { 1, CN470_MAX_TX_POWER, 0, 0, 0 } // 100.0 %
|
||||
#define CN470_BAND0 { 1, CN470_MAX_TX_POWER, 0, 0, 0, 0 } // 100.0 %
|
||||
|
||||
/*!
|
||||
* Defines the first channel for RX window 1 for CN470 band
|
||||
@@ -259,14 +269,9 @@ static const uint8_t DataratesCN470[] = { 12, 11, 10, 9, 8, 7 };
|
||||
static const uint32_t BandwidthsCN470[] = { 125000, 125000, 125000, 125000, 125000, 125000 };
|
||||
|
||||
/*!
|
||||
* Maximum payload with respect to the datarate index. Cannot operate with repeater.
|
||||
* Maximum payload with respect to the datarate index.
|
||||
*/
|
||||
static const uint8_t MaxPayloadOfDatarateCN470[] = { 51, 51, 51, 115, 222, 222 };
|
||||
|
||||
/*!
|
||||
* Maximum payload with respect to the datarate index. Can operate with repeater.
|
||||
*/
|
||||
static const uint8_t MaxPayloadOfDatarateRepeaterCN470[] = { 51, 51, 51, 115, 222, 222 };
|
||||
static const uint8_t MaxPayloadOfDatarateCN470[] = { 51, 51, 51, 115, 242, 242 };
|
||||
|
||||
/*!
|
||||
* \brief The function gets a value of a specific phy attribute.
|
||||
@@ -423,13 +428,6 @@ uint8_t RegionCN470DlChannelReq( DlChannelReqParams_t* dlChannelReq );
|
||||
*/
|
||||
int8_t RegionCN470AlternateDr( int8_t currentDr, AlternateDrType_t type );
|
||||
|
||||
/*!
|
||||
* \brief Calculates the back-off time.
|
||||
*
|
||||
* \param [IN] calcBackOff Pointer to the function parameters.
|
||||
*/
|
||||
void RegionCN470CalcBackOff( CalcBackOffParams_t* calcBackOff );
|
||||
|
||||
/*!
|
||||
* \brief Searches and set the next random available channel
|
||||
*
|
||||
@@ -491,4 +489,8 @@ uint8_t RegionCN470ApplyDrOffset( uint8_t downlinkDwellTime, int8_t dr, int8_t d
|
||||
|
||||
/*! \} defgroup REGIONCN470 */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // __REGION_CN470_H__
|
||||
|
@@ -119,45 +119,21 @@ static bool VerifyRfFreq( uint32_t freq )
|
||||
return true;
|
||||
}
|
||||
|
||||
static uint8_t CountNbOfEnabledChannels( bool joined, uint8_t datarate, uint16_t* channelsMask, ChannelParams_t* channels, Band_t* bands, uint8_t* enabledChannels, uint8_t* delayTx )
|
||||
static TimerTime_t GetTimeOnAir( int8_t datarate, uint16_t pktLen )
|
||||
{
|
||||
uint8_t nbEnabledChannels = 0;
|
||||
uint8_t delayTransmission = 0;
|
||||
int8_t phyDr = DataratesCN779[datarate];
|
||||
uint32_t bandwidth = GetBandwidth( datarate );
|
||||
TimerTime_t timeOnAir = 0;
|
||||
|
||||
for( uint8_t i = 0, k = 0; i < CN779_MAX_NB_CHANNELS; i += 16, k++ )
|
||||
{
|
||||
for( uint8_t j = 0; j < 16; j++ )
|
||||
{
|
||||
if( ( channelsMask[k] & ( 1 << j ) ) != 0 )
|
||||
{
|
||||
if( channels[i + j].Frequency == 0 )
|
||||
{ // Check if the channel is enabled
|
||||
continue;
|
||||
}
|
||||
if( joined == false )
|
||||
{
|
||||
if( ( CN779_JOIN_CHANNELS & ( 1 << j ) ) == 0 )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
}
|
||||
if( RegionCommonValueInRange( datarate, channels[i + j].DrRange.Fields.Min,
|
||||
channels[i + j].DrRange.Fields.Max ) == false )
|
||||
{ // Check if the current channel selection supports the given datarate
|
||||
continue;
|
||||
}
|
||||
if( bands[channels[i + j].Band].TimeOff > 0 )
|
||||
{ // Check if the band is available for transmission
|
||||
delayTransmission++;
|
||||
continue;
|
||||
}
|
||||
enabledChannels[nbEnabledChannels++] = i + j;
|
||||
}
|
||||
}
|
||||
if( datarate == DR_7 )
|
||||
{ // High Speed FSK channel
|
||||
timeOnAir = Radio.TimeOnAir( MODEM_FSK, bandwidth, phyDr * 1000, 0, 5, false, pktLen, true );
|
||||
}
|
||||
|
||||
*delayTx = delayTransmission;
|
||||
return nbEnabledChannels;
|
||||
else
|
||||
{
|
||||
timeOnAir = Radio.TimeOnAir( MODEM_LORA, bandwidth, phyDr, 1, 8, false, pktLen, true );
|
||||
}
|
||||
return timeOnAir;
|
||||
}
|
||||
|
||||
PhyParam_t RegionCN779GetPhyParam( GetPhyParams_t* getPhy )
|
||||
@@ -211,11 +187,6 @@ PhyParam_t RegionCN779GetPhyParam( GetPhyParams_t* getPhy )
|
||||
phyParam.Value = MaxPayloadOfDatarateCN779[getPhy->Datarate];
|
||||
break;
|
||||
}
|
||||
case PHY_MAX_PAYLOAD_REPEATER:
|
||||
{
|
||||
phyParam.Value = MaxPayloadOfDatarateRepeaterCN779[getPhy->Datarate];
|
||||
break;
|
||||
}
|
||||
case PHY_DUTY_CYCLE:
|
||||
{
|
||||
phyParam.Value = CN779_DUTY_CYCLE_ENABLED;
|
||||
@@ -324,11 +295,26 @@ PhyParam_t RegionCN779GetPhyParam( GetPhyParams_t* getPhy )
|
||||
phyParam.Value = CN779_BEACON_CHANNEL_DR;
|
||||
break;
|
||||
}
|
||||
case PHY_PING_SLOT_CHANNEL_FREQ:
|
||||
{
|
||||
phyParam.Value = CN779_PING_SLOT_CHANNEL_FREQ;
|
||||
break;
|
||||
}
|
||||
case PHY_PING_SLOT_CHANNEL_DR:
|
||||
{
|
||||
phyParam.Value = CN779_PING_SLOT_CHANNEL_DR;
|
||||
break;
|
||||
}
|
||||
case PHY_SF_FROM_DR:
|
||||
{
|
||||
phyParam.Value = DataratesCN779[getPhy->Datarate];
|
||||
break;
|
||||
}
|
||||
case PHY_BW_FROM_DR:
|
||||
{
|
||||
phyParam.Value = GetBandwidth( getPhy->Datarate );
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
break;
|
||||
@@ -340,7 +326,8 @@ PhyParam_t RegionCN779GetPhyParam( GetPhyParams_t* getPhy )
|
||||
|
||||
void RegionCN779SetBandTxDone( SetBandTxDoneParams_t* txDone )
|
||||
{
|
||||
RegionCommonSetBandTxDone( txDone->Joined, &NvmCtx.Bands[NvmCtx.Channels[txDone->Channel].Band], txDone->LastTxDoneTime );
|
||||
RegionCommonSetBandTxDone( &NvmCtx.Bands[NvmCtx.Channels[txDone->Channel].Band],
|
||||
txDone->LastTxAirTime, txDone->Joined, txDone->ElapsedTimeSinceStartUp );
|
||||
}
|
||||
|
||||
void RegionCN779InitDefaults( InitDefaultsParams_t* params )
|
||||
@@ -352,10 +339,14 @@ void RegionCN779InitDefaults( InitDefaultsParams_t* params )
|
||||
|
||||
switch( params->Type )
|
||||
{
|
||||
case INIT_TYPE_INIT:
|
||||
case INIT_TYPE_BANDS:
|
||||
{
|
||||
// Initialize bands
|
||||
memcpy1( ( uint8_t* )NvmCtx.Bands, ( uint8_t* )bands, sizeof( Band_t ) * CN779_MAX_NB_BANDS );
|
||||
break;
|
||||
}
|
||||
case INIT_TYPE_INIT:
|
||||
{
|
||||
|
||||
// Channels
|
||||
NvmCtx.Channels[0] = ( ChannelParams_t ) CN779_LC1;
|
||||
@@ -364,6 +355,7 @@ void RegionCN779InitDefaults( InitDefaultsParams_t* params )
|
||||
|
||||
// Initialize the channels default mask
|
||||
NvmCtx.ChannelsDefaultMask[0] = LC( 1 ) + LC( 2 ) + LC( 3 );
|
||||
|
||||
// Update the channels mask
|
||||
RegionCommonChanMaskCopy( NvmCtx.ChannelsMask, NvmCtx.ChannelsDefaultMask, 1 );
|
||||
break;
|
||||
@@ -380,6 +372,11 @@ void RegionCN779InitDefaults( InitDefaultsParams_t* params )
|
||||
{
|
||||
// Restore channels default mask
|
||||
NvmCtx.ChannelsMask[0] |= NvmCtx.ChannelsDefaultMask[0];
|
||||
|
||||
// Channels
|
||||
NvmCtx.Channels[0] = ( ChannelParams_t ) CN779_LC1;
|
||||
NvmCtx.Channels[1] = ( ChannelParams_t ) CN779_LC2;
|
||||
NvmCtx.Channels[2] = ( ChannelParams_t ) CN779_LC3;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
@@ -399,6 +396,10 @@ bool RegionCN779Verify( VerifyParams_t* verify, PhyAttribute_t phyAttribute )
|
||||
{
|
||||
switch( phyAttribute )
|
||||
{
|
||||
case PHY_FREQUENCY:
|
||||
{
|
||||
return VerifyRfFreq( verify->Frequency );
|
||||
}
|
||||
case PHY_TX_DR:
|
||||
{
|
||||
return RegionCommonValueInRange( verify->DatarateParams.Datarate, CN779_TX_MIN_DATARATE, CN779_TX_MAX_DATARATE );
|
||||
@@ -529,7 +530,6 @@ bool RegionCN779RxConfig( RxConfigParams_t* rxConfig, int8_t* datarate )
|
||||
{
|
||||
RadioModems_t modem;
|
||||
int8_t dr = rxConfig->Datarate;
|
||||
uint8_t maxPayload = 0;
|
||||
int8_t phyDr = 0;
|
||||
uint32_t frequency = rxConfig->Frequency;
|
||||
|
||||
@@ -566,15 +566,7 @@ bool RegionCN779RxConfig( RxConfigParams_t* rxConfig, int8_t* datarate )
|
||||
Radio.SetRxConfig( modem, rxConfig->Bandwidth, phyDr, 1, 0, 8, rxConfig->WindowTimeout, false, 0, false, 0, 0, true, rxConfig->RxContinuous );
|
||||
}
|
||||
|
||||
if( rxConfig->RepeaterSupport == true )
|
||||
{
|
||||
maxPayload = MaxPayloadOfDatarateRepeaterCN779[dr];
|
||||
}
|
||||
else
|
||||
{
|
||||
maxPayload = MaxPayloadOfDatarateCN779[dr];
|
||||
}
|
||||
Radio.SetMaxPayloadLength( modem, maxPayload + LORA_MAC_FRMPAYLOAD_OVERHEAD );
|
||||
Radio.SetMaxPayloadLength( modem, MaxPayloadOfDatarateCN779[dr] + LORAMAC_FRAME_PAYLOAD_OVERHEAD_SIZE );
|
||||
|
||||
*datarate = (uint8_t) dr;
|
||||
return true;
|
||||
@@ -597,18 +589,19 @@ bool RegionCN779TxConfig( TxConfigParams_t* txConfig, int8_t* txPower, TimerTime
|
||||
if( txConfig->Datarate == DR_7 )
|
||||
{ // High Speed FSK channel
|
||||
modem = MODEM_FSK;
|
||||
Radio.SetTxConfig( modem, phyTxPower, 25000, bandwidth, phyDr * 1000, 0, 5, false, true, 0, 0, false, 3000 );
|
||||
Radio.SetTxConfig( modem, phyTxPower, 25000, bandwidth, phyDr * 1000, 0, 5, false, true, 0, 0, false, 4000 );
|
||||
}
|
||||
else
|
||||
{
|
||||
modem = MODEM_LORA;
|
||||
Radio.SetTxConfig( modem, phyTxPower, 0, bandwidth, phyDr, 1, 8, false, true, 0, 0, false, 3000 );
|
||||
Radio.SetTxConfig( modem, phyTxPower, 0, bandwidth, phyDr, 1, 8, false, true, 0, 0, false, 4000 );
|
||||
}
|
||||
|
||||
// Update time-on-air
|
||||
*txTimeOnAir = GetTimeOnAir( txConfig->Datarate, txConfig->PktLen );
|
||||
|
||||
// Setup maximum payload lenght of the radio driver
|
||||
Radio.SetMaxPayloadLength( modem, txConfig->PktLen );
|
||||
// Get the time-on-air of the next tx frame
|
||||
*txTimeOnAir = Radio.TimeOnAir( modem, txConfig->PktLen );
|
||||
|
||||
*txPower = txPowerLimited;
|
||||
return true;
|
||||
@@ -832,74 +825,54 @@ int8_t RegionCN779AlternateDr( int8_t currentDr, AlternateDrType_t type )
|
||||
return currentDr;
|
||||
}
|
||||
|
||||
void RegionCN779CalcBackOff( CalcBackOffParams_t* calcBackOff )
|
||||
{
|
||||
RegionCommonCalcBackOffParams_t calcBackOffParams;
|
||||
|
||||
calcBackOffParams.Channels = NvmCtx.Channels;
|
||||
calcBackOffParams.Bands = NvmCtx.Bands;
|
||||
calcBackOffParams.LastTxIsJoinRequest = calcBackOff->LastTxIsJoinRequest;
|
||||
calcBackOffParams.Joined = calcBackOff->Joined;
|
||||
calcBackOffParams.DutyCycleEnabled = calcBackOff->DutyCycleEnabled;
|
||||
calcBackOffParams.Channel = calcBackOff->Channel;
|
||||
calcBackOffParams.ElapsedTime = calcBackOff->ElapsedTime;
|
||||
calcBackOffParams.TxTimeOnAir = calcBackOff->TxTimeOnAir;
|
||||
|
||||
RegionCommonCalcBackOff( &calcBackOffParams );
|
||||
}
|
||||
|
||||
LoRaMacStatus_t RegionCN779NextChannel( NextChanParams_t* nextChanParams, uint8_t* channel, TimerTime_t* time, TimerTime_t* aggregatedTimeOff )
|
||||
{
|
||||
uint8_t nbEnabledChannels = 0;
|
||||
uint8_t delayTx = 0;
|
||||
uint8_t nbRestrictedChannels = 0;
|
||||
uint8_t enabledChannels[CN779_MAX_NB_CHANNELS] = { 0 };
|
||||
TimerTime_t nextTxDelay = 0;
|
||||
RegionCommonIdentifyChannelsParam_t identifyChannelsParam;
|
||||
RegionCommonCountNbOfEnabledChannelsParams_t countChannelsParams;
|
||||
LoRaMacStatus_t status = LORAMAC_STATUS_NO_CHANNEL_FOUND;
|
||||
|
||||
if( RegionCommonCountChannels( NvmCtx.ChannelsMask, 0, 1 ) == 0 )
|
||||
{ // Reactivate default channels
|
||||
NvmCtx.ChannelsMask[0] |= LC( 1 ) + LC( 2 ) + LC( 3 );
|
||||
}
|
||||
|
||||
if( nextChanParams->AggrTimeOff <= TimerGetElapsedTime( nextChanParams->LastAggrTx ) )
|
||||
{
|
||||
// Reset Aggregated time off
|
||||
*aggregatedTimeOff = 0;
|
||||
// Search how many channels are enabled
|
||||
countChannelsParams.Joined = nextChanParams->Joined;
|
||||
countChannelsParams.Datarate = nextChanParams->Datarate;
|
||||
countChannelsParams.ChannelsMask = NvmCtx.ChannelsMask;
|
||||
countChannelsParams.Channels = NvmCtx.Channels;
|
||||
countChannelsParams.Bands = NvmCtx.Bands;
|
||||
countChannelsParams.MaxNbChannels = CN779_MAX_NB_CHANNELS;
|
||||
countChannelsParams.JoinChannels = CN779_JOIN_CHANNELS;
|
||||
|
||||
// Update bands Time OFF
|
||||
nextTxDelay = RegionCommonUpdateBandTimeOff( nextChanParams->Joined, nextChanParams->DutyCycleEnabled, NvmCtx.Bands, CN779_MAX_NB_BANDS );
|
||||
identifyChannelsParam.AggrTimeOff = nextChanParams->AggrTimeOff;
|
||||
identifyChannelsParam.LastAggrTx = nextChanParams->LastAggrTx;
|
||||
identifyChannelsParam.DutyCycleEnabled = nextChanParams->DutyCycleEnabled;
|
||||
identifyChannelsParam.MaxBands = CN779_MAX_NB_BANDS;
|
||||
|
||||
// Search how many channels are enabled
|
||||
nbEnabledChannels = CountNbOfEnabledChannels( nextChanParams->Joined, nextChanParams->Datarate,
|
||||
NvmCtx.ChannelsMask, NvmCtx.Channels,
|
||||
NvmCtx.Bands, enabledChannels, &delayTx );
|
||||
}
|
||||
else
|
||||
{
|
||||
delayTx++;
|
||||
nextTxDelay = nextChanParams->AggrTimeOff - TimerGetElapsedTime( nextChanParams->LastAggrTx );
|
||||
}
|
||||
identifyChannelsParam.ElapsedTimeSinceStartUp = nextChanParams->ElapsedTimeSinceStartUp;
|
||||
identifyChannelsParam.LastTxIsJoinRequest = nextChanParams->LastTxIsJoinRequest;
|
||||
identifyChannelsParam.ExpectedTimeOnAir = GetTimeOnAir( nextChanParams->Datarate, nextChanParams->PktLen );
|
||||
|
||||
if( nbEnabledChannels > 0 )
|
||||
identifyChannelsParam.CountNbOfEnabledChannelsParam = &countChannelsParams;
|
||||
|
||||
status = RegionCommonIdentifyChannels( &identifyChannelsParam, aggregatedTimeOff, enabledChannels,
|
||||
&nbEnabledChannels, &nbRestrictedChannels, time );
|
||||
|
||||
if( status == LORAMAC_STATUS_OK )
|
||||
{
|
||||
// We found a valid channel
|
||||
*channel = enabledChannels[randr( 0, nbEnabledChannels - 1 )];
|
||||
|
||||
*time = 0;
|
||||
return LORAMAC_STATUS_OK;
|
||||
}
|
||||
else
|
||||
else if( status == LORAMAC_STATUS_NO_CHANNEL_FOUND )
|
||||
{
|
||||
if( delayTx > 0 )
|
||||
{
|
||||
// Delay transmission due to AggregatedTimeOff or to a band time off
|
||||
*time = nextTxDelay;
|
||||
return LORAMAC_STATUS_DUTYCYCLE_RESTRICTED;
|
||||
}
|
||||
// Datarate not supported by any channel, restore defaults
|
||||
NvmCtx.ChannelsMask[0] |= LC( 1 ) + LC( 2 ) + LC( 3 );
|
||||
*time = 0;
|
||||
return LORAMAC_STATUS_NO_CHANNEL_FOUND;
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
LoRaMacStatus_t RegionCN779ChannelAdd( ChannelAddParams_t* channelAdd )
|
||||
|
@@ -37,6 +37,11 @@
|
||||
#ifndef __REGION_CN779_H__
|
||||
#define __REGION_CN779_H__
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
#include "region/Region.h"
|
||||
|
||||
/*!
|
||||
@@ -199,6 +204,11 @@
|
||||
*/
|
||||
#define CN779_BEACON_CHANNEL_FREQ 785000000
|
||||
|
||||
/*!
|
||||
* Ping slot channel frequency
|
||||
*/
|
||||
#define CN779_PING_SLOT_CHANNEL_FREQ 785000000
|
||||
|
||||
/*!
|
||||
* Payload size of a beacon frame
|
||||
*/
|
||||
@@ -236,9 +246,9 @@
|
||||
|
||||
/*!
|
||||
* Band 0 definition
|
||||
* { DutyCycle, TxMaxPower, LastJoinTxDoneTime, LastTxDoneTime, TimeOff }
|
||||
* Band = { DutyCycle, TxMaxPower, LastBandUpdateTime, TimeCredits, MaxTimeCredits, ReadyForTransmission }
|
||||
*/
|
||||
#define CN779_BAND0 { 100, CN779_MAX_TX_POWER, 0, 0, 0 } // 1.0 %
|
||||
#define CN779_BAND0 { 100, CN779_MAX_TX_POWER, 0, 0, 0, 0 } // 1.0 %
|
||||
|
||||
/*!
|
||||
* LoRaMac default channel 1
|
||||
@@ -273,15 +283,10 @@ static const uint8_t DataratesCN779[] = { 12, 11, 10, 9, 8, 7, 7, 50 };
|
||||
static const uint32_t BandwidthsCN779[] = { 125000, 125000, 125000, 125000, 125000, 125000, 250000, 0 };
|
||||
|
||||
/*!
|
||||
* Maximum payload with respect to the datarate index. Cannot operate with repeater.
|
||||
* Maximum payload with respect to the datarate index.
|
||||
*/
|
||||
static const uint8_t MaxPayloadOfDatarateCN779[] = { 51, 51, 51, 115, 242, 242, 242, 242 };
|
||||
|
||||
/*!
|
||||
* Maximum payload with respect to the datarate index. Can operate with repeater.
|
||||
*/
|
||||
static const uint8_t MaxPayloadOfDatarateRepeaterCN779[] = { 51, 51, 51, 115, 222, 222, 222, 222 };
|
||||
|
||||
/*!
|
||||
* \brief The function gets a value of a specific phy attribute.
|
||||
*
|
||||
@@ -437,13 +442,6 @@ uint8_t RegionCN779DlChannelReq( DlChannelReqParams_t* dlChannelReq );
|
||||
*/
|
||||
int8_t RegionCN779AlternateDr( int8_t currentDr, AlternateDrType_t type );
|
||||
|
||||
/*!
|
||||
* \brief Calculates the back-off time.
|
||||
*
|
||||
* \param [IN] calcBackOff Pointer to the function parameters.
|
||||
*/
|
||||
void RegionCN779CalcBackOff( CalcBackOffParams_t* calcBackOff );
|
||||
|
||||
/*!
|
||||
* \brief Searches and set the next random available channel
|
||||
*
|
||||
@@ -505,4 +503,8 @@ uint8_t RegionCN779ApplyDrOffset( uint8_t downlinkDwellTime, int8_t dr, int8_t d
|
||||
|
||||
/*! \} defgroup REGIONCN779 */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // __REGION_CN779_H__
|
||||
|
@@ -33,9 +33,108 @@
|
||||
#include "utilities.h"
|
||||
#include "RegionCommon.h"
|
||||
|
||||
#define BACKOFF_DC_1_HOUR 100
|
||||
#define BACKOFF_DC_10_HOURS 1000
|
||||
#define BACKOFF_DC_24_HOURS 10000
|
||||
#define BACKOFF_DC_1_HOUR 100
|
||||
#define BACKOFF_DC_10_HOURS 1000
|
||||
#define BACKOFF_DC_24_HOURS 10000
|
||||
#define BACKOFF_DC_TIMER_PERIOD_FACTOR 100
|
||||
|
||||
#ifndef DUTY_CYCLE_TIME_PERIOD
|
||||
/*!
|
||||
* Default duty cycle time period is 1 hour = 3600000 ms
|
||||
*/
|
||||
#define DUTY_CYCLE_TIME_PERIOD 3600000
|
||||
#endif
|
||||
|
||||
static uint16_t GetDutyCycle( Band_t* band, bool joined, SysTime_t elapsedTimeSinceStartup )
|
||||
{
|
||||
uint16_t joinDutyCycle = RegionCommonGetJoinDc( elapsedTimeSinceStartup );
|
||||
uint16_t dutyCycle = band->DCycle;
|
||||
|
||||
if( joined == false )
|
||||
{
|
||||
// Get the join duty cycle which depends on the runtime
|
||||
joinDutyCycle = RegionCommonGetJoinDc( elapsedTimeSinceStartup );
|
||||
// Take the most restrictive duty cycle
|
||||
dutyCycle = MAX( dutyCycle, joinDutyCycle );
|
||||
}
|
||||
|
||||
// Prevent value of 0
|
||||
if( dutyCycle == 0 )
|
||||
{
|
||||
dutyCycle = 1;
|
||||
}
|
||||
|
||||
return dutyCycle;
|
||||
}
|
||||
|
||||
static uint16_t SetMaxTimeCredits( Band_t* band, bool joined, SysTime_t elapsedTimeSinceStartup )
|
||||
{
|
||||
uint16_t dutyCycle = band->DCycle;
|
||||
uint8_t timePeriodFactor = 1;
|
||||
|
||||
// Get the band duty cycle. If not joined, the function either returns the join duty cycle
|
||||
// or the band duty cycle, whichever is more restrictive.
|
||||
dutyCycle = GetDutyCycle( band, joined, elapsedTimeSinceStartup );
|
||||
|
||||
if( joined == false )
|
||||
{
|
||||
// Apply a factor to increase the maximum time period of observation
|
||||
timePeriodFactor = dutyCycle / BACKOFF_DC_TIMER_PERIOD_FACTOR;
|
||||
}
|
||||
|
||||
// Setup the maximum allowed credits
|
||||
band->MaxTimeCredits = DUTY_CYCLE_TIME_PERIOD * timePeriodFactor;
|
||||
|
||||
// In case if it is the first time, update also the current
|
||||
// time credits
|
||||
if( band->LastBandUpdateTime == 0 )
|
||||
{
|
||||
band->TimeCredits = band->MaxTimeCredits;
|
||||
}
|
||||
|
||||
return dutyCycle;
|
||||
}
|
||||
|
||||
static uint16_t UpdateTimeCredits( Band_t* band, bool joined, bool dutyCycleEnabled,
|
||||
bool lastTxIsJoinRequest, SysTime_t elapsedTimeSinceStartup,
|
||||
TimerTime_t currentTime )
|
||||
{
|
||||
uint16_t dutyCycle = SetMaxTimeCredits( band, joined, elapsedTimeSinceStartup );
|
||||
|
||||
if( joined == false )
|
||||
{
|
||||
if( ( dutyCycleEnabled == false ) &&
|
||||
( lastTxIsJoinRequest == false ) )
|
||||
{
|
||||
// This is the case when the duty cycle is off and the last uplink frame was not a join.
|
||||
// This could happen in case of a rejoin, e.g. in compliance test mode.
|
||||
// In this special case we have to set the time off to 0, since the join duty cycle shall only
|
||||
// be applied after the first join request.
|
||||
band->TimeCredits = band->MaxTimeCredits;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if( dutyCycleEnabled == false )
|
||||
{
|
||||
band->TimeCredits = band->MaxTimeCredits;
|
||||
}
|
||||
}
|
||||
|
||||
// Get the difference between now and the last update
|
||||
band->TimeCredits += TimerGetElapsedTime( band->LastBandUpdateTime );
|
||||
|
||||
// Limit band credits to maximum
|
||||
if( band->TimeCredits > band->MaxTimeCredits )
|
||||
{
|
||||
band->TimeCredits = band->MaxTimeCredits;
|
||||
}
|
||||
|
||||
// Synchronize update time
|
||||
band->LastBandUpdateTime = currentTime;
|
||||
|
||||
return dutyCycle;
|
||||
}
|
||||
|
||||
static uint8_t CountChannels( uint16_t mask, uint8_t nbBits )
|
||||
{
|
||||
@@ -147,62 +246,87 @@ void RegionCommonChanMaskCopy( uint16_t* channelsMaskDest, uint16_t* channelsMas
|
||||
}
|
||||
}
|
||||
|
||||
void RegionCommonSetBandTxDone( bool joined, Band_t* band, TimerTime_t lastTxDone )
|
||||
void RegionCommonSetBandTxDone( Band_t* band, TimerTime_t lastTxAirTime, bool joined, SysTime_t elapsedTimeSinceStartup )
|
||||
{
|
||||
if( joined == true )
|
||||
// Get the band duty cycle. If not joined, the function either returns the join duty cycle
|
||||
// or the band duty cycle, whichever is more restrictive.
|
||||
uint16_t dutyCycle = GetDutyCycle( band, joined, elapsedTimeSinceStartup );
|
||||
|
||||
// Reduce with transmission time
|
||||
if( band->TimeCredits > ( lastTxAirTime * dutyCycle ) )
|
||||
{
|
||||
band->LastTxDoneTime = lastTxDone;
|
||||
// Reduce time credits by the time of air
|
||||
band->TimeCredits -= ( lastTxAirTime * dutyCycle );
|
||||
}
|
||||
else
|
||||
{
|
||||
band->LastTxDoneTime = lastTxDone;
|
||||
band->LastJoinTxDoneTime = lastTxDone;
|
||||
band->TimeCredits = 0;
|
||||
}
|
||||
}
|
||||
|
||||
TimerTime_t RegionCommonUpdateBandTimeOff( bool joined, bool dutyCycle, Band_t* bands, uint8_t nbBands )
|
||||
TimerTime_t RegionCommonUpdateBandTimeOff( bool joined, Band_t* bands,
|
||||
uint8_t nbBands, bool dutyCycleEnabled,
|
||||
bool lastTxIsJoinRequest, SysTime_t elapsedTimeSinceStartup,
|
||||
TimerTime_t expectedTimeOnAir )
|
||||
{
|
||||
TimerTime_t nextTxDelay = ( TimerTime_t )( -1 );
|
||||
TimerTime_t minTimeToWait = TIMERTIME_T_MAX;
|
||||
TimerTime_t currentTime = TimerGetCurrentTime( );
|
||||
TimerTime_t creditCosts = 0;
|
||||
uint16_t dutyCycle = 1;
|
||||
uint8_t validBands = 0;
|
||||
|
||||
// Update bands Time OFF
|
||||
for( uint8_t i = 0; i < nbBands; i++ )
|
||||
{
|
||||
if( joined == false )
|
||||
{
|
||||
TimerTime_t txDoneTime = MAX( TimerGetElapsedTime( bands[i].LastJoinTxDoneTime ),
|
||||
( dutyCycle == true ) ? TimerGetElapsedTime( bands[i].LastTxDoneTime ) : 0 );
|
||||
// Synchronization of bands and credits
|
||||
dutyCycle = UpdateTimeCredits( &bands[i], joined, dutyCycleEnabled,
|
||||
lastTxIsJoinRequest, elapsedTimeSinceStartup,
|
||||
currentTime );
|
||||
|
||||
if( bands[i].TimeOff <= txDoneTime )
|
||||
{
|
||||
bands[i].TimeOff = 0;
|
||||
}
|
||||
if( bands[i].TimeOff != 0 )
|
||||
{
|
||||
nextTxDelay = MIN( bands[i].TimeOff - txDoneTime, nextTxDelay );
|
||||
}
|
||||
// Calculate the credit costs for the next transmission
|
||||
// with the duty cycle and the expected time on air
|
||||
creditCosts = expectedTimeOnAir * dutyCycle;
|
||||
|
||||
// Check if the band is ready for transmission. Its ready,
|
||||
// when the duty cycle is off, or the TimeCredits of the band
|
||||
// is higher than the credit costs for the transmission.
|
||||
if( ( bands[i].TimeCredits > creditCosts ) ||
|
||||
( dutyCycleEnabled == false ) )
|
||||
{
|
||||
bands[i].ReadyForTransmission = true;
|
||||
// This band is a potential candidate for an
|
||||
// upcoming transmission, so increase the counter.
|
||||
validBands++;
|
||||
}
|
||||
else
|
||||
{
|
||||
if( dutyCycle == true )
|
||||
// In this case, the band has not enough credits
|
||||
// for the next transmission.
|
||||
bands[i].ReadyForTransmission = false;
|
||||
|
||||
if( bands[i].MaxTimeCredits > creditCosts )
|
||||
{
|
||||
if( bands[i].TimeOff <= TimerGetElapsedTime( bands[i].LastTxDoneTime ) )
|
||||
{
|
||||
bands[i].TimeOff = 0;
|
||||
}
|
||||
if( bands[i].TimeOff != 0 )
|
||||
{
|
||||
nextTxDelay = MIN( bands[i].TimeOff - TimerGetElapsedTime( bands[i].LastTxDoneTime ),
|
||||
nextTxDelay );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
nextTxDelay = 0;
|
||||
bands[i].TimeOff = 0;
|
||||
// The band can only be taken into account, if the maximum credits
|
||||
// of the band are higher than the credit costs.
|
||||
// We calculate the minTimeToWait among the bands which are not
|
||||
// ready for transmission and which are potentially available
|
||||
// for a transmission in the future.
|
||||
minTimeToWait = MIN( minTimeToWait, ( creditCosts - bands[i].TimeCredits ) );
|
||||
// This band is a potential candidate for an
|
||||
// upcoming transmission (even if its time credits are not enough
|
||||
// at the moment), so increase the counter.
|
||||
validBands++;
|
||||
}
|
||||
}
|
||||
}
|
||||
return nextTxDelay;
|
||||
|
||||
|
||||
if( validBands == 0 )
|
||||
{
|
||||
// There is no valid band available to handle a transmission
|
||||
// in the given DUTY_CYCLE_TIME_PERIOD.
|
||||
return TIMERTIME_T_MAX;
|
||||
}
|
||||
return minTimeToWait;
|
||||
}
|
||||
|
||||
uint8_t RegionCommonParseLinkAdrReq( uint8_t* payload, RegionCommonLinkAdrParams_t* linkAdrParams )
|
||||
@@ -311,50 +435,6 @@ int8_t RegionCommonComputeTxPower( int8_t txPowerIndex, float maxEirp, float ant
|
||||
return phyTxPower;
|
||||
}
|
||||
|
||||
void RegionCommonCalcBackOff( RegionCommonCalcBackOffParams_t* calcBackOffParams )
|
||||
{
|
||||
uint8_t bandIdx = calcBackOffParams->Channels[calcBackOffParams->Channel].Band;
|
||||
uint16_t dutyCycle = calcBackOffParams->Bands[bandIdx].DCycle;
|
||||
uint16_t joinDutyCycle = 0;
|
||||
|
||||
// Reset time-off to initial value.
|
||||
calcBackOffParams->Bands[bandIdx].TimeOff = 0;
|
||||
|
||||
if( calcBackOffParams->Joined == false )
|
||||
{
|
||||
// Get the join duty cycle
|
||||
joinDutyCycle = RegionCommonGetJoinDc( calcBackOffParams->ElapsedTime );
|
||||
// Apply the most restricting duty cycle
|
||||
dutyCycle = MAX( dutyCycle, joinDutyCycle );
|
||||
// Reset the timeoff if the last frame was not a join request and when the duty cycle is not enabled
|
||||
if( ( calcBackOffParams->DutyCycleEnabled == false ) && ( calcBackOffParams->LastTxIsJoinRequest == false ) )
|
||||
{
|
||||
// This is the case when the duty cycle is off and the last uplink frame was not a join.
|
||||
// This could happen in case of a rejoin, e.g. in compliance test mode.
|
||||
// In this special case we have to set the time off to 0, since the join duty cycle shall only
|
||||
// be applied after the first join request.
|
||||
calcBackOffParams->Bands[bandIdx].TimeOff = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Apply band time-off.
|
||||
calcBackOffParams->Bands[bandIdx].TimeOff = calcBackOffParams->TxTimeOnAir * dutyCycle - calcBackOffParams->TxTimeOnAir;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if( calcBackOffParams->DutyCycleEnabled == true )
|
||||
{
|
||||
calcBackOffParams->Bands[bandIdx].TimeOff = calcBackOffParams->TxTimeOnAir * dutyCycle - calcBackOffParams->TxTimeOnAir;
|
||||
}
|
||||
else
|
||||
{
|
||||
calcBackOffParams->Bands[bandIdx].TimeOff = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void RegionCommonRxBeaconSetup( RegionCommonRxBeaconSetupParams_t* rxBeaconSetupParams )
|
||||
{
|
||||
bool rxContinuous = true;
|
||||
@@ -382,3 +462,90 @@ void RegionCommonRxBeaconSetup( RegionCommonRxBeaconSetupParams_t* rxBeaconSetup
|
||||
|
||||
Radio.Rx( rxBeaconSetupParams->RxTime );
|
||||
}
|
||||
|
||||
void RegionCommonCountNbOfEnabledChannels( RegionCommonCountNbOfEnabledChannelsParams_t* countNbOfEnabledChannelsParams,
|
||||
uint8_t* enabledChannels, uint8_t* nbEnabledChannels, uint8_t* nbRestrictedChannels )
|
||||
{
|
||||
uint8_t nbChannelCount = 0;
|
||||
uint8_t nbRestrictedChannelsCount = 0;
|
||||
|
||||
for( uint8_t i = 0, k = 0; i < countNbOfEnabledChannelsParams->MaxNbChannels; i += 16, k++ )
|
||||
{
|
||||
for( uint8_t j = 0; j < 16; j++ )
|
||||
{
|
||||
if( ( countNbOfEnabledChannelsParams->ChannelsMask[k] & ( 1 << j ) ) != 0 )
|
||||
{
|
||||
if( countNbOfEnabledChannelsParams->Channels[i + j].Frequency == 0 )
|
||||
{ // Check if the channel is enabled
|
||||
continue;
|
||||
}
|
||||
if( ( countNbOfEnabledChannelsParams->Joined == false ) &&
|
||||
( countNbOfEnabledChannelsParams->JoinChannels > 0 ) )
|
||||
{
|
||||
if( ( countNbOfEnabledChannelsParams->JoinChannels & ( 1 << j ) ) == 0 )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
}
|
||||
if( RegionCommonValueInRange( countNbOfEnabledChannelsParams->Datarate,
|
||||
countNbOfEnabledChannelsParams->Channels[i + j].DrRange.Fields.Min,
|
||||
countNbOfEnabledChannelsParams->Channels[i + j].DrRange.Fields.Max ) == false )
|
||||
{ // Check if the current channel selection supports the given datarate
|
||||
continue;
|
||||
}
|
||||
if( countNbOfEnabledChannelsParams->Bands[countNbOfEnabledChannelsParams->Channels[i + j].Band].ReadyForTransmission == false )
|
||||
{ // Check if the band is available for transmission
|
||||
nbRestrictedChannelsCount++;
|
||||
continue;
|
||||
}
|
||||
enabledChannels[nbChannelCount++] = i + j;
|
||||
}
|
||||
}
|
||||
}
|
||||
*nbEnabledChannels = nbChannelCount;
|
||||
*nbRestrictedChannels = nbRestrictedChannelsCount;
|
||||
}
|
||||
|
||||
LoRaMacStatus_t RegionCommonIdentifyChannels( RegionCommonIdentifyChannelsParam_t* identifyChannelsParam,
|
||||
TimerTime_t* aggregatedTimeOff, uint8_t* enabledChannels,
|
||||
uint8_t* nbEnabledChannels, uint8_t* nbRestrictedChannels,
|
||||
TimerTime_t* nextTxDelay )
|
||||
{
|
||||
TimerTime_t elapsed = TimerGetElapsedTime( identifyChannelsParam->LastAggrTx );
|
||||
*nextTxDelay = identifyChannelsParam->AggrTimeOff - elapsed;
|
||||
*nbRestrictedChannels = 1;
|
||||
*nbEnabledChannels = 0;
|
||||
|
||||
if( ( identifyChannelsParam->LastAggrTx == 0 ) ||
|
||||
( identifyChannelsParam->AggrTimeOff <= elapsed ) )
|
||||
{
|
||||
// Reset Aggregated time off
|
||||
*aggregatedTimeOff = 0;
|
||||
|
||||
// Update bands Time OFF
|
||||
*nextTxDelay = RegionCommonUpdateBandTimeOff( identifyChannelsParam->CountNbOfEnabledChannelsParam->Joined,
|
||||
identifyChannelsParam->CountNbOfEnabledChannelsParam->Bands,
|
||||
identifyChannelsParam->MaxBands,
|
||||
identifyChannelsParam->DutyCycleEnabled,
|
||||
identifyChannelsParam->LastTxIsJoinRequest,
|
||||
identifyChannelsParam->ElapsedTimeSinceStartUp,
|
||||
identifyChannelsParam->ExpectedTimeOnAir );
|
||||
|
||||
RegionCommonCountNbOfEnabledChannels( identifyChannelsParam->CountNbOfEnabledChannelsParam, enabledChannels,
|
||||
nbEnabledChannels, nbRestrictedChannels );
|
||||
}
|
||||
|
||||
if( *nbEnabledChannels > 0 )
|
||||
{
|
||||
*nextTxDelay = 0;
|
||||
return LORAMAC_STATUS_OK;
|
||||
}
|
||||
else if( *nbRestrictedChannels > 0 )
|
||||
{
|
||||
return LORAMAC_STATUS_DUTYCYCLE_RESTRICTED;
|
||||
}
|
||||
else
|
||||
{
|
||||
return LORAMAC_STATUS_NO_CHANNEL_FOUND;
|
||||
}
|
||||
}
|
||||
|
@@ -37,9 +37,23 @@
|
||||
#ifndef __REGIONCOMMON_H__
|
||||
#define __REGIONCOMMON_H__
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
#include "LoRaMacTypes.h"
|
||||
#include "LoRaMacHeaderTypes.h"
|
||||
#include "region/Region.h"
|
||||
|
||||
/*!
|
||||
* Default ping slots periodicity
|
||||
*
|
||||
* Periodicity is equal to 2^REGION_COMMON_DEFAULT_PING_SLOT_PERIODICITY seconds.
|
||||
* Example: 2^7 = 128 seconds. The end-device will open an Rx slot every 128 seconds.
|
||||
*/
|
||||
#define REGION_COMMON_DEFAULT_PING_SLOT_PERIODICITY 7
|
||||
|
||||
typedef struct sRegionCommonLinkAdrParams
|
||||
{
|
||||
/*!
|
||||
@@ -132,42 +146,6 @@ typedef struct sRegionCommonLinkAdrReqVerifyParams
|
||||
int8_t MaxTxPower;
|
||||
}RegionCommonLinkAdrReqVerifyParams_t;
|
||||
|
||||
typedef struct sRegionCommonCalcBackOffParams
|
||||
{
|
||||
/*!
|
||||
* A pointer to region specific channels.
|
||||
*/
|
||||
ChannelParams_t* Channels;
|
||||
/*!
|
||||
* A pointer to region specific bands.
|
||||
*/
|
||||
Band_t* Bands;
|
||||
/*!
|
||||
* Set to true, if the last uplink was a join request.
|
||||
*/
|
||||
bool LastTxIsJoinRequest;
|
||||
/*!
|
||||
* Set to true, if the node is joined.
|
||||
*/
|
||||
bool Joined;
|
||||
/*!
|
||||
* Set to true, if the duty cycle is enabled.
|
||||
*/
|
||||
bool DutyCycleEnabled;
|
||||
/*!
|
||||
* The current channel.
|
||||
*/
|
||||
uint8_t Channel;
|
||||
/*!
|
||||
* The elapsed time since initialization.
|
||||
*/
|
||||
SysTime_t ElapsedTime;
|
||||
/*!
|
||||
* The time on air of the last Tx frame.
|
||||
*/
|
||||
TimerTime_t TxTimeOnAir;
|
||||
}RegionCommonCalcBackOffParams_t;
|
||||
|
||||
typedef struct sRegionCommonRxBeaconSetupParams
|
||||
{
|
||||
/*!
|
||||
@@ -200,6 +178,90 @@ typedef struct sRegionCommonRxBeaconSetupParams
|
||||
uint16_t SymbolTimeout;
|
||||
}RegionCommonRxBeaconSetupParams_t;
|
||||
|
||||
typedef struct sRegionCommonCountNbOfEnabledChannelsParams
|
||||
{
|
||||
/*!
|
||||
* Set to true, if the device is joined.
|
||||
*/
|
||||
bool Joined;
|
||||
/*!
|
||||
* The datarate to count the available channels.
|
||||
*/
|
||||
uint8_t Datarate;
|
||||
/*!
|
||||
* A pointer to the channels mask to verify.
|
||||
*/
|
||||
uint16_t* ChannelsMask;
|
||||
/*!
|
||||
* A pointer to the channels.
|
||||
*/
|
||||
ChannelParams_t* Channels;
|
||||
/*!
|
||||
* A pointer to the bands.
|
||||
*/
|
||||
Band_t* Bands;
|
||||
/*!
|
||||
* The number of available channels.
|
||||
*/
|
||||
uint16_t MaxNbChannels;
|
||||
/*!
|
||||
* A bitmask containing the join channels.
|
||||
*/
|
||||
uint16_t JoinChannels;
|
||||
}RegionCommonCountNbOfEnabledChannelsParams_t;
|
||||
|
||||
typedef struct sRegionCommonIdentifyChannelsParam
|
||||
{
|
||||
/*!
|
||||
* Aggregated time-off time.
|
||||
*/
|
||||
TimerTime_t AggrTimeOff;
|
||||
/*!
|
||||
* Time of the last aggregated TX.
|
||||
*/
|
||||
TimerTime_t LastAggrTx;
|
||||
/*!
|
||||
* Set to true, if the duty cycle is enabled, otherwise false.
|
||||
*/
|
||||
bool DutyCycleEnabled;
|
||||
/*!
|
||||
* Maximum number of bands.
|
||||
*/
|
||||
uint8_t MaxBands;
|
||||
/*!
|
||||
* Elapsed time since the start of the node.
|
||||
*/
|
||||
SysTime_t ElapsedTimeSinceStartUp;
|
||||
/*!
|
||||
* Joined Set to true, if the last uplink was a join request
|
||||
*/
|
||||
bool LastTxIsJoinRequest;
|
||||
/*!
|
||||
* Expected time-on-air
|
||||
*/
|
||||
TimerTime_t ExpectedTimeOnAir;
|
||||
/*!
|
||||
* Pointer to a structure of RegionCommonCountNbOfEnabledChannelsParams_t.
|
||||
*/
|
||||
RegionCommonCountNbOfEnabledChannelsParams_t* CountNbOfEnabledChannelsParam;
|
||||
}RegionCommonIdentifyChannelsParam_t;
|
||||
|
||||
typedef struct sRegionCommonSetDutyCycleParams
|
||||
{
|
||||
/*!
|
||||
* Duty cycle period.
|
||||
*/
|
||||
TimerTime_t DutyCycleTimePeriod;
|
||||
/*!
|
||||
* Number of bands available.
|
||||
*/
|
||||
uint8_t MaxBands;
|
||||
/*!
|
||||
* A pointer to the bands.
|
||||
*/
|
||||
Band_t* Bands;
|
||||
}RegionCommonSetDutyCycleParams_t;
|
||||
|
||||
/*!
|
||||
* \brief Calculates the join duty cycle.
|
||||
* This is a generic function and valid for all regions.
|
||||
@@ -289,13 +351,15 @@ void RegionCommonChanMaskCopy( uint16_t* channelsMaskDest, uint16_t* channelsMas
|
||||
* \brief Sets the last tx done property.
|
||||
* This is a generic function and valid for all regions.
|
||||
*
|
||||
* \param [IN] joined Set to true, if the node has joined the network
|
||||
*
|
||||
* \param [IN] band The band to be updated.
|
||||
*
|
||||
* \param [IN] lastTxDone The time of the last TX done.
|
||||
* \param [IN] lastTxAirTime The time on air of the last TX frame.
|
||||
*
|
||||
* \param [IN] joined Set to true if the device has joined.
|
||||
*
|
||||
* \param [IN] elapsedTimeSinceStartup Elapsed time since initialization.
|
||||
*/
|
||||
void RegionCommonSetBandTxDone( bool joined, Band_t* band, TimerTime_t lastTxDone );
|
||||
void RegionCommonSetBandTxDone( Band_t* band, TimerTime_t lastTxAirTime, bool joined, SysTime_t elapsedTimeSinceStartup );
|
||||
|
||||
/*!
|
||||
* \brief Updates the time-offs of the bands.
|
||||
@@ -303,15 +367,24 @@ void RegionCommonSetBandTxDone( bool joined, Band_t* band, TimerTime_t lastTxDon
|
||||
*
|
||||
* \param [IN] joined Set to true, if the node has joined the network
|
||||
*
|
||||
* \param [IN] dutyCycle Set to true, if the duty cycle is enabled.
|
||||
*
|
||||
* \param [IN] bands A pointer to the bands.
|
||||
*
|
||||
* \param [IN] nbBands The number of bands available.
|
||||
*
|
||||
* \param [IN] dutyCycleEnabled Set to true, if the duty cycle is enabled.
|
||||
*
|
||||
* \param [IN] lastTxIsJoinRequest Set to true, if the last TX is a join request.
|
||||
*
|
||||
* \param [IN] elapsedTimeSinceStartup Elapsed time since start up.
|
||||
*
|
||||
* \param [IN] expectedTimeOnAir Expected time on air for the next transmission.
|
||||
*
|
||||
* \retval Returns the time which must be waited to perform the next uplink.
|
||||
*/
|
||||
TimerTime_t RegionCommonUpdateBandTimeOff( bool joined, bool dutyCycle, Band_t* bands, uint8_t nbBands );
|
||||
TimerTime_t RegionCommonUpdateBandTimeOff( bool joined, Band_t* bands,
|
||||
uint8_t nbBands, bool dutyCycleEnabled,
|
||||
bool lastTxIsJoinRequest, SysTime_t elapsedTimeSinceStartup,
|
||||
TimerTime_t expectedTimeOnAir );
|
||||
|
||||
/*!
|
||||
* \brief Parses the parameter of an LinkAdrRequest.
|
||||
@@ -385,7 +458,7 @@ void RegionCommonComputeRxWindowParameters( double tSymbol, uint8_t minRxSymbols
|
||||
|
||||
/*!
|
||||
* \brief Computes the txPower, based on the max EIRP and the antenna gain.
|
||||
*
|
||||
*
|
||||
* \remark US915 region uses a conducted power as input value for maxEirp.
|
||||
* Thus, the antennaGain parameter must be set to 0.
|
||||
*
|
||||
@@ -400,13 +473,6 @@ void RegionCommonComputeRxWindowParameters( double tSymbol, uint8_t minRxSymbols
|
||||
*/
|
||||
int8_t RegionCommonComputeTxPower( int8_t txPowerIndex, float maxEirp, float antennaGain );
|
||||
|
||||
/*!
|
||||
* \brief Calculates the duty cycle for the current band.
|
||||
*
|
||||
* \param [IN] calcBackOffParams A pointer to the input parameters.
|
||||
*/
|
||||
void RegionCommonCalcBackOff( RegionCommonCalcBackOffParams_t* calcBackOffParams );
|
||||
|
||||
/*!
|
||||
* \brief Sets up the radio into RX beacon mode.
|
||||
*
|
||||
@@ -414,6 +480,52 @@ void RegionCommonCalcBackOff( RegionCommonCalcBackOffParams_t* calcBackOffParams
|
||||
*/
|
||||
void RegionCommonRxBeaconSetup( RegionCommonRxBeaconSetupParams_t* rxBeaconSetupParams );
|
||||
|
||||
/*!
|
||||
* \brief Counts the number of enabled channels.
|
||||
*
|
||||
* \param [IN] countNbOfEnabledChannelsParams A pointer to the input parameters.
|
||||
*
|
||||
* \param [OUT] enabledChannels A pointer to an array of size XX_MAX_NB_CHANNELS. The function
|
||||
* stores the available channels into this array.
|
||||
*
|
||||
* \param [OUT] nbEnabledChannels The number of available channels found.
|
||||
*
|
||||
* \param [OUT] nbRestrictedChannels It contains the number of channel
|
||||
* which are available, but restricted due to duty cycle.
|
||||
*/
|
||||
void RegionCommonCountNbOfEnabledChannels( RegionCommonCountNbOfEnabledChannelsParams_t* countNbOfEnabledChannelsParams,
|
||||
uint8_t* enabledChannels, uint8_t* nbEnabledChannels, uint8_t* nbRestrictedChannels );
|
||||
|
||||
/*!
|
||||
* \brief Identifies all channels which are available currently.
|
||||
*
|
||||
* \param [IN] identifyChannelsParam A pointer to the input parameters.
|
||||
*
|
||||
* \param [OUT] aggregatedTimeOff The new value of the aggregatedTimeOff. The function
|
||||
* may resets it to 0.
|
||||
*
|
||||
* \param [OUT] enabledChannels A pointer to an array of size XX_MAX_NB_CHANNELS. The function
|
||||
* stores the available channels into this array.
|
||||
*
|
||||
* \param [OUT] nbEnabledChannels The number of available channels found.
|
||||
*
|
||||
* \param [OUT] nbRestrictedChannels It contains the number of channel
|
||||
* which are available, but restricted due to duty cycle.
|
||||
*
|
||||
* \param [OUT] nextTxDelay Holds the time which has to be waited for the next possible
|
||||
* uplink transmission.
|
||||
*
|
||||
*\retval Status of the operation.
|
||||
*/
|
||||
LoRaMacStatus_t RegionCommonIdentifyChannels( RegionCommonIdentifyChannelsParam_t* identifyChannelsParam,
|
||||
TimerTime_t* aggregatedTimeOff, uint8_t* enabledChannels,
|
||||
uint8_t* nbEnabledChannels, uint8_t* nbRestrictedChannels,
|
||||
TimerTime_t* nextTxDelay );
|
||||
|
||||
/*! \} defgroup REGIONCOMMON */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // __REGIONCOMMON_H__
|
||||
|
@@ -119,45 +119,21 @@ static bool VerifyRfFreq( uint32_t freq )
|
||||
return true;
|
||||
}
|
||||
|
||||
static uint8_t CountNbOfEnabledChannels( bool joined, uint8_t datarate, uint16_t* channelsMask, ChannelParams_t* channels, Band_t* bands, uint8_t* enabledChannels, uint8_t* delayTx )
|
||||
static TimerTime_t GetTimeOnAir( int8_t datarate, uint16_t pktLen )
|
||||
{
|
||||
uint8_t nbEnabledChannels = 0;
|
||||
uint8_t delayTransmission = 0;
|
||||
int8_t phyDr = DataratesEU433[datarate];
|
||||
uint32_t bandwidth = GetBandwidth( datarate );
|
||||
TimerTime_t timeOnAir = 0;
|
||||
|
||||
for( uint8_t i = 0, k = 0; i < EU433_MAX_NB_CHANNELS; i += 16, k++ )
|
||||
{
|
||||
for( uint8_t j = 0; j < 16; j++ )
|
||||
{
|
||||
if( ( channelsMask[k] & ( 1 << j ) ) != 0 )
|
||||
{
|
||||
if( channels[i + j].Frequency == 0 )
|
||||
{ // Check if the channel is enabled
|
||||
continue;
|
||||
}
|
||||
if( joined == false )
|
||||
{
|
||||
if( ( EU433_JOIN_CHANNELS & ( 1 << j ) ) == 0 )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
}
|
||||
if( RegionCommonValueInRange( datarate, channels[i + j].DrRange.Fields.Min,
|
||||
channels[i + j].DrRange.Fields.Max ) == false )
|
||||
{ // Check if the current channel selection supports the given datarate
|
||||
continue;
|
||||
}
|
||||
if( bands[channels[i + j].Band].TimeOff > 0 )
|
||||
{ // Check if the band is available for transmission
|
||||
delayTransmission++;
|
||||
continue;
|
||||
}
|
||||
enabledChannels[nbEnabledChannels++] = i + j;
|
||||
}
|
||||
}
|
||||
if( datarate == DR_7 )
|
||||
{ // High Speed FSK channel
|
||||
timeOnAir = Radio.TimeOnAir( MODEM_FSK, bandwidth, phyDr * 1000, 0, 5, false, pktLen, true );
|
||||
}
|
||||
|
||||
*delayTx = delayTransmission;
|
||||
return nbEnabledChannels;
|
||||
else
|
||||
{
|
||||
timeOnAir = Radio.TimeOnAir( MODEM_LORA, bandwidth, phyDr, 1, 8, false, pktLen, true );
|
||||
}
|
||||
return timeOnAir;
|
||||
}
|
||||
|
||||
PhyParam_t RegionEU433GetPhyParam( GetPhyParams_t* getPhy )
|
||||
@@ -211,11 +187,6 @@ PhyParam_t RegionEU433GetPhyParam( GetPhyParams_t* getPhy )
|
||||
phyParam.Value = MaxPayloadOfDatarateEU433[getPhy->Datarate];
|
||||
break;
|
||||
}
|
||||
case PHY_MAX_PAYLOAD_REPEATER:
|
||||
{
|
||||
phyParam.Value = MaxPayloadOfDatarateRepeaterEU433[getPhy->Datarate];
|
||||
break;
|
||||
}
|
||||
case PHY_DUTY_CYCLE:
|
||||
{
|
||||
phyParam.Value = EU433_DUTY_CYCLE_ENABLED;
|
||||
@@ -324,11 +295,26 @@ PhyParam_t RegionEU433GetPhyParam( GetPhyParams_t* getPhy )
|
||||
phyParam.Value = EU433_BEACON_CHANNEL_DR;
|
||||
break;
|
||||
}
|
||||
case PHY_PING_SLOT_CHANNEL_FREQ:
|
||||
{
|
||||
phyParam.Value = EU433_PING_SLOT_CHANNEL_FREQ;
|
||||
break;
|
||||
}
|
||||
case PHY_PING_SLOT_CHANNEL_DR:
|
||||
{
|
||||
phyParam.Value = EU433_PING_SLOT_CHANNEL_DR;
|
||||
break;
|
||||
}
|
||||
case PHY_SF_FROM_DR:
|
||||
{
|
||||
phyParam.Value = DataratesEU433[getPhy->Datarate];
|
||||
break;
|
||||
}
|
||||
case PHY_BW_FROM_DR:
|
||||
{
|
||||
phyParam.Value = GetBandwidth( getPhy->Datarate );
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
break;
|
||||
@@ -340,7 +326,8 @@ PhyParam_t RegionEU433GetPhyParam( GetPhyParams_t* getPhy )
|
||||
|
||||
void RegionEU433SetBandTxDone( SetBandTxDoneParams_t* txDone )
|
||||
{
|
||||
RegionCommonSetBandTxDone( txDone->Joined, &NvmCtx.Bands[NvmCtx.Channels[txDone->Channel].Band], txDone->LastTxDoneTime );
|
||||
RegionCommonSetBandTxDone( &NvmCtx.Bands[NvmCtx.Channels[txDone->Channel].Band],
|
||||
txDone->LastTxAirTime, txDone->Joined, txDone->ElapsedTimeSinceStartUp );
|
||||
}
|
||||
|
||||
void RegionEU433InitDefaults( InitDefaultsParams_t* params )
|
||||
@@ -352,10 +339,14 @@ void RegionEU433InitDefaults( InitDefaultsParams_t* params )
|
||||
|
||||
switch( params->Type )
|
||||
{
|
||||
case INIT_TYPE_INIT:
|
||||
case INIT_TYPE_BANDS:
|
||||
{
|
||||
// Initialize bands
|
||||
memcpy1( ( uint8_t* )NvmCtx.Bands, ( uint8_t* )bands, sizeof( Band_t ) * EU433_MAX_NB_BANDS );
|
||||
break;
|
||||
}
|
||||
case INIT_TYPE_INIT:
|
||||
{
|
||||
|
||||
// Channels
|
||||
NvmCtx.Channels[0] = ( ChannelParams_t ) EU433_LC1;
|
||||
@@ -364,6 +355,7 @@ void RegionEU433InitDefaults( InitDefaultsParams_t* params )
|
||||
|
||||
// Initialize the channels default mask
|
||||
NvmCtx.ChannelsDefaultMask[0] = LC( 1 ) + LC( 2 ) + LC( 3 );
|
||||
|
||||
// Update the channels mask
|
||||
RegionCommonChanMaskCopy( NvmCtx.ChannelsMask, NvmCtx.ChannelsDefaultMask, 1 );
|
||||
break;
|
||||
@@ -380,6 +372,11 @@ void RegionEU433InitDefaults( InitDefaultsParams_t* params )
|
||||
{
|
||||
// Restore channels default mask
|
||||
NvmCtx.ChannelsMask[0] |= NvmCtx.ChannelsDefaultMask[0];
|
||||
|
||||
// Channels
|
||||
NvmCtx.Channels[0] = ( ChannelParams_t ) EU433_LC1;
|
||||
NvmCtx.Channels[1] = ( ChannelParams_t ) EU433_LC2;
|
||||
NvmCtx.Channels[2] = ( ChannelParams_t ) EU433_LC3;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
@@ -399,6 +396,10 @@ bool RegionEU433Verify( VerifyParams_t* verify, PhyAttribute_t phyAttribute )
|
||||
{
|
||||
switch( phyAttribute )
|
||||
{
|
||||
case PHY_FREQUENCY:
|
||||
{
|
||||
return VerifyRfFreq( verify->Frequency );
|
||||
}
|
||||
case PHY_TX_DR:
|
||||
{
|
||||
return RegionCommonValueInRange( verify->DatarateParams.Datarate, EU433_TX_MIN_DATARATE, EU433_TX_MAX_DATARATE );
|
||||
@@ -529,7 +530,6 @@ bool RegionEU433RxConfig( RxConfigParams_t* rxConfig, int8_t* datarate )
|
||||
{
|
||||
RadioModems_t modem;
|
||||
int8_t dr = rxConfig->Datarate;
|
||||
uint8_t maxPayload = 0;
|
||||
int8_t phyDr = 0;
|
||||
uint32_t frequency = rxConfig->Frequency;
|
||||
|
||||
@@ -566,15 +566,7 @@ bool RegionEU433RxConfig( RxConfigParams_t* rxConfig, int8_t* datarate )
|
||||
Radio.SetRxConfig( modem, rxConfig->Bandwidth, phyDr, 1, 0, 8, rxConfig->WindowTimeout, false, 0, false, 0, 0, true, rxConfig->RxContinuous );
|
||||
}
|
||||
|
||||
if( rxConfig->RepeaterSupport == true )
|
||||
{
|
||||
maxPayload = MaxPayloadOfDatarateRepeaterEU433[dr];
|
||||
}
|
||||
else
|
||||
{
|
||||
maxPayload = MaxPayloadOfDatarateEU433[dr];
|
||||
}
|
||||
Radio.SetMaxPayloadLength( modem, maxPayload + LORA_MAC_FRMPAYLOAD_OVERHEAD );
|
||||
Radio.SetMaxPayloadLength( modem, MaxPayloadOfDatarateEU433[dr] + LORAMAC_FRAME_PAYLOAD_OVERHEAD_SIZE );
|
||||
|
||||
*datarate = (uint8_t) dr;
|
||||
return true;
|
||||
@@ -597,18 +589,19 @@ bool RegionEU433TxConfig( TxConfigParams_t* txConfig, int8_t* txPower, TimerTime
|
||||
if( txConfig->Datarate == DR_7 )
|
||||
{ // High Speed FSK channel
|
||||
modem = MODEM_FSK;
|
||||
Radio.SetTxConfig( modem, phyTxPower, 25000, bandwidth, phyDr * 1000, 0, 5, false, true, 0, 0, false, 3000 );
|
||||
Radio.SetTxConfig( modem, phyTxPower, 25000, bandwidth, phyDr * 1000, 0, 5, false, true, 0, 0, false, 4000 );
|
||||
}
|
||||
else
|
||||
{
|
||||
modem = MODEM_LORA;
|
||||
Radio.SetTxConfig( modem, phyTxPower, 0, bandwidth, phyDr, 1, 8, false, true, 0, 0, false, 3000 );
|
||||
Radio.SetTxConfig( modem, phyTxPower, 0, bandwidth, phyDr, 1, 8, false, true, 0, 0, false, 4000 );
|
||||
}
|
||||
|
||||
// Update time-on-air
|
||||
*txTimeOnAir = GetTimeOnAir( txConfig->Datarate, txConfig->PktLen );
|
||||
|
||||
// Setup maximum payload lenght of the radio driver
|
||||
Radio.SetMaxPayloadLength( modem, txConfig->PktLen );
|
||||
// Get the time-on-air of the next tx frame
|
||||
*txTimeOnAir = Radio.TimeOnAir( modem, txConfig->PktLen );
|
||||
|
||||
*txPower = txPowerLimited;
|
||||
return true;
|
||||
@@ -832,74 +825,54 @@ int8_t RegionEU433AlternateDr( int8_t currentDr, AlternateDrType_t type )
|
||||
return currentDr;
|
||||
}
|
||||
|
||||
void RegionEU433CalcBackOff( CalcBackOffParams_t* calcBackOff )
|
||||
{
|
||||
RegionCommonCalcBackOffParams_t calcBackOffParams;
|
||||
|
||||
calcBackOffParams.Channels = NvmCtx.Channels;
|
||||
calcBackOffParams.Bands = NvmCtx.Bands;
|
||||
calcBackOffParams.LastTxIsJoinRequest = calcBackOff->LastTxIsJoinRequest;
|
||||
calcBackOffParams.Joined = calcBackOff->Joined;
|
||||
calcBackOffParams.DutyCycleEnabled = calcBackOff->DutyCycleEnabled;
|
||||
calcBackOffParams.Channel = calcBackOff->Channel;
|
||||
calcBackOffParams.ElapsedTime = calcBackOff->ElapsedTime;
|
||||
calcBackOffParams.TxTimeOnAir = calcBackOff->TxTimeOnAir;
|
||||
|
||||
RegionCommonCalcBackOff( &calcBackOffParams );
|
||||
}
|
||||
|
||||
LoRaMacStatus_t RegionEU433NextChannel( NextChanParams_t* nextChanParams, uint8_t* channel, TimerTime_t* time, TimerTime_t* aggregatedTimeOff )
|
||||
{
|
||||
uint8_t nbEnabledChannels = 0;
|
||||
uint8_t delayTx = 0;
|
||||
uint8_t nbRestrictedChannels = 0;
|
||||
uint8_t enabledChannels[EU433_MAX_NB_CHANNELS] = { 0 };
|
||||
TimerTime_t nextTxDelay = 0;
|
||||
RegionCommonIdentifyChannelsParam_t identifyChannelsParam;
|
||||
RegionCommonCountNbOfEnabledChannelsParams_t countChannelsParams;
|
||||
LoRaMacStatus_t status = LORAMAC_STATUS_NO_CHANNEL_FOUND;
|
||||
|
||||
if( RegionCommonCountChannels( NvmCtx.ChannelsMask, 0, 1 ) == 0 )
|
||||
{ // Reactivate default channels
|
||||
NvmCtx.ChannelsMask[0] |= LC( 1 ) + LC( 2 ) + LC( 3 );
|
||||
}
|
||||
|
||||
if( nextChanParams->AggrTimeOff <= TimerGetElapsedTime( nextChanParams->LastAggrTx ) )
|
||||
{
|
||||
// Reset Aggregated time off
|
||||
*aggregatedTimeOff = 0;
|
||||
// Search how many channels are enabled
|
||||
countChannelsParams.Joined = nextChanParams->Joined;
|
||||
countChannelsParams.Datarate = nextChanParams->Datarate;
|
||||
countChannelsParams.ChannelsMask = NvmCtx.ChannelsMask;
|
||||
countChannelsParams.Channels = NvmCtx.Channels;
|
||||
countChannelsParams.Bands = NvmCtx.Bands;
|
||||
countChannelsParams.MaxNbChannels = EU433_MAX_NB_CHANNELS;
|
||||
countChannelsParams.JoinChannels = EU433_JOIN_CHANNELS;
|
||||
|
||||
// Update bands Time OFF
|
||||
nextTxDelay = RegionCommonUpdateBandTimeOff( nextChanParams->Joined, nextChanParams->DutyCycleEnabled, NvmCtx.Bands, EU433_MAX_NB_BANDS );
|
||||
identifyChannelsParam.AggrTimeOff = nextChanParams->AggrTimeOff;
|
||||
identifyChannelsParam.LastAggrTx = nextChanParams->LastAggrTx;
|
||||
identifyChannelsParam.DutyCycleEnabled = nextChanParams->DutyCycleEnabled;
|
||||
identifyChannelsParam.MaxBands = EU433_MAX_NB_BANDS;
|
||||
|
||||
// Search how many channels are enabled
|
||||
nbEnabledChannels = CountNbOfEnabledChannels( nextChanParams->Joined, nextChanParams->Datarate,
|
||||
NvmCtx.ChannelsMask, NvmCtx.Channels,
|
||||
NvmCtx.Bands, enabledChannels, &delayTx );
|
||||
}
|
||||
else
|
||||
{
|
||||
delayTx++;
|
||||
nextTxDelay = nextChanParams->AggrTimeOff - TimerGetElapsedTime( nextChanParams->LastAggrTx );
|
||||
}
|
||||
identifyChannelsParam.ElapsedTimeSinceStartUp = nextChanParams->ElapsedTimeSinceStartUp;
|
||||
identifyChannelsParam.LastTxIsJoinRequest = nextChanParams->LastTxIsJoinRequest;
|
||||
identifyChannelsParam.ExpectedTimeOnAir = GetTimeOnAir( nextChanParams->Datarate, nextChanParams->PktLen );
|
||||
|
||||
if( nbEnabledChannels > 0 )
|
||||
identifyChannelsParam.CountNbOfEnabledChannelsParam = &countChannelsParams;
|
||||
|
||||
status = RegionCommonIdentifyChannels( &identifyChannelsParam, aggregatedTimeOff, enabledChannels,
|
||||
&nbEnabledChannels, &nbRestrictedChannels, time );
|
||||
|
||||
if( status == LORAMAC_STATUS_OK )
|
||||
{
|
||||
// We found a valid channel
|
||||
*channel = enabledChannels[randr( 0, nbEnabledChannels - 1 )];
|
||||
|
||||
*time = 0;
|
||||
return LORAMAC_STATUS_OK;
|
||||
}
|
||||
else
|
||||
else if( status == LORAMAC_STATUS_NO_CHANNEL_FOUND )
|
||||
{
|
||||
if( delayTx > 0 )
|
||||
{
|
||||
// Delay transmission due to AggregatedTimeOff or to a band time off
|
||||
*time = nextTxDelay;
|
||||
return LORAMAC_STATUS_DUTYCYCLE_RESTRICTED;
|
||||
}
|
||||
// Datarate not supported by any channel, restore defaults
|
||||
NvmCtx.ChannelsMask[0] |= LC( 1 ) + LC( 2 ) + LC( 3 );
|
||||
*time = 0;
|
||||
return LORAMAC_STATUS_NO_CHANNEL_FOUND;
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
LoRaMacStatus_t RegionEU433ChannelAdd( ChannelAddParams_t* channelAdd )
|
||||
|
@@ -37,6 +37,11 @@
|
||||
#ifndef __REGION_EU433_H__
|
||||
#define __REGION_EU433_H__
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
#include "region/Region.h"
|
||||
|
||||
/*!
|
||||
@@ -204,6 +209,11 @@
|
||||
*/
|
||||
#define EU433_BEACON_CHANNEL_FREQ 434665000
|
||||
|
||||
/*!
|
||||
* Ping slot channel frequency
|
||||
*/
|
||||
#define EU433_PING_SLOT_CHANNEL_FREQ 434665000
|
||||
|
||||
/*!
|
||||
* Payload size of a beacon frame
|
||||
*/
|
||||
@@ -236,9 +246,9 @@
|
||||
|
||||
/*!
|
||||
* Band 0 definition
|
||||
* { DutyCycle, TxMaxPower, LastJoinTxDoneTime, LastTxDoneTime, TimeOff }
|
||||
* Band = { DutyCycle, TxMaxPower, LastBandUpdateTime, TimeCredits, MaxTimeCredits, ReadyForTransmission }
|
||||
*/
|
||||
#define EU433_BAND0 { 100, EU433_MAX_TX_POWER, 0, 0, 0 } // 1.0 %
|
||||
#define EU433_BAND0 { 100, EU433_MAX_TX_POWER, 0, 0, 0, 0 } // 1.0 %
|
||||
|
||||
/*!
|
||||
* LoRaMac default channel 1
|
||||
@@ -274,15 +284,10 @@ static const uint8_t DataratesEU433[] = { 12, 11, 10, 9, 8, 7, 7, 50 };
|
||||
static const uint32_t BandwidthsEU433[] = { 125000, 125000, 125000, 125000, 125000, 125000, 250000, 0 };
|
||||
|
||||
/*!
|
||||
* Maximum payload with respect to the datarate index. Cannot operate with repeater.
|
||||
* Maximum payload with respect to the datarate index.
|
||||
*/
|
||||
static const uint8_t MaxPayloadOfDatarateEU433[] = { 51, 51, 51, 115, 242, 242, 242, 242 };
|
||||
|
||||
/*!
|
||||
* Maximum payload with respect to the datarate index. Can operate with repeater.
|
||||
*/
|
||||
static const uint8_t MaxPayloadOfDatarateRepeaterEU433[] = { 51, 51, 51, 115, 222, 222, 222, 222 };
|
||||
|
||||
/*!
|
||||
* \brief The function gets a value of a specific phy attribute.
|
||||
*
|
||||
@@ -438,13 +443,6 @@ uint8_t RegionEU433DlChannelReq( DlChannelReqParams_t* dlChannelReq );
|
||||
*/
|
||||
int8_t RegionEU433AlternateDr( int8_t currentDr, AlternateDrType_t type );
|
||||
|
||||
/*!
|
||||
* \brief Calculates the back-off time.
|
||||
*
|
||||
* \param [IN] calcBackOff Pointer to the function parameters.
|
||||
*/
|
||||
void RegionEU433CalcBackOff( CalcBackOffParams_t* calcBackOff );
|
||||
|
||||
/*!
|
||||
* \brief Searches and set the next random available channel
|
||||
*
|
||||
@@ -502,8 +500,12 @@ uint8_t RegionEU433ApplyDrOffset( uint8_t downlinkDwellTime, int8_t dr, int8_t d
|
||||
*
|
||||
* \param [IN] rxBeaconSetup Pointer to the function parameters
|
||||
*/
|
||||
void RegionEU433RxBeaconSetup( RxBeaconSetup_t* rxBeaconSetup, uint8_t* outDr );
|
||||
void RegionEU433RxBeaconSetup( RxBeaconSetup_t* rxBeaconSetup, uint8_t* outDr );
|
||||
|
||||
/*! \} defgroup REGIONEU433 */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // __REGION_EU433_H__
|
||||
|
@@ -127,7 +127,7 @@ static bool VerifyRfFreq( uint32_t freq, uint8_t *band )
|
||||
}
|
||||
else if( ( freq >= 868700000 ) && ( freq <= 869200000 ) )
|
||||
{
|
||||
*band = 2;
|
||||
*band = 5;
|
||||
}
|
||||
else if( ( freq >= 869400000 ) && ( freq <= 869650000 ) )
|
||||
{
|
||||
@@ -144,45 +144,21 @@ static bool VerifyRfFreq( uint32_t freq, uint8_t *band )
|
||||
return true;
|
||||
}
|
||||
|
||||
static uint8_t CountNbOfEnabledChannels( bool joined, uint8_t datarate, uint16_t* channelsMask, ChannelParams_t* channels, Band_t* bands, uint8_t* enabledChannels, uint8_t* delayTx )
|
||||
static TimerTime_t GetTimeOnAir( int8_t datarate, uint16_t pktLen )
|
||||
{
|
||||
uint8_t nbEnabledChannels = 0;
|
||||
uint8_t delayTransmission = 0;
|
||||
int8_t phyDr = DataratesEU868[datarate];
|
||||
uint32_t bandwidth = GetBandwidth( datarate );
|
||||
TimerTime_t timeOnAir = 0;
|
||||
|
||||
for( uint8_t i = 0, k = 0; i < EU868_MAX_NB_CHANNELS; i += 16, k++ )
|
||||
{
|
||||
for( uint8_t j = 0; j < 16; j++ )
|
||||
{
|
||||
if( ( channelsMask[k] & ( 1 << j ) ) != 0 )
|
||||
{
|
||||
if( channels[i + j].Frequency == 0 )
|
||||
{ // Check if the channel is enabled
|
||||
continue;
|
||||
}
|
||||
if( joined == false )
|
||||
{
|
||||
if( ( EU868_JOIN_CHANNELS & ( 1 << j ) ) == 0 )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
}
|
||||
if( RegionCommonValueInRange( datarate, channels[i + j].DrRange.Fields.Min,
|
||||
channels[i + j].DrRange.Fields.Max ) == false )
|
||||
{ // Check if the current channel selection supports the given datarate
|
||||
continue;
|
||||
}
|
||||
if( bands[channels[i + j].Band].TimeOff > 0 )
|
||||
{ // Check if the band is available for transmission
|
||||
delayTransmission++;
|
||||
continue;
|
||||
}
|
||||
enabledChannels[nbEnabledChannels++] = i + j;
|
||||
}
|
||||
}
|
||||
if( datarate == DR_7 )
|
||||
{ // High Speed FSK channel
|
||||
timeOnAir = Radio.TimeOnAir( MODEM_FSK, bandwidth, phyDr * 1000, 0, 5, false, pktLen, true );
|
||||
}
|
||||
|
||||
*delayTx = delayTransmission;
|
||||
return nbEnabledChannels;
|
||||
else
|
||||
{
|
||||
timeOnAir = Radio.TimeOnAir( MODEM_LORA, bandwidth, phyDr, 1, 8, false, pktLen, true );
|
||||
}
|
||||
return timeOnAir;
|
||||
}
|
||||
|
||||
PhyParam_t RegionEU868GetPhyParam( GetPhyParams_t* getPhy )
|
||||
@@ -236,11 +212,6 @@ PhyParam_t RegionEU868GetPhyParam( GetPhyParams_t* getPhy )
|
||||
phyParam.Value = MaxPayloadOfDatarateEU868[getPhy->Datarate];
|
||||
break;
|
||||
}
|
||||
case PHY_MAX_PAYLOAD_REPEATER:
|
||||
{
|
||||
phyParam.Value = MaxPayloadOfDatarateRepeaterEU868[getPhy->Datarate];
|
||||
break;
|
||||
}
|
||||
case PHY_DUTY_CYCLE:
|
||||
{
|
||||
phyParam.Value = EU868_DUTY_CYCLE_ENABLED;
|
||||
@@ -349,11 +320,26 @@ PhyParam_t RegionEU868GetPhyParam( GetPhyParams_t* getPhy )
|
||||
phyParam.Value = EU868_BEACON_CHANNEL_DR;
|
||||
break;
|
||||
}
|
||||
case PHY_PING_SLOT_CHANNEL_FREQ:
|
||||
{
|
||||
phyParam.Value = EU868_PING_SLOT_CHANNEL_FREQ;
|
||||
break;
|
||||
}
|
||||
case PHY_PING_SLOT_CHANNEL_DR:
|
||||
{
|
||||
phyParam.Value = EU868_PING_SLOT_CHANNEL_DR;
|
||||
break;
|
||||
}
|
||||
case PHY_SF_FROM_DR:
|
||||
{
|
||||
phyParam.Value = DataratesEU868[getPhy->Datarate];
|
||||
break;
|
||||
}
|
||||
case PHY_BW_FROM_DR:
|
||||
{
|
||||
phyParam.Value = GetBandwidth( getPhy->Datarate );
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
break;
|
||||
@@ -365,7 +351,8 @@ PhyParam_t RegionEU868GetPhyParam( GetPhyParams_t* getPhy )
|
||||
|
||||
void RegionEU868SetBandTxDone( SetBandTxDoneParams_t* txDone )
|
||||
{
|
||||
RegionCommonSetBandTxDone( txDone->Joined, &NvmCtx.Bands[NvmCtx.Channels[txDone->Channel].Band], txDone->LastTxDoneTime );
|
||||
RegionCommonSetBandTxDone( &NvmCtx.Bands[NvmCtx.Channels[txDone->Channel].Band],
|
||||
txDone->LastTxAirTime, txDone->Joined, txDone->ElapsedTimeSinceStartUp );
|
||||
}
|
||||
|
||||
void RegionEU868InitDefaults( InitDefaultsParams_t* params )
|
||||
@@ -377,14 +364,19 @@ void RegionEU868InitDefaults( InitDefaultsParams_t* params )
|
||||
EU868_BAND2,
|
||||
EU868_BAND3,
|
||||
EU868_BAND4,
|
||||
EU868_BAND5,
|
||||
};
|
||||
|
||||
switch( params->Type )
|
||||
{
|
||||
case INIT_TYPE_INIT:
|
||||
case INIT_TYPE_BANDS:
|
||||
{
|
||||
// Initialize bands
|
||||
memcpy1( ( uint8_t* )NvmCtx.Bands, ( uint8_t* )bands, sizeof( Band_t ) * EU868_MAX_NB_BANDS );
|
||||
break;
|
||||
}
|
||||
case INIT_TYPE_INIT:
|
||||
{
|
||||
|
||||
// Channels
|
||||
NvmCtx.Channels[0] = ( ChannelParams_t ) EU868_LC1;
|
||||
@@ -393,6 +385,7 @@ void RegionEU868InitDefaults( InitDefaultsParams_t* params )
|
||||
|
||||
// Initialize the channels default mask
|
||||
NvmCtx.ChannelsDefaultMask[0] = LC( 1 ) + LC( 2 ) + LC( 3 );
|
||||
|
||||
// Update the channels mask
|
||||
RegionCommonChanMaskCopy( NvmCtx.ChannelsMask, NvmCtx.ChannelsDefaultMask, 1 );
|
||||
break;
|
||||
@@ -409,6 +402,11 @@ void RegionEU868InitDefaults( InitDefaultsParams_t* params )
|
||||
{
|
||||
// Restore channels default mask
|
||||
NvmCtx.ChannelsMask[0] |= NvmCtx.ChannelsDefaultMask[0];
|
||||
|
||||
// Channels
|
||||
NvmCtx.Channels[0] = ( ChannelParams_t ) EU868_LC1;
|
||||
NvmCtx.Channels[1] = ( ChannelParams_t ) EU868_LC2;
|
||||
NvmCtx.Channels[2] = ( ChannelParams_t ) EU868_LC3;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
@@ -428,6 +426,11 @@ bool RegionEU868Verify( VerifyParams_t* verify, PhyAttribute_t phyAttribute )
|
||||
{
|
||||
switch( phyAttribute )
|
||||
{
|
||||
case PHY_FREQUENCY:
|
||||
{
|
||||
uint8_t band = 0;
|
||||
return VerifyRfFreq( verify->Frequency, &band );
|
||||
}
|
||||
case PHY_TX_DR:
|
||||
{
|
||||
return RegionCommonValueInRange( verify->DatarateParams.Datarate, EU868_TX_MIN_DATARATE, EU868_TX_MAX_DATARATE );
|
||||
@@ -558,7 +561,6 @@ bool RegionEU868RxConfig( RxConfigParams_t* rxConfig, int8_t* datarate )
|
||||
{
|
||||
RadioModems_t modem;
|
||||
int8_t dr = rxConfig->Datarate;
|
||||
uint8_t maxPayload = 0;
|
||||
int8_t phyDr = 0;
|
||||
uint32_t frequency = rxConfig->Frequency;
|
||||
|
||||
@@ -595,16 +597,7 @@ bool RegionEU868RxConfig( RxConfigParams_t* rxConfig, int8_t* datarate )
|
||||
Radio.SetRxConfig( modem, rxConfig->Bandwidth, phyDr, 1, 0, 8, rxConfig->WindowTimeout, false, 0, false, 0, 0, true, rxConfig->RxContinuous );
|
||||
}
|
||||
|
||||
if( rxConfig->RepeaterSupport == true )
|
||||
{
|
||||
maxPayload = MaxPayloadOfDatarateRepeaterEU868[dr];
|
||||
}
|
||||
else
|
||||
{
|
||||
maxPayload = MaxPayloadOfDatarateEU868[dr];
|
||||
}
|
||||
|
||||
Radio.SetMaxPayloadLength( modem, maxPayload + LORA_MAC_FRMPAYLOAD_OVERHEAD );
|
||||
Radio.SetMaxPayloadLength( modem, MaxPayloadOfDatarateEU868[dr] + LORAMAC_FRAME_PAYLOAD_OVERHEAD_SIZE );
|
||||
|
||||
*datarate = (uint8_t) dr;
|
||||
return true;
|
||||
@@ -627,18 +620,19 @@ bool RegionEU868TxConfig( TxConfigParams_t* txConfig, int8_t* txPower, TimerTime
|
||||
if( txConfig->Datarate == DR_7 )
|
||||
{ // High Speed FSK channel
|
||||
modem = MODEM_FSK;
|
||||
Radio.SetTxConfig( modem, phyTxPower, 25000, bandwidth, phyDr * 1000, 0, 5, false, true, 0, 0, false, 3000 );
|
||||
Radio.SetTxConfig( modem, phyTxPower, 25000, bandwidth, phyDr * 1000, 0, 5, false, true, 0, 0, false, 4000 );
|
||||
}
|
||||
else
|
||||
{
|
||||
modem = MODEM_LORA;
|
||||
Radio.SetTxConfig( modem, phyTxPower, 0, bandwidth, phyDr, 1, 8, false, true, 0, 0, false, 3000 );
|
||||
Radio.SetTxConfig( modem, phyTxPower, 0, bandwidth, phyDr, 1, 8, false, true, 0, 0, false, 4000 );
|
||||
}
|
||||
|
||||
// Update time-on-air
|
||||
*txTimeOnAir = GetTimeOnAir( txConfig->Datarate, txConfig->PktLen );
|
||||
|
||||
// Setup maximum payload lenght of the radio driver
|
||||
Radio.SetMaxPayloadLength( modem, txConfig->PktLen );
|
||||
// Get the time-on-air of the next tx frame
|
||||
*txTimeOnAir = Radio.TimeOnAir( modem, txConfig->PktLen );
|
||||
|
||||
*txPower = txPowerLimited;
|
||||
return true;
|
||||
@@ -864,74 +858,54 @@ int8_t RegionEU868AlternateDr( int8_t currentDr, AlternateDrType_t type )
|
||||
return currentDr;
|
||||
}
|
||||
|
||||
void RegionEU868CalcBackOff( CalcBackOffParams_t* calcBackOff )
|
||||
{
|
||||
RegionCommonCalcBackOffParams_t calcBackOffParams;
|
||||
|
||||
calcBackOffParams.Channels = NvmCtx.Channels;
|
||||
calcBackOffParams.Bands = NvmCtx.Bands;
|
||||
calcBackOffParams.LastTxIsJoinRequest = calcBackOff->LastTxIsJoinRequest;
|
||||
calcBackOffParams.Joined = calcBackOff->Joined;
|
||||
calcBackOffParams.DutyCycleEnabled = calcBackOff->DutyCycleEnabled;
|
||||
calcBackOffParams.Channel = calcBackOff->Channel;
|
||||
calcBackOffParams.ElapsedTime = calcBackOff->ElapsedTime;
|
||||
calcBackOffParams.TxTimeOnAir = calcBackOff->TxTimeOnAir;
|
||||
|
||||
RegionCommonCalcBackOff( &calcBackOffParams );
|
||||
}
|
||||
|
||||
LoRaMacStatus_t RegionEU868NextChannel( NextChanParams_t* nextChanParams, uint8_t* channel, TimerTime_t* time, TimerTime_t* aggregatedTimeOff )
|
||||
{
|
||||
uint8_t nbEnabledChannels = 0;
|
||||
uint8_t delayTx = 0;
|
||||
uint8_t nbRestrictedChannels = 0;
|
||||
uint8_t enabledChannels[EU868_MAX_NB_CHANNELS] = { 0 };
|
||||
TimerTime_t nextTxDelay = 0;
|
||||
RegionCommonIdentifyChannelsParam_t identifyChannelsParam;
|
||||
RegionCommonCountNbOfEnabledChannelsParams_t countChannelsParams;
|
||||
LoRaMacStatus_t status = LORAMAC_STATUS_NO_CHANNEL_FOUND;
|
||||
|
||||
if( RegionCommonCountChannels( NvmCtx.ChannelsMask, 0, 1 ) == 0 )
|
||||
{ // Reactivate default channels
|
||||
NvmCtx.ChannelsMask[0] |= LC( 1 ) + LC( 2 ) + LC( 3 );
|
||||
}
|
||||
|
||||
if( nextChanParams->AggrTimeOff <= TimerGetElapsedTime( nextChanParams->LastAggrTx ) )
|
||||
{
|
||||
// Reset Aggregated time off
|
||||
*aggregatedTimeOff = 0;
|
||||
// Search how many channels are enabled
|
||||
countChannelsParams.Joined = nextChanParams->Joined;
|
||||
countChannelsParams.Datarate = nextChanParams->Datarate;
|
||||
countChannelsParams.ChannelsMask = NvmCtx.ChannelsMask;
|
||||
countChannelsParams.Channels = NvmCtx.Channels;
|
||||
countChannelsParams.Bands = NvmCtx.Bands;
|
||||
countChannelsParams.MaxNbChannels = EU868_MAX_NB_CHANNELS;
|
||||
countChannelsParams.JoinChannels = EU868_JOIN_CHANNELS;
|
||||
|
||||
// Update bands Time OFF
|
||||
nextTxDelay = RegionCommonUpdateBandTimeOff( nextChanParams->Joined, nextChanParams->DutyCycleEnabled, NvmCtx.Bands, EU868_MAX_NB_BANDS );
|
||||
identifyChannelsParam.AggrTimeOff = nextChanParams->AggrTimeOff;
|
||||
identifyChannelsParam.LastAggrTx = nextChanParams->LastAggrTx;
|
||||
identifyChannelsParam.DutyCycleEnabled = nextChanParams->DutyCycleEnabled;
|
||||
identifyChannelsParam.MaxBands = EU868_MAX_NB_BANDS;
|
||||
|
||||
// Search how many channels are enabled
|
||||
nbEnabledChannels = CountNbOfEnabledChannels( nextChanParams->Joined, nextChanParams->Datarate,
|
||||
NvmCtx.ChannelsMask, NvmCtx.Channels,
|
||||
NvmCtx.Bands, enabledChannels, &delayTx );
|
||||
}
|
||||
else
|
||||
{
|
||||
delayTx++;
|
||||
nextTxDelay = nextChanParams->AggrTimeOff - TimerGetElapsedTime( nextChanParams->LastAggrTx );
|
||||
}
|
||||
identifyChannelsParam.ElapsedTimeSinceStartUp = nextChanParams->ElapsedTimeSinceStartUp;
|
||||
identifyChannelsParam.LastTxIsJoinRequest = nextChanParams->LastTxIsJoinRequest;
|
||||
identifyChannelsParam.ExpectedTimeOnAir = GetTimeOnAir( nextChanParams->Datarate, nextChanParams->PktLen );
|
||||
|
||||
if( nbEnabledChannels > 0 )
|
||||
identifyChannelsParam.CountNbOfEnabledChannelsParam = &countChannelsParams;
|
||||
|
||||
status = RegionCommonIdentifyChannels( &identifyChannelsParam, aggregatedTimeOff, enabledChannels,
|
||||
&nbEnabledChannels, &nbRestrictedChannels, time );
|
||||
|
||||
if( status == LORAMAC_STATUS_OK )
|
||||
{
|
||||
// We found a valid channel
|
||||
*channel = enabledChannels[randr( 0, nbEnabledChannels - 1 )];
|
||||
|
||||
*time = 0;
|
||||
return LORAMAC_STATUS_OK;
|
||||
}
|
||||
else
|
||||
else if( status == LORAMAC_STATUS_NO_CHANNEL_FOUND )
|
||||
{
|
||||
if( delayTx > 0 )
|
||||
{
|
||||
// Delay transmission due to AggregatedTimeOff or to a band time off
|
||||
*time = nextTxDelay;
|
||||
return LORAMAC_STATUS_DUTYCYCLE_RESTRICTED;
|
||||
}
|
||||
// Datarate not supported by any channel, restore defaults
|
||||
NvmCtx.ChannelsMask[0] |= LC( 1 ) + LC( 2 ) + LC( 3 );
|
||||
*time = 0;
|
||||
return LORAMAC_STATUS_NO_CHANNEL_FOUND;
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
LoRaMacStatus_t RegionEU868ChannelAdd( ChannelAddParams_t* channelAdd )
|
||||
|
@@ -37,6 +37,11 @@
|
||||
#ifndef __REGION_EU868_H__
|
||||
#define __REGION_EU868_H__
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
#include "region/Region.h"
|
||||
|
||||
/*!
|
||||
@@ -196,6 +201,11 @@
|
||||
*/
|
||||
#define EU868_BEACON_CHANNEL_FREQ 869525000
|
||||
|
||||
/*!
|
||||
* Ping slot channel frequency
|
||||
*/
|
||||
#define EU868_PING_SLOT_CHANNEL_FREQ 869525000
|
||||
|
||||
/*!
|
||||
* Payload size of a beacon frame
|
||||
*/
|
||||
@@ -229,37 +239,44 @@
|
||||
/*!
|
||||
* Maximum number of bands
|
||||
*/
|
||||
#define EU868_MAX_NB_BANDS 5
|
||||
#define EU868_MAX_NB_BANDS 6
|
||||
|
||||
/*!
|
||||
* Band 0 definition
|
||||
* { DutyCycle, TxMaxPower, LastJoinTxDoneTime, LastTxDoneTime, TimeOff }
|
||||
* Band = { DutyCycle, TxMaxPower, LastBandUpdateTime, TimeCredits, MaxTimeCredits, ReadyForTransmission }
|
||||
*/
|
||||
#define EU868_BAND0 { 100 , EU868_MAX_TX_POWER, 0, 0, 0 } // 1.0 %
|
||||
#define EU868_BAND0 { 100 , EU868_MAX_TX_POWER, 0, 0, 0, 0 } // 1.0 %
|
||||
|
||||
/*!
|
||||
* Band 1 definition
|
||||
* { DutyCycle, TxMaxPower, LastJoinTxDoneTime, LastTxDoneTime, TimeOff }
|
||||
* Band = { DutyCycle, TxMaxPower, LastBandUpdateTime, TimeCredits, MaxTimeCredits, ReadyForTransmission }
|
||||
*/
|
||||
#define EU868_BAND1 { 100 , EU868_MAX_TX_POWER, 0, 0, 0 } // 1.0 %
|
||||
#define EU868_BAND1 { 100 , EU868_MAX_TX_POWER, 0, 0, 0, 0 } // 1.0 %
|
||||
|
||||
/*!
|
||||
* Band 2 definition
|
||||
* Band = { DutyCycle, TxMaxPower, LastJoinTxDoneTime, LastTxDoneTime, TimeOff }
|
||||
* Band = { DutyCycle, TxMaxPower, LastBandUpdateTime, TimeCredits, MaxTimeCredits, ReadyForTransmission }
|
||||
*/
|
||||
#define EU868_BAND2 { 1000, EU868_MAX_TX_POWER, 0, 0, 0 } // 0.1 %
|
||||
#define EU868_BAND2 { 1000, EU868_MAX_TX_POWER, 0, 0, 0, 0 } // 0.1 %
|
||||
|
||||
/*!
|
||||
* Band 3 definition
|
||||
* Band = { DutyCycle, TxMaxPower, LastJoinTxDoneTime, LastTxDoneTime, TimeOff }
|
||||
* Band = { DutyCycle, TxMaxPower, LastBandUpdateTime, TimeCredits, MaxTimeCredits, ReadyForTransmission }
|
||||
*/
|
||||
#define EU868_BAND3 { 10 , EU868_MAX_TX_POWER, 0, 0, 0 } // 10.0 %
|
||||
#define EU868_BAND3 { 10 , EU868_MAX_TX_POWER, 0, 0, 0, 0 } // 10.0 %
|
||||
|
||||
/*!
|
||||
* Band 4 definition
|
||||
* Band = { DutyCycle, TxMaxPower, LastJoinTxDoneTime, LastTxDoneTime, TimeOff }
|
||||
* Band = { DutyCycle, TxMaxPower, LastBandUpdateTime, TimeCredits, MaxTimeCredits, ReadyForTransmission }
|
||||
*/
|
||||
#define EU868_BAND4 { 100 , EU868_MAX_TX_POWER, 0, 0, 0 } // 1.0 %
|
||||
#define EU868_BAND4 { 100 , EU868_MAX_TX_POWER, 0, 0, 0, 0 } // 1.0 %
|
||||
|
||||
/*!
|
||||
* Band 5 definition
|
||||
* Band = { DutyCycle, TxMaxPower, LastJoinTxDoneTime, LastTxDoneTime, TimeOff,
|
||||
* DutyCycleTimePeriod, MaxAllowedTimeOnAir, AggregatedTimeOnAir, StartTimeOfPeriod }
|
||||
*/
|
||||
#define EU868_BAND5 { 1000, EU868_MAX_TX_POWER, 0, 0, 0, 0 } // 0.1 %
|
||||
|
||||
/*!
|
||||
* LoRaMac default channel 1
|
||||
@@ -295,15 +312,10 @@ static const uint8_t DataratesEU868[] = { 12, 11, 10, 9, 8, 7, 7, 50 };
|
||||
static const uint32_t BandwidthsEU868[] = { 125000, 125000, 125000, 125000, 125000, 125000, 250000, 0 };
|
||||
|
||||
/*!
|
||||
* Maximum payload with respect to the datarate index. Cannot operate with repeater.
|
||||
* Maximum payload with respect to the datarate index.
|
||||
*/
|
||||
static const uint8_t MaxPayloadOfDatarateEU868[] = { 51, 51, 51, 115, 242, 242, 242, 242 };
|
||||
|
||||
/*!
|
||||
* Maximum payload with respect to the datarate index. Can operate with repeater.
|
||||
*/
|
||||
static const uint8_t MaxPayloadOfDatarateRepeaterEU868[] = { 51, 51, 51, 115, 222, 222, 222, 222 };
|
||||
|
||||
/*!
|
||||
* \brief The function gets a value of a specific phy attribute.
|
||||
*
|
||||
@@ -459,13 +471,6 @@ uint8_t RegionEU868DlChannelReq( DlChannelReqParams_t* dlChannelReq );
|
||||
*/
|
||||
int8_t RegionEU868AlternateDr( int8_t currentDr, AlternateDrType_t type );
|
||||
|
||||
/*!
|
||||
* \brief Calculates the back-off time.
|
||||
*
|
||||
* \param [IN] calcBackOff Pointer to the function parameters.
|
||||
*/
|
||||
void RegionEU868CalcBackOff( CalcBackOffParams_t* calcBackOff );
|
||||
|
||||
/*!
|
||||
* \brief Searches and set the next random available channel
|
||||
*
|
||||
@@ -527,4 +532,8 @@ void RegionEU868RxBeaconSetup( RxBeaconSetup_t* rxBeaconSetup, uint8_t* outDr );
|
||||
|
||||
/*! \} defgroup REGIONEU868 */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // __REGION_EU868_H__
|
||||
|
@@ -123,45 +123,21 @@ static bool VerifyRfFreq( uint32_t freq )
|
||||
return true;
|
||||
}
|
||||
|
||||
static uint8_t CountNbOfEnabledChannels( bool joined, uint8_t datarate, uint16_t* channelsMask, ChannelParams_t* channels, Band_t* bands, uint8_t* enabledChannels, uint8_t* delayTx )
|
||||
static TimerTime_t GetTimeOnAir( int8_t datarate, uint16_t pktLen )
|
||||
{
|
||||
uint8_t nbEnabledChannels = 0;
|
||||
uint8_t delayTransmission = 0;
|
||||
int8_t phyDr = DataratesIN865[datarate];
|
||||
uint32_t bandwidth = GetBandwidth( datarate );
|
||||
TimerTime_t timeOnAir = 0;
|
||||
|
||||
for( uint8_t i = 0, k = 0; i < IN865_MAX_NB_CHANNELS; i += 16, k++ )
|
||||
{
|
||||
for( uint8_t j = 0; j < 16; j++ )
|
||||
{
|
||||
if( ( channelsMask[k] & ( 1 << j ) ) != 0 )
|
||||
{
|
||||
if( channels[i + j].Frequency == 0 )
|
||||
{ // Check if the channel is enabled
|
||||
continue;
|
||||
}
|
||||
if( joined == false )
|
||||
{
|
||||
if( ( IN865_JOIN_CHANNELS & ( 1 << j ) ) == 0 )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
}
|
||||
if( RegionCommonValueInRange( datarate, channels[i + j].DrRange.Fields.Min,
|
||||
channels[i + j].DrRange.Fields.Max ) == false )
|
||||
{ // Check if the current channel selection supports the given datarate
|
||||
continue;
|
||||
}
|
||||
if( bands[channels[i + j].Band].TimeOff > 0 )
|
||||
{ // Check if the band is available for transmission
|
||||
delayTransmission++;
|
||||
continue;
|
||||
}
|
||||
enabledChannels[nbEnabledChannels++] = i + j;
|
||||
}
|
||||
}
|
||||
if( datarate == DR_7 )
|
||||
{ // High Speed FSK channel
|
||||
timeOnAir = Radio.TimeOnAir( MODEM_FSK, bandwidth, phyDr * 1000, 0, 5, false, pktLen, true );
|
||||
}
|
||||
|
||||
*delayTx = delayTransmission;
|
||||
return nbEnabledChannels;
|
||||
else
|
||||
{
|
||||
timeOnAir = Radio.TimeOnAir( MODEM_LORA, bandwidth, phyDr, 1, 8, false, pktLen, true );
|
||||
}
|
||||
return timeOnAir;
|
||||
}
|
||||
|
||||
PhyParam_t RegionIN865GetPhyParam( GetPhyParams_t* getPhy )
|
||||
@@ -215,11 +191,6 @@ PhyParam_t RegionIN865GetPhyParam( GetPhyParams_t* getPhy )
|
||||
phyParam.Value = MaxPayloadOfDatarateIN865[getPhy->Datarate];
|
||||
break;
|
||||
}
|
||||
case PHY_MAX_PAYLOAD_REPEATER:
|
||||
{
|
||||
phyParam.Value = MaxPayloadOfDatarateRepeaterIN865[getPhy->Datarate];
|
||||
break;
|
||||
}
|
||||
case PHY_DUTY_CYCLE:
|
||||
{
|
||||
phyParam.Value = IN865_DUTY_CYCLE_ENABLED;
|
||||
@@ -328,11 +299,26 @@ PhyParam_t RegionIN865GetPhyParam( GetPhyParams_t* getPhy )
|
||||
phyParam.Value = IN865_BEACON_CHANNEL_DR;
|
||||
break;
|
||||
}
|
||||
case PHY_PING_SLOT_CHANNEL_FREQ:
|
||||
{
|
||||
phyParam.Value = IN865_PING_SLOT_CHANNEL_FREQ;
|
||||
break;
|
||||
}
|
||||
case PHY_PING_SLOT_CHANNEL_DR:
|
||||
{
|
||||
phyParam.Value = IN865_PING_SLOT_CHANNEL_DR;
|
||||
break;
|
||||
}
|
||||
case PHY_SF_FROM_DR:
|
||||
{
|
||||
phyParam.Value = DataratesIN865[getPhy->Datarate];
|
||||
break;
|
||||
}
|
||||
case PHY_BW_FROM_DR:
|
||||
{
|
||||
phyParam.Value = GetBandwidth( getPhy->Datarate );
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
break;
|
||||
@@ -344,7 +330,8 @@ PhyParam_t RegionIN865GetPhyParam( GetPhyParams_t* getPhy )
|
||||
|
||||
void RegionIN865SetBandTxDone( SetBandTxDoneParams_t* txDone )
|
||||
{
|
||||
RegionCommonSetBandTxDone( txDone->Joined, &NvmCtx.Bands[NvmCtx.Channels[txDone->Channel].Band], txDone->LastTxDoneTime );
|
||||
RegionCommonSetBandTxDone( &NvmCtx.Bands[NvmCtx.Channels[txDone->Channel].Band],
|
||||
txDone->LastTxAirTime, txDone->Joined, txDone->ElapsedTimeSinceStartUp );
|
||||
}
|
||||
|
||||
void RegionIN865InitDefaults( InitDefaultsParams_t* params )
|
||||
@@ -356,10 +343,14 @@ void RegionIN865InitDefaults( InitDefaultsParams_t* params )
|
||||
|
||||
switch( params->Type )
|
||||
{
|
||||
case INIT_TYPE_INIT:
|
||||
case INIT_TYPE_BANDS:
|
||||
{
|
||||
// Initialize bands
|
||||
memcpy1( ( uint8_t* )NvmCtx.Bands, ( uint8_t* )bands, sizeof( Band_t ) * IN865_MAX_NB_BANDS );
|
||||
break;
|
||||
}
|
||||
case INIT_TYPE_INIT:
|
||||
{
|
||||
|
||||
// Channels
|
||||
NvmCtx.Channels[0] = ( ChannelParams_t ) IN865_LC1;
|
||||
@@ -384,6 +375,11 @@ void RegionIN865InitDefaults( InitDefaultsParams_t* params )
|
||||
{
|
||||
// Restore channels default mask
|
||||
NvmCtx.ChannelsMask[0] |= NvmCtx.ChannelsDefaultMask[0];
|
||||
|
||||
// Channels
|
||||
NvmCtx.Channels[0] = ( ChannelParams_t ) IN865_LC1;
|
||||
NvmCtx.Channels[1] = ( ChannelParams_t ) IN865_LC2;
|
||||
NvmCtx.Channels[2] = ( ChannelParams_t ) IN865_LC3;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
@@ -403,6 +399,10 @@ bool RegionIN865Verify( VerifyParams_t* verify, PhyAttribute_t phyAttribute )
|
||||
{
|
||||
switch( phyAttribute )
|
||||
{
|
||||
case PHY_FREQUENCY:
|
||||
{
|
||||
return VerifyRfFreq( verify->Frequency );
|
||||
}
|
||||
case PHY_TX_DR:
|
||||
{
|
||||
if( verify->DatarateParams.Datarate == DR_6 )
|
||||
@@ -547,7 +547,6 @@ bool RegionIN865RxConfig( RxConfigParams_t* rxConfig, int8_t* datarate )
|
||||
{
|
||||
RadioModems_t modem;
|
||||
int8_t dr = rxConfig->Datarate;
|
||||
uint8_t maxPayload = 0;
|
||||
int8_t phyDr = 0;
|
||||
uint32_t frequency = rxConfig->Frequency;
|
||||
|
||||
@@ -584,15 +583,7 @@ bool RegionIN865RxConfig( RxConfigParams_t* rxConfig, int8_t* datarate )
|
||||
Radio.SetRxConfig( modem, rxConfig->Bandwidth, phyDr, 1, 0, 8, rxConfig->WindowTimeout, false, 0, false, 0, 0, true, rxConfig->RxContinuous );
|
||||
}
|
||||
|
||||
if( rxConfig->RepeaterSupport == true )
|
||||
{
|
||||
maxPayload = MaxPayloadOfDatarateRepeaterIN865[dr];
|
||||
}
|
||||
else
|
||||
{
|
||||
maxPayload = MaxPayloadOfDatarateIN865[dr];
|
||||
}
|
||||
Radio.SetMaxPayloadLength( modem, maxPayload + LORA_MAC_FRMPAYLOAD_OVERHEAD );
|
||||
Radio.SetMaxPayloadLength( modem, MaxPayloadOfDatarateIN865[dr] + LORAMAC_FRAME_PAYLOAD_OVERHEAD_SIZE );
|
||||
|
||||
*datarate = (uint8_t) dr;
|
||||
return true;
|
||||
@@ -615,18 +606,19 @@ bool RegionIN865TxConfig( TxConfigParams_t* txConfig, int8_t* txPower, TimerTime
|
||||
if( txConfig->Datarate == DR_7 )
|
||||
{ // High Speed FSK channel
|
||||
modem = MODEM_FSK;
|
||||
Radio.SetTxConfig( modem, phyTxPower, 25000, bandwidth, phyDr * 1000, 0, 5, false, true, 0, 0, false, 3000 );
|
||||
Radio.SetTxConfig( modem, phyTxPower, 25000, bandwidth, phyDr * 1000, 0, 5, false, true, 0, 0, false, 4000 );
|
||||
}
|
||||
else
|
||||
{
|
||||
modem = MODEM_LORA;
|
||||
Radio.SetTxConfig( modem, phyTxPower, 0, bandwidth, phyDr, 1, 8, false, true, 0, 0, false, 3000 );
|
||||
Radio.SetTxConfig( modem, phyTxPower, 0, bandwidth, phyDr, 1, 8, false, true, 0, 0, false, 4000 );
|
||||
}
|
||||
|
||||
// Update time-on-air
|
||||
*txTimeOnAir = GetTimeOnAir( txConfig->Datarate, txConfig->PktLen );
|
||||
|
||||
// Setup maximum payload lenght of the radio driver
|
||||
Radio.SetMaxPayloadLength( modem, txConfig->PktLen );
|
||||
// Get the time-on-air of the next tx frame
|
||||
*txTimeOnAir = Radio.TimeOnAir( modem, txConfig->PktLen );
|
||||
|
||||
*txPower = txPowerLimited;
|
||||
return true;
|
||||
@@ -857,74 +849,54 @@ int8_t RegionIN865AlternateDr( int8_t currentDr, AlternateDrType_t type )
|
||||
return currentDr;
|
||||
}
|
||||
|
||||
void RegionIN865CalcBackOff( CalcBackOffParams_t* calcBackOff )
|
||||
{
|
||||
RegionCommonCalcBackOffParams_t calcBackOffParams;
|
||||
|
||||
calcBackOffParams.Channels = NvmCtx.Channels;
|
||||
calcBackOffParams.Bands = NvmCtx.Bands;
|
||||
calcBackOffParams.LastTxIsJoinRequest = calcBackOff->LastTxIsJoinRequest;
|
||||
calcBackOffParams.Joined = calcBackOff->Joined;
|
||||
calcBackOffParams.DutyCycleEnabled = calcBackOff->DutyCycleEnabled;
|
||||
calcBackOffParams.Channel = calcBackOff->Channel;
|
||||
calcBackOffParams.ElapsedTime = calcBackOff->ElapsedTime;
|
||||
calcBackOffParams.TxTimeOnAir = calcBackOff->TxTimeOnAir;
|
||||
|
||||
RegionCommonCalcBackOff( &calcBackOffParams );
|
||||
}
|
||||
|
||||
LoRaMacStatus_t RegionIN865NextChannel( NextChanParams_t* nextChanParams, uint8_t* channel, TimerTime_t* time, TimerTime_t* aggregatedTimeOff )
|
||||
{
|
||||
uint8_t nbEnabledChannels = 0;
|
||||
uint8_t delayTx = 0;
|
||||
uint8_t nbRestrictedChannels = 0;
|
||||
uint8_t enabledChannels[IN865_MAX_NB_CHANNELS] = { 0 };
|
||||
TimerTime_t nextTxDelay = 0;
|
||||
RegionCommonIdentifyChannelsParam_t identifyChannelsParam;
|
||||
RegionCommonCountNbOfEnabledChannelsParams_t countChannelsParams;
|
||||
LoRaMacStatus_t status = LORAMAC_STATUS_NO_CHANNEL_FOUND;
|
||||
|
||||
if( RegionCommonCountChannels( NvmCtx.ChannelsMask, 0, 1 ) == 0 )
|
||||
{ // Reactivate default channels
|
||||
NvmCtx.ChannelsMask[0] |= LC( 1 ) + LC( 2 ) + LC( 3 );
|
||||
}
|
||||
|
||||
if( nextChanParams->AggrTimeOff <= TimerGetElapsedTime( nextChanParams->LastAggrTx ) )
|
||||
{
|
||||
// Reset Aggregated time off
|
||||
*aggregatedTimeOff = 0;
|
||||
// Search how many channels are enabled
|
||||
countChannelsParams.Joined = nextChanParams->Joined;
|
||||
countChannelsParams.Datarate = nextChanParams->Datarate;
|
||||
countChannelsParams.ChannelsMask = NvmCtx.ChannelsMask;
|
||||
countChannelsParams.Channels = NvmCtx.Channels;
|
||||
countChannelsParams.Bands = NvmCtx.Bands;
|
||||
countChannelsParams.MaxNbChannels = IN865_MAX_NB_CHANNELS;
|
||||
countChannelsParams.JoinChannels = IN865_JOIN_CHANNELS;
|
||||
|
||||
// Update bands Time OFF
|
||||
nextTxDelay = RegionCommonUpdateBandTimeOff( nextChanParams->Joined, nextChanParams->DutyCycleEnabled, NvmCtx.Bands, IN865_MAX_NB_BANDS );
|
||||
identifyChannelsParam.AggrTimeOff = nextChanParams->AggrTimeOff;
|
||||
identifyChannelsParam.LastAggrTx = nextChanParams->LastAggrTx;
|
||||
identifyChannelsParam.DutyCycleEnabled = nextChanParams->DutyCycleEnabled;
|
||||
identifyChannelsParam.MaxBands = IN865_MAX_NB_BANDS;
|
||||
|
||||
// Search how many channels are enabled
|
||||
nbEnabledChannels = CountNbOfEnabledChannels( nextChanParams->Joined, nextChanParams->Datarate,
|
||||
NvmCtx.ChannelsMask, NvmCtx.Channels,
|
||||
NvmCtx.Bands, enabledChannels, &delayTx );
|
||||
}
|
||||
else
|
||||
{
|
||||
delayTx++;
|
||||
nextTxDelay = nextChanParams->AggrTimeOff - TimerGetElapsedTime( nextChanParams->LastAggrTx );
|
||||
}
|
||||
identifyChannelsParam.ElapsedTimeSinceStartUp = nextChanParams->ElapsedTimeSinceStartUp;
|
||||
identifyChannelsParam.LastTxIsJoinRequest = nextChanParams->LastTxIsJoinRequest;
|
||||
identifyChannelsParam.ExpectedTimeOnAir = GetTimeOnAir( nextChanParams->Datarate, nextChanParams->PktLen );
|
||||
|
||||
if( nbEnabledChannels > 0 )
|
||||
identifyChannelsParam.CountNbOfEnabledChannelsParam = &countChannelsParams;
|
||||
|
||||
status = RegionCommonIdentifyChannels( &identifyChannelsParam, aggregatedTimeOff, enabledChannels,
|
||||
&nbEnabledChannels, &nbRestrictedChannels, time );
|
||||
|
||||
if( status == LORAMAC_STATUS_OK )
|
||||
{
|
||||
// We found a valid channel
|
||||
*channel = enabledChannels[randr( 0, nbEnabledChannels - 1 )];
|
||||
|
||||
*time = 0;
|
||||
return LORAMAC_STATUS_OK;
|
||||
}
|
||||
else
|
||||
else if( status == LORAMAC_STATUS_NO_CHANNEL_FOUND )
|
||||
{
|
||||
if( delayTx > 0 )
|
||||
{
|
||||
// Delay transmission due to AggregatedTimeOff or to a band time off
|
||||
*time = nextTxDelay;
|
||||
return LORAMAC_STATUS_DUTYCYCLE_RESTRICTED;
|
||||
}
|
||||
// Datarate not supported by any channel, restore defaults
|
||||
NvmCtx.ChannelsMask[0] |= LC( 1 ) + LC( 2 ) + LC( 3 );
|
||||
*time = 0;
|
||||
return LORAMAC_STATUS_NO_CHANNEL_FOUND;
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
LoRaMacStatus_t RegionIN865ChannelAdd( ChannelAddParams_t* channelAdd )
|
||||
|
@@ -37,6 +37,11 @@
|
||||
#ifndef __REGION_IN865_H__
|
||||
#define __REGION_IN865_H__
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
#include "region/Region.h"
|
||||
|
||||
/*!
|
||||
@@ -132,7 +137,7 @@
|
||||
/*!
|
||||
* Enabled or disabled the duty cycle
|
||||
*/
|
||||
#define IN865_DUTY_CYCLE_ENABLED 1
|
||||
#define IN865_DUTY_CYCLE_ENABLED 0
|
||||
|
||||
/*!
|
||||
* Maximum RX window duration
|
||||
@@ -196,6 +201,11 @@
|
||||
*/
|
||||
#define IN865_BEACON_CHANNEL_FREQ 866550000
|
||||
|
||||
/*!
|
||||
* Ping slot channel frequency
|
||||
*/
|
||||
#define IN865_PING_SLOT_CHANNEL_FREQ 866550000
|
||||
|
||||
/*!
|
||||
* Payload size of a beacon frame
|
||||
*/
|
||||
@@ -233,9 +243,9 @@
|
||||
|
||||
/*!
|
||||
* Band 0 definition
|
||||
* { DutyCycle, TxMaxPower, LastJoinTxDoneTime, LastTxDoneTime, TimeOff }
|
||||
* Band = { DutyCycle, TxMaxPower, LastBandUpdateTime, TimeCredits, MaxTimeCredits, ReadyForTransmission }
|
||||
*/
|
||||
#define IN865_BAND0 { 1 , IN865_MAX_TX_POWER, 0, 0, 0 } // 100.0 %
|
||||
#define IN865_BAND0 { 1 , IN865_MAX_TX_POWER, 0, 0, 0, 0 } // 100.0 %
|
||||
|
||||
/*!
|
||||
* LoRaMac default channel 1
|
||||
@@ -271,15 +281,10 @@ static const uint8_t DataratesIN865[] = { 12, 11, 10, 9, 8, 7, 7, 50 };
|
||||
static const uint32_t BandwidthsIN865[] = { 125000, 125000, 125000, 125000, 125000, 125000, 250000, 0 };
|
||||
|
||||
/*!
|
||||
* Maximum payload with respect to the datarate index. Cannot operate with repeater.
|
||||
* Maximum payload with respect to the datarate index.
|
||||
*/
|
||||
static const uint8_t MaxPayloadOfDatarateIN865[] = { 51, 51, 51, 115, 242, 242, 242, 242 };
|
||||
|
||||
/*!
|
||||
* Maximum payload with respect to the datarate index. Can operate with repeater.
|
||||
*/
|
||||
static const uint8_t MaxPayloadOfDatarateRepeaterIN865[] = { 51, 51, 51, 115, 222, 222, 222, 222 };
|
||||
|
||||
/*!
|
||||
* Effective datarate offsets for receive window 1.
|
||||
*/
|
||||
@@ -440,13 +445,6 @@ uint8_t RegionIN865DlChannelReq( DlChannelReqParams_t* dlChannelReq );
|
||||
*/
|
||||
int8_t RegionIN865AlternateDr( int8_t currentDr, AlternateDrType_t type );
|
||||
|
||||
/*!
|
||||
* \brief Calculates the back-off time.
|
||||
*
|
||||
* \param [IN] calcBackOff Pointer to the function parameters.
|
||||
*/
|
||||
void RegionIN865CalcBackOff( CalcBackOffParams_t* calcBackOff );
|
||||
|
||||
/*!
|
||||
* \brief Searches and set the next random available channel
|
||||
*
|
||||
@@ -508,4 +506,8 @@ uint8_t RegionIN865ApplyDrOffset( uint8_t downlinkDwellTime, int8_t dr, int8_t d
|
||||
|
||||
/*! \} defgroup REGIONIN865 */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // __REGION_IN865_H__
|
||||
|
@@ -138,45 +138,12 @@ static bool VerifyRfFreq( uint32_t freq )
|
||||
return false;
|
||||
}
|
||||
|
||||
static uint8_t CountNbOfEnabledChannels( bool joined, uint8_t datarate, uint16_t* channelsMask, ChannelParams_t* channels, Band_t* bands, uint8_t* enabledChannels, uint8_t* delayTx )
|
||||
static TimerTime_t GetTimeOnAir( int8_t datarate, uint16_t pktLen )
|
||||
{
|
||||
uint8_t nbEnabledChannels = 0;
|
||||
uint8_t delayTransmission = 0;
|
||||
int8_t phyDr = DataratesKR920[datarate];
|
||||
uint32_t bandwidth = GetBandwidth( datarate );
|
||||
|
||||
for( uint8_t i = 0, k = 0; i < KR920_MAX_NB_CHANNELS; i += 16, k++ )
|
||||
{
|
||||
for( uint8_t j = 0; j < 16; j++ )
|
||||
{
|
||||
if( ( channelsMask[k] & ( 1 << j ) ) != 0 )
|
||||
{
|
||||
if( channels[i + j].Frequency == 0 )
|
||||
{ // Check if the channel is enabled
|
||||
continue;
|
||||
}
|
||||
if( joined == false )
|
||||
{
|
||||
if( ( KR920_JOIN_CHANNELS & ( 1 << j ) ) == 0 )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
}
|
||||
if( RegionCommonValueInRange( datarate, channels[i + j].DrRange.Fields.Min,
|
||||
channels[i + j].DrRange.Fields.Max ) == false )
|
||||
{ // Check if the current channel selection supports the given datarate
|
||||
continue;
|
||||
}
|
||||
if( bands[channels[i + j].Band].TimeOff > 0 )
|
||||
{ // Check if the band is available for transmission
|
||||
delayTransmission++;
|
||||
continue;
|
||||
}
|
||||
enabledChannels[nbEnabledChannels++] = i + j;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
*delayTx = delayTransmission;
|
||||
return nbEnabledChannels;
|
||||
return Radio.TimeOnAir( MODEM_LORA, bandwidth, phyDr, 1, 8, false, pktLen, true );
|
||||
}
|
||||
|
||||
PhyParam_t RegionKR920GetPhyParam( GetPhyParams_t* getPhy )
|
||||
@@ -230,11 +197,6 @@ PhyParam_t RegionKR920GetPhyParam( GetPhyParams_t* getPhy )
|
||||
phyParam.Value = MaxPayloadOfDatarateKR920[getPhy->Datarate];
|
||||
break;
|
||||
}
|
||||
case PHY_MAX_PAYLOAD_REPEATER:
|
||||
{
|
||||
phyParam.Value = MaxPayloadOfDatarateRepeaterKR920[getPhy->Datarate];
|
||||
break;
|
||||
}
|
||||
case PHY_DUTY_CYCLE:
|
||||
{
|
||||
phyParam.Value = KR920_DUTY_CYCLE_ENABLED;
|
||||
@@ -347,11 +309,26 @@ PhyParam_t RegionKR920GetPhyParam( GetPhyParams_t* getPhy )
|
||||
phyParam.Value = KR920_BEACON_CHANNEL_DR;
|
||||
break;
|
||||
}
|
||||
case PHY_PING_SLOT_CHANNEL_FREQ:
|
||||
{
|
||||
phyParam.Value = KR920_PING_SLOT_CHANNEL_FREQ;
|
||||
break;
|
||||
}
|
||||
case PHY_PING_SLOT_CHANNEL_DR:
|
||||
{
|
||||
phyParam.Value = KR920_PING_SLOT_CHANNEL_DR;
|
||||
break;
|
||||
}
|
||||
case PHY_SF_FROM_DR:
|
||||
{
|
||||
phyParam.Value = DataratesKR920[getPhy->Datarate];
|
||||
break;
|
||||
}
|
||||
case PHY_BW_FROM_DR:
|
||||
{
|
||||
phyParam.Value = GetBandwidth( getPhy->Datarate );
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
break;
|
||||
@@ -363,7 +340,8 @@ PhyParam_t RegionKR920GetPhyParam( GetPhyParams_t* getPhy )
|
||||
|
||||
void RegionKR920SetBandTxDone( SetBandTxDoneParams_t* txDone )
|
||||
{
|
||||
RegionCommonSetBandTxDone( txDone->Joined, &NvmCtx.Bands[NvmCtx.Channels[txDone->Channel].Band], txDone->LastTxDoneTime );
|
||||
RegionCommonSetBandTxDone( &NvmCtx.Bands[NvmCtx.Channels[txDone->Channel].Band],
|
||||
txDone->LastTxAirTime, txDone->Joined, txDone->ElapsedTimeSinceStartUp );
|
||||
}
|
||||
|
||||
void RegionKR920InitDefaults( InitDefaultsParams_t* params )
|
||||
@@ -375,10 +353,14 @@ void RegionKR920InitDefaults( InitDefaultsParams_t* params )
|
||||
|
||||
switch( params->Type )
|
||||
{
|
||||
case INIT_TYPE_INIT:
|
||||
case INIT_TYPE_BANDS:
|
||||
{
|
||||
// Initialize bands
|
||||
memcpy1( ( uint8_t* )NvmCtx.Bands, ( uint8_t* )bands, sizeof( Band_t ) * KR920_MAX_NB_BANDS );
|
||||
break;
|
||||
}
|
||||
case INIT_TYPE_INIT:
|
||||
{
|
||||
|
||||
// Channels
|
||||
NvmCtx.Channels[0] = ( ChannelParams_t ) KR920_LC1;
|
||||
@@ -387,6 +369,7 @@ void RegionKR920InitDefaults( InitDefaultsParams_t* params )
|
||||
|
||||
// Initialize the channels default mask
|
||||
NvmCtx.ChannelsDefaultMask[0] = LC( 1 ) + LC( 2 ) + LC( 3 );
|
||||
|
||||
// Update the channels mask
|
||||
RegionCommonChanMaskCopy( NvmCtx.ChannelsMask, NvmCtx.ChannelsDefaultMask, 1 );
|
||||
break;
|
||||
@@ -403,6 +386,11 @@ void RegionKR920InitDefaults( InitDefaultsParams_t* params )
|
||||
{
|
||||
// Restore channels default mask
|
||||
NvmCtx.ChannelsMask[0] |= NvmCtx.ChannelsDefaultMask[0];
|
||||
|
||||
// Channels
|
||||
NvmCtx.Channels[0] = ( ChannelParams_t ) KR920_LC1;
|
||||
NvmCtx.Channels[1] = ( ChannelParams_t ) KR920_LC2;
|
||||
NvmCtx.Channels[2] = ( ChannelParams_t ) KR920_LC3;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
@@ -422,6 +410,10 @@ bool RegionKR920Verify( VerifyParams_t* verify, PhyAttribute_t phyAttribute )
|
||||
{
|
||||
switch( phyAttribute )
|
||||
{
|
||||
case PHY_FREQUENCY:
|
||||
{
|
||||
return VerifyRfFreq( verify->Frequency );
|
||||
}
|
||||
case PHY_TX_DR:
|
||||
{
|
||||
return RegionCommonValueInRange( verify->DatarateParams.Datarate, KR920_TX_MIN_DATARATE, KR920_TX_MAX_DATARATE );
|
||||
@@ -544,7 +536,6 @@ void RegionKR920ComputeRxWindowParameters( int8_t datarate, uint8_t minRxSymbols
|
||||
bool RegionKR920RxConfig( RxConfigParams_t* rxConfig, int8_t* datarate )
|
||||
{
|
||||
int8_t dr = rxConfig->Datarate;
|
||||
uint8_t maxPayload = 0;
|
||||
int8_t phyDr = 0;
|
||||
uint32_t frequency = rxConfig->Frequency;
|
||||
|
||||
@@ -571,8 +562,7 @@ bool RegionKR920RxConfig( RxConfigParams_t* rxConfig, int8_t* datarate )
|
||||
|
||||
// Radio configuration
|
||||
Radio.SetRxConfig( MODEM_LORA, rxConfig->Bandwidth, phyDr, 1, 0, 8, rxConfig->WindowTimeout, false, 0, false, 0, 0, true, rxConfig->RxContinuous );
|
||||
maxPayload = MaxPayloadOfDatarateKR920[dr];
|
||||
Radio.SetMaxPayloadLength( MODEM_LORA, maxPayload + LORA_MAC_FRMPAYLOAD_OVERHEAD );
|
||||
Radio.SetMaxPayloadLength( MODEM_LORA, MaxPayloadOfDatarateKR920[dr] + LORAMAC_FRAME_PAYLOAD_OVERHEAD_SIZE );
|
||||
|
||||
*datarate = (uint8_t) dr;
|
||||
return true;
|
||||
@@ -596,12 +586,12 @@ bool RegionKR920TxConfig( TxConfigParams_t* txConfig, int8_t* txPower, TimerTime
|
||||
// Setup the radio frequency
|
||||
Radio.SetChannel( NvmCtx.Channels[txConfig->Channel].Frequency );
|
||||
|
||||
Radio.SetTxConfig( MODEM_LORA, phyTxPower, 0, bandwidth, phyDr, 1, 8, false, true, 0, 0, false, 3000 );
|
||||
Radio.SetTxConfig( MODEM_LORA, phyTxPower, 0, bandwidth, phyDr, 1, 8, false, true, 0, 0, false, 4000 );
|
||||
|
||||
// Setup maximum payload lenght of the radio driver
|
||||
Radio.SetMaxPayloadLength( MODEM_LORA, txConfig->PktLen );
|
||||
// Get the time-on-air of the next tx frame
|
||||
*txTimeOnAir = Radio.TimeOnAir( MODEM_LORA, txConfig->PktLen );
|
||||
// Update time-on-air
|
||||
*txTimeOnAir = GetTimeOnAir( txConfig->Datarate, txConfig->PktLen );
|
||||
|
||||
*txPower = txPowerLimited;
|
||||
return true;
|
||||
@@ -825,55 +815,45 @@ int8_t RegionKR920AlternateDr( int8_t currentDr, AlternateDrType_t type )
|
||||
return currentDr;
|
||||
}
|
||||
|
||||
void RegionKR920CalcBackOff( CalcBackOffParams_t* calcBackOff )
|
||||
{
|
||||
RegionCommonCalcBackOffParams_t calcBackOffParams;
|
||||
|
||||
calcBackOffParams.Channels = NvmCtx.Channels;
|
||||
calcBackOffParams.Bands = NvmCtx.Bands;
|
||||
calcBackOffParams.LastTxIsJoinRequest = calcBackOff->LastTxIsJoinRequest;
|
||||
calcBackOffParams.Joined = calcBackOff->Joined;
|
||||
calcBackOffParams.DutyCycleEnabled = calcBackOff->DutyCycleEnabled;
|
||||
calcBackOffParams.Channel = calcBackOff->Channel;
|
||||
calcBackOffParams.ElapsedTime = calcBackOff->ElapsedTime;
|
||||
calcBackOffParams.TxTimeOnAir = calcBackOff->TxTimeOnAir;
|
||||
|
||||
RegionCommonCalcBackOff( &calcBackOffParams );
|
||||
}
|
||||
|
||||
LoRaMacStatus_t RegionKR920NextChannel( NextChanParams_t* nextChanParams, uint8_t* channel, TimerTime_t* time, TimerTime_t* aggregatedTimeOff )
|
||||
{
|
||||
uint8_t channelNext = 0;
|
||||
uint8_t nbEnabledChannels = 0;
|
||||
uint8_t delayTx = 0;
|
||||
uint8_t nbRestrictedChannels = 0;
|
||||
uint8_t enabledChannels[KR920_MAX_NB_CHANNELS] = { 0 };
|
||||
TimerTime_t nextTxDelay = 0;
|
||||
RegionCommonIdentifyChannelsParam_t identifyChannelsParam;
|
||||
RegionCommonCountNbOfEnabledChannelsParams_t countChannelsParams;
|
||||
LoRaMacStatus_t status = LORAMAC_STATUS_NO_CHANNEL_FOUND;
|
||||
|
||||
if( RegionCommonCountChannels( NvmCtx.ChannelsMask, 0, 1 ) == 0 )
|
||||
{ // Reactivate default channels
|
||||
NvmCtx.ChannelsMask[0] |= LC( 1 ) + LC( 2 ) + LC( 3 );
|
||||
}
|
||||
|
||||
if( nextChanParams->AggrTimeOff <= TimerGetElapsedTime( nextChanParams->LastAggrTx ) )
|
||||
{
|
||||
// Reset Aggregated time off
|
||||
*aggregatedTimeOff = 0;
|
||||
// Search how many channels are enabled
|
||||
countChannelsParams.Joined = nextChanParams->Joined;
|
||||
countChannelsParams.Datarate = nextChanParams->Datarate;
|
||||
countChannelsParams.ChannelsMask = NvmCtx.ChannelsMask;
|
||||
countChannelsParams.Channels = NvmCtx.Channels;
|
||||
countChannelsParams.Bands = NvmCtx.Bands;
|
||||
countChannelsParams.MaxNbChannels = KR920_MAX_NB_CHANNELS;
|
||||
countChannelsParams.JoinChannels = KR920_JOIN_CHANNELS;
|
||||
|
||||
// Update bands Time OFF
|
||||
nextTxDelay = RegionCommonUpdateBandTimeOff( nextChanParams->Joined, nextChanParams->DutyCycleEnabled, NvmCtx.Bands, KR920_MAX_NB_BANDS );
|
||||
identifyChannelsParam.AggrTimeOff = nextChanParams->AggrTimeOff;
|
||||
identifyChannelsParam.LastAggrTx = nextChanParams->LastAggrTx;
|
||||
identifyChannelsParam.DutyCycleEnabled = nextChanParams->DutyCycleEnabled;
|
||||
identifyChannelsParam.MaxBands = KR920_MAX_NB_BANDS;
|
||||
|
||||
// Search how many channels are enabled
|
||||
nbEnabledChannels = CountNbOfEnabledChannels( nextChanParams->Joined, nextChanParams->Datarate,
|
||||
NvmCtx.ChannelsMask, NvmCtx.Channels,
|
||||
NvmCtx.Bands, enabledChannels, &delayTx );
|
||||
}
|
||||
else
|
||||
{
|
||||
delayTx++;
|
||||
nextTxDelay = nextChanParams->AggrTimeOff - TimerGetElapsedTime( nextChanParams->LastAggrTx );
|
||||
}
|
||||
identifyChannelsParam.ElapsedTimeSinceStartUp = nextChanParams->ElapsedTimeSinceStartUp;
|
||||
identifyChannelsParam.LastTxIsJoinRequest = nextChanParams->LastTxIsJoinRequest;
|
||||
identifyChannelsParam.ExpectedTimeOnAir = GetTimeOnAir( nextChanParams->Datarate, nextChanParams->PktLen );
|
||||
|
||||
if( nbEnabledChannels > 0 )
|
||||
identifyChannelsParam.CountNbOfEnabledChannelsParam = &countChannelsParams;
|
||||
|
||||
status = RegionCommonIdentifyChannels( &identifyChannelsParam, aggregatedTimeOff, enabledChannels,
|
||||
&nbEnabledChannels, &nbRestrictedChannels, time );
|
||||
|
||||
if( status == LORAMAC_STATUS_OK )
|
||||
{
|
||||
for( uint8_t i = 0, j = randr( 0, nbEnabledChannels - 1 ); i < KR920_MAX_NB_CHANNELS; i++ )
|
||||
{
|
||||
@@ -886,25 +866,19 @@ LoRaMacStatus_t RegionKR920NextChannel( NextChanParams_t* nextChanParams, uint8_
|
||||
{
|
||||
// Free channel found
|
||||
*channel = channelNext;
|
||||
*time = 0;
|
||||
return LORAMAC_STATUS_OK;
|
||||
}
|
||||
}
|
||||
return LORAMAC_STATUS_NO_FREE_CHANNEL_FOUND;
|
||||
// Even if one or more channels are available according to the channel plan, no free channel
|
||||
// was found during the LBT procedure.
|
||||
status = LORAMAC_STATUS_NO_FREE_CHANNEL_FOUND;
|
||||
}
|
||||
else
|
||||
else if( status == LORAMAC_STATUS_NO_CHANNEL_FOUND )
|
||||
{
|
||||
if( delayTx > 0 )
|
||||
{
|
||||
// Delay transmission due to AggregatedTimeOff or to a band time off
|
||||
*time = nextTxDelay;
|
||||
return LORAMAC_STATUS_DUTYCYCLE_RESTRICTED;
|
||||
}
|
||||
// Datarate not supported by any channel, restore defaults
|
||||
NvmCtx.ChannelsMask[0] |= LC( 1 ) + LC( 2 ) + LC( 3 );
|
||||
*time = 0;
|
||||
return LORAMAC_STATUS_NO_CHANNEL_FOUND;
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
LoRaMacStatus_t RegionKR920ChannelAdd( ChannelAddParams_t* channelAdd )
|
||||
|
@@ -37,6 +37,11 @@
|
||||
#ifndef __REGION_KR920_H__
|
||||
#define __REGION_KR920_H__
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
#include "region/Region.h"
|
||||
|
||||
/*!
|
||||
@@ -201,6 +206,11 @@
|
||||
*/
|
||||
#define KR920_BEACON_CHANNEL_FREQ 923100000
|
||||
|
||||
/*!
|
||||
* Ping slot channel frequency
|
||||
*/
|
||||
#define KR920_PING_SLOT_CHANNEL_FREQ 923100000
|
||||
|
||||
/*!
|
||||
* Payload size of a beacon frame
|
||||
*/
|
||||
@@ -238,9 +248,9 @@
|
||||
|
||||
/*!
|
||||
* Band 0 definition
|
||||
* { DutyCycle, TxMaxPower, LastJoinTxDoneTime, LastTxDoneTime, TimeOff }
|
||||
* Band = { DutyCycle, TxMaxPower, LastBandUpdateTime, TimeCredits, MaxTimeCredits, ReadyForTransmission }
|
||||
*/
|
||||
#define KR920_BAND0 { 1 , KR920_MAX_TX_POWER, 0, 0, 0 } // 100.0 %
|
||||
#define KR920_BAND0 { 1 , KR920_MAX_TX_POWER, 0, 0, 0, 0 } // 100.0 %
|
||||
|
||||
/*!
|
||||
* LoRaMac default channel 1
|
||||
@@ -286,15 +296,10 @@ static const uint8_t DataratesKR920[] = { 12, 11, 10, 9, 8, 7 };
|
||||
static const uint32_t BandwidthsKR920[] = { 125000, 125000, 125000, 125000, 125000, 125000 };
|
||||
|
||||
/*!
|
||||
* Maximum payload with respect to the datarate index. Can operate with and without a repeater.
|
||||
* Maximum payload with respect to the datarate index.
|
||||
*/
|
||||
static const uint8_t MaxPayloadOfDatarateKR920[] = { 51, 51, 51, 115, 242, 242 };
|
||||
|
||||
/*!
|
||||
* Maximum payload with respect to the datarate index. Can operate with repeater.
|
||||
*/
|
||||
static const uint8_t MaxPayloadOfDatarateRepeaterKR920[] = { 51, 51, 51, 115, 222, 222 };
|
||||
|
||||
/*!
|
||||
* \brief The function gets a value of a specific phy attribute.
|
||||
*
|
||||
@@ -450,13 +455,6 @@ uint8_t RegionKR920DlChannelReq( DlChannelReqParams_t* dlChannelReq );
|
||||
*/
|
||||
int8_t RegionKR920AlternateDr( int8_t currentDr, AlternateDrType_t type );
|
||||
|
||||
/*!
|
||||
* \brief Calculates the back-off time.
|
||||
*
|
||||
* \param [IN] calcBackOff Pointer to the function parameters.
|
||||
*/
|
||||
void RegionKR920CalcBackOff( CalcBackOffParams_t* calcBackOff );
|
||||
|
||||
/*!
|
||||
* \brief Searches and set the next random available channel
|
||||
*
|
||||
@@ -518,4 +516,8 @@ uint8_t RegionKR920ApplyDrOffset( uint8_t downlinkDwellTime, int8_t dr, int8_t d
|
||||
|
||||
/*! \} defgroup REGIONKR920 */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // __REGION_KR920_H__
|
||||
|
@@ -120,45 +120,21 @@ static bool VerifyRfFreq( uint32_t freq )
|
||||
return true;
|
||||
}
|
||||
|
||||
static uint8_t CountNbOfEnabledChannels( bool joined, uint8_t datarate, uint16_t* channelsMask, ChannelParams_t* channels, Band_t* bands, uint8_t* enabledChannels, uint8_t* delayTx )
|
||||
static TimerTime_t GetTimeOnAir( int8_t datarate, uint16_t pktLen )
|
||||
{
|
||||
uint8_t nbEnabledChannels = 0;
|
||||
uint8_t delayTransmission = 0;
|
||||
int8_t phyDr = DataratesRU864[datarate];
|
||||
uint32_t bandwidth = GetBandwidth( datarate );
|
||||
TimerTime_t timeOnAir = 0;
|
||||
|
||||
for( uint8_t i = 0, k = 0; i < RU864_MAX_NB_CHANNELS; i += 16, k++ )
|
||||
{
|
||||
for( uint8_t j = 0; j < 16; j++ )
|
||||
{
|
||||
if( ( channelsMask[k] & ( 1 << j ) ) != 0 )
|
||||
{
|
||||
if( channels[i + j].Frequency == 0 )
|
||||
{ // Check if the channel is enabled
|
||||
continue;
|
||||
}
|
||||
if( joined == false )
|
||||
{
|
||||
if( ( RU864_JOIN_CHANNELS & ( 1 << j ) ) == 0 )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
}
|
||||
if( RegionCommonValueInRange( datarate, channels[i + j].DrRange.Fields.Min,
|
||||
channels[i + j].DrRange.Fields.Max ) == false )
|
||||
{ // Check if the current channel selection supports the given datarate
|
||||
continue;
|
||||
}
|
||||
if( bands[channels[i + j].Band].TimeOff > 0 )
|
||||
{ // Check if the band is available for transmission
|
||||
delayTransmission++;
|
||||
continue;
|
||||
}
|
||||
enabledChannels[nbEnabledChannels++] = i + j;
|
||||
}
|
||||
}
|
||||
if( datarate == DR_7 )
|
||||
{ // High Speed FSK channel
|
||||
timeOnAir = Radio.TimeOnAir( MODEM_FSK, bandwidth, phyDr * 1000, 0, 5, false, pktLen, true );
|
||||
}
|
||||
|
||||
*delayTx = delayTransmission;
|
||||
return nbEnabledChannels;
|
||||
else
|
||||
{
|
||||
timeOnAir = Radio.TimeOnAir( MODEM_LORA, bandwidth, phyDr, 1, 8, false, pktLen, true );
|
||||
}
|
||||
return timeOnAir;
|
||||
}
|
||||
|
||||
PhyParam_t RegionRU864GetPhyParam( GetPhyParams_t* getPhy )
|
||||
@@ -187,6 +163,11 @@ PhyParam_t RegionRU864GetPhyParam( GetPhyParams_t* getPhy )
|
||||
phyParam.Value = GetNextLowerTxDr( getPhy->Datarate, RU864_TX_MIN_DATARATE );
|
||||
break;
|
||||
}
|
||||
case PHY_MAX_TX_POWER:
|
||||
{
|
||||
phyParam.Value = RU864_MAX_TX_POWER;
|
||||
break;
|
||||
}
|
||||
case PHY_DEF_TX_POWER:
|
||||
{
|
||||
phyParam.Value = RU864_DEFAULT_TX_POWER;
|
||||
@@ -207,11 +188,6 @@ PhyParam_t RegionRU864GetPhyParam( GetPhyParams_t* getPhy )
|
||||
phyParam.Value = MaxPayloadOfDatarateRU864[getPhy->Datarate];
|
||||
break;
|
||||
}
|
||||
case PHY_MAX_PAYLOAD_REPEATER:
|
||||
{
|
||||
phyParam.Value = MaxPayloadOfDatarateRepeaterRU864[getPhy->Datarate];
|
||||
break;
|
||||
}
|
||||
case PHY_DUTY_CYCLE:
|
||||
{
|
||||
phyParam.Value = RU864_DUTY_CYCLE_ENABLED;
|
||||
@@ -320,6 +296,26 @@ PhyParam_t RegionRU864GetPhyParam( GetPhyParams_t* getPhy )
|
||||
phyParam.Value = RU864_BEACON_CHANNEL_DR;
|
||||
break;
|
||||
}
|
||||
case PHY_PING_SLOT_CHANNEL_FREQ:
|
||||
{
|
||||
phyParam.Value = RU864_PING_SLOT_CHANNEL_FREQ;
|
||||
break;
|
||||
}
|
||||
case PHY_PING_SLOT_CHANNEL_DR:
|
||||
{
|
||||
phyParam.Value = RU864_PING_SLOT_CHANNEL_DR;
|
||||
break;
|
||||
}
|
||||
case PHY_SF_FROM_DR:
|
||||
{
|
||||
phyParam.Value = DataratesRU864[getPhy->Datarate];
|
||||
break;
|
||||
}
|
||||
case PHY_BW_FROM_DR:
|
||||
{
|
||||
phyParam.Value = GetBandwidth( getPhy->Datarate );
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
break;
|
||||
@@ -331,7 +327,8 @@ PhyParam_t RegionRU864GetPhyParam( GetPhyParams_t* getPhy )
|
||||
|
||||
void RegionRU864SetBandTxDone( SetBandTxDoneParams_t* txDone )
|
||||
{
|
||||
RegionCommonSetBandTxDone( txDone->Joined, &NvmCtx.Bands[NvmCtx.Channels[txDone->Channel].Band], txDone->LastTxDoneTime );
|
||||
RegionCommonSetBandTxDone( &NvmCtx.Bands[NvmCtx.Channels[txDone->Channel].Band],
|
||||
txDone->LastTxAirTime, txDone->Joined, txDone->ElapsedTimeSinceStartUp );
|
||||
}
|
||||
|
||||
void RegionRU864InitDefaults( InitDefaultsParams_t* params )
|
||||
@@ -343,10 +340,14 @@ void RegionRU864InitDefaults( InitDefaultsParams_t* params )
|
||||
|
||||
switch( params->Type )
|
||||
{
|
||||
case INIT_TYPE_INIT:
|
||||
case INIT_TYPE_BANDS:
|
||||
{
|
||||
// Initialize bands
|
||||
memcpy1( ( uint8_t* )NvmCtx.Bands, ( uint8_t* )bands, sizeof( Band_t ) * RU864_MAX_NB_BANDS );
|
||||
break;
|
||||
}
|
||||
case INIT_TYPE_INIT:
|
||||
{
|
||||
|
||||
// Channels
|
||||
NvmCtx.Channels[0] = ( ChannelParams_t ) RU864_LC1;
|
||||
@@ -370,6 +371,10 @@ void RegionRU864InitDefaults( InitDefaultsParams_t* params )
|
||||
{
|
||||
// Restore channels default mask
|
||||
NvmCtx.ChannelsMask[0] |= NvmCtx.ChannelsDefaultMask[0];
|
||||
|
||||
// Channels
|
||||
NvmCtx.Channels[0] = ( ChannelParams_t ) RU864_LC1;
|
||||
NvmCtx.Channels[1] = ( ChannelParams_t ) RU864_LC2;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
@@ -389,6 +394,10 @@ bool RegionRU864Verify( VerifyParams_t* verify, PhyAttribute_t phyAttribute )
|
||||
{
|
||||
switch( phyAttribute )
|
||||
{
|
||||
case PHY_FREQUENCY:
|
||||
{
|
||||
return VerifyRfFreq( verify->Frequency );
|
||||
}
|
||||
case PHY_TX_DR:
|
||||
{
|
||||
return RegionCommonValueInRange( verify->DatarateParams.Datarate, RU864_TX_MIN_DATARATE, RU864_TX_MAX_DATARATE );
|
||||
@@ -519,7 +528,6 @@ bool RegionRU864RxConfig( RxConfigParams_t* rxConfig, int8_t* datarate )
|
||||
{
|
||||
RadioModems_t modem;
|
||||
int8_t dr = rxConfig->Datarate;
|
||||
uint8_t maxPayload = 0;
|
||||
int8_t phyDr = 0;
|
||||
uint32_t frequency = rxConfig->Frequency;
|
||||
|
||||
@@ -556,16 +564,7 @@ bool RegionRU864RxConfig( RxConfigParams_t* rxConfig, int8_t* datarate )
|
||||
Radio.SetRxConfig( modem, rxConfig->Bandwidth, phyDr, 1, 0, 8, rxConfig->WindowTimeout, false, 0, false, 0, 0, true, rxConfig->RxContinuous );
|
||||
}
|
||||
|
||||
if( rxConfig->RepeaterSupport == true )
|
||||
{
|
||||
maxPayload = MaxPayloadOfDatarateRepeaterRU864[dr];
|
||||
}
|
||||
else
|
||||
{
|
||||
maxPayload = MaxPayloadOfDatarateRU864[dr];
|
||||
}
|
||||
|
||||
Radio.SetMaxPayloadLength( modem, maxPayload + LORA_MAC_FRMPAYLOAD_OVERHEAD );
|
||||
Radio.SetMaxPayloadLength( modem, MaxPayloadOfDatarateRU864[dr] + LORAMAC_FRAME_PAYLOAD_OVERHEAD_SIZE );
|
||||
|
||||
*datarate = (uint8_t) dr;
|
||||
return true;
|
||||
@@ -588,18 +587,19 @@ bool RegionRU864TxConfig( TxConfigParams_t* txConfig, int8_t* txPower, TimerTime
|
||||
if( txConfig->Datarate == DR_7 )
|
||||
{ // High Speed FSK channel
|
||||
modem = MODEM_FSK;
|
||||
Radio.SetTxConfig( modem, phyTxPower, 25000, bandwidth, phyDr * 1000, 0, 5, false, true, 0, 0, false, 3000 );
|
||||
Radio.SetTxConfig( modem, phyTxPower, 25000, bandwidth, phyDr * 1000, 0, 5, false, true, 0, 0, false, 4000 );
|
||||
}
|
||||
else
|
||||
{
|
||||
modem = MODEM_LORA;
|
||||
Radio.SetTxConfig( modem, phyTxPower, 0, bandwidth, phyDr, 1, 8, false, true, 0, 0, false, 3000 );
|
||||
Radio.SetTxConfig( modem, phyTxPower, 0, bandwidth, phyDr, 1, 8, false, true, 0, 0, false, 4000 );
|
||||
}
|
||||
|
||||
// Update time-on-air
|
||||
*txTimeOnAir = GetTimeOnAir( txConfig->Datarate, txConfig->PktLen );
|
||||
|
||||
// Setup maximum payload lenght of the radio driver
|
||||
Radio.SetMaxPayloadLength( modem, txConfig->PktLen );
|
||||
// Get the time-on-air of the next tx frame
|
||||
*txTimeOnAir = Radio.TimeOnAir( modem, txConfig->PktLen );
|
||||
|
||||
*txPower = txPowerLimited;
|
||||
return true;
|
||||
@@ -823,74 +823,54 @@ int8_t RegionRU864AlternateDr( int8_t currentDr, AlternateDrType_t type )
|
||||
return currentDr;
|
||||
}
|
||||
|
||||
void RegionRU864CalcBackOff( CalcBackOffParams_t* calcBackOff )
|
||||
{
|
||||
RegionCommonCalcBackOffParams_t calcBackOffParams;
|
||||
|
||||
calcBackOffParams.Channels = NvmCtx.Channels;
|
||||
calcBackOffParams.Bands = NvmCtx.Bands;
|
||||
calcBackOffParams.LastTxIsJoinRequest = calcBackOff->LastTxIsJoinRequest;
|
||||
calcBackOffParams.Joined = calcBackOff->Joined;
|
||||
calcBackOffParams.DutyCycleEnabled = calcBackOff->DutyCycleEnabled;
|
||||
calcBackOffParams.Channel = calcBackOff->Channel;
|
||||
calcBackOffParams.ElapsedTime = calcBackOff->ElapsedTime;
|
||||
calcBackOffParams.TxTimeOnAir = calcBackOff->TxTimeOnAir;
|
||||
|
||||
RegionCommonCalcBackOff( &calcBackOffParams );
|
||||
}
|
||||
|
||||
LoRaMacStatus_t RegionRU864NextChannel( NextChanParams_t* nextChanParams, uint8_t* channel, TimerTime_t* time, TimerTime_t* aggregatedTimeOff )
|
||||
{
|
||||
uint8_t nbEnabledChannels = 0;
|
||||
uint8_t delayTx = 0;
|
||||
uint8_t nbRestrictedChannels = 0;
|
||||
uint8_t enabledChannels[RU864_MAX_NB_CHANNELS] = { 0 };
|
||||
TimerTime_t nextTxDelay = 0;
|
||||
RegionCommonIdentifyChannelsParam_t identifyChannelsParam;
|
||||
RegionCommonCountNbOfEnabledChannelsParams_t countChannelsParams;
|
||||
LoRaMacStatus_t status = LORAMAC_STATUS_NO_CHANNEL_FOUND;
|
||||
|
||||
if( RegionCommonCountChannels( NvmCtx.ChannelsMask, 0, 1 ) == 0 )
|
||||
{ // Reactivate default channels
|
||||
NvmCtx.ChannelsMask[0] |= LC( 1 ) + LC( 2 );
|
||||
}
|
||||
|
||||
if( nextChanParams->AggrTimeOff <= TimerGetElapsedTime( nextChanParams->LastAggrTx ) )
|
||||
{
|
||||
// Reset Aggregated time off
|
||||
*aggregatedTimeOff = 0;
|
||||
// Search how many channels are enabled
|
||||
countChannelsParams.Joined = nextChanParams->Joined;
|
||||
countChannelsParams.Datarate = nextChanParams->Datarate;
|
||||
countChannelsParams.ChannelsMask = NvmCtx.ChannelsMask;
|
||||
countChannelsParams.Channels = NvmCtx.Channels;
|
||||
countChannelsParams.Bands = NvmCtx.Bands;
|
||||
countChannelsParams.MaxNbChannels = RU864_MAX_NB_CHANNELS;
|
||||
countChannelsParams.JoinChannels = RU864_JOIN_CHANNELS;
|
||||
|
||||
// Update bands Time OFF
|
||||
nextTxDelay = RegionCommonUpdateBandTimeOff( nextChanParams->Joined, nextChanParams->DutyCycleEnabled, NvmCtx.Bands, RU864_MAX_NB_BANDS );
|
||||
identifyChannelsParam.AggrTimeOff = nextChanParams->AggrTimeOff;
|
||||
identifyChannelsParam.LastAggrTx = nextChanParams->LastAggrTx;
|
||||
identifyChannelsParam.DutyCycleEnabled = nextChanParams->DutyCycleEnabled;
|
||||
identifyChannelsParam.MaxBands = RU864_MAX_NB_BANDS;
|
||||
|
||||
// Search how many channels are enabled
|
||||
nbEnabledChannels = CountNbOfEnabledChannels( nextChanParams->Joined, nextChanParams->Datarate,
|
||||
NvmCtx.ChannelsMask, NvmCtx.Channels,
|
||||
NvmCtx.Bands, enabledChannels, &delayTx );
|
||||
}
|
||||
else
|
||||
{
|
||||
delayTx++;
|
||||
nextTxDelay = nextChanParams->AggrTimeOff - TimerGetElapsedTime( nextChanParams->LastAggrTx );
|
||||
}
|
||||
identifyChannelsParam.ElapsedTimeSinceStartUp = nextChanParams->ElapsedTimeSinceStartUp;
|
||||
identifyChannelsParam.LastTxIsJoinRequest = nextChanParams->LastTxIsJoinRequest;
|
||||
identifyChannelsParam.ExpectedTimeOnAir = GetTimeOnAir( nextChanParams->Datarate, nextChanParams->PktLen );
|
||||
|
||||
if( nbEnabledChannels > 0 )
|
||||
identifyChannelsParam.CountNbOfEnabledChannelsParam = &countChannelsParams;
|
||||
|
||||
status = RegionCommonIdentifyChannels( &identifyChannelsParam, aggregatedTimeOff, enabledChannels,
|
||||
&nbEnabledChannels, &nbRestrictedChannels, time );
|
||||
|
||||
if( status == LORAMAC_STATUS_OK )
|
||||
{
|
||||
// We found a valid channel
|
||||
*channel = enabledChannels[randr( 0, nbEnabledChannels - 1 )];
|
||||
|
||||
*time = 0;
|
||||
return LORAMAC_STATUS_OK;
|
||||
}
|
||||
else
|
||||
else if( status == LORAMAC_STATUS_NO_CHANNEL_FOUND )
|
||||
{
|
||||
if( delayTx > 0 )
|
||||
{
|
||||
// Delay transmission due to AggregatedTimeOff or to a band time off
|
||||
*time = nextTxDelay;
|
||||
return LORAMAC_STATUS_DUTYCYCLE_RESTRICTED;
|
||||
}
|
||||
// Datarate not supported by any channel, restore defaults
|
||||
NvmCtx.ChannelsMask[0] |= LC( 1 ) + LC( 2 );
|
||||
*time = 0;
|
||||
return LORAMAC_STATUS_NO_CHANNEL_FOUND;
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
LoRaMacStatus_t RegionRU864ChannelAdd( ChannelAddParams_t* channelAdd )
|
||||
|
@@ -35,6 +35,11 @@
|
||||
#ifndef __REGION_RU864_H__
|
||||
#define __REGION_RU864_H__
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
#include "LoRaMac.h"
|
||||
|
||||
/*!
|
||||
@@ -194,6 +199,11 @@
|
||||
*/
|
||||
#define RU864_BEACON_CHANNEL_FREQ 869100000
|
||||
|
||||
/*!
|
||||
* Ping slot channel frequency
|
||||
*/
|
||||
#define RU864_PING_SLOT_CHANNEL_FREQ 868900000
|
||||
|
||||
/*!
|
||||
* Payload size of a beacon frame
|
||||
*/
|
||||
@@ -219,6 +229,11 @@
|
||||
*/
|
||||
#define RU864_BEACON_CHANNEL_BW 0
|
||||
|
||||
/*!
|
||||
* Datarate of the ping slot channel
|
||||
*/
|
||||
#define RU864_PING_SLOT_CHANNEL_DR DR_3
|
||||
|
||||
/*!
|
||||
* Maximum number of bands
|
||||
*/
|
||||
@@ -226,9 +241,9 @@
|
||||
|
||||
/*!
|
||||
* Band 0 definition
|
||||
* { DutyCycle, TxMaxPower, LastJoinTxDoneTime, LastTxDoneTime, TimeOff }
|
||||
* Band = { DutyCycle, TxMaxPower, LastBandUpdateTime, TimeCredits, MaxTimeCredits, ReadyForTransmission }
|
||||
*/
|
||||
#define RU864_BAND0 { 100 , RU864_MAX_TX_POWER, 0, 0, 0 } // 1.0 %
|
||||
#define RU864_BAND0 { 100 , RU864_MAX_TX_POWER, 0, 0, 0, 0 } // 1.0 %
|
||||
|
||||
/*!
|
||||
* LoRaMac default channel 1
|
||||
@@ -259,15 +274,10 @@ static const uint8_t DataratesRU864[] = { 12, 11, 10, 9, 8, 7, 7, 50 };
|
||||
static const uint32_t BandwidthsRU864[] = { 125000, 125000, 125000, 125000, 125000, 125000, 250000, 0 };
|
||||
|
||||
/*!
|
||||
* Maximum payload with respect to the datarate index. Cannot operate with repeater.
|
||||
* Maximum payload with respect to the datarate index.
|
||||
*/
|
||||
static const uint8_t MaxPayloadOfDatarateRU864[] = { 51, 51, 51, 115, 242, 242, 242, 242 };
|
||||
|
||||
/*!
|
||||
* Maximum payload with respect to the datarate index. Can operate with repeater.
|
||||
*/
|
||||
static const uint8_t MaxPayloadOfDatarateRepeaterRU864[] = { 51, 51, 51, 115, 222, 222, 222, 222 };
|
||||
|
||||
/*!
|
||||
* \brief The function gets a value of a specific phy attribute.
|
||||
*
|
||||
@@ -423,13 +433,6 @@ uint8_t RegionRU864DlChannelReq( DlChannelReqParams_t* dlChannelReq );
|
||||
*/
|
||||
int8_t RegionRU864AlternateDr( int8_t currentDr, AlternateDrType_t type );
|
||||
|
||||
/*!
|
||||
* \brief Calculates the back-off time.
|
||||
*
|
||||
* \param [IN] calcBackOff Pointer to the function parameters.
|
||||
*/
|
||||
void RegionRU864CalcBackOff( CalcBackOffParams_t* calcBackOff );
|
||||
|
||||
/*!
|
||||
* \brief Searches and set the next random available channel
|
||||
*
|
||||
@@ -491,4 +494,8 @@ void RegionRU864RxBeaconSetup( RxBeaconSetup_t* rxBeaconSetup, uint8_t* outDr );
|
||||
|
||||
/*! \} defgroup REGIONRU864 */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // __REGION_RU864_H__
|
||||
|
@@ -254,38 +254,12 @@ static bool VerifyRfFreq( uint32_t freq )
|
||||
return true;
|
||||
}
|
||||
|
||||
static uint8_t CountNbOfEnabledChannels( uint8_t datarate, uint16_t* channelsMask, ChannelParams_t* channels, Band_t* bands, uint8_t* enabledChannels, uint8_t* delayTx )
|
||||
static TimerTime_t GetTimeOnAir( int8_t datarate, uint16_t pktLen )
|
||||
{
|
||||
uint8_t nbEnabledChannels = 0;
|
||||
uint8_t delayTransmission = 0;
|
||||
int8_t phyDr = DataratesUS915[datarate];
|
||||
uint32_t bandwidth = GetBandwidth( datarate );
|
||||
|
||||
for( uint8_t i = 0, k = 0; i < US915_MAX_NB_CHANNELS; i += 16, k++ )
|
||||
{
|
||||
for( uint8_t j = 0; j < 16; j++ )
|
||||
{
|
||||
if( ( channelsMask[k] & ( 1 << j ) ) != 0 )
|
||||
{
|
||||
if( channels[i + j].Frequency == 0 )
|
||||
{ // Check if the channel is enabled
|
||||
continue;
|
||||
}
|
||||
if( RegionCommonValueInRange( datarate, channels[i + j].DrRange.Fields.Min,
|
||||
channels[i + j].DrRange.Fields.Max ) == false )
|
||||
{ // Check if the current channel selection supports the given datarate
|
||||
continue;
|
||||
}
|
||||
if( bands[channels[i + j].Band].TimeOff > 0 )
|
||||
{ // Check if the band is available for transmission
|
||||
delayTransmission++;
|
||||
continue;
|
||||
}
|
||||
enabledChannels[nbEnabledChannels++] = i + j;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
*delayTx = delayTransmission;
|
||||
return nbEnabledChannels;
|
||||
return Radio.TimeOnAir( MODEM_LORA, bandwidth, phyDr, 1, 8, false, pktLen, true );
|
||||
}
|
||||
|
||||
PhyParam_t RegionUS915GetPhyParam( GetPhyParams_t* getPhy )
|
||||
@@ -339,11 +313,6 @@ PhyParam_t RegionUS915GetPhyParam( GetPhyParams_t* getPhy )
|
||||
phyParam.Value = MaxPayloadOfDatarateUS915[getPhy->Datarate];
|
||||
break;
|
||||
}
|
||||
case PHY_MAX_PAYLOAD_REPEATER:
|
||||
{
|
||||
phyParam.Value = MaxPayloadOfDatarateRepeaterUS915[getPhy->Datarate];
|
||||
break;
|
||||
}
|
||||
case PHY_DUTY_CYCLE:
|
||||
{
|
||||
phyParam.Value = US915_DUTY_CYCLE_ENABLED;
|
||||
@@ -427,7 +396,7 @@ PhyParam_t RegionUS915GetPhyParam( GetPhyParams_t* getPhy )
|
||||
}
|
||||
case PHY_DEF_MAX_EIRP:
|
||||
{
|
||||
phyParam.fValue = US915_DEFAULT_MAX_ERP + 2.15;
|
||||
phyParam.fValue = US915_DEFAULT_MAX_ERP + 2.15f;
|
||||
break;
|
||||
}
|
||||
case PHY_DEF_ANTENNA_GAIN:
|
||||
@@ -437,7 +406,7 @@ PhyParam_t RegionUS915GetPhyParam( GetPhyParams_t* getPhy )
|
||||
}
|
||||
case PHY_BEACON_CHANNEL_FREQ:
|
||||
{
|
||||
phyParam.Value = US915_BEACON_CHANNEL_FREQ;
|
||||
phyParam.Value = US915_BEACON_CHANNEL_FREQ + ( getPhy->Channel * US915_BEACON_CHANNEL_STEPWIDTH );
|
||||
break;
|
||||
}
|
||||
case PHY_BEACON_FORMAT:
|
||||
@@ -462,11 +431,26 @@ PhyParam_t RegionUS915GetPhyParam( GetPhyParams_t* getPhy )
|
||||
phyParam.Value = US915_BEACON_NB_CHANNELS;
|
||||
break;
|
||||
}
|
||||
case PHY_PING_SLOT_CHANNEL_FREQ:
|
||||
{
|
||||
phyParam.Value = US915_PING_SLOT_CHANNEL_FREQ + ( getPhy->Channel * US915_BEACON_CHANNEL_STEPWIDTH );
|
||||
break;
|
||||
}
|
||||
case PHY_PING_SLOT_CHANNEL_DR:
|
||||
{
|
||||
phyParam.Value = US915_PING_SLOT_CHANNEL_DR;
|
||||
break;
|
||||
}
|
||||
case PHY_SF_FROM_DR:
|
||||
{
|
||||
phyParam.Value = DataratesUS915[getPhy->Datarate];
|
||||
break;
|
||||
}
|
||||
case PHY_BW_FROM_DR:
|
||||
{
|
||||
phyParam.Value = GetBandwidth( getPhy->Datarate );
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
break;
|
||||
@@ -478,7 +462,8 @@ PhyParam_t RegionUS915GetPhyParam( GetPhyParams_t* getPhy )
|
||||
|
||||
void RegionUS915SetBandTxDone( SetBandTxDoneParams_t* txDone )
|
||||
{
|
||||
RegionCommonSetBandTxDone( txDone->Joined, &NvmCtx.Bands[NvmCtx.Channels[txDone->Channel].Band], txDone->LastTxDoneTime );
|
||||
RegionCommonSetBandTxDone( &NvmCtx.Bands[NvmCtx.Channels[txDone->Channel].Band],
|
||||
txDone->LastTxAirTime, txDone->Joined, txDone->ElapsedTimeSinceStartUp );
|
||||
}
|
||||
|
||||
void RegionUS915InitDefaults( InitDefaultsParams_t* params )
|
||||
@@ -490,7 +475,7 @@ void RegionUS915InitDefaults( InitDefaultsParams_t* params )
|
||||
|
||||
switch( params->Type )
|
||||
{
|
||||
case INIT_TYPE_INIT:
|
||||
case INIT_TYPE_BANDS:
|
||||
{
|
||||
// Initialize bands
|
||||
memcpy1( ( uint8_t* )NvmCtx.Bands, ( uint8_t* )bands, sizeof( Band_t ) * US915_MAX_NB_BANDS );
|
||||
@@ -501,6 +486,23 @@ void RegionUS915InitDefaults( InitDefaultsParams_t* params )
|
||||
// Initialize the join trials counter
|
||||
NvmCtx.JoinTrialsCounter = 0;
|
||||
|
||||
// ChannelsMask
|
||||
NvmCtx.ChannelsDefaultMask[0] = 0xFFFF;
|
||||
NvmCtx.ChannelsDefaultMask[1] = 0xFFFF;
|
||||
NvmCtx.ChannelsDefaultMask[2] = 0xFFFF;
|
||||
NvmCtx.ChannelsDefaultMask[3] = 0xFFFF;
|
||||
NvmCtx.ChannelsDefaultMask[4] = 0x00FF;
|
||||
NvmCtx.ChannelsDefaultMask[5] = 0x0000;
|
||||
|
||||
// Copy channels default mask
|
||||
RegionCommonChanMaskCopy( NvmCtx.ChannelsMask, NvmCtx.ChannelsDefaultMask, 6 );
|
||||
|
||||
// Copy into channels mask remaining
|
||||
RegionCommonChanMaskCopy( NvmCtx.ChannelsMaskRemaining, NvmCtx.ChannelsMask, 6 );
|
||||
break;
|
||||
}
|
||||
case INIT_TYPE_INIT:
|
||||
{
|
||||
// Channels
|
||||
// 125 kHz channels
|
||||
for( uint8_t i = 0; i < US915_MAX_NB_CHANNELS - 8; i++ )
|
||||
@@ -516,20 +518,6 @@ void RegionUS915InitDefaults( InitDefaultsParams_t* params )
|
||||
NvmCtx.Channels[i].DrRange.Value = ( DR_4 << 4 ) | DR_4;
|
||||
NvmCtx.Channels[i].Band = 0;
|
||||
}
|
||||
|
||||
// ChannelsMask
|
||||
NvmCtx.ChannelsDefaultMask[0] = 0xFFFF;
|
||||
NvmCtx.ChannelsDefaultMask[1] = 0xFFFF;
|
||||
NvmCtx.ChannelsDefaultMask[2] = 0xFFFF;
|
||||
NvmCtx.ChannelsDefaultMask[3] = 0xFFFF;
|
||||
NvmCtx.ChannelsDefaultMask[4] = 0x00FF;
|
||||
NvmCtx.ChannelsDefaultMask[5] = 0x0000;
|
||||
|
||||
// Copy channels default mask
|
||||
RegionCommonChanMaskCopy( NvmCtx.ChannelsMask, NvmCtx.ChannelsDefaultMask, 6 );
|
||||
|
||||
// Copy into channels mask remaining
|
||||
RegionCommonChanMaskCopy( NvmCtx.ChannelsMaskRemaining, NvmCtx.ChannelsMask, 6 );
|
||||
break;
|
||||
}
|
||||
case INIT_TYPE_RESTORE_CTX:
|
||||
@@ -568,6 +556,10 @@ bool RegionUS915Verify( VerifyParams_t* verify, PhyAttribute_t phyAttribute )
|
||||
{
|
||||
switch( phyAttribute )
|
||||
{
|
||||
case PHY_FREQUENCY:
|
||||
{
|
||||
return VerifyRfFreq( verify->Frequency );
|
||||
}
|
||||
case PHY_TX_DR:
|
||||
{
|
||||
return RegionCommonValueInRange( verify->DatarateParams.Datarate, US915_TX_MIN_DATARATE, US915_TX_MAX_DATARATE );
|
||||
@@ -676,7 +668,6 @@ void RegionUS915ComputeRxWindowParameters( int8_t datarate, uint8_t minRxSymbols
|
||||
bool RegionUS915RxConfig( RxConfigParams_t* rxConfig, int8_t* datarate )
|
||||
{
|
||||
int8_t dr = rxConfig->Datarate;
|
||||
uint8_t maxPayload = 0;
|
||||
int8_t phyDr = 0;
|
||||
uint32_t frequency = rxConfig->Frequency;
|
||||
|
||||
@@ -699,15 +690,7 @@ bool RegionUS915RxConfig( RxConfigParams_t* rxConfig, int8_t* datarate )
|
||||
// Radio configuration
|
||||
Radio.SetRxConfig( MODEM_LORA, rxConfig->Bandwidth, phyDr, 1, 0, 8, rxConfig->WindowTimeout, false, 0, false, 0, 0, true, rxConfig->RxContinuous );
|
||||
|
||||
if( rxConfig->RepeaterSupport == true )
|
||||
{
|
||||
maxPayload = MaxPayloadOfDatarateRepeaterUS915[dr];
|
||||
}
|
||||
else
|
||||
{
|
||||
maxPayload = MaxPayloadOfDatarateUS915[dr];
|
||||
}
|
||||
Radio.SetMaxPayloadLength( MODEM_LORA, maxPayload + LORA_MAC_FRMPAYLOAD_OVERHEAD );
|
||||
Radio.SetMaxPayloadLength( MODEM_LORA, MaxPayloadOfDatarateUS915[dr] + LORAMAC_FRAME_PAYLOAD_OVERHEAD_SIZE );
|
||||
|
||||
*datarate = (uint8_t) dr;
|
||||
return true;
|
||||
@@ -726,14 +709,15 @@ bool RegionUS915TxConfig( TxConfigParams_t* txConfig, int8_t* txPower, TimerTime
|
||||
// Setup the radio frequency
|
||||
Radio.SetChannel( NvmCtx.Channels[txConfig->Channel].Frequency );
|
||||
|
||||
Radio.SetTxConfig( MODEM_LORA, phyTxPower, 0, bandwidth, phyDr, 1, 8, false, true, 0, 0, false, 3000 );
|
||||
Radio.SetTxConfig( MODEM_LORA, phyTxPower, 0, bandwidth, phyDr, 1, 8, false, true, 0, 0, false, 4000 );
|
||||
|
||||
// Setup maximum payload lenght of the radio driver
|
||||
Radio.SetMaxPayloadLength( MODEM_LORA, txConfig->PktLen );
|
||||
// Get the time-on-air of the next tx frame
|
||||
*txTimeOnAir = Radio.TimeOnAir( MODEM_LORA, txConfig->PktLen );
|
||||
*txPower = txPowerLimited;
|
||||
|
||||
// Update time-on-air
|
||||
*txTimeOnAir = GetTimeOnAir( txConfig->Datarate, txConfig->PktLen );
|
||||
|
||||
*txPower = txPowerLimited;
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -969,29 +953,15 @@ int8_t RegionUS915AlternateDr( int8_t currentDr, AlternateDrType_t type )
|
||||
return currentDr;
|
||||
}
|
||||
|
||||
void RegionUS915CalcBackOff( CalcBackOffParams_t* calcBackOff )
|
||||
{
|
||||
RegionCommonCalcBackOffParams_t calcBackOffParams;
|
||||
|
||||
calcBackOffParams.Channels = NvmCtx.Channels;
|
||||
calcBackOffParams.Bands = NvmCtx.Bands;
|
||||
calcBackOffParams.LastTxIsJoinRequest = calcBackOff->LastTxIsJoinRequest;
|
||||
calcBackOffParams.Joined = calcBackOff->Joined;
|
||||
calcBackOffParams.DutyCycleEnabled = calcBackOff->DutyCycleEnabled;
|
||||
calcBackOffParams.Channel = calcBackOff->Channel;
|
||||
calcBackOffParams.ElapsedTime = calcBackOff->ElapsedTime;
|
||||
calcBackOffParams.TxTimeOnAir = calcBackOff->TxTimeOnAir;
|
||||
|
||||
RegionCommonCalcBackOff( &calcBackOffParams );
|
||||
}
|
||||
|
||||
LoRaMacStatus_t RegionUS915NextChannel( NextChanParams_t* nextChanParams, uint8_t* channel, TimerTime_t* time, TimerTime_t* aggregatedTimeOff )
|
||||
{
|
||||
uint8_t nbEnabledChannels = 0;
|
||||
uint8_t delayTx = 0;
|
||||
uint8_t nbRestrictedChannels = 0;
|
||||
uint8_t enabledChannels[US915_MAX_NB_CHANNELS] = { 0 };
|
||||
TimerTime_t nextTxDelay = 0;
|
||||
uint8_t newChannelIndex;
|
||||
uint8_t newChannelIndex = 0;
|
||||
RegionCommonIdentifyChannelsParam_t identifyChannelsParam;
|
||||
RegionCommonCountNbOfEnabledChannelsParams_t countChannelsParams;
|
||||
LoRaMacStatus_t status = LORAMAC_STATUS_NO_CHANNEL_FOUND;
|
||||
|
||||
// Count 125kHz channels
|
||||
if( RegionCommonCountChannels( NvmCtx.ChannelsMaskRemaining, 0, 4 ) == 0 )
|
||||
@@ -1009,26 +979,30 @@ LoRaMacStatus_t RegionUS915NextChannel( NextChanParams_t* nextChanParams, uint8_
|
||||
}
|
||||
}
|
||||
|
||||
if( nextChanParams->AggrTimeOff <= TimerGetElapsedTime( nextChanParams->LastAggrTx ) )
|
||||
{
|
||||
// Reset Aggregated time off
|
||||
*aggregatedTimeOff = 0;
|
||||
// Search how many channels are enabled
|
||||
countChannelsParams.Joined = nextChanParams->Joined;
|
||||
countChannelsParams.Datarate = nextChanParams->Datarate;
|
||||
countChannelsParams.ChannelsMask = NvmCtx.ChannelsMaskRemaining;
|
||||
countChannelsParams.Channels = NvmCtx.Channels;
|
||||
countChannelsParams.Bands = NvmCtx.Bands;
|
||||
countChannelsParams.MaxNbChannels = US915_MAX_NB_CHANNELS;
|
||||
countChannelsParams.JoinChannels = 0;
|
||||
|
||||
// Update bands Time OFF
|
||||
nextTxDelay = RegionCommonUpdateBandTimeOff( nextChanParams->Joined, nextChanParams->DutyCycleEnabled, NvmCtx.Bands, US915_MAX_NB_BANDS );
|
||||
identifyChannelsParam.AggrTimeOff = nextChanParams->AggrTimeOff;
|
||||
identifyChannelsParam.LastAggrTx = nextChanParams->LastAggrTx;
|
||||
identifyChannelsParam.DutyCycleEnabled = nextChanParams->DutyCycleEnabled;
|
||||
identifyChannelsParam.MaxBands = US915_MAX_NB_BANDS;
|
||||
|
||||
// Search how many channels are enabled
|
||||
nbEnabledChannels = CountNbOfEnabledChannels( nextChanParams->Datarate,
|
||||
NvmCtx.ChannelsMaskRemaining, NvmCtx.Channels,
|
||||
NvmCtx.Bands, enabledChannels, &delayTx );
|
||||
}
|
||||
else
|
||||
{
|
||||
delayTx++;
|
||||
nextTxDelay = nextChanParams->AggrTimeOff - TimerGetElapsedTime( nextChanParams->LastAggrTx );
|
||||
}
|
||||
identifyChannelsParam.CountNbOfEnabledChannelsParam = &countChannelsParams;
|
||||
|
||||
if( nbEnabledChannels > 0 )
|
||||
identifyChannelsParam.ElapsedTimeSinceStartUp = nextChanParams->ElapsedTimeSinceStartUp;
|
||||
identifyChannelsParam.LastTxIsJoinRequest = nextChanParams->LastTxIsJoinRequest;
|
||||
identifyChannelsParam.ExpectedTimeOnAir = GetTimeOnAir( nextChanParams->Datarate, nextChanParams->PktLen );
|
||||
|
||||
status = RegionCommonIdentifyChannels( &identifyChannelsParam, aggregatedTimeOff, enabledChannels,
|
||||
&nbEnabledChannels, &nbRestrictedChannels, time );
|
||||
|
||||
if( status == LORAMAC_STATUS_OK )
|
||||
{
|
||||
if( nextChanParams->Joined == true )
|
||||
{
|
||||
@@ -1066,22 +1040,8 @@ LoRaMacStatus_t RegionUS915NextChannel( NextChanParams_t* nextChanParams, uint8_
|
||||
|
||||
// Disable the channel in the mask
|
||||
RegionCommonChanDisable( NvmCtx.ChannelsMaskRemaining, *channel, US915_MAX_NB_CHANNELS );
|
||||
|
||||
*time = 0;
|
||||
return LORAMAC_STATUS_OK;
|
||||
}
|
||||
else
|
||||
{
|
||||
if( delayTx > 0 )
|
||||
{
|
||||
// Delay transmission due to AggregatedTimeOff or to a band time off
|
||||
*time = nextTxDelay;
|
||||
return LORAMAC_STATUS_DUTYCYCLE_RESTRICTED;
|
||||
}
|
||||
// Datarate not supported by any channel
|
||||
*time = 0;
|
||||
return LORAMAC_STATUS_NO_CHANNEL_FOUND;
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
LoRaMacStatus_t RegionUS915ChannelAdd( ChannelAddParams_t* channelAdd )
|
||||
|
@@ -37,6 +37,11 @@
|
||||
#ifndef __REGION_US915_H__
|
||||
#define __REGION_US915_H__
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
#include "region/Region.h"
|
||||
|
||||
/*!
|
||||
@@ -87,7 +92,7 @@
|
||||
/*!
|
||||
* Minimal Tx output power that can be used by the node
|
||||
*/
|
||||
#define US915_MIN_TX_POWER TX_POWER_10
|
||||
#define US915_MIN_TX_POWER TX_POWER_14
|
||||
|
||||
/*!
|
||||
* Maximal Tx output power that can be used by the node
|
||||
@@ -182,6 +187,11 @@
|
||||
*/
|
||||
#define US915_BEACON_CHANNEL_STEPWIDTH 600000
|
||||
|
||||
/*!
|
||||
* Ping slot channel frequency
|
||||
*/
|
||||
#define US915_PING_SLOT_CHANNEL_FREQ 923300000
|
||||
|
||||
/*!
|
||||
* Number of possible beacon channels
|
||||
*/
|
||||
@@ -224,9 +234,9 @@
|
||||
|
||||
/*!
|
||||
* Band 0 definition
|
||||
* { DutyCycle, TxMaxPower, LastJoinTxDoneTime, LastTxDoneTime, TimeOff }
|
||||
* Band = { DutyCycle, TxMaxPower, LastBandUpdateTime, TimeCredits, MaxTimeCredits, ReadyForTransmission }
|
||||
*/
|
||||
#define US915_BAND0 { 1, US915_MAX_TX_POWER, 0, 0, 0 } // 100.0 %
|
||||
#define US915_BAND0 { 1, US915_MAX_TX_POWER, 0, 0, 0, 0 } // 100.0 %
|
||||
|
||||
/*!
|
||||
* Defines the first channel for RX window 1 for US band
|
||||
@@ -266,15 +276,10 @@ static const int8_t DatarateOffsetsUS915[5][4] =
|
||||
};
|
||||
|
||||
/*!
|
||||
* Maximum payload with respect to the datarate index. Cannot operate with repeater.
|
||||
* Maximum payload with respect to the datarate index.
|
||||
*/
|
||||
static const uint8_t MaxPayloadOfDatarateUS915[] = { 11, 53, 125, 242, 242, 0, 0, 0, 53, 129, 242, 242, 242, 242, 0, 0 };
|
||||
|
||||
/*!
|
||||
* Maximum payload with respect to the datarate index. Can operate with repeater.
|
||||
*/
|
||||
static const uint8_t MaxPayloadOfDatarateRepeaterUS915[] = { 11, 53, 125, 242, 242, 0, 0, 0, 33, 109, 222, 222, 222, 222, 0, 0 };
|
||||
|
||||
/*!
|
||||
* \brief The function gets a value of a specific phy attribute.
|
||||
*
|
||||
@@ -432,13 +437,6 @@ uint8_t RegionUS915DlChannelReq( DlChannelReqParams_t* dlChannelReq );
|
||||
*/
|
||||
int8_t RegionUS915AlternateDr( int8_t currentDr, AlternateDrType_t type );
|
||||
|
||||
/*!
|
||||
* \brief Calculates the back-off time.
|
||||
*
|
||||
* \param [IN] calcBackOff Pointer to the function parameters.
|
||||
*/
|
||||
void RegionUS915CalcBackOff( CalcBackOffParams_t* calcBackOff );
|
||||
|
||||
/*!
|
||||
* \brief Searches and set the next random available channel
|
||||
*
|
||||
@@ -496,8 +494,12 @@ uint8_t RegionUS915ApplyDrOffset( uint8_t downlinkDwellTime, int8_t dr, int8_t d
|
||||
*
|
||||
* \param [IN] rxBeaconSetup Pointer to the function parameters
|
||||
*/
|
||||
void RegionUS915RxBeaconSetup( RxBeaconSetup_t* rxBeaconSetup, uint8_t* outDr );
|
||||
void RegionUS915RxBeaconSetup( RxBeaconSetup_t* rxBeaconSetup, uint8_t* outDr );
|
||||
|
||||
/*! \} defgroup REGIONUS915 */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // __REGION_US915_H__
|
||||
|
@@ -30,13 +30,37 @@
|
||||
*
|
||||
* \author Johannes Bruder ( STACKFORCE )
|
||||
*
|
||||
* \defgroup SECUREELEMENT Secure Element API Definition
|
||||
*
|
||||
* \{
|
||||
*
|
||||
*/
|
||||
#ifndef __SECURE_ELEMENT_H__
|
||||
#define __SECURE_ELEMENT_H__
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
#include <stdint.h>
|
||||
#include "LoRaMacCrypto.h"
|
||||
|
||||
/*!
|
||||
* Secure-element keys size in bytes
|
||||
*/
|
||||
#define SE_KEY_SIZE 16
|
||||
|
||||
/*!
|
||||
* Secure-element EUI size in bytes
|
||||
*/
|
||||
#define SE_EUI_SIZE 8
|
||||
|
||||
/*!
|
||||
* Secure-element pin size in bytes
|
||||
*/
|
||||
#define SE_PIN_SIZE 4
|
||||
|
||||
/*!
|
||||
* Return values.
|
||||
*/
|
||||
@@ -70,6 +94,10 @@ typedef enum eSecureElementStatus
|
||||
* Undefined Error occurred
|
||||
*/
|
||||
SECURE_ELEMENT_ERROR,
|
||||
/*!
|
||||
* Failed to encrypt
|
||||
*/
|
||||
SECURE_ELEMENT_FAIL_ENCRYPT,
|
||||
}SecureElementStatus_t;
|
||||
|
||||
/*!
|
||||
@@ -77,7 +105,7 @@ typedef enum eSecureElementStatus
|
||||
* non volatile context have to be stored.
|
||||
*
|
||||
*/
|
||||
typedef void ( *EventNvmCtxChanged )( void );
|
||||
typedef void ( *SecureElementNvmEvent )( void );
|
||||
|
||||
/*!
|
||||
* Initialization of Secure Element driver
|
||||
@@ -86,7 +114,7 @@ typedef void ( *EventNvmCtxChanged )( void );
|
||||
* non-volatile context have to be stored.
|
||||
* \retval - Status of the operation
|
||||
*/
|
||||
SecureElementStatus_t SecureElementInit( EventNvmCtxChanged seNvmCtxChanged );
|
||||
SecureElementStatus_t SecureElementInit( SecureElementNvmEvent seNvmCtxChanged );
|
||||
|
||||
/*!
|
||||
* Restores the internal nvm context from passed pointer.
|
||||
@@ -114,15 +142,16 @@ void* SecureElementGetNvmCtx( size_t* seNvmCtxSize );
|
||||
SecureElementStatus_t SecureElementSetKey( KeyIdentifier_t keyID, uint8_t* key );
|
||||
|
||||
/*!
|
||||
* Computes a CMAC
|
||||
* Computes a CMAC of a message using provided initial Bx block
|
||||
*
|
||||
* \param[IN] micBxBuffer - Buffer containing the initial Bx block
|
||||
* \param[IN] buffer - Data buffer
|
||||
* \param[IN] size - Data buffer size
|
||||
* \param[IN] keyID - Key identifier to determine the AES key to be used
|
||||
* \param[OUT] cmac - Computed cmac
|
||||
* \retval - Status of the operation
|
||||
*/
|
||||
SecureElementStatus_t SecureElementComputeAesCmac( uint8_t* buffer, uint16_t size, KeyIdentifier_t keyID, uint32_t* cmac );
|
||||
SecureElementStatus_t SecureElementComputeAesCmac( uint8_t* micBxBuffer, uint8_t* buffer, uint16_t size, KeyIdentifier_t keyID, uint32_t* cmac );
|
||||
|
||||
/*!
|
||||
* Verifies a CMAC (computes and compare with expected cmac)
|
||||
@@ -157,6 +186,22 @@ SecureElementStatus_t SecureElementAesEncrypt( uint8_t* buffer, uint16_t size, K
|
||||
*/
|
||||
SecureElementStatus_t SecureElementDeriveAndStoreKey( Version_t version, uint8_t* input, KeyIdentifier_t rootKeyID, KeyIdentifier_t targetKeyID );
|
||||
|
||||
/*!
|
||||
* Process JoinAccept message.
|
||||
*
|
||||
* \param[IN] encJoinAccept - Received encrypted JoinAccept message
|
||||
* \param[IN] encJoinAcceptSize - Received encrypted JoinAccept message Size
|
||||
* \param[OUT] decJoinAccept - Decrypted and validated JoinAccept message
|
||||
* \param[OUT] versionMinor - Detected LoRaWAN specification version minor field.
|
||||
* - 0 -> LoRaWAN 1.0.x
|
||||
* - 1 -> LoRaWAN 1.1.x
|
||||
* \retval - Status of the operation
|
||||
*/
|
||||
SecureElementStatus_t SecureElementProcessJoinAccept( JoinReqIdentifier_t joinReqType, uint8_t* joinEui,
|
||||
uint16_t devNonce, uint8_t* encJoinAccept,
|
||||
uint8_t encJoinAcceptSize, uint8_t* decJoinAccept,
|
||||
uint8_t* versionMinor );
|
||||
|
||||
/*!
|
||||
* Generates a random number
|
||||
*
|
||||
@@ -165,4 +210,55 @@ SecureElementStatus_t SecureElementDeriveAndStoreKey( Version_t version, uint8_t
|
||||
*/
|
||||
SecureElementStatus_t SecureElementRandomNumber( uint32_t* randomNum );
|
||||
|
||||
/*!
|
||||
* Sets the DevEUI
|
||||
*
|
||||
* \param[IN] devEui - Pointer to the 8-byte devEUI
|
||||
* \retval - Status of the operation
|
||||
*/
|
||||
SecureElementStatus_t SecureElementSetDevEui( uint8_t* devEui );
|
||||
|
||||
/*!
|
||||
* Gets the DevEUI
|
||||
*
|
||||
* \retval - Pointer to the 8-byte devEUI
|
||||
*/
|
||||
uint8_t* SecureElementGetDevEui( void );
|
||||
|
||||
/*!
|
||||
* Sets the JoinEUI
|
||||
*
|
||||
* \param[IN] joinEui - Pointer to the 8-byte joinEui
|
||||
* \retval - Status of the operation
|
||||
*/
|
||||
SecureElementStatus_t SecureElementSetJoinEui( uint8_t* joinEui );
|
||||
|
||||
/*!
|
||||
* Gets the DevEUI
|
||||
*
|
||||
* \retval - Pointer to the 8-byte joinEui
|
||||
*/
|
||||
uint8_t* SecureElementGetJoinEui( void );
|
||||
|
||||
/*!
|
||||
* Sets the pin
|
||||
*
|
||||
* \param[IN] pin - Pointer to the 4-byte pin
|
||||
* \retval - Status of the operation
|
||||
*/
|
||||
SecureElementStatus_t SecureElementSetPin( uint8_t* pin );
|
||||
|
||||
/*!
|
||||
* Gets the Pin
|
||||
*
|
||||
* \retval - Pointer to the 4-byte pin
|
||||
*/
|
||||
uint8_t* SecureElementGetPin( void );
|
||||
|
||||
/*! \} defgroup SECUREELEMENT */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // __SECURE_ELEMENT_H__
|
||||
|
@@ -22,17 +22,62 @@ cmake_minimum_required(VERSION 3.6)
|
||||
# Target
|
||||
#---------------------------------------------------------------------------------------
|
||||
|
||||
file(GLOB ${PROJECT_NAME}_SOURCES "*.c"
|
||||
"soft-se/*.c")
|
||||
if(${SECURE_ELEMENT} MATCHES SOFT_SE)
|
||||
file(GLOB ${PROJECT_NAME}_SOURCES "*.c" "soft-se/*.c")
|
||||
else()
|
||||
if(${SECURE_ELEMENT} MATCHES LR1110_SE)
|
||||
if (${RADIO} MATCHES lr1110)
|
||||
file(GLOB ${PROJECT_NAME}_SOURCES "*.c" "lr1110-se/*.c")
|
||||
else()
|
||||
message(FATAL_ERROR "LR1110_SE secure elemeent can only be used when LR1110 radio is selected.")
|
||||
endif()
|
||||
elseif((${SECURE_ELEMENT} MATCHES ATECC608A_TNGLORA_SE))
|
||||
file(GLOB ${PROJECT_NAME}_SOURCES "*.c"
|
||||
"atecc608a-tnglora-se/*.c"
|
||||
"atecc608a-tnglora-se/cryptoauthlib/lib/*.c"
|
||||
"atecc608a-tnglora-se/cryptoauthlib/lib/basic/*.c"
|
||||
"atecc608a-tnglora-se/cryptoauthlib/lib/crypto/*.c"
|
||||
"atecc608a-tnglora-se/cryptoauthlib/lib/crypto/hashes/*.c"
|
||||
"atecc608a-tnglora-se/cryptoauthlib/lib/hal/atca_hal.c"
|
||||
"atecc608a-tnglora-se/cryptoauthlib/lib/host/*.c"
|
||||
)
|
||||
else()
|
||||
message(FATAL_ERROR "No secure-element selected.")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
add_library(${PROJECT_NAME} OBJECT EXCLUDE_FROM_ALL ${${PROJECT_NAME}_SOURCES})
|
||||
|
||||
if(${SECURE_ELEMENT_PRE_PROVISIONED} MATCHES ON)
|
||||
target_compile_definitions(${PROJECT_NAME} PRIVATE -DSECURE_ELEMENT_PRE_PROVISIONED)
|
||||
endif()
|
||||
|
||||
if(${SECURE_ELEMENT} MATCHES SOFT_SE)
|
||||
target_include_directories( ${PROJECT_NAME} PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/soft-se)
|
||||
else()
|
||||
if(${SECURE_ELEMENT} MATCHES LR1110_SE)
|
||||
if(${RADIO} MATCHES lr1110)
|
||||
target_include_directories( ${PROJECT_NAME} PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/lr1110-se)
|
||||
endif()
|
||||
elseif((${SECURE_ELEMENT} MATCHES ATECC608A_TNGLORA_SE))
|
||||
target_include_directories( ${PROJECT_NAME} PUBLIC
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/atecc608a-tnglora-se
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/atecc608a-tnglora-se/cryptoauthlib/lib
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/atecc608a-tnglora-se/cryptoauthlib/lib/basic
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/atecc608a-tnglora-se/cryptoauthlib/lib/crypto
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/atecc608a-tnglora-se/cryptoauthlib/lib/crypto/hashes
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/atecc608a-tnglora-se/cryptoauthlib/lib/hal
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/atecc608a-tnglora-se/cryptoauthlib/lib/host
|
||||
)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
target_include_directories( ${PROJECT_NAME} PUBLIC
|
||||
${CMAKE_CURRENT_SOURCE_DIR}
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/soft-se
|
||||
$<TARGET_PROPERTY:board,INTERFACE_INCLUDE_DIRECTORIES>
|
||||
$<TARGET_PROPERTY:system,INTERFACE_INCLUDE_DIRECTORIES>
|
||||
$<TARGET_PROPERTY:mac,INTERFACE_INCLUDE_DIRECTORIES>
|
||||
$<TARGET_PROPERTY:radio,INTERFACE_INCLUDE_DIRECTORIES>
|
||||
)
|
||||
|
||||
set_property(TARGET ${PROJECT_NAME} PROPERTY C_STANDARD 11)
|
||||
|
@@ -0,0 +1,27 @@
|
||||
/* Cryptoauthlib Configuration File */
|
||||
#ifndef ATCA_CONFIG_H
|
||||
#define ATCA_CONFIG_H
|
||||
|
||||
/* Include HALS */
|
||||
#define ATCA_HAL_I2C
|
||||
|
||||
/* Included device support */
|
||||
#define ATCA_ATECC608A_SUPPORT
|
||||
|
||||
/* ATECC608A I2C bus configuration */
|
||||
#define ATCA_HAL_ATECC608A_I2C_FREQUENCY 100000U
|
||||
#define ATCA_HAL_ATECC608A_I2C_BUS_PINS 2U
|
||||
#define ATCA_HAL_ATECC608A_I2C_ADDRESS 0x59U
|
||||
#define ATCA_HAL_ATECC608A_I2C_RX_RETRIES 20
|
||||
#define ATCA_HAL_ATECC608A_I2C_WAKEUP_DELAY 1500U
|
||||
|
||||
/* \brief How long to wait after an initial wake failure for the POST to
|
||||
* complete.
|
||||
* If Power-on self test (POST) is enabled, the self test will run on waking
|
||||
* from sleep or during power-on, which delays the wake reply.
|
||||
*/
|
||||
#ifndef ATCA_POST_DELAY_MSEC
|
||||
#define ATCA_POST_DELAY_MSEC 25
|
||||
#endif
|
||||
|
||||
#endif
|
@@ -0,0 +1,299 @@
|
||||
/**
|
||||
* @file atecc608a-tnglora-se-hal.c
|
||||
*
|
||||
* @brief Secure Element hardware abstraction layer implementation
|
||||
*
|
||||
* @remark Current implementation only supports LoRaWAN 1.0.x version
|
||||
*
|
||||
* @copyright Copyright (c) 2020 The Things Industries B.V.
|
||||
*
|
||||
* Revised BSD License
|
||||
* Copyright The Things Industries B.V 2020. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* * Neither the name of the Things Industries B.V nor the
|
||||
* names of its contributors may be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE THINGS INDUSTRIES B.V BE LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include "atca_hal.h"
|
||||
#include "atca_device.h"
|
||||
#include "atca_execution.h"
|
||||
#include "atca_status.h"
|
||||
#include "i2c-board.h"
|
||||
#include "delay.h"
|
||||
|
||||
#include "radio.h"
|
||||
|
||||
#include "atecc608a-tnglora-se-hal.h"
|
||||
|
||||
uint32_t ATECC608ASeHalGetRandomNumber( void )
|
||||
{
|
||||
return Radio.Random( );
|
||||
}
|
||||
|
||||
/** @brief This function delays for a number of microseconds.
|
||||
*
|
||||
* @param[in] delay number of 0.001 milliseconds to delay
|
||||
*/
|
||||
void atca_delay_us(uint32_t delay)
|
||||
{
|
||||
// use ASF supplied delay
|
||||
DelayMs(delay / 1000);
|
||||
}
|
||||
|
||||
/** @brief This function delays for a number of tens of microseconds.
|
||||
*
|
||||
* @param[in] delay number of 0.01 milliseconds to delay
|
||||
*/
|
||||
void atca_delay_10us(uint32_t delay)
|
||||
{
|
||||
// use ASF supplied delay
|
||||
DelayMs(delay / 100);
|
||||
}
|
||||
|
||||
/** @brief This function delays for a number of milliseconds.
|
||||
*
|
||||
* You can override this function if you like to do
|
||||
* something else in your system while delaying.
|
||||
* @param[in] delay number of milliseconds to delay
|
||||
*/
|
||||
void atca_delay_ms(uint32_t delay)
|
||||
{
|
||||
// use ASF supplied delay
|
||||
DelayMs(delay);
|
||||
}
|
||||
|
||||
/** @brief discover i2c buses available for this hardware
|
||||
* this maintains a list of logical to physical bus mappings freeing the application
|
||||
* of the a-priori knowledge
|
||||
* @param[in] i2c_buses - an array of logical bus numbers
|
||||
* @param[in] max_buses - maximum number of buses the app wants to attempt to discover
|
||||
* @return ATCA_SUCCESS
|
||||
*/
|
||||
|
||||
ATCA_STATUS hal_i2c_discover_buses(int i2c_buses[], int max_buses)
|
||||
{
|
||||
return ATCA_SUCCESS;
|
||||
}
|
||||
|
||||
/** @brief discover any CryptoAuth devices on a given logical bus number
|
||||
* @param[in] bus_num logical bus number on which to look for CryptoAuth devices
|
||||
* @param[out] cfg pointer to head of an array of interface config structures which get filled in by this method
|
||||
* @param[out] found number of devices found on this bus
|
||||
* @return ATCA_SUCCESS
|
||||
*/
|
||||
|
||||
ATCA_STATUS hal_i2c_discover_devices(int bus_num, ATCAIfaceCfg cfg[], int *found)
|
||||
{
|
||||
return ATCA_SUCCESS;
|
||||
}
|
||||
|
||||
/** @brief
|
||||
- this HAL implementation assumes you've included the ASF SERCOM I2C libraries in your project, otherwise,
|
||||
the HAL layer will not compile because the ASF I2C drivers are a dependency *
|
||||
*/
|
||||
|
||||
/** @brief hal_i2c_init manages requests to initialize a physical interface. it manages use counts so when an interface
|
||||
* has released the physical layer, it will disable the interface for some other use.
|
||||
* You can have multiple ATCAIFace instances using the same bus, and you can have multiple ATCAIFace instances on
|
||||
* multiple i2c buses, so hal_i2c_init manages these things and ATCAIFace is abstracted from the physical details.
|
||||
*/
|
||||
|
||||
/** @brief initialize an I2C interface using given config
|
||||
* @param[in] hal - opaque ptr to HAL data
|
||||
* @param[in] cfg - interface configuration
|
||||
* @return ATCA_SUCCESS on success, otherwise an error code.
|
||||
*/
|
||||
ATCA_STATUS hal_i2c_init(void *hal, ATCAIfaceCfg *cfg)
|
||||
{
|
||||
return ATCA_SUCCESS;
|
||||
}
|
||||
|
||||
/** @brief HAL implementation of I2C post init
|
||||
* @param[in] iface instance
|
||||
* @return ATCA_SUCCESS
|
||||
*/
|
||||
ATCA_STATUS hal_i2c_post_init(ATCAIface iface)
|
||||
{
|
||||
return ATCA_SUCCESS;
|
||||
}
|
||||
|
||||
/** @brief HAL implementation of I2C send over ASF
|
||||
* @param[in] iface instance
|
||||
* @param[in] txdata pointer to space to bytes to send
|
||||
* @param[in] txlength number of bytes to send
|
||||
* @return ATCA_SUCCESS on success, otherwise an error code.
|
||||
*/
|
||||
|
||||
ATCA_STATUS hal_i2c_send(ATCAIface iface, uint8_t *txdata, int txlength)
|
||||
{
|
||||
|
||||
txdata[0] = 0x3;
|
||||
txlength++;
|
||||
if (I2cMcuWriteBuffer((I2c_t *)NULL, iface->mIfaceCFG->atcai2c.slave_address, 0, txdata, (size_t)txlength) == 1)
|
||||
{
|
||||
return ATCA_SUCCESS;
|
||||
}
|
||||
else
|
||||
{
|
||||
return ATCA_TX_FAIL;
|
||||
}
|
||||
}
|
||||
|
||||
/** @brief HAL implementation of I2C receive function for ASF I2C
|
||||
* @param[in] iface Device to interact with.
|
||||
* @param[out] rxdata Data received will be returned here.
|
||||
* @param[inout] rxlength As input, the size of the rxdata buffer.
|
||||
* As output, the number of bytes received.
|
||||
* @return ATCA_SUCCESS on success, otherwise an error code.
|
||||
*/
|
||||
ATCA_STATUS hal_i2c_receive(ATCAIface iface, uint8_t *rxdata, uint16_t *rxlength)
|
||||
{
|
||||
// read procedure is:
|
||||
// 1. read 1 byte, this will be the length of the package
|
||||
// 2. read the rest of the package
|
||||
|
||||
uint8_t lengthPackage[1] = {0};
|
||||
int r = -1;
|
||||
int retries = iface->mIfaceCFG->rx_retries;
|
||||
while (--retries > 0 && r != 1)
|
||||
{
|
||||
r = I2cMcuReadBuffer((I2c_t *)NULL, iface->mIfaceCFG->atcai2c.slave_address, 0, lengthPackage, 1);
|
||||
}
|
||||
|
||||
if (r != 1)
|
||||
{
|
||||
return ATCA_RX_TIMEOUT;
|
||||
}
|
||||
|
||||
uint8_t bytesToRead = lengthPackage[0] - 1;
|
||||
|
||||
if (bytesToRead > *rxlength)
|
||||
{
|
||||
printf("hal_i2c_receive buffer too small, requested %u, but have %u", bytesToRead, *rxlength);
|
||||
return ATCA_SMALL_BUFFER;
|
||||
}
|
||||
|
||||
memset(rxdata, 0, *rxlength);
|
||||
rxdata[0] = lengthPackage[0];
|
||||
|
||||
r = -1;
|
||||
retries = iface->mIfaceCFG->rx_retries;
|
||||
while (--retries > 0 && r != 1)
|
||||
{
|
||||
r = I2cMcuReadBuffer((I2c_t *)NULL, iface->mIfaceCFG->atcai2c.slave_address, 0, rxdata + 1, bytesToRead);
|
||||
}
|
||||
|
||||
if (r != 1)
|
||||
{
|
||||
return ATCA_RX_TIMEOUT;
|
||||
}
|
||||
|
||||
*rxlength = lengthPackage[0];
|
||||
|
||||
return ATCA_SUCCESS;
|
||||
}
|
||||
|
||||
/** @brief method to change the bus speec of I2C
|
||||
* @param[in] iface interface on which to change bus speed
|
||||
* @param[in] speed baud rate (typically 100000 or 400000)
|
||||
*/
|
||||
|
||||
void change_i2c_speed(ATCAIface iface, uint32_t speed)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
/** @brief wake up CryptoAuth device using I2C bus
|
||||
* @param[in] iface interface to logical device to wakeup
|
||||
* @return ATCA_SUCCESS on success, otherwise an error code.
|
||||
*/
|
||||
|
||||
ATCA_STATUS hal_i2c_wake(ATCAIface iface)
|
||||
{
|
||||
// 2. Send NULL buffer to address 0x0 (NACK)
|
||||
uint8_t emptybuff[1] = {0};
|
||||
int r = I2cMcuWriteBuffer((I2c_t *)NULL, 0x00, 0, emptybuff, (size_t)0);
|
||||
|
||||
// 3. Wait for wake_delay
|
||||
atca_delay_us(iface->mIfaceCFG->wake_delay);
|
||||
|
||||
uint8_t rx_buffer[4] = {0};
|
||||
|
||||
// 4. Read from normal slave_address
|
||||
r = -1;
|
||||
int retries = iface->mIfaceCFG->rx_retries;
|
||||
while (--retries > 0 && r != 1)
|
||||
{
|
||||
r = I2cMcuReadBuffer((I2c_t *)NULL, iface->mIfaceCFG->atcai2c.slave_address, 0, rx_buffer, 4);
|
||||
}
|
||||
|
||||
// 5. Set frequency back to requested one
|
||||
const uint8_t expected_response[4] = {0x04, 0x11, 0x33, 0x43};
|
||||
uint8_t selftest_fail_resp[4] = {0x04, 0x07, 0xC4, 0x40};
|
||||
|
||||
if (memcmp(rx_buffer, expected_response, 4) == 0)
|
||||
{
|
||||
return ATCA_SUCCESS;
|
||||
}
|
||||
if (memcmp(rx_buffer, selftest_fail_resp, 4) == 0)
|
||||
{
|
||||
return ATCA_STATUS_SELFTEST_ERROR;
|
||||
}
|
||||
return ATCA_WAKE_FAILED;
|
||||
}
|
||||
|
||||
/** @brief idle CryptoAuth device using I2C bus
|
||||
* @param[in] iface interface to logical device to idle
|
||||
* @return ATCA_SUCCESS on success, otherwise an error code.
|
||||
*/
|
||||
|
||||
ATCA_STATUS hal_i2c_idle(ATCAIface iface)
|
||||
{
|
||||
uint8_t buffer[1] = { 0x2 }; // idle word address value
|
||||
I2cMcuWriteBuffer((I2c_t*)NULL, iface->mIfaceCFG->atcai2c.slave_address,0, buffer, (size_t)1);
|
||||
return ATCA_SUCCESS;
|
||||
}
|
||||
|
||||
/** @brief sleep CryptoAuth device using I2C bus
|
||||
* @param[in] iface interface to logical device to sleep
|
||||
* @return ATCA_SUCCESS on success, otherwise an error code.
|
||||
*/
|
||||
|
||||
ATCA_STATUS hal_i2c_sleep(ATCAIface iface)
|
||||
{
|
||||
uint8_t buffer[1] = { 0x1 }; // sleep word address value
|
||||
I2cMcuWriteBuffer((I2c_t*)NULL, iface->mIfaceCFG->atcai2c.slave_address,0, buffer, (size_t)1);
|
||||
return ATCA_SUCCESS;
|
||||
}
|
||||
|
||||
/** @brief manages reference count on given bus and releases resource if no more refences exist
|
||||
* @param[in] hal_data - opaque pointer to hal data structure - known only to the HAL implementation
|
||||
* return ATCA_SUCCESS
|
||||
*/
|
||||
|
||||
ATCA_STATUS hal_i2c_release(void *hal_data)
|
||||
{
|
||||
return ATCA_SUCCESS;
|
||||
}
|
@@ -0,0 +1,58 @@
|
||||
/**
|
||||
* @file atecc608a-tnglora-se-hal.h
|
||||
*
|
||||
* @brief Secure Element hardware abstraction layer
|
||||
*
|
||||
* @remark Current implementation only supports LoRaWAN 1.0.x version
|
||||
*
|
||||
* @copyright Copyright (c) 2020 The Things Industries B.V.
|
||||
*
|
||||
* Revised BSD License
|
||||
* Copyright The Things Industries B.V 2020. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* * Neither the name of the Things Industries B.V nor the
|
||||
* names of its contributors may be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE THINGS INDUSTRIES B.V BE LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
#ifndef __ATECC608A_TNGLORA_SE_HAL_H__
|
||||
#define __ATECC608A_TNGLORA_SE_HAL_H__
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
/*!
|
||||
* \brief Get a random number
|
||||
*
|
||||
* \remark The number SHALL NOT be generated using a pseudo random number
|
||||
* generator
|
||||
* \retval number 32 bit random value
|
||||
*/
|
||||
uint32_t ATECC608ASeHalGetRandomNumber( void );
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // __ATECC608A_TNGLORA_SE_HAL_H__
|
@@ -0,0 +1,644 @@
|
||||
/**
|
||||
* @file atecc608a-tnglora-se.c
|
||||
*
|
||||
* @brief ATECC608A-TNGLORA Secure Element hardware implementation
|
||||
*
|
||||
* @remark Current implementation only supports LoRaWAN 1.0.x version
|
||||
*
|
||||
* @copyright Copyright (c) 2020 The Things Industries B.V.
|
||||
*
|
||||
* Revised BSD License
|
||||
* Copyright The Things Industries B.V 2020. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* * Neither the name of the Things Industries B.V nor the
|
||||
* names of its contributors may be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE THINGS INDUSTRIES B.V BE LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "atca_basic.h"
|
||||
#include "cryptoauthlib.h"
|
||||
#include "atca_devtypes.h"
|
||||
|
||||
#include "secure-element.h"
|
||||
#include "se-identity.h"
|
||||
#include "atecc608a-tnglora-se-hal.h"
|
||||
|
||||
/*!
|
||||
* Number of supported crypto keys
|
||||
*/
|
||||
#define NUM_OF_KEYS 15
|
||||
|
||||
#define DEV_EUI_ASCII_SIZE_BYTE 16U
|
||||
|
||||
/*!
|
||||
* Identifier value pair type for Keys
|
||||
*/
|
||||
typedef struct sKey
|
||||
{
|
||||
/*
|
||||
* Key identifier (used for maping the stack MAC key to the ATECC608A-TNGLoRaWAN slot)
|
||||
*/
|
||||
KeyIdentifier_t KeyID;
|
||||
/*
|
||||
* Key slot number
|
||||
*/
|
||||
uint16_t KeySlotNumber;
|
||||
/*
|
||||
* Key block index within slot (each block can contain two keys, so index is either 0 or 1)
|
||||
*/
|
||||
uint8_t KeyBlockIndex;
|
||||
} Key_t;
|
||||
|
||||
/*
|
||||
* Secure Element Non Volatile Context structure
|
||||
*/
|
||||
typedef struct sSecureElementNvCtx
|
||||
{
|
||||
/*!
|
||||
* DevEUI storage
|
||||
*/
|
||||
uint8_t DevEui[SE_EUI_SIZE];
|
||||
/*!
|
||||
* Join EUI storage
|
||||
*/
|
||||
uint8_t JoinEui[SE_EUI_SIZE];
|
||||
/*!
|
||||
* Pin storage
|
||||
*/
|
||||
uint8_t Pin[SE_PIN_SIZE];
|
||||
/*!
|
||||
* LoRaWAN key list
|
||||
*/
|
||||
Key_t KeyList[NUM_OF_KEYS];
|
||||
} SecureElementNvCtx_t;
|
||||
|
||||
/*!
|
||||
* Secure element context
|
||||
*/
|
||||
static SecureElementNvCtx_t SeNvmCtx = {
|
||||
/*!
|
||||
* end-device IEEE EUI (big endian)
|
||||
*/
|
||||
.DevEui = { 0 },
|
||||
/*!
|
||||
* App/Join server IEEE EUI (big endian)
|
||||
*/
|
||||
.JoinEui = { 0 },
|
||||
/*!
|
||||
* Secure-element pin (big endian)
|
||||
*/
|
||||
.Pin = SECURE_ELEMENT_PIN,
|
||||
/*!
|
||||
* LoRaWAN key list
|
||||
*/
|
||||
.KeyList = ATECC608A_SE_KEY_LIST
|
||||
};
|
||||
|
||||
static SecureElementNvmEvent SeNvmCtxChanged;
|
||||
|
||||
static ATCAIfaceCfg atecc608_i2c_config;
|
||||
|
||||
static ATCA_STATUS convert_ascii_devEUI( uint8_t* devEUI_ascii, uint8_t* devEUI );
|
||||
|
||||
static ATCA_STATUS atcab_read_joinEUI( uint8_t* joinEUI )
|
||||
{
|
||||
ATCA_STATUS status = ATCA_GEN_FAIL;
|
||||
uint8_t read_buf[ATCA_BLOCK_SIZE];
|
||||
|
||||
if( joinEUI == NULL )
|
||||
{
|
||||
return ATCA_BAD_PARAM;
|
||||
}
|
||||
|
||||
do
|
||||
{
|
||||
status = atcab_read_zone( ATCA_ZONE_DATA, TNGLORA_JOIN_EUI_SLOT, 0, 0, read_buf, ATCA_BLOCK_SIZE );
|
||||
if( status != ATCA_SUCCESS )
|
||||
{
|
||||
break;
|
||||
}
|
||||
memcpy1( joinEUI, read_buf, SE_EUI_SIZE );
|
||||
} while( 0 );
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
static ATCA_STATUS atcab_read_ascii_devEUI( uint8_t* devEUI_ascii )
|
||||
{
|
||||
ATCA_STATUS status = ATCA_GEN_FAIL;
|
||||
uint8_t read_buf[ATCA_BLOCK_SIZE];
|
||||
|
||||
if( devEUI_ascii == NULL )
|
||||
{
|
||||
return ATCA_BAD_PARAM;
|
||||
}
|
||||
|
||||
do
|
||||
{
|
||||
status = atcab_read_zone( ATCA_ZONE_DATA, TNGLORA_DEV_EUI_SLOT, 0, 0, read_buf, ATCA_BLOCK_SIZE );
|
||||
if( status != ATCA_SUCCESS )
|
||||
{
|
||||
break;
|
||||
}
|
||||
memcpy1( devEUI_ascii, read_buf, DEV_EUI_ASCII_SIZE_BYTE );
|
||||
} while( 0 );
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
static ATCA_STATUS convert_ascii_devEUI( uint8_t* devEUI_ascii, uint8_t* devEUI )
|
||||
{
|
||||
for( size_t pos = 0; pos < DEV_EUI_ASCII_SIZE_BYTE; pos += 2 )
|
||||
{
|
||||
uint8_t temp = 0;
|
||||
if( ( devEUI_ascii[pos] >= '0' ) && ( devEUI_ascii[pos] <= '9' ) )
|
||||
{
|
||||
temp = ( devEUI_ascii[pos] - '0' ) << 4;
|
||||
}
|
||||
else if( ( devEUI_ascii[pos] >= 'A' ) && ( devEUI_ascii[pos] <= 'F' ) )
|
||||
{
|
||||
temp = ( ( devEUI_ascii[pos] - 'A' ) + 10 ) << 4;
|
||||
}
|
||||
else
|
||||
{
|
||||
return ATCA_BAD_PARAM;
|
||||
}
|
||||
if( ( devEUI_ascii[pos + 1] >= '0' ) && ( devEUI_ascii[pos + 1] <= '9' ) )
|
||||
{
|
||||
temp |= devEUI_ascii[pos + 1] - '0';
|
||||
}
|
||||
else if( ( devEUI_ascii[pos + 1] >= 'A' ) && ( devEUI_ascii[pos + 1] <= 'F' ) )
|
||||
{
|
||||
temp |= ( devEUI_ascii[pos + 1] - 'A' ) + 10;
|
||||
}
|
||||
else
|
||||
{
|
||||
return ATCA_BAD_PARAM;
|
||||
}
|
||||
devEUI[pos / 2] = temp;
|
||||
}
|
||||
return ATCA_SUCCESS;
|
||||
}
|
||||
|
||||
static ATCA_STATUS atcab_read_devEUI( uint8_t* devEUI )
|
||||
{
|
||||
ATCA_STATUS status = ATCA_GEN_FAIL;
|
||||
uint8_t devEUI_ascii[DEV_EUI_ASCII_SIZE_BYTE];
|
||||
|
||||
status = atcab_read_ascii_devEUI( devEUI_ascii );
|
||||
if( status != ATCA_SUCCESS )
|
||||
{
|
||||
return status;
|
||||
}
|
||||
status = convert_ascii_devEUI( devEUI_ascii, devEUI );
|
||||
return status;
|
||||
}
|
||||
|
||||
/*
|
||||
* Gets key item from key list.
|
||||
*
|
||||
* cmac = aes128_cmac(keyID, B0 | msg)
|
||||
*
|
||||
* \param[IN] keyID - Key identifier
|
||||
* \param[OUT] keyItem - Key item reference
|
||||
* \retval - Status of the operation
|
||||
*/
|
||||
SecureElementStatus_t GetKeyByID( KeyIdentifier_t keyID, Key_t** keyItem )
|
||||
{
|
||||
for( uint8_t i = 0; i < NUM_OF_KEYS; i++ )
|
||||
{
|
||||
if( SeNvmCtx.KeyList[i].KeyID == keyID )
|
||||
{
|
||||
*keyItem = &( SeNvmCtx.KeyList[i] );
|
||||
return SECURE_ELEMENT_SUCCESS;
|
||||
}
|
||||
}
|
||||
return SECURE_ELEMENT_ERROR_INVALID_KEY_ID;
|
||||
}
|
||||
|
||||
/*
|
||||
* Dummy callback in case if the user provides NULL function pointer
|
||||
*/
|
||||
static void DummyCB( void )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* Computes a CMAC of a message using provided initial Bx block
|
||||
*
|
||||
* cmac = aes128_cmac(keyID, blocks[i].Buffer)
|
||||
*
|
||||
* \param[IN] micBxBuffer - Buffer containing the initial Bx block
|
||||
* \param[IN] buffer - Data buffer
|
||||
* \param[IN] size - Data buffer size
|
||||
* \param[IN] keyID - Key identifier to determine the AES key to be used
|
||||
* \param[OUT] cmac - Computed cmac
|
||||
* \retval - Status of the operation
|
||||
*/
|
||||
static SecureElementStatus_t ComputeCmac( uint8_t* micBxBuffer, uint8_t* buffer, uint16_t size, KeyIdentifier_t keyID,
|
||||
uint32_t* cmac )
|
||||
{
|
||||
if( ( buffer == NULL ) || ( cmac == NULL ) )
|
||||
{
|
||||
return SECURE_ELEMENT_ERROR_NPE;
|
||||
}
|
||||
|
||||
uint8_t Cmac[16] = { 0 };
|
||||
|
||||
Key_t* keyItem;
|
||||
SecureElementStatus_t retval = GetKeyByID( keyID, &keyItem );
|
||||
if( retval != SECURE_ELEMENT_SUCCESS )
|
||||
{
|
||||
return retval;
|
||||
}
|
||||
|
||||
atca_aes_cmac_ctx_t atcaAesCmacCtx;
|
||||
ATCA_STATUS status =
|
||||
atcab_aes_cmac_init( &atcaAesCmacCtx, keyItem->KeySlotNumber, keyItem->KeyBlockIndex );
|
||||
|
||||
if( ATCA_SUCCESS == status )
|
||||
{
|
||||
if( micBxBuffer != NULL )
|
||||
{
|
||||
atcab_aes_cmac_update( &atcaAesCmacCtx, micBxBuffer, 16 );
|
||||
}
|
||||
|
||||
atcab_aes_cmac_update( &atcaAesCmacCtx, buffer, size );
|
||||
|
||||
atcab_aes_cmac_finish( &atcaAesCmacCtx, Cmac, 16 );
|
||||
|
||||
*cmac = ( uint32_t )( ( uint32_t ) Cmac[3] << 24 | ( uint32_t ) Cmac[2] << 16 | ( uint32_t ) Cmac[1] << 8 |
|
||||
( uint32_t ) Cmac[0] );
|
||||
return SECURE_ELEMENT_SUCCESS;
|
||||
}
|
||||
else
|
||||
{
|
||||
return SECURE_ELEMENT_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
SecureElementStatus_t SecureElementInit( SecureElementNvmEvent seNvmCtxChanged )
|
||||
{
|
||||
#if !defined( SECURE_ELEMENT_PRE_PROVISIONED )
|
||||
#error "ATECC608A is always pre-provisioned. Please set SECURE_ELEMENT_PRE_PROVISIONED to ON"
|
||||
#endif
|
||||
atecc608_i2c_config.iface_type = ATCA_I2C_IFACE;
|
||||
atecc608_i2c_config.atcai2c.baud = ATCA_HAL_ATECC608A_I2C_FREQUENCY;
|
||||
atecc608_i2c_config.atcai2c.bus = ATCA_HAL_ATECC608A_I2C_BUS_PINS;
|
||||
atecc608_i2c_config.atcai2c.slave_address = ATCA_HAL_ATECC608A_I2C_ADDRESS;
|
||||
atecc608_i2c_config.devtype = ATECC608A;
|
||||
atecc608_i2c_config.rx_retries = ATCA_HAL_ATECC608A_I2C_RX_RETRIES;
|
||||
atecc608_i2c_config.wake_delay = ATCA_HAL_ATECC608A_I2C_WAKEUP_DELAY;
|
||||
|
||||
if( atcab_init( &atecc608_i2c_config ) != ATCA_SUCCESS )
|
||||
{
|
||||
return SECURE_ELEMENT_ERROR;
|
||||
}
|
||||
|
||||
if( atcab_read_devEUI( SeNvmCtx.DevEui ) != ATCA_SUCCESS )
|
||||
{
|
||||
return SECURE_ELEMENT_ERROR;
|
||||
}
|
||||
|
||||
if( atcab_read_joinEUI( SeNvmCtx.JoinEui ) != ATCA_SUCCESS )
|
||||
{
|
||||
return SECURE_ELEMENT_ERROR;
|
||||
}
|
||||
|
||||
// Assign callback
|
||||
if( seNvmCtxChanged != 0 )
|
||||
{
|
||||
SeNvmCtxChanged = seNvmCtxChanged;
|
||||
}
|
||||
else
|
||||
{
|
||||
SeNvmCtxChanged = DummyCB;
|
||||
}
|
||||
|
||||
return SECURE_ELEMENT_SUCCESS;
|
||||
}
|
||||
|
||||
SecureElementStatus_t SecureElementRestoreNvmCtx( void* seNvmCtx )
|
||||
{
|
||||
// Restore nvm context
|
||||
if( seNvmCtx != 0 )
|
||||
{
|
||||
memcpy1( ( uint8_t* ) &SeNvmCtx, ( uint8_t* ) seNvmCtx, sizeof( SeNvmCtx ) );
|
||||
return SECURE_ELEMENT_SUCCESS;
|
||||
}
|
||||
else
|
||||
{
|
||||
return SECURE_ELEMENT_ERROR_NPE;
|
||||
}
|
||||
}
|
||||
|
||||
void* SecureElementGetNvmCtx( size_t* seNvmCtxSize )
|
||||
{
|
||||
*seNvmCtxSize = sizeof( SeNvmCtx );
|
||||
return &SeNvmCtx;
|
||||
}
|
||||
|
||||
SecureElementStatus_t SecureElementSetKey( KeyIdentifier_t keyID, uint8_t* key )
|
||||
{
|
||||
// No key setting for HW SE, can only derive keys
|
||||
return SECURE_ELEMENT_SUCCESS;
|
||||
}
|
||||
|
||||
SecureElementStatus_t SecureElementComputeAesCmac( uint8_t* micBxBuffer, uint8_t* buffer, uint16_t size,
|
||||
KeyIdentifier_t keyID, uint32_t* cmac )
|
||||
{
|
||||
if( keyID >= LORAMAC_CRYPTO_MULTICAST_KEYS )
|
||||
{
|
||||
// Never accept multicast key identifier for cmac computation
|
||||
return SECURE_ELEMENT_ERROR_INVALID_KEY_ID;
|
||||
}
|
||||
return ComputeCmac( micBxBuffer, buffer, size, keyID, cmac );
|
||||
}
|
||||
|
||||
SecureElementStatus_t SecureElementVerifyAesCmac( uint8_t* buffer, uint16_t size, uint32_t expectedCmac,
|
||||
KeyIdentifier_t keyID )
|
||||
{
|
||||
if( buffer == NULL )
|
||||
{
|
||||
return SECURE_ELEMENT_ERROR_NPE;
|
||||
}
|
||||
|
||||
SecureElementStatus_t retval = SECURE_ELEMENT_ERROR;
|
||||
uint32_t compCmac = 0;
|
||||
|
||||
retval = ComputeCmac( NULL, buffer, size, keyID, &compCmac );
|
||||
if( retval != SECURE_ELEMENT_SUCCESS )
|
||||
{
|
||||
return retval;
|
||||
}
|
||||
|
||||
if( expectedCmac != compCmac )
|
||||
{
|
||||
retval = SECURE_ELEMENT_FAIL_CMAC;
|
||||
}
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
SecureElementStatus_t SecureElementAesEncrypt( uint8_t* buffer, uint16_t size, KeyIdentifier_t keyID,
|
||||
uint8_t* encBuffer )
|
||||
{
|
||||
if( buffer == NULL || encBuffer == NULL )
|
||||
{
|
||||
return SECURE_ELEMENT_ERROR_NPE;
|
||||
}
|
||||
|
||||
// Check if the size is divisible by 16,
|
||||
if( ( size % 16 ) != 0 )
|
||||
{
|
||||
return SECURE_ELEMENT_ERROR_BUF_SIZE;
|
||||
}
|
||||
|
||||
Key_t* pItem;
|
||||
SecureElementStatus_t retval = GetKeyByID( keyID, &pItem );
|
||||
|
||||
if( retval == SECURE_ELEMENT_SUCCESS )
|
||||
{
|
||||
uint8_t block = 0;
|
||||
|
||||
while( size != 0 )
|
||||
{
|
||||
atcab_aes_encrypt( pItem->KeySlotNumber, pItem->KeyBlockIndex, &buffer[block], &encBuffer[block] );
|
||||
block = block + 16;
|
||||
size = size - 16;
|
||||
}
|
||||
}
|
||||
return retval;
|
||||
}
|
||||
|
||||
SecureElementStatus_t SecureElementDeriveAndStoreKey( Version_t version, uint8_t* input, KeyIdentifier_t rootKeyID,
|
||||
KeyIdentifier_t targetKeyID )
|
||||
{
|
||||
if( input == NULL )
|
||||
{
|
||||
return SECURE_ELEMENT_ERROR_NPE;
|
||||
}
|
||||
|
||||
// Source key slot is the LSB and target key slot is the MSB
|
||||
uint16_t source_target_ids = 0;
|
||||
Key_t* source_key;
|
||||
Key_t* target_key;
|
||||
ATCA_STATUS status = ATCA_SUCCESS;
|
||||
|
||||
// In case of MC_KE_KEY, only McRootKey can be used as root key
|
||||
if( targetKeyID == MC_KE_KEY )
|
||||
{
|
||||
if( rootKeyID != MC_ROOT_KEY )
|
||||
{
|
||||
return SECURE_ELEMENT_ERROR_INVALID_KEY_ID;
|
||||
}
|
||||
}
|
||||
|
||||
if( ( rootKeyID == APP_KEY ) || ( rootKeyID == MC_ROOT_KEY ) || ( rootKeyID == MC_KE_KEY ) )
|
||||
{
|
||||
// Allow the stack to move forward as these rootkeys dont exist inside SE.
|
||||
return SECURE_ELEMENT_SUCCESS;
|
||||
}
|
||||
|
||||
if( GetKeyByID( rootKeyID, &source_key ) != SECURE_ELEMENT_SUCCESS )
|
||||
{
|
||||
return SECURE_ELEMENT_ERROR_INVALID_KEY_ID;
|
||||
}
|
||||
|
||||
if( GetKeyByID( targetKeyID, &target_key ) != SECURE_ELEMENT_SUCCESS )
|
||||
{
|
||||
return SECURE_ELEMENT_ERROR_INVALID_KEY_ID;
|
||||
}
|
||||
|
||||
source_target_ids = target_key->KeySlotNumber << 8;
|
||||
source_target_ids += source_key->KeySlotNumber;
|
||||
|
||||
uint32_t detail = source_key->KeyBlockIndex;
|
||||
|
||||
status = atcab_kdf( KDF_MODE_ALG_AES | KDF_MODE_SOURCE_SLOT | KDF_MODE_TARGET_SLOT, source_target_ids, detail,
|
||||
input, NULL, NULL );
|
||||
if( status == ATCA_SUCCESS )
|
||||
{
|
||||
return SECURE_ELEMENT_SUCCESS;
|
||||
}
|
||||
else
|
||||
{
|
||||
return SECURE_ELEMENT_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
SecureElementStatus_t SecureElementProcessJoinAccept( JoinReqIdentifier_t joinReqType, uint8_t* joinEui,
|
||||
uint16_t devNonce, uint8_t* encJoinAccept,
|
||||
uint8_t encJoinAcceptSize, uint8_t* decJoinAccept,
|
||||
uint8_t* versionMinor )
|
||||
{
|
||||
if( ( encJoinAccept == NULL ) || ( decJoinAccept == NULL ) || ( versionMinor == NULL ) )
|
||||
{
|
||||
return SECURE_ELEMENT_ERROR_NPE;
|
||||
}
|
||||
|
||||
// Check that frame size isn't bigger than a JoinAccept with CFList size
|
||||
if( encJoinAcceptSize > LORAMAC_JOIN_ACCEPT_FRAME_MAX_SIZE )
|
||||
{
|
||||
return SECURE_ELEMENT_ERROR_BUF_SIZE;
|
||||
}
|
||||
|
||||
// Determine decryption key
|
||||
KeyIdentifier_t encKeyID = NWK_KEY;
|
||||
|
||||
if( joinReqType != JOIN_REQ )
|
||||
{
|
||||
encKeyID = J_S_ENC_KEY;
|
||||
}
|
||||
|
||||
memcpy1( decJoinAccept, encJoinAccept, encJoinAcceptSize );
|
||||
|
||||
// Decrypt JoinAccept, skip MHDR
|
||||
if( SecureElementAesEncrypt( encJoinAccept + LORAMAC_MHDR_FIELD_SIZE, encJoinAcceptSize - LORAMAC_MHDR_FIELD_SIZE,
|
||||
encKeyID, decJoinAccept + LORAMAC_MHDR_FIELD_SIZE ) != SECURE_ELEMENT_SUCCESS )
|
||||
{
|
||||
return SECURE_ELEMENT_FAIL_ENCRYPT;
|
||||
}
|
||||
|
||||
*versionMinor = ( ( decJoinAccept[11] & 0x80 ) == 0x80 ) ? 1 : 0;
|
||||
|
||||
uint32_t mic = 0;
|
||||
|
||||
mic = ( ( uint32_t ) decJoinAccept[encJoinAcceptSize - LORAMAC_MIC_FIELD_SIZE] << 0 );
|
||||
mic |= ( ( uint32_t ) decJoinAccept[encJoinAcceptSize - LORAMAC_MIC_FIELD_SIZE + 1] << 8 );
|
||||
mic |= ( ( uint32_t ) decJoinAccept[encJoinAcceptSize - LORAMAC_MIC_FIELD_SIZE + 2] << 16 );
|
||||
mic |= ( ( uint32_t ) decJoinAccept[encJoinAcceptSize - LORAMAC_MIC_FIELD_SIZE + 3] << 24 );
|
||||
|
||||
// - Header buffer to be used for MIC computation
|
||||
// - LoRaWAN 1.0.x : micHeader = [MHDR(1)]
|
||||
// - LoRaWAN 1.1.x : micHeader = [JoinReqType(1), JoinEUI(8), DevNonce(2), MHDR(1)]
|
||||
|
||||
// Verify mic
|
||||
if( *versionMinor == 0 )
|
||||
{
|
||||
// For LoRaWAN 1.0.x
|
||||
// cmac = aes128_cmac(NwkKey, MHDR | JoinNonce | NetID | DevAddr | DLSettings | RxDelay | CFList |
|
||||
// CFListType)
|
||||
if( SecureElementVerifyAesCmac( decJoinAccept, ( encJoinAcceptSize - LORAMAC_MIC_FIELD_SIZE ), mic, NWK_KEY ) !=
|
||||
SECURE_ELEMENT_SUCCESS )
|
||||
{
|
||||
return SECURE_ELEMENT_FAIL_CMAC;
|
||||
}
|
||||
}
|
||||
#if( USE_LRWAN_1_1_X_CRYPTO == 1 )
|
||||
else if( *versionMinor == 1 )
|
||||
{
|
||||
uint8_t micHeader11[JOIN_ACCEPT_MIC_COMPUTATION_OFFSET] = { 0 };
|
||||
uint16_t bufItr = 0;
|
||||
|
||||
micHeader11[bufItr++] = ( uint8_t ) joinReqType;
|
||||
|
||||
memcpyr( micHeader11 + bufItr, joinEui, LORAMAC_JOIN_EUI_FIELD_SIZE );
|
||||
bufItr += LORAMAC_JOIN_EUI_FIELD_SIZE;
|
||||
|
||||
micHeader11[bufItr++] = devNonce & 0xFF;
|
||||
micHeader11[bufItr++] = ( devNonce >> 8 ) & 0xFF;
|
||||
|
||||
// For LoRaWAN 1.1.x and later:
|
||||
// cmac = aes128_cmac(JSIntKey, JoinReqType | JoinEUI | DevNonce | MHDR | JoinNonce | NetID | DevAddr |
|
||||
// DLSettings | RxDelay | CFList | CFListType)
|
||||
// Prepare the msg for integrity check (adding JoinReqType, JoinEUI and DevNonce)
|
||||
uint8_t localBuffer[LORAMAC_JOIN_ACCEPT_FRAME_MAX_SIZE + JOIN_ACCEPT_MIC_COMPUTATION_OFFSET] = { 0 };
|
||||
|
||||
memcpy1( localBuffer, micHeader11, JOIN_ACCEPT_MIC_COMPUTATION_OFFSET );
|
||||
memcpy1( localBuffer + JOIN_ACCEPT_MIC_COMPUTATION_OFFSET - 1, decJoinAccept, encJoinAcceptSize );
|
||||
|
||||
if( SecureElementVerifyAesCmac( localBuffer,
|
||||
encJoinAcceptSize + JOIN_ACCEPT_MIC_COMPUTATION_OFFSET -
|
||||
LORAMAC_MHDR_FIELD_SIZE - LORAMAC_MIC_FIELD_SIZE,
|
||||
mic, J_S_INT_KEY ) != SECURE_ELEMENT_SUCCESS )
|
||||
{
|
||||
return SECURE_ELEMENT_FAIL_CMAC;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
else
|
||||
{
|
||||
return SECURE_ELEMENT_ERROR_INVALID_LORAWAM_SPEC_VERSION;
|
||||
}
|
||||
|
||||
return SECURE_ELEMENT_SUCCESS;
|
||||
}
|
||||
|
||||
SecureElementStatus_t SecureElementRandomNumber( uint32_t* randomNum )
|
||||
{
|
||||
if( randomNum == NULL )
|
||||
{
|
||||
return SECURE_ELEMENT_ERROR_NPE;
|
||||
}
|
||||
*randomNum = ATECC608ASeHalGetRandomNumber( );
|
||||
return SECURE_ELEMENT_SUCCESS;
|
||||
}
|
||||
|
||||
SecureElementStatus_t SecureElementSetDevEui( uint8_t* devEui )
|
||||
{
|
||||
if( devEui == NULL )
|
||||
{
|
||||
return SECURE_ELEMENT_ERROR_NPE;
|
||||
}
|
||||
memcpy1( SeNvmCtx.DevEui, devEui, SE_EUI_SIZE );
|
||||
SeNvmCtxChanged( );
|
||||
return SECURE_ELEMENT_SUCCESS;
|
||||
}
|
||||
|
||||
uint8_t* SecureElementGetDevEui( void )
|
||||
{
|
||||
return SeNvmCtx.DevEui;
|
||||
}
|
||||
|
||||
SecureElementStatus_t SecureElementSetJoinEui( uint8_t* joinEui )
|
||||
{
|
||||
if( joinEui == NULL )
|
||||
{
|
||||
return SECURE_ELEMENT_ERROR_NPE;
|
||||
}
|
||||
memcpy1( SeNvmCtx.JoinEui, joinEui, SE_EUI_SIZE );
|
||||
SeNvmCtxChanged( );
|
||||
return SECURE_ELEMENT_SUCCESS;
|
||||
}
|
||||
|
||||
uint8_t* SecureElementGetJoinEui( void )
|
||||
{
|
||||
return SeNvmCtx.JoinEui;
|
||||
}
|
||||
|
||||
SecureElementStatus_t SecureElementSetPin( uint8_t* pin )
|
||||
{
|
||||
if( pin == NULL )
|
||||
{
|
||||
return SECURE_ELEMENT_ERROR_NPE;
|
||||
}
|
||||
|
||||
memcpy1( SeNvmCtx.Pin, pin, SE_PIN_SIZE );
|
||||
SeNvmCtxChanged( );
|
||||
return SECURE_ELEMENT_SUCCESS;
|
||||
}
|
||||
|
||||
uint8_t* SecureElementGetPin( void )
|
||||
{
|
||||
return SeNvmCtx.Pin;
|
||||
}
|
@@ -0,0 +1,250 @@
|
||||
/*!
|
||||
* \file se-identity.h
|
||||
*
|
||||
* \brief Secure Element identity and keys
|
||||
*
|
||||
* \copyright Revised BSD License, see section \ref LICENSE.
|
||||
*
|
||||
* \code
|
||||
* ______ _
|
||||
* / _____) _ | |
|
||||
* ( (____ _____ ____ _| |_ _____ ____| |__
|
||||
* \____ \| ___ | (_ _) ___ |/ ___) _ \
|
||||
* _____) ) ____| | | || |_| ____( (___| | | |
|
||||
* (______/|_____)_|_|_| \__)_____)\____)_| |_|
|
||||
* (C)2020 Semtech
|
||||
*
|
||||
* ___ _____ _ ___ _ _____ ___ ___ ___ ___
|
||||
* / __|_ _/_\ / __| |/ / __/ _ \| _ \/ __| __|
|
||||
* \__ \ | |/ _ \ (__| ' <| _| (_) | / (__| _|
|
||||
* |___/ |_/_/ \_\___|_|\_\_| \___/|_|_\\___|___|
|
||||
* embedded.connectivity.solutions===============
|
||||
*
|
||||
* \endcode
|
||||
*
|
||||
*/
|
||||
#ifndef __SOFT_SE_IDENTITY_H__
|
||||
#define __SOFT_SE_IDENTITY_H__
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*!
|
||||
******************************************************************************
|
||||
********************************** WARNING ***********************************
|
||||
******************************************************************************
|
||||
The secure-element implementation supports both 1.0.x and 1.1.x LoRaWAN
|
||||
versions of the specification.
|
||||
Thus it has been decided to use the 1.1.x keys and EUI name definitions.
|
||||
The below table shows the names equivalence between versions:
|
||||
+---------------------+-------------------------+
|
||||
| 1.0.x | 1.1.x |
|
||||
+=====================+=========================+
|
||||
| LORAWAN_DEVICE_EUI | LORAWAN_DEVICE_EUI |
|
||||
+---------------------+-------------------------+
|
||||
| LORAWAN_APP_EUI | LORAWAN_JOIN_EUI |
|
||||
+---------------------+-------------------------+
|
||||
| LORAWAN_GEN_APP_KEY | LORAWAN_APP_KEY |
|
||||
+---------------------+-------------------------+
|
||||
| LORAWAN_APP_KEY | LORAWAN_NWK_KEY |
|
||||
+---------------------+-------------------------+
|
||||
| LORAWAN_NWK_S_KEY | LORAWAN_F_NWK_S_INT_KEY |
|
||||
+---------------------+-------------------------+
|
||||
| LORAWAN_NWK_S_KEY | LORAWAN_S_NWK_S_INT_KEY |
|
||||
+---------------------+-------------------------+
|
||||
| LORAWAN_NWK_S_KEY | LORAWAN_NWK_S_ENC_KEY |
|
||||
+---------------------+-------------------------+
|
||||
| LORAWAN_APP_S_KEY | LORAWAN_APP_S_KEY |
|
||||
+---------------------+-------------------------+
|
||||
******************************************************************************
|
||||
******************************************************************************
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
/*!
|
||||
* Secure-element pin
|
||||
*/
|
||||
#define SECURE_ELEMENT_PIN \
|
||||
{ \
|
||||
0x00, 0x00, 0x00, 0x00 \
|
||||
}
|
||||
|
||||
/*!
|
||||
* When set to 1 DevAdd is LORAWAN_DEVICE_ADDRESS
|
||||
* When set to 0 DevAdd is automatically generated using a pseudo random generator
|
||||
*/
|
||||
#define STATIC_DEVICE_ADDRESS 0
|
||||
|
||||
/*!
|
||||
* Device address on the network (big endian)
|
||||
*
|
||||
* \remark In this application the value is automatically generated using
|
||||
* a pseudo random generator seeded with a value derived from
|
||||
* BoardUniqueId value if LORAWAN_DEVICE_ADDRESS is set to 0
|
||||
*/
|
||||
#define LORAWAN_DEVICE_ADDRESS ( uint32_t ) 0x00000000
|
||||
|
||||
/*
|
||||
* =============================================================================
|
||||
* BELOW LINES SHOULDN'T BE MODIFIED
|
||||
* =============================================================================
|
||||
*/
|
||||
|
||||
/*!
|
||||
* ATECC608A predefined key slots setup
|
||||
*/
|
||||
#define TNGLORA_DEV_EUI_SLOT 10U
|
||||
#define TNGLORA_JOIN_EUI_SLOT 9U
|
||||
#define TNGLORA_APP_KEY_SLOT 0U
|
||||
#define TNGLORA_NWK_KEY_SLOT 0U
|
||||
#define TNGLORA_S_NWK_S_INT_KEY_SLOT 4U
|
||||
#define TNGLORA_F_NWK_S_INT_KEY_SLOT 5U
|
||||
#define TNGLORA_J_S_INT_KEY_SLOT 6U
|
||||
#define TNGLORA_J_S_ENC_KEY_SLOT 7U
|
||||
#define TNGLORA_APP_S_KEY_SLOT 2U
|
||||
#define TNGLORA_NWK_S_ENC_KEY_SLOT 3U
|
||||
#define TNGLORA_MC_APP_S_KEY_0_SLOT 11U
|
||||
#define TNGLORA_MC_NWK_S_KEY_0_SLOT 12U
|
||||
#define TNGLORA_APP_KEY_BLOCK_INDEX 1U
|
||||
#define TNGLORA_REMAINING_KEYS_BLOCK_INDEX 0U
|
||||
|
||||
#define ATECC608A_SE_KEY_LIST \
|
||||
{ \
|
||||
{ \
|
||||
/*! \
|
||||
* Application root key \
|
||||
* WARNING: FOR 1.0.x DEVICES IT IS THE \ref LORAWAN_GEN_APP_KEY \
|
||||
*/ \
|
||||
.KeyID = APP_KEY, \
|
||||
.KeySlotNumber = TNGLORA_APP_KEY_SLOT, \
|
||||
.KeyBlockIndex = TNGLORA_APP_KEY_BLOCK_INDEX, \
|
||||
}, \
|
||||
{ \
|
||||
/*! \
|
||||
* Network root key \
|
||||
* WARNING: FOR 1.0.x DEVICES IT IS THE \ref LORAWAN_APP_KEY \
|
||||
*/ \
|
||||
.KeyID = NWK_KEY, \
|
||||
.KeySlotNumber = TNGLORA_APP_KEY_SLOT, \
|
||||
.KeyBlockIndex = TNGLORA_APP_KEY_BLOCK_INDEX, \
|
||||
}, \
|
||||
{ \
|
||||
/*! \
|
||||
* Join session integrity key (Dynamically updated) \
|
||||
* WARNING: NOT USED FOR 1.0.x DEVICES \
|
||||
*/ \
|
||||
.KeyID = J_S_INT_KEY, \
|
||||
.KeySlotNumber = TNGLORA_J_S_INT_KEY_SLOT, \
|
||||
.KeyBlockIndex = TNGLORA_REMAINING_KEYS_BLOCK_INDEX, \
|
||||
}, \
|
||||
{ \
|
||||
/*! \
|
||||
* Join session encryption key (Dynamically updated) \
|
||||
* WARNING: NOT USED FOR 1.0.x DEVICES \
|
||||
*/ \
|
||||
.KeyID = J_S_ENC_KEY, \
|
||||
.KeySlotNumber = TNGLORA_J_S_ENC_KEY_SLOT, \
|
||||
.KeyBlockIndex = TNGLORA_REMAINING_KEYS_BLOCK_INDEX, \
|
||||
}, \
|
||||
{ \
|
||||
/*! \
|
||||
* Forwarding Network session integrity key \
|
||||
* WARNING: NWK_S_KEY FOR 1.0.x DEVICES \
|
||||
*/ \
|
||||
.KeyID = F_NWK_S_INT_KEY, \
|
||||
.KeySlotNumber = TNGLORA_F_NWK_S_INT_KEY_SLOT, \
|
||||
.KeyBlockIndex = TNGLORA_REMAINING_KEYS_BLOCK_INDEX, \
|
||||
}, \
|
||||
{ \
|
||||
/*! \
|
||||
* Serving Network session integrity key \
|
||||
* WARNING: NOT USED FOR 1.0.x DEVICES. MUST BE THE SAME AS \ref LORAWAN_F_NWK_S_INT_KEY \
|
||||
*/ \
|
||||
.KeyID = S_NWK_S_INT_KEY, \
|
||||
.KeySlotNumber = TNGLORA_S_NWK_S_INT_KEY_SLOT, \
|
||||
.KeyBlockIndex = TNGLORA_REMAINING_KEYS_BLOCK_INDEX, \
|
||||
}, \
|
||||
{ \
|
||||
/*! \
|
||||
* Network session encryption key \
|
||||
* WARNING: NOT USED FOR 1.0.x DEVICES. MUST BE THE SAME AS \ref LORAWAN_F_NWK_S_INT_KEY \
|
||||
*/ \
|
||||
.KeyID = NWK_S_ENC_KEY, \
|
||||
.KeySlotNumber = TNGLORA_NWK_S_ENC_KEY_SLOT, \
|
||||
.KeyBlockIndex = TNGLORA_REMAINING_KEYS_BLOCK_INDEX, \
|
||||
}, \
|
||||
{ \
|
||||
/*! \
|
||||
* Application session key \
|
||||
*/ \
|
||||
.KeyID = APP_S_KEY, \
|
||||
.KeySlotNumber = TNGLORA_APP_S_KEY_SLOT, \
|
||||
.KeyBlockIndex = TNGLORA_REMAINING_KEYS_BLOCK_INDEX, \
|
||||
}, \
|
||||
{ \
|
||||
/*! \
|
||||
* Multicast root key (Dynamically updated) \
|
||||
* WARNING: NOT CURRENTLY SUPPORTED BY ATECC608A \
|
||||
* TODO: Add support \
|
||||
*/ \
|
||||
.KeyID = MC_ROOT_KEY, \
|
||||
.KeySlotNumber = 0, \
|
||||
.KeyBlockIndex = 0, \
|
||||
}, \
|
||||
{ \
|
||||
/*! \
|
||||
* Multicast key encryption key (Dynamically updated) \
|
||||
* WARNING: NOT CURRENTLY SUPPORTED BY ATECC608A \
|
||||
* TODO: Add support \
|
||||
*/ \
|
||||
.KeyID = MC_KE_KEY, \
|
||||
.KeySlotNumber = 0, \
|
||||
.KeyBlockIndex = 0, \
|
||||
}, \
|
||||
{ \
|
||||
/*! \
|
||||
* Multicast group #0 root key (Dynamically updated) \
|
||||
* WARNING: NOT CURRENTLY SUPPORTED BY ATECC608A \
|
||||
* TODO: Add support \
|
||||
*/ \
|
||||
.KeyID = MC_KEY_0, \
|
||||
.KeySlotNumber = 0, \
|
||||
.KeyBlockIndex = 0, \
|
||||
}, \
|
||||
{ \
|
||||
/*! \
|
||||
* Multicast group #0 application session key (Dynamically updated) \
|
||||
*/ \
|
||||
.KeyID = MC_APP_S_KEY_0, \
|
||||
.KeySlotNumber = TNGLORA_MC_APP_S_KEY_0_SLOT, \
|
||||
.KeyBlockIndex = TNGLORA_REMAINING_KEYS_BLOCK_INDEX, \
|
||||
}, \
|
||||
{ \
|
||||
/*! \
|
||||
* Multicast group #0 network session key (Dynamically updated) \
|
||||
*/ \
|
||||
.KeyID = MC_NWK_S_KEY_0, \
|
||||
.KeySlotNumber = TNGLORA_MC_NWK_S_KEY_0_SLOT, \
|
||||
.KeyBlockIndex = TNGLORA_REMAINING_KEYS_BLOCK_INDEX, \
|
||||
}, \
|
||||
{ \
|
||||
/*! \
|
||||
* All zeros key. (ClassB usage)(constant) \
|
||||
* WARNING: NOT CURRENTLY SUPPORTED BY ATECC608A \
|
||||
* TODO: Add support \
|
||||
* SE should provide a slot for SLOT_RAND_ZERO_KEY. \
|
||||
* .KeyValue = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
|
||||
* 0x00, 0x00 } \
|
||||
*/ \
|
||||
.KeyID = SLOT_RAND_ZERO_KEY, \
|
||||
.KeySlotNumber = 0, \
|
||||
.KeyBlockIndex = 0, \
|
||||
}, \
|
||||
},
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // __SOFT_SE_IDENTITY_H__
|
@@ -23,6 +23,11 @@
|
||||
#ifndef __GPIO_IOE_H__
|
||||
#define __GPIO_IOE_H__
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
#include <stdint.h>
|
||||
#include "gpio.h"
|
||||
|
||||
@@ -95,4 +100,8 @@ uint32_t GpioIoeRead( Gpio_t *obj );
|
||||
*/
|
||||
void GpioIoeInterruptHandler( void );
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // __GPIO_IOE_H__
|
||||
|
@@ -0,0 +1,39 @@
|
||||
/*!
|
||||
* \file soft-se-hal.h
|
||||
*
|
||||
* \brief Secure Element hardware abstraction layer implementation
|
||||
*
|
||||
* \copyright Revised BSD License, see section \ref LICENSE.
|
||||
*
|
||||
* \code
|
||||
* ______ _
|
||||
* / _____) _ | |
|
||||
* ( (____ _____ ____ _| |_ _____ ____| |__
|
||||
* \____ \| ___ | (_ _) ___ |/ ___) _ \
|
||||
* _____) ) ____| | | || |_| ____( (___| | | |
|
||||
* (______/|_____)_|_|_| \__)_____)\____)_| |_|
|
||||
* (C)2020 Semtech
|
||||
*
|
||||
* ___ _____ _ ___ _ _____ ___ ___ ___ ___
|
||||
* / __|_ _/_\ / __| |/ / __/ _ \| _ \/ __| __|
|
||||
* \__ \ | |/ _ \ (__| ' <| _| (_) | / (__| _|
|
||||
* |___/ |_/_/ \_\___|_|\_\_| \___/|_|_\\___|___|
|
||||
* embedded.connectivity.solutions===============
|
||||
*
|
||||
* \endcode
|
||||
*
|
||||
*/
|
||||
#include "board.h"
|
||||
#include "radio.h"
|
||||
|
||||
#include "lr1110-se-hal.h"
|
||||
|
||||
void LR1110SeHalGetUniqueId( uint8_t *id )
|
||||
{
|
||||
BoardGetUniqueId( id );
|
||||
}
|
||||
|
||||
uint32_t LR1110SeHalGetRandomNumber( void )
|
||||
{
|
||||
return Radio.Random( );
|
||||
}
|
@@ -0,0 +1,56 @@
|
||||
/*!
|
||||
* \file lr1110-se-hal.h
|
||||
*
|
||||
* \brief Secure Element hardware abstraction layer
|
||||
*
|
||||
* \copyright Revised BSD License, see section \ref LICENSE.
|
||||
*
|
||||
* \code
|
||||
* ______ _
|
||||
* / _____) _ | |
|
||||
* ( (____ _____ ____ _| |_ _____ ____| |__
|
||||
* \____ \| ___ | (_ _) ___ |/ ___) _ \
|
||||
* _____) ) ____| | | || |_| ____( (___| | | |
|
||||
* (______/|_____)_|_|_| \__)_____)\____)_| |_|
|
||||
* (C)2020 Semtech
|
||||
*
|
||||
* ___ _____ _ ___ _ _____ ___ ___ ___ ___
|
||||
* / __|_ _/_\ / __| |/ / __/ _ \| _ \/ __| __|
|
||||
* \__ \ | |/ _ \ (__| ' <| _| (_) | / (__| _|
|
||||
* |___/ |_/_/ \_\___|_|\_\_| \___/|_|_\\___|___|
|
||||
* embedded.connectivity.solutions===============
|
||||
*
|
||||
* \endcode
|
||||
*
|
||||
*/
|
||||
#ifndef __LR1110_SE_HAL_H__
|
||||
#define __LR1110_SE_HAL_H__
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
/*!
|
||||
* \brief Get a 64 bits unique ID
|
||||
*
|
||||
* \param [IN] id Pointer to an array that will contain the Unique ID
|
||||
*/
|
||||
void LR1110SeHalGetUniqueId( uint8_t *id );
|
||||
|
||||
/*!
|
||||
* \brief Get a random number
|
||||
*
|
||||
* \remark The number SHALL NOT be generated using a pseudo random number
|
||||
* generator
|
||||
* \retval number 32 bit random value
|
||||
*/
|
||||
uint32_t LR1110SeHalGetRandomNumber( void );
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // __LR1110_SE_HAL_H__
|
@@ -0,0 +1,506 @@
|
||||
/*!
|
||||
* \file lr1110-se.c
|
||||
*
|
||||
* \brief LR1110 Secure Element hardware implementation
|
||||
*
|
||||
* \copyright Revised BSD License, see section \ref LICENSE.
|
||||
*
|
||||
* \code
|
||||
* ______ _
|
||||
* / _____) _ | |
|
||||
* ( (____ _____ ____ _| |_ _____ ____| |__
|
||||
* \____ \| ___ | (_ _) ___ |/ ___) _ \
|
||||
* _____) ) ____| | | || |_| ____( (___| | | |
|
||||
* (______/|_____)_|_|_| \__)_____)\____)_| |_|
|
||||
* (C)2019-2019 Semtech
|
||||
*
|
||||
* \endcode
|
||||
*
|
||||
* \authors Semtech WSP Applications Team
|
||||
*/
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include "lr1110.h"
|
||||
#include "lr1110_system.h"
|
||||
#include "lr1110_crypto_engine.h"
|
||||
|
||||
#include "secure-element.h"
|
||||
#include "se-identity.h"
|
||||
#include "lr1110-se-hal.h"
|
||||
|
||||
/*!
|
||||
* Number of supported crypto keys
|
||||
*/
|
||||
#define NUM_OF_KEYS 23
|
||||
|
||||
/*
|
||||
* CMAC/AES Message Integrity Code (MIC) Block B0 size
|
||||
*/
|
||||
#define MIC_BLOCK_BX_SIZE 16
|
||||
|
||||
/*
|
||||
* Maximum size of the message that can be handled by the crypto operations
|
||||
*/
|
||||
#define CRYPTO_MAXMESSAGE_SIZE 256
|
||||
|
||||
/*
|
||||
* Maximum size of the buffer for crypto operations
|
||||
*/
|
||||
#define CRYPTO_BUFFER_SIZE CRYPTO_MAXMESSAGE_SIZE + MIC_BLOCK_BX_SIZE
|
||||
|
||||
/*!
|
||||
* Secure-element LoRaWAN identity local storage.
|
||||
*/
|
||||
typedef struct sSecureElementNvCtx
|
||||
{
|
||||
/*
|
||||
* DevEUI storage
|
||||
*/
|
||||
uint8_t DevEui[SE_EUI_SIZE];
|
||||
/*
|
||||
* Join EUI storage
|
||||
*/
|
||||
uint8_t JoinEui[SE_EUI_SIZE];
|
||||
/*
|
||||
* PIN of the LR1110
|
||||
*/
|
||||
uint8_t Pin[SE_PIN_SIZE];
|
||||
} SecureElementNvCtx_t;
|
||||
|
||||
static SecureElementNvCtx_t SeContext = {
|
||||
/*!
|
||||
* end-device IEEE EUI (big endian)
|
||||
*
|
||||
* \remark In this application the value is automatically generated by calling
|
||||
* BoardGetUniqueId function
|
||||
*/
|
||||
.DevEui = LORAWAN_DEVICE_EUI,
|
||||
/*!
|
||||
* App/Join server IEEE EUI (big endian)
|
||||
*/
|
||||
.JoinEui = LORAWAN_JOIN_EUI,
|
||||
/*!
|
||||
* Secure-element pin (big endian)
|
||||
*/
|
||||
.Pin = SECURE_ELEMENT_PIN,
|
||||
};
|
||||
|
||||
static SecureElementNvmEvent SeNvmCtxChanged;
|
||||
|
||||
/*!
|
||||
* LR1110 radio context
|
||||
*/
|
||||
extern lr1110_t LR1110;
|
||||
|
||||
/*!
|
||||
* Converts key ids from SecureElement to LR1110
|
||||
*
|
||||
* \param [IN] key_id SecureElement key id to be converted
|
||||
*
|
||||
* \retval key_id Converted LR1110 key id
|
||||
*/
|
||||
static lr1110_crypto_keys_idx_t convert_key_id_from_se_to_lr1110( KeyIdentifier_t key_id );
|
||||
|
||||
/*!
|
||||
* Dummy callback in case if the user provides NULL function pointer
|
||||
*/
|
||||
static void DummyCB( void )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
SecureElementStatus_t SecureElementInit( SecureElementNvmEvent seNvmCtxChanged )
|
||||
{
|
||||
lr1110_crypto_status_t status = LR1110_CRYPTO_STATUS_ERROR;
|
||||
|
||||
// Assign callback
|
||||
if( seNvmCtxChanged != 0 )
|
||||
{
|
||||
SeNvmCtxChanged = seNvmCtxChanged;
|
||||
}
|
||||
else
|
||||
{
|
||||
SeNvmCtxChanged = DummyCB;
|
||||
}
|
||||
|
||||
lr1110_crypto_restore_from_flash( &LR1110, &status );
|
||||
|
||||
#if defined( SECURE_ELEMENT_PRE_PROVISIONED )
|
||||
// Read LR1110 pre-provisioned identity
|
||||
lr1110_system_read_uid( &LR1110, SeContext.DevEui );
|
||||
lr1110_system_read_join_eui( &LR1110, SeContext.JoinEui );
|
||||
lr1110_system_read_pin( &LR1110, SeContext.Pin );
|
||||
#else
|
||||
#if( STATIC_DEVICE_EUI == 0 )
|
||||
// Get a DevEUI from MCU unique ID
|
||||
LR1110SeHalGetUniqueId( SeContext.DevEui );
|
||||
#endif
|
||||
#endif
|
||||
|
||||
SeNvmCtxChanged( );
|
||||
|
||||
return ( SecureElementStatus_t ) status;
|
||||
}
|
||||
|
||||
SecureElementStatus_t SecureElementRestoreNvmCtx( void* seNvmCtx )
|
||||
{
|
||||
lr1110_crypto_status_t status = LR1110_CRYPTO_STATUS_ERROR;
|
||||
|
||||
if( seNvmCtx == NULL )
|
||||
{
|
||||
return SECURE_ELEMENT_ERROR_NPE;
|
||||
}
|
||||
|
||||
// Restore lr1110 crypto context
|
||||
lr1110_crypto_restore_from_flash( &LR1110, &status );
|
||||
|
||||
// Restore nvm context
|
||||
memcpy1( ( uint8_t* ) &SeContext, ( uint8_t* ) seNvmCtx, sizeof( SeContext ) );
|
||||
|
||||
return ( SecureElementStatus_t ) status;
|
||||
}
|
||||
|
||||
void* SecureElementGetNvmCtx( size_t* seNvmCtxSize )
|
||||
{
|
||||
*seNvmCtxSize = sizeof( SeContext );
|
||||
return &SeContext;
|
||||
}
|
||||
|
||||
SecureElementStatus_t SecureElementSetKey( KeyIdentifier_t keyID, uint8_t* key )
|
||||
{
|
||||
if( key == NULL )
|
||||
{
|
||||
return SECURE_ELEMENT_ERROR_NPE;
|
||||
}
|
||||
|
||||
SecureElementStatus_t status = SECURE_ELEMENT_ERROR;
|
||||
|
||||
if( ( keyID == MC_KEY_0 ) || ( keyID == MC_KEY_1 ) || ( keyID == MC_KEY_2 ) || ( keyID == MC_KEY_3 ) )
|
||||
{ // Decrypt the key if its a Mckey
|
||||
|
||||
lr1110_crypto_derive_and_store_key( &LR1110, ( lr1110_crypto_status_t* ) &status,
|
||||
convert_key_id_from_se_to_lr1110( MC_KE_KEY ),
|
||||
convert_key_id_from_se_to_lr1110( keyID ), key );
|
||||
|
||||
if( status == SECURE_ELEMENT_SUCCESS )
|
||||
{
|
||||
lr1110_crypto_store_to_flash( &LR1110, ( lr1110_crypto_status_t* ) &status );
|
||||
}
|
||||
return status;
|
||||
}
|
||||
else
|
||||
{
|
||||
lr1110_crypto_set_key( &LR1110, ( lr1110_crypto_status_t* ) &status, convert_key_id_from_se_to_lr1110( keyID ),
|
||||
key );
|
||||
if( status == SECURE_ELEMENT_SUCCESS )
|
||||
{
|
||||
lr1110_crypto_store_to_flash( &LR1110, ( lr1110_crypto_status_t* ) &status );
|
||||
}
|
||||
return status;
|
||||
}
|
||||
}
|
||||
|
||||
SecureElementStatus_t SecureElementComputeAesCmac( uint8_t* micBxBuffer, uint8_t* buffer, uint16_t size,
|
||||
KeyIdentifier_t keyID, uint32_t* cmac )
|
||||
{
|
||||
SecureElementStatus_t status = SECURE_ELEMENT_ERROR;
|
||||
uint16_t localSize = size;
|
||||
uint8_t* localbuffer = buffer;
|
||||
|
||||
if( micBxBuffer != NULL )
|
||||
{
|
||||
uint8_t micBuff[CRYPTO_BUFFER_SIZE];
|
||||
|
||||
memset1( micBuff, 0, CRYPTO_BUFFER_SIZE );
|
||||
|
||||
memcpy1( micBuff, micBxBuffer, MIC_BLOCK_BX_SIZE );
|
||||
memcpy1( ( micBuff + MIC_BLOCK_BX_SIZE ), buffer, size );
|
||||
localSize += MIC_BLOCK_BX_SIZE;
|
||||
localbuffer = micBuff;
|
||||
}
|
||||
|
||||
lr1110_crypto_compute_aes_cmac( &LR1110, ( lr1110_crypto_status_t* ) &status,
|
||||
convert_key_id_from_se_to_lr1110( keyID ), localbuffer, localSize,
|
||||
( uint8_t* ) cmac );
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
SecureElementStatus_t SecureElementVerifyAesCmac( uint8_t* buffer, uint16_t size, uint32_t expectedCmac,
|
||||
KeyIdentifier_t keyID )
|
||||
{
|
||||
SecureElementStatus_t status = SECURE_ELEMENT_ERROR;
|
||||
|
||||
if( buffer == NULL )
|
||||
{
|
||||
return SECURE_ELEMENT_ERROR_NPE;
|
||||
}
|
||||
|
||||
lr1110_crypto_verify_aes_cmac( &LR1110, ( lr1110_crypto_status_t* ) &status,
|
||||
convert_key_id_from_se_to_lr1110( keyID ), buffer, size,
|
||||
( uint8_t* ) &expectedCmac );
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
SecureElementStatus_t SecureElementAesEncrypt( uint8_t* buffer, uint16_t size, KeyIdentifier_t keyID,
|
||||
uint8_t* encBuffer )
|
||||
{
|
||||
SecureElementStatus_t status = SECURE_ELEMENT_ERROR;
|
||||
|
||||
if( ( buffer == NULL ) || ( encBuffer == NULL ) )
|
||||
{
|
||||
return SECURE_ELEMENT_ERROR_NPE;
|
||||
}
|
||||
|
||||
lr1110_crypto_aes_encrypt_01( &LR1110, ( lr1110_crypto_status_t* ) &status,
|
||||
convert_key_id_from_se_to_lr1110( keyID ), buffer, size, encBuffer );
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
SecureElementStatus_t SecureElementDeriveAndStoreKey( Version_t version, uint8_t* input, KeyIdentifier_t rootKeyID,
|
||||
KeyIdentifier_t targetKeyID )
|
||||
{
|
||||
SecureElementStatus_t status = SECURE_ELEMENT_ERROR;
|
||||
|
||||
if( input == NULL )
|
||||
{
|
||||
return SECURE_ELEMENT_ERROR_NPE;
|
||||
}
|
||||
|
||||
lr1110_crypto_derive_and_store_key( &LR1110, ( lr1110_crypto_status_t* ) &status,
|
||||
convert_key_id_from_se_to_lr1110( rootKeyID ),
|
||||
convert_key_id_from_se_to_lr1110( targetKeyID ), input );
|
||||
|
||||
lr1110_crypto_store_to_flash( &LR1110, ( lr1110_crypto_status_t* ) &status );
|
||||
return status;
|
||||
}
|
||||
|
||||
SecureElementStatus_t SecureElementProcessJoinAccept( JoinReqIdentifier_t joinReqType, uint8_t* joinEui,
|
||||
uint16_t devNonce, uint8_t* encJoinAccept,
|
||||
uint8_t encJoinAcceptSize, uint8_t* decJoinAccept,
|
||||
uint8_t* versionMinor )
|
||||
{
|
||||
SecureElementStatus_t status = SECURE_ELEMENT_ERROR;
|
||||
|
||||
if( ( encJoinAccept == NULL ) || ( decJoinAccept == NULL ) || ( versionMinor == NULL ) )
|
||||
{
|
||||
return SECURE_ELEMENT_ERROR_NPE;
|
||||
}
|
||||
|
||||
// Check that frame size isn't bigger than a JoinAccept with CFList size
|
||||
if( encJoinAcceptSize > LORAMAC_JOIN_ACCEPT_FRAME_MAX_SIZE )
|
||||
{
|
||||
return SECURE_ELEMENT_ERROR_BUF_SIZE;
|
||||
}
|
||||
|
||||
// Determine decryption key
|
||||
KeyIdentifier_t encKeyID = NWK_KEY;
|
||||
|
||||
if( joinReqType != JOIN_REQ )
|
||||
{
|
||||
encKeyID = J_S_ENC_KEY;
|
||||
}
|
||||
|
||||
// - Header buffer to be used for MIC computation
|
||||
// - LoRaWAN 1.0.x : micHeader = [MHDR(1)]
|
||||
// - LoRaWAN 1.1.x : micHeader = [JoinReqType(1), JoinEUI(8), DevNonce(2), MHDR(1)]
|
||||
|
||||
// Try first to process LoRaWAN 1.0.x JoinAccept
|
||||
uint8_t micHeader10[1] = { 0x20 };
|
||||
|
||||
// cmac = aes128_cmac(NwkKey, MHDR | JoinNonce | NetID | DevAddr | DLSettings | RxDelay | CFList |
|
||||
// CFListType)
|
||||
lr1110_crypto_process_join_accept(
|
||||
&LR1110, ( lr1110_crypto_status_t* ) &status, convert_key_id_from_se_to_lr1110( encKeyID ),
|
||||
convert_key_id_from_se_to_lr1110( NWK_KEY ), ( lr1110_crypto_lorawan_version_t ) 0, micHeader10,
|
||||
encJoinAccept + 1, encJoinAcceptSize - 1, decJoinAccept + 1 );
|
||||
|
||||
if( status == SECURE_ELEMENT_SUCCESS )
|
||||
{
|
||||
*versionMinor = ( ( decJoinAccept[11] & 0x80 ) == 0x80 ) ? 1 : 0;
|
||||
if( *versionMinor == 0 )
|
||||
{
|
||||
// Network server is operating according to LoRaWAN 1.0.x
|
||||
return SECURE_ELEMENT_SUCCESS;
|
||||
}
|
||||
}
|
||||
|
||||
#if( USE_LRWAN_1_1_X_CRYPTO == 1 )
|
||||
// 1.0.x trial failed. Trying to process LoRaWAN 1.1.x JoinAccept
|
||||
uint8_t micHeader11[JOIN_ACCEPT_MIC_COMPUTATION_OFFSET] = { 0 };
|
||||
uint16_t bufItr = 0;
|
||||
|
||||
// cmac = aes128_cmac(JSIntKey, JoinReqType | JoinEUI | DevNonce | MHDR | JoinNonce | NetID | DevAddr |
|
||||
// DLSettings | RxDelay | CFList | CFListType)
|
||||
micHeader11[bufItr++] = ( uint8_t ) joinReqType;
|
||||
|
||||
memcpyr( micHeader11 + bufItr, joinEui, LORAMAC_JOIN_EUI_FIELD_SIZE );
|
||||
bufItr += LORAMAC_JOIN_EUI_FIELD_SIZE;
|
||||
|
||||
micHeader11[bufItr++] = devNonce & 0xFF;
|
||||
micHeader11[bufItr++] = ( devNonce >> 8 ) & 0xFF;
|
||||
|
||||
micHeader11[bufItr++] = 0x20;
|
||||
|
||||
lr1110_crypto_process_join_accept(
|
||||
&LR1110, ( lr1110_crypto_status_t* ) &status, convert_key_id_from_se_to_lr1110( encKeyID ),
|
||||
convert_key_id_from_se_to_lr1110( J_S_INT_KEY ), ( lr1110_crypto_lorawan_version_t ) 1, micHeader11,
|
||||
encJoinAccept + 1, encJoinAcceptSize - 1, decJoinAccept + 1 );
|
||||
|
||||
if( status == SECURE_ELEMENT_SUCCESS )
|
||||
{
|
||||
*versionMinor = ( ( decJoinAccept[11] & 0x80 ) == 0x80 ) ? 1 : 0;
|
||||
if( *versionMinor == 1 )
|
||||
{
|
||||
// Network server is operating according to LoRaWAN 1.1.x
|
||||
return SECURE_ELEMENT_SUCCESS;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
SecureElementStatus_t SecureElementRandomNumber( uint32_t* randomNum )
|
||||
{
|
||||
if( randomNum == NULL )
|
||||
{
|
||||
return SECURE_ELEMENT_ERROR_NPE;
|
||||
}
|
||||
*randomNum = LR1110SeHalGetRandomNumber( );
|
||||
return SECURE_ELEMENT_SUCCESS;
|
||||
}
|
||||
|
||||
SecureElementStatus_t SecureElementSetDevEui( uint8_t* devEui )
|
||||
{
|
||||
if( devEui == NULL )
|
||||
{
|
||||
return SECURE_ELEMENT_ERROR_NPE;
|
||||
}
|
||||
memcpy1( SeContext.DevEui, devEui, SE_EUI_SIZE );
|
||||
SeNvmCtxChanged( );
|
||||
return SECURE_ELEMENT_SUCCESS;
|
||||
}
|
||||
|
||||
uint8_t* SecureElementGetDevEui( void )
|
||||
{
|
||||
return SeContext.DevEui;
|
||||
}
|
||||
|
||||
SecureElementStatus_t SecureElementSetJoinEui( uint8_t* joinEui )
|
||||
{
|
||||
if( joinEui == NULL )
|
||||
{
|
||||
return SECURE_ELEMENT_ERROR_NPE;
|
||||
}
|
||||
memcpy1( SeContext.JoinEui, joinEui, SE_EUI_SIZE );
|
||||
SeNvmCtxChanged( );
|
||||
return SECURE_ELEMENT_SUCCESS;
|
||||
}
|
||||
|
||||
uint8_t* SecureElementGetJoinEui( void )
|
||||
{
|
||||
return SeContext.JoinEui;
|
||||
}
|
||||
|
||||
SecureElementStatus_t SecureElementSetPin( uint8_t* pin )
|
||||
{
|
||||
if( pin == NULL )
|
||||
{
|
||||
return SECURE_ELEMENT_ERROR_NPE;
|
||||
}
|
||||
|
||||
memcpy1( SeContext.Pin, pin, SE_PIN_SIZE );
|
||||
SeNvmCtxChanged( );
|
||||
return SECURE_ELEMENT_SUCCESS;
|
||||
}
|
||||
|
||||
uint8_t* SecureElementGetPin( void )
|
||||
{
|
||||
return SeContext.Pin;
|
||||
}
|
||||
|
||||
static lr1110_crypto_keys_idx_t convert_key_id_from_se_to_lr1110( KeyIdentifier_t key_id )
|
||||
{
|
||||
lr1110_crypto_keys_idx_t id = LR1110_CRYPTO_KEYS_IDX_GP0;
|
||||
|
||||
switch( key_id )
|
||||
{
|
||||
case APP_KEY:
|
||||
id = LR1110_CRYPTO_KEYS_IDX_APP_KEY;
|
||||
break;
|
||||
case NWK_KEY:
|
||||
id = LR1110_CRYPTO_KEYS_IDX_NWK_KEY;
|
||||
break;
|
||||
case J_S_INT_KEY:
|
||||
id = LR1110_CRYPTO_KEYS_IDX_J_S_INT_KEY;
|
||||
break;
|
||||
case J_S_ENC_KEY:
|
||||
id = LR1110_CRYPTO_KEYS_IDX_J_S_ENC_KEY;
|
||||
break;
|
||||
case F_NWK_S_INT_KEY:
|
||||
id = LR1110_CRYPTO_KEYS_IDX_F_NWK_S_INT_KEY;
|
||||
break;
|
||||
case S_NWK_S_INT_KEY:
|
||||
id = LR1110_CRYPTO_KEYS_IDX_S_NWK_S_INT_KEY;
|
||||
break;
|
||||
case NWK_S_ENC_KEY:
|
||||
id = LR1110_CRYPTO_KEYS_IDX_NWK_S_ENC_KEY;
|
||||
break;
|
||||
case APP_S_KEY:
|
||||
id = LR1110_CRYPTO_KEYS_IDX_APP_S_KEY;
|
||||
break;
|
||||
case MC_ROOT_KEY:
|
||||
id = LR1110_CRYPTO_KEYS_IDX_GP_KE_KEY_5;
|
||||
break;
|
||||
case MC_KE_KEY:
|
||||
id = LR1110_CRYPTO_KEYS_IDX_GP_KE_KEY_4;
|
||||
break;
|
||||
case MC_KEY_0:
|
||||
id = LR1110_CRYPTO_KEYS_IDX_GP_KE_KEY_0;
|
||||
break;
|
||||
case MC_APP_S_KEY_0:
|
||||
id = LR1110_CRYPTO_KEYS_IDX_MC_APP_S_KEY_0;
|
||||
break;
|
||||
case MC_NWK_S_KEY_0:
|
||||
id = LR1110_CRYPTO_KEYS_IDX_MC_NWK_S_KEY_0;
|
||||
break;
|
||||
case MC_KEY_1:
|
||||
id = LR1110_CRYPTO_KEYS_IDX_GP_KE_KEY_1;
|
||||
break;
|
||||
case MC_APP_S_KEY_1:
|
||||
id = LR1110_CRYPTO_KEYS_IDX_MC_APP_S_KEY_1;
|
||||
break;
|
||||
case MC_NWK_S_KEY_1:
|
||||
id = LR1110_CRYPTO_KEYS_IDX_MC_NWK_S_KEY_1;
|
||||
break;
|
||||
case MC_KEY_2:
|
||||
id = LR1110_CRYPTO_KEYS_IDX_GP_KE_KEY_2;
|
||||
break;
|
||||
case MC_APP_S_KEY_2:
|
||||
id = LR1110_CRYPTO_KEYS_IDX_MC_APP_S_KEY_2;
|
||||
break;
|
||||
case MC_NWK_S_KEY_2:
|
||||
id = LR1110_CRYPTO_KEYS_IDX_MC_NWK_S_KEY_2;
|
||||
break;
|
||||
case MC_KEY_3:
|
||||
id = LR1110_CRYPTO_KEYS_IDX_GP_KE_KEY_3;
|
||||
break;
|
||||
case MC_APP_S_KEY_3:
|
||||
id = LR1110_CRYPTO_KEYS_IDX_MC_APP_S_KEY_3;
|
||||
break;
|
||||
case MC_NWK_S_KEY_3:
|
||||
id = LR1110_CRYPTO_KEYS_IDX_MC_NWK_S_KEY_3;
|
||||
break;
|
||||
case SLOT_RAND_ZERO_KEY:
|
||||
id = LR1110_CRYPTO_KEYS_IDX_GP0;
|
||||
break;
|
||||
default:
|
||||
id = LR1110_CRYPTO_KEYS_IDX_GP1;
|
||||
break;
|
||||
}
|
||||
return id;
|
||||
}
|
@@ -0,0 +1,102 @@
|
||||
/*!
|
||||
* \file se-identity.h
|
||||
*
|
||||
* \brief Secure Element identity and keys
|
||||
*
|
||||
* \copyright Revised BSD License, see section \ref LICENSE.
|
||||
*
|
||||
* \code
|
||||
* ______ _
|
||||
* / _____) _ | |
|
||||
* ( (____ _____ ____ _| |_ _____ ____| |__
|
||||
* \____ \| ___ | (_ _) ___ |/ ___) _ \
|
||||
* _____) ) ____| | | || |_| ____( (___| | | |
|
||||
* (______/|_____)_|_|_| \__)_____)\____)_| |_|
|
||||
* (C)2020 Semtech
|
||||
*
|
||||
* ___ _____ _ ___ _ _____ ___ ___ ___ ___
|
||||
* / __|_ _/_\ / __| |/ / __/ _ \| _ \/ __| __|
|
||||
* \__ \ | |/ _ \ (__| ' <| _| (_) | / (__| _|
|
||||
* |___/ |_/_/ \_\___|_|\_\_| \___/|_|_\\___|___|
|
||||
* embedded.connectivity.solutions===============
|
||||
*
|
||||
* \endcode
|
||||
*
|
||||
*/
|
||||
#ifndef __SOFT_SE_IDENTITY_H__
|
||||
#define __SOFT_SE_IDENTITY_H__
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*!
|
||||
******************************************************************************
|
||||
********************************** WARNING ***********************************
|
||||
******************************************************************************
|
||||
The secure-element implementation supports both 1.0.x and 1.1.x LoRaWAN
|
||||
versions of the specification.
|
||||
Thus it has been decided to use the 1.1.x keys and EUI name definitions.
|
||||
The below table shows the names equivalence between versions:
|
||||
+---------------------+-------------------------+
|
||||
| 1.0.x | 1.1.x |
|
||||
+=====================+=========================+
|
||||
| LORAWAN_DEVICE_EUI | LORAWAN_DEVICE_EUI |
|
||||
+---------------------+-------------------------+
|
||||
| LORAWAN_APP_EUI | LORAWAN_JOIN_EUI |
|
||||
+---------------------+-------------------------+
|
||||
| LORAWAN_GEN_APP_KEY | LORAWAN_APP_KEY |
|
||||
+---------------------+-------------------------+
|
||||
| LORAWAN_APP_KEY | LORAWAN_NWK_KEY |
|
||||
+---------------------+-------------------------+
|
||||
| LORAWAN_NWK_S_KEY | LORAWAN_F_NWK_S_INT_KEY |
|
||||
+---------------------+-------------------------+
|
||||
| LORAWAN_NWK_S_KEY | LORAWAN_S_NWK_S_INT_KEY |
|
||||
+---------------------+-------------------------+
|
||||
| LORAWAN_NWK_S_KEY | LORAWAN_NWK_S_ENC_KEY |
|
||||
+---------------------+-------------------------+
|
||||
| LORAWAN_APP_S_KEY | LORAWAN_APP_S_KEY |
|
||||
+---------------------+-------------------------+
|
||||
******************************************************************************
|
||||
******************************************************************************
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
/*!
|
||||
* When set to 1 DevEui is LORAWAN_DEVICE_EUI
|
||||
* When set to 0 DevEui is automatically set with a value provided by MCU platform
|
||||
*/
|
||||
#define STATIC_DEVICE_EUI 0
|
||||
|
||||
/*!
|
||||
* end-device IEEE EUI (big endian)
|
||||
*/
|
||||
#define LORAWAN_DEVICE_EUI { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }
|
||||
|
||||
/*!
|
||||
* App/Join server IEEE EUI (big endian)
|
||||
*/
|
||||
#define LORAWAN_JOIN_EUI { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }
|
||||
|
||||
/*!
|
||||
* Secure-element pin
|
||||
*/
|
||||
#define SECURE_ELEMENT_PIN { 0x00, 0x00, 0x00, 0x00 }
|
||||
|
||||
/*!
|
||||
* When set to 1 DevAddr is LORAWAN_DEVICE_ADDRESS
|
||||
* When set to 0 DevAddr is automatically set with a value provided by a pseudo
|
||||
* random generator seeded with a value provided by the MCU platform
|
||||
*/
|
||||
#define STATIC_DEVICE_ADDRESS 0
|
||||
|
||||
/*!
|
||||
* Device address on the network (big endian)
|
||||
*/
|
||||
#define LORAWAN_DEVICE_ADDRESS ( uint32_t )0x00000000
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // __SOFT_SE_IDENTITY_H__
|
@@ -43,21 +43,21 @@ uint8_t MAG3110Init( void )
|
||||
MAG3110Read( MAG3110_ID, ®Val );
|
||||
if( regVal != 0xC4 ) // Fixed Device ID Number = 0xC4
|
||||
{
|
||||
return LORA_FAIL;
|
||||
return FAIL;
|
||||
}
|
||||
|
||||
MAG3110Reset( );
|
||||
}
|
||||
return LORA_SUCCESS;
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
uint8_t MAG3110Reset( void )
|
||||
{
|
||||
if( MAG3110Write( 0x11, 0x10 ) == LORA_SUCCESS ) // Reset the MAG3110 with CTRL_REG2
|
||||
if( MAG3110Write( 0x11, 0x10 ) == SUCCESS ) // Reset the MAG3110 with CTRL_REG2
|
||||
{
|
||||
return LORA_SUCCESS;
|
||||
return SUCCESS;
|
||||
}
|
||||
return LORA_FAIL;
|
||||
return FAIL;
|
||||
}
|
||||
|
||||
uint8_t MAG3110Write( uint8_t addr, uint8_t data )
|
||||
|
@@ -23,6 +23,11 @@
|
||||
#ifndef __MAG3110_H__
|
||||
#define __MAG3110_H__
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
/*!
|
||||
@@ -38,14 +43,14 @@
|
||||
/*!
|
||||
* \brief Initializes the device
|
||||
*
|
||||
* \retval status [LORA_SUCCESS, LORA_FAIL]
|
||||
* \retval status [SUCCESS, FAIL]
|
||||
*/
|
||||
uint8_t MAG3110Init( void );
|
||||
|
||||
/*!
|
||||
* \brief Resets the device
|
||||
*
|
||||
* \retval status [LORA_SUCCESS, LORA_FAIL]
|
||||
* \retval status [SUCCESS, FAIL]
|
||||
*/
|
||||
uint8_t MAG3110Reset( void );
|
||||
|
||||
@@ -54,7 +59,7 @@ uint8_t MAG3110Reset( void );
|
||||
*
|
||||
* \param [IN]: addr
|
||||
* \param [IN]: data
|
||||
* \retval status [LORA_SUCCESS, LORA_FAIL]
|
||||
* \retval status [SUCCESS, FAIL]
|
||||
*/
|
||||
uint8_t MAG3110Write( uint8_t addr, uint8_t data );
|
||||
|
||||
@@ -64,7 +69,7 @@ uint8_t MAG3110Write( uint8_t addr, uint8_t data );
|
||||
* \param [IN]: addr
|
||||
* \param [IN]: data
|
||||
* \param [IN]: size
|
||||
* \retval status [LORA_SUCCESS, LORA_FAIL]
|
||||
* \retval status [SUCCESS, FAIL]
|
||||
*/
|
||||
uint8_t MAG3110WriteBuffer( uint8_t addr, uint8_t *data, uint8_t size );
|
||||
|
||||
@@ -73,7 +78,7 @@ uint8_t MAG3110WriteBuffer( uint8_t addr, uint8_t *data, uint8_t size );
|
||||
*
|
||||
* \param [IN]: addr
|
||||
* \param [OUT]: data
|
||||
* \retval status [LORA_SUCCESS, LORA_FAIL]
|
||||
* \retval status [SUCCESS, FAIL]
|
||||
*/
|
||||
uint8_t MAG3110Read( uint8_t addr, uint8_t *data );
|
||||
|
||||
@@ -83,7 +88,7 @@ uint8_t MAG3110Read( uint8_t addr, uint8_t *data );
|
||||
* \param [IN]: addr
|
||||
* \param [OUT]: data
|
||||
* \param [IN]: size
|
||||
* \retval status [LORA_SUCCESS, LORA_FAIL]
|
||||
* \retval status [SUCCESS, FAIL]
|
||||
*/
|
||||
uint8_t MAG3110ReadBuffer( uint8_t addr, uint8_t *data, uint8_t size );
|
||||
|
||||
@@ -101,4 +106,8 @@ void MAG3110SetDeviceAddr( uint8_t addr );
|
||||
*/
|
||||
uint8_t MAG3110GetDeviceAddr( void );
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // __MAG3110_H__
|
||||
|
@@ -36,7 +36,7 @@ static bool MMA8451Initialized = false;
|
||||
*
|
||||
* \param [IN]: addr
|
||||
* \param [IN]: data
|
||||
* \retval status [LORA_SUCCESS, LORA_FAIL]
|
||||
* \retval status [SUCCESS, FAIL]
|
||||
*/
|
||||
uint8_t MMA8451Write( uint8_t addr, uint8_t data );
|
||||
|
||||
@@ -46,7 +46,7 @@ uint8_t MMA8451Write( uint8_t addr, uint8_t data );
|
||||
* \param [IN]: addr
|
||||
* \param [IN]: data
|
||||
* \param [IN]: size
|
||||
* \retval status [LORA_SUCCESS, LORA_FAIL]
|
||||
* \retval status [SUCCESS, FAIL]
|
||||
*/
|
||||
uint8_t MMA8451WriteBuffer( uint8_t addr, uint8_t *data, uint8_t size );
|
||||
|
||||
@@ -55,7 +55,7 @@ uint8_t MMA8451WriteBuffer( uint8_t addr, uint8_t *data, uint8_t size );
|
||||
*
|
||||
* \param [IN]: addr
|
||||
* \param [OUT]: data
|
||||
* \retval status [LORA_SUCCESS, LORA_FAIL]
|
||||
* \retval status [SUCCESS, FAIL]
|
||||
*/
|
||||
uint8_t MMA8451Read( uint8_t addr, uint8_t *data );
|
||||
|
||||
@@ -65,7 +65,7 @@ uint8_t MMA8451Read( uint8_t addr, uint8_t *data );
|
||||
* \param [IN]: addr
|
||||
* \param [OUT]: data
|
||||
* \param [IN]: size
|
||||
* \retval status [LORA_SUCCESS, LORA_FAIL]
|
||||
* \retval status [SUCCESS, FAIL]
|
||||
*/
|
||||
uint8_t MMA8451ReadBuffer( uint8_t addr, uint8_t *data, uint8_t size );
|
||||
|
||||
@@ -96,7 +96,7 @@ uint8_t MMA8451Init( void )
|
||||
MMA8451Read( MMA8451_ID, ®Val );
|
||||
if( regVal != 0x1A ) // Fixed Device ID Number = 0x1A
|
||||
{
|
||||
return LORA_FAIL;
|
||||
return FAIL;
|
||||
}
|
||||
MMA8451Reset( );
|
||||
|
||||
@@ -105,17 +105,17 @@ uint8_t MMA8451Init( void )
|
||||
MMA8451Write( MMA8451_CTRL_REG3, 0x01 );
|
||||
MMA8451OrientDetect( );
|
||||
}
|
||||
return LORA_SUCCESS;
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
uint8_t MMA8451Reset( )
|
||||
{
|
||||
if( MMA8451Write( 0x2B, 0x40 ) == LORA_SUCCESS ) // Reset the MMA8451 with CTRL_REG2
|
||||
if( MMA8451Write( 0x2B, 0x40 ) == SUCCESS ) // Reset the MMA8451 with CTRL_REG2
|
||||
{
|
||||
return LORA_SUCCESS;
|
||||
return SUCCESS;
|
||||
}
|
||||
return LORA_FAIL;
|
||||
return FAIL;
|
||||
}
|
||||
|
||||
uint8_t MMA8451Write( uint8_t addr, uint8_t data )
|
||||
|
@@ -23,6 +23,11 @@
|
||||
#ifndef __MMA8451_H__
|
||||
#define __MMA8451_H__
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
/*
|
||||
@@ -58,14 +63,14 @@
|
||||
/*!
|
||||
* \brief Initializes the device
|
||||
*
|
||||
* \retval status [LORA_SUCCESS, LORA_FAIL]
|
||||
* \retval status [SUCCESS, FAIL]
|
||||
*/
|
||||
uint8_t MMA8451Init( void );
|
||||
|
||||
/*!
|
||||
* \brief Resets the device
|
||||
*
|
||||
* \retval status [LORA_SUCCESS, LORA_FAIL]
|
||||
* \retval status [SUCCESS, FAIL]
|
||||
*/
|
||||
uint8_t MMA8451Reset( void );
|
||||
|
||||
@@ -83,4 +88,8 @@ void MMA8451OrientDetect( void );
|
||||
*/
|
||||
uint8_t MMA8451GetOrientation( void );
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // __MMA8451_H__
|
||||
|
@@ -52,7 +52,7 @@ typedef enum
|
||||
*
|
||||
* \param [IN]: addr
|
||||
* \param [IN]: data
|
||||
* \retval status [LORA_SUCCESS, LORA_FAIL]
|
||||
* \retval status [SUCCESS, FAIL]
|
||||
*/
|
||||
uint8_t MPL3115Write( uint8_t addr, uint8_t data );
|
||||
|
||||
@@ -62,7 +62,7 @@ uint8_t MPL3115Write( uint8_t addr, uint8_t data );
|
||||
* \param [IN]: addr
|
||||
* \param [IN]: data
|
||||
* \param [IN]: size
|
||||
* \retval status [LORA_SUCCESS, LORA_FAIL]
|
||||
* \retval status [SUCCESS, FAIL]
|
||||
*/
|
||||
uint8_t MPL3115WriteBuffer( uint8_t addr, uint8_t *data, uint8_t size );
|
||||
|
||||
@@ -71,7 +71,7 @@ uint8_t MPL3115WriteBuffer( uint8_t addr, uint8_t *data, uint8_t size );
|
||||
*
|
||||
* \param [IN]: addr
|
||||
* \param [OUT]: data
|
||||
* \retval status [LORA_SUCCESS, LORA_FAIL]
|
||||
* \retval status [SUCCESS, FAIL]
|
||||
*/
|
||||
uint8_t MPL3115Read( uint8_t addr, uint8_t *data );
|
||||
|
||||
@@ -81,7 +81,7 @@ uint8_t MPL3115Read( uint8_t addr, uint8_t *data );
|
||||
* \param [IN]: addr
|
||||
* \param [OUT]: data
|
||||
* \param [IN]: size
|
||||
* \retval status [LORA_SUCCESS, LORA_FAIL]
|
||||
* \retval status [SUCCESS, FAIL]
|
||||
*/
|
||||
uint8_t MPL3115ReadBuffer( uint8_t addr, uint8_t *data, uint8_t size );
|
||||
|
||||
@@ -141,24 +141,24 @@ uint8_t MPL3115Init( void )
|
||||
MPL3115Read( MPL3115_ID, ®Val );
|
||||
if( regVal != 0xC4 )
|
||||
{
|
||||
return LORA_FAIL;
|
||||
return FAIL;
|
||||
}
|
||||
|
||||
MPL3115Write( PT_DATA_CFG_REG, DREM | PDEFE | TDEFE ); // Enable data ready flags for pressure and temperature )
|
||||
MPL3115Write( CTRL_REG1, ALT | OS_32 | SBYB ); // Set sensor to active state with oversampling ratio 128 (512 ms between samples)
|
||||
MPL3115Initialized = true;
|
||||
}
|
||||
return LORA_SUCCESS;
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
uint8_t MPL3115Reset( void )
|
||||
{
|
||||
// Reset all registers to POR values
|
||||
if( MPL3115Write( CTRL_REG1, RST ) == LORA_SUCCESS )
|
||||
if( MPL3115Write( CTRL_REG1, RST ) == SUCCESS )
|
||||
{
|
||||
return LORA_SUCCESS;
|
||||
return SUCCESS;
|
||||
}
|
||||
return LORA_FAIL;
|
||||
return FAIL;
|
||||
}
|
||||
|
||||
uint8_t MPL3115Write( uint8_t addr, uint8_t data )
|
||||
|
@@ -23,6 +23,11 @@
|
||||
#ifndef __MPL3115_H__
|
||||
#define __MPL3115_H__
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
/*
|
||||
@@ -123,14 +128,14 @@
|
||||
/*!
|
||||
* \brief Initializes the device
|
||||
*
|
||||
* \retval status [LORA_SUCCESS, LORA_FAIL]
|
||||
* \retval status [SUCCESS, FAIL]
|
||||
*/
|
||||
uint8_t MPL3115Init( void );
|
||||
|
||||
/*!
|
||||
* \brief Resets the device
|
||||
*
|
||||
* \retval status [LORA_SUCCESS, LORA_FAIL]
|
||||
* \retval status [SUCCESS, FAIL]
|
||||
*/
|
||||
uint8_t MPL3115Reset( void );
|
||||
|
||||
@@ -155,4 +160,8 @@ float MPL3115ReadPressure( void );
|
||||
*/
|
||||
float MPL3115ReadTemperature( void );
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // __MPL3115_H__
|
||||
|
@@ -43,7 +43,7 @@ bool PAM7QGetGpsData( uint8_t *nmeaString, uint8_t *nmeaStringSize, uint16_t nme
|
||||
|
||||
status = PAM7QReadBuffer( MESSAGE_SIZE_1, nmeaString, 2 );
|
||||
|
||||
if( status == LORA_SUCCESS )
|
||||
if( status == SUCCESS )
|
||||
{
|
||||
// build a 16bit number
|
||||
pendingBytes = ( uint16_t )( ( nmeaString[0] << 8 ) | nmeaString[1] );
|
||||
@@ -63,7 +63,7 @@ bool PAM7QGetGpsData( uint8_t *nmeaString, uint8_t *nmeaStringSize, uint16_t nme
|
||||
status = PAM7QReadBuffer( PAYLOAD, nmeaString, pendingBytes );
|
||||
|
||||
// make sure the string is terminated
|
||||
if( status == LORA_SUCCESS )
|
||||
if( status == SUCCESS )
|
||||
{
|
||||
nmeaString[pendingBytes] = 0x00;
|
||||
|
||||
|
@@ -23,6 +23,11 @@
|
||||
#ifndef __PAM7Q_H__
|
||||
#define __PAM7Q_H__
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
|
||||
@@ -55,5 +60,9 @@ void GpsMcuOnPpsSignal( void );
|
||||
#define PAYLOAD 0xFF
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // __PAM7Q_H__
|
||||
|
||||
|
@@ -31,6 +31,10 @@
|
||||
#ifndef AES_H
|
||||
#define AES_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#if 1
|
||||
@@ -159,4 +163,8 @@ void aes_decrypt_256( const uint8_t in[N_BLOCK],
|
||||
uint8_t o_key[2 * N_BLOCK] );
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
@@ -4,150 +4,151 @@ Copyright (C) 2009 Lander Casado, Philippas Tsigas
|
||||
All rights reserved.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining
|
||||
a copy of this software and associated documentation files
|
||||
a copy of this software and associated documentation files
|
||||
(the "Software"), to deal with the Software without restriction, including
|
||||
without limitation the rights to use, copy, modify, merge, publish,
|
||||
without limitation the rights to use, copy, modify, merge, publish,
|
||||
distribute, sublicense, and/or sell copies of the Software, and to
|
||||
permit persons to whom the Software is furnished to do so, subject to
|
||||
the following conditions:
|
||||
the following conditions:
|
||||
|
||||
Redistributions of source code must retain the above copyright notice,
|
||||
Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimers. Redistributions in
|
||||
binary form must reproduce the above copyright notice, this list of
|
||||
conditions and the following disclaimers in the documentation and/or
|
||||
conditions and the following disclaimers in the documentation and/or
|
||||
other materials provided with the distribution.
|
||||
|
||||
In no event shall the authors or copyright holders be liable for any special,
|
||||
incidental, indirect or consequential damages of any kind, or any damages
|
||||
whatsoever resulting from loss of use, data or profits, whether or not
|
||||
advised of the possibility of damage, and on any theory of liability,
|
||||
incidental, indirect or consequential damages of any kind, or any damages
|
||||
whatsoever resulting from loss of use, data or profits, whether or not
|
||||
advised of the possibility of damage, and on any theory of liability,
|
||||
arising out of or in connection with the use or performance of this software.
|
||||
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
DEALINGS WITH THE SOFTWARE
|
||||
|
||||
*****************************************************************************/
|
||||
//#include <sys/param.h>
|
||||
//#include <sys/systm.h>
|
||||
#include <stdint.h>
|
||||
#include "aes.h"
|
||||
#include "cmac.h"
|
||||
#include "utilities.h"
|
||||
|
||||
#define LSHIFT(v, r) do { \
|
||||
int32_t i; \
|
||||
for (i = 0; i < 15; i++) \
|
||||
(r)[i] = (v)[i] << 1 | (v)[i + 1] >> 7; \
|
||||
(r)[15] = (v)[15] << 1; \
|
||||
} while (0)
|
||||
|
||||
#define XOR(v, r) do { \
|
||||
int32_t i; \
|
||||
for (i = 0; i < 16; i++) \
|
||||
{ \
|
||||
(r)[i] = (r)[i] ^ (v)[i]; \
|
||||
} \
|
||||
} while (0) \
|
||||
#define LSHIFT( v, r ) \
|
||||
do \
|
||||
{ \
|
||||
int32_t i; \
|
||||
for( i = 0; i < 15; i++ ) \
|
||||
( r )[i] = ( v )[i] << 1 | ( v )[i + 1] >> 7; \
|
||||
( r )[15] = ( v )[15] << 1; \
|
||||
} while( 0 )
|
||||
|
||||
#define XOR( v, r ) \
|
||||
do \
|
||||
{ \
|
||||
int32_t i; \
|
||||
for( i = 0; i < 16; i++ ) \
|
||||
{ \
|
||||
( r )[i] = ( r )[i] ^ ( v )[i]; \
|
||||
} \
|
||||
} while( 0 )
|
||||
|
||||
void AES_CMAC_Init(AES_CMAC_CTX *ctx)
|
||||
void AES_CMAC_Init( AES_CMAC_CTX* ctx )
|
||||
{
|
||||
memset1(ctx->X, 0, sizeof ctx->X);
|
||||
ctx->M_n = 0;
|
||||
memset1(ctx->rijndael.ksch, '\0', 240);
|
||||
}
|
||||
|
||||
void AES_CMAC_SetKey(AES_CMAC_CTX *ctx, const uint8_t key[AES_CMAC_KEY_LENGTH])
|
||||
{
|
||||
//rijndael_set_key_enc_only(&ctx->rijndael, key, 128);
|
||||
aes_set_key( key, AES_CMAC_KEY_LENGTH, &ctx->rijndael);
|
||||
}
|
||||
|
||||
void AES_CMAC_Update(AES_CMAC_CTX *ctx, const uint8_t *data, uint32_t len)
|
||||
{
|
||||
uint32_t mlen;
|
||||
uint8_t in[16];
|
||||
|
||||
if (ctx->M_n > 0) {
|
||||
mlen = MIN(16 - ctx->M_n, len);
|
||||
memcpy1(ctx->M_last + ctx->M_n, data, mlen);
|
||||
ctx->M_n += mlen;
|
||||
if (ctx->M_n < 16 || len == mlen)
|
||||
return;
|
||||
XOR(ctx->M_last, ctx->X);
|
||||
//rijndael_encrypt(&ctx->rijndael, ctx->X, ctx->X);
|
||||
aes_encrypt( ctx->X, ctx->X, &ctx->rijndael);
|
||||
data += mlen;
|
||||
len -= mlen;
|
||||
}
|
||||
while (len > 16) { /* not last block */
|
||||
|
||||
XOR(data, ctx->X);
|
||||
//rijndael_encrypt(&ctx->rijndael, ctx->X, ctx->X);
|
||||
|
||||
memcpy1(in, &ctx->X[0], 16); //Bestela ez du ondo iten
|
||||
aes_encrypt( in, in, &ctx->rijndael);
|
||||
memcpy1(&ctx->X[0], in, 16);
|
||||
|
||||
data += 16;
|
||||
len -= 16;
|
||||
}
|
||||
/* potential last block, save it */
|
||||
memcpy1(ctx->M_last, data, len);
|
||||
ctx->M_n = len;
|
||||
}
|
||||
|
||||
void AES_CMAC_Final(uint8_t digest[AES_CMAC_DIGEST_LENGTH], AES_CMAC_CTX *ctx)
|
||||
{
|
||||
uint8_t K[16];
|
||||
uint8_t in[16];
|
||||
/* generate subkey K1 */
|
||||
memset1(K, '\0', 16);
|
||||
|
||||
//rijndael_encrypt(&ctx->rijndael, K, K);
|
||||
|
||||
aes_encrypt( K, K, &ctx->rijndael);
|
||||
|
||||
if (K[0] & 0x80) {
|
||||
LSHIFT(K, K);
|
||||
K[15] ^= 0x87;
|
||||
} else
|
||||
LSHIFT(K, K);
|
||||
|
||||
|
||||
if (ctx->M_n == 16) {
|
||||
/* last block was a complete block */
|
||||
XOR(K, ctx->M_last);
|
||||
|
||||
} else {
|
||||
/* generate subkey K2 */
|
||||
if (K[0] & 0x80) {
|
||||
LSHIFT(K, K);
|
||||
K[15] ^= 0x87;
|
||||
} else
|
||||
LSHIFT(K, K);
|
||||
|
||||
/* padding(M_last) */
|
||||
ctx->M_last[ctx->M_n] = 0x80;
|
||||
while (++ctx->M_n < 16)
|
||||
ctx->M_last[ctx->M_n] = 0;
|
||||
|
||||
XOR(K, ctx->M_last);
|
||||
|
||||
|
||||
}
|
||||
XOR(ctx->M_last, ctx->X);
|
||||
|
||||
//rijndael_encrypt(&ctx->rijndael, ctx->X, digest);
|
||||
|
||||
memcpy1(in, &ctx->X[0], 16); //Bestela ez du ondo iten
|
||||
aes_encrypt(in, digest, &ctx->rijndael);
|
||||
memset1(K, 0, sizeof K);
|
||||
|
||||
memset1( ctx->X, 0, sizeof ctx->X );
|
||||
ctx->M_n = 0;
|
||||
memset1( ctx->rijndael.ksch, '\0', 240 );
|
||||
}
|
||||
|
||||
void AES_CMAC_SetKey( AES_CMAC_CTX* ctx, const uint8_t key[AES_CMAC_KEY_LENGTH] )
|
||||
{
|
||||
aes_set_key( key, AES_CMAC_KEY_LENGTH, &ctx->rijndael );
|
||||
}
|
||||
|
||||
void AES_CMAC_Update( AES_CMAC_CTX* ctx, const uint8_t* data, uint32_t len )
|
||||
{
|
||||
uint32_t mlen;
|
||||
uint8_t in[16];
|
||||
|
||||
if( ctx->M_n > 0 )
|
||||
{
|
||||
mlen = MIN( 16 - ctx->M_n, len );
|
||||
memcpy1( ctx->M_last + ctx->M_n, data, mlen );
|
||||
ctx->M_n += mlen;
|
||||
if( ctx->M_n < 16 || len == mlen )
|
||||
return;
|
||||
XOR( ctx->M_last, ctx->X );
|
||||
|
||||
memcpy1( in, &ctx->X[0], 16 ); // Otherwise it does not look good
|
||||
aes_encrypt( in, in, &ctx->rijndael );
|
||||
memcpy1( &ctx->X[0], in, 16 );
|
||||
|
||||
data += mlen;
|
||||
len -= mlen;
|
||||
}
|
||||
while( len > 16 )
|
||||
{ /* not last block */
|
||||
|
||||
XOR( data, ctx->X );
|
||||
|
||||
memcpy1( in, &ctx->X[0], 16 ); // Otherwise it does not look good
|
||||
aes_encrypt( in, in, &ctx->rijndael );
|
||||
memcpy1( &ctx->X[0], in, 16 );
|
||||
|
||||
data += 16;
|
||||
len -= 16;
|
||||
}
|
||||
/* potential last block, save it */
|
||||
memcpy1( ctx->M_last, data, len );
|
||||
ctx->M_n = len;
|
||||
}
|
||||
|
||||
void AES_CMAC_Final( uint8_t digest[AES_CMAC_DIGEST_LENGTH], AES_CMAC_CTX* ctx )
|
||||
{
|
||||
uint8_t K[16];
|
||||
uint8_t in[16];
|
||||
/* generate subkey K1 */
|
||||
memset1( K, '\0', 16 );
|
||||
|
||||
aes_encrypt( K, K, &ctx->rijndael );
|
||||
|
||||
if( K[0] & 0x80 )
|
||||
{
|
||||
LSHIFT( K, K );
|
||||
K[15] ^= 0x87;
|
||||
}
|
||||
else
|
||||
LSHIFT( K, K );
|
||||
|
||||
if( ctx->M_n == 16 )
|
||||
{
|
||||
/* last block was a complete block */
|
||||
XOR( K, ctx->M_last );
|
||||
}
|
||||
else
|
||||
{
|
||||
/* generate subkey K2 */
|
||||
if( K[0] & 0x80 )
|
||||
{
|
||||
LSHIFT( K, K );
|
||||
K[15] ^= 0x87;
|
||||
}
|
||||
else
|
||||
LSHIFT( K, K );
|
||||
|
||||
/* padding(M_last) */
|
||||
ctx->M_last[ctx->M_n] = 0x80;
|
||||
while( ++ctx->M_n < 16 )
|
||||
ctx->M_last[ctx->M_n] = 0;
|
||||
|
||||
XOR( K, ctx->M_last );
|
||||
}
|
||||
XOR( ctx->M_last, ctx->X );
|
||||
|
||||
memcpy1( in, &ctx->X[0], 16 ); // Otherwise it does not look good
|
||||
aes_encrypt( in, digest, &ctx->rijndael );
|
||||
memset1( K, 0, sizeof K );
|
||||
}
|
||||
|
@@ -36,6 +36,10 @@ DEALINGS WITH THE SOFTWARE
|
||||
#ifndef _CMAC_H_
|
||||
#define _CMAC_H_
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
#endif
|
||||
|
||||
#include "aes.h"
|
||||
|
||||
#define AES_CMAC_KEY_LENGTH 16
|
||||
@@ -59,5 +63,9 @@ void AES_CMAC_Final(uint8_t digest[AES_CMAC_DIGEST_LENGTH], AES_CMAC_CTX *
|
||||
// __attribute__((__bounded__(__minbytes__,1,AES_CMAC_DIGEST_LENGTH)));
|
||||
//__END_DECLS
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _CMAC_H_ */
|
||||
|
||||
|
@@ -0,0 +1,297 @@
|
||||
/*!
|
||||
* \file se-identity.h
|
||||
*
|
||||
* \brief Secure Element identity and keys
|
||||
*
|
||||
* \copyright Revised BSD License, see section \ref LICENSE.
|
||||
*
|
||||
* \code
|
||||
* ______ _
|
||||
* / _____) _ | |
|
||||
* ( (____ _____ ____ _| |_ _____ ____| |__
|
||||
* \____ \| ___ | (_ _) ___ |/ ___) _ \
|
||||
* _____) ) ____| | | || |_| ____( (___| | | |
|
||||
* (______/|_____)_|_|_| \__)_____)\____)_| |_|
|
||||
* (C)2020 Semtech
|
||||
*
|
||||
* ___ _____ _ ___ _ _____ ___ ___ ___ ___
|
||||
* / __|_ _/_\ / __| |/ / __/ _ \| _ \/ __| __|
|
||||
* \__ \ | |/ _ \ (__| ' <| _| (_) | / (__| _|
|
||||
* |___/ |_/_/ \_\___|_|\_\_| \___/|_|_\\___|___|
|
||||
* embedded.connectivity.solutions===============
|
||||
*
|
||||
* \endcode
|
||||
*
|
||||
*/
|
||||
#ifndef __SOFT_SE_IDENTITY_H__
|
||||
#define __SOFT_SE_IDENTITY_H__
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*!
|
||||
******************************************************************************
|
||||
********************************** WARNING ***********************************
|
||||
******************************************************************************
|
||||
The secure-element implementation supports both 1.0.x and 1.1.x LoRaWAN
|
||||
versions of the specification.
|
||||
Thus it has been decided to use the 1.1.x keys and EUI name definitions.
|
||||
The below table shows the names equivalence between versions:
|
||||
+---------------------+-------------------------+
|
||||
| 1.0.x | 1.1.x |
|
||||
+=====================+=========================+
|
||||
| LORAWAN_DEVICE_EUI | LORAWAN_DEVICE_EUI |
|
||||
+---------------------+-------------------------+
|
||||
| LORAWAN_APP_EUI | LORAWAN_JOIN_EUI |
|
||||
+---------------------+-------------------------+
|
||||
| LORAWAN_GEN_APP_KEY | LORAWAN_APP_KEY |
|
||||
+---------------------+-------------------------+
|
||||
| LORAWAN_APP_KEY | LORAWAN_NWK_KEY |
|
||||
+---------------------+-------------------------+
|
||||
| LORAWAN_NWK_S_KEY | LORAWAN_F_NWK_S_INT_KEY |
|
||||
+---------------------+-------------------------+
|
||||
| LORAWAN_NWK_S_KEY | LORAWAN_S_NWK_S_INT_KEY |
|
||||
+---------------------+-------------------------+
|
||||
| LORAWAN_NWK_S_KEY | LORAWAN_NWK_S_ENC_KEY |
|
||||
+---------------------+-------------------------+
|
||||
| LORAWAN_APP_S_KEY | LORAWAN_APP_S_KEY |
|
||||
+---------------------+-------------------------+
|
||||
******************************************************************************
|
||||
******************************************************************************
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
/*!
|
||||
* When set to 1 DevEui is LORAWAN_DEVICE_EUI
|
||||
* When set to 0 DevEui is automatically set with a value provided by MCU platform
|
||||
*/
|
||||
#define STATIC_DEVICE_EUI 0
|
||||
|
||||
/*!
|
||||
* end-device IEEE EUI (big endian)
|
||||
*/
|
||||
#define LORAWAN_DEVICE_EUI { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }
|
||||
|
||||
/*!
|
||||
* App/Join server IEEE EUI (big endian)
|
||||
*/
|
||||
#define LORAWAN_JOIN_EUI { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }
|
||||
|
||||
/*!
|
||||
* Secure-element pin
|
||||
*/
|
||||
#define SECURE_ELEMENT_PIN { 0x00, 0x00, 0x00, 0x00 }
|
||||
|
||||
/*!
|
||||
* When set to 1 DevAddr is LORAWAN_DEVICE_ADDRESS
|
||||
* When set to 0 DevAddr is automatically set with a value provided by a pseudo
|
||||
* random generator seeded with a value provided by the MCU platform
|
||||
*/
|
||||
#define STATIC_DEVICE_ADDRESS 0
|
||||
|
||||
/*!
|
||||
* Device address on the network (big endian)
|
||||
*/
|
||||
#define LORAWAN_DEVICE_ADDRESS ( uint32_t )0x00000000
|
||||
|
||||
#define SOFT_SE_KEY_LIST \
|
||||
{ \
|
||||
{ \
|
||||
/*! \
|
||||
* Application root key \
|
||||
* WARNING: FOR 1.0.x DEVICES IT IS THE \ref LORAWAN_GEN_APP_KEY \
|
||||
*/ \
|
||||
.KeyID = APP_KEY, \
|
||||
.KeyValue = { 0x2B, 0x7E, 0x15, 0x16, 0x28, 0xAE, 0xD2, 0xA6, 0xAB, 0xF7, 0x15, 0x88, 0x09, 0xCF, 0x4F, \
|
||||
0x3C }, \
|
||||
}, \
|
||||
{ \
|
||||
/*! \
|
||||
* Network root key \
|
||||
* WARNING: FOR 1.0.x DEVICES IT IS THE \ref LORAWAN_APP_KEY \
|
||||
*/ \
|
||||
.KeyID = NWK_KEY, \
|
||||
.KeyValue = { 0x2B, 0x7E, 0x15, 0x16, 0x28, 0xAE, 0xD2, 0xA6, 0xAB, 0xF7, 0x15, 0x88, 0x09, 0xCF, 0x4F, \
|
||||
0x3C }, \
|
||||
}, \
|
||||
{ \
|
||||
/*! \
|
||||
* Join session integrity key (Dynamically updated) \
|
||||
* WARNING: NOT USED FOR 1.0.x DEVICES \
|
||||
*/ \
|
||||
.KeyID = J_S_INT_KEY, \
|
||||
.KeyValue = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
|
||||
0x00 }, \
|
||||
}, \
|
||||
{ \
|
||||
/*! \
|
||||
* Join session encryption key (Dynamically updated) \
|
||||
* WARNING: NOT USED FOR 1.0.x DEVICES \
|
||||
*/ \
|
||||
.KeyID = J_S_ENC_KEY, \
|
||||
.KeyValue = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
|
||||
0x00 }, \
|
||||
}, \
|
||||
{ \
|
||||
/*! \
|
||||
* Forwarding Network session integrity key \
|
||||
* WARNING: NWK_S_KEY FOR 1.0.x DEVICES \
|
||||
*/ \
|
||||
.KeyID = F_NWK_S_INT_KEY, \
|
||||
.KeyValue = { 0x2B, 0x7E, 0x15, 0x16, 0x28, 0xAE, 0xD2, 0xA6, 0xAB, 0xF7, 0x15, 0x88, 0x09, 0xCF, 0x4F, \
|
||||
0x3C }, \
|
||||
}, \
|
||||
{ \
|
||||
/*! \
|
||||
* Serving Network session integrity key \
|
||||
* WARNING: NOT USED FOR 1.0.x DEVICES. MUST BE THE SAME AS \ref LORAWAN_F_NWK_S_INT_KEY \
|
||||
*/ \
|
||||
.KeyID = S_NWK_S_INT_KEY, \
|
||||
.KeyValue = { 0x2B, 0x7E, 0x15, 0x16, 0x28, 0xAE, 0xD2, 0xA6, 0xAB, 0xF7, 0x15, 0x88, 0x09, 0xCF, 0x4F, \
|
||||
0x3C }, \
|
||||
}, \
|
||||
{ \
|
||||
/*! \
|
||||
* Network session encryption key \
|
||||
* WARNING: NOT USED FOR 1.0.x DEVICES. MUST BE THE SAME AS \ref LORAWAN_F_NWK_S_INT_KEY \
|
||||
*/ \
|
||||
.KeyID = NWK_S_ENC_KEY, \
|
||||
.KeyValue = { 0x2B, 0x7E, 0x15, 0x16, 0x28, 0xAE, 0xD2, 0xA6, 0xAB, 0xF7, 0x15, 0x88, 0x09, 0xCF, 0x4F, \
|
||||
0x3C }, \
|
||||
}, \
|
||||
{ \
|
||||
/*! \
|
||||
* Application session key \
|
||||
*/ \
|
||||
.KeyID = APP_S_KEY, \
|
||||
.KeyValue = { 0x2B, 0x7E, 0x15, 0x16, 0x28, 0xAE, 0xD2, 0xA6, 0xAB, 0xF7, 0x15, 0x88, 0x09, 0xCF, 0x4F, \
|
||||
0x3C }, \
|
||||
}, \
|
||||
{ \
|
||||
/*! \
|
||||
* Multicast root key (Dynamically updated) \
|
||||
*/ \
|
||||
.KeyID = MC_ROOT_KEY, \
|
||||
.KeyValue = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
|
||||
0x00 }, \
|
||||
}, \
|
||||
{ \
|
||||
/*! \
|
||||
* Multicast key encryption key (Dynamically updated) \
|
||||
*/ \
|
||||
.KeyID = MC_KE_KEY, \
|
||||
.KeyValue = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
|
||||
0x00 }, \
|
||||
}, \
|
||||
{ \
|
||||
/*! \
|
||||
* Multicast group #0 root key (Dynamically updated) \
|
||||
*/ \
|
||||
.KeyID = MC_KEY_0, \
|
||||
.KeyValue = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
|
||||
0x00 }, \
|
||||
}, \
|
||||
{ \
|
||||
/*! \
|
||||
* Multicast group #0 application session key (Dynamically updated) \
|
||||
*/ \
|
||||
.KeyID = MC_APP_S_KEY_0, \
|
||||
.KeyValue = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
|
||||
0x00 }, \
|
||||
}, \
|
||||
{ \
|
||||
/*! \
|
||||
* Multicast group #0 network session key (Dynamically updated) \
|
||||
*/ \
|
||||
.KeyID = MC_NWK_S_KEY_0, \
|
||||
.KeyValue = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
|
||||
0x00 }, \
|
||||
}, \
|
||||
{ \
|
||||
/*! \
|
||||
* Multicast group #1 root key (Dynamically updated) \
|
||||
*/ \
|
||||
.KeyID = MC_KEY_1, \
|
||||
.KeyValue = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
|
||||
0x00 }, \
|
||||
}, \
|
||||
{ \
|
||||
/*! \
|
||||
* Multicast group #1 application session key (Dynamically updated) \
|
||||
*/ \
|
||||
.KeyID = MC_APP_S_KEY_1, \
|
||||
.KeyValue = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
|
||||
0x00 }, \
|
||||
}, \
|
||||
{ \
|
||||
/*! \
|
||||
* Multicast group #1 network session key (Dynamically updated) \
|
||||
*/ \
|
||||
.KeyID = MC_NWK_S_KEY_1, \
|
||||
.KeyValue = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
|
||||
0x00 }, \
|
||||
}, \
|
||||
{ \
|
||||
/*! \
|
||||
* Multicast group #2 root key (Dynamically updated) \
|
||||
*/ \
|
||||
.KeyID = MC_KEY_2, \
|
||||
.KeyValue = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
|
||||
0x00 }, \
|
||||
}, \
|
||||
{ \
|
||||
/*! \
|
||||
* Multicast group #2 application session key (Dynamically updated) \
|
||||
*/ \
|
||||
.KeyID = MC_APP_S_KEY_2, \
|
||||
.KeyValue = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
|
||||
0x00 }, \
|
||||
}, \
|
||||
{ \
|
||||
/*! \
|
||||
* Multicast group #2 network session key (Dynamically updated) \
|
||||
*/ \
|
||||
.KeyID = MC_NWK_S_KEY_2, \
|
||||
.KeyValue = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
|
||||
0x00 }, \
|
||||
}, \
|
||||
{ \
|
||||
/*! \
|
||||
* Multicast group #3 root key (Dynamically updated) \
|
||||
*/ \
|
||||
.KeyID = MC_KEY_3, \
|
||||
.KeyValue = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
|
||||
0x00 }, \
|
||||
}, \
|
||||
{ \
|
||||
/*! \
|
||||
* Multicast group #3 application session key (Dynamically updated) \
|
||||
*/ \
|
||||
.KeyID = MC_APP_S_KEY_3, \
|
||||
.KeyValue = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
|
||||
0x00 }, \
|
||||
}, \
|
||||
{ \
|
||||
/*! \
|
||||
* Multicast group #3 network session key (Dynamically updated) \
|
||||
*/ \
|
||||
.KeyID = MC_NWK_S_KEY_3, \
|
||||
.KeyValue = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
|
||||
0x00 }, \
|
||||
}, \
|
||||
{ \
|
||||
/*! \
|
||||
* All zeros key. (ClassB usage)(constant) \
|
||||
*/ \
|
||||
.KeyID = SLOT_RAND_ZERO_KEY, \
|
||||
.KeyValue = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
|
||||
0x00 }, \
|
||||
}, \
|
||||
},
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // __SOFT_SE_IDENTITY_H__
|
@@ -0,0 +1,39 @@
|
||||
/*!
|
||||
* \file soft-se-hal.h
|
||||
*
|
||||
* \brief Secure Element hardware abstraction layer implementation
|
||||
*
|
||||
* \copyright Revised BSD License, see section \ref LICENSE.
|
||||
*
|
||||
* \code
|
||||
* ______ _
|
||||
* / _____) _ | |
|
||||
* ( (____ _____ ____ _| |_ _____ ____| |__
|
||||
* \____ \| ___ | (_ _) ___ |/ ___) _ \
|
||||
* _____) ) ____| | | || |_| ____( (___| | | |
|
||||
* (______/|_____)_|_|_| \__)_____)\____)_| |_|
|
||||
* (C)2020 Semtech
|
||||
*
|
||||
* ___ _____ _ ___ _ _____ ___ ___ ___ ___
|
||||
* / __|_ _/_\ / __| |/ / __/ _ \| _ \/ __| __|
|
||||
* \__ \ | |/ _ \ (__| ' <| _| (_) | / (__| _|
|
||||
* |___/ |_/_/ \_\___|_|\_\_| \___/|_|_\\___|___|
|
||||
* embedded.connectivity.solutions===============
|
||||
*
|
||||
* \endcode
|
||||
*
|
||||
*/
|
||||
#include "board.h"
|
||||
#include "radio.h"
|
||||
|
||||
#include "soft-se-hal.h"
|
||||
|
||||
void SoftSeHalGetUniqueId( uint8_t *id )
|
||||
{
|
||||
BoardGetUniqueId( id );
|
||||
}
|
||||
|
||||
uint32_t SoftSeHalGetRandomNumber( void )
|
||||
{
|
||||
return Radio.Random( );
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user