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:
supowang
2020-05-29 11:59:05 +08:00
parent 5d9895cecc
commit f9bd2588a2
137 changed files with 10401 additions and 4328 deletions

View File

@@ -103,7 +103,7 @@
<bEvRecOn>1</bEvRecOn> <bEvRecOn>1</bEvRecOn>
<bSchkAxf>0</bSchkAxf> <bSchkAxf>0</bSchkAxf>
<bTchkAxf>0</bTchkAxf> <bTchkAxf>0</bTchkAxf>
<nTsel>0</nTsel> <nTsel>6</nTsel>
<sDll></sDll> <sDll></sDll>
<sDllPa></sDllPa> <sDllPa></sDllPa>
<sDlgDll></sDlgDll> <sDlgDll></sDlgDll>
@@ -114,9 +114,34 @@
<tDlgDll></tDlgDll> <tDlgDll></tDlgDll>
<tDlgPa></tDlgPa> <tDlgPa></tDlgPa>
<tIfile></tIfile> <tIfile></tIfile>
<pMon>BIN\UL2CM3.DLL</pMon> <pMon>STLink\ST-LINKIII-KEIL_SWO.dll</pMon>
</DebugOpt> </DebugOpt>
<TargetDriverDllRegistry> <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> <SetRegEntry>
<Number>0</Number> <Number>0</Number>
<Key>UL2CM3</Key> <Key>UL2CM3</Key>
@@ -130,12 +155,12 @@
<DebugFlag> <DebugFlag>
<trace>0</trace> <trace>0</trace>
<periodic>0</periodic> <periodic>0</periodic>
<aLwin>0</aLwin> <aLwin>1</aLwin>
<aCover>0</aCover> <aCover>0</aCover>
<aSer1>0</aSer1> <aSer1>0</aSer1>
<aSer2>0</aSer2> <aSer2>0</aSer2>
<aPa>0</aPa> <aPa>0</aPa>
<viewmode>0</viewmode> <viewmode>1</viewmode>
<vrSel>0</vrSel> <vrSel>0</vrSel>
<aSym>0</aSym> <aSym>0</aSym>
<aTbox>0</aTbox> <aTbox>0</aTbox>
@@ -198,7 +223,7 @@
<Group> <Group>
<GroupName>Application/User</GroupName> <GroupName>Application/User</GroupName>
<tvExp>1</tvExp> <tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg> <tvExpOptDlg>0</tvExpOptDlg>
<cbSel>0</cbSel> <cbSel>0</cbSel>
<RteFlg>0</RteFlg> <RteFlg>0</RteFlg>
@@ -1002,7 +1027,7 @@
<Group> <Group>
<GroupName>lorawan/mac</GroupName> <GroupName>lorawan/mac</GroupName>
<tvExp>0</tvExp> <tvExp>1</tvExp>
<tvExpOptDlg>0</tvExpOptDlg> <tvExpOptDlg>0</tvExpOptDlg>
<cbSel>0</cbSel> <cbSel>0</cbSel>
<RteFlg>0</RteFlg> <RteFlg>0</RteFlg>
@@ -1085,18 +1110,6 @@
<tvExp>0</tvExp> <tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg> <tvExpOptDlg>0</tvExpOptDlg>
<bDave2>0</bDave2> <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> <PathWithFileName>..\..\..\components\connectivity\LoraWAN\mac\LoRaMacParser.c</PathWithFileName>
<FilenameWithoutPath>LoRaMacParser.c</FilenameWithoutPath> <FilenameWithoutPath>LoRaMacParser.c</FilenameWithoutPath>
<RteFlg>0</RteFlg> <RteFlg>0</RteFlg>
@@ -1104,7 +1117,7 @@
</File> </File>
<File> <File>
<GroupNumber>5</GroupNumber> <GroupNumber>5</GroupNumber>
<FileNumber>75</FileNumber> <FileNumber>74</FileNumber>
<FileType>1</FileType> <FileType>1</FileType>
<tvExp>0</tvExp> <tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg> <tvExpOptDlg>0</tvExpOptDlg>
@@ -1116,7 +1129,7 @@
</File> </File>
<File> <File>
<GroupNumber>5</GroupNumber> <GroupNumber>5</GroupNumber>
<FileNumber>76</FileNumber> <FileNumber>75</FileNumber>
<FileType>1</FileType> <FileType>1</FileType>
<tvExp>0</tvExp> <tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg> <tvExpOptDlg>0</tvExpOptDlg>
@@ -1128,7 +1141,7 @@
</File> </File>
<File> <File>
<GroupNumber>5</GroupNumber> <GroupNumber>5</GroupNumber>
<FileNumber>77</FileNumber> <FileNumber>76</FileNumber>
<FileType>1</FileType> <FileType>1</FileType>
<tvExp>0</tvExp> <tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg> <tvExpOptDlg>0</tvExpOptDlg>
@@ -1140,7 +1153,7 @@
</File> </File>
<File> <File>
<GroupNumber>5</GroupNumber> <GroupNumber>5</GroupNumber>
<FileNumber>78</FileNumber> <FileNumber>77</FileNumber>
<FileType>1</FileType> <FileType>1</FileType>
<tvExp>0</tvExp> <tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg> <tvExpOptDlg>0</tvExpOptDlg>
@@ -1150,6 +1163,18 @@
<RteFlg>0</RteFlg> <RteFlg>0</RteFlg>
<bShared>0</bShared> <bShared>0</bShared>
</File> </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>
<Group> <Group>

View File

@@ -762,11 +762,6 @@
<FileType>1</FileType> <FileType>1</FileType>
<FilePath>..\..\..\components\connectivity\LoraWAN\mac\LoRaMacCrypto.c</FilePath> <FilePath>..\..\..\components\connectivity\LoraWAN\mac\LoRaMacCrypto.c</FilePath>
</File> </File>
<File>
<FileName>LoRaMacFCntHandler.c</FileName>
<FileType>1</FileType>
<FilePath>..\..\..\components\connectivity\LoraWAN\mac\LoRaMacFCntHandler.c</FilePath>
</File>
<File> <File>
<FileName>LoRaMacParser.c</FileName> <FileName>LoRaMacParser.c</FileName>
<FileType>1</FileType> <FileType>1</FileType>
@@ -792,6 +787,11 @@
<FileType>1</FileType> <FileType>1</FileType>
<FilePath>..\..\..\components\connectivity\LoraWAN\peripherals\soft-se\soft-se.c</FilePath> <FilePath>..\..\..\components\connectivity\LoraWAN\peripherals\soft-se\soft-se.c</FilePath>
</File> </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> </Files>
</Group> </Group>
<Group> <Group>

View 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)

View File

@@ -20,6 +20,8 @@
* *
* \author Gregory Cristian ( Semtech ) * \author Gregory Cristian ( Semtech )
*/ */
#include <stdint.h>
#include <stdbool.h>
#include "stm32l0xx.h" #include "stm32l0xx.h"
#include "board-config.h" #include "board-config.h"
#include "adc-board.h" #include "adc-board.h"
@@ -70,6 +72,8 @@ uint16_t AdcMcuReadChannel( Adc_t *obj, uint32_t channel )
{ {
ADC_ChannelConfTypeDef adcConf = { 0 }; ADC_ChannelConfTypeDef adcConf = { 0 };
uint16_t adcData = 0; uint16_t adcData = 0;
uint32_t tickStart = 0;
bool isAdcReady = true;
// Enable HSI // Enable HSI
__HAL_RCC_HSI_ENABLE( ); __HAL_RCC_HSI_ENABLE( );
@@ -83,18 +87,31 @@ uint16_t AdcMcuReadChannel( Adc_t *obj, uint32_t channel )
adcConf.Channel = channel; adcConf.Channel = channel;
adcConf.Rank = ADC_RANK_CHANNEL_NUMBER; adcConf.Rank = ADC_RANK_CHANNEL_NUMBER;
HAL_ADC_ConfigChannel( &AdcHandle, &adcConf ); HAL_ADC_ConfigChannel( &AdcHandle, &adcConf );
// Enable ADC1 // Enable ADC1
__HAL_ADC_ENABLE( &AdcHandle ); __HAL_ADC_ENABLE( &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;
}
}
if( isAdcReady != false )
{
// Start ADC Software Conversion // Start ADC Software Conversion
HAL_ADC_Start( &AdcHandle ); HAL_ADC_Start( &AdcHandle );
HAL_ADC_PollForConversion( &AdcHandle, HAL_MAX_DELAY ); HAL_ADC_PollForConversion( &AdcHandle, HAL_MAX_DELAY );
adcData = HAL_ADC_GetValue( &AdcHandle ); adcData = HAL_ADC_GetValue( &AdcHandle );
}
__HAL_ADC_DISABLE( &AdcHandle ); __HAL_ADC_DISABLE( &AdcHandle );

View File

@@ -185,8 +185,8 @@ void RtcInit( void )
time.Seconds = 0; time.Seconds = 0;
time.SubSeconds = 0; time.SubSeconds = 0;
time.TimeFormat = 0; time.TimeFormat = 0;
time.StoreOperation = RTC_DAYLIGHTSAVING_NONE; time.StoreOperation = RTC_STOREOPERATION_RESET;
time.DayLightSaving = RTC_STOREOPERATION_RESET; time.DayLightSaving = RTC_DAYLIGHTSAVING_NONE;
HAL_RTC_SetTime( &RtcHandle, &time, RTC_FORMAT_BIN ); HAL_RTC_SetTime( &RtcHandle, &time, RTC_FORMAT_BIN );
// Enable Direct Read of the calendar registers (not through Shadow registers) // Enable Direct Read of the calendar registers (not through Shadow registers)
@@ -469,7 +469,7 @@ void RtcSetMcuWakeUpTime( void )
mcuWakeUpTime = ( int16_t )( ( now - hit ) ); mcuWakeUpTime = ( int16_t )( ( now - hit ) );
McuWakeUpTimeCal += mcuWakeUpTime; 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 correction;
uint32_t seconds; 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 // Make sure it is correct due to asynchronus nature of RTC
do do
{ {
firstRead = time->SubSeconds; firstRead = RTC->SSR;
HAL_RTC_GetDate( &RtcHandle, date, RTC_FORMAT_BIN ); HAL_RTC_GetDate( &RtcHandle, date, RTC_FORMAT_BIN );
HAL_RTC_GetTime( &RtcHandle, time, 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 // Calculte amount of elapsed days since 01/01/2000
seconds = DIVC( ( DAYS_IN_YEAR * 3 + DAYS_IN_LEAP_YEAR ) * date->Year , 4 ); 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 ); 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; 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 kDev = RTC_TEMP_DEV_COEFFICIENT;
float t = RTC_TEMP_TURNOVER; float t = RTC_TEMP_TURNOVER;
float tDev = RTC_TEMP_DEV_TURNOVER; float tDev = RTC_TEMP_DEV_TURNOVER;
float interim = 0.0; float interim = 0.0f;
float ppm = 0.0; float ppm = 0.0f;
if( k < 0.0 ) if( k < 0.0f )
{ {
ppm = ( k - kDev ); ppm = ( k - kDev );
} }
@@ -609,12 +606,12 @@ TimerTime_t RtcTempCompensation( TimerTime_t period, float temperature )
ppm *= interim * interim; ppm *= interim * interim;
// Calculate the drift in time // Calculate the drift in time
interim = ( ( float ) period * ppm ) / 1e6; interim = ( ( float ) period * ppm ) / 1000000.0f;
// Calculate the resulting time period // Calculate the resulting time period
interim += period; interim += period;
interim = floor( interim ); interim = floor( interim );
if( interim < 0.0 ) if( interim < 0.0f )
{ {
interim = ( float )period; interim = ( float )period;
} }

View File

@@ -140,12 +140,24 @@ void SX1276IoDeInit( void )
GpioInit( &SX1276.DIO5, RADIO_DIO_5, PIN_INPUT, PIN_PUSH_PULL, PIN_NO_PULL, 0 ); 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. * \brief Enables/disables the TCXO if available on board design.
* *
* \param [IN] state TCXO enabled when true and disabled when false. * \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 ) if( state == true )
{ {

View File

@@ -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 }; uint8_t AppSKey[] = { 0x2B, 0x7E, 0x15, 0x16, 0x28, 0xAE, 0xD2, 0xA6, 0xAB, 0xF7, 0x15, 0x88, 0x09, 0xCF, 0x4F, 0x3C };
#endif #endif
bool NextTx = true; bool NextTx = true;
uint8_t IsTxConfirmed = false; uint8_t IsTxConfirmed = false;
TimerEvent_t TxNextPacketTimer; TimerEvent_t TxNextPacketTimer;
@@ -318,8 +319,6 @@ void LoRa_JoinNetwork(uint8_t jointype)
{ {
MlmeReq_t mlmeReq; MlmeReq_t mlmeReq;
mlmeReq.Type = MLME_JOIN; mlmeReq.Type = MLME_JOIN;
mlmeReq.Req.Join.DevEui = DevEui;
mlmeReq.Req.Join.JoinEui = JoinEui;
mlmeReq.Req.Join.Datarate = LORAWAN_DEFAULT_DATARATE; mlmeReq.Req.Join.Datarate = LORAWAN_DEFAULT_DATARATE;
LoRaMacMlmeRequest( &mlmeReq ); LoRaMacMlmeRequest( &mlmeReq );
} }

View File

@@ -9,6 +9,47 @@
#include "LoRaMac.h" #include "LoRaMac.h"
#include "NvmCtxMgmt.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 OVER_THE_AIR_ACTIVATION 0
#define ABP_ACTIVATION_LRWAN_VERSION_V10x 0x01000300 // 1.0.3.0 #define ABP_ACTIVATION_LRWAN_VERSION_V10x 0x01000300 // 1.0.3.0
@@ -19,16 +60,13 @@
#define LORAWAN_NETWORK_ID ( uint32_t )0 #define LORAWAN_NETWORK_ID ( uint32_t )0
#define ACTIVE_REGION LORAMAC_REGION_CN470
#define LORAWAN_APP_DATA_MAX_SIZE 64 #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; extern bool NextTx;

View File

@@ -23,6 +23,11 @@
#ifndef __ADC_BOARD_H__ #ifndef __ADC_BOARD_H__
#define __ADC_BOARD_H__ #define __ADC_BOARD_H__
#ifdef __cplusplus
extern "C"
{
#endif
#include "adc.h" #include "adc.h"
/*! /*!
@@ -46,4 +51,8 @@ void AdcMcuConfig( void );
*/ */
uint16_t AdcMcuReadChannel( Adc_t *obj, uint32_t channel ); uint16_t AdcMcuReadChannel( Adc_t *obj, uint32_t channel );
#ifdef __cplusplus
}
#endif
#endif // __ADC_BOARD_H__ #endif // __ADC_BOARD_H__

View File

@@ -23,6 +23,11 @@
#ifndef __BOARD_H__ #ifndef __BOARD_H__
#define __BOARD_H__ #define __BOARD_H__
#ifdef __cplusplus
extern "C"
{
#endif
#include <stdint.h> #include <stdint.h>
#include "utilities.h" #include "utilities.h"
/*! /*!
@@ -113,4 +118,8 @@ uint8_t GetBoardPowerSource( void );
*/ */
Version_t BoardGetVersion( void ); Version_t BoardGetVersion( void );
#ifdef __cplusplus
}
#endif
#endif // __BOARD_H__ #endif // __BOARD_H__

View File

@@ -25,6 +25,11 @@
#ifndef __DELAY_BOARD_H__ #ifndef __DELAY_BOARD_H__
#define __DELAY_BOARD_H__ #define __DELAY_BOARD_H__
#ifdef __cplusplus
extern "C"
{
#endif
#include <stdint.h> #include <stdint.h>
/*! /*!
@@ -34,4 +39,8 @@
*/ */
void DelayMsMcu( uint32_t ms ); void DelayMsMcu( uint32_t ms );
#ifdef __cplusplus
}
#endif
#endif // __DELAY_BOARD_H__ #endif // __DELAY_BOARD_H__

View File

@@ -28,6 +28,11 @@
#ifndef __DISPLAY_BOARD_H__ #ifndef __DISPLAY_BOARD_H__
#define __DISPLAY_BOARD_H__ #define __DISPLAY_BOARD_H__
#ifdef __cplusplus
extern "C"
{
#endif
#include <stdint.h> #include <stdint.h>
#include <stdbool.h> #include <stdbool.h>
@@ -290,4 +295,8 @@ void DisplayPrint( const char *string );
*/ */
void DisplayPrintf( const char *format, ... ); void DisplayPrintf( const char *format, ... );
#ifdef __cplusplus
}
#endif
#endif // __DISPLAY_BOARD_H__ #endif // __DISPLAY_BOARD_H__

View File

@@ -23,6 +23,11 @@
#ifndef __EEPROM_BOARD_H__ #ifndef __EEPROM_BOARD_H__
#define __EEPROM_BOARD_H__ #define __EEPROM_BOARD_H__
#ifdef __cplusplus
extern "C"
{
#endif
#include <stdint.h> #include <stdint.h>
/*! /*!
@@ -31,7 +36,7 @@
* \param[IN] addr EEPROM address to write to * \param[IN] addr EEPROM address to write to
* \param[IN] buffer Pointer to the buffer to be written. * \param[IN] buffer Pointer to the buffer to be written.
* \param[IN] size Size of 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 ); 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[IN] addr EEPROM address to read from
* \param[OUT] buffer Pointer to the buffer to be written with read data. * \param[OUT] buffer Pointer to the buffer to be written with read data.
* \param[IN] size Size of the buffer to be read. * \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 ); 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 ); uint8_t EepromMcuGetDeviceAddr( void );
#ifdef __cplusplus
}
#endif
#endif // __EEPROM_BOARD_H__ #endif // __EEPROM_BOARD_H__

View File

@@ -23,6 +23,11 @@
#ifndef __GPIO_BOARD_H__ #ifndef __GPIO_BOARD_H__
#define __GPIO_BOARD_H__ #define __GPIO_BOARD_H__
#ifdef __cplusplus
extern "C"
{
#endif
#include "gpio.h" #include "gpio.h"
/*! /*!
@@ -89,4 +94,8 @@ void GpioMcuToggle( Gpio_t *obj );
*/ */
uint32_t GpioMcuRead( Gpio_t *obj ); uint32_t GpioMcuRead( Gpio_t *obj );
#ifdef __cplusplus
}
#endif
#endif // __GPIO_BOARD_H__ #endif // __GPIO_BOARD_H__

View File

@@ -23,6 +23,11 @@
#ifndef __GPS_BOARD_H__ #ifndef __GPS_BOARD_H__
#define __GPS_BOARD_H__ #define __GPS_BOARD_H__
#ifdef __cplusplus
extern "C"
{
#endif
#include "uart.h" #include "uart.h"
/*! /*!
@@ -71,4 +76,8 @@ void GpsMcuProcess( void );
*/ */
void GpsMcuIrqNotify( UartNotifyId_t id ); void GpsMcuIrqNotify( UartNotifyId_t id );
#ifdef __cplusplus
}
#endif
#endif // __GPS_BOARD_H__ #endif // __GPS_BOARD_H__

View File

@@ -23,6 +23,11 @@
#ifndef __I2C_BOARD_H__ #ifndef __I2C_BOARD_H__
#define __I2C_BOARD_H__ #define __I2C_BOARD_H__
#ifdef __cplusplus
extern "C"
{
#endif
#include <stdint.h> #include <stdint.h>
#include <stdbool.h> #include <stdbool.h>
#include "i2c.h" #include "i2c.h"
@@ -137,4 +142,8 @@ uint8_t I2cMcuWaitStandbyState( I2c_t *obj, uint8_t deviceAddr );
*/ */
void I2cSetAddrSize( I2c_t *obj, I2cAddrSize addrSize ); void I2cSetAddrSize( I2c_t *obj, I2cAddrSize addrSize );
#ifdef __cplusplus
}
#endif
#endif // __I2C_BOARD_H__ #endif // __I2C_BOARD_H__

View File

@@ -25,8 +25,10 @@
#ifndef __LPM_BOARD_H__ #ifndef __LPM_BOARD_H__
#define __LPM_BOARD_H__ #define __LPM_BOARD_H__
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C"
{
#endif #endif
#include "board-config.h" #include "board-config.h"

View 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__

View File

@@ -23,6 +23,11 @@
#ifndef __PIN_NAME_BOARD_H__ #ifndef __PIN_NAME_BOARD_H__
#define __PIN_NAME_BOARD_H__ #define __PIN_NAME_BOARD_H__
#ifdef __cplusplus
extern "C"
{
#endif
/*! /*!
* STM32 Pin Names * 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, \ 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 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__ #endif // __PIN_NAME_BOARD_H__

View File

@@ -23,8 +23,18 @@
#ifndef __PIN_NAME_IOE_H__ #ifndef __PIN_NAME_IOE_H__
#define __PIN_NAME_IOE_H__ #define __PIN_NAME_IOE_H__
#ifdef __cplusplus
extern "C"
{
#endif
// SX1509 Pin Names // SX1509 Pin Names
#define IOE_PINS \ #define IOE_PINS \
IOE_0, IOE_1, IOE_2, IOE_3, IOE_4, IOE_5, IOE_6, IOE_7, \ 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 IOE_8, IOE_9, IOE_10, IOE_11, IOE_12, IOE_13, IOE_14, IOE_15
#ifdef __cplusplus
}
#endif
#endif // __PIN_NAME_IOE_H__ #endif // __PIN_NAME_IOE_H__

View File

@@ -23,6 +23,11 @@
#ifndef __RTC_BOARD_H__ #ifndef __RTC_BOARD_H__
#define __RTC_BOARD_H__ #define __RTC_BOARD_H__
#ifdef __cplusplus
extern "C"
{
#endif
#include <stdint.h> #include <stdint.h>
#include <stdbool.h> #include <stdbool.h>
#include "timer.h" #include "timer.h"
@@ -30,22 +35,22 @@
/*! /*!
* \brief Temperature coefficient of the clock source * \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 * \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 * \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 * \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 * \brief Initializes the RTC timer
@@ -189,4 +194,8 @@ void RtcProcess( void );
*/ */
TimerTime_t RtcTempCompensation( TimerTime_t period, float temperature ); TimerTime_t RtcTempCompensation( TimerTime_t period, float temperature );
#ifdef __cplusplus
}
#endif
#endif // __RTC_BOARD_H__ #endif // __RTC_BOARD_H__

View File

@@ -23,8 +23,17 @@
#ifndef __SPI_BOARD_H__ #ifndef __SPI_BOARD_H__
#define __SPI_BOARD_H__ #define __SPI_BOARD_H__
#ifdef __cplusplus
extern "C"
{
#endif
#include "spi.h" #include "spi.h"
// An Spi.c file has to be implmented under system directory. // An Spi.c file has to be implmented under system directory.
#ifdef __cplusplus
}
#endif
#endif // __SPI_BOARD_H__ #endif // __SPI_BOARD_H__

View File

@@ -23,6 +23,11 @@
#ifndef __SX126x_BOARD_H__ #ifndef __SX126x_BOARD_H__
#define __SX126x_BOARD_H__ #define __SX126x_BOARD_H__
#ifdef __cplusplus
extern "C"
{
#endif
#include <stdint.h> #include <stdint.h>
#include <stdbool.h> #include <stdbool.h>
#include "sx126x/sx126x.h" #include "sx126x/sx126x.h"
@@ -46,6 +51,16 @@ void SX126xIoIrqInit( DioIrqHandler dioIrq );
*/ */
void SX126xIoDeInit( void ); 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 * \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 [in] opcode Opcode of the command
* \param [out] buffer Buffer holding data from the radio * \param [out] buffer Buffer holding data from the radio
* \param [in] size Size of the buffer * \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 * \brief Write a single byte of data to the radio memory
@@ -156,4 +173,8 @@ void SX126xDbgPinRxWrite( uint8_t state );
*/ */
extern SX126x_t SX126x; extern SX126x_t SX126x;
#ifdef __cplusplus
}
#endif
#endif // __SX126x_BOARD_H__ #endif // __SX126x_BOARD_H__

View File

@@ -23,6 +23,11 @@
#ifndef __SX1272_BOARD_H__ #ifndef __SX1272_BOARD_H__
#define __SX1272_BOARD_H__ #define __SX1272_BOARD_H__
#ifdef __cplusplus
extern "C"
{
#endif
#include <stdint.h> #include <stdint.h>
#include <stdbool.h> #include <stdbool.h>
#include "sx1272/sx1272.h" #include "sx1272/sx1272.h"
@@ -72,6 +77,16 @@ void SX1272IoIrqInit( DioIrqHandler **irqHandlers );
*/ */
void SX1272IoDeInit( void ); 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 * \brief Resets the radio
*/ */
@@ -120,6 +135,13 @@ void SX1272SetAntSw( uint8_t opMode );
*/ */
bool SX1272CheckRfFrequency( uint32_t frequency ); 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]. * \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; extern SX1272_t SX1272;
#ifdef __cplusplus
}
#endif
#endif // __SX1272_BOARD_H__ #endif // __SX1272_BOARD_H__

View File

@@ -23,6 +23,11 @@
#ifndef __SX1276_BOARD_H__ #ifndef __SX1276_BOARD_H__
#define __SX1276_BOARD_H__ #define __SX1276_BOARD_H__
#ifdef __cplusplus
extern "C"
{
#endif
#include <stdint.h> #include <stdint.h>
#include <stdbool.h> #include <stdbool.h>
#include "sx1276/sx1276.h" #include "sx1276/sx1276.h"
@@ -73,6 +78,16 @@ void SX1276IoIrqInit( DioIrqHandler **irqHandlers );
*/ */
void SX1276IoDeInit( void ); 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 * \brief Resets the radio
*/ */
@@ -121,6 +136,13 @@ void SX1276SetAntSw( uint8_t opMode );
*/ */
bool SX1276CheckRfFrequency( uint32_t frequency ); 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]. * \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; extern SX1276_t SX1276;
#ifdef __cplusplus
}
#endif
#endif // __SX1276_BOARD_H__ #endif // __SX1276_BOARD_H__

View File

@@ -23,6 +23,11 @@
#ifndef __UART_BOARD_H__ #ifndef __UART_BOARD_H__
#define __UART_BOARD_H__ #define __UART_BOARD_H__
#ifdef __cplusplus
extern "C"
{
#endif
#include <stdint.h> #include <stdint.h>
#include "uart.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 ); uint8_t UartMcuGetBuffer( Uart_t *obj, uint8_t *buffer, uint16_t size, uint16_t *nbReadBytes );
#ifdef __cplusplus
}
#endif
#endif // __UART_BOARD_H__ #endif // __UART_BOARD_H__

View File

@@ -23,6 +23,11 @@
#ifndef __UART_USB_BOARD_H__ #ifndef __UART_USB_BOARD_H__
#define __UART_USB_BOARD_H__ #define __UART_USB_BOARD_H__
#ifdef __cplusplus
extern "C"
{
#endif
#include <stdint.h> #include <stdint.h>
#include "uart.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 ); uint8_t UartUsbGetChar( Uart_t *obj, uint8_t *data );
#ifdef __cplusplus
}
#endif
#endif // __UART_USB_BOARD_H__ #endif // __UART_USB_BOARD_H__

View File

@@ -23,6 +23,11 @@
#ifndef __UTILITIES_H__ #ifndef __UTILITIES_H__
#define __UTILITIES_H__ #define __UTILITIES_H__
#ifdef __cplusplus
extern "C"
{
#endif
#include <stdint.h> #include <stdint.h>
/*! /*!
@@ -43,7 +48,9 @@
* \param [IN] b 2nd value * \param [IN] b 2nd value
* \retval minValue Minimum value * \retval minValue Minimum value
*/ */
#ifndef MIN
#define MIN( a, b ) ( ( ( a ) < ( b ) ) ? ( a ) : ( b ) ) #define MIN( a, b ) ( ( ( a ) < ( b ) ) ? ( a ) : ( b ) )
#endif
/*! /*!
* \brief Returns the maximum value between a and b * \brief Returns the maximum value between a and b
@@ -52,7 +59,9 @@
* \param [IN] b 2nd value * \param [IN] b 2nd value
* \retval maxValue Maximum value * \retval maxValue Maximum value
*/ */
#ifndef MAX
#define MAX( a, b ) ( ( ( a ) > ( b ) ) ? ( a ) : ( b ) ) #define MAX( a, b ) ( ( ( a ) > ( b ) ) ? ( a ) : ( b ) )
#endif
/*! /*!
* \brief Returns 2 raised to the power of n * \brief Returns 2 raised to the power of n
@@ -69,8 +78,8 @@ typedef union Version_u
{ {
struct Version_s struct Version_s
{ {
uint8_t Rfu;
uint8_t Revision; uint8_t Revision;
uint8_t Patch;
uint8_t Minor; uint8_t Minor;
uint8_t Major; uint8_t Major;
}Fields; }Fields;
@@ -162,4 +171,8 @@ void BoardCriticalSectionBegin( uint32_t *mask );
*/ */
void BoardCriticalSectionEnd( uint32_t *mask ); void BoardCriticalSectionEnd( uint32_t *mask );
#ifdef __cplusplus
}
#endif
#endif // __UTILITIES_H__ #endif // __UTILITIES_H__

File diff suppressed because it is too large Load Diff

View File

@@ -36,6 +36,15 @@
* layer and the supported features. * 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 * \example classA/NAMote72/main.c
* LoRaWAN class A application example for the NAMote72. * LoRaWAN class A application example for the NAMote72.
* *
@@ -63,10 +72,60 @@
* \example classC/NucleoL152/main.c * \example classC/NucleoL152/main.c
* LoRaWAN class C application example for the NucleoL152. * 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__ #ifndef __LORAMAC_H__
#define __LORAMAC_H__ #define __LORAMAC_H__
#ifdef __cplusplus
extern "C"
{
#endif
#include <stdint.h> #include <stdint.h>
#include <stdbool.h> #include <stdbool.h>
#include "utilities.h" #include "utilities.h"
@@ -90,24 +149,11 @@
*/ */
#define DOWN_LINK 1 #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 * LoRaMac MLME-Confirm queue length
*/ */
#define LORA_MAC_MLME_CONFIRM_QUEUE_LEN 5 #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 * Maximum number of multicast context
*/ */
@@ -116,34 +162,7 @@
/*! /*!
* Start value for multicast keys enumeration * 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 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;
/*! /*!
* End-Device activation type * End-Device activation type
@@ -164,7 +183,6 @@ typedef enum eActivationType
ACTIVATION_TYPE_OTAA = 2, ACTIVATION_TYPE_OTAA = 2,
}ActivationType_t; }ActivationType_t;
/*! /*!
* LoRaMAC channels parameters definition * LoRaMAC channels parameters definition
*/ */
@@ -222,9 +240,9 @@ typedef struct sChannelParams
}ChannelParams_t; }ChannelParams_t;
/*! /*!
* LoRaMAC receive window 2 channel parameters * LoRaMAC receive window channel parameters
*/ */
typedef struct sRx2ChannelParams typedef struct sRxChannelParams
{ {
/*! /*!
* Frequency in Hz * 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. * The allowed ranges are region specific. Please refer to \ref DR_0 to \ref DR_15 for details.
*/ */
uint8_t Datarate; uint8_t Datarate;
}Rx2ChannelParams_t; }RxChannelParams_t;
/*! /*!
* LoRaMAC receive window enumeration * LoRaMAC receive window enumeration
@@ -257,14 +275,22 @@ typedef enum eLoRaMacRxSlot
* LoRaMAC receive window 2 for class c - continuous listening * LoRaMAC receive window 2 for class c - continuous listening
*/ */
RX_SLOT_WIN_CLASS_C, RX_SLOT_WIN_CLASS_C,
/*!
* LoRaMAC class c multicast downlink
*/
RX_SLOT_WIN_CLASS_C_MULTICAST,
/*! /*!
* LoRaMAC class b ping slot window * LoRaMAC class b ping slot window
*/ */
RX_SLOT_WIN_PING_SLOT, RX_SLOT_WIN_CLASS_B_PING_SLOT,
/*! /*!
* LoRaMAC class b multicast slot window * 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; }LoRaMacRxSlot_t;
/*! /*!
@@ -328,14 +354,6 @@ typedef struct sLoRaMacCtxs
* \brief Size of MLME Confirm queue module context * \brief Size of MLME Confirm queue module context
*/ */
size_t ConfirmQueueNvmCtxSize; size_t ConfirmQueueNvmCtxSize;
/*!
* \brief Pointer to FCnt handler module context
*/
void* FCntHandlerNvmCtx;
/*!
* \brief Size of FCnt handler module context
*/
size_t FCntHandlerNvmCtxSize;
}LoRaMacCtxs_t; }LoRaMacCtxs_t;
/*! /*!
@@ -393,7 +411,11 @@ typedef struct sLoRaMacParams
/*! /*!
* LoRaMAC 2nd reception window settings * 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 * Uplink dwell time configuration. 0: No limit, 1: 400ms
*/ */
@@ -410,44 +432,8 @@ typedef struct sLoRaMacParams
* Antenna gain of the node * Antenna gain of the node
*/ */
float AntennaGain; float AntennaGain;
/*!
* Indicates if the node supports repeaters
*/
bool RepeaterSupport;
}LoRaMacParams_t; }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 * 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 * Timestamp in seconds since 00:00:00, Sunday 6th of January 1980
* (start of the GPS epoch) modulo 2^32 * (start of the GPS epoch) modulo 2^32
*/ */
uint32_t Time; SysTime_t Time;
/*! /*!
* Frequency * Frequency
*/ */
@@ -629,6 +615,10 @@ typedef union eLoRaMacFlags_t
* MLME-Ind pending * 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 * MAC cycle done
*/ */
@@ -679,6 +669,19 @@ typedef enum eMcps
MCPS_PROPRIETARY, MCPS_PROPRIETARY,
}Mcps_t; }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 * LoRaMAC MCPS-Request for an unconfirmed frame
*/ */
@@ -799,6 +802,11 @@ typedef struct sMcpsReq
*/ */
McpsReqProprietary_t Proprietary; McpsReqProprietary_t Proprietary;
}Req; }Req;
/*!
* MCPS-Request return parameters
*/
RequestReturnParam_t ReqReturn;
}McpsReq_t; }McpsReq_t;
/*! /*!
@@ -909,6 +917,10 @@ typedef struct sMcpsIndication
* The device address of the frame * The device address of the frame
*/ */
uint32_t DevAddress; uint32_t DevAddress;
/*!
* Set if a DeviceTimeAns MAC command was received.
*/
bool DeviceTimeAnsReceived;
}McpsIndication_t; }McpsIndication_t;
/*! /*!
@@ -937,6 +949,10 @@ typedef struct sMcpsIndication
*/ */
typedef enum eMlme typedef enum eMlme
{ {
/*!
* An unknown MLME service
*/
MLME_UNKNOWN,
/*! /*!
* Initiates the Over-the-Air activation * Initiates the Over-the-Air activation
* *
@@ -1033,18 +1049,6 @@ typedef enum eMlme
*/ */
typedef struct sMlmeReqJoin 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. * Datarate used for join request.
*/ */
@@ -1105,7 +1109,7 @@ typedef struct sMlmeReqDeriveMcSessionKeyPair
/*! /*!
* Address identifier to select the multicast group * Address identifier to select the multicast group
*/ */
AddressIdentifier_t AddrID; AddressIdentifier_t GroupID;
}MlmeReqDeriveMcSessionKeyPair_t; }MlmeReqDeriveMcSessionKeyPair_t;
/*! /*!
@@ -1144,6 +1148,11 @@ typedef struct sMlmeReq
*/ */
MlmeReqDeriveMcSessionKeyPair_t DeriveMcSessionKeyPair; MlmeReqDeriveMcSessionKeyPair_t DeriveMcSessionKeyPair;
}Req; }Req;
/*!
* MLME-Request return parameters
*/
RequestReturnParam_t ReqReturn;
}MlmeReq_t; }MlmeReq_t;
/*! /*!
@@ -1216,6 +1225,9 @@ typedef struct sMlmeIndication
* ----------------------------------------------| :-: | :-: * ----------------------------------------------| :-: | :-:
* \ref MIB_DEVICE_CLASS | YES | YES * \ref MIB_DEVICE_CLASS | YES | YES
* \ref MIB_NETWORK_ACTIVATION | 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_ADR | YES | YES
* \ref MIB_NET_ID | YES | YES * \ref MIB_NET_ID | YES | YES
* \ref MIB_DEV_ADDR | 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_APP_S_KEY_3 | NO | YES
* \ref MIB_MC_NWK_S_KEY_3 | NO | YES * \ref MIB_MC_NWK_S_KEY_3 | NO | YES
* \ref MIB_PUBLIC_NETWORK | YES | YES * \ref MIB_PUBLIC_NETWORK | YES | YES
* \ref MIB_REPEATER_SUPPORT | YES | YES
* \ref MIB_CHANNELS | YES | NO * \ref MIB_CHANNELS | YES | NO
* \ref MIB_RX2_CHANNEL | YES | YES * \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_MASK | YES | YES
* \ref MIB_CHANNELS_DEFAULT_MASK | YES | YES * \ref MIB_CHANNELS_DEFAULT_MASK | YES | YES
* \ref MIB_CHANNELS_NB_TRANS | YES | YES * \ref MIB_CHANNELS_NB_TRANS | YES | YES
@@ -1273,7 +1287,8 @@ typedef struct sMlmeIndication
* \ref MIB_ANTENNA_GAIN | YES | YES * \ref MIB_ANTENNA_GAIN | YES | YES
* \ref MIB_DEFAULT_ANTENNA_GAIN | YES | YES * \ref MIB_DEFAULT_ANTENNA_GAIN | YES | YES
* \ref MIB_NVM_CTXS | 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 * The following table provides links to the function implementations of the
* related MIB primitives: * related MIB primitives:
@@ -1297,6 +1312,22 @@ typedef enum eMib
* LoRaWAN Specification V1.0.2 * LoRaWAN Specification V1.0.2
*/ */
MIB_NETWORK_ACTIVATION, 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 * Adaptive data rate
* *
@@ -1451,14 +1482,6 @@ typedef enum eMib
* [true: public network, false: private network] * [true: public network, false: private network]
*/ */
MIB_PUBLIC_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 * Communication channels. A get request will return a
* pointer which references the first entry of the channel list. The * 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 * LoRaWAN Specification V1.0.2, chapter 3.3.2
*/ */
MIB_RX2_DEFAULT_CHANNEL, 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 * LoRaWAN channels mask
* *
@@ -1600,6 +1635,10 @@ typedef enum eMib
* LoRaWAN MAC layer operating version when activated by ABP. * LoRaWAN MAC layer operating version when activated by ABP.
*/ */
MIB_ABP_LORAWAN_VERSION, MIB_ABP_LORAWAN_VERSION,
/*!
* LoRaWAN MAC and regional parameter version.
*/
MIB_LORAWAN_VERSION,
/*! /*!
* Beacon interval in ms * Beacon interval in ms
*/ */
@@ -1677,6 +1716,24 @@ typedef union uMibParam
* Related MIB type: \ref MIB_NETWORK_ACTIVATION * Related MIB type: \ref MIB_NETWORK_ACTIVATION
*/ */
ActivationType_t NetworkActivation; 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 * Activation state of ADR
* *
@@ -1827,12 +1884,6 @@ typedef union uMibParam
* Related MIB type: \ref MIB_PUBLIC_NETWORK * Related MIB type: \ref MIB_PUBLIC_NETWORK
*/ */
bool EnablePublicNetwork; bool EnablePublicNetwork;
/*!
* Enable or disable repeater support
*
* Related MIB type: \ref MIB_REPEATER_SUPPORT
*/
bool EnableRepeaterSupport;
/*! /*!
* LoRaWAN Channel * LoRaWAN Channel
* *
@@ -1844,13 +1895,25 @@ typedef union uMibParam
* *
* Related MIB type: \ref MIB_RX2_CHANNEL * Related MIB type: \ref MIB_RX2_CHANNEL
*/ */
Rx2ChannelParams_t Rx2Channel; RxChannelParams_t Rx2Channel;
/*! /*!
* Channel for the receive window 2 * Channel for the receive window 2
* *
* Related MIB type: \ref MIB_RX2_DEFAULT_CHANNEL * 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 * Channel mask
* *
@@ -1928,7 +1991,7 @@ typedef union uMibParam
* *
* Related MIB type: \ref MIB_MULTICAST_CHANNEL * Related MIB type: \ref MIB_MULTICAST_CHANNEL
*/ */
MulticastChannel_t MulticastChannel; McChannelParams_t MulticastChannel;
/*! /*!
* System overall timing error in milliseconds. * System overall timing error in milliseconds.
* *
@@ -1965,6 +2028,16 @@ typedef union uMibParam
* Related MIB type: \ref MIB_ABP_LORAWAN_VERSION * Related MIB type: \ref MIB_ABP_LORAWAN_VERSION
*/ */
Version_t AbpLrWanVersion; 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 * Beacon interval in ms
* *
@@ -2131,7 +2204,17 @@ typedef enum eLoRaMacStatus
*/ */
LORAMAC_STATUS_SKIPPED_APP_DATA, 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, LORAMAC_STATUS_DUTYCYCLE_RESTRICTED,
/*! /*!
@@ -2175,7 +2258,11 @@ typedef enum eLoRaMacStatus
*/ */
LORAMAC_STATUS_CONFIRM_QUEUE_ERROR, 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 LORAMAC_STATUS_ERROR
}LoRaMacStatus_t; }LoRaMacStatus_t;
@@ -2260,10 +2347,6 @@ typedef enum LoRaMacNvmCtxModule_e
* Context for the confirm queue * Context for the confirm queue
*/ */
LORAMAC_NVMCTXMODULE_CONFIRM_QUEUE, LORAMAC_NVMCTXMODULE_CONFIRM_QUEUE,
/*!
* Context for the frame count handler
*/
LORAMAC_NVMCTXMODULE_FCNT_HANDLER
}LoRaMacNvmCtxModule_t; }LoRaMacNvmCtxModule_t;
@@ -2382,6 +2465,13 @@ LoRaMacStatus_t LoRaMacStart( void );
*/ */
LoRaMacStatus_t LoRaMacStop( 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. * Processes the LoRaMac events.
* *
@@ -2449,18 +2539,60 @@ LoRaMacStatus_t LoRaMacChannelAdd( uint8_t id, ChannelParams_t params );
LoRaMacStatus_t LoRaMacChannelRemove( uint8_t id ); 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. * \param [IN] channel - Multicast channel to set.
* *
* \retval LoRaMacStatus_t Status of the operation. Possible returns are: * \retval LoRaMacStatus_t Status of the operation. Possible returns are:
* \ref LORAMAC_STATUS_OK, * \ref LORAMAC_STATUS_OK,
* \ref LORAMAC_STATUS_BUSY, * \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 * \brief LoRaMAC MIB-Get
@@ -2526,32 +2658,15 @@ LoRaMacStatus_t LoRaMacMibSetRequestConfirm( MibRequestConfirm_t* mibSet );
* *
* \details The Mac layer management entity handles management services. The * \details The Mac layer management entity handles management services. The
* following code-snippet shows how to use the API to perform a * 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 * \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_t mlmeReq;
* mlmeReq.Type = MLME_JOIN; * mlmeReq.Type = MLME_JOIN;
* mlmeReq.Req.Join.DevEui = DevEui; * mlmeReq.Req.Join.Datarate = LORAWAN_DEFAULT_DATARATE;
* mlmeReq.Req.Join.JoinEui = JoinEui;
* *
* if( LoRaMacMlmeRequest( &mlmeReq ) == LORAMAC_STATUS_OK ) * if( LoRaMacMlmeRequest( &mlmeReq ) == LORAMAC_STATUS_OK )
* { * {
@@ -2605,6 +2720,18 @@ LoRaMacStatus_t LoRaMacMlmeRequest( MlmeReq_t* mlmeRequest );
*/ */
LoRaMacStatus_t LoRaMacMcpsRequest( McpsReq_t* mcpsRequest ); 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. * Automatically add the Region.h file at the end of LoRaMac.h file.
* This is required because Region.h uses definitions from LoRaMac.h * This is required because Region.h uses definitions from LoRaMac.h
@@ -2613,4 +2740,8 @@ LoRaMacStatus_t LoRaMacMcpsRequest( McpsReq_t* mcpsRequest );
/*! \} defgroup LORAMAC */ /*! \} defgroup LORAMAC */
#ifdef __cplusplus
}
#endif
#endif // __LORAMAC_H__ #endif // __LORAMAC_H__

View File

@@ -65,10 +65,6 @@ static bool CalcNextV10X( CalcNextAdrParams_t* adrNext, int8_t* drOut, int8_t* t
if( adrNext->AdrAckCounter >= adrNext->AdrAckLimit ) if( adrNext->AdrAckCounter >= adrNext->AdrAckLimit )
{ {
adrAckReq = true; adrAckReq = true;
// Set TX Power to maximum
getPhy.Attribute = PHY_MAX_TX_POWER;
phyParam = RegionGetPhyParam( adrNext->Region, &getPhy );
txPower = phyParam.Value;
} }
else else
{ {
@@ -76,6 +72,11 @@ static bool CalcNextV10X( CalcNextAdrParams_t* adrNext, int8_t* drOut, int8_t* t
} }
if( adrNext->AdrAckCounter >= ( adrNext->AdrAckLimit + adrNext->AdrAckDelay ) ) 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 ) if( ( adrNext->AdrAckCounter % adrNext->AdrAckDelay ) == 1 )
{ {
// Decrease the datarate // Decrease the datarate

View File

@@ -37,6 +37,11 @@
#ifndef __LORAMACADR_H__ #ifndef __LORAMACADR_H__
#define __LORAMACADR_H__ #define __LORAMACADR_H__
#ifdef __cplusplus
extern "C"
{
#endif
/*! \} defgroup LORAMACADR */ /*! \} defgroup LORAMACADR */
/* /*
@@ -101,4 +106,8 @@ typedef struct sCalcNextAdrParams
*/ */
bool LoRaMacAdrCalcNext( CalcNextAdrParams_t* adrNext, int8_t* drOut, int8_t* txPowOut, uint32_t* adrAckCounter ); bool LoRaMacAdrCalcNext( CalcNextAdrParams_t* adrNext, int8_t* drOut, int8_t* txPowOut, uint32_t* adrAckCounter );
#ifdef __cplusplus
}
#endif
#endif // __LORAMACADR_H__ #endif // __LORAMACADR_H__

File diff suppressed because it is too large Load Diff

View File

@@ -37,6 +37,11 @@
#ifndef __LORAMACCLASSB_H__ #ifndef __LORAMACCLASSB_H__
#define __LORAMACCLASSB_H__ #define __LORAMACCLASSB_H__
#ifdef __cplusplus
extern "C"
{
#endif
#include "systime.h" #include "systime.h"
#include "LoRaMacTypes.h" #include "LoRaMacTypes.h"
@@ -121,42 +126,15 @@ typedef enum ePingSlotState
*/ */
typedef struct sPingSlotContext 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 * Ping slot length time in ms
*/ */
uint32_t PingSlotWindow; uint32_t PingSlotWindow;
/*!
* Number of ping slots
*/
uint8_t PingNb;
/*!
* Period of the ping slots
*/
uint16_t PingPeriod;
/*! /*!
* Ping offset * Ping offset
*/ */
uint16_t PingOffset; 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 * Current symbol timeout. The node enlarges this variable in case of beacon
* loss. * loss.
@@ -184,10 +162,6 @@ typedef struct sBeaconContext
* Set if the node has acquired the beacon * Set if the node has acquired the beacon
*/ */
uint8_t BeaconAcquired : 1; 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 * Set if a beacon delay was set for the beacon acquisition
*/ */
@@ -205,10 +179,7 @@ typedef struct sBeaconContext
*/ */
uint8_t ResumeBeaconing : 1; uint8_t ResumeBeaconing : 1;
}Ctrl; }Ctrl;
/*!
* Beacon reception frequency
*/
uint32_t Frequency;
/*! /*!
* Current temperature * Current temperature
*/ */
@@ -216,15 +187,15 @@ typedef struct sBeaconContext
/*! /*!
* Beacon time received with the beacon frame * Beacon time received with the beacon frame
*/ */
TimerTime_t BeaconTime; SysTime_t BeaconTime;
/*! /*!
* Time when the last beacon was received * Time when the last beacon was received
*/ */
TimerTime_t LastBeaconRx; SysTime_t LastBeaconRx;
/*! /*!
* Time when the next beacon will be received * 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. * This is the time where the RX window will be opened.
* Its base is NextBeaconRx with temperature compensations * Its base is NextBeaconRx with temperature compensations
@@ -314,7 +285,7 @@ typedef struct sLoRaMacClassBParams
* Signature of callback function to be called by this module when the * Signature of callback function to be called by this module when the
* non-volatile needs to be saved. * non-volatile needs to be saved.
*/ */
typedef void ( *EventNvmCtxChanged )( void ); typedef void ( *LoRaMacClassBNvmEvent )( void );
/*! /*!
* \brief Initialize LoRaWAN Class B * \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] 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. * \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. * Restores the internal non-volatile context from passed pointer.
@@ -561,4 +532,8 @@ void LoRaMacClassBSetMulticastPeriodicity( MulticastCtx_t* multicastChannel );
void LoRaMacClassBProcess( void ); void LoRaMacClassBProcess( void );
#ifdef __cplusplus
}
#endif
#endif // __LORAMACCLASSB_H__ #endif // __LORAMACCLASSB_H__

View File

@@ -36,6 +36,11 @@
#ifndef __LORAMACCLASSBCONFIG_H__ #ifndef __LORAMACCLASSBCONFIG_H__
#define __LORAMACCLASSBCONFIG_H__ #define __LORAMACCLASSBCONFIG_H__
#ifdef __cplusplus
extern "C"
{
#endif
/*! /*!
* Defines the beacon interval in ms * Defines the beacon interval in ms
*/ */
@@ -112,4 +117,8 @@
*/ */
#define CLASSB_WINDOW_MOVE_EXPANSION_FACTOR 2 #define CLASSB_WINDOW_MOVE_EXPANSION_FACTOR 2
#ifdef __cplusplus
}
#endif
#endif // __LORAMACCLASSBCONFIG_H__ #endif // __LORAMACCLASSBCONFIG_H__

View File

@@ -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 ) Maintainer: Miguel Luis ( Semtech ), Daniel Jaeckle ( STACKFORCE ), Johannes Bruder ( STACKFORCE )
*/ */
#include <stddef.h>
#include "utilities.h" #include "utilities.h"
#include "LoRaMacCommands.h" #include "LoRaMacCommands.h"
#include "LoRaMacConfirmQueue.h" #include "LoRaMacConfirmQueue.h"
/* /*!
* Number of MAC Command slots * Number of MAC Command slots
*/ */
#define NUM_OF_MAC_COMMANDS 15 #define NUM_OF_MAC_COMMANDS 15
/* /*!
* Size of the CID field of MAC commands * 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 * Mac Commands list structure
*/ */
typedef struct sMacCommandsList typedef struct sMacCommandsList
@@ -52,7 +48,7 @@ typedef struct sMacCommandsList
MacCommand_t* Last; MacCommand_t* Last;
} MacCommandsList_t; } MacCommandsList_t;
/* /*!
* LoRaMac Commands Context structure * LoRaMac Commands Context structure
*/ */
typedef struct sLoRaMacCommandsCtx typedef struct sLoRaMacCommandsCtx
@@ -71,25 +67,25 @@ typedef struct sLoRaMacCommandsCtx
size_t SerializedCmdsSize; size_t SerializedCmdsSize;
} LoRaMacCommandsCtx_t; } LoRaMacCommandsCtx_t;
/* /*!
* Callback function to notify the upper layer about context change * Callback function to notify the upper layer about context change
*/ */
static EventNvmCtxChanged CommandsNvmCtxChanged; static LoRaMacCommandsNvmEvent CommandsNvmCtxChanged;
/* /*!
* Non-volatile module context. * Non-volatile module context.
*/ */
static LoRaMacCommandsCtx_t NvmCtx; static LoRaMacCommandsCtx_t NvmCtx;
/* Memory management functions */ /* Memory management functions */
/* /*!
* \brief Determines if a MAC command slot is free * \brief Determines if a MAC command slot is free
* *
* \param[IN] slot - Slot to check * \param[IN] slot - Slot to check
* \retval - Status of the operation * \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;
@@ -103,38 +99,37 @@ bool isSlotFree( const MacCommand_t* slot )
return true; return true;
} }
/* /*!
* \brief Allocates a new MAC command memory slot * \brief Allocates a new MAC command memory slot
* *
* \retval - Pointer to slot * \retval - Pointer to slot
*/ */
MacCommand_t* mallocNewMacCommandSlot( ) static MacCommand_t* MallocNewMacCommandSlot( void )
{ {
uint8_t itr = 0; uint8_t itr = 0;
while( isSlotFree( ( const MacCommand_t* ) &NvmCtx.MacCommandSlots[itr]) == false ) while( IsSlotFree( ( const MacCommand_t* )&NvmCtx.MacCommandSlots[itr] ) == false )
{ {
itr++; itr++;
if( itr == NUM_OF_MAC_COMMANDS ) if( itr == NUM_OF_MAC_COMMANDS )
{ {
return 0; return NULL;
} }
} }
return &NvmCtx.MacCommandSlots[itr]; return &NvmCtx.MacCommandSlots[itr];
} }
/*!
/*
* \brief Free memory slot * \brief Free memory slot
* *
* \param[IN] slot - Slot to free * \param[IN] slot - Slot to free
* *
* \retval - Status of the operation * \retval - Status of the operation
*/ */
bool freeMacCommandSlot( MacCommand_t* slot ) static bool FreeMacCommandSlot( MacCommand_t* slot )
{ {
if( slot == 0 ) if( slot == NULL )
{ {
return false; return false;
} }
@@ -144,73 +139,72 @@ bool freeMacCommandSlot( MacCommand_t* slot )
return true; return true;
} }
/* Linked list functions */ /* Linked list functions */
/* /*!
* \brief Initialize list * \brief Initialize list
* *
* \param[IN] list - List that shall be initialized * \param[IN] list - List that shall be initialized
* \retval - Status of the operation * \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; return false;
} }
list->First = 0; list->First = NULL;
list->Last = 0; list->Last = NULL;
return true; return true;
} }
/* /*!
* \brief Add an element to the list * \brief Add an element to the list
* *
* \param[IN] list - List where the element shall be added. * \param[IN] list - List where the element shall be added.
* \param[IN] element - Element to add * \param[IN] element - Element to add
* \retval - Status of the operation * \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; return false;
} }
/* Check if this is the first entry to enter the list. */ // Check if this is the first entry to enter the list.
if( list->First == 0 ) if( list->First == NULL )
{ {
list->First = element; 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 ) if( list->Last )
{ {
list->Last->Next = element; list->Last->Next = element;
} }
/* Update the next point of this entry. */ // Update the next point of this entry.
element->Next = 0; element->Next = NULL;
/* Update the last entry of the list. */ // Update the last entry of the list.
list->Last = element; list->Last = element;
return true; return true;
} }
/* /*!
* \brief Return the previous element in the list. * \brief Return the previous element in the list.
* *
* \param[IN] list - List * \param[IN] list - List
* \param[IN] element - Element where the previous element shall be searched * \param[IN] element - Element where the previous element shall be searched
* \retval - Status of the operation * \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; return NULL;
} }
@@ -220,14 +214,11 @@ static MacCommand_t* linkedListGetPrevious( MacCommandsList_t* list, MacCommand_
// Start at the head of the list // Start at the head of the list
curElement = list->First; curElement = list->First;
/* // When current element is the first of the list, there's no previous element so we can return NULL immediately.
* When current element is the first of the list, there's no previous element so we can return NULL immediately.
*/
if( element != curElement ) if( element != curElement )
{ {
// Loop through all elements until the end is reached or the next of current is the current element. // 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; curElement = curElement->Next;
} }
@@ -240,21 +231,21 @@ static MacCommand_t* linkedListGetPrevious( MacCommandsList_t* list, MacCommand_
return curElement; return curElement;
} }
/* /*!
* \brief Remove an element from the list * \brief Remove an element from the list
* *
* \param[IN] list - List where the element shall be removed from. * \param[IN] list - List where the element shall be removed from.
* \param[IN] element - Element to remove * \param[IN] element - Element to remove
* \retval - Status of the operation * \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; return false;
} }
MacCommand_t* PrevElement = linkedListGetPrevious( list, element ); MacCommand_t* PrevElement = LinkedListGetPrevious( list, element );
if( list->First == element ) if( list->First == element )
{ {
@@ -266,12 +257,12 @@ static bool linkedListRemove( MacCommandsList_t* list, MacCommand_t* element )
list->Last = PrevElement; list->Last = PrevElement;
} }
if( PrevElement ) if( PrevElement != NULL )
{ {
PrevElement->Next = element->Next; PrevElement->Next = element->Next;
} }
element->Next = 0; element->Next = NULL;
return true; return true;
} }
@@ -290,6 +281,7 @@ static bool IsSticky( uint8_t cid )
case MOTE_MAC_DL_CHANNEL_ANS: case MOTE_MAC_DL_CHANNEL_ANS:
case MOTE_MAC_RX_PARAM_SETUP_ANS: case MOTE_MAC_RX_PARAM_SETUP_ANS:
case MOTE_MAC_RX_TIMING_SETUP_ANS: case MOTE_MAC_RX_TIMING_SETUP_ANS:
case MOTE_MAC_TX_PARAM_SETUP_ANS:
return true; return true;
default: default:
return false; return false;
@@ -307,13 +299,12 @@ static void NvmCtxCallback( void )
} }
} }
LoRaMacCommandStatus_t LoRaMacCommandsInit( EventNvmCtxChanged commandsNvmCtxChanged ) LoRaMacCommandStatus_t LoRaMacCommandsInit( LoRaMacCommandsNvmEvent commandsNvmCtxChanged )
{ {
// Initialize with default // 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 // Assign callback
CommandsNvmCtxChanged = commandsNvmCtxChanged; CommandsNvmCtxChanged = commandsNvmCtxChanged;
@@ -343,22 +334,22 @@ void* LoRaMacCommandsGetNvmCtx( size_t* commandsNvmCtxSize )
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; return LORAMAC_COMMANDS_ERROR_NPE;
} }
MacCommand_t* newCmd; MacCommand_t* newCmd;
// Allocate a memory slot // Allocate a memory slot
newCmd = mallocNewMacCommandSlot( ); newCmd = MallocNewMacCommandSlot( );
if( newCmd == 0 ) if( newCmd == NULL )
{ {
return LORAMAC_COMMANDS_ERROR_MEMORY; return LORAMAC_COMMANDS_ERROR_MEMORY;
} }
// Add it to the list of Mac commands // Add it to the list of Mac commands
if( linkedListAdd( &NvmCtx.MacCommandList, newCmd ) == false ) if( LinkedListAdd( &NvmCtx.MacCommandList, newCmd ) == false )
{ {
return LORAMAC_COMMANDS_ERROR; return LORAMAC_COMMANDS_ERROR;
} }
@@ -384,7 +375,7 @@ LoRaMacCommandStatus_t LoRaMacCommandsRemoveCmd( MacCommand_t* macCmd )
} }
// Remove the Mac command element from MacCommandList // 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; return LORAMAC_COMMANDS_ERROR_CMD_NOT_FOUND;
} }
@@ -392,7 +383,7 @@ LoRaMacCommandStatus_t LoRaMacCommandsRemoveCmd( MacCommand_t* macCmd )
NvmCtx.SerializedCmdsSize -= ( CID_FIELD_SIZE + macCmd->PayloadSize ); NvmCtx.SerializedCmdsSize -= ( CID_FIELD_SIZE + macCmd->PayloadSize );
// Free the MacCommand Slot // Free the MacCommand Slot
if( freeMacCommandSlot( macCmd ) == false ) if( FreeMacCommandSlot( macCmd ) == false )
{ {
return LORAMAC_COMMANDS_ERROR; return LORAMAC_COMMANDS_ERROR;
} }
@@ -410,19 +401,19 @@ LoRaMacCommandStatus_t LoRaMacCommandsGetCmd( uint8_t cid, MacCommand_t** macCmd
curElement = NvmCtx.MacCommandList.First; curElement = NvmCtx.MacCommandList.First;
// Loop through all elements until we find the element with the given CID // 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; curElement = curElement->Next;
} }
// Update the pointer anyway
*macCmd = curElement;
// Handle error in case if we reached the end without finding it. // Handle error in case if we reached the end without finding it.
if( curElement == NULL ) if( curElement == NULL )
{ {
return LORAMAC_COMMANDS_ERROR_CMD_NOT_FOUND; return LORAMAC_COMMANDS_ERROR_CMD_NOT_FOUND;
} }
*macCmd = curElement;
return LORAMAC_COMMANDS_SUCCESS; return LORAMAC_COMMANDS_SUCCESS;
} }
@@ -435,7 +426,7 @@ LoRaMacCommandStatus_t LoRaMacCommandsRemoveNoneStickyCmds( void )
curElement = NvmCtx.MacCommandList.First; curElement = NvmCtx.MacCommandList.First;
// Loop through all elements // Loop through all elements
while( curElement ) while( curElement != NULL )
{ {
if( curElement->IsSticky == false ) if( curElement->IsSticky == false )
{ {
@@ -466,16 +457,9 @@ LoRaMacCommandStatus_t LoRaMacCommandsRemoveStickyAnsCmds( void )
while( curElement != NULL ) while( curElement != NULL )
{ {
nexElement = curElement->Next; 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 ); LoRaMacCommandsRemoveCmd( curElement );
break;
}
}
} }
curElement = nexElement; curElement = nexElement;
} }
@@ -493,28 +477,28 @@ LoRaMacCommandStatus_t LoRaMacCommandsGetSizeSerializedCmds( size_t* size )
} }
*size = NvmCtx.SerializedCmdsSize; *size = NvmCtx.SerializedCmdsSize;
return LORAMAC_COMMANDS_SUCCESS; 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 ) ) if( ( buffer == NULL ) || ( effectiveSize == NULL ) )
{ {
return LORAMAC_COMMANDS_ERROR_NPE; return LORAMAC_COMMANDS_ERROR_NPE;
} }
MacCommand_t* curElement;
curElement = NvmCtx.MacCommandList.First;
uint8_t itr = 0;
// Loop through all elements // Loop through all elements which fits into the buffer
while( curElement ) while( curElement != NULL )
{ {
// If the next MAC command still fits into the buffer, add it. // If the next MAC command still fits into the buffer, add it.
if( ( availableSize - itr ) >= ( CID_FIELD_SIZE + curElement->PayloadSize ) ) if( ( availableSize - itr ) >= ( CID_FIELD_SIZE + curElement->PayloadSize ) )
{ {
buffer[itr++] = curElement->CID; buffer[itr++] = curElement->CID;
memcpy1( &buffer[itr], curElement->Payload, curElement->PayloadSize ); memcpy1( &buffer[itr], curElement->Payload, curElement->PayloadSize );
itr = itr + curElement->PayloadSize; itr += curElement->PayloadSize;
} }
else else
{ {
@@ -523,6 +507,18 @@ LoRaMacCommandStatus_t LoRaMacCommandsSerializeCmds( size_t availableSize, size_
curElement = curElement->Next; 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; return LORAMAC_COMMANDS_SUCCESS;
} }
@@ -538,7 +534,7 @@ LoRaMacCommandStatus_t LoRaMacCommandsStickyCmdsPending( bool* cmdsPending )
*cmdsPending = false; *cmdsPending = false;
// Loop through all elements // Loop through all elements
while( curElement ) while( curElement != NULL )
{ {
if( curElement->IsSticky == true ) if( curElement->IsSticky == true )
{ {
@@ -551,3 +547,103 @@ LoRaMacCommandStatus_t LoRaMacCommandsStickyCmdsPending( bool* cmdsPending )
return LORAMAC_COMMANDS_SUCCESS; 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;
}

View File

@@ -35,6 +35,11 @@
#ifndef __LORAMAC_COMMANDS_H__ #ifndef __LORAMAC_COMMANDS_H__
#define __LORAMAC_COMMANDS_H__ #define __LORAMAC_COMMANDS_H__
#ifdef __cplusplus
extern "C"
{
#endif
#include <stdint.h> #include <stdint.h>
#include <stddef.h> #include <stddef.h>
#include "LoRaMacTypes.h" #include "LoRaMacTypes.h"
@@ -109,7 +114,7 @@ typedef enum eLoRaMacCommandsStatus
* Signature of callback function to be called by this module when the * Signature of callback function to be called by this module when the
* non-volatile needs to be saved. * non-volatile needs to be saved.
*/ */
typedef void ( *EventNvmCtxChanged )( void ); typedef void ( *LoRaMacCommandsNvmEvent )( void );
/*! /*!
* \brief Initialization of LoRaMac MAC commands module * \brief Initialization of LoRaMac MAC commands module
@@ -119,7 +124,7 @@ typedef void ( *EventNvmCtxChanged )( void );
* *
* \retval - Status of the operation * \retval - Status of the operation
*/ */
LoRaMacCommandStatus_t LoRaMacCommandsInit( EventNvmCtxChanged commandsNvmCtxChanged ); LoRaMacCommandStatus_t LoRaMacCommandsInit( LoRaMacCommandsNvmEvent commandsNvmCtxChanged );
/*! /*!
* Restores the internal non-volatile context from passed pointer. * 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 ); 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 */ /*! \} addtogroup LORAMAC */
#ifdef __cplusplus
}
#endif
#endif // __LORAMAC_COMMANDS_H__ #endif // __LORAMAC_COMMANDS_H__

View File

@@ -66,7 +66,7 @@ typedef struct sLoRaMacConfirmQueueCtx
/* /*
* Callback function to notify the upper layer about context change * Callback function to notify the upper layer about context change
*/ */
EventNvmCtxChanged EventNvmCtxChanged; LoRaMacConfirmQueueNvmEvent LoRaMacConfirmQueueNvmEvent;
/*! /*!
* Non-volatile module context. * Non-volatile module context.
*/ */
@@ -112,26 +112,47 @@ static MlmeConfirmQueue_t* DecreaseBufferPointer( MlmeConfirmQueue_t* bufferPoin
return bufferPointer; 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 ) static MlmeConfirmQueue_t* GetElement( Mlme_t request, MlmeConfirmQueue_t* bufferStart, MlmeConfirmQueue_t* bufferEnd )
{ {
MlmeConfirmQueue_t* element = bufferStart; 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 ) if( element->Request == request )
{ {
// We have found the element // We have found the element
return element; return element;
} }
else
{
element = IncreaseBufferPointer( element ); element = IncreaseBufferPointer( element );
} }
}
return NULL; return NULL;
} }
void LoRaMacConfirmQueueInit( LoRaMacPrimitives_t* primitives, EventNvmCtxChanged confirmQueueNvmCtxChanged ) void LoRaMacConfirmQueueInit( LoRaMacPrimitives_t* primitives, LoRaMacConfirmQueueNvmEvent confirmQueueNvmCtxChanged )
{ {
ConfirmQueueCtx.Primitives = primitives; ConfirmQueueCtx.Primitives = primitives;
@@ -151,7 +172,7 @@ void LoRaMacConfirmQueueInit( LoRaMacPrimitives_t* primitives, EventNvmCtxChange
ConfirmQueueCtx.ConfirmQueueNvmCtx->CommonStatus = LORAMAC_EVENT_INFO_STATUS_ERROR; ConfirmQueueCtx.ConfirmQueueNvmCtx->CommonStatus = LORAMAC_EVENT_INFO_STATUS_ERROR;
// Assign callback // Assign callback
ConfirmQueueCtx.EventNvmCtxChanged = confirmQueueNvmCtxChanged; ConfirmQueueCtx.LoRaMacConfirmQueueNvmEvent = confirmQueueNvmCtxChanged;
} }
bool LoRaMacConfirmQueueRestoreNvmCtx( void* confirmQueueNvmCtx ) bool LoRaMacConfirmQueueRestoreNvmCtx( void* confirmQueueNvmCtx )
@@ -176,7 +197,7 @@ void* LoRaMacConfirmQueueGetNvmCtx( size_t* confirmQueueNvmCtxSize )
bool LoRaMacConfirmQueueAdd( MlmeConfirmQueue_t* mlmeConfirm ) 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 // Protect the buffer against overwrites
return false; return false;
@@ -197,7 +218,7 @@ bool LoRaMacConfirmQueueAdd( MlmeConfirmQueue_t* mlmeConfirm )
bool LoRaMacConfirmQueueRemoveLast( void ) bool LoRaMacConfirmQueueRemoveLast( void )
{ {
if( ConfirmQueueCtx.ConfirmQueueNvmCtx->MlmeConfirmQueueCnt == 0 ) if( IsListEmpty( ConfirmQueueCtx.ConfirmQueueNvmCtx->MlmeConfirmQueueCnt ) == true )
{ {
return false; return false;
} }
@@ -212,7 +233,7 @@ bool LoRaMacConfirmQueueRemoveLast( void )
bool LoRaMacConfirmQueueRemoveFirst( void ) bool LoRaMacConfirmQueueRemoveFirst( void )
{ {
if( ConfirmQueueCtx.ConfirmQueueNvmCtx->MlmeConfirmQueueCnt == 0 ) if( IsListEmpty( ConfirmQueueCtx.ConfirmQueueNvmCtx->MlmeConfirmQueueCnt ) == true )
{ {
return false; return false;
} }
@@ -229,7 +250,7 @@ void LoRaMacConfirmQueueSetStatus( LoRaMacEventInfoStatus_t status, Mlme_t reque
{ {
MlmeConfirmQueue_t* element = NULL; MlmeConfirmQueue_t* element = NULL;
if( ConfirmQueueCtx.ConfirmQueueNvmCtx->MlmeConfirmQueueCnt > 0 ) if( IsListEmpty( ConfirmQueueCtx.ConfirmQueueNvmCtx->MlmeConfirmQueueCnt ) == false )
{ {
element = GetElement( request, ConfirmQueueCtx.BufferStart, ConfirmQueueCtx.BufferEnd ); element = GetElement( request, ConfirmQueueCtx.BufferStart, ConfirmQueueCtx.BufferEnd );
if( element != NULL ) if( element != NULL )
@@ -244,7 +265,7 @@ LoRaMacEventInfoStatus_t LoRaMacConfirmQueueGetStatus( Mlme_t request )
{ {
MlmeConfirmQueue_t* element = NULL; MlmeConfirmQueue_t* element = NULL;
if( ConfirmQueueCtx.ConfirmQueueNvmCtx->MlmeConfirmQueueCnt > 0 ) if( IsListEmpty( ConfirmQueueCtx.ConfirmQueueNvmCtx->MlmeConfirmQueueCnt ) == false )
{ {
element = GetElement( request, ConfirmQueueCtx.BufferStart, ConfirmQueueCtx.BufferEnd ); element = GetElement( request, ConfirmQueueCtx.BufferStart, ConfirmQueueCtx.BufferEnd );
if( element != NULL ) if( element != NULL )
@@ -261,7 +282,7 @@ void LoRaMacConfirmQueueSetStatusCmn( LoRaMacEventInfoStatus_t status )
ConfirmQueueCtx.ConfirmQueueNvmCtx->CommonStatus = status; ConfirmQueueCtx.ConfirmQueueNvmCtx->CommonStatus = status;
if( ConfirmQueueCtx.ConfirmQueueNvmCtx->MlmeConfirmQueueCnt > 0 ) if( IsListEmpty( ConfirmQueueCtx.ConfirmQueueNvmCtx->MlmeConfirmQueueCnt ) == false )
{ {
do do
{ {
@@ -333,7 +354,7 @@ uint8_t LoRaMacConfirmQueueGetCnt( void )
bool LoRaMacConfirmQueueIsFull( void ) bool LoRaMacConfirmQueueIsFull( void )
{ {
if( ConfirmQueueCtx.ConfirmQueueNvmCtx->MlmeConfirmQueueCnt >= LORA_MAC_MLME_CONFIRM_QUEUE_LEN ) if( IsListFull( ConfirmQueueCtx.ConfirmQueueNvmCtx->MlmeConfirmQueueCnt ) == true )
{ {
return true; return true;
} }

View File

@@ -39,6 +39,11 @@
#ifndef __LORAMAC_CONFIRMQUEUE_H__ #ifndef __LORAMAC_CONFIRMQUEUE_H__
#define __LORAMAC_CONFIRMQUEUE_H__ #define __LORAMAC_CONFIRMQUEUE_H__
#ifdef __cplusplus
extern "C"
{
#endif
#include <stdbool.h> #include <stdbool.h>
#include <stdint.h> #include <stdint.h>
@@ -77,7 +82,7 @@ typedef struct sMlmeConfirmQueue
* Signature of callback function to be called by this module when the * Signature of callback function to be called by this module when the
* non-volatile needs to be saved. * non-volatile needs to be saved.
*/ */
typedef void ( *EventNvmCtxChanged )( void ); typedef void ( *LoRaMacConfirmQueueNvmEvent )( void );
/*! /*!
* \brief Initializes the confirm queue * \brief Initializes the confirm queue
@@ -87,7 +92,7 @@ typedef void ( *EventNvmCtxChanged )( void );
* \param [IN] confirmQueueNvmCtxChanged - Callback function which will be called when the * \param [IN] confirmQueueNvmCtxChanged - Callback function which will be called when the
* non-volatile context needs to be saved. * 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. * Restores the internal non-volatile context from passed pointer.
@@ -192,4 +197,8 @@ uint8_t LoRaMacConfirmQueueGetCnt( void );
*/ */
bool LoRaMacConfirmQueueIsFull( void ); bool LoRaMacConfirmQueueIsFull( void );
#ifdef __cplusplus
}
#endif
#endif // __LORAMAC_CONFIRMQUEUE_H__ #endif // __LORAMAC_CONFIRMQUEUE_H__

File diff suppressed because it is too large Load Diff

View File

@@ -37,6 +37,11 @@
#ifndef __LORAMAC_CRYPTO_H__ #ifndef __LORAMAC_CRYPTO_H__
#define __LORAMAC_CRYPTO_H__ #define __LORAMAC_CRYPTO_H__
#ifdef __cplusplus
extern "C"
{
#endif
#include <stdlib.h> #include <stdlib.h>
#include <stdint.h> #include <stdint.h>
#include <stdbool.h> #include <stdbool.h>
@@ -44,6 +49,26 @@
#include "LoRaMacTypes.h" #include "LoRaMacTypes.h"
#include "LoRaMacMessageTypes.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 * LoRaMac Cryto Status
*/ */
@@ -70,9 +95,21 @@ typedef enum eLoRaMacCryptoStatus
*/ */
LORAMAC_CRYPTO_FAIL_RJCOUNT0_OVERFLOW, 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 * Not allowed parameter value
*/ */
@@ -125,7 +162,7 @@ typedef enum eLoRaMacCryptoStatus
* crypto module context. * crypto module context.
* *
*/ */
typedef void ( *EventNvmCtxChanged )( void ); typedef void ( *LoRaMacCryptoNvmEvent )( void );
/*! /*!
* Initialization of LoRaMac Crypto module * Initialization of LoRaMac Crypto module
@@ -135,7 +172,7 @@ typedef void ( *EventNvmCtxChanged )( void );
* non-volatile context have to be stored. * non-volatile context have to be stored.
* \retval - Status of the operation * \retval - Status of the operation
*/ */
LoRaMacCryptoStatus_t LoRaMacCryptoInit( EventNvmCtxChanged cryptoNvmCtxChanged ); LoRaMacCryptoStatus_t LoRaMacCryptoInit( LoRaMacCryptoNvmEvent cryptoNvmCtxChanged );
/*! /*!
* Sets the LoRaWAN specification version to be used. * Sets the LoRaWAN specification version to be used.
@@ -164,6 +201,34 @@ LoRaMacCryptoStatus_t LoRaMacCryptoRestoreNvmCtx( void* cryptoNvmCtx );
*/ */
void* LoRaMacCryptoGetNvmCtx( size_t* cryptoNvmCtxSize ); 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 * 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 ); 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 ) * 1.1.x
* \param[IN] nonce - Nonce value ( nonce <= 15) * McRootKey = aes128_encrypt(AppKey, 0x20 | pad16)
* \param[IN] devEUI - DevEUI Value *
* \param[IN] keyID - Key identifier of the root key to use to perform the derivation ( AppKey )
* \retval - Status of the operation * \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 * Derives a Multicast group key pair ( McAppSKey, McNwkSKey ) from McKey
@@ -260,4 +337,8 @@ LoRaMacCryptoStatus_t LoRaMacCryptoDeriveMcSessionKeyPair( AddressIdentifier_t a
/*! \} addtogroup LORAMAC */ /*! \} addtogroup LORAMAC */
#ifdef __cplusplus
}
#endif
#endif // __LORAMAC_CRYPTO_H__ #endif // __LORAMAC_CRYPTO_H__

View File

@@ -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;
}

View File

@@ -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__

View File

@@ -37,13 +37,54 @@
#ifndef __LORAMAC_HEADER_TYPES_H__ #ifndef __LORAMAC_HEADER_TYPES_H__
#define __LORAMAC_HEADER_TYPES_H__ #define __LORAMAC_HEADER_TYPES_H__
#ifdef __cplusplus
extern "C"
{
#endif
#include <stdint.h> #include <stdint.h>
/*! Frame header (FHDR) maximum field size */ /*! MAC header field size */
#define LORAMAC_FHDR_MAX_FIELD_SIZE 22 #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 */ /*! 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 */ /*! FHDR Frame control field size */
#define LORAMAC_FHDR_F_CTRL_FIELD_SIZE 1 #define LORAMAC_FHDR_F_CTRL_FIELD_SIZE 1
@@ -54,6 +95,102 @@
/*! FOpts maximum field size */ /*! 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 * LoRaMAC field definition of DLSettings
@@ -183,4 +320,8 @@ typedef struct sLoRaMacFrameHeader
/*! \} addtogroup LORAMAC */ /*! \} addtogroup LORAMAC */
#ifdef __cplusplus
}
#endif
#endif // __LORAMAC_HEADER_TYPES_H__ #endif // __LORAMAC_HEADER_TYPES_H__

View File

@@ -37,43 +37,14 @@
#ifndef __LORAMAC_MESSAGE_TYPES_H__ #ifndef __LORAMAC_MESSAGE_TYPES_H__
#define __LORAMAC_MESSAGE_TYPES_H__ #define __LORAMAC_MESSAGE_TYPES_H__
#ifdef __cplusplus
extern "C"
{
#endif
#include <stdint.h> #include <stdint.h>
#include "LoRaMacHeaderTypes.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 * LoRaMac type for Join-request message
*/ */
@@ -324,4 +295,8 @@ typedef struct sLoRaMacMessage
/*! \} addtogroup LORAMAC */ /*! \} addtogroup LORAMAC */
#ifdef __cplusplus
}
#endif
#endif // __LORAMAC_MESSAGE_TYPES_H__ #endif // __LORAMAC_MESSAGE_TYPES_H__

View File

@@ -47,10 +47,10 @@ LoRaMacParserStatus_t LoRaMacParserJoinAccept( LoRaMacMessageJoinAccept_t* macMs
macMsg->RxDelay = macMsg->Buffer[bufItr++]; 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 ); memcpy1( macMsg->CFList, &macMsg->Buffer[bufItr], LORAMAC_CF_LIST_FIELD_SIZE );
bufItr = bufItr + LORAMAC_C_FLIST_FIELD_SIZE; bufItr = bufItr + LORAMAC_CF_LIST_FIELD_SIZE;
} }
else if( ( macMsg->BufSize - LORAMAC_MIC_FIELD_SIZE - bufItr ) > 0 ) else if( ( macMsg->BufSize - LORAMAC_MIC_FIELD_SIZE - bufItr ) > 0 )
{ {

View File

@@ -37,6 +37,11 @@
#ifndef __LORAMAC_PARSER_H__ #ifndef __LORAMAC_PARSER_H__
#define __LORAMAC_PARSER_H__ #define __LORAMAC_PARSER_H__
#ifdef __cplusplus
extern "C"
{
#endif
#include <stdint.h> #include <stdint.h>
#include "LoRaMacMessageTypes.h" #include "LoRaMacMessageTypes.h"
@@ -82,5 +87,9 @@ LoRaMacParserStatus_t LoRaMacParserData( LoRaMacMessageData_t *macMsg );
/*! \} addtogroup LORAMAC */ /*! \} addtogroup LORAMAC */
#ifdef __cplusplus
}
#endif
#endif // __LORAMAC_PARSER_H__ #endif // __LORAMAC_PARSER_H__

View File

@@ -107,7 +107,7 @@ LoRaMacSerializerStatus_t LoRaMacSerializerReJoinType0or2( LoRaMacMessageReJoinT
macMsg->Buffer[bufItr++] = macMsg->ReJoinType; 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; bufItr += LORAMAC_NET_ID_FIELD_SIZE;
memcpyr( &macMsg->Buffer[bufItr], macMsg->DevEUI, LORAMAC_DEV_EUI_FIELD_SIZE ); memcpyr( &macMsg->Buffer[bufItr], macMsg->DevEUI, LORAMAC_DEV_EUI_FIELD_SIZE );
@@ -130,24 +130,24 @@ LoRaMacSerializerStatus_t LoRaMacSerializerData( LoRaMacMessageData_t* macMsg )
// Check macMsg->BufSize // Check macMsg->BufSize
uint16_t computedBufSize = LORAMAC_MHDR_FIELD_SIZE 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_CTRL_FIELD_SIZE
+ LORAMAC_FHDR_F_CNT_FIELD_SIZE; + LORAMAC_FHDR_F_CNT_FIELD_SIZE;
if( macMsg->FRMPayloadSize == 0 ) computedBufSize += macMsg->FHDR.FCtrl.Bits.FOptsLen;
if( macMsg->FRMPayloadSize > 0 )
{ {
computedBufSize += LORAMAC_F_PORT_FIELD_SIZE;
}
computedBufSize += macMsg->FRMPayloadSize;
computedBufSize += LORAMAC_MIC_FIELD_SIZE;
if( macMsg->BufSize < computedBufSize ) if( macMsg->BufSize < computedBufSize )
{ {
return LORAMAC_SERIALIZER_ERROR_BUF_SIZE; return LORAMAC_SERIALIZER_ERROR_BUF_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;
}
}
macMsg->Buffer[bufItr++] = macMsg->MHDR.Value; macMsg->Buffer[bufItr++] = macMsg->MHDR.Value;

View File

@@ -36,6 +36,11 @@
*/ */
#ifndef __LORAMAC_SERIALIZER_H__ #ifndef __LORAMAC_SERIALIZER_H__
#define __LORAMAC_SERIALIZER_H__ #define __LORAMAC_SERIALIZER_H__
#ifdef __cplusplus
extern "C"
{
#endif
#include <stdint.h> #include <stdint.h>
#include "LoRaMacMessageTypes.h" #include "LoRaMacMessageTypes.h"
@@ -97,5 +102,9 @@ LoRaMacSerializerStatus_t LoRaMacSerializerData( LoRaMacMessageData_t* macMsg );
/*! \} addtogroup LORAMAC */ /*! \} addtogroup LORAMAC */
#ifdef __cplusplus
}
#endif
#endif // __LORAMAC_SERIALIZER_H__ #endif // __LORAMAC_SERIALIZER_H__

View File

@@ -36,6 +36,11 @@
#ifndef __LORAMACTEST_H__ #ifndef __LORAMACTEST_H__
#define __LORAMACTEST_H__ #define __LORAMACTEST_H__
#ifdef __cplusplus
extern "C"
{
#endif
/*! /*!
* \brief Enabled or disables the duty cycle * \brief Enabled or disables the duty cycle
* *
@@ -48,4 +53,8 @@ void LoRaMacTestSetDutyCycleOn( bool enable );
/*! \} defgroup LORAMACTEST */ /*! \} defgroup LORAMACTEST */
#ifdef __cplusplus
}
#endif
#endif // __LORAMACTEST_H__ #endif // __LORAMACTEST_H__

View File

@@ -35,6 +35,11 @@
#ifndef __LORAMAC_TYPES_H__ #ifndef __LORAMAC_TYPES_H__
#define __LORAMAC_TYPES_H__ #define __LORAMAC_TYPES_H__
#ifdef __cplusplus
extern "C"
{
#endif
#include <stdint.h> #include <stdint.h>
#include <stdbool.h> #include <stdbool.h>
#include "timer.h" #include "timer.h"
@@ -47,7 +52,34 @@
/*! /*!
* Start value for multicast keys enumeration * 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. * LoRaWAN Frame type enumeration to differ between the possible data up/down frame configurations.
@@ -162,10 +194,14 @@ typedef enum eKeyIdentifier
* Application session key * Application session key
*/ */
APP_S_KEY, APP_S_KEY,
/*!
* Multicast root key
*/
MC_ROOT_KEY,
/*! /*!
* Multicast key encryption key * Multicast key encryption key
*/ */
MC_KE_KEY = LORAMAC_CRYPTO_MULITCAST_KEYS, MC_KE_KEY = LORAMAC_CRYPTO_MULTICAST_KEYS,
/*! /*!
* Multicast root key index 0 * Multicast root key index 0
*/ */
@@ -251,27 +287,13 @@ typedef enum eAddressIdentifier
UNICAST_DEV_ADDR = 4, UNICAST_DEV_ADDR = 4,
}AddressIdentifier_t; }AddressIdentifier_t;
/*!
* Multicast context
*/
typedef struct sMulticastCtx
{
/* /*
* Address identifier * Multicast Rx window parameters
*/ */
AddressIdentifier_t AddrID; typedef union uMcRxParams
/*! {
* Address struct
*/ {
uint32_t Address;
/*!
* Downlink counter
*/
uint32_t* DownLinkCounter;
/*!
* True if the entry is active
*/
bool IsEnabled;
/*! /*!
* Reception frequency of the ping slot windows * Reception frequency of the ping slot windows
*/ */
@@ -281,10 +303,105 @@ typedef struct sMulticastCtx
*/ */
int8_t Datarate; int8_t Datarate;
/*! /*!
* This parameter is necessary for class b operation. It defines the * This parameter is necessary for class B operation. It defines the
* periodicity of the multicast downlink slots * periodicity of the multicast downlink slots
*/ */
uint16_t Periodicity; 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 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;
/*
* Following parameters are only used for ClassB multicast channels
*/
/*! /*!
* Number of multicast slots. The variable can be * Number of multicast slots. The variable can be
* calculated as follows: * calculated as follows:
@@ -475,17 +592,24 @@ typedef struct sBand
*/ */
int8_t TxMaxPower; 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; }Band_t;
/*! /*!
@@ -548,5 +672,9 @@ typedef enum eLoRaMacBatteryLevel
BAT_LEVEL_NO_MEASURE = 0xFF, BAT_LEVEL_NO_MEASURE = 0xFF,
}LoRaMacBatteryLevel_t; }LoRaMacBatteryLevel_t;
#ifdef __cplusplus
}
#endif
#endif // __LORAMAC_TYPES_H__ #endif // __LORAMAC_TYPES_H__

View File

@@ -51,7 +51,6 @@
#define AS923_TX_PARAM_SETUP_REQ( ) AS923_CASE { return RegionAS923TxParamSetupReq( txParamSetupReq ); } #define AS923_TX_PARAM_SETUP_REQ( ) AS923_CASE { return RegionAS923TxParamSetupReq( txParamSetupReq ); }
#define AS923_DL_CHANNEL_REQ( ) AS923_CASE { return RegionAS923DlChannelReq( dlChannelReq ); } #define AS923_DL_CHANNEL_REQ( ) AS923_CASE { return RegionAS923DlChannelReq( dlChannelReq ); }
#define AS923_ALTERNATE_DR( ) AS923_CASE { return RegionAS923AlternateDr( currentDr, type ); } #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_NEXT_CHANNEL( ) AS923_CASE { return RegionAS923NextChannel( nextChanParams, channel, time, aggregatedTimeOff ); }
#define AS923_CHANNEL_ADD( ) AS923_CASE { return RegionAS923ChannelAdd( channelAdd ); } #define AS923_CHANNEL_ADD( ) AS923_CASE { return RegionAS923ChannelAdd( channelAdd ); }
#define AS923_CHANNEL_REMOVE( ) AS923_CASE { return RegionAS923ChannelsRemove( channelRemove ); } #define AS923_CHANNEL_REMOVE( ) AS923_CASE { return RegionAS923ChannelsRemove( channelRemove ); }
@@ -76,7 +75,6 @@
#define AS923_TX_PARAM_SETUP_REQ( ) #define AS923_TX_PARAM_SETUP_REQ( )
#define AS923_DL_CHANNEL_REQ( ) #define AS923_DL_CHANNEL_REQ( )
#define AS923_ALTERNATE_DR( ) #define AS923_ALTERNATE_DR( )
#define AS923_CALC_BACKOFF( )
#define AS923_NEXT_CHANNEL( ) #define AS923_NEXT_CHANNEL( )
#define AS923_CHANNEL_ADD( ) #define AS923_CHANNEL_ADD( )
#define AS923_CHANNEL_REMOVE( ) #define AS923_CHANNEL_REMOVE( )
@@ -105,7 +103,6 @@
#define AU915_TX_PARAM_SETUP_REQ( ) AU915_CASE { return RegionAU915TxParamSetupReq( txParamSetupReq ); } #define AU915_TX_PARAM_SETUP_REQ( ) AU915_CASE { return RegionAU915TxParamSetupReq( txParamSetupReq ); }
#define AU915_DL_CHANNEL_REQ( ) AU915_CASE { return RegionAU915DlChannelReq( dlChannelReq ); } #define AU915_DL_CHANNEL_REQ( ) AU915_CASE { return RegionAU915DlChannelReq( dlChannelReq ); }
#define AU915_ALTERNATE_DR( ) AU915_CASE { return RegionAU915AlternateDr( currentDr, type ); } #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_NEXT_CHANNEL( ) AU915_CASE { return RegionAU915NextChannel( nextChanParams, channel, time, aggregatedTimeOff ); }
#define AU915_CHANNEL_ADD( ) AU915_CASE { return RegionAU915ChannelAdd( channelAdd ); } #define AU915_CHANNEL_ADD( ) AU915_CASE { return RegionAU915ChannelAdd( channelAdd ); }
#define AU915_CHANNEL_REMOVE( ) AU915_CASE { return RegionAU915ChannelsRemove( channelRemove ); } #define AU915_CHANNEL_REMOVE( ) AU915_CASE { return RegionAU915ChannelsRemove( channelRemove ); }
@@ -130,7 +127,6 @@
#define AU915_TX_PARAM_SETUP_REQ( ) #define AU915_TX_PARAM_SETUP_REQ( )
#define AU915_DL_CHANNEL_REQ( ) #define AU915_DL_CHANNEL_REQ( )
#define AU915_ALTERNATE_DR( ) #define AU915_ALTERNATE_DR( )
#define AU915_CALC_BACKOFF( )
#define AU915_NEXT_CHANNEL( ) #define AU915_NEXT_CHANNEL( )
#define AU915_CHANNEL_ADD( ) #define AU915_CHANNEL_ADD( )
#define AU915_CHANNEL_REMOVE( ) #define AU915_CHANNEL_REMOVE( )
@@ -159,7 +155,6 @@
#define CN470_TX_PARAM_SETUP_REQ( ) CN470_CASE { return RegionCN470TxParamSetupReq( txParamSetupReq ); } #define CN470_TX_PARAM_SETUP_REQ( ) CN470_CASE { return RegionCN470TxParamSetupReq( txParamSetupReq ); }
#define CN470_DL_CHANNEL_REQ( ) CN470_CASE { return RegionCN470DlChannelReq( dlChannelReq ); } #define CN470_DL_CHANNEL_REQ( ) CN470_CASE { return RegionCN470DlChannelReq( dlChannelReq ); }
#define CN470_ALTERNATE_DR( ) CN470_CASE { return RegionCN470AlternateDr( currentDr, type ); } #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_NEXT_CHANNEL( ) CN470_CASE { return RegionCN470NextChannel( nextChanParams, channel, time, aggregatedTimeOff ); }
#define CN470_CHANNEL_ADD( ) CN470_CASE { return RegionCN470ChannelAdd( channelAdd ); } #define CN470_CHANNEL_ADD( ) CN470_CASE { return RegionCN470ChannelAdd( channelAdd ); }
#define CN470_CHANNEL_REMOVE( ) CN470_CASE { return RegionCN470ChannelsRemove( channelRemove ); } #define CN470_CHANNEL_REMOVE( ) CN470_CASE { return RegionCN470ChannelsRemove( channelRemove ); }
@@ -184,7 +179,6 @@
#define CN470_TX_PARAM_SETUP_REQ( ) #define CN470_TX_PARAM_SETUP_REQ( )
#define CN470_DL_CHANNEL_REQ( ) #define CN470_DL_CHANNEL_REQ( )
#define CN470_ALTERNATE_DR( ) #define CN470_ALTERNATE_DR( )
#define CN470_CALC_BACKOFF( )
#define CN470_NEXT_CHANNEL( ) #define CN470_NEXT_CHANNEL( )
#define CN470_CHANNEL_ADD( ) #define CN470_CHANNEL_ADD( )
#define CN470_CHANNEL_REMOVE( ) #define CN470_CHANNEL_REMOVE( )
@@ -213,7 +207,6 @@
#define CN779_TX_PARAM_SETUP_REQ( ) CN779_CASE { return RegionCN779TxParamSetupReq( txParamSetupReq ); } #define CN779_TX_PARAM_SETUP_REQ( ) CN779_CASE { return RegionCN779TxParamSetupReq( txParamSetupReq ); }
#define CN779_DL_CHANNEL_REQ( ) CN779_CASE { return RegionCN779DlChannelReq( dlChannelReq ); } #define CN779_DL_CHANNEL_REQ( ) CN779_CASE { return RegionCN779DlChannelReq( dlChannelReq ); }
#define CN779_ALTERNATE_DR( ) CN779_CASE { return RegionCN779AlternateDr( currentDr, type ); } #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_NEXT_CHANNEL( ) CN779_CASE { return RegionCN779NextChannel( nextChanParams, channel, time, aggregatedTimeOff ); }
#define CN779_CHANNEL_ADD( ) CN779_CASE { return RegionCN779ChannelAdd( channelAdd ); } #define CN779_CHANNEL_ADD( ) CN779_CASE { return RegionCN779ChannelAdd( channelAdd ); }
#define CN779_CHANNEL_REMOVE( ) CN779_CASE { return RegionCN779ChannelsRemove( channelRemove ); } #define CN779_CHANNEL_REMOVE( ) CN779_CASE { return RegionCN779ChannelsRemove( channelRemove ); }
@@ -238,7 +231,6 @@
#define CN779_TX_PARAM_SETUP_REQ( ) #define CN779_TX_PARAM_SETUP_REQ( )
#define CN779_DL_CHANNEL_REQ( ) #define CN779_DL_CHANNEL_REQ( )
#define CN779_ALTERNATE_DR( ) #define CN779_ALTERNATE_DR( )
#define CN779_CALC_BACKOFF( )
#define CN779_NEXT_CHANNEL( ) #define CN779_NEXT_CHANNEL( )
#define CN779_CHANNEL_ADD( ) #define CN779_CHANNEL_ADD( )
#define CN779_CHANNEL_REMOVE( ) #define CN779_CHANNEL_REMOVE( )
@@ -267,7 +259,6 @@
#define EU433_TX_PARAM_SETUP_REQ( ) EU433_CASE { return RegionEU433TxParamSetupReq( txParamSetupReq ); } #define EU433_TX_PARAM_SETUP_REQ( ) EU433_CASE { return RegionEU433TxParamSetupReq( txParamSetupReq ); }
#define EU433_DL_CHANNEL_REQ( ) EU433_CASE { return RegionEU433DlChannelReq( dlChannelReq ); } #define EU433_DL_CHANNEL_REQ( ) EU433_CASE { return RegionEU433DlChannelReq( dlChannelReq ); }
#define EU433_ALTERNATE_DR( ) EU433_CASE { return RegionEU433AlternateDr( currentDr, type ); } #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_NEXT_CHANNEL( ) EU433_CASE { return RegionEU433NextChannel( nextChanParams, channel, time, aggregatedTimeOff ); }
#define EU433_CHANNEL_ADD( ) EU433_CASE { return RegionEU433ChannelAdd( channelAdd ); } #define EU433_CHANNEL_ADD( ) EU433_CASE { return RegionEU433ChannelAdd( channelAdd ); }
#define EU433_CHANNEL_REMOVE( ) EU433_CASE { return RegionEU433ChannelsRemove( channelRemove ); } #define EU433_CHANNEL_REMOVE( ) EU433_CASE { return RegionEU433ChannelsRemove( channelRemove ); }
@@ -292,7 +283,6 @@
#define EU433_TX_PARAM_SETUP_REQ( ) #define EU433_TX_PARAM_SETUP_REQ( )
#define EU433_DL_CHANNEL_REQ( ) #define EU433_DL_CHANNEL_REQ( )
#define EU433_ALTERNATE_DR( ) #define EU433_ALTERNATE_DR( )
#define EU433_CALC_BACKOFF( )
#define EU433_NEXT_CHANNEL( ) #define EU433_NEXT_CHANNEL( )
#define EU433_CHANNEL_ADD( ) #define EU433_CHANNEL_ADD( )
#define EU433_CHANNEL_REMOVE( ) #define EU433_CHANNEL_REMOVE( )
@@ -321,7 +311,6 @@
#define EU868_TX_PARAM_SETUP_REQ( ) EU868_CASE { return RegionEU868TxParamSetupReq( txParamSetupReq ); } #define EU868_TX_PARAM_SETUP_REQ( ) EU868_CASE { return RegionEU868TxParamSetupReq( txParamSetupReq ); }
#define EU868_DL_CHANNEL_REQ( ) EU868_CASE { return RegionEU868DlChannelReq( dlChannelReq ); } #define EU868_DL_CHANNEL_REQ( ) EU868_CASE { return RegionEU868DlChannelReq( dlChannelReq ); }
#define EU868_ALTERNATE_DR( ) EU868_CASE { return RegionEU868AlternateDr( currentDr, type ); } #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_NEXT_CHANNEL( ) EU868_CASE { return RegionEU868NextChannel( nextChanParams, channel, time, aggregatedTimeOff ); }
#define EU868_CHANNEL_ADD( ) EU868_CASE { return RegionEU868ChannelAdd( channelAdd ); } #define EU868_CHANNEL_ADD( ) EU868_CASE { return RegionEU868ChannelAdd( channelAdd ); }
#define EU868_CHANNEL_REMOVE( ) EU868_CASE { return RegionEU868ChannelsRemove( channelRemove ); } #define EU868_CHANNEL_REMOVE( ) EU868_CASE { return RegionEU868ChannelsRemove( channelRemove ); }
@@ -346,7 +335,6 @@
#define EU868_TX_PARAM_SETUP_REQ( ) #define EU868_TX_PARAM_SETUP_REQ( )
#define EU868_DL_CHANNEL_REQ( ) #define EU868_DL_CHANNEL_REQ( )
#define EU868_ALTERNATE_DR( ) #define EU868_ALTERNATE_DR( )
#define EU868_CALC_BACKOFF( )
#define EU868_NEXT_CHANNEL( ) #define EU868_NEXT_CHANNEL( )
#define EU868_CHANNEL_ADD( ) #define EU868_CHANNEL_ADD( )
#define EU868_CHANNEL_REMOVE( ) #define EU868_CHANNEL_REMOVE( )
@@ -375,7 +363,6 @@
#define KR920_TX_PARAM_SETUP_REQ( ) KR920_CASE { return RegionKR920TxParamSetupReq( txParamSetupReq ); } #define KR920_TX_PARAM_SETUP_REQ( ) KR920_CASE { return RegionKR920TxParamSetupReq( txParamSetupReq ); }
#define KR920_DL_CHANNEL_REQ( ) KR920_CASE { return RegionKR920DlChannelReq( dlChannelReq ); } #define KR920_DL_CHANNEL_REQ( ) KR920_CASE { return RegionKR920DlChannelReq( dlChannelReq ); }
#define KR920_ALTERNATE_DR( ) KR920_CASE { return RegionKR920AlternateDr( currentDr, type ); } #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_NEXT_CHANNEL( ) KR920_CASE { return RegionKR920NextChannel( nextChanParams, channel, time, aggregatedTimeOff ); }
#define KR920_CHANNEL_ADD( ) KR920_CASE { return RegionKR920ChannelAdd( channelAdd ); } #define KR920_CHANNEL_ADD( ) KR920_CASE { return RegionKR920ChannelAdd( channelAdd ); }
#define KR920_CHANNEL_REMOVE( ) KR920_CASE { return RegionKR920ChannelsRemove( channelRemove ); } #define KR920_CHANNEL_REMOVE( ) KR920_CASE { return RegionKR920ChannelsRemove( channelRemove ); }
@@ -400,7 +387,6 @@
#define KR920_TX_PARAM_SETUP_REQ( ) #define KR920_TX_PARAM_SETUP_REQ( )
#define KR920_DL_CHANNEL_REQ( ) #define KR920_DL_CHANNEL_REQ( )
#define KR920_ALTERNATE_DR( ) #define KR920_ALTERNATE_DR( )
#define KR920_CALC_BACKOFF( )
#define KR920_NEXT_CHANNEL( ) #define KR920_NEXT_CHANNEL( )
#define KR920_CHANNEL_ADD( ) #define KR920_CHANNEL_ADD( )
#define KR920_CHANNEL_REMOVE( ) #define KR920_CHANNEL_REMOVE( )
@@ -429,7 +415,6 @@
#define IN865_TX_PARAM_SETUP_REQ( ) IN865_CASE { return RegionIN865TxParamSetupReq( txParamSetupReq ); } #define IN865_TX_PARAM_SETUP_REQ( ) IN865_CASE { return RegionIN865TxParamSetupReq( txParamSetupReq ); }
#define IN865_DL_CHANNEL_REQ( ) IN865_CASE { return RegionIN865DlChannelReq( dlChannelReq ); } #define IN865_DL_CHANNEL_REQ( ) IN865_CASE { return RegionIN865DlChannelReq( dlChannelReq ); }
#define IN865_ALTERNATE_DR( ) IN865_CASE { return RegionIN865AlternateDr( currentDr, type ); } #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_NEXT_CHANNEL( ) IN865_CASE { return RegionIN865NextChannel( nextChanParams, channel, time, aggregatedTimeOff ); }
#define IN865_CHANNEL_ADD( ) IN865_CASE { return RegionIN865ChannelAdd( channelAdd ); } #define IN865_CHANNEL_ADD( ) IN865_CASE { return RegionIN865ChannelAdd( channelAdd ); }
#define IN865_CHANNEL_REMOVE( ) IN865_CASE { return RegionIN865ChannelsRemove( channelRemove ); } #define IN865_CHANNEL_REMOVE( ) IN865_CASE { return RegionIN865ChannelsRemove( channelRemove ); }
@@ -454,7 +439,6 @@
#define IN865_TX_PARAM_SETUP_REQ( ) #define IN865_TX_PARAM_SETUP_REQ( )
#define IN865_DL_CHANNEL_REQ( ) #define IN865_DL_CHANNEL_REQ( )
#define IN865_ALTERNATE_DR( ) #define IN865_ALTERNATE_DR( )
#define IN865_CALC_BACKOFF( )
#define IN865_NEXT_CHANNEL( ) #define IN865_NEXT_CHANNEL( )
#define IN865_CHANNEL_ADD( ) #define IN865_CHANNEL_ADD( )
#define IN865_CHANNEL_REMOVE( ) #define IN865_CHANNEL_REMOVE( )
@@ -483,7 +467,6 @@
#define US915_TX_PARAM_SETUP_REQ( ) US915_CASE { return RegionUS915TxParamSetupReq( txParamSetupReq ); } #define US915_TX_PARAM_SETUP_REQ( ) US915_CASE { return RegionUS915TxParamSetupReq( txParamSetupReq ); }
#define US915_DL_CHANNEL_REQ( ) US915_CASE { return RegionUS915DlChannelReq( dlChannelReq ); } #define US915_DL_CHANNEL_REQ( ) US915_CASE { return RegionUS915DlChannelReq( dlChannelReq ); }
#define US915_ALTERNATE_DR( ) US915_CASE { return RegionUS915AlternateDr( currentDr, type ); } #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_NEXT_CHANNEL( ) US915_CASE { return RegionUS915NextChannel( nextChanParams, channel, time, aggregatedTimeOff ); }
#define US915_CHANNEL_ADD( ) US915_CASE { return RegionUS915ChannelAdd( channelAdd ); } #define US915_CHANNEL_ADD( ) US915_CASE { return RegionUS915ChannelAdd( channelAdd ); }
#define US915_CHANNEL_REMOVE( ) US915_CASE { return RegionUS915ChannelsRemove( channelRemove ); } #define US915_CHANNEL_REMOVE( ) US915_CASE { return RegionUS915ChannelsRemove( channelRemove ); }
@@ -508,7 +491,6 @@
#define US915_TX_PARAM_SETUP_REQ( ) #define US915_TX_PARAM_SETUP_REQ( )
#define US915_DL_CHANNEL_REQ( ) #define US915_DL_CHANNEL_REQ( )
#define US915_ALTERNATE_DR( ) #define US915_ALTERNATE_DR( )
#define US915_CALC_BACKOFF( )
#define US915_NEXT_CHANNEL( ) #define US915_NEXT_CHANNEL( )
#define US915_CHANNEL_ADD( ) #define US915_CHANNEL_ADD( )
#define US915_CHANNEL_REMOVE( ) #define US915_CHANNEL_REMOVE( )
@@ -537,7 +519,6 @@
#define RU864_TX_PARAM_SETUP_REQ( ) RU864_CASE { return RegionRU864TxParamSetupReq( txParamSetupReq ); } #define RU864_TX_PARAM_SETUP_REQ( ) RU864_CASE { return RegionRU864TxParamSetupReq( txParamSetupReq ); }
#define RU864_DL_CHANNEL_REQ( ) RU864_CASE { return RegionRU864DlChannelReq( dlChannelReq ); } #define RU864_DL_CHANNEL_REQ( ) RU864_CASE { return RegionRU864DlChannelReq( dlChannelReq ); }
#define RU864_ALTERNATE_DR( ) RU864_CASE { return RegionRU864AlternateDr( currentDr, type ); } #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_NEXT_CHANNEL( ) RU864_CASE { return RegionRU864NextChannel( nextChanParams, channel, time, aggregatedTimeOff ); }
#define RU864_CHANNEL_ADD( ) RU864_CASE { return RegionRU864ChannelAdd( channelAdd ); } #define RU864_CHANNEL_ADD( ) RU864_CASE { return RegionRU864ChannelAdd( channelAdd ); }
#define RU864_CHANNEL_REMOVE( ) RU864_CASE { return RegionRU864ChannelsRemove( channelRemove ); } #define RU864_CHANNEL_REMOVE( ) RU864_CASE { return RegionRU864ChannelsRemove( channelRemove ); }
@@ -562,7 +543,6 @@
#define RU864_TX_PARAM_SETUP_REQ( ) #define RU864_TX_PARAM_SETUP_REQ( )
#define RU864_DL_CHANNEL_REQ( ) #define RU864_DL_CHANNEL_REQ( )
#define RU864_ALTERNATE_DR( ) #define RU864_ALTERNATE_DR( )
#define RU864_CALC_BACKOFF( )
#define RU864_NEXT_CHANNEL( ) #define RU864_NEXT_CHANNEL( )
#define RU864_CHANNEL_ADD( ) #define RU864_CHANNEL_ADD( )
#define RU864_CHANNEL_REMOVE( ) #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 ) LoRaMacStatus_t RegionNextChannel( LoRaMacRegion_t region, NextChanParams_t* nextChanParams, uint8_t* channel, TimerTime_t* time, TimerTime_t* aggregatedTimeOff )
{ {
switch( region ) 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;
}

View File

@@ -52,17 +52,32 @@
#ifndef __REGION_H__ #ifndef __REGION_H__
#define __REGION_H__ #define __REGION_H__
#ifdef __cplusplus
extern "C"
{
#endif
#include <stdint.h> #include <stdint.h>
#include <stdbool.h> #include <stdbool.h>
#include "utilities.h" #include "utilities.h"
#include "LoRaMac.h" #include "LoRaMac.h"
#include "timer.h" #include "timer.h"
#include "RegionCommon.h"
/*! /*!
* Macro to compute bit of a channel index. * Macro to compute bit of a channel index.
*/ */
#define LC( channelIndex ) ( uint16_t )( 1 << ( channelIndex - 1 ) ) #define LC( channelIndex ) ( uint16_t )( 1 << ( channelIndex - 1 ) )
#ifndef REGION_VERSION
/*!
* Regional parameters version definition.
*/
#define REGION_VERSION 0x00010003
#endif
/*! /*!
* Region | SF * Region | SF
* ------------ | :-----: * ------------ | :-----:
@@ -476,7 +491,7 @@
* EU868 | - * EU868 | -
* IN865 | Max EIRP - 18 * IN865 | Max EIRP - 18
* KR920 | - * KR920 | -
* US915 | Max ERP - 16 * US915 | Max ERP - 18
* RU864 | - * RU864 | -
*/ */
#define TX_POWER_9 9 #define TX_POWER_9 9
@@ -492,28 +507,72 @@
* EU868 | - * EU868 | -
* IN865 | Max EIRP - 20 * IN865 | Max EIRP - 20
* KR920 | - * KR920 | -
* US915 | Max ERP - 10 * US915 | Max ERP - 20
* RU864 | - * RU864 | -
*/ */
#define TX_POWER_10 10 #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 #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 #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 #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 #define TX_POWER_14 14
@@ -529,6 +588,11 @@
*/ */
typedef enum ePhyAttribute typedef enum ePhyAttribute
{ {
/*!
* Frequency. It is available
* to perform a verification with RegionVerify().
*/
PHY_FREQUENCY,
/*! /*!
* Minimum RX datarate. * Minimum RX datarate.
*/ */
@@ -585,10 +649,6 @@ typedef enum ePhyAttribute
* Maximum payload possible. * Maximum payload possible.
*/ */
PHY_MAX_PAYLOAD, PHY_MAX_PAYLOAD,
/*!
* Maximum payload possible when repeater support is enabled.
*/
PHY_MAX_PAYLOAD_REPEATER,
/*! /*!
* Duty cycle. * Duty cycle.
*/ */
@@ -743,10 +803,26 @@ typedef enum ePhyAttribute
* The number of channels for the beacon reception. * The number of channels for the beacon reception.
*/ */
PHY_BEACON_NB_CHANNELS, PHY_BEACON_NB_CHANNELS,
/*!
* Ping slot channel frequency.
*/
PHY_PING_SLOT_CHANNEL_FREQ,
/*! /*!
* The datarate of a ping slot channel. * 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; }PhyAttribute_t;
/*! /*!
@@ -754,6 +830,10 @@ typedef enum ePhyAttribute
*/ */
typedef enum eInitType typedef enum eInitType
{ {
/*!
* Initializes the band definitions.
*/
INIT_TYPE_BANDS,
/*! /*!
* Initializes the region specific data to defaults, according to the * Initializes the region specific data to defaults, according to the
* LoRaWAN specification. * LoRaWAN specification.
@@ -825,6 +905,10 @@ typedef union uPhyParam
* Beacon format * Beacon format
*/ */
BeaconFormat_t BeaconFormat; BeaconFormat_t BeaconFormat;
/*!
* Duty Cycle Period
*/
TimerTime_t DutyCycleTimePeriod;
}PhyParam_t; }PhyParam_t;
/*! /*!
@@ -839,23 +923,29 @@ typedef struct sGetPhyParams
/*! /*!
* Datarate. * Datarate.
* The parameter is needed for the following queries: * 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; int8_t Datarate;
/*! /*!
* Uplink dwell time. This parameter must be set to query: * 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: * 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; uint8_t UplinkDwellTime;
/*! /*!
* Downlink dwell time. This parameter must be set to query: * 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: * 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; 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; }GetPhyParams_t;
/*! /*!
@@ -875,6 +965,14 @@ typedef struct sSetBandTxDoneParams
* Last TX done time. * Last TX done time.
*/ */
TimerTime_t LastTxDoneTime; TimerTime_t LastTxDoneTime;
/*!
* Time-on-air of the last transmission.
*/
TimerTime_t LastTxAirTime;
/*!
* Elapsed time since initialization.
*/
SysTime_t ElapsedTimeSinceStartUp;
}SetBandTxDoneParams_t; }SetBandTxDoneParams_t;
/*! /*!
@@ -909,6 +1007,10 @@ typedef struct sGetNvmCtxParams
*/ */
typedef union uVerifyParams typedef union uVerifyParams
{ {
/*!
* Channel frequency to verify
*/
uint32_t Frequency;
/*! /*!
* TX power to verify. * TX power to verify.
*/ */
@@ -1004,10 +1106,6 @@ typedef struct sRxConfigParams
* Downlink dwell time. * Downlink dwell time.
*/ */
uint8_t DownlinkDwellTime; uint8_t DownlinkDwellTime;
/*!
* Set to true, if a repeater is supported.
*/
bool RepeaterSupport;
/*! /*!
* Set to true, if RX should be continuous. * Set to true, if RX should be continuous.
*/ */
@@ -1171,37 +1269,6 @@ typedef enum eAlternateDrType
ALTERNATE_DR_RESTORE ALTERNATE_DR_RESTORE
}AlternateDrType_t; }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. * Parameter structure for the function RegionNextChannel.
*/ */
@@ -1227,6 +1294,18 @@ typedef struct sNextChanParams
* Set to true, if the duty cycle is enabled, otherwise false. * Set to true, if the duty cycle is enabled, otherwise false.
*/ */
bool DutyCycleEnabled; 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; }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 ); 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 * \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 ); 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 */ /*! \} defgroup REGION */
#ifdef __cplusplus
}
#endif
#endif // __REGION_H__ #endif // __REGION_H__

View File

@@ -119,45 +119,21 @@ static bool VerifyRfFreq( uint32_t freq )
return true; 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; int8_t phyDr = DataratesAS923[datarate];
uint8_t delayTransmission = 0; uint32_t bandwidth = GetBandwidth( datarate );
TimerTime_t timeOnAir = 0;
for( uint8_t i = 0, k = 0; i < AS923_MAX_NB_CHANNELS; i += 16, k++ ) if( datarate == DR_7 )
{ // High Speed FSK channel
timeOnAir = Radio.TimeOnAir( MODEM_FSK, bandwidth, phyDr * 1000, 0, 5, false, pktLen, true );
}
else
{ {
for( uint8_t j = 0; j < 16; j++ ) timeOnAir = Radio.TimeOnAir( MODEM_LORA, bandwidth, phyDr, 1, 8, false, pktLen, true );
{
if( ( channelsMask[k] & ( 1 << j ) ) != 0 )
{
if( channels[i + j].Frequency == 0 )
{ // Check if the channel is enabled
continue;
} }
if( joined == false ) return timeOnAir;
{
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;
}
}
}
*delayTx = delayTransmission;
return nbEnabledChannels;
} }
PhyParam_t RegionAS923GetPhyParam( GetPhyParams_t* getPhy ) PhyParam_t RegionAS923GetPhyParam( GetPhyParams_t* getPhy )
@@ -239,18 +215,6 @@ PhyParam_t RegionAS923GetPhyParam( GetPhyParams_t* getPhy )
} }
break; 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: case PHY_DUTY_CYCLE:
{ {
phyParam.Value = AS923_DUTY_CYCLE_ENABLED; phyParam.Value = AS923_DUTY_CYCLE_ENABLED;
@@ -363,11 +327,26 @@ PhyParam_t RegionAS923GetPhyParam( GetPhyParams_t* getPhy )
phyParam.Value = AS923_BEACON_CHANNEL_DR; phyParam.Value = AS923_BEACON_CHANNEL_DR;
break; break;
} }
case PHY_PING_SLOT_CHANNEL_FREQ:
{
phyParam.Value = AS923_PING_SLOT_CHANNEL_FREQ;
break;
}
case PHY_PING_SLOT_CHANNEL_DR: case PHY_PING_SLOT_CHANNEL_DR:
{ {
phyParam.Value = AS923_PING_SLOT_CHANNEL_DR; phyParam.Value = AS923_PING_SLOT_CHANNEL_DR;
break; break;
} }
case PHY_SF_FROM_DR:
{
phyParam.Value = DataratesAS923[getPhy->Datarate];
break;
}
case PHY_BW_FROM_DR:
{
phyParam.Value = GetBandwidth( getPhy->Datarate );
break;
}
default: default:
{ {
break; break;
@@ -379,7 +358,8 @@ PhyParam_t RegionAS923GetPhyParam( GetPhyParams_t* getPhy )
void RegionAS923SetBandTxDone( SetBandTxDoneParams_t* txDone ) 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 ) void RegionAS923InitDefaults( InitDefaultsParams_t* params )
@@ -391,10 +371,14 @@ void RegionAS923InitDefaults( InitDefaultsParams_t* params )
switch( params->Type ) switch( params->Type )
{ {
case INIT_TYPE_INIT: case INIT_TYPE_BANDS:
{ {
// Initialize bands // Initialize bands
memcpy1( ( uint8_t* )NvmCtx.Bands, ( uint8_t* )bands, sizeof( Band_t ) * AS923_MAX_NB_BANDS ); memcpy1( ( uint8_t* )NvmCtx.Bands, ( uint8_t* )bands, sizeof( Band_t ) * AS923_MAX_NB_BANDS );
break;
}
case INIT_TYPE_INIT:
{
// Channels // Channels
NvmCtx.Channels[0] = ( ChannelParams_t ) AS923_LC1; NvmCtx.Channels[0] = ( ChannelParams_t ) AS923_LC1;
@@ -402,6 +386,7 @@ void RegionAS923InitDefaults( InitDefaultsParams_t* params )
// Initialize the channels default mask // Initialize the channels default mask
NvmCtx.ChannelsDefaultMask[0] = LC( 1 ) + LC( 2 ); NvmCtx.ChannelsDefaultMask[0] = LC( 1 ) + LC( 2 );
// Update the channels mask // Update the channels mask
RegionCommonChanMaskCopy( NvmCtx.ChannelsMask, NvmCtx.ChannelsDefaultMask, 1 ); RegionCommonChanMaskCopy( NvmCtx.ChannelsMask, NvmCtx.ChannelsDefaultMask, 1 );
break; break;
@@ -418,6 +403,10 @@ void RegionAS923InitDefaults( InitDefaultsParams_t* params )
{ {
// Restore channels default mask // Restore channels default mask
NvmCtx.ChannelsMask[0] |= NvmCtx.ChannelsDefaultMask[0]; NvmCtx.ChannelsMask[0] |= NvmCtx.ChannelsDefaultMask[0];
// Channels
NvmCtx.Channels[0] = ( ChannelParams_t ) AS923_LC1;
NvmCtx.Channels[1] = ( ChannelParams_t ) AS923_LC2;
break; break;
} }
default: default:
@@ -437,6 +426,10 @@ bool RegionAS923Verify( VerifyParams_t* verify, PhyAttribute_t phyAttribute )
{ {
switch( phyAttribute ) switch( phyAttribute )
{ {
case PHY_FREQUENCY:
{
return VerifyRfFreq( verify->Frequency );
}
case PHY_TX_DR: case PHY_TX_DR:
{ {
if( verify->DatarateParams.UplinkDwellTime == 0 ) if( verify->DatarateParams.UplinkDwellTime == 0 )
@@ -581,7 +574,6 @@ bool RegionAS923RxConfig( RxConfigParams_t* rxConfig, int8_t* datarate )
{ {
RadioModems_t modem; RadioModems_t modem;
int8_t dr = rxConfig->Datarate; int8_t dr = rxConfig->Datarate;
uint8_t maxPayload = 0;
int8_t phyDr = 0; int8_t phyDr = 0;
uint32_t frequency = rxConfig->Frequency; 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 ); Radio.SetRxConfig( modem, rxConfig->Bandwidth, phyDr, 1, 0, 8, rxConfig->WindowTimeout, false, 0, false, 0, 0, true, rxConfig->RxContinuous );
} }
// Check for repeater support Radio.SetMaxPayloadLength( modem, MaxPayloadOfDatarateDwell0AS923[dr] + LORAMAC_FRAME_PAYLOAD_OVERHEAD_SIZE );
if( rxConfig->RepeaterSupport == true )
{
maxPayload = MaxPayloadOfDatarateRepeaterDwell0AS923[dr];
}
else
{
maxPayload = MaxPayloadOfDatarateDwell0AS923[dr];
}
Radio.SetMaxPayloadLength( modem, maxPayload + LORA_MAC_FRMPAYLOAD_OVERHEAD );
*datarate = (uint8_t) dr; *datarate = (uint8_t) dr;
return true; return true;
@@ -651,18 +633,19 @@ bool RegionAS923TxConfig( TxConfigParams_t* txConfig, int8_t* txPower, TimerTime
if( txConfig->Datarate == DR_7 ) if( txConfig->Datarate == DR_7 )
{ // High Speed FSK channel { // High Speed FSK channel
modem = MODEM_FSK; 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 else
{ {
modem = MODEM_LORA; 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 // Setup maximum payload lenght of the radio driver
Radio.SetMaxPayloadLength( modem, txConfig->PktLen ); Radio.SetMaxPayloadLength( modem, txConfig->PktLen );
// Get the time-on-air of the next tx frame
*txTimeOnAir = Radio.TimeOnAir( modem, txConfig->PktLen );
*txPower = txPowerLimited; *txPower = txPowerLimited;
return true; return true;
@@ -888,55 +871,45 @@ int8_t RegionAS923AlternateDr( int8_t currentDr, AlternateDrType_t type )
return AS923_DWELL_LIMIT_DATARATE; 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 ) LoRaMacStatus_t RegionAS923NextChannel( NextChanParams_t* nextChanParams, uint8_t* channel, TimerTime_t* time, TimerTime_t* aggregatedTimeOff )
{ {
uint8_t channelNext = 0; uint8_t channelNext = 0;
uint8_t nbEnabledChannels = 0; uint8_t nbEnabledChannels = 0;
uint8_t delayTx = 0; uint8_t nbRestrictedChannels = 0;
uint8_t enabledChannels[AS923_MAX_NB_CHANNELS] = { 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 ) if( RegionCommonCountChannels( NvmCtx.ChannelsMask, 0, 1 ) == 0 )
{ // Reactivate default channels { // Reactivate default channels
NvmCtx.ChannelsMask[0] |= LC( 1 ) + LC( 2 ); NvmCtx.ChannelsMask[0] |= LC( 1 ) + LC( 2 );
} }
if( nextChanParams->AggrTimeOff <= TimerGetElapsedTime( nextChanParams->LastAggrTx ) )
{
// Reset Aggregated time off
*aggregatedTimeOff = 0;
// Update bands Time OFF
nextTxDelay = RegionCommonUpdateBandTimeOff( nextChanParams->Joined, nextChanParams->DutyCycleEnabled, NvmCtx.Bands, AS923_MAX_NB_BANDS );
// Search how many channels are enabled // Search how many channels are enabled
nbEnabledChannels = CountNbOfEnabledChannels( nextChanParams->Joined, nextChanParams->Datarate, countChannelsParams.Joined = nextChanParams->Joined;
NvmCtx.ChannelsMask, NvmCtx.Channels, countChannelsParams.Datarate = nextChanParams->Datarate;
NvmCtx.Bands, enabledChannels, &delayTx ); countChannelsParams.ChannelsMask = NvmCtx.ChannelsMask;
} countChannelsParams.Channels = NvmCtx.Channels;
else countChannelsParams.Bands = NvmCtx.Bands;
{ countChannelsParams.MaxNbChannels = AS923_MAX_NB_CHANNELS;
delayTx++; countChannelsParams.JoinChannels = AS923_JOIN_CHANNELS;
nextTxDelay = nextChanParams->AggrTimeOff - TimerGetElapsedTime( nextChanParams->LastAggrTx );
}
if( nbEnabledChannels > 0 ) identifyChannelsParam.AggrTimeOff = nextChanParams->AggrTimeOff;
identifyChannelsParam.LastAggrTx = nextChanParams->LastAggrTx;
identifyChannelsParam.DutyCycleEnabled = nextChanParams->DutyCycleEnabled;
identifyChannelsParam.MaxBands = AS923_MAX_NB_BANDS;
identifyChannelsParam.ElapsedTimeSinceStartUp = nextChanParams->ElapsedTimeSinceStartUp;
identifyChannelsParam.LastTxIsJoinRequest = nextChanParams->LastTxIsJoinRequest;
identifyChannelsParam.ExpectedTimeOnAir = GetTimeOnAir( nextChanParams->Datarate, nextChanParams->PktLen );
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++ ) 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 // Free channel found
*channel = channelNext; *channel = channelNext;
*time = 0;
return LORAMAC_STATUS_OK; 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 // Datarate not supported by any channel, restore defaults
NvmCtx.ChannelsMask[0] |= LC( 1 ) + LC( 2 ); NvmCtx.ChannelsMask[0] |= LC( 1 ) + LC( 2 );
*time = 0;
return LORAMAC_STATUS_NO_CHANNEL_FOUND;
} }
return status;
} }
LoRaMacStatus_t RegionAS923ChannelAdd( ChannelAddParams_t* channelAdd ) LoRaMacStatus_t RegionAS923ChannelAdd( ChannelAddParams_t* channelAdd )

View File

@@ -37,6 +37,11 @@
#ifndef __REGION_AS923_H__ #ifndef __REGION_AS923_H__
#define __REGION_AS923_H__ #define __REGION_AS923_H__
#ifdef __cplusplus
extern "C"
{
#endif
#include "region/Region.h" #include "region/Region.h"
/*! /*!
@@ -212,6 +217,11 @@
*/ */
#define AS923_BEACON_CHANNEL_FREQ 923400000 #define AS923_BEACON_CHANNEL_FREQ 923400000
/*!
* Ping slot channel frequency
*/
#define AS923_PING_SLOT_CHANNEL_FREQ 923400000
/*! /*!
* Payload size of a beacon frame * Payload size of a beacon frame
*/ */
@@ -249,9 +259,9 @@
/*! /*!
* Band 0 definition * 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 * 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 }; 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. * 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 }; 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. * Maximum payload with respect to the datarate index.
* The table is valid for the dwell time configuration of 0 for uplinks and downlinks. The table provides * The table is only valid for uplinks.
* 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.
*/ */
static const uint8_t MaxPayloadOfDatarateDwell1UpAS923[] = { 0, 0, 11, 53, 125, 242, 242, 242 }; 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. * Maximum payload with respect to the datarate index.
* The table proides repeater support. The table is only valid for downlinks. * The table is only valid for downlinks.
*/ */
static const uint8_t MaxPayloadOfDatarateDwell1DownAS923[] = { 0, 0, 11, 53, 126, 242, 242, 242 }; 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 ); 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 * \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 */ /*! \} defgroup REGIONAS923 */
#ifdef __cplusplus
}
#endif
#endif // __REGION_AS923_H__ #endif // __REGION_AS923_H__

View File

@@ -140,38 +140,12 @@ static bool VerifyRfFreq( uint32_t freq )
return true; 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; int8_t phyDr = DataratesAU915[datarate];
uint8_t delayTransmission = 0; uint32_t bandwidth = GetBandwidth( datarate );
for( uint8_t i = 0, k = 0; i < AU915_MAX_NB_CHANNELS; i += 16, k++ ) return Radio.TimeOnAir( MODEM_LORA, bandwidth, phyDr, 1, 8, false, pktLen, true );
{
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;
} }
PhyParam_t RegionAU915GetPhyParam( GetPhyParams_t* getPhy ) PhyParam_t RegionAU915GetPhyParam( GetPhyParams_t* getPhy )
@@ -253,18 +227,6 @@ PhyParam_t RegionAU915GetPhyParam( GetPhyParams_t* getPhy )
} }
break; 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: case PHY_DUTY_CYCLE:
{ {
phyParam.Value = AU915_DUTY_CYCLE_ENABLED; phyParam.Value = AU915_DUTY_CYCLE_ENABLED;
@@ -360,6 +322,11 @@ PhyParam_t RegionAU915GetPhyParam( GetPhyParams_t* getPhy )
phyParam.fValue = AU915_DEFAULT_ANTENNA_GAIN; phyParam.fValue = AU915_DEFAULT_ANTENNA_GAIN;
break; break;
} }
case PHY_BEACON_CHANNEL_FREQ:
{
phyParam.Value = AU915_BEACON_CHANNEL_FREQ + ( getPhy->Channel * AU915_BEACON_CHANNEL_STEPWIDTH );
break;
}
case PHY_BEACON_FORMAT: case PHY_BEACON_FORMAT:
{ {
phyParam.BeaconFormat.BeaconSize = AU915_BEACON_SIZE; phyParam.BeaconFormat.BeaconSize = AU915_BEACON_SIZE;
@@ -382,11 +349,26 @@ PhyParam_t RegionAU915GetPhyParam( GetPhyParams_t* getPhy )
phyParam.Value = AU915_BEACON_NB_CHANNELS; phyParam.Value = AU915_BEACON_NB_CHANNELS;
break; 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: case PHY_PING_SLOT_CHANNEL_DR:
{ {
phyParam.Value = AU915_PING_SLOT_CHANNEL_DR; phyParam.Value = AU915_PING_SLOT_CHANNEL_DR;
break; break;
} }
case PHY_SF_FROM_DR:
{
phyParam.Value = DataratesAU915[getPhy->Datarate];
break;
}
case PHY_BW_FROM_DR:
{
phyParam.Value = GetBandwidth( getPhy->Datarate );
break;
}
default: default:
{ {
break; break;
@@ -398,7 +380,8 @@ PhyParam_t RegionAU915GetPhyParam( GetPhyParams_t* getPhy )
void RegionAU915SetBandTxDone( SetBandTxDoneParams_t* txDone ) 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 ) void RegionAU915InitDefaults( InitDefaultsParams_t* params )
@@ -410,11 +393,28 @@ void RegionAU915InitDefaults( InitDefaultsParams_t* params )
switch( params->Type ) switch( params->Type )
{ {
case INIT_TYPE_INIT: case INIT_TYPE_BANDS:
{ {
// Initialize bands // Initialize bands
memcpy1( ( uint8_t* )NvmCtx.Bands, ( uint8_t* )bands, sizeof( Band_t ) * AU915_MAX_NB_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 // Channels
// 125 kHz channels // 125 kHz channels
for( uint8_t i = 0; i < AU915_MAX_NB_CHANNELS - 8; i++ ) 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].DrRange.Value = ( DR_6 << 4 ) | DR_6;
NvmCtx.Channels[i].Band = 0; 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; break;
} }
case INIT_TYPE_RESTORE_CTX: case INIT_TYPE_RESTORE_CTX:
@@ -482,6 +468,10 @@ bool RegionAU915Verify( VerifyParams_t* verify, PhyAttribute_t phyAttribute )
{ {
switch( phyAttribute ) switch( phyAttribute )
{ {
case PHY_FREQUENCY:
{
return VerifyRfFreq( verify->Frequency );
}
case PHY_TX_DR: case PHY_TX_DR:
case PHY_DEF_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 ) bool RegionAU915RxConfig( RxConfigParams_t* rxConfig, int8_t* datarate )
{ {
int8_t dr = rxConfig->Datarate; int8_t dr = rxConfig->Datarate;
uint8_t maxPayload = 0;
int8_t phyDr = 0; int8_t phyDr = 0;
uint32_t frequency = rxConfig->Frequency; uint32_t frequency = rxConfig->Frequency;
@@ -615,15 +604,7 @@ bool RegionAU915RxConfig( RxConfigParams_t* rxConfig, int8_t* datarate )
// Radio configuration // Radio configuration
Radio.SetRxConfig( MODEM_LORA, rxConfig->Bandwidth, phyDr, 1, 0, 8, rxConfig->WindowTimeout, false, 0, false, 0, 0, true, rxConfig->RxContinuous ); Radio.SetRxConfig( MODEM_LORA, rxConfig->Bandwidth, phyDr, 1, 0, 8, rxConfig->WindowTimeout, false, 0, false, 0, 0, true, rxConfig->RxContinuous );
if( rxConfig->RepeaterSupport == true ) Radio.SetMaxPayloadLength( MODEM_LORA, MaxPayloadOfDatarateDwell0AU915[dr] + LORAMAC_FRAME_PAYLOAD_OVERHEAD_SIZE );
{
maxPayload = MaxPayloadOfDatarateRepeaterDwell0AU915[dr];
}
else
{
maxPayload = MaxPayloadOfDatarateDwell0AU915[dr];
}
Radio.SetMaxPayloadLength( MODEM_LORA, maxPayload + LORA_MAC_FRMPAYLOAD_OVERHEAD );
*datarate = (uint8_t) dr; *datarate = (uint8_t) dr;
return true; return true;
@@ -642,14 +623,14 @@ bool RegionAU915TxConfig( TxConfigParams_t* txConfig, int8_t* txPower, TimerTime
// Setup the radio frequency // Setup the radio frequency
Radio.SetChannel( NvmCtx.Channels[txConfig->Channel].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 // Setup maximum payload lenght of the radio driver
Radio.SetMaxPayloadLength( MODEM_LORA, txConfig->PktLen ); 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; *txPower = txPowerLimited;
return true; return true;
} }
@@ -880,28 +861,14 @@ int8_t RegionAU915AlternateDr( int8_t currentDr, AlternateDrType_t type )
return currentDr; 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 ) LoRaMacStatus_t RegionAU915NextChannel( NextChanParams_t* nextChanParams, uint8_t* channel, TimerTime_t* time, TimerTime_t* aggregatedTimeOff )
{ {
uint8_t nbEnabledChannels = 0; uint8_t nbEnabledChannels = 0;
uint8_t delayTx = 0; uint8_t nbRestrictedChannels = 0;
uint8_t enabledChannels[AU915_MAX_NB_CHANNELS] = { 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 // Count 125kHz channels
if( RegionCommonCountChannels( NvmCtx.ChannelsMaskRemaining, 0, 4 ) == 0 ) 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;
// Update bands Time OFF
nextTxDelay = RegionCommonUpdateBandTimeOff( nextChanParams->Joined, nextChanParams->DutyCycleEnabled, NvmCtx.Bands, AU915_MAX_NB_BANDS );
// Search how many channels are enabled // Search how many channels are enabled
nbEnabledChannels = CountNbOfEnabledChannels( nextChanParams->Datarate, countChannelsParams.Joined = nextChanParams->Joined;
NvmCtx.ChannelsMaskRemaining, NvmCtx.Channels, countChannelsParams.Datarate = nextChanParams->Datarate;
NvmCtx.Bands, enabledChannels, &delayTx ); countChannelsParams.ChannelsMask = NvmCtx.ChannelsMaskRemaining;
} countChannelsParams.Channels = NvmCtx.Channels;
else countChannelsParams.Bands = NvmCtx.Bands;
{ countChannelsParams.MaxNbChannels = AU915_MAX_NB_CHANNELS;
delayTx++; countChannelsParams.JoinChannels = 0;
nextTxDelay = nextChanParams->AggrTimeOff - TimerGetElapsedTime( nextChanParams->LastAggrTx );
}
if( nbEnabledChannels > 0 ) identifyChannelsParam.AggrTimeOff = nextChanParams->AggrTimeOff;
identifyChannelsParam.LastAggrTx = nextChanParams->LastAggrTx;
identifyChannelsParam.DutyCycleEnabled = nextChanParams->DutyCycleEnabled;
identifyChannelsParam.MaxBands = AU915_MAX_NB_BANDS;
identifyChannelsParam.ElapsedTimeSinceStartUp = nextChanParams->ElapsedTimeSinceStartUp;
identifyChannelsParam.LastTxIsJoinRequest = nextChanParams->LastTxIsJoinRequest;
identifyChannelsParam.ExpectedTimeOnAir = GetTimeOnAir( nextChanParams->Datarate, nextChanParams->PktLen );
identifyChannelsParam.CountNbOfEnabledChannelsParam = &countChannelsParams;
status = RegionCommonIdentifyChannels( &identifyChannelsParam, aggregatedTimeOff, enabledChannels,
&nbEnabledChannels, &nbRestrictedChannels, time );
if( status == LORAMAC_STATUS_OK )
{ {
// We found a valid channel // We found a valid channel
*channel = enabledChannels[randr( 0, nbEnabledChannels - 1 )]; *channel = enabledChannels[randr( 0, nbEnabledChannels - 1 )];
// Disable the channel in the mask // Disable the channel in the mask
RegionCommonChanDisable( NvmCtx.ChannelsMaskRemaining, *channel, AU915_MAX_NB_CHANNELS - 8 ); 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 ) LoRaMacStatus_t RegionAU915ChannelAdd( ChannelAddParams_t* channelAdd )

View File

@@ -37,6 +37,11 @@
#ifndef __REGION_AU915_H__ #ifndef __REGION_AU915_H__
#define __REGION_AU915_H__ #define __REGION_AU915_H__
#ifdef __cplusplus
extern "C"
{
#endif
#include "region/Region.h" #include "region/Region.h"
/*! /*!
@@ -93,7 +98,7 @@
/*! /*!
* Minimal Tx output power that can be used by the node * 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 * Maximal Tx output power that can be used by the node
@@ -203,6 +208,11 @@
*/ */
#define AU915_BEACON_CHANNEL_STEPWIDTH 600000 #define AU915_BEACON_CHANNEL_STEPWIDTH 600000
/*!
* Ping slot channel frequency
*/
#define AU915_PING_SLOT_CHANNEL_FREQ 923300000
/*! /*!
* Number of possible beacon channels * Number of possible beacon channels
*/ */
@@ -226,7 +236,7 @@
/*! /*!
* Datarate of the beacon channel * Datarate of the beacon channel
*/ */
#define AU915_BEACON_CHANNEL_DR DR_10 #define AU915_BEACON_CHANNEL_DR DR_8
/*! /*!
* Bandwith of the beacon channel * Bandwith of the beacon channel
@@ -236,7 +246,7 @@
/*! /*!
* Ping slot channel datarate * 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 * LoRaMac maximum number of bands
@@ -245,9 +255,9 @@
/*! /*!
* Band 0 definition * 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 * 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. * 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. * Maximum payload with respect to the datarate index.
* 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.
* The table is valid for the dwell time configuration of 1 for uplinks. * 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 }; static const uint8_t MaxPayloadOfDatarateDwell1AU915[] = { 0, 0, 11, 53, 125, 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 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 };
/*! /*!
* \brief The function gets a value of a specific phy attribute. * \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 ); 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 * \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 */ /*! \} defgroup REGIONAU915 */
#ifdef __cplusplus
}
#endif
#endif // __REGION_AU915_H__ #endif // __REGION_AU915_H__

View File

@@ -128,38 +128,12 @@ static bool VerifyRfFreq( uint32_t freq )
return true; 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; int8_t phyDr = DataratesCN470[datarate];
uint8_t delayTransmission = 0; uint32_t bandwidth = GetBandwidth( datarate );
for( uint8_t i = 0, k = 0; i < CN470_MAX_NB_CHANNELS; i += 16, k++ ) return Radio.TimeOnAir( MODEM_LORA, bandwidth, phyDr, 1, 8, false, pktLen, true );
{
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;
} }
PhyParam_t RegionCN470GetPhyParam( GetPhyParams_t* getPhy ) PhyParam_t RegionCN470GetPhyParam( GetPhyParams_t* getPhy )
@@ -213,11 +187,6 @@ PhyParam_t RegionCN470GetPhyParam( GetPhyParams_t* getPhy )
phyParam.Value = MaxPayloadOfDatarateCN470[getPhy->Datarate]; phyParam.Value = MaxPayloadOfDatarateCN470[getPhy->Datarate];
break; break;
} }
case PHY_MAX_PAYLOAD_REPEATER:
{
phyParam.Value = MaxPayloadOfDatarateRepeaterCN470[getPhy->Datarate];
break;
}
case PHY_DUTY_CYCLE: case PHY_DUTY_CYCLE:
{ {
phyParam.Value = CN470_DUTY_CYCLE_ENABLED; phyParam.Value = CN470_DUTY_CYCLE_ENABLED;
@@ -309,6 +278,11 @@ PhyParam_t RegionCN470GetPhyParam( GetPhyParams_t* getPhy )
phyParam.fValue = CN470_DEFAULT_ANTENNA_GAIN; phyParam.fValue = CN470_DEFAULT_ANTENNA_GAIN;
break; break;
} }
case PHY_BEACON_CHANNEL_FREQ:
{
phyParam.Value = CN470_BEACON_CHANNEL_FREQ;
break;
}
case PHY_BEACON_FORMAT: case PHY_BEACON_FORMAT:
{ {
phyParam.BeaconFormat.BeaconSize = CN470_BEACON_SIZE; phyParam.BeaconFormat.BeaconSize = CN470_BEACON_SIZE;
@@ -331,11 +305,26 @@ PhyParam_t RegionCN470GetPhyParam( GetPhyParams_t* getPhy )
phyParam.Value = CN470_BEACON_NB_CHANNELS; phyParam.Value = CN470_BEACON_NB_CHANNELS;
break; break;
} }
case PHY_PING_SLOT_CHANNEL_FREQ:
{
phyParam.Value = CN470_PING_SLOT_CHANNEL_FREQ;
break;
}
case PHY_PING_SLOT_CHANNEL_DR: case PHY_PING_SLOT_CHANNEL_DR:
{ {
phyParam.Value = CN470_PING_SLOT_CHANNEL_DR; phyParam.Value = CN470_PING_SLOT_CHANNEL_DR;
break; break;
} }
case PHY_SF_FROM_DR:
{
phyParam.Value = DataratesCN470[getPhy->Datarate];
break;
}
case PHY_BW_FROM_DR:
{
phyParam.Value = GetBandwidth( getPhy->Datarate );
break;
}
default: default:
{ {
break; break;
@@ -347,7 +336,8 @@ PhyParam_t RegionCN470GetPhyParam( GetPhyParams_t* getPhy )
void RegionCN470SetBandTxDone( SetBandTxDoneParams_t* txDone ) 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 ) void RegionCN470InitDefaults( InitDefaultsParams_t* params )
@@ -359,11 +349,14 @@ void RegionCN470InitDefaults( InitDefaultsParams_t* params )
switch( params->Type ) switch( params->Type )
{ {
case INIT_TYPE_INIT: case INIT_TYPE_BANDS:
{ {
// Initialize bands // Initialize bands
memcpy1( ( uint8_t* )NvmCtx.Bands, ( uint8_t* )bands, sizeof( Band_t ) * CN470_MAX_NB_BANDS ); memcpy1( ( uint8_t* )NvmCtx.Bands, ( uint8_t* )bands, sizeof( Band_t ) * CN470_MAX_NB_BANDS );
break;
}
case INIT_TYPE_INIT:
{
// Channels // Channels
// 125 kHz channels // 125 kHz channels
for( uint8_t i = 0; i < CN470_MAX_NB_CHANNELS; i++ ) 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 // Initialize the channels default mask
#if 0
NvmCtx.ChannelsDefaultMask[0] = 0xFFFF; NvmCtx.ChannelsDefaultMask[0] = 0xFFFF;
NvmCtx.ChannelsDefaultMask[1] = 0xFFFF; NvmCtx.ChannelsDefaultMask[1] = 0xFFFF;
NvmCtx.ChannelsDefaultMask[2] = 0xFFFF; NvmCtx.ChannelsDefaultMask[2] = 0xFFFF;
NvmCtx.ChannelsDefaultMask[3] = 0xFFFF; NvmCtx.ChannelsDefaultMask[3] = 0xFFFF;
NvmCtx.ChannelsDefaultMask[4] = 0xFFFF; NvmCtx.ChannelsDefaultMask[4] = 0xFFFF;
NvmCtx.ChannelsDefaultMask[5] = 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 // Update the channels mask
RegionCommonChanMaskCopy( NvmCtx.ChannelsMask, NvmCtx.ChannelsDefaultMask, 6 ); RegionCommonChanMaskCopy( NvmCtx.ChannelsMask, NvmCtx.ChannelsDefaultMask, 6 );
break; break;
@@ -424,6 +409,10 @@ bool RegionCN470Verify( VerifyParams_t* verify, PhyAttribute_t phyAttribute )
{ {
switch( phyAttribute ) switch( phyAttribute )
{ {
case PHY_FREQUENCY:
{
return VerifyRfFreq( verify->Frequency );
}
case PHY_TX_DR: case PHY_TX_DR:
case PHY_DEF_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 ) bool RegionCN470RxConfig( RxConfigParams_t* rxConfig, int8_t* datarate )
{ {
int8_t dr = rxConfig->Datarate; int8_t dr = rxConfig->Datarate;
uint8_t maxPayload = 0;
int8_t phyDr = 0; int8_t phyDr = 0;
uint32_t frequency = rxConfig->Frequency; uint32_t frequency = rxConfig->Frequency;
@@ -529,15 +517,7 @@ bool RegionCN470RxConfig( RxConfigParams_t* rxConfig, int8_t* datarate )
// Radio configuration // Radio configuration
Radio.SetRxConfig( MODEM_LORA, rxConfig->Bandwidth, phyDr, 1, 0, 8, rxConfig->WindowTimeout, false, 0, false, 0, 0, true, rxConfig->RxContinuous ); Radio.SetRxConfig( MODEM_LORA, rxConfig->Bandwidth, phyDr, 1, 0, 8, rxConfig->WindowTimeout, false, 0, false, 0, 0, true, rxConfig->RxContinuous );
if( rxConfig->RepeaterSupport == true ) Radio.SetMaxPayloadLength( MODEM_LORA, MaxPayloadOfDatarateCN470[dr] + LORAMAC_FRAME_PAYLOAD_OVERHEAD_SIZE );
{
maxPayload = MaxPayloadOfDatarateRepeaterCN470[dr];
}
else
{
maxPayload = MaxPayloadOfDatarateCN470[dr];
}
Radio.SetMaxPayloadLength( MODEM_LORA, maxPayload + LORA_MAC_FRMPAYLOAD_OVERHEAD );
*datarate = (uint8_t) dr; *datarate = (uint8_t) dr;
return true; return true;
@@ -555,11 +535,11 @@ bool RegionCN470TxConfig( TxConfigParams_t* txConfig, int8_t* txPower, TimerTime
// Setup the radio frequency // Setup the radio frequency
Radio.SetChannel( NvmCtx.Channels[txConfig->Channel].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 // Setup maximum payload lenght of the radio driver
Radio.SetMaxPayloadLength( MODEM_LORA, txConfig->PktLen ); Radio.SetMaxPayloadLength( MODEM_LORA, txConfig->PktLen );
// Get the time-on-air of the next tx frame // Update time-on-air
*txTimeOnAir = Radio.TimeOnAir( MODEM_LORA, txConfig->PktLen ); *txTimeOnAir = GetTimeOnAir( txConfig->Datarate, txConfig->PktLen );
*txPower = txPowerLimited; *txPower = txPowerLimited;
return true; return true;
@@ -708,28 +688,14 @@ int8_t RegionCN470AlternateDr( int8_t currentDr, AlternateDrType_t type )
return currentDr; 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 ) LoRaMacStatus_t RegionCN470NextChannel( NextChanParams_t* nextChanParams, uint8_t* channel, TimerTime_t* time, TimerTime_t* aggregatedTimeOff )
{ {
uint8_t nbEnabledChannels = 0; uint8_t nbEnabledChannels = 0;
uint8_t delayTx = 0; uint8_t nbRestrictedChannels = 0;
uint8_t enabledChannels[CN470_MAX_NB_CHANNELS] = { 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 // Count 125kHz channels
if( RegionCommonCountChannels( NvmCtx.ChannelsMask, 0, 6 ) == 0 ) if( RegionCommonCountChannels( NvmCtx.ChannelsMask, 0, 6 ) == 0 )
@@ -742,45 +708,35 @@ LoRaMacStatus_t RegionCN470NextChannel( NextChanParams_t* nextChanParams, uint8_
NvmCtx.ChannelsMask[5] = 0xFFFF; NvmCtx.ChannelsMask[5] = 0xFFFF;
} }
if( nextChanParams->AggrTimeOff <= TimerGetElapsedTime( nextChanParams->LastAggrTx ) )
{
// Reset Aggregated time off
*aggregatedTimeOff = 0;
// Update bands Time OFF
nextTxDelay = RegionCommonUpdateBandTimeOff( nextChanParams->Joined, nextChanParams->DutyCycleEnabled, NvmCtx.Bands, CN470_MAX_NB_BANDS );
// Search how many channels are enabled // Search how many channels are enabled
nbEnabledChannels = CountNbOfEnabledChannels( nextChanParams->Datarate, countChannelsParams.Joined = nextChanParams->Joined;
NvmCtx.ChannelsMask, NvmCtx.Channels, countChannelsParams.Datarate = nextChanParams->Datarate;
NvmCtx.Bands, enabledChannels, &delayTx ); countChannelsParams.ChannelsMask = NvmCtx.ChannelsMask;
} countChannelsParams.Channels = NvmCtx.Channels;
else countChannelsParams.Bands = NvmCtx.Bands;
{ countChannelsParams.MaxNbChannels = CN470_MAX_NB_CHANNELS;
delayTx++; countChannelsParams.JoinChannels = 0;
nextTxDelay = nextChanParams->AggrTimeOff - TimerGetElapsedTime( nextChanParams->LastAggrTx );
}
if( nbEnabledChannels > 0 ) identifyChannelsParam.AggrTimeOff = nextChanParams->AggrTimeOff;
identifyChannelsParam.LastAggrTx = nextChanParams->LastAggrTx;
identifyChannelsParam.DutyCycleEnabled = nextChanParams->DutyCycleEnabled;
identifyChannelsParam.MaxBands = CN470_MAX_NB_BANDS;
identifyChannelsParam.ElapsedTimeSinceStartUp = nextChanParams->ElapsedTimeSinceStartUp;
identifyChannelsParam.LastTxIsJoinRequest = nextChanParams->LastTxIsJoinRequest;
identifyChannelsParam.ExpectedTimeOnAir = GetTimeOnAir( nextChanParams->Datarate, nextChanParams->PktLen );
identifyChannelsParam.CountNbOfEnabledChannelsParam = &countChannelsParams;
status = RegionCommonIdentifyChannels( &identifyChannelsParam, aggregatedTimeOff, enabledChannels,
&nbEnabledChannels, &nbRestrictedChannels, time );
if( status == LORAMAC_STATUS_OK )
{ {
// We found a valid channel // We found a valid channel
*channel = enabledChannels[randr( 0, nbEnabledChannels - 1 )]; *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 ) LoRaMacStatus_t RegionCN470ChannelAdd( ChannelAddParams_t* channelAdd )

View File

@@ -37,6 +37,11 @@
#ifndef __REGION_CN470_H__ #ifndef __REGION_CN470_H__
#define __REGION_CN470_H__ #define __REGION_CN470_H__
#ifdef __cplusplus
extern "C"
{
#endif
#include "region/Region.h" #include "region/Region.h"
/*! /*!
@@ -187,6 +192,11 @@
*/ */
#define CN470_BEACON_CHANNEL_STEPWIDTH 200000 #define CN470_BEACON_CHANNEL_STEPWIDTH 200000
/*!
* Ping slot channel frequency
*/
#define CN470_PING_SLOT_CHANNEL_FREQ 508300000
/*! /*!
* Number of possible beacon channels * Number of possible beacon channels
*/ */
@@ -229,9 +239,9 @@
/*! /*!
* Band 0 definition * 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 * 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 }; 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 }; static const uint8_t MaxPayloadOfDatarateCN470[] = { 51, 51, 51, 115, 242, 242 };
/*!
* Maximum payload with respect to the datarate index. Can operate with repeater.
*/
static const uint8_t MaxPayloadOfDatarateRepeaterCN470[] = { 51, 51, 51, 115, 222, 222 };
/*! /*!
* \brief The function gets a value of a specific phy attribute. * \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 ); 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 * \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 */ /*! \} defgroup REGIONCN470 */
#ifdef __cplusplus
}
#endif
#endif // __REGION_CN470_H__ #endif // __REGION_CN470_H__

View File

@@ -119,45 +119,21 @@ static bool VerifyRfFreq( uint32_t freq )
return true; 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; int8_t phyDr = DataratesCN779[datarate];
uint8_t delayTransmission = 0; uint32_t bandwidth = GetBandwidth( datarate );
TimerTime_t timeOnAir = 0;
for( uint8_t i = 0, k = 0; i < CN779_MAX_NB_CHANNELS; i += 16, k++ ) if( datarate == DR_7 )
{ // High Speed FSK channel
timeOnAir = Radio.TimeOnAir( MODEM_FSK, bandwidth, phyDr * 1000, 0, 5, false, pktLen, true );
}
else
{ {
for( uint8_t j = 0; j < 16; j++ ) timeOnAir = Radio.TimeOnAir( MODEM_LORA, bandwidth, phyDr, 1, 8, false, pktLen, true );
{
if( ( channelsMask[k] & ( 1 << j ) ) != 0 )
{
if( channels[i + j].Frequency == 0 )
{ // Check if the channel is enabled
continue;
} }
if( joined == false ) return timeOnAir;
{
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;
}
}
}
*delayTx = delayTransmission;
return nbEnabledChannels;
} }
PhyParam_t RegionCN779GetPhyParam( GetPhyParams_t* getPhy ) PhyParam_t RegionCN779GetPhyParam( GetPhyParams_t* getPhy )
@@ -211,11 +187,6 @@ PhyParam_t RegionCN779GetPhyParam( GetPhyParams_t* getPhy )
phyParam.Value = MaxPayloadOfDatarateCN779[getPhy->Datarate]; phyParam.Value = MaxPayloadOfDatarateCN779[getPhy->Datarate];
break; break;
} }
case PHY_MAX_PAYLOAD_REPEATER:
{
phyParam.Value = MaxPayloadOfDatarateRepeaterCN779[getPhy->Datarate];
break;
}
case PHY_DUTY_CYCLE: case PHY_DUTY_CYCLE:
{ {
phyParam.Value = CN779_DUTY_CYCLE_ENABLED; phyParam.Value = CN779_DUTY_CYCLE_ENABLED;
@@ -324,11 +295,26 @@ PhyParam_t RegionCN779GetPhyParam( GetPhyParams_t* getPhy )
phyParam.Value = CN779_BEACON_CHANNEL_DR; phyParam.Value = CN779_BEACON_CHANNEL_DR;
break; break;
} }
case PHY_PING_SLOT_CHANNEL_FREQ:
{
phyParam.Value = CN779_PING_SLOT_CHANNEL_FREQ;
break;
}
case PHY_PING_SLOT_CHANNEL_DR: case PHY_PING_SLOT_CHANNEL_DR:
{ {
phyParam.Value = CN779_PING_SLOT_CHANNEL_DR; phyParam.Value = CN779_PING_SLOT_CHANNEL_DR;
break; break;
} }
case PHY_SF_FROM_DR:
{
phyParam.Value = DataratesCN779[getPhy->Datarate];
break;
}
case PHY_BW_FROM_DR:
{
phyParam.Value = GetBandwidth( getPhy->Datarate );
break;
}
default: default:
{ {
break; break;
@@ -340,7 +326,8 @@ PhyParam_t RegionCN779GetPhyParam( GetPhyParams_t* getPhy )
void RegionCN779SetBandTxDone( SetBandTxDoneParams_t* txDone ) 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 ) void RegionCN779InitDefaults( InitDefaultsParams_t* params )
@@ -352,10 +339,14 @@ void RegionCN779InitDefaults( InitDefaultsParams_t* params )
switch( params->Type ) switch( params->Type )
{ {
case INIT_TYPE_INIT: case INIT_TYPE_BANDS:
{ {
// Initialize bands // Initialize bands
memcpy1( ( uint8_t* )NvmCtx.Bands, ( uint8_t* )bands, sizeof( Band_t ) * CN779_MAX_NB_BANDS ); memcpy1( ( uint8_t* )NvmCtx.Bands, ( uint8_t* )bands, sizeof( Band_t ) * CN779_MAX_NB_BANDS );
break;
}
case INIT_TYPE_INIT:
{
// Channels // Channels
NvmCtx.Channels[0] = ( ChannelParams_t ) CN779_LC1; NvmCtx.Channels[0] = ( ChannelParams_t ) CN779_LC1;
@@ -364,6 +355,7 @@ void RegionCN779InitDefaults( InitDefaultsParams_t* params )
// Initialize the channels default mask // Initialize the channels default mask
NvmCtx.ChannelsDefaultMask[0] = LC( 1 ) + LC( 2 ) + LC( 3 ); NvmCtx.ChannelsDefaultMask[0] = LC( 1 ) + LC( 2 ) + LC( 3 );
// Update the channels mask // Update the channels mask
RegionCommonChanMaskCopy( NvmCtx.ChannelsMask, NvmCtx.ChannelsDefaultMask, 1 ); RegionCommonChanMaskCopy( NvmCtx.ChannelsMask, NvmCtx.ChannelsDefaultMask, 1 );
break; break;
@@ -380,6 +372,11 @@ void RegionCN779InitDefaults( InitDefaultsParams_t* params )
{ {
// Restore channels default mask // Restore channels default mask
NvmCtx.ChannelsMask[0] |= NvmCtx.ChannelsDefaultMask[0]; 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; break;
} }
default: default:
@@ -399,6 +396,10 @@ bool RegionCN779Verify( VerifyParams_t* verify, PhyAttribute_t phyAttribute )
{ {
switch( phyAttribute ) switch( phyAttribute )
{ {
case PHY_FREQUENCY:
{
return VerifyRfFreq( verify->Frequency );
}
case PHY_TX_DR: case PHY_TX_DR:
{ {
return RegionCommonValueInRange( verify->DatarateParams.Datarate, CN779_TX_MIN_DATARATE, CN779_TX_MAX_DATARATE ); 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; RadioModems_t modem;
int8_t dr = rxConfig->Datarate; int8_t dr = rxConfig->Datarate;
uint8_t maxPayload = 0;
int8_t phyDr = 0; int8_t phyDr = 0;
uint32_t frequency = rxConfig->Frequency; 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 ); Radio.SetRxConfig( modem, rxConfig->Bandwidth, phyDr, 1, 0, 8, rxConfig->WindowTimeout, false, 0, false, 0, 0, true, rxConfig->RxContinuous );
} }
if( rxConfig->RepeaterSupport == true ) Radio.SetMaxPayloadLength( modem, MaxPayloadOfDatarateCN779[dr] + LORAMAC_FRAME_PAYLOAD_OVERHEAD_SIZE );
{
maxPayload = MaxPayloadOfDatarateRepeaterCN779[dr];
}
else
{
maxPayload = MaxPayloadOfDatarateCN779[dr];
}
Radio.SetMaxPayloadLength( modem, maxPayload + LORA_MAC_FRMPAYLOAD_OVERHEAD );
*datarate = (uint8_t) dr; *datarate = (uint8_t) dr;
return true; return true;
@@ -597,18 +589,19 @@ bool RegionCN779TxConfig( TxConfigParams_t* txConfig, int8_t* txPower, TimerTime
if( txConfig->Datarate == DR_7 ) if( txConfig->Datarate == DR_7 )
{ // High Speed FSK channel { // High Speed FSK channel
modem = MODEM_FSK; 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 else
{ {
modem = MODEM_LORA; 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 // Setup maximum payload lenght of the radio driver
Radio.SetMaxPayloadLength( modem, txConfig->PktLen ); Radio.SetMaxPayloadLength( modem, txConfig->PktLen );
// Get the time-on-air of the next tx frame
*txTimeOnAir = Radio.TimeOnAir( modem, txConfig->PktLen );
*txPower = txPowerLimited; *txPower = txPowerLimited;
return true; return true;
@@ -832,74 +825,54 @@ int8_t RegionCN779AlternateDr( int8_t currentDr, AlternateDrType_t type )
return currentDr; 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 ) LoRaMacStatus_t RegionCN779NextChannel( NextChanParams_t* nextChanParams, uint8_t* channel, TimerTime_t* time, TimerTime_t* aggregatedTimeOff )
{ {
uint8_t nbEnabledChannels = 0; uint8_t nbEnabledChannels = 0;
uint8_t delayTx = 0; uint8_t nbRestrictedChannels = 0;
uint8_t enabledChannels[CN779_MAX_NB_CHANNELS] = { 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 ) if( RegionCommonCountChannels( NvmCtx.ChannelsMask, 0, 1 ) == 0 )
{ // Reactivate default channels { // Reactivate default channels
NvmCtx.ChannelsMask[0] |= LC( 1 ) + LC( 2 ) + LC( 3 ); NvmCtx.ChannelsMask[0] |= LC( 1 ) + LC( 2 ) + LC( 3 );
} }
if( nextChanParams->AggrTimeOff <= TimerGetElapsedTime( nextChanParams->LastAggrTx ) )
{
// Reset Aggregated time off
*aggregatedTimeOff = 0;
// Update bands Time OFF
nextTxDelay = RegionCommonUpdateBandTimeOff( nextChanParams->Joined, nextChanParams->DutyCycleEnabled, NvmCtx.Bands, CN779_MAX_NB_BANDS );
// Search how many channels are enabled // Search how many channels are enabled
nbEnabledChannels = CountNbOfEnabledChannels( nextChanParams->Joined, nextChanParams->Datarate, countChannelsParams.Joined = nextChanParams->Joined;
NvmCtx.ChannelsMask, NvmCtx.Channels, countChannelsParams.Datarate = nextChanParams->Datarate;
NvmCtx.Bands, enabledChannels, &delayTx ); countChannelsParams.ChannelsMask = NvmCtx.ChannelsMask;
} countChannelsParams.Channels = NvmCtx.Channels;
else countChannelsParams.Bands = NvmCtx.Bands;
{ countChannelsParams.MaxNbChannels = CN779_MAX_NB_CHANNELS;
delayTx++; countChannelsParams.JoinChannels = CN779_JOIN_CHANNELS;
nextTxDelay = nextChanParams->AggrTimeOff - TimerGetElapsedTime( nextChanParams->LastAggrTx );
}
if( nbEnabledChannels > 0 ) identifyChannelsParam.AggrTimeOff = nextChanParams->AggrTimeOff;
identifyChannelsParam.LastAggrTx = nextChanParams->LastAggrTx;
identifyChannelsParam.DutyCycleEnabled = nextChanParams->DutyCycleEnabled;
identifyChannelsParam.MaxBands = CN779_MAX_NB_BANDS;
identifyChannelsParam.ElapsedTimeSinceStartUp = nextChanParams->ElapsedTimeSinceStartUp;
identifyChannelsParam.LastTxIsJoinRequest = nextChanParams->LastTxIsJoinRequest;
identifyChannelsParam.ExpectedTimeOnAir = GetTimeOnAir( nextChanParams->Datarate, nextChanParams->PktLen );
identifyChannelsParam.CountNbOfEnabledChannelsParam = &countChannelsParams;
status = RegionCommonIdentifyChannels( &identifyChannelsParam, aggregatedTimeOff, enabledChannels,
&nbEnabledChannels, &nbRestrictedChannels, time );
if( status == LORAMAC_STATUS_OK )
{ {
// We found a valid channel // We found a valid channel
*channel = enabledChannels[randr( 0, nbEnabledChannels - 1 )]; *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 // Datarate not supported by any channel, restore defaults
NvmCtx.ChannelsMask[0] |= LC( 1 ) + LC( 2 ) + LC( 3 ); 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 ) LoRaMacStatus_t RegionCN779ChannelAdd( ChannelAddParams_t* channelAdd )

View File

@@ -37,6 +37,11 @@
#ifndef __REGION_CN779_H__ #ifndef __REGION_CN779_H__
#define __REGION_CN779_H__ #define __REGION_CN779_H__
#ifdef __cplusplus
extern "C"
{
#endif
#include "region/Region.h" #include "region/Region.h"
/*! /*!
@@ -199,6 +204,11 @@
*/ */
#define CN779_BEACON_CHANNEL_FREQ 785000000 #define CN779_BEACON_CHANNEL_FREQ 785000000
/*!
* Ping slot channel frequency
*/
#define CN779_PING_SLOT_CHANNEL_FREQ 785000000
/*! /*!
* Payload size of a beacon frame * Payload size of a beacon frame
*/ */
@@ -236,9 +246,9 @@
/*! /*!
* Band 0 definition * 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 * 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 }; 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 }; 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. * \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 ); 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 * \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 */ /*! \} defgroup REGIONCN779 */
#ifdef __cplusplus
}
#endif
#endif // __REGION_CN779_H__ #endif // __REGION_CN779_H__

View File

@@ -36,6 +36,105 @@
#define BACKOFF_DC_1_HOUR 100 #define BACKOFF_DC_1_HOUR 100
#define BACKOFF_DC_10_HOURS 1000 #define BACKOFF_DC_10_HOURS 1000
#define BACKOFF_DC_24_HOURS 10000 #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 ) 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 else
{ {
band->LastTxDoneTime = lastTxDone; band->TimeCredits = 0;
band->LastJoinTxDoneTime = lastTxDone;
} }
} }
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++ ) for( uint8_t i = 0; i < nbBands; i++ )
{ {
if( joined == false ) // Synchronization of bands and credits
{ dutyCycle = UpdateTimeCredits( &bands[i], joined, dutyCycleEnabled,
TimerTime_t txDoneTime = MAX( TimerGetElapsedTime( bands[i].LastJoinTxDoneTime ), lastTxIsJoinRequest, elapsedTimeSinceStartup,
( dutyCycle == true ) ? TimerGetElapsedTime( bands[i].LastTxDoneTime ) : 0 ); currentTime );
if( bands[i].TimeOff <= txDoneTime ) // 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].TimeOff = 0; bands[i].ReadyForTransmission = true;
} // This band is a potential candidate for an
if( bands[i].TimeOff != 0 ) // upcoming transmission, so increase the counter.
{ validBands++;
nextTxDelay = MIN( bands[i].TimeOff - txDoneTime, nextTxDelay );
}
} }
else 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 ) ) // 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++;
}
}
}
if( validBands == 0 )
{ {
bands[i].TimeOff = 0; // There is no valid band available to handle a transmission
// in the given DUTY_CYCLE_TIME_PERIOD.
return TIMERTIME_T_MAX;
} }
if( bands[i].TimeOff != 0 ) return minTimeToWait;
{
nextTxDelay = MIN( bands[i].TimeOff - TimerGetElapsedTime( bands[i].LastTxDoneTime ),
nextTxDelay );
}
}
else
{
nextTxDelay = 0;
bands[i].TimeOff = 0;
}
}
}
return nextTxDelay;
} }
uint8_t RegionCommonParseLinkAdrReq( uint8_t* payload, RegionCommonLinkAdrParams_t* linkAdrParams ) 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; 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 ) void RegionCommonRxBeaconSetup( RegionCommonRxBeaconSetupParams_t* rxBeaconSetupParams )
{ {
bool rxContinuous = true; bool rxContinuous = true;
@@ -382,3 +462,90 @@ void RegionCommonRxBeaconSetup( RegionCommonRxBeaconSetupParams_t* rxBeaconSetup
Radio.Rx( rxBeaconSetupParams->RxTime ); 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;
}
}

View File

@@ -37,9 +37,23 @@
#ifndef __REGIONCOMMON_H__ #ifndef __REGIONCOMMON_H__
#define __REGIONCOMMON_H__ #define __REGIONCOMMON_H__
#ifdef __cplusplus
extern "C"
{
#endif
#include "LoRaMacTypes.h" #include "LoRaMacTypes.h"
#include "LoRaMacHeaderTypes.h"
#include "region/Region.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 typedef struct sRegionCommonLinkAdrParams
{ {
/*! /*!
@@ -132,42 +146,6 @@ typedef struct sRegionCommonLinkAdrReqVerifyParams
int8_t MaxTxPower; int8_t MaxTxPower;
}RegionCommonLinkAdrReqVerifyParams_t; }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 typedef struct sRegionCommonRxBeaconSetupParams
{ {
/*! /*!
@@ -200,6 +178,90 @@ typedef struct sRegionCommonRxBeaconSetupParams
uint16_t SymbolTimeout; uint16_t SymbolTimeout;
}RegionCommonRxBeaconSetupParams_t; }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. * \brief Calculates the join duty cycle.
* This is a generic function and valid for all regions. * 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. * \brief Sets the last tx done property.
* This is a generic function and valid for all regions. * 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] 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. * \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] 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] bands A pointer to the bands.
* *
* \param [IN] nbBands The number of bands available. * \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. * \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. * \brief Parses the parameter of an LinkAdrRequest.
@@ -400,13 +473,6 @@ void RegionCommonComputeRxWindowParameters( double tSymbol, uint8_t minRxSymbols
*/ */
int8_t RegionCommonComputeTxPower( int8_t txPowerIndex, float maxEirp, float antennaGain ); 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. * \brief Sets up the radio into RX beacon mode.
* *
@@ -414,6 +480,52 @@ void RegionCommonCalcBackOff( RegionCommonCalcBackOffParams_t* calcBackOffParams
*/ */
void RegionCommonRxBeaconSetup( RegionCommonRxBeaconSetupParams_t* rxBeaconSetupParams ); 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 */ /*! \} defgroup REGIONCOMMON */
#ifdef __cplusplus
}
#endif
#endif // __REGIONCOMMON_H__ #endif // __REGIONCOMMON_H__

View File

@@ -119,45 +119,21 @@ static bool VerifyRfFreq( uint32_t freq )
return true; 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; int8_t phyDr = DataratesEU433[datarate];
uint8_t delayTransmission = 0; uint32_t bandwidth = GetBandwidth( datarate );
TimerTime_t timeOnAir = 0;
for( uint8_t i = 0, k = 0; i < EU433_MAX_NB_CHANNELS; i += 16, k++ ) if( datarate == DR_7 )
{ // High Speed FSK channel
timeOnAir = Radio.TimeOnAir( MODEM_FSK, bandwidth, phyDr * 1000, 0, 5, false, pktLen, true );
}
else
{ {
for( uint8_t j = 0; j < 16; j++ ) timeOnAir = Radio.TimeOnAir( MODEM_LORA, bandwidth, phyDr, 1, 8, false, pktLen, true );
{
if( ( channelsMask[k] & ( 1 << j ) ) != 0 )
{
if( channels[i + j].Frequency == 0 )
{ // Check if the channel is enabled
continue;
} }
if( joined == false ) return timeOnAir;
{
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;
}
}
}
*delayTx = delayTransmission;
return nbEnabledChannels;
} }
PhyParam_t RegionEU433GetPhyParam( GetPhyParams_t* getPhy ) PhyParam_t RegionEU433GetPhyParam( GetPhyParams_t* getPhy )
@@ -211,11 +187,6 @@ PhyParam_t RegionEU433GetPhyParam( GetPhyParams_t* getPhy )
phyParam.Value = MaxPayloadOfDatarateEU433[getPhy->Datarate]; phyParam.Value = MaxPayloadOfDatarateEU433[getPhy->Datarate];
break; break;
} }
case PHY_MAX_PAYLOAD_REPEATER:
{
phyParam.Value = MaxPayloadOfDatarateRepeaterEU433[getPhy->Datarate];
break;
}
case PHY_DUTY_CYCLE: case PHY_DUTY_CYCLE:
{ {
phyParam.Value = EU433_DUTY_CYCLE_ENABLED; phyParam.Value = EU433_DUTY_CYCLE_ENABLED;
@@ -324,11 +295,26 @@ PhyParam_t RegionEU433GetPhyParam( GetPhyParams_t* getPhy )
phyParam.Value = EU433_BEACON_CHANNEL_DR; phyParam.Value = EU433_BEACON_CHANNEL_DR;
break; break;
} }
case PHY_PING_SLOT_CHANNEL_FREQ:
{
phyParam.Value = EU433_PING_SLOT_CHANNEL_FREQ;
break;
}
case PHY_PING_SLOT_CHANNEL_DR: case PHY_PING_SLOT_CHANNEL_DR:
{ {
phyParam.Value = EU433_PING_SLOT_CHANNEL_DR; phyParam.Value = EU433_PING_SLOT_CHANNEL_DR;
break; break;
} }
case PHY_SF_FROM_DR:
{
phyParam.Value = DataratesEU433[getPhy->Datarate];
break;
}
case PHY_BW_FROM_DR:
{
phyParam.Value = GetBandwidth( getPhy->Datarate );
break;
}
default: default:
{ {
break; break;
@@ -340,7 +326,8 @@ PhyParam_t RegionEU433GetPhyParam( GetPhyParams_t* getPhy )
void RegionEU433SetBandTxDone( SetBandTxDoneParams_t* txDone ) 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 ) void RegionEU433InitDefaults( InitDefaultsParams_t* params )
@@ -352,10 +339,14 @@ void RegionEU433InitDefaults( InitDefaultsParams_t* params )
switch( params->Type ) switch( params->Type )
{ {
case INIT_TYPE_INIT: case INIT_TYPE_BANDS:
{ {
// Initialize bands // Initialize bands
memcpy1( ( uint8_t* )NvmCtx.Bands, ( uint8_t* )bands, sizeof( Band_t ) * EU433_MAX_NB_BANDS ); memcpy1( ( uint8_t* )NvmCtx.Bands, ( uint8_t* )bands, sizeof( Band_t ) * EU433_MAX_NB_BANDS );
break;
}
case INIT_TYPE_INIT:
{
// Channels // Channels
NvmCtx.Channels[0] = ( ChannelParams_t ) EU433_LC1; NvmCtx.Channels[0] = ( ChannelParams_t ) EU433_LC1;
@@ -364,6 +355,7 @@ void RegionEU433InitDefaults( InitDefaultsParams_t* params )
// Initialize the channels default mask // Initialize the channels default mask
NvmCtx.ChannelsDefaultMask[0] = LC( 1 ) + LC( 2 ) + LC( 3 ); NvmCtx.ChannelsDefaultMask[0] = LC( 1 ) + LC( 2 ) + LC( 3 );
// Update the channels mask // Update the channels mask
RegionCommonChanMaskCopy( NvmCtx.ChannelsMask, NvmCtx.ChannelsDefaultMask, 1 ); RegionCommonChanMaskCopy( NvmCtx.ChannelsMask, NvmCtx.ChannelsDefaultMask, 1 );
break; break;
@@ -380,6 +372,11 @@ void RegionEU433InitDefaults( InitDefaultsParams_t* params )
{ {
// Restore channels default mask // Restore channels default mask
NvmCtx.ChannelsMask[0] |= NvmCtx.ChannelsDefaultMask[0]; 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; break;
} }
default: default:
@@ -399,6 +396,10 @@ bool RegionEU433Verify( VerifyParams_t* verify, PhyAttribute_t phyAttribute )
{ {
switch( phyAttribute ) switch( phyAttribute )
{ {
case PHY_FREQUENCY:
{
return VerifyRfFreq( verify->Frequency );
}
case PHY_TX_DR: case PHY_TX_DR:
{ {
return RegionCommonValueInRange( verify->DatarateParams.Datarate, EU433_TX_MIN_DATARATE, EU433_TX_MAX_DATARATE ); 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; RadioModems_t modem;
int8_t dr = rxConfig->Datarate; int8_t dr = rxConfig->Datarate;
uint8_t maxPayload = 0;
int8_t phyDr = 0; int8_t phyDr = 0;
uint32_t frequency = rxConfig->Frequency; 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 ); Radio.SetRxConfig( modem, rxConfig->Bandwidth, phyDr, 1, 0, 8, rxConfig->WindowTimeout, false, 0, false, 0, 0, true, rxConfig->RxContinuous );
} }
if( rxConfig->RepeaterSupport == true ) Radio.SetMaxPayloadLength( modem, MaxPayloadOfDatarateEU433[dr] + LORAMAC_FRAME_PAYLOAD_OVERHEAD_SIZE );
{
maxPayload = MaxPayloadOfDatarateRepeaterEU433[dr];
}
else
{
maxPayload = MaxPayloadOfDatarateEU433[dr];
}
Radio.SetMaxPayloadLength( modem, maxPayload + LORA_MAC_FRMPAYLOAD_OVERHEAD );
*datarate = (uint8_t) dr; *datarate = (uint8_t) dr;
return true; return true;
@@ -597,18 +589,19 @@ bool RegionEU433TxConfig( TxConfigParams_t* txConfig, int8_t* txPower, TimerTime
if( txConfig->Datarate == DR_7 ) if( txConfig->Datarate == DR_7 )
{ // High Speed FSK channel { // High Speed FSK channel
modem = MODEM_FSK; 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 else
{ {
modem = MODEM_LORA; 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 // Setup maximum payload lenght of the radio driver
Radio.SetMaxPayloadLength( modem, txConfig->PktLen ); Radio.SetMaxPayloadLength( modem, txConfig->PktLen );
// Get the time-on-air of the next tx frame
*txTimeOnAir = Radio.TimeOnAir( modem, txConfig->PktLen );
*txPower = txPowerLimited; *txPower = txPowerLimited;
return true; return true;
@@ -832,74 +825,54 @@ int8_t RegionEU433AlternateDr( int8_t currentDr, AlternateDrType_t type )
return currentDr; 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 ) LoRaMacStatus_t RegionEU433NextChannel( NextChanParams_t* nextChanParams, uint8_t* channel, TimerTime_t* time, TimerTime_t* aggregatedTimeOff )
{ {
uint8_t nbEnabledChannels = 0; uint8_t nbEnabledChannels = 0;
uint8_t delayTx = 0; uint8_t nbRestrictedChannels = 0;
uint8_t enabledChannels[EU433_MAX_NB_CHANNELS] = { 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 ) if( RegionCommonCountChannels( NvmCtx.ChannelsMask, 0, 1 ) == 0 )
{ // Reactivate default channels { // Reactivate default channels
NvmCtx.ChannelsMask[0] |= LC( 1 ) + LC( 2 ) + LC( 3 ); NvmCtx.ChannelsMask[0] |= LC( 1 ) + LC( 2 ) + LC( 3 );
} }
if( nextChanParams->AggrTimeOff <= TimerGetElapsedTime( nextChanParams->LastAggrTx ) )
{
// Reset Aggregated time off
*aggregatedTimeOff = 0;
// Update bands Time OFF
nextTxDelay = RegionCommonUpdateBandTimeOff( nextChanParams->Joined, nextChanParams->DutyCycleEnabled, NvmCtx.Bands, EU433_MAX_NB_BANDS );
// Search how many channels are enabled // Search how many channels are enabled
nbEnabledChannels = CountNbOfEnabledChannels( nextChanParams->Joined, nextChanParams->Datarate, countChannelsParams.Joined = nextChanParams->Joined;
NvmCtx.ChannelsMask, NvmCtx.Channels, countChannelsParams.Datarate = nextChanParams->Datarate;
NvmCtx.Bands, enabledChannels, &delayTx ); countChannelsParams.ChannelsMask = NvmCtx.ChannelsMask;
} countChannelsParams.Channels = NvmCtx.Channels;
else countChannelsParams.Bands = NvmCtx.Bands;
{ countChannelsParams.MaxNbChannels = EU433_MAX_NB_CHANNELS;
delayTx++; countChannelsParams.JoinChannels = EU433_JOIN_CHANNELS;
nextTxDelay = nextChanParams->AggrTimeOff - TimerGetElapsedTime( nextChanParams->LastAggrTx );
}
if( nbEnabledChannels > 0 ) identifyChannelsParam.AggrTimeOff = nextChanParams->AggrTimeOff;
identifyChannelsParam.LastAggrTx = nextChanParams->LastAggrTx;
identifyChannelsParam.DutyCycleEnabled = nextChanParams->DutyCycleEnabled;
identifyChannelsParam.MaxBands = EU433_MAX_NB_BANDS;
identifyChannelsParam.ElapsedTimeSinceStartUp = nextChanParams->ElapsedTimeSinceStartUp;
identifyChannelsParam.LastTxIsJoinRequest = nextChanParams->LastTxIsJoinRequest;
identifyChannelsParam.ExpectedTimeOnAir = GetTimeOnAir( nextChanParams->Datarate, nextChanParams->PktLen );
identifyChannelsParam.CountNbOfEnabledChannelsParam = &countChannelsParams;
status = RegionCommonIdentifyChannels( &identifyChannelsParam, aggregatedTimeOff, enabledChannels,
&nbEnabledChannels, &nbRestrictedChannels, time );
if( status == LORAMAC_STATUS_OK )
{ {
// We found a valid channel // We found a valid channel
*channel = enabledChannels[randr( 0, nbEnabledChannels - 1 )]; *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 // Datarate not supported by any channel, restore defaults
NvmCtx.ChannelsMask[0] |= LC( 1 ) + LC( 2 ) + LC( 3 ); 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 ) LoRaMacStatus_t RegionEU433ChannelAdd( ChannelAddParams_t* channelAdd )

View File

@@ -37,6 +37,11 @@
#ifndef __REGION_EU433_H__ #ifndef __REGION_EU433_H__
#define __REGION_EU433_H__ #define __REGION_EU433_H__
#ifdef __cplusplus
extern "C"
{
#endif
#include "region/Region.h" #include "region/Region.h"
/*! /*!
@@ -204,6 +209,11 @@
*/ */
#define EU433_BEACON_CHANNEL_FREQ 434665000 #define EU433_BEACON_CHANNEL_FREQ 434665000
/*!
* Ping slot channel frequency
*/
#define EU433_PING_SLOT_CHANNEL_FREQ 434665000
/*! /*!
* Payload size of a beacon frame * Payload size of a beacon frame
*/ */
@@ -236,9 +246,9 @@
/*! /*!
* Band 0 definition * 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 * 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 }; 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 }; 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. * \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 ); 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 * \brief Searches and set the next random available channel
* *
@@ -506,4 +504,8 @@ uint8_t RegionEU433ApplyDrOffset( uint8_t downlinkDwellTime, int8_t dr, int8_t d
/*! \} defgroup REGIONEU433 */ /*! \} defgroup REGIONEU433 */
#ifdef __cplusplus
}
#endif
#endif // __REGION_EU433_H__ #endif // __REGION_EU433_H__

View File

@@ -127,7 +127,7 @@ static bool VerifyRfFreq( uint32_t freq, uint8_t *band )
} }
else if( ( freq >= 868700000 ) && ( freq <= 869200000 ) ) else if( ( freq >= 868700000 ) && ( freq <= 869200000 ) )
{ {
*band = 2; *band = 5;
} }
else if( ( freq >= 869400000 ) && ( freq <= 869650000 ) ) else if( ( freq >= 869400000 ) && ( freq <= 869650000 ) )
{ {
@@ -144,45 +144,21 @@ static bool VerifyRfFreq( uint32_t freq, uint8_t *band )
return true; 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; int8_t phyDr = DataratesEU868[datarate];
uint8_t delayTransmission = 0; uint32_t bandwidth = GetBandwidth( datarate );
TimerTime_t timeOnAir = 0;
for( uint8_t i = 0, k = 0; i < EU868_MAX_NB_CHANNELS; i += 16, k++ ) if( datarate == DR_7 )
{ // High Speed FSK channel
timeOnAir = Radio.TimeOnAir( MODEM_FSK, bandwidth, phyDr * 1000, 0, 5, false, pktLen, true );
}
else
{ {
for( uint8_t j = 0; j < 16; j++ ) timeOnAir = Radio.TimeOnAir( MODEM_LORA, bandwidth, phyDr, 1, 8, false, pktLen, true );
{
if( ( channelsMask[k] & ( 1 << j ) ) != 0 )
{
if( channels[i + j].Frequency == 0 )
{ // Check if the channel is enabled
continue;
} }
if( joined == false ) return timeOnAir;
{
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;
}
}
}
*delayTx = delayTransmission;
return nbEnabledChannels;
} }
PhyParam_t RegionEU868GetPhyParam( GetPhyParams_t* getPhy ) PhyParam_t RegionEU868GetPhyParam( GetPhyParams_t* getPhy )
@@ -236,11 +212,6 @@ PhyParam_t RegionEU868GetPhyParam( GetPhyParams_t* getPhy )
phyParam.Value = MaxPayloadOfDatarateEU868[getPhy->Datarate]; phyParam.Value = MaxPayloadOfDatarateEU868[getPhy->Datarate];
break; break;
} }
case PHY_MAX_PAYLOAD_REPEATER:
{
phyParam.Value = MaxPayloadOfDatarateRepeaterEU868[getPhy->Datarate];
break;
}
case PHY_DUTY_CYCLE: case PHY_DUTY_CYCLE:
{ {
phyParam.Value = EU868_DUTY_CYCLE_ENABLED; phyParam.Value = EU868_DUTY_CYCLE_ENABLED;
@@ -349,11 +320,26 @@ PhyParam_t RegionEU868GetPhyParam( GetPhyParams_t* getPhy )
phyParam.Value = EU868_BEACON_CHANNEL_DR; phyParam.Value = EU868_BEACON_CHANNEL_DR;
break; break;
} }
case PHY_PING_SLOT_CHANNEL_FREQ:
{
phyParam.Value = EU868_PING_SLOT_CHANNEL_FREQ;
break;
}
case PHY_PING_SLOT_CHANNEL_DR: case PHY_PING_SLOT_CHANNEL_DR:
{ {
phyParam.Value = EU868_PING_SLOT_CHANNEL_DR; phyParam.Value = EU868_PING_SLOT_CHANNEL_DR;
break; break;
} }
case PHY_SF_FROM_DR:
{
phyParam.Value = DataratesEU868[getPhy->Datarate];
break;
}
case PHY_BW_FROM_DR:
{
phyParam.Value = GetBandwidth( getPhy->Datarate );
break;
}
default: default:
{ {
break; break;
@@ -365,7 +351,8 @@ PhyParam_t RegionEU868GetPhyParam( GetPhyParams_t* getPhy )
void RegionEU868SetBandTxDone( SetBandTxDoneParams_t* txDone ) 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 ) void RegionEU868InitDefaults( InitDefaultsParams_t* params )
@@ -377,14 +364,19 @@ void RegionEU868InitDefaults( InitDefaultsParams_t* params )
EU868_BAND2, EU868_BAND2,
EU868_BAND3, EU868_BAND3,
EU868_BAND4, EU868_BAND4,
EU868_BAND5,
}; };
switch( params->Type ) switch( params->Type )
{ {
case INIT_TYPE_INIT: case INIT_TYPE_BANDS:
{ {
// Initialize bands // Initialize bands
memcpy1( ( uint8_t* )NvmCtx.Bands, ( uint8_t* )bands, sizeof( Band_t ) * EU868_MAX_NB_BANDS ); memcpy1( ( uint8_t* )NvmCtx.Bands, ( uint8_t* )bands, sizeof( Band_t ) * EU868_MAX_NB_BANDS );
break;
}
case INIT_TYPE_INIT:
{
// Channels // Channels
NvmCtx.Channels[0] = ( ChannelParams_t ) EU868_LC1; NvmCtx.Channels[0] = ( ChannelParams_t ) EU868_LC1;
@@ -393,6 +385,7 @@ void RegionEU868InitDefaults( InitDefaultsParams_t* params )
// Initialize the channels default mask // Initialize the channels default mask
NvmCtx.ChannelsDefaultMask[0] = LC( 1 ) + LC( 2 ) + LC( 3 ); NvmCtx.ChannelsDefaultMask[0] = LC( 1 ) + LC( 2 ) + LC( 3 );
// Update the channels mask // Update the channels mask
RegionCommonChanMaskCopy( NvmCtx.ChannelsMask, NvmCtx.ChannelsDefaultMask, 1 ); RegionCommonChanMaskCopy( NvmCtx.ChannelsMask, NvmCtx.ChannelsDefaultMask, 1 );
break; break;
@@ -409,6 +402,11 @@ void RegionEU868InitDefaults( InitDefaultsParams_t* params )
{ {
// Restore channels default mask // Restore channels default mask
NvmCtx.ChannelsMask[0] |= NvmCtx.ChannelsDefaultMask[0]; 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; break;
} }
default: default:
@@ -428,6 +426,11 @@ bool RegionEU868Verify( VerifyParams_t* verify, PhyAttribute_t phyAttribute )
{ {
switch( phyAttribute ) switch( phyAttribute )
{ {
case PHY_FREQUENCY:
{
uint8_t band = 0;
return VerifyRfFreq( verify->Frequency, &band );
}
case PHY_TX_DR: case PHY_TX_DR:
{ {
return RegionCommonValueInRange( verify->DatarateParams.Datarate, EU868_TX_MIN_DATARATE, EU868_TX_MAX_DATARATE ); 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; RadioModems_t modem;
int8_t dr = rxConfig->Datarate; int8_t dr = rxConfig->Datarate;
uint8_t maxPayload = 0;
int8_t phyDr = 0; int8_t phyDr = 0;
uint32_t frequency = rxConfig->Frequency; 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 ); Radio.SetRxConfig( modem, rxConfig->Bandwidth, phyDr, 1, 0, 8, rxConfig->WindowTimeout, false, 0, false, 0, 0, true, rxConfig->RxContinuous );
} }
if( rxConfig->RepeaterSupport == true ) Radio.SetMaxPayloadLength( modem, MaxPayloadOfDatarateEU868[dr] + LORAMAC_FRAME_PAYLOAD_OVERHEAD_SIZE );
{
maxPayload = MaxPayloadOfDatarateRepeaterEU868[dr];
}
else
{
maxPayload = MaxPayloadOfDatarateEU868[dr];
}
Radio.SetMaxPayloadLength( modem, maxPayload + LORA_MAC_FRMPAYLOAD_OVERHEAD );
*datarate = (uint8_t) dr; *datarate = (uint8_t) dr;
return true; return true;
@@ -627,18 +620,19 @@ bool RegionEU868TxConfig( TxConfigParams_t* txConfig, int8_t* txPower, TimerTime
if( txConfig->Datarate == DR_7 ) if( txConfig->Datarate == DR_7 )
{ // High Speed FSK channel { // High Speed FSK channel
modem = MODEM_FSK; 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 else
{ {
modem = MODEM_LORA; 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 // Setup maximum payload lenght of the radio driver
Radio.SetMaxPayloadLength( modem, txConfig->PktLen ); Radio.SetMaxPayloadLength( modem, txConfig->PktLen );
// Get the time-on-air of the next tx frame
*txTimeOnAir = Radio.TimeOnAir( modem, txConfig->PktLen );
*txPower = txPowerLimited; *txPower = txPowerLimited;
return true; return true;
@@ -864,74 +858,54 @@ int8_t RegionEU868AlternateDr( int8_t currentDr, AlternateDrType_t type )
return currentDr; 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 ) LoRaMacStatus_t RegionEU868NextChannel( NextChanParams_t* nextChanParams, uint8_t* channel, TimerTime_t* time, TimerTime_t* aggregatedTimeOff )
{ {
uint8_t nbEnabledChannels = 0; uint8_t nbEnabledChannels = 0;
uint8_t delayTx = 0; uint8_t nbRestrictedChannels = 0;
uint8_t enabledChannels[EU868_MAX_NB_CHANNELS] = { 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 ) if( RegionCommonCountChannels( NvmCtx.ChannelsMask, 0, 1 ) == 0 )
{ // Reactivate default channels { // Reactivate default channels
NvmCtx.ChannelsMask[0] |= LC( 1 ) + LC( 2 ) + LC( 3 ); NvmCtx.ChannelsMask[0] |= LC( 1 ) + LC( 2 ) + LC( 3 );
} }
if( nextChanParams->AggrTimeOff <= TimerGetElapsedTime( nextChanParams->LastAggrTx ) )
{
// Reset Aggregated time off
*aggregatedTimeOff = 0;
// Update bands Time OFF
nextTxDelay = RegionCommonUpdateBandTimeOff( nextChanParams->Joined, nextChanParams->DutyCycleEnabled, NvmCtx.Bands, EU868_MAX_NB_BANDS );
// Search how many channels are enabled // Search how many channels are enabled
nbEnabledChannels = CountNbOfEnabledChannels( nextChanParams->Joined, nextChanParams->Datarate, countChannelsParams.Joined = nextChanParams->Joined;
NvmCtx.ChannelsMask, NvmCtx.Channels, countChannelsParams.Datarate = nextChanParams->Datarate;
NvmCtx.Bands, enabledChannels, &delayTx ); countChannelsParams.ChannelsMask = NvmCtx.ChannelsMask;
} countChannelsParams.Channels = NvmCtx.Channels;
else countChannelsParams.Bands = NvmCtx.Bands;
{ countChannelsParams.MaxNbChannels = EU868_MAX_NB_CHANNELS;
delayTx++; countChannelsParams.JoinChannels = EU868_JOIN_CHANNELS;
nextTxDelay = nextChanParams->AggrTimeOff - TimerGetElapsedTime( nextChanParams->LastAggrTx );
}
if( nbEnabledChannels > 0 ) identifyChannelsParam.AggrTimeOff = nextChanParams->AggrTimeOff;
identifyChannelsParam.LastAggrTx = nextChanParams->LastAggrTx;
identifyChannelsParam.DutyCycleEnabled = nextChanParams->DutyCycleEnabled;
identifyChannelsParam.MaxBands = EU868_MAX_NB_BANDS;
identifyChannelsParam.ElapsedTimeSinceStartUp = nextChanParams->ElapsedTimeSinceStartUp;
identifyChannelsParam.LastTxIsJoinRequest = nextChanParams->LastTxIsJoinRequest;
identifyChannelsParam.ExpectedTimeOnAir = GetTimeOnAir( nextChanParams->Datarate, nextChanParams->PktLen );
identifyChannelsParam.CountNbOfEnabledChannelsParam = &countChannelsParams;
status = RegionCommonIdentifyChannels( &identifyChannelsParam, aggregatedTimeOff, enabledChannels,
&nbEnabledChannels, &nbRestrictedChannels, time );
if( status == LORAMAC_STATUS_OK )
{ {
// We found a valid channel // We found a valid channel
*channel = enabledChannels[randr( 0, nbEnabledChannels - 1 )]; *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 // Datarate not supported by any channel, restore defaults
NvmCtx.ChannelsMask[0] |= LC( 1 ) + LC( 2 ) + LC( 3 ); 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 ) LoRaMacStatus_t RegionEU868ChannelAdd( ChannelAddParams_t* channelAdd )

View File

@@ -37,6 +37,11 @@
#ifndef __REGION_EU868_H__ #ifndef __REGION_EU868_H__
#define __REGION_EU868_H__ #define __REGION_EU868_H__
#ifdef __cplusplus
extern "C"
{
#endif
#include "region/Region.h" #include "region/Region.h"
/*! /*!
@@ -196,6 +201,11 @@
*/ */
#define EU868_BEACON_CHANNEL_FREQ 869525000 #define EU868_BEACON_CHANNEL_FREQ 869525000
/*!
* Ping slot channel frequency
*/
#define EU868_PING_SLOT_CHANNEL_FREQ 869525000
/*! /*!
* Payload size of a beacon frame * Payload size of a beacon frame
*/ */
@@ -229,37 +239,44 @@
/*! /*!
* Maximum number of bands * Maximum number of bands
*/ */
#define EU868_MAX_NB_BANDS 5 #define EU868_MAX_NB_BANDS 6
/*! /*!
* Band 0 definition * 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 * 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 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 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 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 * 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 }; 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 }; 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. * \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 ); 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 * \brief Searches and set the next random available channel
* *
@@ -527,4 +532,8 @@ void RegionEU868RxBeaconSetup( RxBeaconSetup_t* rxBeaconSetup, uint8_t* outDr );
/*! \} defgroup REGIONEU868 */ /*! \} defgroup REGIONEU868 */
#ifdef __cplusplus
}
#endif
#endif // __REGION_EU868_H__ #endif // __REGION_EU868_H__

View File

@@ -123,45 +123,21 @@ static bool VerifyRfFreq( uint32_t freq )
return true; 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; int8_t phyDr = DataratesIN865[datarate];
uint8_t delayTransmission = 0; uint32_t bandwidth = GetBandwidth( datarate );
TimerTime_t timeOnAir = 0;
for( uint8_t i = 0, k = 0; i < IN865_MAX_NB_CHANNELS; i += 16, k++ ) if( datarate == DR_7 )
{ // High Speed FSK channel
timeOnAir = Radio.TimeOnAir( MODEM_FSK, bandwidth, phyDr * 1000, 0, 5, false, pktLen, true );
}
else
{ {
for( uint8_t j = 0; j < 16; j++ ) timeOnAir = Radio.TimeOnAir( MODEM_LORA, bandwidth, phyDr, 1, 8, false, pktLen, true );
{
if( ( channelsMask[k] & ( 1 << j ) ) != 0 )
{
if( channels[i + j].Frequency == 0 )
{ // Check if the channel is enabled
continue;
} }
if( joined == false ) return timeOnAir;
{
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;
}
}
}
*delayTx = delayTransmission;
return nbEnabledChannels;
} }
PhyParam_t RegionIN865GetPhyParam( GetPhyParams_t* getPhy ) PhyParam_t RegionIN865GetPhyParam( GetPhyParams_t* getPhy )
@@ -215,11 +191,6 @@ PhyParam_t RegionIN865GetPhyParam( GetPhyParams_t* getPhy )
phyParam.Value = MaxPayloadOfDatarateIN865[getPhy->Datarate]; phyParam.Value = MaxPayloadOfDatarateIN865[getPhy->Datarate];
break; break;
} }
case PHY_MAX_PAYLOAD_REPEATER:
{
phyParam.Value = MaxPayloadOfDatarateRepeaterIN865[getPhy->Datarate];
break;
}
case PHY_DUTY_CYCLE: case PHY_DUTY_CYCLE:
{ {
phyParam.Value = IN865_DUTY_CYCLE_ENABLED; phyParam.Value = IN865_DUTY_CYCLE_ENABLED;
@@ -328,11 +299,26 @@ PhyParam_t RegionIN865GetPhyParam( GetPhyParams_t* getPhy )
phyParam.Value = IN865_BEACON_CHANNEL_DR; phyParam.Value = IN865_BEACON_CHANNEL_DR;
break; break;
} }
case PHY_PING_SLOT_CHANNEL_FREQ:
{
phyParam.Value = IN865_PING_SLOT_CHANNEL_FREQ;
break;
}
case PHY_PING_SLOT_CHANNEL_DR: case PHY_PING_SLOT_CHANNEL_DR:
{ {
phyParam.Value = IN865_PING_SLOT_CHANNEL_DR; phyParam.Value = IN865_PING_SLOT_CHANNEL_DR;
break; break;
} }
case PHY_SF_FROM_DR:
{
phyParam.Value = DataratesIN865[getPhy->Datarate];
break;
}
case PHY_BW_FROM_DR:
{
phyParam.Value = GetBandwidth( getPhy->Datarate );
break;
}
default: default:
{ {
break; break;
@@ -344,7 +330,8 @@ PhyParam_t RegionIN865GetPhyParam( GetPhyParams_t* getPhy )
void RegionIN865SetBandTxDone( SetBandTxDoneParams_t* txDone ) 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 ) void RegionIN865InitDefaults( InitDefaultsParams_t* params )
@@ -356,10 +343,14 @@ void RegionIN865InitDefaults( InitDefaultsParams_t* params )
switch( params->Type ) switch( params->Type )
{ {
case INIT_TYPE_INIT: case INIT_TYPE_BANDS:
{ {
// Initialize bands // Initialize bands
memcpy1( ( uint8_t* )NvmCtx.Bands, ( uint8_t* )bands, sizeof( Band_t ) * IN865_MAX_NB_BANDS ); memcpy1( ( uint8_t* )NvmCtx.Bands, ( uint8_t* )bands, sizeof( Band_t ) * IN865_MAX_NB_BANDS );
break;
}
case INIT_TYPE_INIT:
{
// Channels // Channels
NvmCtx.Channels[0] = ( ChannelParams_t ) IN865_LC1; NvmCtx.Channels[0] = ( ChannelParams_t ) IN865_LC1;
@@ -384,6 +375,11 @@ void RegionIN865InitDefaults( InitDefaultsParams_t* params )
{ {
// Restore channels default mask // Restore channels default mask
NvmCtx.ChannelsMask[0] |= NvmCtx.ChannelsDefaultMask[0]; 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; break;
} }
default: default:
@@ -403,6 +399,10 @@ bool RegionIN865Verify( VerifyParams_t* verify, PhyAttribute_t phyAttribute )
{ {
switch( phyAttribute ) switch( phyAttribute )
{ {
case PHY_FREQUENCY:
{
return VerifyRfFreq( verify->Frequency );
}
case PHY_TX_DR: case PHY_TX_DR:
{ {
if( verify->DatarateParams.Datarate == DR_6 ) if( verify->DatarateParams.Datarate == DR_6 )
@@ -547,7 +547,6 @@ bool RegionIN865RxConfig( RxConfigParams_t* rxConfig, int8_t* datarate )
{ {
RadioModems_t modem; RadioModems_t modem;
int8_t dr = rxConfig->Datarate; int8_t dr = rxConfig->Datarate;
uint8_t maxPayload = 0;
int8_t phyDr = 0; int8_t phyDr = 0;
uint32_t frequency = rxConfig->Frequency; 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 ); Radio.SetRxConfig( modem, rxConfig->Bandwidth, phyDr, 1, 0, 8, rxConfig->WindowTimeout, false, 0, false, 0, 0, true, rxConfig->RxContinuous );
} }
if( rxConfig->RepeaterSupport == true ) Radio.SetMaxPayloadLength( modem, MaxPayloadOfDatarateIN865[dr] + LORAMAC_FRAME_PAYLOAD_OVERHEAD_SIZE );
{
maxPayload = MaxPayloadOfDatarateRepeaterIN865[dr];
}
else
{
maxPayload = MaxPayloadOfDatarateIN865[dr];
}
Radio.SetMaxPayloadLength( modem, maxPayload + LORA_MAC_FRMPAYLOAD_OVERHEAD );
*datarate = (uint8_t) dr; *datarate = (uint8_t) dr;
return true; return true;
@@ -615,18 +606,19 @@ bool RegionIN865TxConfig( TxConfigParams_t* txConfig, int8_t* txPower, TimerTime
if( txConfig->Datarate == DR_7 ) if( txConfig->Datarate == DR_7 )
{ // High Speed FSK channel { // High Speed FSK channel
modem = MODEM_FSK; 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 else
{ {
modem = MODEM_LORA; 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 // Setup maximum payload lenght of the radio driver
Radio.SetMaxPayloadLength( modem, txConfig->PktLen ); Radio.SetMaxPayloadLength( modem, txConfig->PktLen );
// Get the time-on-air of the next tx frame
*txTimeOnAir = Radio.TimeOnAir( modem, txConfig->PktLen );
*txPower = txPowerLimited; *txPower = txPowerLimited;
return true; return true;
@@ -857,74 +849,54 @@ int8_t RegionIN865AlternateDr( int8_t currentDr, AlternateDrType_t type )
return currentDr; 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 ) LoRaMacStatus_t RegionIN865NextChannel( NextChanParams_t* nextChanParams, uint8_t* channel, TimerTime_t* time, TimerTime_t* aggregatedTimeOff )
{ {
uint8_t nbEnabledChannels = 0; uint8_t nbEnabledChannels = 0;
uint8_t delayTx = 0; uint8_t nbRestrictedChannels = 0;
uint8_t enabledChannels[IN865_MAX_NB_CHANNELS] = { 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 ) if( RegionCommonCountChannels( NvmCtx.ChannelsMask, 0, 1 ) == 0 )
{ // Reactivate default channels { // Reactivate default channels
NvmCtx.ChannelsMask[0] |= LC( 1 ) + LC( 2 ) + LC( 3 ); NvmCtx.ChannelsMask[0] |= LC( 1 ) + LC( 2 ) + LC( 3 );
} }
if( nextChanParams->AggrTimeOff <= TimerGetElapsedTime( nextChanParams->LastAggrTx ) )
{
// Reset Aggregated time off
*aggregatedTimeOff = 0;
// Update bands Time OFF
nextTxDelay = RegionCommonUpdateBandTimeOff( nextChanParams->Joined, nextChanParams->DutyCycleEnabled, NvmCtx.Bands, IN865_MAX_NB_BANDS );
// Search how many channels are enabled // Search how many channels are enabled
nbEnabledChannels = CountNbOfEnabledChannels( nextChanParams->Joined, nextChanParams->Datarate, countChannelsParams.Joined = nextChanParams->Joined;
NvmCtx.ChannelsMask, NvmCtx.Channels, countChannelsParams.Datarate = nextChanParams->Datarate;
NvmCtx.Bands, enabledChannels, &delayTx ); countChannelsParams.ChannelsMask = NvmCtx.ChannelsMask;
} countChannelsParams.Channels = NvmCtx.Channels;
else countChannelsParams.Bands = NvmCtx.Bands;
{ countChannelsParams.MaxNbChannels = IN865_MAX_NB_CHANNELS;
delayTx++; countChannelsParams.JoinChannels = IN865_JOIN_CHANNELS;
nextTxDelay = nextChanParams->AggrTimeOff - TimerGetElapsedTime( nextChanParams->LastAggrTx );
}
if( nbEnabledChannels > 0 ) identifyChannelsParam.AggrTimeOff = nextChanParams->AggrTimeOff;
identifyChannelsParam.LastAggrTx = nextChanParams->LastAggrTx;
identifyChannelsParam.DutyCycleEnabled = nextChanParams->DutyCycleEnabled;
identifyChannelsParam.MaxBands = IN865_MAX_NB_BANDS;
identifyChannelsParam.ElapsedTimeSinceStartUp = nextChanParams->ElapsedTimeSinceStartUp;
identifyChannelsParam.LastTxIsJoinRequest = nextChanParams->LastTxIsJoinRequest;
identifyChannelsParam.ExpectedTimeOnAir = GetTimeOnAir( nextChanParams->Datarate, nextChanParams->PktLen );
identifyChannelsParam.CountNbOfEnabledChannelsParam = &countChannelsParams;
status = RegionCommonIdentifyChannels( &identifyChannelsParam, aggregatedTimeOff, enabledChannels,
&nbEnabledChannels, &nbRestrictedChannels, time );
if( status == LORAMAC_STATUS_OK )
{ {
// We found a valid channel // We found a valid channel
*channel = enabledChannels[randr( 0, nbEnabledChannels - 1 )]; *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 // Datarate not supported by any channel, restore defaults
NvmCtx.ChannelsMask[0] |= LC( 1 ) + LC( 2 ) + LC( 3 ); 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 ) LoRaMacStatus_t RegionIN865ChannelAdd( ChannelAddParams_t* channelAdd )

View File

@@ -37,6 +37,11 @@
#ifndef __REGION_IN865_H__ #ifndef __REGION_IN865_H__
#define __REGION_IN865_H__ #define __REGION_IN865_H__
#ifdef __cplusplus
extern "C"
{
#endif
#include "region/Region.h" #include "region/Region.h"
/*! /*!
@@ -132,7 +137,7 @@
/*! /*!
* Enabled or disabled the duty cycle * Enabled or disabled the duty cycle
*/ */
#define IN865_DUTY_CYCLE_ENABLED 1 #define IN865_DUTY_CYCLE_ENABLED 0
/*! /*!
* Maximum RX window duration * Maximum RX window duration
@@ -196,6 +201,11 @@
*/ */
#define IN865_BEACON_CHANNEL_FREQ 866550000 #define IN865_BEACON_CHANNEL_FREQ 866550000
/*!
* Ping slot channel frequency
*/
#define IN865_PING_SLOT_CHANNEL_FREQ 866550000
/*! /*!
* Payload size of a beacon frame * Payload size of a beacon frame
*/ */
@@ -233,9 +243,9 @@
/*! /*!
* Band 0 definition * 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 * 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 }; 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 }; 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. * 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 ); 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 * \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 */ /*! \} defgroup REGIONIN865 */
#ifdef __cplusplus
}
#endif
#endif // __REGION_IN865_H__ #endif // __REGION_IN865_H__

View File

@@ -138,45 +138,12 @@ static bool VerifyRfFreq( uint32_t freq )
return false; 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; int8_t phyDr = DataratesKR920[datarate];
uint8_t delayTransmission = 0; uint32_t bandwidth = GetBandwidth( datarate );
for( uint8_t i = 0, k = 0; i < KR920_MAX_NB_CHANNELS; i += 16, k++ ) return Radio.TimeOnAir( MODEM_LORA, bandwidth, phyDr, 1, 8, false, pktLen, true );
{
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;
} }
PhyParam_t RegionKR920GetPhyParam( GetPhyParams_t* getPhy ) PhyParam_t RegionKR920GetPhyParam( GetPhyParams_t* getPhy )
@@ -230,11 +197,6 @@ PhyParam_t RegionKR920GetPhyParam( GetPhyParams_t* getPhy )
phyParam.Value = MaxPayloadOfDatarateKR920[getPhy->Datarate]; phyParam.Value = MaxPayloadOfDatarateKR920[getPhy->Datarate];
break; break;
} }
case PHY_MAX_PAYLOAD_REPEATER:
{
phyParam.Value = MaxPayloadOfDatarateRepeaterKR920[getPhy->Datarate];
break;
}
case PHY_DUTY_CYCLE: case PHY_DUTY_CYCLE:
{ {
phyParam.Value = KR920_DUTY_CYCLE_ENABLED; phyParam.Value = KR920_DUTY_CYCLE_ENABLED;
@@ -347,11 +309,26 @@ PhyParam_t RegionKR920GetPhyParam( GetPhyParams_t* getPhy )
phyParam.Value = KR920_BEACON_CHANNEL_DR; phyParam.Value = KR920_BEACON_CHANNEL_DR;
break; break;
} }
case PHY_PING_SLOT_CHANNEL_FREQ:
{
phyParam.Value = KR920_PING_SLOT_CHANNEL_FREQ;
break;
}
case PHY_PING_SLOT_CHANNEL_DR: case PHY_PING_SLOT_CHANNEL_DR:
{ {
phyParam.Value = KR920_PING_SLOT_CHANNEL_DR; phyParam.Value = KR920_PING_SLOT_CHANNEL_DR;
break; break;
} }
case PHY_SF_FROM_DR:
{
phyParam.Value = DataratesKR920[getPhy->Datarate];
break;
}
case PHY_BW_FROM_DR:
{
phyParam.Value = GetBandwidth( getPhy->Datarate );
break;
}
default: default:
{ {
break; break;
@@ -363,7 +340,8 @@ PhyParam_t RegionKR920GetPhyParam( GetPhyParams_t* getPhy )
void RegionKR920SetBandTxDone( SetBandTxDoneParams_t* txDone ) 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 ) void RegionKR920InitDefaults( InitDefaultsParams_t* params )
@@ -375,10 +353,14 @@ void RegionKR920InitDefaults( InitDefaultsParams_t* params )
switch( params->Type ) switch( params->Type )
{ {
case INIT_TYPE_INIT: case INIT_TYPE_BANDS:
{ {
// Initialize bands // Initialize bands
memcpy1( ( uint8_t* )NvmCtx.Bands, ( uint8_t* )bands, sizeof( Band_t ) * KR920_MAX_NB_BANDS ); memcpy1( ( uint8_t* )NvmCtx.Bands, ( uint8_t* )bands, sizeof( Band_t ) * KR920_MAX_NB_BANDS );
break;
}
case INIT_TYPE_INIT:
{
// Channels // Channels
NvmCtx.Channels[0] = ( ChannelParams_t ) KR920_LC1; NvmCtx.Channels[0] = ( ChannelParams_t ) KR920_LC1;
@@ -387,6 +369,7 @@ void RegionKR920InitDefaults( InitDefaultsParams_t* params )
// Initialize the channels default mask // Initialize the channels default mask
NvmCtx.ChannelsDefaultMask[0] = LC( 1 ) + LC( 2 ) + LC( 3 ); NvmCtx.ChannelsDefaultMask[0] = LC( 1 ) + LC( 2 ) + LC( 3 );
// Update the channels mask // Update the channels mask
RegionCommonChanMaskCopy( NvmCtx.ChannelsMask, NvmCtx.ChannelsDefaultMask, 1 ); RegionCommonChanMaskCopy( NvmCtx.ChannelsMask, NvmCtx.ChannelsDefaultMask, 1 );
break; break;
@@ -403,6 +386,11 @@ void RegionKR920InitDefaults( InitDefaultsParams_t* params )
{ {
// Restore channels default mask // Restore channels default mask
NvmCtx.ChannelsMask[0] |= NvmCtx.ChannelsDefaultMask[0]; 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; break;
} }
default: default:
@@ -422,6 +410,10 @@ bool RegionKR920Verify( VerifyParams_t* verify, PhyAttribute_t phyAttribute )
{ {
switch( phyAttribute ) switch( phyAttribute )
{ {
case PHY_FREQUENCY:
{
return VerifyRfFreq( verify->Frequency );
}
case PHY_TX_DR: case PHY_TX_DR:
{ {
return RegionCommonValueInRange( verify->DatarateParams.Datarate, KR920_TX_MIN_DATARATE, KR920_TX_MAX_DATARATE ); 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 ) bool RegionKR920RxConfig( RxConfigParams_t* rxConfig, int8_t* datarate )
{ {
int8_t dr = rxConfig->Datarate; int8_t dr = rxConfig->Datarate;
uint8_t maxPayload = 0;
int8_t phyDr = 0; int8_t phyDr = 0;
uint32_t frequency = rxConfig->Frequency; uint32_t frequency = rxConfig->Frequency;
@@ -571,8 +562,7 @@ bool RegionKR920RxConfig( RxConfigParams_t* rxConfig, int8_t* datarate )
// Radio configuration // Radio configuration
Radio.SetRxConfig( MODEM_LORA, rxConfig->Bandwidth, phyDr, 1, 0, 8, rxConfig->WindowTimeout, false, 0, false, 0, 0, true, rxConfig->RxContinuous ); 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, MaxPayloadOfDatarateKR920[dr] + LORAMAC_FRAME_PAYLOAD_OVERHEAD_SIZE );
Radio.SetMaxPayloadLength( MODEM_LORA, maxPayload + LORA_MAC_FRMPAYLOAD_OVERHEAD );
*datarate = (uint8_t) dr; *datarate = (uint8_t) dr;
return true; return true;
@@ -596,12 +586,12 @@ bool RegionKR920TxConfig( TxConfigParams_t* txConfig, int8_t* txPower, TimerTime
// Setup the radio frequency // Setup the radio frequency
Radio.SetChannel( NvmCtx.Channels[txConfig->Channel].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 // Setup maximum payload lenght of the radio driver
Radio.SetMaxPayloadLength( MODEM_LORA, txConfig->PktLen ); Radio.SetMaxPayloadLength( MODEM_LORA, txConfig->PktLen );
// Get the time-on-air of the next tx frame // Update time-on-air
*txTimeOnAir = Radio.TimeOnAir( MODEM_LORA, txConfig->PktLen ); *txTimeOnAir = GetTimeOnAir( txConfig->Datarate, txConfig->PktLen );
*txPower = txPowerLimited; *txPower = txPowerLimited;
return true; return true;
@@ -825,55 +815,45 @@ int8_t RegionKR920AlternateDr( int8_t currentDr, AlternateDrType_t type )
return currentDr; 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 ) LoRaMacStatus_t RegionKR920NextChannel( NextChanParams_t* nextChanParams, uint8_t* channel, TimerTime_t* time, TimerTime_t* aggregatedTimeOff )
{ {
uint8_t channelNext = 0; uint8_t channelNext = 0;
uint8_t nbEnabledChannels = 0; uint8_t nbEnabledChannels = 0;
uint8_t delayTx = 0; uint8_t nbRestrictedChannels = 0;
uint8_t enabledChannels[KR920_MAX_NB_CHANNELS] = { 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 ) if( RegionCommonCountChannels( NvmCtx.ChannelsMask, 0, 1 ) == 0 )
{ // Reactivate default channels { // Reactivate default channels
NvmCtx.ChannelsMask[0] |= LC( 1 ) + LC( 2 ) + LC( 3 ); NvmCtx.ChannelsMask[0] |= LC( 1 ) + LC( 2 ) + LC( 3 );
} }
if( nextChanParams->AggrTimeOff <= TimerGetElapsedTime( nextChanParams->LastAggrTx ) )
{
// Reset Aggregated time off
*aggregatedTimeOff = 0;
// Update bands Time OFF
nextTxDelay = RegionCommonUpdateBandTimeOff( nextChanParams->Joined, nextChanParams->DutyCycleEnabled, NvmCtx.Bands, KR920_MAX_NB_BANDS );
// Search how many channels are enabled // Search how many channels are enabled
nbEnabledChannels = CountNbOfEnabledChannels( nextChanParams->Joined, nextChanParams->Datarate, countChannelsParams.Joined = nextChanParams->Joined;
NvmCtx.ChannelsMask, NvmCtx.Channels, countChannelsParams.Datarate = nextChanParams->Datarate;
NvmCtx.Bands, enabledChannels, &delayTx ); countChannelsParams.ChannelsMask = NvmCtx.ChannelsMask;
} countChannelsParams.Channels = NvmCtx.Channels;
else countChannelsParams.Bands = NvmCtx.Bands;
{ countChannelsParams.MaxNbChannels = KR920_MAX_NB_CHANNELS;
delayTx++; countChannelsParams.JoinChannels = KR920_JOIN_CHANNELS;
nextTxDelay = nextChanParams->AggrTimeOff - TimerGetElapsedTime( nextChanParams->LastAggrTx );
}
if( nbEnabledChannels > 0 ) identifyChannelsParam.AggrTimeOff = nextChanParams->AggrTimeOff;
identifyChannelsParam.LastAggrTx = nextChanParams->LastAggrTx;
identifyChannelsParam.DutyCycleEnabled = nextChanParams->DutyCycleEnabled;
identifyChannelsParam.MaxBands = KR920_MAX_NB_BANDS;
identifyChannelsParam.ElapsedTimeSinceStartUp = nextChanParams->ElapsedTimeSinceStartUp;
identifyChannelsParam.LastTxIsJoinRequest = nextChanParams->LastTxIsJoinRequest;
identifyChannelsParam.ExpectedTimeOnAir = GetTimeOnAir( nextChanParams->Datarate, nextChanParams->PktLen );
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++ ) 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 // Free channel found
*channel = channelNext; *channel = channelNext;
*time = 0;
return LORAMAC_STATUS_OK; 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 // Datarate not supported by any channel, restore defaults
NvmCtx.ChannelsMask[0] |= LC( 1 ) + LC( 2 ) + LC( 3 ); 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 ) LoRaMacStatus_t RegionKR920ChannelAdd( ChannelAddParams_t* channelAdd )

View File

@@ -37,6 +37,11 @@
#ifndef __REGION_KR920_H__ #ifndef __REGION_KR920_H__
#define __REGION_KR920_H__ #define __REGION_KR920_H__
#ifdef __cplusplus
extern "C"
{
#endif
#include "region/Region.h" #include "region/Region.h"
/*! /*!
@@ -201,6 +206,11 @@
*/ */
#define KR920_BEACON_CHANNEL_FREQ 923100000 #define KR920_BEACON_CHANNEL_FREQ 923100000
/*!
* Ping slot channel frequency
*/
#define KR920_PING_SLOT_CHANNEL_FREQ 923100000
/*! /*!
* Payload size of a beacon frame * Payload size of a beacon frame
*/ */
@@ -238,9 +248,9 @@
/*! /*!
* Band 0 definition * 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 * 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 }; 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 }; 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. * \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 ); 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 * \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 */ /*! \} defgroup REGIONKR920 */
#ifdef __cplusplus
}
#endif
#endif // __REGION_KR920_H__ #endif // __REGION_KR920_H__

View File

@@ -120,45 +120,21 @@ static bool VerifyRfFreq( uint32_t freq )
return true; 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; int8_t phyDr = DataratesRU864[datarate];
uint8_t delayTransmission = 0; uint32_t bandwidth = GetBandwidth( datarate );
TimerTime_t timeOnAir = 0;
for( uint8_t i = 0, k = 0; i < RU864_MAX_NB_CHANNELS; i += 16, k++ ) if( datarate == DR_7 )
{ // High Speed FSK channel
timeOnAir = Radio.TimeOnAir( MODEM_FSK, bandwidth, phyDr * 1000, 0, 5, false, pktLen, true );
}
else
{ {
for( uint8_t j = 0; j < 16; j++ ) timeOnAir = Radio.TimeOnAir( MODEM_LORA, bandwidth, phyDr, 1, 8, false, pktLen, true );
{
if( ( channelsMask[k] & ( 1 << j ) ) != 0 )
{
if( channels[i + j].Frequency == 0 )
{ // Check if the channel is enabled
continue;
} }
if( joined == false ) return timeOnAir;
{
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;
}
}
}
*delayTx = delayTransmission;
return nbEnabledChannels;
} }
PhyParam_t RegionRU864GetPhyParam( GetPhyParams_t* getPhy ) 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 ); phyParam.Value = GetNextLowerTxDr( getPhy->Datarate, RU864_TX_MIN_DATARATE );
break; break;
} }
case PHY_MAX_TX_POWER:
{
phyParam.Value = RU864_MAX_TX_POWER;
break;
}
case PHY_DEF_TX_POWER: case PHY_DEF_TX_POWER:
{ {
phyParam.Value = RU864_DEFAULT_TX_POWER; phyParam.Value = RU864_DEFAULT_TX_POWER;
@@ -207,11 +188,6 @@ PhyParam_t RegionRU864GetPhyParam( GetPhyParams_t* getPhy )
phyParam.Value = MaxPayloadOfDatarateRU864[getPhy->Datarate]; phyParam.Value = MaxPayloadOfDatarateRU864[getPhy->Datarate];
break; break;
} }
case PHY_MAX_PAYLOAD_REPEATER:
{
phyParam.Value = MaxPayloadOfDatarateRepeaterRU864[getPhy->Datarate];
break;
}
case PHY_DUTY_CYCLE: case PHY_DUTY_CYCLE:
{ {
phyParam.Value = RU864_DUTY_CYCLE_ENABLED; phyParam.Value = RU864_DUTY_CYCLE_ENABLED;
@@ -320,6 +296,26 @@ PhyParam_t RegionRU864GetPhyParam( GetPhyParams_t* getPhy )
phyParam.Value = RU864_BEACON_CHANNEL_DR; phyParam.Value = RU864_BEACON_CHANNEL_DR;
break; 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: default:
{ {
break; break;
@@ -331,7 +327,8 @@ PhyParam_t RegionRU864GetPhyParam( GetPhyParams_t* getPhy )
void RegionRU864SetBandTxDone( SetBandTxDoneParams_t* txDone ) 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 ) void RegionRU864InitDefaults( InitDefaultsParams_t* params )
@@ -343,10 +340,14 @@ void RegionRU864InitDefaults( InitDefaultsParams_t* params )
switch( params->Type ) switch( params->Type )
{ {
case INIT_TYPE_INIT: case INIT_TYPE_BANDS:
{ {
// Initialize bands // Initialize bands
memcpy1( ( uint8_t* )NvmCtx.Bands, ( uint8_t* )bands, sizeof( Band_t ) * RU864_MAX_NB_BANDS ); memcpy1( ( uint8_t* )NvmCtx.Bands, ( uint8_t* )bands, sizeof( Band_t ) * RU864_MAX_NB_BANDS );
break;
}
case INIT_TYPE_INIT:
{
// Channels // Channels
NvmCtx.Channels[0] = ( ChannelParams_t ) RU864_LC1; NvmCtx.Channels[0] = ( ChannelParams_t ) RU864_LC1;
@@ -370,6 +371,10 @@ void RegionRU864InitDefaults( InitDefaultsParams_t* params )
{ {
// Restore channels default mask // Restore channels default mask
NvmCtx.ChannelsMask[0] |= NvmCtx.ChannelsDefaultMask[0]; NvmCtx.ChannelsMask[0] |= NvmCtx.ChannelsDefaultMask[0];
// Channels
NvmCtx.Channels[0] = ( ChannelParams_t ) RU864_LC1;
NvmCtx.Channels[1] = ( ChannelParams_t ) RU864_LC2;
break; break;
} }
default: default:
@@ -389,6 +394,10 @@ bool RegionRU864Verify( VerifyParams_t* verify, PhyAttribute_t phyAttribute )
{ {
switch( phyAttribute ) switch( phyAttribute )
{ {
case PHY_FREQUENCY:
{
return VerifyRfFreq( verify->Frequency );
}
case PHY_TX_DR: case PHY_TX_DR:
{ {
return RegionCommonValueInRange( verify->DatarateParams.Datarate, RU864_TX_MIN_DATARATE, RU864_TX_MAX_DATARATE ); 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; RadioModems_t modem;
int8_t dr = rxConfig->Datarate; int8_t dr = rxConfig->Datarate;
uint8_t maxPayload = 0;
int8_t phyDr = 0; int8_t phyDr = 0;
uint32_t frequency = rxConfig->Frequency; 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 ); Radio.SetRxConfig( modem, rxConfig->Bandwidth, phyDr, 1, 0, 8, rxConfig->WindowTimeout, false, 0, false, 0, 0, true, rxConfig->RxContinuous );
} }
if( rxConfig->RepeaterSupport == true ) Radio.SetMaxPayloadLength( modem, MaxPayloadOfDatarateRU864[dr] + LORAMAC_FRAME_PAYLOAD_OVERHEAD_SIZE );
{
maxPayload = MaxPayloadOfDatarateRepeaterRU864[dr];
}
else
{
maxPayload = MaxPayloadOfDatarateRU864[dr];
}
Radio.SetMaxPayloadLength( modem, maxPayload + LORA_MAC_FRMPAYLOAD_OVERHEAD );
*datarate = (uint8_t) dr; *datarate = (uint8_t) dr;
return true; return true;
@@ -588,18 +587,19 @@ bool RegionRU864TxConfig( TxConfigParams_t* txConfig, int8_t* txPower, TimerTime
if( txConfig->Datarate == DR_7 ) if( txConfig->Datarate == DR_7 )
{ // High Speed FSK channel { // High Speed FSK channel
modem = MODEM_FSK; 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 else
{ {
modem = MODEM_LORA; 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 // Setup maximum payload lenght of the radio driver
Radio.SetMaxPayloadLength( modem, txConfig->PktLen ); Radio.SetMaxPayloadLength( modem, txConfig->PktLen );
// Get the time-on-air of the next tx frame
*txTimeOnAir = Radio.TimeOnAir( modem, txConfig->PktLen );
*txPower = txPowerLimited; *txPower = txPowerLimited;
return true; return true;
@@ -823,74 +823,54 @@ int8_t RegionRU864AlternateDr( int8_t currentDr, AlternateDrType_t type )
return currentDr; 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 ) LoRaMacStatus_t RegionRU864NextChannel( NextChanParams_t* nextChanParams, uint8_t* channel, TimerTime_t* time, TimerTime_t* aggregatedTimeOff )
{ {
uint8_t nbEnabledChannels = 0; uint8_t nbEnabledChannels = 0;
uint8_t delayTx = 0; uint8_t nbRestrictedChannels = 0;
uint8_t enabledChannels[RU864_MAX_NB_CHANNELS] = { 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 ) if( RegionCommonCountChannels( NvmCtx.ChannelsMask, 0, 1 ) == 0 )
{ // Reactivate default channels { // Reactivate default channels
NvmCtx.ChannelsMask[0] |= LC( 1 ) + LC( 2 ); NvmCtx.ChannelsMask[0] |= LC( 1 ) + LC( 2 );
} }
if( nextChanParams->AggrTimeOff <= TimerGetElapsedTime( nextChanParams->LastAggrTx ) )
{
// Reset Aggregated time off
*aggregatedTimeOff = 0;
// Update bands Time OFF
nextTxDelay = RegionCommonUpdateBandTimeOff( nextChanParams->Joined, nextChanParams->DutyCycleEnabled, NvmCtx.Bands, RU864_MAX_NB_BANDS );
// Search how many channels are enabled // Search how many channels are enabled
nbEnabledChannels = CountNbOfEnabledChannels( nextChanParams->Joined, nextChanParams->Datarate, countChannelsParams.Joined = nextChanParams->Joined;
NvmCtx.ChannelsMask, NvmCtx.Channels, countChannelsParams.Datarate = nextChanParams->Datarate;
NvmCtx.Bands, enabledChannels, &delayTx ); countChannelsParams.ChannelsMask = NvmCtx.ChannelsMask;
} countChannelsParams.Channels = NvmCtx.Channels;
else countChannelsParams.Bands = NvmCtx.Bands;
{ countChannelsParams.MaxNbChannels = RU864_MAX_NB_CHANNELS;
delayTx++; countChannelsParams.JoinChannels = RU864_JOIN_CHANNELS;
nextTxDelay = nextChanParams->AggrTimeOff - TimerGetElapsedTime( nextChanParams->LastAggrTx );
}
if( nbEnabledChannels > 0 ) identifyChannelsParam.AggrTimeOff = nextChanParams->AggrTimeOff;
identifyChannelsParam.LastAggrTx = nextChanParams->LastAggrTx;
identifyChannelsParam.DutyCycleEnabled = nextChanParams->DutyCycleEnabled;
identifyChannelsParam.MaxBands = RU864_MAX_NB_BANDS;
identifyChannelsParam.ElapsedTimeSinceStartUp = nextChanParams->ElapsedTimeSinceStartUp;
identifyChannelsParam.LastTxIsJoinRequest = nextChanParams->LastTxIsJoinRequest;
identifyChannelsParam.ExpectedTimeOnAir = GetTimeOnAir( nextChanParams->Datarate, nextChanParams->PktLen );
identifyChannelsParam.CountNbOfEnabledChannelsParam = &countChannelsParams;
status = RegionCommonIdentifyChannels( &identifyChannelsParam, aggregatedTimeOff, enabledChannels,
&nbEnabledChannels, &nbRestrictedChannels, time );
if( status == LORAMAC_STATUS_OK )
{ {
// We found a valid channel // We found a valid channel
*channel = enabledChannels[randr( 0, nbEnabledChannels - 1 )]; *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 // Datarate not supported by any channel, restore defaults
NvmCtx.ChannelsMask[0] |= LC( 1 ) + LC( 2 ); NvmCtx.ChannelsMask[0] |= LC( 1 ) + LC( 2 );
*time = 0;
return LORAMAC_STATUS_NO_CHANNEL_FOUND;
} }
return status;
} }
LoRaMacStatus_t RegionRU864ChannelAdd( ChannelAddParams_t* channelAdd ) LoRaMacStatus_t RegionRU864ChannelAdd( ChannelAddParams_t* channelAdd )

View File

@@ -35,6 +35,11 @@
#ifndef __REGION_RU864_H__ #ifndef __REGION_RU864_H__
#define __REGION_RU864_H__ #define __REGION_RU864_H__
#ifdef __cplusplus
extern "C"
{
#endif
#include "LoRaMac.h" #include "LoRaMac.h"
/*! /*!
@@ -194,6 +199,11 @@
*/ */
#define RU864_BEACON_CHANNEL_FREQ 869100000 #define RU864_BEACON_CHANNEL_FREQ 869100000
/*!
* Ping slot channel frequency
*/
#define RU864_PING_SLOT_CHANNEL_FREQ 868900000
/*! /*!
* Payload size of a beacon frame * Payload size of a beacon frame
*/ */
@@ -219,6 +229,11 @@
*/ */
#define RU864_BEACON_CHANNEL_BW 0 #define RU864_BEACON_CHANNEL_BW 0
/*!
* Datarate of the ping slot channel
*/
#define RU864_PING_SLOT_CHANNEL_DR DR_3
/*! /*!
* Maximum number of bands * Maximum number of bands
*/ */
@@ -226,9 +241,9 @@
/*! /*!
* Band 0 definition * 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 * 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 }; 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 }; 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. * \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 ); 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 * \brief Searches and set the next random available channel
* *
@@ -491,4 +494,8 @@ void RegionRU864RxBeaconSetup( RxBeaconSetup_t* rxBeaconSetup, uint8_t* outDr );
/*! \} defgroup REGIONRU864 */ /*! \} defgroup REGIONRU864 */
#ifdef __cplusplus
}
#endif
#endif // __REGION_RU864_H__ #endif // __REGION_RU864_H__

View File

@@ -254,38 +254,12 @@ static bool VerifyRfFreq( uint32_t freq )
return true; 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; int8_t phyDr = DataratesUS915[datarate];
uint8_t delayTransmission = 0; uint32_t bandwidth = GetBandwidth( datarate );
for( uint8_t i = 0, k = 0; i < US915_MAX_NB_CHANNELS; i += 16, k++ ) return Radio.TimeOnAir( MODEM_LORA, bandwidth, phyDr, 1, 8, false, pktLen, true );
{
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;
} }
PhyParam_t RegionUS915GetPhyParam( GetPhyParams_t* getPhy ) PhyParam_t RegionUS915GetPhyParam( GetPhyParams_t* getPhy )
@@ -339,11 +313,6 @@ PhyParam_t RegionUS915GetPhyParam( GetPhyParams_t* getPhy )
phyParam.Value = MaxPayloadOfDatarateUS915[getPhy->Datarate]; phyParam.Value = MaxPayloadOfDatarateUS915[getPhy->Datarate];
break; break;
} }
case PHY_MAX_PAYLOAD_REPEATER:
{
phyParam.Value = MaxPayloadOfDatarateRepeaterUS915[getPhy->Datarate];
break;
}
case PHY_DUTY_CYCLE: case PHY_DUTY_CYCLE:
{ {
phyParam.Value = US915_DUTY_CYCLE_ENABLED; phyParam.Value = US915_DUTY_CYCLE_ENABLED;
@@ -427,7 +396,7 @@ PhyParam_t RegionUS915GetPhyParam( GetPhyParams_t* getPhy )
} }
case PHY_DEF_MAX_EIRP: case PHY_DEF_MAX_EIRP:
{ {
phyParam.fValue = US915_DEFAULT_MAX_ERP + 2.15; phyParam.fValue = US915_DEFAULT_MAX_ERP + 2.15f;
break; break;
} }
case PHY_DEF_ANTENNA_GAIN: case PHY_DEF_ANTENNA_GAIN:
@@ -437,7 +406,7 @@ PhyParam_t RegionUS915GetPhyParam( GetPhyParams_t* getPhy )
} }
case PHY_BEACON_CHANNEL_FREQ: case PHY_BEACON_CHANNEL_FREQ:
{ {
phyParam.Value = US915_BEACON_CHANNEL_FREQ; phyParam.Value = US915_BEACON_CHANNEL_FREQ + ( getPhy->Channel * US915_BEACON_CHANNEL_STEPWIDTH );
break; break;
} }
case PHY_BEACON_FORMAT: case PHY_BEACON_FORMAT:
@@ -462,11 +431,26 @@ PhyParam_t RegionUS915GetPhyParam( GetPhyParams_t* getPhy )
phyParam.Value = US915_BEACON_NB_CHANNELS; phyParam.Value = US915_BEACON_NB_CHANNELS;
break; 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: case PHY_PING_SLOT_CHANNEL_DR:
{ {
phyParam.Value = US915_PING_SLOT_CHANNEL_DR; phyParam.Value = US915_PING_SLOT_CHANNEL_DR;
break; break;
} }
case PHY_SF_FROM_DR:
{
phyParam.Value = DataratesUS915[getPhy->Datarate];
break;
}
case PHY_BW_FROM_DR:
{
phyParam.Value = GetBandwidth( getPhy->Datarate );
break;
}
default: default:
{ {
break; break;
@@ -478,7 +462,8 @@ PhyParam_t RegionUS915GetPhyParam( GetPhyParams_t* getPhy )
void RegionUS915SetBandTxDone( SetBandTxDoneParams_t* txDone ) 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 ) void RegionUS915InitDefaults( InitDefaultsParams_t* params )
@@ -490,7 +475,7 @@ void RegionUS915InitDefaults( InitDefaultsParams_t* params )
switch( params->Type ) switch( params->Type )
{ {
case INIT_TYPE_INIT: case INIT_TYPE_BANDS:
{ {
// Initialize bands // Initialize bands
memcpy1( ( uint8_t* )NvmCtx.Bands, ( uint8_t* )bands, sizeof( Band_t ) * US915_MAX_NB_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 // Initialize the join trials counter
NvmCtx.JoinTrialsCounter = 0; 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 // Channels
// 125 kHz channels // 125 kHz channels
for( uint8_t i = 0; i < US915_MAX_NB_CHANNELS - 8; i++ ) 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].DrRange.Value = ( DR_4 << 4 ) | DR_4;
NvmCtx.Channels[i].Band = 0; 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; break;
} }
case INIT_TYPE_RESTORE_CTX: case INIT_TYPE_RESTORE_CTX:
@@ -568,6 +556,10 @@ bool RegionUS915Verify( VerifyParams_t* verify, PhyAttribute_t phyAttribute )
{ {
switch( phyAttribute ) switch( phyAttribute )
{ {
case PHY_FREQUENCY:
{
return VerifyRfFreq( verify->Frequency );
}
case PHY_TX_DR: case PHY_TX_DR:
{ {
return RegionCommonValueInRange( verify->DatarateParams.Datarate, US915_TX_MIN_DATARATE, US915_TX_MAX_DATARATE ); 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 ) bool RegionUS915RxConfig( RxConfigParams_t* rxConfig, int8_t* datarate )
{ {
int8_t dr = rxConfig->Datarate; int8_t dr = rxConfig->Datarate;
uint8_t maxPayload = 0;
int8_t phyDr = 0; int8_t phyDr = 0;
uint32_t frequency = rxConfig->Frequency; uint32_t frequency = rxConfig->Frequency;
@@ -699,15 +690,7 @@ bool RegionUS915RxConfig( RxConfigParams_t* rxConfig, int8_t* datarate )
// Radio configuration // Radio configuration
Radio.SetRxConfig( MODEM_LORA, rxConfig->Bandwidth, phyDr, 1, 0, 8, rxConfig->WindowTimeout, false, 0, false, 0, 0, true, rxConfig->RxContinuous ); Radio.SetRxConfig( MODEM_LORA, rxConfig->Bandwidth, phyDr, 1, 0, 8, rxConfig->WindowTimeout, false, 0, false, 0, 0, true, rxConfig->RxContinuous );
if( rxConfig->RepeaterSupport == true ) Radio.SetMaxPayloadLength( MODEM_LORA, MaxPayloadOfDatarateUS915[dr] + LORAMAC_FRAME_PAYLOAD_OVERHEAD_SIZE );
{
maxPayload = MaxPayloadOfDatarateRepeaterUS915[dr];
}
else
{
maxPayload = MaxPayloadOfDatarateUS915[dr];
}
Radio.SetMaxPayloadLength( MODEM_LORA, maxPayload + LORA_MAC_FRMPAYLOAD_OVERHEAD );
*datarate = (uint8_t) dr; *datarate = (uint8_t) dr;
return true; return true;
@@ -726,14 +709,15 @@ bool RegionUS915TxConfig( TxConfigParams_t* txConfig, int8_t* txPower, TimerTime
// Setup the radio frequency // Setup the radio frequency
Radio.SetChannel( NvmCtx.Channels[txConfig->Channel].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 // Setup maximum payload lenght of the radio driver
Radio.SetMaxPayloadLength( MODEM_LORA, txConfig->PktLen ); 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; return true;
} }
@@ -969,29 +953,15 @@ int8_t RegionUS915AlternateDr( int8_t currentDr, AlternateDrType_t type )
return currentDr; 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 ) LoRaMacStatus_t RegionUS915NextChannel( NextChanParams_t* nextChanParams, uint8_t* channel, TimerTime_t* time, TimerTime_t* aggregatedTimeOff )
{ {
uint8_t nbEnabledChannels = 0; uint8_t nbEnabledChannels = 0;
uint8_t delayTx = 0; uint8_t nbRestrictedChannels = 0;
uint8_t enabledChannels[US915_MAX_NB_CHANNELS] = { 0 }; uint8_t enabledChannels[US915_MAX_NB_CHANNELS] = { 0 };
TimerTime_t nextTxDelay = 0; uint8_t newChannelIndex = 0;
uint8_t newChannelIndex; RegionCommonIdentifyChannelsParam_t identifyChannelsParam;
RegionCommonCountNbOfEnabledChannelsParams_t countChannelsParams;
LoRaMacStatus_t status = LORAMAC_STATUS_NO_CHANNEL_FOUND;
// Count 125kHz channels // Count 125kHz channels
if( RegionCommonCountChannels( NvmCtx.ChannelsMaskRemaining, 0, 4 ) == 0 ) 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;
// Update bands Time OFF
nextTxDelay = RegionCommonUpdateBandTimeOff( nextChanParams->Joined, nextChanParams->DutyCycleEnabled, NvmCtx.Bands, US915_MAX_NB_BANDS );
// Search how many channels are enabled // Search how many channels are enabled
nbEnabledChannels = CountNbOfEnabledChannels( nextChanParams->Datarate, countChannelsParams.Joined = nextChanParams->Joined;
NvmCtx.ChannelsMaskRemaining, NvmCtx.Channels, countChannelsParams.Datarate = nextChanParams->Datarate;
NvmCtx.Bands, enabledChannels, &delayTx ); countChannelsParams.ChannelsMask = NvmCtx.ChannelsMaskRemaining;
} countChannelsParams.Channels = NvmCtx.Channels;
else countChannelsParams.Bands = NvmCtx.Bands;
{ countChannelsParams.MaxNbChannels = US915_MAX_NB_CHANNELS;
delayTx++; countChannelsParams.JoinChannels = 0;
nextTxDelay = nextChanParams->AggrTimeOff - TimerGetElapsedTime( nextChanParams->LastAggrTx );
}
if( nbEnabledChannels > 0 ) identifyChannelsParam.AggrTimeOff = nextChanParams->AggrTimeOff;
identifyChannelsParam.LastAggrTx = nextChanParams->LastAggrTx;
identifyChannelsParam.DutyCycleEnabled = nextChanParams->DutyCycleEnabled;
identifyChannelsParam.MaxBands = US915_MAX_NB_BANDS;
identifyChannelsParam.CountNbOfEnabledChannelsParam = &countChannelsParams;
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 ) if( nextChanParams->Joined == true )
{ {
@@ -1066,22 +1040,8 @@ LoRaMacStatus_t RegionUS915NextChannel( NextChanParams_t* nextChanParams, uint8_
// Disable the channel in the mask // Disable the channel in the mask
RegionCommonChanDisable( NvmCtx.ChannelsMaskRemaining, *channel, US915_MAX_NB_CHANNELS ); 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 ) LoRaMacStatus_t RegionUS915ChannelAdd( ChannelAddParams_t* channelAdd )

View File

@@ -37,6 +37,11 @@
#ifndef __REGION_US915_H__ #ifndef __REGION_US915_H__
#define __REGION_US915_H__ #define __REGION_US915_H__
#ifdef __cplusplus
extern "C"
{
#endif
#include "region/Region.h" #include "region/Region.h"
/*! /*!
@@ -87,7 +92,7 @@
/*! /*!
* Minimal Tx output power that can be used by the node * 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 * Maximal Tx output power that can be used by the node
@@ -182,6 +187,11 @@
*/ */
#define US915_BEACON_CHANNEL_STEPWIDTH 600000 #define US915_BEACON_CHANNEL_STEPWIDTH 600000
/*!
* Ping slot channel frequency
*/
#define US915_PING_SLOT_CHANNEL_FREQ 923300000
/*! /*!
* Number of possible beacon channels * Number of possible beacon channels
*/ */
@@ -224,9 +234,9 @@
/*! /*!
* Band 0 definition * 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 * 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 }; 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. * \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 ); 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 * \brief Searches and set the next random available channel
* *
@@ -500,4 +498,8 @@ uint8_t RegionUS915ApplyDrOffset( uint8_t downlinkDwellTime, int8_t dr, int8_t d
/*! \} defgroup REGIONUS915 */ /*! \} defgroup REGIONUS915 */
#ifdef __cplusplus
}
#endif
#endif // __REGION_US915_H__ #endif // __REGION_US915_H__

View File

@@ -30,13 +30,37 @@
* *
* \author Johannes Bruder ( STACKFORCE ) * \author Johannes Bruder ( STACKFORCE )
* *
* \defgroup SECUREELEMENT Secure Element API Definition
*
* \{
*
*/ */
#ifndef __SECURE_ELEMENT_H__ #ifndef __SECURE_ELEMENT_H__
#define __SECURE_ELEMENT_H__ #define __SECURE_ELEMENT_H__
#ifdef __cplusplus
extern "C"
{
#endif
#include <stdint.h> #include <stdint.h>
#include "LoRaMacCrypto.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. * Return values.
*/ */
@@ -70,6 +94,10 @@ typedef enum eSecureElementStatus
* Undefined Error occurred * Undefined Error occurred
*/ */
SECURE_ELEMENT_ERROR, SECURE_ELEMENT_ERROR,
/*!
* Failed to encrypt
*/
SECURE_ELEMENT_FAIL_ENCRYPT,
}SecureElementStatus_t; }SecureElementStatus_t;
/*! /*!
@@ -77,7 +105,7 @@ typedef enum eSecureElementStatus
* non volatile context have to be stored. * non volatile context have to be stored.
* *
*/ */
typedef void ( *EventNvmCtxChanged )( void ); typedef void ( *SecureElementNvmEvent )( void );
/*! /*!
* Initialization of Secure Element driver * Initialization of Secure Element driver
@@ -86,7 +114,7 @@ typedef void ( *EventNvmCtxChanged )( void );
* non-volatile context have to be stored. * non-volatile context have to be stored.
* \retval - Status of the operation * \retval - Status of the operation
*/ */
SecureElementStatus_t SecureElementInit( EventNvmCtxChanged seNvmCtxChanged ); SecureElementStatus_t SecureElementInit( SecureElementNvmEvent seNvmCtxChanged );
/*! /*!
* Restores the internal nvm context from passed pointer. * 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 ); 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] buffer - Data buffer
* \param[IN] size - Data buffer size * \param[IN] size - Data buffer size
* \param[IN] keyID - Key identifier to determine the AES key to be used * \param[IN] keyID - Key identifier to determine the AES key to be used
* \param[OUT] cmac - Computed cmac * \param[OUT] cmac - Computed cmac
* \retval - Status of the operation * \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) * 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 ); 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 * Generates a random number
* *
@@ -165,4 +210,55 @@ SecureElementStatus_t SecureElementDeriveAndStoreKey( Version_t version, uint8_t
*/ */
SecureElementStatus_t SecureElementRandomNumber( uint32_t* randomNum ); 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__ #endif // __SECURE_ELEMENT_H__

View File

@@ -22,17 +22,62 @@ cmake_minimum_required(VERSION 3.6)
# Target # Target
#--------------------------------------------------------------------------------------- #---------------------------------------------------------------------------------------
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" file(GLOB ${PROJECT_NAME}_SOURCES "*.c"
"soft-se/*.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}) 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 target_include_directories( ${PROJECT_NAME} PUBLIC
${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_SOURCE_DIR}
${CMAKE_CURRENT_SOURCE_DIR}/soft-se
$<TARGET_PROPERTY:board,INTERFACE_INCLUDE_DIRECTORIES> $<TARGET_PROPERTY:board,INTERFACE_INCLUDE_DIRECTORIES>
$<TARGET_PROPERTY:system,INTERFACE_INCLUDE_DIRECTORIES> $<TARGET_PROPERTY:system,INTERFACE_INCLUDE_DIRECTORIES>
$<TARGET_PROPERTY:mac,INTERFACE_INCLUDE_DIRECTORIES> $<TARGET_PROPERTY:mac,INTERFACE_INCLUDE_DIRECTORIES>
$<TARGET_PROPERTY:radio,INTERFACE_INCLUDE_DIRECTORIES>
) )
set_property(TARGET ${PROJECT_NAME} PROPERTY C_STANDARD 11) set_property(TARGET ${PROJECT_NAME} PROPERTY C_STANDARD 11)

View File

@@ -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

View File

@@ -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;
}

View File

@@ -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__

View File

@@ -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;
}

View File

@@ -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__

View File

@@ -23,6 +23,11 @@
#ifndef __GPIO_IOE_H__ #ifndef __GPIO_IOE_H__
#define __GPIO_IOE_H__ #define __GPIO_IOE_H__
#ifdef __cplusplus
extern "C"
{
#endif
#include <stdint.h> #include <stdint.h>
#include "gpio.h" #include "gpio.h"
@@ -95,4 +100,8 @@ uint32_t GpioIoeRead( Gpio_t *obj );
*/ */
void GpioIoeInterruptHandler( void ); void GpioIoeInterruptHandler( void );
#ifdef __cplusplus
}
#endif
#endif // __GPIO_IOE_H__ #endif // __GPIO_IOE_H__

View File

@@ -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( );
}

View File

@@ -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__

View File

@@ -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;
}

View File

@@ -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__

View File

@@ -43,21 +43,21 @@ uint8_t MAG3110Init( void )
MAG3110Read( MAG3110_ID, &regVal ); MAG3110Read( MAG3110_ID, &regVal );
if( regVal != 0xC4 ) // Fixed Device ID Number = 0xC4 if( regVal != 0xC4 ) // Fixed Device ID Number = 0xC4
{ {
return LORA_FAIL; return FAIL;
} }
MAG3110Reset( ); MAG3110Reset( );
} }
return LORA_SUCCESS; return SUCCESS;
} }
uint8_t MAG3110Reset( void ) 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 ) uint8_t MAG3110Write( uint8_t addr, uint8_t data )

View File

@@ -23,6 +23,11 @@
#ifndef __MAG3110_H__ #ifndef __MAG3110_H__
#define __MAG3110_H__ #define __MAG3110_H__
#ifdef __cplusplus
extern "C"
{
#endif
#include <stdint.h> #include <stdint.h>
/*! /*!
@@ -38,14 +43,14 @@
/*! /*!
* \brief Initializes the device * \brief Initializes the device
* *
* \retval status [LORA_SUCCESS, LORA_FAIL] * \retval status [SUCCESS, FAIL]
*/ */
uint8_t MAG3110Init( void ); uint8_t MAG3110Init( void );
/*! /*!
* \brief Resets the device * \brief Resets the device
* *
* \retval status [LORA_SUCCESS, LORA_FAIL] * \retval status [SUCCESS, FAIL]
*/ */
uint8_t MAG3110Reset( void ); uint8_t MAG3110Reset( void );
@@ -54,7 +59,7 @@ uint8_t MAG3110Reset( void );
* *
* \param [IN]: addr * \param [IN]: addr
* \param [IN]: data * \param [IN]: data
* \retval status [LORA_SUCCESS, LORA_FAIL] * \retval status [SUCCESS, FAIL]
*/ */
uint8_t MAG3110Write( uint8_t addr, uint8_t data ); 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]: addr
* \param [IN]: data * \param [IN]: data
* \param [IN]: size * \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 ); 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 [IN]: addr
* \param [OUT]: data * \param [OUT]: data
* \retval status [LORA_SUCCESS, LORA_FAIL] * \retval status [SUCCESS, FAIL]
*/ */
uint8_t MAG3110Read( uint8_t addr, uint8_t *data ); 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 [IN]: addr
* \param [OUT]: data * \param [OUT]: data
* \param [IN]: size * \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 ); 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 ); uint8_t MAG3110GetDeviceAddr( void );
#ifdef __cplusplus
}
#endif
#endif // __MAG3110_H__ #endif // __MAG3110_H__

View File

@@ -36,7 +36,7 @@ static bool MMA8451Initialized = false;
* *
* \param [IN]: addr * \param [IN]: addr
* \param [IN]: data * \param [IN]: data
* \retval status [LORA_SUCCESS, LORA_FAIL] * \retval status [SUCCESS, FAIL]
*/ */
uint8_t MMA8451Write( uint8_t addr, uint8_t data ); 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]: addr
* \param [IN]: data * \param [IN]: data
* \param [IN]: size * \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 ); 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 [IN]: addr
* \param [OUT]: data * \param [OUT]: data
* \retval status [LORA_SUCCESS, LORA_FAIL] * \retval status [SUCCESS, FAIL]
*/ */
uint8_t MMA8451Read( uint8_t addr, uint8_t *data ); 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 [IN]: addr
* \param [OUT]: data * \param [OUT]: data
* \param [IN]: size * \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 ); uint8_t MMA8451ReadBuffer( uint8_t addr, uint8_t *data, uint8_t size );
@@ -96,7 +96,7 @@ uint8_t MMA8451Init( void )
MMA8451Read( MMA8451_ID, &regVal ); MMA8451Read( MMA8451_ID, &regVal );
if( regVal != 0x1A ) // Fixed Device ID Number = 0x1A if( regVal != 0x1A ) // Fixed Device ID Number = 0x1A
{ {
return LORA_FAIL; return FAIL;
} }
MMA8451Reset( ); MMA8451Reset( );
@@ -105,17 +105,17 @@ uint8_t MMA8451Init( void )
MMA8451Write( MMA8451_CTRL_REG3, 0x01 ); MMA8451Write( MMA8451_CTRL_REG3, 0x01 );
MMA8451OrientDetect( ); MMA8451OrientDetect( );
} }
return LORA_SUCCESS; return SUCCESS;
} }
uint8_t MMA8451Reset( ) 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 ) uint8_t MMA8451Write( uint8_t addr, uint8_t data )

View File

@@ -23,6 +23,11 @@
#ifndef __MMA8451_H__ #ifndef __MMA8451_H__
#define __MMA8451_H__ #define __MMA8451_H__
#ifdef __cplusplus
extern "C"
{
#endif
#include <stdint.h> #include <stdint.h>
/* /*
@@ -58,14 +63,14 @@
/*! /*!
* \brief Initializes the device * \brief Initializes the device
* *
* \retval status [LORA_SUCCESS, LORA_FAIL] * \retval status [SUCCESS, FAIL]
*/ */
uint8_t MMA8451Init( void ); uint8_t MMA8451Init( void );
/*! /*!
* \brief Resets the device * \brief Resets the device
* *
* \retval status [LORA_SUCCESS, LORA_FAIL] * \retval status [SUCCESS, FAIL]
*/ */
uint8_t MMA8451Reset( void ); uint8_t MMA8451Reset( void );
@@ -83,4 +88,8 @@ void MMA8451OrientDetect( void );
*/ */
uint8_t MMA8451GetOrientation( void ); uint8_t MMA8451GetOrientation( void );
#ifdef __cplusplus
}
#endif
#endif // __MMA8451_H__ #endif // __MMA8451_H__

View File

@@ -52,7 +52,7 @@ typedef enum
* *
* \param [IN]: addr * \param [IN]: addr
* \param [IN]: data * \param [IN]: data
* \retval status [LORA_SUCCESS, LORA_FAIL] * \retval status [SUCCESS, FAIL]
*/ */
uint8_t MPL3115Write( uint8_t addr, uint8_t data ); 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]: addr
* \param [IN]: data * \param [IN]: data
* \param [IN]: size * \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 ); 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 [IN]: addr
* \param [OUT]: data * \param [OUT]: data
* \retval status [LORA_SUCCESS, LORA_FAIL] * \retval status [SUCCESS, FAIL]
*/ */
uint8_t MPL3115Read( uint8_t addr, uint8_t *data ); 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 [IN]: addr
* \param [OUT]: data * \param [OUT]: data
* \param [IN]: size * \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 ); uint8_t MPL3115ReadBuffer( uint8_t addr, uint8_t *data, uint8_t size );
@@ -141,24 +141,24 @@ uint8_t MPL3115Init( void )
MPL3115Read( MPL3115_ID, &regVal ); MPL3115Read( MPL3115_ID, &regVal );
if( regVal != 0xC4 ) 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( 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) MPL3115Write( CTRL_REG1, ALT | OS_32 | SBYB ); // Set sensor to active state with oversampling ratio 128 (512 ms between samples)
MPL3115Initialized = true; MPL3115Initialized = true;
} }
return LORA_SUCCESS; return SUCCESS;
} }
uint8_t MPL3115Reset( void ) uint8_t MPL3115Reset( void )
{ {
// Reset all registers to POR values // 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 ) uint8_t MPL3115Write( uint8_t addr, uint8_t data )

View File

@@ -23,6 +23,11 @@
#ifndef __MPL3115_H__ #ifndef __MPL3115_H__
#define __MPL3115_H__ #define __MPL3115_H__
#ifdef __cplusplus
extern "C"
{
#endif
#include <stdint.h> #include <stdint.h>
/* /*
@@ -123,14 +128,14 @@
/*! /*!
* \brief Initializes the device * \brief Initializes the device
* *
* \retval status [LORA_SUCCESS, LORA_FAIL] * \retval status [SUCCESS, FAIL]
*/ */
uint8_t MPL3115Init( void ); uint8_t MPL3115Init( void );
/*! /*!
* \brief Resets the device * \brief Resets the device
* *
* \retval status [LORA_SUCCESS, LORA_FAIL] * \retval status [SUCCESS, FAIL]
*/ */
uint8_t MPL3115Reset( void ); uint8_t MPL3115Reset( void );
@@ -155,4 +160,8 @@ float MPL3115ReadPressure( void );
*/ */
float MPL3115ReadTemperature( void ); float MPL3115ReadTemperature( void );
#ifdef __cplusplus
}
#endif
#endif // __MPL3115_H__ #endif // __MPL3115_H__

View File

@@ -43,7 +43,7 @@ bool PAM7QGetGpsData( uint8_t *nmeaString, uint8_t *nmeaStringSize, uint16_t nme
status = PAM7QReadBuffer( MESSAGE_SIZE_1, nmeaString, 2 ); status = PAM7QReadBuffer( MESSAGE_SIZE_1, nmeaString, 2 );
if( status == LORA_SUCCESS ) if( status == SUCCESS )
{ {
// build a 16bit number // build a 16bit number
pendingBytes = ( uint16_t )( ( nmeaString[0] << 8 ) | nmeaString[1] ); 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 ); status = PAM7QReadBuffer( PAYLOAD, nmeaString, pendingBytes );
// make sure the string is terminated // make sure the string is terminated
if( status == LORA_SUCCESS ) if( status == SUCCESS )
{ {
nmeaString[pendingBytes] = 0x00; nmeaString[pendingBytes] = 0x00;

View File

@@ -23,6 +23,11 @@
#ifndef __PAM7Q_H__ #ifndef __PAM7Q_H__
#define __PAM7Q_H__ #define __PAM7Q_H__
#ifdef __cplusplus
extern "C"
{
#endif
#include <stdbool.h> #include <stdbool.h>
#include <stdint.h> #include <stdint.h>
@@ -55,5 +60,9 @@ void GpsMcuOnPpsSignal( void );
#define PAYLOAD 0xFF #define PAYLOAD 0xFF
#ifdef __cplusplus
}
#endif
#endif // __PAM7Q_H__ #endif // __PAM7Q_H__

View File

@@ -31,6 +31,10 @@
#ifndef AES_H #ifndef AES_H
#define AES_H #define AES_H
#ifdef __cplusplus
extern "C" {
#endif
#include <stdint.h> #include <stdint.h>
#if 1 #if 1
@@ -159,4 +163,8 @@ void aes_decrypt_256( const uint8_t in[N_BLOCK],
uint8_t o_key[2 * N_BLOCK] ); uint8_t o_key[2 * N_BLOCK] );
#endif #endif
#ifdef __cplusplus
}
#endif
#endif #endif

View File

@@ -32,28 +32,29 @@ FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS WITH THE SOFTWARE DEALINGS WITH THE SOFTWARE
*****************************************************************************/ *****************************************************************************/
//#include <sys/param.h>
//#include <sys/systm.h>
#include <stdint.h> #include <stdint.h>
#include "aes.h" #include "aes.h"
#include "cmac.h" #include "cmac.h"
#include "utilities.h" #include "utilities.h"
#define LSHIFT(v, r) do { \ #define LSHIFT( v, r ) \
do \
{ \
int32_t i; \ int32_t i; \
for( i = 0; i < 15; i++ ) \ for( i = 0; i < 15; i++ ) \
( r )[i] = ( v )[i] << 1 | ( v )[i + 1] >> 7; \ ( r )[i] = ( v )[i] << 1 | ( v )[i + 1] >> 7; \
( r )[15] = ( v )[15] << 1; \ ( r )[15] = ( v )[15] << 1; \
} while( 0 ) } while( 0 )
#define XOR(v, r) do { \ #define XOR( v, r ) \
do \
{ \
int32_t i; \ int32_t i; \
for( i = 0; i < 16; i++ ) \ for( i = 0; i < 16; i++ ) \
{ \ { \
( r )[i] = ( r )[i] ^ ( v )[i]; \ ( r )[i] = ( r )[i] ^ ( v )[i]; \
} \ } \
} while (0) \ } while( 0 )
void AES_CMAC_Init( AES_CMAC_CTX* ctx ) void AES_CMAC_Init( AES_CMAC_CTX* ctx )
{ {
@@ -64,7 +65,6 @@ void AES_CMAC_Init(AES_CMAC_CTX *ctx)
void AES_CMAC_SetKey( AES_CMAC_CTX* ctx, const uint8_t key[AES_CMAC_KEY_LENGTH] ) 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 ); aes_set_key( key, AES_CMAC_KEY_LENGTH, &ctx->rijndael );
} }
@@ -73,24 +73,28 @@ void AES_CMAC_Update(AES_CMAC_CTX *ctx, const uint8_t *data, uint32_t len)
uint32_t mlen; uint32_t mlen;
uint8_t in[16]; uint8_t in[16];
if (ctx->M_n > 0) { if( ctx->M_n > 0 )
{
mlen = MIN( 16 - ctx->M_n, len ); mlen = MIN( 16 - ctx->M_n, len );
memcpy1( ctx->M_last + ctx->M_n, data, mlen ); memcpy1( ctx->M_last + ctx->M_n, data, mlen );
ctx->M_n += mlen; ctx->M_n += mlen;
if( ctx->M_n < 16 || len == mlen ) if( ctx->M_n < 16 || len == mlen )
return; return;
XOR( ctx->M_last, ctx->X ); XOR( ctx->M_last, ctx->X );
//rijndael_encrypt(&ctx->rijndael, ctx->X, ctx->X);
aes_encrypt( ctx->X, ctx->X, &ctx->rijndael); 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; data += mlen;
len -= mlen; len -= mlen;
} }
while (len > 16) { /* not last block */ while( len > 16 )
{ /* not last block */
XOR( data, ctx->X ); XOR( data, ctx->X );
//rijndael_encrypt(&ctx->rijndael, ctx->X, ctx->X);
memcpy1(in, &ctx->X[0], 16); //Bestela ez du ondo iten memcpy1( in, &ctx->X[0], 16 ); // Otherwise it does not look good
aes_encrypt( in, in, &ctx->rijndael ); aes_encrypt( in, in, &ctx->rijndael );
memcpy1( &ctx->X[0], in, 16 ); memcpy1( &ctx->X[0], in, 16 );
@@ -109,27 +113,30 @@ void AES_CMAC_Final(uint8_t digest[AES_CMAC_DIGEST_LENGTH], AES_CMAC_CTX *ctx)
/* generate subkey K1 */ /* generate subkey K1 */
memset1( K, '\0', 16 ); memset1( K, '\0', 16 );
//rijndael_encrypt(&ctx->rijndael, K, K);
aes_encrypt( K, K, &ctx->rijndael ); aes_encrypt( K, K, &ctx->rijndael );
if (K[0] & 0x80) { if( K[0] & 0x80 )
{
LSHIFT( K, K ); LSHIFT( K, K );
K[15] ^= 0x87; K[15] ^= 0x87;
} else }
else
LSHIFT( K, K ); LSHIFT( K, K );
if( ctx->M_n == 16 )
if (ctx->M_n == 16) { {
/* last block was a complete block */ /* last block was a complete block */
XOR( K, ctx->M_last ); XOR( K, ctx->M_last );
}
} else { else
{
/* generate subkey K2 */ /* generate subkey K2 */
if (K[0] & 0x80) { if( K[0] & 0x80 )
{
LSHIFT( K, K ); LSHIFT( K, K );
K[15] ^= 0x87; K[15] ^= 0x87;
} else }
else
LSHIFT( K, K ); LSHIFT( K, K );
/* padding(M_last) */ /* padding(M_last) */
@@ -138,16 +145,10 @@ void AES_CMAC_Final(uint8_t digest[AES_CMAC_DIGEST_LENGTH], AES_CMAC_CTX *ctx)
ctx->M_last[ctx->M_n] = 0; ctx->M_last[ctx->M_n] = 0;
XOR( K, ctx->M_last ); XOR( K, ctx->M_last );
} }
XOR( ctx->M_last, ctx->X ); XOR( ctx->M_last, ctx->X );
//rijndael_encrypt(&ctx->rijndael, ctx->X, digest); memcpy1( in, &ctx->X[0], 16 ); // Otherwise it does not look good
memcpy1(in, &ctx->X[0], 16); //Bestela ez du ondo iten
aes_encrypt( in, digest, &ctx->rijndael ); aes_encrypt( in, digest, &ctx->rijndael );
memset1( K, 0, sizeof K ); memset1( K, 0, sizeof K );
} }

View File

@@ -36,6 +36,10 @@ DEALINGS WITH THE SOFTWARE
#ifndef _CMAC_H_ #ifndef _CMAC_H_
#define _CMAC_H_ #define _CMAC_H_
#ifdef __cplusplus
extern "C"
#endif
#include "aes.h" #include "aes.h"
#define AES_CMAC_KEY_LENGTH 16 #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))); // __attribute__((__bounded__(__minbytes__,1,AES_CMAC_DIGEST_LENGTH)));
//__END_DECLS //__END_DECLS
#ifdef __cplusplus
}
#endif
#endif /* _CMAC_H_ */ #endif /* _CMAC_H_ */

View File

@@ -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__

View File

@@ -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