add lorawan project

This commit is contained in:
mculover666
2020-06-08 21:40:22 +08:00
parent 7761a3acdb
commit fe6803fa40
133 changed files with 57442 additions and 298 deletions

View File

@@ -0,0 +1,59 @@
/**
******************************************************************************
* @file adc.h
* @author MCD Application Team
* @brief configuration of the ADC instances
******************************************************************************
* @attention
*
* <h2><center>&copy; Copyright (c) 2019 STMicroelectronics.
* All rights reserved.</center></h2>
*
* This software component is licensed by ST under Ultimate Liberty license
* SLA0044, the "License"; You may not use this file except in compliance with
* the License. You may obtain a copy of the License at:
* www.st.com/SLA0044
*
******************************************************************************
*/
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef __ADC_H__
#define __ADC_H__
#ifdef __cplusplus
extern "C" {
#endif
/* Includes ------------------------------------------------------------------*/
#include "main.h"
/* Exported types ------------------------------------------------------------*/
/* Exported constants --------------------------------------------------------*/
/* External variables --------------------------------------------------------*/
/* USER CODE BEGIN Includes */
/* USER CODE END Includes */
#ifdef HAL_ADC_MODULE_ENABLED
extern ADC_HandleTypeDef hadc1;
#endif
/* USER CODE BEGIN Private defines */
/* USER CODE END Private defines */
/* Exported macros -----------------------------------------------------------*/
/* Defines -------------------------------------------------------------------*/
/* Exported functions ------------------------------------------------------- */
void MX_ADC1_Init(void);
/* USER CODE BEGIN Prototypes */
/* USER CODE END Prototypes */
#ifdef __cplusplus
}
#endif
#endif /* __ADC_H__ */
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/

View File

@@ -0,0 +1,81 @@
/**
******************************************************************************
* @file adc_if.h
* @author MCD Application Team
* @brief API and configuration of the adc_if.c instances
******************************************************************************
* @attention
*
* <h2><center>&copy; Copyright (c) 2019 STMicroelectronics.
* All rights reserved.</center></h2>
*
* This software component is licensed by ST under Ultimate Liberty license
* SLA0044, the "License"; You may not use this file except in compliance with
* the License. You may obtain a copy of the License at:
* www.st.com/SLA0044
*
******************************************************************************
*/
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef __ADC_IF_H__
#define __ADC_IF_H__
#ifdef __cplusplus
extern "C" {
#endif
/* Includes ------------------------------------------------------------------*/
#include "main.h"
#include "platform.h"
/* Includes ------------------------------------------------------------------*/
/* Exported types ------------------------------------------------------------*/
/* Exported constants --------------------------------------------------------*/
#define VDDA_VREFINT_CAL ((uint32_t) 3000)
#define BAT_CR2032 ((uint32_t) 3000)
#define VDD_BAT BAT_CR2032
#define VDD_MIN 1800
/* External variables --------------------------------------------------------*/
/* Exported macros -----------------------------------------------------------*/
/* Exported functions ------------------------------------------------------- */
/*!
* @brief Initializes the ADC input
* @param none
* @retval none
*/
void SYS_InitMeasurement(void);
/*!
* @brief DeInitializes the ADC
* @param none
* @retval none
*/
void SYS_DeInitMeasurement(void);
/*!
* @brief Get the current temperature
* @param none
* @retval value temperature in degreeCelcius( q7.8 )
*/
int16_t SYS_GetTemperatureLevel(void);
/*!
* @brief Get the current battery level
* @param none
* @retval value battery level in linear scale
*/
uint16_t SYS_GetBatteryLevel(void);
#ifdef __cplusplus
}
#endif
#endif /* __ADC_IF_H__ */
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/

View File

@@ -0,0 +1,63 @@
/**
******************************************************************************
* @file dma.h
* @author MCD Application Team
* @brief Header for driver dma.c module
******************************************************************************
* @attention
*
* <h2><center>&copy; Copyright (c) 2019 STMicroelectronics.
* All rights reserved.</center></h2>
*
* This software component is licensed by ST under Ultimate Liberty license
* SLA0044, the "License"; You may not use this file except in compliance with
* the License. You may obtain a copy of the License at:
* www.st.com/SLA0044
*
******************************************************************************
*/
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef __DMA_H__
#define __DMA_H__
#ifdef __cplusplus
extern "C" {
#endif
/* Includes ------------------------------------------------------------------*/
#include "main.h"
/* DMA memory to memory transfer handles -------------------------------------*/
/* USER CODE BEGIN Includes */
/* USER CODE END Includes */
/* USER CODE BEGIN Private defines */
/* USER CODE END Private defines */
/**
* @brief Enables DMA controller clock
* @param None
* @retval None
*
*/
void MX_DMA_Init(void);
/* USER CODE BEGIN Prototypes */
/* USER CODE END Prototypes */
#ifdef __cplusplus
}
#endif
#endif /* __DMA_H__ */
/**
* @}
*/
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/

View File

@@ -50,6 +50,10 @@ extern "C" {
/* USER CODE END EM */
#define RTC_N_PREDIV_S 10 /* subsecond number of bits */
#define RTC_PREDIV_S ((1<<RTC_N_PREDIV_S)-1) /* RTC_SYNCH_PREDIV; */
#define RTC_PREDIV_A (1<<(15-RTC_N_PREDIV_S))-1 /* RTC_ASYNCH_PREDIV; */
/* Exported functions prototypes ---------------------------------------------*/
void Error_Handler(void);

View File

@@ -9,6 +9,8 @@
#include "gpio.h"
#include "tos_k.h"
#include "stdio.h"
#include "app_system.h"
#include "app_lorawan.h"
void board_init(void);
void SystemClock_Config(void);

View File

@@ -0,0 +1,56 @@
/**
******************************************************************************
* @file platform.h
* @author MCD Application Team
* @brief configuration of general hw instances
******************************************************************************
* @attention
*
* <h2><center>&copy; Copyright (c) 2019 STMicroelectronics.
* All rights reserved.</center></h2>
*
* This software component is licensed by ST under Ultimate Liberty license
* SLA0044, the "License"; You may not use this file except in compliance with
* the License. You may obtain a copy of the License at:
* www.st.com/SLA0044
*
******************************************************************************
*/
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef __PLATFORM_H__
#define __PLATFORM_H__
#ifdef __cplusplus
extern "C" {
#endif
/* Includes ------------------------------------------------------------------*/
#include <stdbool.h>
#include "stm32wlxx.h"
#include "stm32wlxx_ll_gpio.h"
#include "main.h"
#include "usart.h"
#include "rtc.h"
/* Exported types ------------------------------------------------------------*/
/* Exported constants --------------------------------------------------------*/
/* External variables --------------------------------------------------------*/
/* Exported macros -----------------------------------------------------------*/
/* Defines -------------------------------------------------------------------*/
/* #warning "DBG LCH: VREFINT to be defined from AN" */
/* Nothing for L4 but other platform might need it */
#define __HAL_RCC_DBGMCU_CLK_ENABLE()
#define __HAL_RCC_DBGMCU_CLK_DISABLE()
#ifdef __cplusplus
}
#endif
#endif /* __PLATFORM_H__ */
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/

View File

@@ -0,0 +1,63 @@
/**
******************************************************************************
* @file rtc.h
* @author MCD Application Team
* @brief configuration of the RTC instances
******************************************************************************
* @attention
*
* <h2><center>&copy; Copyright (c) 2019 STMicroelectronics.
* All rights reserved.</center></h2>
*
* This software component is licensed by ST under Ultimate Liberty license
* SLA0044, the "License"; You may not use this file except in compliance with
* the License. You may obtain a copy of the License at:
* www.st.com/SLA0044
*
******************************************************************************
*/
#ifndef __RTC_H__
#define __RTC_H__
#ifdef __cplusplus
extern "C" {
#endif
/* Includes ------------------------------------------------------------------*/
#include "main.h"
/* USER CODE BEGIN Includes */
/* USER CODE END Includes */
extern RTC_HandleTypeDef hrtc;
/* Defines ------------------------------------------------------------*/
/* USER CODE BEGIN Private defines */
/* USER CODE END Private defines */
/* Exported types ------------------------------------------------------------*/
/* Exported constants --------------------------------------------------------*/
/* External variables --------------------------------------------------------*/
/* Exported macros -----------------------------------------------------------*/
/* Exported functions ------------------------------------------------------- */
/**
* @brief Initializes the RTC
* @param None
* @retval None
*/
void MX_RTC_Init(void);
/* USER CODE BEGIN Prototypes */
/* USER CODE END Prototypes */
#ifdef __cplusplus
}
#endif
#endif /* __RTC_H__ */
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/

View File

@@ -0,0 +1,156 @@
/**
******************************************************************************
* @file rtc_if.h
* @author MCD Application Team
* @brief configuration of the rtc_if.c instances
******************************************************************************
* @attention
*
* <h2><center>&copy; Copyright (c) 2019 STMicroelectronics.
* All rights reserved.</center></h2>
*
* This software component is licensed by ST under Ultimate Liberty license
* SLA0044, the "License"; You may not use this file except in compliance with
* the License. You may obtain a copy of the License at:
* www.st.com/SLA0044
*
******************************************************************************
*/
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef __RTC_IF_H__
#define __RTC_IF_H__
#ifdef __cplusplus
extern "C" {
#endif
/* Includes ------------------------------------------------------------------*/
//#include "stm32_timer.h"
/* Exported types ------------------------------------------------------------*/
/* Exported constants --------------------------------------------------------*/
/* External variables --------------------------------------------------------*/
/* Exported macros -----------------------------------------------------------*/
/* Exported functions ------------------------------------------------------- */
/*!
* @brief Initializes the RTC timer
* @note The timer is based on the RTC
* @param none
* @retval none
*/
void RTC_Init( void );
/*!
* @brief Return the minimum timeout in ticks the RTC is able to handle
* @param none
* @retval minimum value for a timeout in ticks
*/
uint32_t RTC_GetMinimumTimeout( void );
/*!
* @brief Get the RTC timer elapsed time since the last Alarm was set
* @param none
* @retval RTC Elapsed time in ticks
*/
uint32_t RTC_GetTimerElapsedTime(void);
/*!
* @brief Get the RTC timer value
* @param none
* @retval RTC Timer value in ticks
*/
uint32_t RTC_GetTimerValue( void );
/*!
* @brief set Time Reference set also the RTC_DateStruct and RTC_TimeStruct
* @param none
* @retval Timer Reference Value in Ticks
*/
uint32_t RTC_SetTimerContext( void );
/*!
* @brief Get the RTC timer Reference
* @param none
* @retval Timer Value in Ticks
*/
uint32_t RTC_GetTimerContext( void );
/*!
* @brief RTC IRQ Handler on the RTC Alarm
* @param none
* @retval none
*/
void RTC_IrqHandler ( void );
/*!
* @brief a delay of delay ms by polling RTC
* @param delay in ms
* @retval none
*/
void RTC_DelayMs(uint32_t delay);
/*!
* @brief calculates the wake up time between wake up and mcu start
* @note resolution in RTC_ALARM_TIME_BASE in timer ticks
* @param none
* @retval none
*/
void RTC_setMcuWakeUpTime(void);
/*!
* @brief returns the wake up time in us
* @param none
* @retval wake up time in ticks
*/
int16_t RTC_getMcuWakeUpTime( void );
/*!
* @brief converts time in ms to time in ticks
* @param [IN] time in milliseconds
* @retval returns time in timer ticks
*/
uint32_t RTC_ms2Tick( uint32_t timeMicroSec );
/*!
* @brief converts time in ticks to time in ms
* @param [IN] time in timer ticks
* @retval returns time in timer milliseconds
*/
uint32_t RTC_Tick2ms( uint32_t tick );
/*!
* \brief Get system time
* \param [IN] subSeconds in ms
*
* \uint32_t seconds
*/
uint32_t HW_RTC_GetCalendarTime(uint16_t *subSeconds);
/*!
* \brief Read from backup registers
* \param [IN] Data 0
* \param [IN] Data 1
*
*/
void HW_RTC_BKUPRead(uint32_t *Data0, uint32_t *Data1);
/*!
* \brief Write in backup registers
* \param [IN] Data 0
* \param [IN] Data 1
*
*/
void HW_RTC_BKUPWrite(uint32_t Data0, uint32_t Data1);
#ifdef __cplusplus
}
#endif
#endif /* __RTC_IF_H__ */
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/

View File

@@ -0,0 +1,81 @@
/**
******************************************************************************
* @file stm32_lpm_if.h
* @author MCD Application Team
* @brief Header for stm32_lpm_f.c module (deveice specfic LP management)
******************************************************************************
* @attention
*
* <h2><center>&copy; Copyright (c) 2019 STMicroelectronics.
* All rights reserved.</center></h2>
*
* This software component is licensed by ST under Ultimate Liberty license
* SLA0044, the "License"; You may not use this file except in compliance with
* the License. You may obtain a copy of the License at:
* www.st.com/SLA0044
*
******************************************************************************
*/
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef __STM32_LPM_IF_H__
#define __STM32_LPM_IF_H__
#ifdef __cplusplus
extern "C" {
#endif
/* Includes ------------------------------------------------------------------*/
#include "stm32_lpm.h"
/**
* @brief Enters Low Power Off Mode
* @param none
* @retval none
*/
void PWR_EnterOffMode(void);
/**
* @brief Exits Low Power Off Mode
* @param none
* @retval none
*/
void PWR_ExitOffMode(void);
/**
* @brief Enters Low Power Stop Mode
* @note ARM exists the function when waking up
* @param none
* @retval none
*/
void PWR_EnterStopMode(void);
/**
* @brief Exits Low Power Stop Mode
* @note Enable the pll at 32MHz
* @param none
* @retval none
*/
void PWR_ExitStopMode(void);
/**
* @brief Enters Low Power Sleep Mode
* @note ARM exits the function when waking up
* @param none
* @retval none
*/
void PWR_EnterSleepMode(void);
/**
* @brief Enters Low Power Sleep Mode
* @note ARM exits the function when waking up
* @param none
* @retval none
*/
void PWR_ExitSleepMode(void);
#ifdef __cplusplus
}
#endif
#endif /*__STM32_LPM_IF_H__ */
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/

View File

@@ -33,30 +33,30 @@
* @brief This is the list of modules to be used in the HAL driver
*/
#define HAL_MODULE_ENABLED
/* #define HAL_ADC_MODULE_ENABLED */
/* #define HAL_COMP_MODULE_ENABLED */
/* #define HAL_CRC_MODULE_ENABLED */
/* #define HAL_CRYP_MODULE_ENABLED */
/* #define HAL_DAC_MODULE_ENABLED */
/* #define HAL_GTZC_MODULE_ENABLED */
/* #define HAL_HSEM_MODULE_ENABLED */
/* #define HAL_I2C_MODULE_ENABLED */
/* #define HAL_I2S_MODULE_ENABLED */
/* #define HAL_IPCC_MODULE_ENABLED */
/* #define HAL_IRDA_MODULE_ENABLED */
/* #define HAL_IWDG_MODULE_ENABLED */
/* #define HAL_LPTIM_MODULE_ENABLED */
/* #define HAL_PKA_MODULE_ENABLED */
/* #define HAL_RNG_MODULE_ENABLED */
/* #define HAL_RTC_MODULE_ENABLED */
/* #define HAL_SMARTCARD_MODULE_ENABLED */
/* #define HAL_SMBUS_MODULE_ENABLED */
/* #define HAL_SPI_MODULE_ENABLED */
/* #define HAL_SUBGHZ_MODULE_ENABLED */
/* #define HAL_TIM_MODULE_ENABLED */
#define HAL_ADC_MODULE_ENABLED
//#define HAL_COMP_MODULE_ENABLED
//#define HAL_CRC_MODULE_ENABLED
//#define HAL_CRYP_MODULE_ENABLED
//#define HAL_DAC_MODULE_ENABLED
//#define HAL_GTZC_MODULE_ENABLED
//#define HAL_HSEM_MODULE_ENABLED
//#define HAL_I2C_MODULE_ENABLED
//#define HAL_I2S_MODULE_ENABLED
//#define HAL_IPCC_MODULE_ENABLED
//#define HAL_IRDA_MODULE_ENABLED
//#define HAL_IWDG_MODULE_ENABLED
#define HAL_LPTIM_MODULE_ENABLED
//#define HAL_PKA_MODULE_ENABLED
//#define HAL_RNG_MODULE_ENABLED
#define HAL_RTC_MODULE_ENABLED
//#define HAL_SMARTCARD_MODULE_ENABLED
//#define HAL_SMBUS_MODULE_ENABLED
#define HAL_SPI_MODULE_ENABLED
#define HAL_SUBGHZ_MODULE_ENABLED
//#define HAL_TIM_MODULE_ENABLED
#define HAL_UART_MODULE_ENABLED
/* #define HAL_USART_MODULE_ENABLED */
/* #define HAL_WWDG_MODULE_ENABLED */
#define HAL_USART_MODULE_ENABLED
//#define HAL_WWDG_MODULE_ENABLED
#define HAL_EXTI_MODULE_ENABLED
#define HAL_CORTEX_MODULE_ENABLED
#define HAL_DMA_MODULE_ENABLED

View File

@@ -1,26 +1,27 @@
/**
******************************************************************************
* File Name : USART.h
* Description : This file provides code for the configuration
* of the USART instances.
* @file usart.h
* @author MCD Application Team
* @brief configuration of the USART instances
******************************************************************************
* @attention
*
* <h2><center>&copy; Copyright (c) 2019 STMicroelectronics.
* All rights reserved.</center></h2>
*
* This software component is licensed by ST under BSD 3-Clause license,
* the "License"; You may not use this file except in compliance with the
* License. You may obtain a copy of the License at:
* opensource.org/licenses/BSD-3-Clause
* This software component is licensed by ST under Ultimate Liberty license
* SLA0044, the "License"; You may not use this file except in compliance with
* the License. You may obtain a copy of the License at:
* www.st.com/SLA0044
*
******************************************************************************
*/
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef __usart_H
#define __usart_H
#ifndef __USART_H__
#define __USART_H__
#ifdef __cplusplus
extern "C" {
extern "C" {
#endif
/* Includes ------------------------------------------------------------------*/
@@ -30,34 +31,32 @@
/* USER CODE END Includes */
extern UART_HandleTypeDef hlpuart1;
/* Pin mapping */
#define USARTx_TX_Pin GPIO_PIN_6
#define USARTx_TX_GPIO_Port GPIOB
#define USARTx_RX_Pin GPIO_PIN_7
#define USARTx_RX_GPIO_Port GPIOB
/* Not generated BY MX (?), was definied in usart_if.c */
#define USARTx_RX_GPIO_CLK_ENABLE() __HAL_RCC_GPIOB_CLK_ENABLE()
#define USARTx_TX_GPIO_CLK_ENABLE() __HAL_RCC_GPIOB_CLK_ENABLE()
#define USARTx_CLK_ENABLE() __HAL_RCC_USART1_CLK_ENABLE()
#define USARTx_TX_AF GPIO_AF7_USART1
#define USARTx_RX_AF GPIO_AF7_USART1
extern UART_HandleTypeDef huart1;
extern UART_HandleTypeDef huart2;
/* USER CODE BEGIN Private defines */
/* USER CODE END Private defines */
void MX_LPUART1_UART_Init(void);
void MX_USART1_UART_Init(void);
void MX_USART2_UART_Init(void);
/* USER CODE BEGIN Prototypes */
/* USER CODE END Prototypes */
#ifdef __cplusplus
}
#endif
#endif /*__ usart_H */
/**
* @}
*/
/**
* @}
*/
#endif /* __USART_H__*/
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/

View File

@@ -0,0 +1,70 @@
/**
******************************************************************************
* @file usart_if.h
* @author MCD Application Team
* @brief Header file for the UART driver handling for hyperterminal communication
******************************************************************************
* @attention
*
* <h2><center>&copy; Copyright (c) 2019 STMicroelectronics.
* All rights reserved.</center></h2>
*
* This software component is licensed by ST under Ultimate Liberty license
* SLA0044, the "License"; You may not use this file except in compliance with
* the License. You may obtain a copy of the License at:
* www.st.com/SLA0044
*
******************************************************************************
*/
#include "usart.h"
#include "dma.h"
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef __USART_IF_H__
#define __USART_IF_H__
#ifdef __cplusplus
extern "C" {
#endif
/* Includes ------------------------------------------------------------------*/
/* Exported types ------------------------------------------------------------*/
/* Exported constants --------------------------------------------------------*/
/* External variables --------------------------------------------------------*/
/* Exported functions ------------------------------------------------------- */
/**
* @brief Init the UART and associated DMA.
* @param TxCpltCallback
* @return none
*/
uint8_t vcom_Init(void (*cb)(void*));
/**
* @brief DeInit the UART and associated DMA.
* @param none
* @return none
*/
uint8_t vcom_DeInit(void);
/**
* @brief send buffer @p_data of size size to vcom using DMA
* @param p_data data to be sent
* @param szie of buffer p_data to be sent
* @return none
*/
uint8_t vcom_Trace(uint8_t *p_data, uint16_t size);
#ifdef __cplusplus
}
#endif
#endif /* __USART_IF_H__ */
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/

View File

@@ -0,0 +1,936 @@
/*
---------------------------------------------------------------------------
Copyright (c) 1998-2008, Brian Gladman, Worcester, UK. All rights reserved.
LICENSE TERMS
The redistribution and use of this software (with or without changes)
is allowed without the payment of fees or royalties provided that:
1. source code distributions include the above copyright notice, this
list of conditions and the following disclaimer;
2. binary distributions include the above copyright notice, this list
of conditions and the following disclaimer in their documentation;
3. the name of the copyright holder is not used to endorse products
built using this software without specific written permission.
DISCLAIMER
This software is provided 'as is' with no explicit or implied warranties
in respect of its properties, including, but not limited to, correctness
and/or fitness for purpose.
---------------------------------------------------------------------------
Issue 09/09/2006
This is an AES implementation that uses only 8-bit byte operations on the
cipher state (there are options to use 32-bit types if available).
The combination of mix columns and byte substitution used here is based on
that developed by Karl Malbrain. His contribution is acknowledged.
*/
/* define if you have a fast memcpy function on your system */
#if 0
# define HAVE_MEMCPY
# include <string.h>
# if defined( _MSC_VER )
# include <intrin.h>
# pragma intrinsic( memcpy )
# endif
#endif
#include <stdlib.h>
#include <stdint.h>
/* define if you have fast 32-bit types on your system */
#if ( __CORTEX_M != 0 ) // if Cortex is different from M0/M0+
# define HAVE_UINT_32T
#endif
/* define if you don't want any tables */
#if 1
# define USE_TABLES
#endif
/* On Intel Core 2 duo VERSION_1 is faster */
/* alternative versions (test for performance on your system) */
#if 1
# define VERSION_1
#endif
#include "aes.h"
//#if defined( HAVE_UINT_32T )
// typedef unsigned long uint32_t;
//#endif
/* functions for finite field multiplication in the AES Galois field */
#define WPOLY 0x011b
#define BPOLY 0x1b
#define DPOLY 0x008d
#define f1(x) (x)
#define f2(x) ((x << 1) ^ (((x >> 7) & 1) * WPOLY))
#define f4(x) ((x << 2) ^ (((x >> 6) & 1) * WPOLY) ^ (((x >> 6) & 2) * WPOLY))
#define f8(x) ((x << 3) ^ (((x >> 5) & 1) * WPOLY) ^ (((x >> 5) & 2) * WPOLY) \
^ (((x >> 5) & 4) * WPOLY))
#define d2(x) (((x) >> 1) ^ ((x) & 1 ? DPOLY : 0))
#define f3(x) (f2(x) ^ x)
#define f9(x) (f8(x) ^ x)
#define fb(x) (f8(x) ^ f2(x) ^ x)
#define fd(x) (f8(x) ^ f4(x) ^ x)
#define fe(x) (f8(x) ^ f4(x) ^ f2(x))
#if defined( USE_TABLES )
#define sb_data(w) { /* S Box data values */ \
w(0x63), w(0x7c), w(0x77), w(0x7b), w(0xf2), w(0x6b), w(0x6f), w(0xc5),\
w(0x30), w(0x01), w(0x67), w(0x2b), w(0xfe), w(0xd7), w(0xab), w(0x76),\
w(0xca), w(0x82), w(0xc9), w(0x7d), w(0xfa), w(0x59), w(0x47), w(0xf0),\
w(0xad), w(0xd4), w(0xa2), w(0xaf), w(0x9c), w(0xa4), w(0x72), w(0xc0),\
w(0xb7), w(0xfd), w(0x93), w(0x26), w(0x36), w(0x3f), w(0xf7), w(0xcc),\
w(0x34), w(0xa5), w(0xe5), w(0xf1), w(0x71), w(0xd8), w(0x31), w(0x15),\
w(0x04), w(0xc7), w(0x23), w(0xc3), w(0x18), w(0x96), w(0x05), w(0x9a),\
w(0x07), w(0x12), w(0x80), w(0xe2), w(0xeb), w(0x27), w(0xb2), w(0x75),\
w(0x09), w(0x83), w(0x2c), w(0x1a), w(0x1b), w(0x6e), w(0x5a), w(0xa0),\
w(0x52), w(0x3b), w(0xd6), w(0xb3), w(0x29), w(0xe3), w(0x2f), w(0x84),\
w(0x53), w(0xd1), w(0x00), w(0xed), w(0x20), w(0xfc), w(0xb1), w(0x5b),\
w(0x6a), w(0xcb), w(0xbe), w(0x39), w(0x4a), w(0x4c), w(0x58), w(0xcf),\
w(0xd0), w(0xef), w(0xaa), w(0xfb), w(0x43), w(0x4d), w(0x33), w(0x85),\
w(0x45), w(0xf9), w(0x02), w(0x7f), w(0x50), w(0x3c), w(0x9f), w(0xa8),\
w(0x51), w(0xa3), w(0x40), w(0x8f), w(0x92), w(0x9d), w(0x38), w(0xf5),\
w(0xbc), w(0xb6), w(0xda), w(0x21), w(0x10), w(0xff), w(0xf3), w(0xd2),\
w(0xcd), w(0x0c), w(0x13), w(0xec), w(0x5f), w(0x97), w(0x44), w(0x17),\
w(0xc4), w(0xa7), w(0x7e), w(0x3d), w(0x64), w(0x5d), w(0x19), w(0x73),\
w(0x60), w(0x81), w(0x4f), w(0xdc), w(0x22), w(0x2a), w(0x90), w(0x88),\
w(0x46), w(0xee), w(0xb8), w(0x14), w(0xde), w(0x5e), w(0x0b), w(0xdb),\
w(0xe0), w(0x32), w(0x3a), w(0x0a), w(0x49), w(0x06), w(0x24), w(0x5c),\
w(0xc2), w(0xd3), w(0xac), w(0x62), w(0x91), w(0x95), w(0xe4), w(0x79),\
w(0xe7), w(0xc8), w(0x37), w(0x6d), w(0x8d), w(0xd5), w(0x4e), w(0xa9),\
w(0x6c), w(0x56), w(0xf4), w(0xea), w(0x65), w(0x7a), w(0xae), w(0x08),\
w(0xba), w(0x78), w(0x25), w(0x2e), w(0x1c), w(0xa6), w(0xb4), w(0xc6),\
w(0xe8), w(0xdd), w(0x74), w(0x1f), w(0x4b), w(0xbd), w(0x8b), w(0x8a),\
w(0x70), w(0x3e), w(0xb5), w(0x66), w(0x48), w(0x03), w(0xf6), w(0x0e),\
w(0x61), w(0x35), w(0x57), w(0xb9), w(0x86), w(0xc1), w(0x1d), w(0x9e),\
w(0xe1), w(0xf8), w(0x98), w(0x11), w(0x69), w(0xd9), w(0x8e), w(0x94),\
w(0x9b), w(0x1e), w(0x87), w(0xe9), w(0xce), w(0x55), w(0x28), w(0xdf),\
w(0x8c), w(0xa1), w(0x89), w(0x0d), w(0xbf), w(0xe6), w(0x42), w(0x68),\
w(0x41), w(0x99), w(0x2d), w(0x0f), w(0xb0), w(0x54), w(0xbb), w(0x16) }
#define isb_data(w) { /* inverse S Box data values */ \
w(0x52), w(0x09), w(0x6a), w(0xd5), w(0x30), w(0x36), w(0xa5), w(0x38),\
w(0xbf), w(0x40), w(0xa3), w(0x9e), w(0x81), w(0xf3), w(0xd7), w(0xfb),\
w(0x7c), w(0xe3), w(0x39), w(0x82), w(0x9b), w(0x2f), w(0xff), w(0x87),\
w(0x34), w(0x8e), w(0x43), w(0x44), w(0xc4), w(0xde), w(0xe9), w(0xcb),\
w(0x54), w(0x7b), w(0x94), w(0x32), w(0xa6), w(0xc2), w(0x23), w(0x3d),\
w(0xee), w(0x4c), w(0x95), w(0x0b), w(0x42), w(0xfa), w(0xc3), w(0x4e),\
w(0x08), w(0x2e), w(0xa1), w(0x66), w(0x28), w(0xd9), w(0x24), w(0xb2),\
w(0x76), w(0x5b), w(0xa2), w(0x49), w(0x6d), w(0x8b), w(0xd1), w(0x25),\
w(0x72), w(0xf8), w(0xf6), w(0x64), w(0x86), w(0x68), w(0x98), w(0x16),\
w(0xd4), w(0xa4), w(0x5c), w(0xcc), w(0x5d), w(0x65), w(0xb6), w(0x92),\
w(0x6c), w(0x70), w(0x48), w(0x50), w(0xfd), w(0xed), w(0xb9), w(0xda),\
w(0x5e), w(0x15), w(0x46), w(0x57), w(0xa7), w(0x8d), w(0x9d), w(0x84),\
w(0x90), w(0xd8), w(0xab), w(0x00), w(0x8c), w(0xbc), w(0xd3), w(0x0a),\
w(0xf7), w(0xe4), w(0x58), w(0x05), w(0xb8), w(0xb3), w(0x45), w(0x06),\
w(0xd0), w(0x2c), w(0x1e), w(0x8f), w(0xca), w(0x3f), w(0x0f), w(0x02),\
w(0xc1), w(0xaf), w(0xbd), w(0x03), w(0x01), w(0x13), w(0x8a), w(0x6b),\
w(0x3a), w(0x91), w(0x11), w(0x41), w(0x4f), w(0x67), w(0xdc), w(0xea),\
w(0x97), w(0xf2), w(0xcf), w(0xce), w(0xf0), w(0xb4), w(0xe6), w(0x73),\
w(0x96), w(0xac), w(0x74), w(0x22), w(0xe7), w(0xad), w(0x35), w(0x85),\
w(0xe2), w(0xf9), w(0x37), w(0xe8), w(0x1c), w(0x75), w(0xdf), w(0x6e),\
w(0x47), w(0xf1), w(0x1a), w(0x71), w(0x1d), w(0x29), w(0xc5), w(0x89),\
w(0x6f), w(0xb7), w(0x62), w(0x0e), w(0xaa), w(0x18), w(0xbe), w(0x1b),\
w(0xfc), w(0x56), w(0x3e), w(0x4b), w(0xc6), w(0xd2), w(0x79), w(0x20),\
w(0x9a), w(0xdb), w(0xc0), w(0xfe), w(0x78), w(0xcd), w(0x5a), w(0xf4),\
w(0x1f), w(0xdd), w(0xa8), w(0x33), w(0x88), w(0x07), w(0xc7), w(0x31),\
w(0xb1), w(0x12), w(0x10), w(0x59), w(0x27), w(0x80), w(0xec), w(0x5f),\
w(0x60), w(0x51), w(0x7f), w(0xa9), w(0x19), w(0xb5), w(0x4a), w(0x0d),\
w(0x2d), w(0xe5), w(0x7a), w(0x9f), w(0x93), w(0xc9), w(0x9c), w(0xef),\
w(0xa0), w(0xe0), w(0x3b), w(0x4d), w(0xae), w(0x2a), w(0xf5), w(0xb0),\
w(0xc8), w(0xeb), w(0xbb), w(0x3c), w(0x83), w(0x53), w(0x99), w(0x61),\
w(0x17), w(0x2b), w(0x04), w(0x7e), w(0xba), w(0x77), w(0xd6), w(0x26),\
w(0xe1), w(0x69), w(0x14), w(0x63), w(0x55), w(0x21), w(0x0c), w(0x7d) }
#define mm_data(w) { /* basic data for forming finite field tables */ \
w(0x00), w(0x01), w(0x02), w(0x03), w(0x04), w(0x05), w(0x06), w(0x07),\
w(0x08), w(0x09), w(0x0a), w(0x0b), w(0x0c), w(0x0d), w(0x0e), w(0x0f),\
w(0x10), w(0x11), w(0x12), w(0x13), w(0x14), w(0x15), w(0x16), w(0x17),\
w(0x18), w(0x19), w(0x1a), w(0x1b), w(0x1c), w(0x1d), w(0x1e), w(0x1f),\
w(0x20), w(0x21), w(0x22), w(0x23), w(0x24), w(0x25), w(0x26), w(0x27),\
w(0x28), w(0x29), w(0x2a), w(0x2b), w(0x2c), w(0x2d), w(0x2e), w(0x2f),\
w(0x30), w(0x31), w(0x32), w(0x33), w(0x34), w(0x35), w(0x36), w(0x37),\
w(0x38), w(0x39), w(0x3a), w(0x3b), w(0x3c), w(0x3d), w(0x3e), w(0x3f),\
w(0x40), w(0x41), w(0x42), w(0x43), w(0x44), w(0x45), w(0x46), w(0x47),\
w(0x48), w(0x49), w(0x4a), w(0x4b), w(0x4c), w(0x4d), w(0x4e), w(0x4f),\
w(0x50), w(0x51), w(0x52), w(0x53), w(0x54), w(0x55), w(0x56), w(0x57),\
w(0x58), w(0x59), w(0x5a), w(0x5b), w(0x5c), w(0x5d), w(0x5e), w(0x5f),\
w(0x60), w(0x61), w(0x62), w(0x63), w(0x64), w(0x65), w(0x66), w(0x67),\
w(0x68), w(0x69), w(0x6a), w(0x6b), w(0x6c), w(0x6d), w(0x6e), w(0x6f),\
w(0x70), w(0x71), w(0x72), w(0x73), w(0x74), w(0x75), w(0x76), w(0x77),\
w(0x78), w(0x79), w(0x7a), w(0x7b), w(0x7c), w(0x7d), w(0x7e), w(0x7f),\
w(0x80), w(0x81), w(0x82), w(0x83), w(0x84), w(0x85), w(0x86), w(0x87),\
w(0x88), w(0x89), w(0x8a), w(0x8b), w(0x8c), w(0x8d), w(0x8e), w(0x8f),\
w(0x90), w(0x91), w(0x92), w(0x93), w(0x94), w(0x95), w(0x96), w(0x97),\
w(0x98), w(0x99), w(0x9a), w(0x9b), w(0x9c), w(0x9d), w(0x9e), w(0x9f),\
w(0xa0), w(0xa1), w(0xa2), w(0xa3), w(0xa4), w(0xa5), w(0xa6), w(0xa7),\
w(0xa8), w(0xa9), w(0xaa), w(0xab), w(0xac), w(0xad), w(0xae), w(0xaf),\
w(0xb0), w(0xb1), w(0xb2), w(0xb3), w(0xb4), w(0xb5), w(0xb6), w(0xb7),\
w(0xb8), w(0xb9), w(0xba), w(0xbb), w(0xbc), w(0xbd), w(0xbe), w(0xbf),\
w(0xc0), w(0xc1), w(0xc2), w(0xc3), w(0xc4), w(0xc5), w(0xc6), w(0xc7),\
w(0xc8), w(0xc9), w(0xca), w(0xcb), w(0xcc), w(0xcd), w(0xce), w(0xcf),\
w(0xd0), w(0xd1), w(0xd2), w(0xd3), w(0xd4), w(0xd5), w(0xd6), w(0xd7),\
w(0xd8), w(0xd9), w(0xda), w(0xdb), w(0xdc), w(0xdd), w(0xde), w(0xdf),\
w(0xe0), w(0xe1), w(0xe2), w(0xe3), w(0xe4), w(0xe5), w(0xe6), w(0xe7),\
w(0xe8), w(0xe9), w(0xea), w(0xeb), w(0xec), w(0xed), w(0xee), w(0xef),\
w(0xf0), w(0xf1), w(0xf2), w(0xf3), w(0xf4), w(0xf5), w(0xf6), w(0xf7),\
w(0xf8), w(0xf9), w(0xfa), w(0xfb), w(0xfc), w(0xfd), w(0xfe), w(0xff) }
static const uint8_t sbox[256] = sb_data(f1);
#if defined( AES_DEC_PREKEYED )
static const uint8_t isbox[256] = isb_data(f1);
#endif
static const uint8_t gfm2_sbox[256] = sb_data(f2);
static const uint8_t gfm3_sbox[256] = sb_data(f3);
#if defined( AES_DEC_PREKEYED )
static const uint8_t gfmul_9[256] = mm_data(f9);
static const uint8_t gfmul_b[256] = mm_data(fb);
static const uint8_t gfmul_d[256] = mm_data(fd);
static const uint8_t gfmul_e[256] = mm_data(fe);
#endif
#define s_box(x) sbox[(x)]
#if defined( AES_DEC_PREKEYED )
#define is_box(x) isbox[(x)]
#endif
#define gfm2_sb(x) gfm2_sbox[(x)]
#define gfm3_sb(x) gfm3_sbox[(x)]
#if defined( AES_DEC_PREKEYED )
#define gfm_9(x) gfmul_9[(x)]
#define gfm_b(x) gfmul_b[(x)]
#define gfm_d(x) gfmul_d[(x)]
#define gfm_e(x) gfmul_e[(x)]
#endif
#else
/* this is the high bit of x right shifted by 1 */
/* position. Since the starting polynomial has */
/* 9 bits (0x11b), this right shift keeps the */
/* values of all top bits within a byte */
static uint8_t hibit(const uint8_t x)
{ uint8_t r = (uint8_t)((x >> 1) | (x >> 2));
r |= (r >> 2);
r |= (r >> 4);
return (r + 1) >> 1;
}
/* return the inverse of the finite field element x */
static uint8_t gf_inv(const uint8_t x)
{ uint8_t p1 = x, p2 = BPOLY, n1 = hibit(x), n2 = 0x80, v1 = 1, v2 = 0;
if(x < 2)
return x;
for( ; ; )
{
if(n1)
while(n2 >= n1) /* divide polynomial p2 by p1 */
{
n2 /= n1; /* shift smaller polynomial left */
p2 ^= (p1 * n2) & 0xff; /* and remove from larger one */
v2 ^= (v1 * n2); /* shift accumulated value and */
n2 = hibit(p2); /* add into result */
}
else
return v1;
if(n2) /* repeat with values swapped */
while(n1 >= n2)
{
n1 /= n2;
p1 ^= p2 * n1;
v1 ^= v2 * n1;
n1 = hibit(p1);
}
else
return v2;
}
}
/* The forward and inverse affine transformations used in the S-box */
uint8_t fwd_affine(const uint8_t x)
{
#if defined( HAVE_UINT_32T )
uint32_t w = x;
w ^= (w << 1) ^ (w << 2) ^ (w << 3) ^ (w << 4);
return 0x63 ^ ((w ^ (w >> 8)) & 0xff);
#else
return 0x63 ^ x ^ (x << 1) ^ (x << 2) ^ (x << 3) ^ (x << 4)
^ (x >> 7) ^ (x >> 6) ^ (x >> 5) ^ (x >> 4);
#endif
}
uint8_t inv_affine(const uint8_t x)
{
#if defined( HAVE_UINT_32T )
uint32_t w = x;
w = (w << 1) ^ (w << 3) ^ (w << 6);
return 0x05 ^ ((w ^ (w >> 8)) & 0xff);
#else
return 0x05 ^ (x << 1) ^ (x << 3) ^ (x << 6)
^ (x >> 7) ^ (x >> 5) ^ (x >> 2);
#endif
}
#define s_box(x) fwd_affine(gf_inv(x))
#define is_box(x) gf_inv(inv_affine(x))
#define gfm2_sb(x) f2(s_box(x))
#define gfm3_sb(x) f3(s_box(x))
#define gfm_9(x) f9(x)
#define gfm_b(x) fb(x)
#define gfm_d(x) fd(x)
#define gfm_e(x) fe(x)
#endif
#if defined( HAVE_MEMCPY )
# define block_copy_nn(d, s, l) memcpy(d, s, l)
# define block_copy(d, s) memcpy(d, s, N_BLOCK)
#else
# define block_copy_nn(d, s, l) copy_block_nn(d, s, l)
# define block_copy(d, s) copy_block(d, s)
#endif
static void copy_block( void *d, const void *s )
{
#if defined( HAVE_UINT_32T )
((uint32_t*)d)[ 0] = ((uint32_t*)s)[ 0];
((uint32_t*)d)[ 1] = ((uint32_t*)s)[ 1];
((uint32_t*)d)[ 2] = ((uint32_t*)s)[ 2];
((uint32_t*)d)[ 3] = ((uint32_t*)s)[ 3];
#else
((uint8_t*)d)[ 0] = ((uint8_t*)s)[ 0];
((uint8_t*)d)[ 1] = ((uint8_t*)s)[ 1];
((uint8_t*)d)[ 2] = ((uint8_t*)s)[ 2];
((uint8_t*)d)[ 3] = ((uint8_t*)s)[ 3];
((uint8_t*)d)[ 4] = ((uint8_t*)s)[ 4];
((uint8_t*)d)[ 5] = ((uint8_t*)s)[ 5];
((uint8_t*)d)[ 6] = ((uint8_t*)s)[ 6];
((uint8_t*)d)[ 7] = ((uint8_t*)s)[ 7];
((uint8_t*)d)[ 8] = ((uint8_t*)s)[ 8];
((uint8_t*)d)[ 9] = ((uint8_t*)s)[ 9];
((uint8_t*)d)[10] = ((uint8_t*)s)[10];
((uint8_t*)d)[11] = ((uint8_t*)s)[11];
((uint8_t*)d)[12] = ((uint8_t*)s)[12];
((uint8_t*)d)[13] = ((uint8_t*)s)[13];
((uint8_t*)d)[14] = ((uint8_t*)s)[14];
((uint8_t*)d)[15] = ((uint8_t*)s)[15];
#endif
}
static void copy_block_nn( uint8_t * d, const uint8_t *s, uint8_t nn )
{
while( nn-- )
//*((uint8_t*)d)++ = *((uint8_t*)s)++;
*d++ = *s++;
}
static void xor_block( void *d, const void *s )
{
#if defined( HAVE_UINT_32T )
((uint32_t*)d)[ 0] ^= ((uint32_t*)s)[ 0];
((uint32_t*)d)[ 1] ^= ((uint32_t*)s)[ 1];
((uint32_t*)d)[ 2] ^= ((uint32_t*)s)[ 2];
((uint32_t*)d)[ 3] ^= ((uint32_t*)s)[ 3];
#else
((uint8_t*)d)[ 0] ^= ((uint8_t*)s)[ 0];
((uint8_t*)d)[ 1] ^= ((uint8_t*)s)[ 1];
((uint8_t*)d)[ 2] ^= ((uint8_t*)s)[ 2];
((uint8_t*)d)[ 3] ^= ((uint8_t*)s)[ 3];
((uint8_t*)d)[ 4] ^= ((uint8_t*)s)[ 4];
((uint8_t*)d)[ 5] ^= ((uint8_t*)s)[ 5];
((uint8_t*)d)[ 6] ^= ((uint8_t*)s)[ 6];
((uint8_t*)d)[ 7] ^= ((uint8_t*)s)[ 7];
((uint8_t*)d)[ 8] ^= ((uint8_t*)s)[ 8];
((uint8_t*)d)[ 9] ^= ((uint8_t*)s)[ 9];
((uint8_t*)d)[10] ^= ((uint8_t*)s)[10];
((uint8_t*)d)[11] ^= ((uint8_t*)s)[11];
((uint8_t*)d)[12] ^= ((uint8_t*)s)[12];
((uint8_t*)d)[13] ^= ((uint8_t*)s)[13];
((uint8_t*)d)[14] ^= ((uint8_t*)s)[14];
((uint8_t*)d)[15] ^= ((uint8_t*)s)[15];
#endif
}
static void copy_and_key( void *d, const void *s, const void *k )
{
#if defined( HAVE_UINT_32T )
((uint32_t*)d)[ 0] = ((uint32_t*)s)[ 0] ^ ((uint32_t*)k)[ 0];
((uint32_t*)d)[ 1] = ((uint32_t*)s)[ 1] ^ ((uint32_t*)k)[ 1];
((uint32_t*)d)[ 2] = ((uint32_t*)s)[ 2] ^ ((uint32_t*)k)[ 2];
((uint32_t*)d)[ 3] = ((uint32_t*)s)[ 3] ^ ((uint32_t*)k)[ 3];
#elif 1
((uint8_t*)d)[ 0] = ((uint8_t*)s)[ 0] ^ ((uint8_t*)k)[ 0];
((uint8_t*)d)[ 1] = ((uint8_t*)s)[ 1] ^ ((uint8_t*)k)[ 1];
((uint8_t*)d)[ 2] = ((uint8_t*)s)[ 2] ^ ((uint8_t*)k)[ 2];
((uint8_t*)d)[ 3] = ((uint8_t*)s)[ 3] ^ ((uint8_t*)k)[ 3];
((uint8_t*)d)[ 4] = ((uint8_t*)s)[ 4] ^ ((uint8_t*)k)[ 4];
((uint8_t*)d)[ 5] = ((uint8_t*)s)[ 5] ^ ((uint8_t*)k)[ 5];
((uint8_t*)d)[ 6] = ((uint8_t*)s)[ 6] ^ ((uint8_t*)k)[ 6];
((uint8_t*)d)[ 7] = ((uint8_t*)s)[ 7] ^ ((uint8_t*)k)[ 7];
((uint8_t*)d)[ 8] = ((uint8_t*)s)[ 8] ^ ((uint8_t*)k)[ 8];
((uint8_t*)d)[ 9] = ((uint8_t*)s)[ 9] ^ ((uint8_t*)k)[ 9];
((uint8_t*)d)[10] = ((uint8_t*)s)[10] ^ ((uint8_t*)k)[10];
((uint8_t*)d)[11] = ((uint8_t*)s)[11] ^ ((uint8_t*)k)[11];
((uint8_t*)d)[12] = ((uint8_t*)s)[12] ^ ((uint8_t*)k)[12];
((uint8_t*)d)[13] = ((uint8_t*)s)[13] ^ ((uint8_t*)k)[13];
((uint8_t*)d)[14] = ((uint8_t*)s)[14] ^ ((uint8_t*)k)[14];
((uint8_t*)d)[15] = ((uint8_t*)s)[15] ^ ((uint8_t*)k)[15];
#else
block_copy(d, s);
xor_block(d, k);
#endif
}
static void add_round_key( uint8_t d[N_BLOCK], const uint8_t k[N_BLOCK] )
{
xor_block(d, k);
}
static void shift_sub_rows( uint8_t st[N_BLOCK] )
{ uint8_t tt;
st[ 0] = s_box(st[ 0]); st[ 4] = s_box(st[ 4]);
st[ 8] = s_box(st[ 8]); st[12] = s_box(st[12]);
tt = st[1]; st[ 1] = s_box(st[ 5]); st[ 5] = s_box(st[ 9]);
st[ 9] = s_box(st[13]); st[13] = s_box( tt );
tt = st[2]; st[ 2] = s_box(st[10]); st[10] = s_box( tt );
tt = st[6]; st[ 6] = s_box(st[14]); st[14] = s_box( tt );
tt = st[15]; st[15] = s_box(st[11]); st[11] = s_box(st[ 7]);
st[ 7] = s_box(st[ 3]); st[ 3] = s_box( tt );
}
#if defined( AES_DEC_PREKEYED )
static void inv_shift_sub_rows( uint8_t st[N_BLOCK] )
{ uint8_t tt;
st[ 0] = is_box(st[ 0]); st[ 4] = is_box(st[ 4]);
st[ 8] = is_box(st[ 8]); st[12] = is_box(st[12]);
tt = st[13]; st[13] = is_box(st[9]); st[ 9] = is_box(st[5]);
st[ 5] = is_box(st[1]); st[ 1] = is_box( tt );
tt = st[2]; st[ 2] = is_box(st[10]); st[10] = is_box( tt );
tt = st[6]; st[ 6] = is_box(st[14]); st[14] = is_box( tt );
tt = st[3]; st[ 3] = is_box(st[ 7]); st[ 7] = is_box(st[11]);
st[11] = is_box(st[15]); st[15] = is_box( tt );
}
#endif
#if defined( VERSION_1 )
static void mix_sub_columns( uint8_t dt[N_BLOCK] )
{ uint8_t st[N_BLOCK];
block_copy(st, dt);
#else
static void mix_sub_columns( uint8_t dt[N_BLOCK], uint8_t st[N_BLOCK] )
{
#endif
dt[ 0] = gfm2_sb(st[0]) ^ gfm3_sb(st[5]) ^ s_box(st[10]) ^ s_box(st[15]);
dt[ 1] = s_box(st[0]) ^ gfm2_sb(st[5]) ^ gfm3_sb(st[10]) ^ s_box(st[15]);
dt[ 2] = s_box(st[0]) ^ s_box(st[5]) ^ gfm2_sb(st[10]) ^ gfm3_sb(st[15]);
dt[ 3] = gfm3_sb(st[0]) ^ s_box(st[5]) ^ s_box(st[10]) ^ gfm2_sb(st[15]);
dt[ 4] = gfm2_sb(st[4]) ^ gfm3_sb(st[9]) ^ s_box(st[14]) ^ s_box(st[3]);
dt[ 5] = s_box(st[4]) ^ gfm2_sb(st[9]) ^ gfm3_sb(st[14]) ^ s_box(st[3]);
dt[ 6] = s_box(st[4]) ^ s_box(st[9]) ^ gfm2_sb(st[14]) ^ gfm3_sb(st[3]);
dt[ 7] = gfm3_sb(st[4]) ^ s_box(st[9]) ^ s_box(st[14]) ^ gfm2_sb(st[3]);
dt[ 8] = gfm2_sb(st[8]) ^ gfm3_sb(st[13]) ^ s_box(st[2]) ^ s_box(st[7]);
dt[ 9] = s_box(st[8]) ^ gfm2_sb(st[13]) ^ gfm3_sb(st[2]) ^ s_box(st[7]);
dt[10] = s_box(st[8]) ^ s_box(st[13]) ^ gfm2_sb(st[2]) ^ gfm3_sb(st[7]);
dt[11] = gfm3_sb(st[8]) ^ s_box(st[13]) ^ s_box(st[2]) ^ gfm2_sb(st[7]);
dt[12] = gfm2_sb(st[12]) ^ gfm3_sb(st[1]) ^ s_box(st[6]) ^ s_box(st[11]);
dt[13] = s_box(st[12]) ^ gfm2_sb(st[1]) ^ gfm3_sb(st[6]) ^ s_box(st[11]);
dt[14] = s_box(st[12]) ^ s_box(st[1]) ^ gfm2_sb(st[6]) ^ gfm3_sb(st[11]);
dt[15] = gfm3_sb(st[12]) ^ s_box(st[1]) ^ s_box(st[6]) ^ gfm2_sb(st[11]);
}
#if defined( AES_DEC_PREKEYED )
#if defined( VERSION_1 )
static void inv_mix_sub_columns( uint8_t dt[N_BLOCK] )
{ uint8_t st[N_BLOCK];
block_copy(st, dt);
#else
static void inv_mix_sub_columns( uint8_t dt[N_BLOCK], uint8_t st[N_BLOCK] )
{
#endif
dt[ 0] = is_box(gfm_e(st[ 0]) ^ gfm_b(st[ 1]) ^ gfm_d(st[ 2]) ^ gfm_9(st[ 3]));
dt[ 5] = is_box(gfm_9(st[ 0]) ^ gfm_e(st[ 1]) ^ gfm_b(st[ 2]) ^ gfm_d(st[ 3]));
dt[10] = is_box(gfm_d(st[ 0]) ^ gfm_9(st[ 1]) ^ gfm_e(st[ 2]) ^ gfm_b(st[ 3]));
dt[15] = is_box(gfm_b(st[ 0]) ^ gfm_d(st[ 1]) ^ gfm_9(st[ 2]) ^ gfm_e(st[ 3]));
dt[ 4] = is_box(gfm_e(st[ 4]) ^ gfm_b(st[ 5]) ^ gfm_d(st[ 6]) ^ gfm_9(st[ 7]));
dt[ 9] = is_box(gfm_9(st[ 4]) ^ gfm_e(st[ 5]) ^ gfm_b(st[ 6]) ^ gfm_d(st[ 7]));
dt[14] = is_box(gfm_d(st[ 4]) ^ gfm_9(st[ 5]) ^ gfm_e(st[ 6]) ^ gfm_b(st[ 7]));
dt[ 3] = is_box(gfm_b(st[ 4]) ^ gfm_d(st[ 5]) ^ gfm_9(st[ 6]) ^ gfm_e(st[ 7]));
dt[ 8] = is_box(gfm_e(st[ 8]) ^ gfm_b(st[ 9]) ^ gfm_d(st[10]) ^ gfm_9(st[11]));
dt[13] = is_box(gfm_9(st[ 8]) ^ gfm_e(st[ 9]) ^ gfm_b(st[10]) ^ gfm_d(st[11]));
dt[ 2] = is_box(gfm_d(st[ 8]) ^ gfm_9(st[ 9]) ^ gfm_e(st[10]) ^ gfm_b(st[11]));
dt[ 7] = is_box(gfm_b(st[ 8]) ^ gfm_d(st[ 9]) ^ gfm_9(st[10]) ^ gfm_e(st[11]));
dt[12] = is_box(gfm_e(st[12]) ^ gfm_b(st[13]) ^ gfm_d(st[14]) ^ gfm_9(st[15]));
dt[ 1] = is_box(gfm_9(st[12]) ^ gfm_e(st[13]) ^ gfm_b(st[14]) ^ gfm_d(st[15]));
dt[ 6] = is_box(gfm_d(st[12]) ^ gfm_9(st[13]) ^ gfm_e(st[14]) ^ gfm_b(st[15]));
dt[11] = is_box(gfm_b(st[12]) ^ gfm_d(st[13]) ^ gfm_9(st[14]) ^ gfm_e(st[15]));
}
#endif
#if defined( AES_ENC_PREKEYED ) || defined( AES_DEC_PREKEYED )
/* Set the cipher key for the pre-keyed version */
return_type aes_set_key( const uint8_t key[], length_type keylen, aes_context ctx[1] )
{
uint8_t cc, rc, hi;
switch( keylen )
{
case 16:
case 24:
case 32:
break;
default:
ctx->rnd = 0;
return ( uint8_t )-1;
}
block_copy_nn(ctx->ksch, key, keylen);
hi = (keylen + 28) << 2;
ctx->rnd = (hi >> 4) - 1;
for( cc = keylen, rc = 1; cc < hi; cc += 4 )
{ uint8_t tt, t0, t1, t2, t3;
t0 = ctx->ksch[cc - 4];
t1 = ctx->ksch[cc - 3];
t2 = ctx->ksch[cc - 2];
t3 = ctx->ksch[cc - 1];
if( cc % keylen == 0 )
{
tt = t0;
t0 = s_box(t1) ^ rc;
t1 = s_box(t2);
t2 = s_box(t3);
t3 = s_box(tt);
rc = f2(rc);
}
else if( keylen > 24 && cc % keylen == 16 )
{
t0 = s_box(t0);
t1 = s_box(t1);
t2 = s_box(t2);
t3 = s_box(t3);
}
tt = cc - keylen;
ctx->ksch[cc + 0] = ctx->ksch[tt + 0] ^ t0;
ctx->ksch[cc + 1] = ctx->ksch[tt + 1] ^ t1;
ctx->ksch[cc + 2] = ctx->ksch[tt + 2] ^ t2;
ctx->ksch[cc + 3] = ctx->ksch[tt + 3] ^ t3;
}
return 0;
}
#endif
#if defined( AES_ENC_PREKEYED )
/* Encrypt a single block of 16 bytes */
return_type aes_encrypt( const uint8_t in[N_BLOCK], uint8_t out[N_BLOCK], const aes_context ctx[1] )
{
if( ctx->rnd )
{
uint8_t s1[N_BLOCK], r;
copy_and_key( s1, in, ctx->ksch );
for( r = 1 ; r < ctx->rnd ; ++r )
#if defined( VERSION_1 )
{
mix_sub_columns( s1 );
add_round_key( s1, ctx->ksch + r * N_BLOCK);
}
#else
{ uint8_t s2[N_BLOCK];
mix_sub_columns( s2, s1 );
copy_and_key( s1, s2, ctx->ksch + r * N_BLOCK);
}
#endif
shift_sub_rows( s1 );
copy_and_key( out, s1, ctx->ksch + r * N_BLOCK );
}
else
return ( uint8_t )-1;
return 0;
}
/* CBC encrypt a number of blocks (input and return an IV) */
return_type aes_cbc_encrypt( const uint8_t *in, uint8_t *out,
int32_t n_block, uint8_t iv[N_BLOCK], const aes_context ctx[1] )
{
while(n_block--)
{
xor_block(iv, in);
if(aes_encrypt(iv, iv, ctx) != EXIT_SUCCESS)
return EXIT_FAILURE;
//memcpy(out, iv, N_BLOCK);
block_copy(out, iv);
in += N_BLOCK;
out += N_BLOCK;
}
return EXIT_SUCCESS;
}
#endif
#if defined( AES_DEC_PREKEYED )
/* Decrypt a single block of 16 bytes */
return_type aes_decrypt( const uint8_t in[N_BLOCK], uint8_t out[N_BLOCK], const aes_context ctx[1] )
{
if( ctx->rnd )
{
uint8_t s1[N_BLOCK], r;
copy_and_key( s1, in, ctx->ksch + ctx->rnd * N_BLOCK );
inv_shift_sub_rows( s1 );
for( r = ctx->rnd ; --r ; )
#if defined( VERSION_1 )
{
add_round_key( s1, ctx->ksch + r * N_BLOCK );
inv_mix_sub_columns( s1 );
}
#else
{ uint8_t s2[N_BLOCK];
copy_and_key( s2, s1, ctx->ksch + r * N_BLOCK );
inv_mix_sub_columns( s1, s2 );
}
#endif
copy_and_key( out, s1, ctx->ksch );
}
else
return -1;
return 0;
}
/* CBC decrypt a number of blocks (input and return an IV) */
return_type aes_cbc_decrypt( const uint8_t *in, uint8_t *out,
int32_t n_block, uint8_t iv[N_BLOCK], const aes_context ctx[1] )
{
while(n_block--)
{ uint8_t tmp[N_BLOCK];
//memcpy(tmp, in, N_BLOCK);
block_copy(tmp, in);
if(aes_decrypt(in, out, ctx) != EXIT_SUCCESS)
return EXIT_FAILURE;
xor_block(out, iv);
//memcpy(iv, tmp, N_BLOCK);
block_copy(iv, tmp);
in += N_BLOCK;
out += N_BLOCK;
}
return EXIT_SUCCESS;
}
#endif
#if defined( AES_ENC_128_OTFK )
/* The 'on the fly' encryption key update for for 128 bit keys */
static void update_encrypt_key_128( uint8_t k[N_BLOCK], uint8_t *rc )
{ uint8_t cc;
k[0] ^= s_box(k[13]) ^ *rc;
k[1] ^= s_box(k[14]);
k[2] ^= s_box(k[15]);
k[3] ^= s_box(k[12]);
*rc = f2( *rc );
for(cc = 4; cc < 16; cc += 4 )
{
k[cc + 0] ^= k[cc - 4];
k[cc + 1] ^= k[cc - 3];
k[cc + 2] ^= k[cc - 2];
k[cc + 3] ^= k[cc - 1];
}
}
/* Encrypt a single block of 16 bytes with 'on the fly' 128 bit keying */
void aes_encrypt_128( const uint8_t in[N_BLOCK], uint8_t out[N_BLOCK],
const uint8_t key[N_BLOCK], uint8_t o_key[N_BLOCK] )
{ uint8_t s1[N_BLOCK], r, rc = 1;
if(o_key != key)
block_copy( o_key, key );
copy_and_key( s1, in, o_key );
for( r = 1 ; r < 10 ; ++r )
#if defined( VERSION_1 )
{
mix_sub_columns( s1 );
update_encrypt_key_128( o_key, &rc );
add_round_key( s1, o_key );
}
#else
{ uint8_t s2[N_BLOCK];
mix_sub_columns( s2, s1 );
update_encrypt_key_128( o_key, &rc );
copy_and_key( s1, s2, o_key );
}
#endif
shift_sub_rows( s1 );
update_encrypt_key_128( o_key, &rc );
copy_and_key( out, s1, o_key );
}
#endif
#if defined( AES_DEC_128_OTFK )
/* The 'on the fly' decryption key update for for 128 bit keys */
static void update_decrypt_key_128( uint8_t k[N_BLOCK], uint8_t *rc )
{ uint8_t cc;
for( cc = 12; cc > 0; cc -= 4 )
{
k[cc + 0] ^= k[cc - 4];
k[cc + 1] ^= k[cc - 3];
k[cc + 2] ^= k[cc - 2];
k[cc + 3] ^= k[cc - 1];
}
*rc = d2(*rc);
k[0] ^= s_box(k[13]) ^ *rc;
k[1] ^= s_box(k[14]);
k[2] ^= s_box(k[15]);
k[3] ^= s_box(k[12]);
}
/* Decrypt a single block of 16 bytes with 'on the fly' 128 bit keying */
void aes_decrypt_128( const uint8_t in[N_BLOCK], uint8_t out[N_BLOCK],
const uint8_t key[N_BLOCK], uint8_t o_key[N_BLOCK] )
{
uint8_t s1[N_BLOCK], r, rc = 0x6c;
if(o_key != key)
block_copy( o_key, key );
copy_and_key( s1, in, o_key );
inv_shift_sub_rows( s1 );
for( r = 10 ; --r ; )
#if defined( VERSION_1 )
{
update_decrypt_key_128( o_key, &rc );
add_round_key( s1, o_key );
inv_mix_sub_columns( s1 );
}
#else
{ uint8_t s2[N_BLOCK];
update_decrypt_key_128( o_key, &rc );
copy_and_key( s2, s1, o_key );
inv_mix_sub_columns( s1, s2 );
}
#endif
update_decrypt_key_128( o_key, &rc );
copy_and_key( out, s1, o_key );
}
#endif
#if defined( AES_ENC_256_OTFK )
/* The 'on the fly' encryption key update for for 256 bit keys */
static void update_encrypt_key_256( uint8_t k[2 * N_BLOCK], uint8_t *rc )
{ uint8_t cc;
k[0] ^= s_box(k[29]) ^ *rc;
k[1] ^= s_box(k[30]);
k[2] ^= s_box(k[31]);
k[3] ^= s_box(k[28]);
*rc = f2( *rc );
for(cc = 4; cc < 16; cc += 4)
{
k[cc + 0] ^= k[cc - 4];
k[cc + 1] ^= k[cc - 3];
k[cc + 2] ^= k[cc - 2];
k[cc + 3] ^= k[cc - 1];
}
k[16] ^= s_box(k[12]);
k[17] ^= s_box(k[13]);
k[18] ^= s_box(k[14]);
k[19] ^= s_box(k[15]);
for( cc = 20; cc < 32; cc += 4 )
{
k[cc + 0] ^= k[cc - 4];
k[cc + 1] ^= k[cc - 3];
k[cc + 2] ^= k[cc - 2];
k[cc + 3] ^= k[cc - 1];
}
}
/* Encrypt a single block of 16 bytes with 'on the fly' 256 bit keying */
void aes_encrypt_256( const uint8_t in[N_BLOCK], uint8_t out[N_BLOCK],
const uint8_t key[2 * N_BLOCK], uint8_t o_key[2 * N_BLOCK] )
{
uint8_t s1[N_BLOCK], r, rc = 1;
if(o_key != key)
{
block_copy( o_key, key );
block_copy( o_key + 16, key + 16 );
}
copy_and_key( s1, in, o_key );
for( r = 1 ; r < 14 ; ++r )
#if defined( VERSION_1 )
{
mix_sub_columns(s1);
if( r & 1 )
add_round_key( s1, o_key + 16 );
else
{
update_encrypt_key_256( o_key, &rc );
add_round_key( s1, o_key );
}
}
#else
{ uint8_t s2[N_BLOCK];
mix_sub_columns( s2, s1 );
if( r & 1 )
copy_and_key( s1, s2, o_key + 16 );
else
{
update_encrypt_key_256( o_key, &rc );
copy_and_key( s1, s2, o_key );
}
}
#endif
shift_sub_rows( s1 );
update_encrypt_key_256( o_key, &rc );
copy_and_key( out, s1, o_key );
}
#endif
#if defined( AES_DEC_256_OTFK )
/* The 'on the fly' encryption key update for for 256 bit keys */
static void update_decrypt_key_256( uint8_t k[2 * N_BLOCK], uint8_t *rc )
{ uint8_t cc;
for(cc = 28; cc > 16; cc -= 4)
{
k[cc + 0] ^= k[cc - 4];
k[cc + 1] ^= k[cc - 3];
k[cc + 2] ^= k[cc - 2];
k[cc + 3] ^= k[cc - 1];
}
k[16] ^= s_box(k[12]);
k[17] ^= s_box(k[13]);
k[18] ^= s_box(k[14]);
k[19] ^= s_box(k[15]);
for(cc = 12; cc > 0; cc -= 4)
{
k[cc + 0] ^= k[cc - 4];
k[cc + 1] ^= k[cc - 3];
k[cc + 2] ^= k[cc - 2];
k[cc + 3] ^= k[cc - 1];
}
*rc = d2(*rc);
k[0] ^= s_box(k[29]) ^ *rc;
k[1] ^= s_box(k[30]);
k[2] ^= s_box(k[31]);
k[3] ^= s_box(k[28]);
}
/* Decrypt a single block of 16 bytes with 'on the fly'
256 bit keying
*/
void aes_decrypt_256( const uint8_t in[N_BLOCK], uint8_t out[N_BLOCK],
const uint8_t key[2 * N_BLOCK], uint8_t o_key[2 * N_BLOCK] )
{
uint8_t s1[N_BLOCK], r, rc = 0x80;
if(o_key != key)
{
block_copy( o_key, key );
block_copy( o_key + 16, key + 16 );
}
copy_and_key( s1, in, o_key );
inv_shift_sub_rows( s1 );
for( r = 14 ; --r ; )
#if defined( VERSION_1 )
{
if( ( r & 1 ) )
{
update_decrypt_key_256( o_key, &rc );
add_round_key( s1, o_key + 16 );
}
else
add_round_key( s1, o_key );
inv_mix_sub_columns( s1 );
}
#else
{ uint8_t s2[N_BLOCK];
if( ( r & 1 ) )
{
update_decrypt_key_256( o_key, &rc );
copy_and_key( s2, s1, o_key + 16 );
}
else
copy_and_key( s2, s1, o_key );
inv_mix_sub_columns( s1, s2 );
}
#endif
copy_and_key( out, s1, o_key );
}
#endif

View File

@@ -0,0 +1,162 @@
/*
---------------------------------------------------------------------------
Copyright (c) 1998-2008, Brian Gladman, Worcester, UK. All rights reserved.
LICENSE TERMS
The redistribution and use of this software (with or without changes)
is allowed without the payment of fees or royalties provided that:
1. source code distributions include the above copyright notice, this
list of conditions and the following disclaimer;
2. binary distributions include the above copyright notice, this list
of conditions and the following disclaimer in their documentation;
3. the name of the copyright holder is not used to endorse products
built using this software without specific written permission.
DISCLAIMER
This software is provided 'as is' with no explicit or implied warranties
in respect of its properties, including, but not limited to, correctness
and/or fitness for purpose.
---------------------------------------------------------------------------
Issue 09/09/2006
This is an AES implementation that uses only 8-bit byte operations on the
cipher state.
*/
#ifndef AES_H
#define AES_H
#include <stdint.h>
#if 1
# define AES_ENC_PREKEYED /* AES encryption with a precomputed key schedule */
#endif
#if 0
# define AES_DEC_PREKEYED /* AES decryption with a precomputed key schedule */
#endif
#if 0
# define AES_ENC_128_OTFK /* AES encryption with 'on the fly' 128 bit keying */
#endif
#if 0
# define AES_DEC_128_OTFK /* AES decryption with 'on the fly' 128 bit keying */
#endif
#if 0
# define AES_ENC_256_OTFK /* AES encryption with 'on the fly' 256 bit keying */
#endif
#if 0
# define AES_DEC_256_OTFK /* AES decryption with 'on the fly' 256 bit keying */
#endif
#define N_ROW 4
#define N_COL 4
#define N_BLOCK (N_ROW * N_COL)
#define N_MAX_ROUNDS 14
typedef uint8_t return_type;
/* Warning: The key length for 256 bit keys overflows a byte
(see comment below)
*/
typedef uint8_t length_type;
typedef struct
{ uint8_t ksch[(N_MAX_ROUNDS + 1) * N_BLOCK];
uint8_t rnd;
} aes_context;
/* The following calls are for a precomputed key schedule
NOTE: If the length_type used for the key length is an
unsigned 8-bit character, a key length of 256 bits must
be entered as a length in bytes (valid inputs are hence
128, 192, 16, 24 and 32).
*/
#if defined( AES_ENC_PREKEYED ) || defined( AES_DEC_PREKEYED )
return_type aes_set_key( const uint8_t key[],
length_type keylen,
aes_context ctx[1] );
#endif
#if defined( AES_ENC_PREKEYED )
return_type aes_encrypt( const uint8_t in[N_BLOCK],
uint8_t out[N_BLOCK],
const aes_context ctx[1] );
return_type aes_cbc_encrypt( const uint8_t *in,
uint8_t *out,
int32_t n_block,
uint8_t iv[N_BLOCK],
const aes_context ctx[1] );
#endif
#if defined( AES_DEC_PREKEYED )
return_type aes_decrypt( const uint8_t in[N_BLOCK],
uint8_t out[N_BLOCK],
const aes_context ctx[1] );
return_type aes_cbc_decrypt( const uint8_t *in,
uint8_t *out,
int32_t n_block,
uint8_t iv[N_BLOCK],
const aes_context ctx[1] );
#endif
/* The following calls are for 'on the fly' keying. In this case the
encryption and decryption keys are different.
The encryption subroutines take a key in an array of bytes in
key[L] where L is 16, 24 or 32 bytes for key lengths of 128,
192, and 256 bits respectively. They then encrypts the input
data, in[] with this key and put the reult in the output array
out[]. In addition, the second key array, o_key[L], is used
to output the key that is needed by the decryption subroutine
to reverse the encryption operation. The two key arrays can
be the same array but in this case the original key will be
overwritten.
In the same way, the decryption subroutines output keys that
can be used to reverse their effect when used for encryption.
Only 128 and 256 bit keys are supported in these 'on the fly'
modes.
*/
#if defined( AES_ENC_128_OTFK )
void aes_encrypt_128( const uint8_t in[N_BLOCK],
uint8_t out[N_BLOCK],
const uint8_t key[N_BLOCK],
uint8_t o_key[N_BLOCK] );
#endif
#if defined( AES_DEC_128_OTFK )
void aes_decrypt_128( const uint8_t in[N_BLOCK],
uint8_t out[N_BLOCK],
const uint8_t key[N_BLOCK],
uint8_t o_key[N_BLOCK] );
#endif
#if defined( AES_ENC_256_OTFK )
void aes_encrypt_256( const uint8_t in[N_BLOCK],
uint8_t out[N_BLOCK],
const uint8_t key[2 * N_BLOCK],
uint8_t o_key[2 * N_BLOCK] );
#endif
#if defined( AES_DEC_256_OTFK )
void aes_decrypt_256( const uint8_t in[N_BLOCK],
uint8_t out[N_BLOCK],
const uint8_t key[2 * N_BLOCK],
uint8_t o_key[2 * N_BLOCK] );
#endif
#endif

View File

@@ -0,0 +1,153 @@
/**************************************************************************
Copyright (C) 2009 Lander Casado, Philippas Tsigas
All rights reserved.
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files
(the "Software"), to deal with the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimers. Redistributions in
binary form must reproduce the above copyright notice, this list of
conditions and the following disclaimers in the documentation and/or
other materials provided with the distribution.
In no event shall the authors or copyright holders be liable for any special,
incidental, indirect or consequential damages of any kind, or any damages
whatsoever resulting from loss of use, data or profits, whether or not
advised of the possibility of damage, and on any theory of liability,
arising out of or in connection with the use or performance of this software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS WITH THE SOFTWARE
*****************************************************************************/
//#include <sys/param.h>
//#include <sys/systm.h>
#include <stdint.h>
#include "aes.h"
#include "cmac.h"
#include "utilities.h"
#define LSHIFT(v, r) do { \
int32_t i; \
for (i = 0; i < 15; i++) \
(r)[i] = (v)[i] << 1 | (v)[i + 1] >> 7; \
(r)[15] = (v)[15] << 1; \
} while (0)
#define XOR(v, r) do { \
int32_t i; \
for (i = 0; i < 16; i++) \
{ \
(r)[i] = (r)[i] ^ (v)[i]; \
} \
} while (0) \
void AES_CMAC_Init(AES_CMAC_CTX *ctx)
{
memset1(ctx->X, 0, sizeof ctx->X);
ctx->M_n = 0;
memset1(ctx->rijndael.ksch, '\0', 240);
}
void AES_CMAC_SetKey(AES_CMAC_CTX *ctx, const uint8_t key[AES_CMAC_KEY_LENGTH])
{
//rijndael_set_key_enc_only(&ctx->rijndael, key, 128);
aes_set_key( key, AES_CMAC_KEY_LENGTH, &ctx->rijndael);
}
void AES_CMAC_Update(AES_CMAC_CTX *ctx, const uint8_t *data, uint32_t len)
{
uint32_t mlen;
uint8_t in[16];
if (ctx->M_n > 0) {
mlen = MIN(16 - ctx->M_n, len);
memcpy1(ctx->M_last + ctx->M_n, data, mlen);
ctx->M_n += mlen;
if (ctx->M_n < 16 || len == mlen)
return;
XOR(ctx->M_last, ctx->X);
//rijndael_encrypt(&ctx->rijndael, ctx->X, ctx->X);
aes_encrypt( ctx->X, ctx->X, &ctx->rijndael);
data += mlen;
len -= mlen;
}
while (len > 16) { /* not last block */
XOR(data, ctx->X);
//rijndael_encrypt(&ctx->rijndael, ctx->X, ctx->X);
memcpy1(in, &ctx->X[0], 16); //Bestela ez du ondo iten
aes_encrypt( in, in, &ctx->rijndael);
memcpy1(&ctx->X[0], in, 16);
data += 16;
len -= 16;
}
/* potential last block, save it */
memcpy1(ctx->M_last, data, len);
ctx->M_n = len;
}
void AES_CMAC_Final(uint8_t digest[AES_CMAC_DIGEST_LENGTH], AES_CMAC_CTX *ctx)
{
uint8_t K[16];
uint8_t in[16];
/* generate subkey K1 */
memset1(K, '\0', 16);
//rijndael_encrypt(&ctx->rijndael, K, K);
aes_encrypt( K, K, &ctx->rijndael);
if (K[0] & 0x80) {
LSHIFT(K, K);
K[15] ^= 0x87;
} else
LSHIFT(K, K);
if (ctx->M_n == 16) {
/* last block was a complete block */
XOR(K, ctx->M_last);
} else {
/* generate subkey K2 */
if (K[0] & 0x80) {
LSHIFT(K, K);
K[15] ^= 0x87;
} else
LSHIFT(K, K);
/* padding(M_last) */
ctx->M_last[ctx->M_n] = 0x80;
while (++ctx->M_n < 16)
ctx->M_last[ctx->M_n] = 0;
XOR(K, ctx->M_last);
}
XOR(ctx->M_last, ctx->X);
//rijndael_encrypt(&ctx->rijndael, ctx->X, digest);
memcpy1(in, &ctx->X[0], 16); //Bestela ez du ondo iten
aes_encrypt(in, digest, &ctx->rijndael);
memset1(K, 0, sizeof K);
}

View File

@@ -0,0 +1,63 @@
/**************************************************************************
Copyright (C) 2009 Lander Casado, Philippas Tsigas
All rights reserved.
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files
(the "Software"), to deal with the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimers. Redistributions in
binary form must reproduce the above copyright notice, this list of
conditions and the following disclaimers in the documentation and/or
other materials provided with the distribution.
In no event shall the authors or copyright holders be liable for any special,
incidental, indirect or consequential damages of any kind, or any damages
whatsoever resulting from loss of use, data or profits, whether or not
advised of the possibility of damage, and on any theory of liability,
arising out of or in connection with the use or performance of this software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS WITH THE SOFTWARE
*****************************************************************************/
#ifndef _CMAC_H_
#define _CMAC_H_
#include "aes.h"
#define AES_CMAC_KEY_LENGTH 16
#define AES_CMAC_DIGEST_LENGTH 16
typedef struct _AES_CMAC_CTX {
aes_context rijndael;
uint8_t X[16];
uint8_t M_last[16];
uint32_t M_n;
} AES_CMAC_CTX;
//#include <sys/cdefs.h>
//__BEGIN_DECLS
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_Update(AES_CMAC_CTX * ctx, const uint8_t * data, uint32_t len);
// __attribute__((__bounded__(__string__,2,3)));
void AES_CMAC_Final(uint8_t digest[AES_CMAC_DIGEST_LENGTH], AES_CMAC_CTX * ctx);
// __attribute__((__bounded__(__minbytes__,1,AES_CMAC_DIGEST_LENGTH)));
//__END_DECLS
#endif /* _CMAC_H_ */

View File

@@ -0,0 +1,417 @@
/*
/ _____) _ | |
( (____ _____ ____ _| |_ _____ ____| |__
\____ \| ___ | (_ _) ___ |/ ___) _ \
_____) ) ____| | | || |_| ____( (___| | | |
(______/|_____)_|_|_| \__)_____)\____)_| |_|
(C)2013 Semtech
___ _____ _ ___ _ _____ ___ ___ ___ ___
/ __|_ _/_\ / __| |/ / __/ _ \| _ \/ __| __|
\__ \ | |/ _ \ (__| ' <| _| (_) | / (__| _|
|___/ |_/_/ \_\___|_|\_\_| \___/|_|_\\___|___|
embedded.connectivity.solutions===============
Description: Secure Element software implementation
License: Revised BSD License, see LICENSE.TXT file include in the project
Maintainer: Miguel Luis ( Semtech ), Gregory Cristian ( Semtech ),
Daniel Jaeckle ( STACKFORCE ), Johannes Bruder ( STACKFORCE )
*/
#include "secure-element.h"
#include <stdlib.h>
#include <stdint.h>
#include "LoRaMacCrypto.h"
#include "utilities.h"
#include "aes.h"
#include "cmac.h"
#include "radio.h"
#define NUM_OF_KEYS 24
#define KEY_SIZE 16
/*!
* Identifier value pair type for Keys
*/
typedef struct sKey
{
/*
* Key identifier
*/
KeyIdentifier_t KeyID;
/*
* Key value
*/
uint8_t KeyValue[KEY_SIZE];
} 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];
/*
* AES computation context variable
*/
aes_context AesContext;
/*
* CMAC computation context variable
*/
AES_CMAC_CTX AesCmacCtx[1];
/*
* Key List
*/
Key_t KeyList[NUM_OF_KEYS];
}SecureElementNvCtx_t;
/*
* Module context
*/
static SecureElementNvCtx_t SeNvmCtx;
static SecureElementNvmEvent SeNvmCtxChanged;
/*
* Local functions
*/
/*
* 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
*/
static 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];
AES_CMAC_Init( SeNvmCtx.AesCmacCtx );
Key_t* keyItem;
SecureElementStatus_t retval = GetKeyByID( keyID, &keyItem );
if( retval == SECURE_ELEMENT_SUCCESS )
{
AES_CMAC_SetKey( SeNvmCtx.AesCmacCtx, keyItem->KeyValue );
if( micBxBuffer != NULL )
{
AES_CMAC_Update( SeNvmCtx.AesCmacCtx, micBxBuffer, 16 );
}
AES_CMAC_Update( SeNvmCtx.AesCmacCtx, buffer, size );
AES_CMAC_Final( Cmac, SeNvmCtx.AesCmacCtx );
// Bring into the required format
*cmac = ( uint32_t )( ( uint32_t ) Cmac[3] << 24 | ( uint32_t ) Cmac[2] << 16 | ( uint32_t ) Cmac[1] << 8 | ( uint32_t ) Cmac[0] );
}
return retval;
}
/*
* API functions
*/
SecureElementStatus_t SecureElementInit( SecureElementNvmEvent seNvmCtxChanged )
{
uint8_t itr = 0;
uint8_t zeroKey[16] = { 0 };
// Initialize with defaults
SeNvmCtx.KeyList[itr++].KeyID = APP_KEY;
SeNvmCtx.KeyList[itr++].KeyID = GEN_APP_KEY;
SeNvmCtx.KeyList[itr++].KeyID = NWK_KEY;
SeNvmCtx.KeyList[itr++].KeyID = J_S_INT_KEY;
SeNvmCtx.KeyList[itr++].KeyID = J_S_ENC_KEY;
SeNvmCtx.KeyList[itr++].KeyID = F_NWK_S_INT_KEY;
SeNvmCtx.KeyList[itr++].KeyID = S_NWK_S_INT_KEY;
SeNvmCtx.KeyList[itr++].KeyID = NWK_S_ENC_KEY;
SeNvmCtx.KeyList[itr++].KeyID = APP_S_KEY;
SeNvmCtx.KeyList[itr++].KeyID = MC_ROOT_KEY;
SeNvmCtx.KeyList[itr++].KeyID = MC_KE_KEY;
SeNvmCtx.KeyList[itr++].KeyID = MC_KEY_0;
SeNvmCtx.KeyList[itr++].KeyID = MC_APP_S_KEY_0;
SeNvmCtx.KeyList[itr++].KeyID = MC_NWK_S_KEY_0;
SeNvmCtx.KeyList[itr++].KeyID = MC_KEY_1;
SeNvmCtx.KeyList[itr++].KeyID = MC_APP_S_KEY_1;
SeNvmCtx.KeyList[itr++].KeyID = MC_NWK_S_KEY_1;
SeNvmCtx.KeyList[itr++].KeyID = MC_KEY_2;
SeNvmCtx.KeyList[itr++].KeyID = MC_APP_S_KEY_2;
SeNvmCtx.KeyList[itr++].KeyID = MC_NWK_S_KEY_2;
SeNvmCtx.KeyList[itr++].KeyID = MC_KEY_3;
SeNvmCtx.KeyList[itr++].KeyID = MC_APP_S_KEY_3;
SeNvmCtx.KeyList[itr++].KeyID = MC_NWK_S_KEY_3;
SeNvmCtx.KeyList[itr].KeyID = SLOT_RAND_ZERO_KEY;
// Set standard keys
memcpy1( SeNvmCtx.KeyList[itr].KeyValue, zeroKey, KEY_SIZE );
memset1( SeNvmCtx.DevEui, 0, SE_EUI_SIZE );
memset1( SeNvmCtx.JoinEui, 0, SE_EUI_SIZE );
// 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 )
{
if( key == NULL )
{
return SECURE_ELEMENT_ERROR_NPE;
}
for( uint8_t i = 0; i < NUM_OF_KEYS; i++ )
{
if( SeNvmCtx.KeyList[i].KeyID == keyID )
{
if( ( keyID == MC_KEY_0 ) || ( keyID == MC_KEY_1 ) || ( keyID == MC_KEY_2 ) || ( keyID == MC_KEY_3 ) )
{ // Decrypt the key if its a Mckey
SecureElementStatus_t retval = SECURE_ELEMENT_ERROR;
uint8_t decryptedKey[16] = { 0 };
retval = SecureElementAesEncrypt( key, 16, MC_KE_KEY, decryptedKey );
memcpy1( SeNvmCtx.KeyList[i].KeyValue, decryptedKey, KEY_SIZE );
SeNvmCtxChanged( );
return retval;
}
else
{
memcpy1( SeNvmCtx.KeyList[i].KeyValue, key, KEY_SIZE );
SeNvmCtxChanged( );
return SECURE_ELEMENT_SUCCESS;
}
}
}
return SECURE_ELEMENT_ERROR_INVALID_KEY_ID;
}
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;
}
memset1( SeNvmCtx.AesContext.ksch, '\0', 240 );
Key_t* pItem;
SecureElementStatus_t retval = GetKeyByID( keyID, &pItem );
if( retval == SECURE_ELEMENT_SUCCESS )
{
aes_set_key( pItem->KeyValue, 16, &SeNvmCtx.AesContext );
uint8_t block = 0;
while( size != 0 )
{
aes_encrypt( &buffer[block], &encBuffer[block], &SeNvmCtx.AesContext );
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;
}
SecureElementStatus_t retval = SECURE_ELEMENT_ERROR;
uint8_t key[16] = { 0 };
// In case of MC_KE_KEY, prevent other keys than NwkKey or AppKey for LoRaWAN 1.1 or later
if( targetKeyID == MC_KE_KEY )
{
if( ( ( rootKeyID == APP_KEY ) && ( version.Fields.Minor == 0 ) ) || ( rootKeyID == NWK_KEY ) )
{
return SECURE_ELEMENT_ERROR_INVALID_KEY_ID;
}
}
// Derive key
retval = SecureElementAesEncrypt( input, 16, rootKeyID, key );
if( retval != SECURE_ELEMENT_SUCCESS )
{
return retval;
}
// Store key
retval = SecureElementSetKey( targetKeyID, key );
if( retval != SECURE_ELEMENT_SUCCESS )
{
return retval;
}
return SECURE_ELEMENT_SUCCESS;
}
SecureElementStatus_t SecureElementRandomNumber( uint32_t* randomNum )
{
if( randomNum == NULL )
{
return SECURE_ELEMENT_ERROR_NPE;
}
*randomNum = Radio.Random( );
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;
}

View File

@@ -0,0 +1,25 @@
--- Revised BSD License ---
Copyright (c) 2013, SEMTECH S.A.
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 Semtech corporation 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 SEMTECH S.A. 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.

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,131 @@
/*!
* \file LoRaMacAdr.c
*
* \brief LoRa MAC ADR implementation
*
* \copyright Revised BSD License, see section \ref LICENSE.
*
* \code
* ______ _
* / _____) _ | |
* ( (____ _____ ____ _| |_ _____ ____| |__
* \____ \| ___ | (_ _) ___ |/ ___) _ \
* _____) ) ____| | | || |_| ____( (___| | | |
* (______/|_____)_|_|_| \__)_____)\____)_| |_|
* (C)2013-2017 Semtech
*
* ___ _____ _ ___ _ _____ ___ ___ ___ ___
* / __|_ _/_\ / __| |/ / __/ _ \| _ \/ __| __|
* \__ \ | |/ _ \ (__| ' <| _| (_) | / (__| _|
* |___/ |_/_/ \_\___|_|\_\_| \___/|_|_\\___|___|
* embedded.connectivity.solutions===============
*
* \endcode
*
* \author Miguel Luis ( Semtech )
*
* \author Gregory Cristian ( Semtech )
*
* \author Daniel Jaeckle ( STACKFORCE )
*
* \author Johannes Bruder ( STACKFORCE )
*/
#include "utilities.h"
#include "region/Region.h"
#include "LoRaMacAdr.h"
static bool CalcNextV10X( CalcNextAdrParams_t* adrNext, int8_t* drOut, int8_t* txPowOut, uint32_t* adrAckCounter )
{
bool adrAckReq = false;
int8_t datarate = adrNext->Datarate;
int8_t txPower = adrNext->TxPower;
int8_t minTxDatarate;
GetPhyParams_t getPhy;
PhyParam_t phyParam;
// Report back the adr ack counter
*adrAckCounter = adrNext->AdrAckCounter;
if( adrNext->AdrEnabled == true )
{
// Query minimum TX Datarate
getPhy.Attribute = PHY_MIN_TX_DR;
getPhy.UplinkDwellTime = adrNext->UplinkDwellTime;
phyParam = RegionGetPhyParam( adrNext->Region, &getPhy );
minTxDatarate = phyParam.Value;
datarate = MAX( datarate, minTxDatarate );
if( datarate == minTxDatarate )
{
*adrAckCounter = 0;
adrAckReq = false;
}
else
{
if( adrNext->AdrAckCounter >= adrNext->AdrAckLimit )
{
adrAckReq = true;
}
else
{
adrAckReq = false;
}
if( adrNext->AdrAckCounter >= ( adrNext->AdrAckLimit + adrNext->AdrAckDelay ) )
{
// Set TX Power to maximum
getPhy.Attribute = PHY_MAX_TX_POWER;
phyParam = RegionGetPhyParam( adrNext->Region, &getPhy );
txPower = phyParam.Value;
if( ( adrNext->AdrAckCounter % adrNext->AdrAckDelay ) == 1 )
{
// Decrease the datarate
getPhy.Attribute = PHY_NEXT_LOWER_TX_DR;
getPhy.Datarate = datarate;
getPhy.UplinkDwellTime = adrNext->UplinkDwellTime;
phyParam = RegionGetPhyParam( adrNext->Region, &getPhy );
datarate = phyParam.Value;
if( datarate == minTxDatarate )
{
// We must set adrAckReq to false as soon as we reach the lowest datarate
adrAckReq = false;
if( adrNext->UpdateChanMask == true )
{
InitDefaultsParams_t params;
params.Type = INIT_TYPE_RESTORE_DEFAULT_CHANNELS;
RegionInitDefaults( adrNext->Region, &params );
}
}
}
}
}
}
*drOut = datarate;
*txPowOut = txPower;
return adrAckReq;
}
/*!
* \brief Calculates the next datarate to set, when ADR is on or off.
*
* \param [IN] adrNext Pointer to the function parameters.
*
* \param [OUT] drOut The calculated datarate for the next TX.
*
* \param [OUT] txPowOut The TX power for the next TX.
*
* \param [OUT] adrAckCounter The calculated ADR acknowledgement counter.
*
* \retval Returns true, if an ADR request should be performed.
*/
bool LoRaMacAdrCalcNext( CalcNextAdrParams_t* adrNext, int8_t* drOut, int8_t* txPowOut, uint32_t* adrAckCounter )
{
if( adrNext->Version.Fields.Minor == 0 )
{
return CalcNextV10X( adrNext, drOut, txPowOut, adrAckCounter );
}
return false;
}

View File

@@ -0,0 +1,104 @@
/*!
* \file LoRaMacAdr.h
*
* \brief LoRa MAC ADR implementation
*
* \copyright Revised BSD License, see section \ref LICENSE.
*
* \code
* ______ _
* / _____) _ | |
* ( (____ _____ ____ _| |_ _____ ____| |__
* \____ \| ___ | (_ _) ___ |/ ___) _ \
* _____) ) ____| | | || |_| ____( (___| | | |
* (______/|_____)_|_|_| \__)_____)\____)_| |_|
* (C)2013-2017 Semtech
*
* ___ _____ _ ___ _ _____ ___ ___ ___ ___
* / __|_ _/_\ / __| |/ / __/ _ \| _ \/ __| __|
* \__ \ | |/ _ \ (__| ' <| _| (_) | / (__| _|
* |___/ |_/_/ \_\___|_|\_\_| \___/|_|_\\___|___|
* embedded.connectivity.solutions===============
*
* \endcode
*
* \author Miguel Luis ( Semtech )
*
* \author Gregory Cristian ( Semtech )
*
* \author Daniel Jaeckle ( STACKFORCE )
*
* \author Johannes Bruder ( STACKFORCE )
*
* \defgroup LORAMACADR LoRa MAC ADR implementation
* Implementation of the ADR algorithm for LoRa.
* \{
*/
#ifndef __LORAMACADR_H__
#define __LORAMACADR_H__
/*! \} defgroup LORAMACADR */
/*
* Parameter structure for the function CalcNextAdr.
*/
typedef struct sCalcNextAdrParams
{
/*!
* LoRaWAN Minor Version 1.X
*/
Version_t Version;
/*!
* Set to true, if the function should update the channels mask.
*/
bool UpdateChanMask;
/*!
* Set to true, if ADR is enabled.
*/
bool AdrEnabled;
/*!
* ADR ack counter.
*/
uint32_t AdrAckCounter;
/*!
* ADR Ack limit
*/
uint16_t AdrAckLimit;
/*!
* ADR Ack delay
*/
uint16_t AdrAckDelay;
/*!
* Datarate used currently.
*/
int8_t Datarate;
/*!
* TX power used currently.
*/
int8_t TxPower;
/*!
* UplinkDwellTime
*/
uint8_t UplinkDwellTime;
/*!
* Region
*/
LoRaMacRegion_t Region;
}CalcNextAdrParams_t;
/*!
* \brief Calculates the next datarate to set, when ADR is on or off.
*
* \param [IN] adrNext Pointer to the function parameters.
*
* \param [OUT] drOut The calculated datarate for the next TX.
*
* \param [OUT] txPowOut The TX power for the next TX.
*
* \param [OUT] adrAckCounter The calculated ADR acknowledgement counter.
*
* \retval Returns true, if an ADR request should be performed.
*/
bool LoRaMacAdrCalcNext( CalcNextAdrParams_t* adrNext, int8_t* drOut, int8_t* txPowOut, uint32_t* adrAckCounter );
#endif // __LORAMACADR_H__

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,670 @@
/*!
* \file LoRaMacClassB.h
*
* \brief LoRa MAC Class B layer implementation
*
* \copyright Revised BSD License, see section \ref LICENSE.
*
* \code
* ______ _
* / _____) _ | |
* ( (____ _____ ____ _| |_ _____ ____| |__
* \____ \| ___ | (_ _) ___ |/ ___) _ \
* _____) ) ____| | | || |_| ____( (___| | | |
* (______/|_____)_|_|_| \__)_____)\____)_| |_|
* (C)2013 Semtech
*
* ___ _____ _ ___ _ _____ ___ ___ ___ ___
* / __|_ _/_\ / __| |/ / __/ _ \| _ \/ __| __|
* \__ \ | |/ _ \ (__| ' <| _| (_) | / (__| _|
* |___/ |_/_/ \_\___|_|\_\_| \___/|_|_\\___|___|
* embedded.connectivity.solutions===============
*
* \endcode
*
* \author Miguel Luis ( Semtech )
*
* \author Gregory Cristian ( Semtech )
*
* \author Daniel Jaeckle ( STACKFORCE )
*
* \defgroup LORAMACCLASSB LoRa MAC Class B layer implementation
* This module specifies the API implementation of the LoRaMAC Class B layer.
* This is a placeholder for a detailed description of the LoRaMac
* layer and the supported features.
* \{
*/
#ifndef __LORAMACCLASSB_H__
#define __LORAMACCLASSB_H__
#include "systime.h"
#include "LoRaMacTypes.h"
/*!
* States of the class B beacon acquisition and tracking
*/
typedef enum eBeaconState
{
/*!
* Initial state to acquire the beacon
*/
BEACON_STATE_ACQUISITION,
/*!
* Beacon acquisition state when a time reference is available
*/
BEACON_STATE_ACQUISITION_BY_TIME,
/*!
* Handles the state when the beacon reception fails
*/
BEACON_STATE_TIMEOUT,
/*!
* Handles the state when the beacon was missed due to an uplink
*/
BEACON_STATE_BEACON_MISSED,
/*!
* Reacquisition state which applies the algorithm to enlarge the reception
* windows
*/
BEACON_STATE_REACQUISITION,
/*!
* The node has locked a beacon successfully
*/
BEACON_STATE_LOCKED,
/*!
* The beacon state machine is stopped due to operations with higher priority
*/
BEACON_STATE_HALT,
/*!
* The node currently operates in the beacon window and is idle. In this
* state, the temperature measurement takes place
*/
BEACON_STATE_IDLE,
/*!
* The node operates in the guard time of class B
*/
BEACON_STATE_GUARD,
/*!
* The node is in receive mode to lock a beacon
*/
BEACON_STATE_RX,
/*!
* The nodes switches the device class
*/
BEACON_STATE_LOST,
}BeaconState_t;
/*!
* States of the class B ping slot mechanism
*/
typedef enum ePingSlotState
{
/*!
* Calculation of the ping slot offset
*/
PINGSLOT_STATE_CALC_PING_OFFSET,
/*!
* State to set the timer to open the next ping slot
*/
PINGSLOT_STATE_SET_TIMER,
/*!
* The node is in idle state
*/
PINGSLOT_STATE_IDLE,
/*!
* The node opens up a ping slot window
*/
PINGSLOT_STATE_RX,
}PingSlotState_t;
/*!
* Class B ping slot context structure
*/
typedef struct sPingSlotContext
{
/*!
* Ping slot length time in ms
*/
uint32_t PingSlotWindow;
/*!
* Ping offset
*/
uint16_t PingOffset;
/*!
* Current symbol timeout. The node enlarges this variable in case of beacon
* loss.
*/
uint16_t SymbolTimeout;
/*!
* The multicast channel which will be enabled next.
*/
MulticastCtx_t *NextMulticastChannel;
}PingSlotContext_t;
/*!
* Class B beacon context structure
*/
typedef struct sBeaconContext
{
struct sBeaconCtrl
{
/*!
* Set if the node receives beacons
*/
uint8_t BeaconMode : 1;
/*!
* Set if the node has acquired the beacon
*/
uint8_t BeaconAcquired : 1;
/*!
* Set if a beacon delay was set for the beacon acquisition
*/
uint8_t BeaconDelaySet : 1;
/*!
* Set if a beacon channel was set for the beacon acquisition
*/
uint8_t BeaconChannelSet : 1;
/*!
* Set if beacon acquisition is pending
*/
uint8_t AcquisitionPending : 1;
/*!
* Set if the beacon state machine will be resumed
*/
uint8_t ResumeBeaconing : 1;
}Ctrl;
/*!
* Current temperature
*/
float Temperature;
/*!
* Beacon time received with the beacon frame
*/
SysTime_t BeaconTime;
/*!
* Time when the last beacon was received
*/
SysTime_t LastBeaconRx;
/*!
* Time when the next beacon will be received
*/
SysTime_t NextBeaconRx;
/*!
* This is the time where the RX window will be opened.
* Its base is NextBeaconRx with temperature compensations
* and RX window movement.
*/
TimerTime_t NextBeaconRxAdjusted;
/*!
* Current symbol timeout. The node enlarges this variable in case of beacon
* loss.
*/
uint16_t SymbolTimeout;
/*!
* Specifies how much time the beacon window will be moved.
*/
TimerTime_t BeaconWindowMovement;
/*!
* Beacon timing channel for next beacon
*/
uint8_t BeaconTimingChannel;
/*!
* Delay for next beacon in ms
*/
TimerTime_t BeaconTimingDelay;
TimerTime_t TimeStamp;
}BeaconContext_t;
/*!
* Data structure which contains the callbacks
*/
typedef struct sLoRaMacClassBCallback
{
/*!
* \brief Measures the temperature level
*
* \retval Temperature level
*/
uint16_t ( *GetTemperatureLevel )( void );
/*!
*\brief Will be called each time a Radio IRQ is handled by the MAC
* layer.
*
*\warning Runs in a IRQ context. Should only change variables state.
*/
void ( *MacProcessNotify )( void );
}LoRaMacClassBCallback_t;
/*!
* Data structure which pointers to the properties LoRaMAC
*/
typedef struct sLoRaMacClassBParams
{
/*!
* Pointer to the MlmeIndication structure
*/
MlmeIndication_t *MlmeIndication;
/*!
* Pointer to the McpsIndication structure
*/
McpsIndication_t *McpsIndication;
/*!
* Pointer to the MlmeConfirm structure
*/
MlmeConfirm_t *MlmeConfirm;
/*!
* Pointer to the LoRaMacFlags structure
*/
LoRaMacFlags_t *LoRaMacFlags;
/*!
* Pointer to the LoRaMac device address
*/
uint32_t *LoRaMacDevAddr;
/*!
* Pointer to the LoRaMac region definition
*/
LoRaMacRegion_t *LoRaMacRegion;
/*!
* Pointer to the LoRaMacParams structure
*/
LoRaMacParams_t *LoRaMacParams;
/*!
* Pointer to the multicast channel list
*/
MulticastCtx_t *MulticastChannels;
}LoRaMacClassBParams_t;
/*!
* Signature of callback function to be called by this module when the
* non-volatile needs to be saved.
*/
typedef void ( *LoRaMacClassBNvmEvent )( void );
/*!
* \brief Initialize LoRaWAN Class B
*
* \param [IN] classBParams Information and feedback parameter
* \param [IN] callbacks Contains the callback which the Class B implementation needs
* \param [IN] callback function which will be called when the non-volatile context needs to be saved.
*/
void LoRaMacClassBInit( LoRaMacClassBParams_t *classBParams, LoRaMacClassBCallback_t *callbacks, LoRaMacClassBNvmEvent classBNvmCtxChanged );
/*!
* Restores the internal non-volatile context from passed pointer.
*
* \param [IN] classBNvmCtx - Pointer to non-volatile class B module context to be restored.
*
* \retval - Status of the operation
*/
bool LoRaMacClassBRestoreNvmCtx( void* classBNvmCtx );
/*!
* Returns a pointer to the internal non-volatile context.
*
* \param [IN] classBNvmCtxSize - Size of the module non-volatile context
*
* \retval - Points to a structure where the module store its non-volatile context
*/
void* LoRaMacClassBGetNvmCtx( size_t* classBNvmCtxSize );
/*!
* \brief Set the state of the beacon state machine
*
* \param [IN] beaconState Beacon state.
*/
void LoRaMacClassBSetBeaconState( BeaconState_t beaconState );
/*!
* \brief Set the state of the ping slot state machine
*
* \param [IN] pingSlotState Ping slot state.
*/
void LoRaMacClassBSetPingSlotState( PingSlotState_t pingSlotState );
/*!
* \brief Set the state of the multicast slot state machine
*
* \param [IN] pingSlotState multicast slot state.
*/
void LoRaMacClassBSetMulticastSlotState( PingSlotState_t multicastSlotState );
/*!
* \brief Verifies if an acquisition procedure is in progress
*
* \retval [true, if the acquisition is in progress; false, if not]
*/
bool LoRaMacClassBIsAcquisitionInProgress( void );
/*!
* \brief State machine of the Class B for beaconing
*/
void LoRaMacClassBBeaconTimerEvent( void* context );
/*!
* \brief State machine of the Class B for ping slots
*/
void LoRaMacClassBPingSlotTimerEvent( void* context );
/*!
* \brief State machine of the Class B for multicast slots
*/
void LoRaMacClassBMulticastSlotTimerEvent( void* context );
/*!
* \brief Receives and decodes the beacon frame
*
* \param [IN] payload Pointer to the payload
* \param [IN] size Size of the payload
* \retval [true, if the node has received a beacon; false, if not]
*/
bool LoRaMacClassBRxBeacon( uint8_t *payload, uint16_t size );
/*!
* \brief The function validates, if the node expects a beacon
* at the current time.
*
* \retval [true, if the node expects a beacon; false, if not]
*/
bool LoRaMacClassBIsBeaconExpected( void );
/*!
* \brief The function validates, if the node expects a ping slot
* at the current time.
*
* \retval [true, if the node expects a ping slot; false, if not]
*/
bool LoRaMacClassBIsPingExpected( void );
/*!
* \brief The function validates, if the node expects a multicast slot
* at the current time.
*
* \retval [true, if the node expects a multicast slot; false, if not]
*/
bool LoRaMacClassBIsMulticastExpected( void );
/*!
* \brief Verifies if the acquisition pending bit is set
*
* \retval [true, if the bit is set; false, if not]
*/
bool LoRaMacClassBIsAcquisitionPending( void );
/*!
* \brief Verifies if the beacon mode active bit is set
*
* \retval [true, if the bit is set; false, if not]
*/
bool LoRaMacClassBIsBeaconModeActive( void );
/*!
* \brief Stops the beacon and ping slot operation
*/
void LoRaMacClassBHaltBeaconing( void );
/*!
* \brief Resumes the beacon and ping slot operation
*/
void LoRaMacClassBResumeBeaconing( void );
/*!
* \brief Sets the periodicity of the ping slots
*
* \param [IN] periodicity Periodicity
*/
void LoRaMacClassBSetPingSlotInfo( uint8_t periodicity );
/*!
* \brief Switches the device class
*
* \param [IN] nextClass Device class to switch to
*
* \retval LoRaMacStatus_t Status of the operation.
*/
LoRaMacStatus_t LoRaMacClassBSwitchClass( DeviceClass_t nextClass );
/*!
* \brief LoRaMAC ClassB MIB-Get
*
* \details The mac information base service to get attributes of the LoRaMac
* Class B layer.
*
* \param [IN] mibRequest - MIB-GET-Request to perform. Refer to \ref MibRequestConfirm_t.
*
* \retval LoRaMacStatus_t Status of the operation. Possible returns are:
* \ref LORAMAC_STATUS_OK,
* \ref LORAMAC_STATUS_SERVICE_UNKNOWN,
* \ref LORAMAC_STATUS_PARAMETER_INVALID.
*/
LoRaMacStatus_t LoRaMacClassBMibGetRequestConfirm( MibRequestConfirm_t *mibGet );
/*!
* \brief LoRaMAC Class B MIB-Set
*
* \details The mac information base service to set attributes of the LoRaMac
* Class B layer.
*
* \param [IN] mibRequest - MIB-SET-Request to perform. Refer to \ref MibRequestConfirm_t.
*
* \retval LoRaMacStatus_t Status of the operation. Possible returns are:
* \ref LORAMAC_STATUS_OK,
* \ref LORAMAC_STATUS_BUSY,
* \ref LORAMAC_STATUS_SERVICE_UNKNOWN,
* \ref LORAMAC_STATUS_PARAMETER_INVALID.
*/
LoRaMacStatus_t LoRaMacMibClassBSetRequestConfirm( MibRequestConfirm_t *mibSet );
/*!
* \brief This function handles the PING_SLOT_FREQ_ANS
*/
void LoRaMacClassBPingSlotInfoAns( void );
/*!
* \brief This function handles the PING_SLOT_CHANNEL_REQ
*
* \param [IN] datarate Device class to switch to
* \param [IN] frequency Device class to switch to
*
* \retval Status for the MAC answer.
*/
uint8_t LoRaMacClassBPingSlotChannelReq( uint8_t datarate, uint32_t frequency );
/*!
* \brief This function handles the BEACON_TIMING_ANS
*
* \param [IN] beaconTimingDelay The beacon timing delay
* \param [IN] beaconTimingChannel The beacon timing channel
* \param [IN] lastRxDone The time of the last frame reception
*/
void LoRaMacClassBBeaconTimingAns( uint16_t beaconTimingDelay, uint8_t beaconTimingChannel, TimerTime_t lastRxDone );
/*!
* \brief This function handles the ClassB DEVICE_TIME_ANS
*/
void LoRaMacClassBDeviceTimeAns( void );
/*!
* \brief This function handles the BEACON_FREQ_REQ
*
* \param [IN] frequency Frequency to set
*
* \retval [true, if MAC shall send an answer; false, if not]
*/
bool LoRaMacClassBBeaconFreqReq( uint32_t frequency );
/*!
* \brief Queries the ping slot window time
*
* \param [IN] txTimeOnAir TX time on air for the next uplink
*
* \retval Returns the time the uplink should be delayed
*/
TimerTime_t LoRaMacClassBIsUplinkCollision( TimerTime_t txTimeOnAir );
/*!
* \brief Stops the timers for the RX slots. This includes the
* timers for ping and multicast slots.
*/
void LoRaMacClassBStopRxSlots( void );
/*!
* \brief Starts the timers for the RX slots. This includes the
* timers for ping and multicast slots.
*/
void LoRaMacClassBStartRxSlots( void );
/*!
* \brief Starts the timers for the RX slots. This includes the
* timers for ping and multicast slots.
*
* \param [IN] periodicity Downlink periodicity
*
* \param [IN] multicastChannel Related multicast channel
*/
void LoRaMacClassBSetMulticastPeriodicity( MulticastCtx_t* multicastChannel );
void LoRaMacClassBProcess( void );
/*
* LoRaMac Class B Context structure for NVM parameters
* related to ping slots
*/
typedef struct sLoRaMacClassBPingSlotNvmCtx
{
struct sPingSlotCtrlNvm
{
/*!
* 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;
/*!
* Number of ping slots
*/
uint8_t PingNb;
/*!
* Period of the ping slots
*/
uint16_t PingPeriod;
/*!
* Reception frequency of the ping slot windows
*/
uint32_t Frequency;
/*!
* Datarate of the ping slot
*/
int8_t Datarate;
} LoRaMacClassBPingSlotNvmCtx_t;
/*
* LoRaMac Class B Context structure for NVM parameters
* related to beaconing
*/
typedef struct sLoRaMacClassBBeaconNvmCtx
{
struct sBeaconCtrlNvm
{
/*!
* Set if the node has a custom frequency for beaconing and ping slots
*/
uint8_t CustomFreq : 1;
}Ctrl;
/*!
* Beacon reception frequency
*/
uint32_t Frequency;
/*!
* State of the beaconing mechanism
*/
BeaconState_t BeaconState;
/*!
* Time when the last beacon was received
*/
SysTime_t LastBeaconRx;
/*!
* Data structure for the gateway specific part. The
* content of the values may differ for each gateway
*/
struct sGwSpecific GwSpecific;
} LoRaMacClassBBeaconNvmCtx_t;
/*
* LoRaMac Class B Context structure
*/
typedef struct sLoRaMacClassBNvmCtx
{
/*!
* Class B ping slot context
*/
LoRaMacClassBPingSlotNvmCtx_t PingSlotCtx;
/*!
* Class B beacon context
*/
LoRaMacClassBBeaconNvmCtx_t BeaconCtx;
} LoRaMacClassBNvmCtx_t;
/*
* LoRaMac Class B Context structure
*/
typedef struct sLoRaMacClassBCtx
{
/*!
* Class B ping slot context
*/
PingSlotContext_t PingSlotCtx;
/*!
* Class B beacon context
*/
BeaconContext_t BeaconCtx;
/*!
* State of the beaconing mechanism
*/
BeaconState_t BeaconState;
/*!
* State of the ping slot mechanism
*/
PingSlotState_t PingSlotState;
/*!
* State of the multicast slot mechanism
*/
PingSlotState_t MulticastSlotState;
/*!
* Timer for CLASS B beacon acquisition and tracking.
*/
TimerEvent_t BeaconTimer;
/*!
* Timer for CLASS B ping slot timer.
*/
TimerEvent_t PingSlotTimer;
/*!
* Timer for CLASS B multicast ping slot timer.
*/
TimerEvent_t MulticastSlotTimer;
/*!
* Container for the callbacks related to class b.
*/
LoRaMacClassBCallback_t LoRaMacClassBCallbacks;
/*!
* Data structure which holds the parameters which needs to be set
* in class b operation.
*/
LoRaMacClassBParams_t LoRaMacClassBParams;
/*
* Callback function to notify the upper layer about context change
*/
LoRaMacClassBNvmEvent LoRaMacClassBNvmEvent;
/*!
* Non-volatile module context.
*/
LoRaMacClassBNvmCtx_t* NvmCtx;
} LoRaMacClassBCtx_t;
#endif // __LORAMACCLASSB_H__

View File

@@ -0,0 +1,115 @@
/*!
* \file LoRaMacClassBConfig.h
*
* \brief LoRa MAC Class B configuration
*
* \copyright Revised BSD License, see section \ref LICENSE.
*
* \code
* ______ _
* / _____) _ | |
* ( (____ _____ ____ _| |_ _____ ____| |__
* \____ \| ___ | (_ _) ___ |/ ___) _ \
* _____) ) ____| | | || |_| ____( (___| | | |
* (______/|_____)_|_|_| \__)_____)\____)_| |_|
* (C)2013 Semtech
*
* ___ _____ _ ___ _ _____ ___ ___ ___ ___
* / __|_ _/_\ / __| |/ / __/ _ \| _ \/ __| __|
* \__ \ | |/ _ \ (__| ' <| _| (_) | / (__| _|
* |___/ |_/_/ \_\___|_|\_\_| \___/|_|_\\___|___|
* embedded.connectivity.solutions===============
*
* \endcode
*
* \author Miguel Luis ( Semtech )
*
* \author Gregory Cristian ( Semtech )
*
* \author Daniel Jaeckle ( STACKFORCE )
*
* \defgroup LORAMACCLASSB LoRa MAC Class B configuration
* This header file contains parameters to configure the class b operation.
* By default, all parameters are set according to the specification.
* \{
*/
#ifndef __LORAMACCLASSBCONFIG_H__
#define __LORAMACCLASSBCONFIG_H__
/*!
* Defines the beacon interval in ms
*/
#define CLASSB_BEACON_INTERVAL 128000
/*!
* Beacon reserved time in ms
*/
#define CLASSB_BEACON_RESERVED 2120
/*!
* Beacon guard time in ms
*/
#define CLASSB_BEACON_GUARD 3000
/*!
* Beacon window time in ms
*/
#define CLASSB_BEACON_WINDOW 122880
/*!
* Beacon window time in numer of slots
*/
#define CLASSB_BEACON_WINDOW_SLOTS 4096
/*!
* Ping slot length time in ms
*/
#define CLASSB_PING_SLOT_WINDOW 30
/*!
* Maximum allowed beacon less time in ms
*/
#define CLASSB_MAX_BEACON_LESS_PERIOD 7200000
/*!
* Delay time for the BeaconTimingAns in ms
*/
#define CLASSB_BEACON_DELAY_BEACON_TIMING_ANS 30
/*!
* Default symbol timeout for beacons and ping slot windows
*/
#define CLASSB_BEACON_SYMBOL_TO_DEFAULT 8
/*!
* Maximum symbol timeout for beacons
*/
#define CLASSB_BEACON_SYMBOL_TO_EXPANSION_MAX 255
/*!
* Maximum symbol timeout for ping slots
*/
#define CLASSB_PING_SLOT_SYMBOL_TO_EXPANSION_MAX 30
/*!
* Symbol expansion value for beacon windows in case of beacon
* loss in symbols
*/
#define CLASSB_BEACON_SYMBOL_TO_EXPANSION_FACTOR 2
/*!
* Defines the default window movement time
*/
#define CLASSB_WINDOW_MOVE_DEFAULT 2
/*!
* Defines the maximum time for the beacon movement
*/
#define CLASSB_WINDOW_MOVE_EXPANSION_MAX 256
/*!
* Defines the expansion factor for the beacon movement
*/
#define CLASSB_WINDOW_MOVE_EXPANSION_FACTOR 2
#endif // __LORAMACCLASSBCONFIG_H__

View File

@@ -0,0 +1,547 @@
/*
/ _____) _ | |
( (____ _____ ____ _| |_ _____ ____| |__
\____ \| ___ | (_ _) ___ |/ ___) _ \
_____) ) ____| | | || |_| ____( (___| | | |
(______/|_____)_|_|_| \__)_____)\____)_| |_|
(C)2013 Semtech
___ _____ _ ___ _ _____ ___ ___ ___ ___
/ __|_ _/_\ / __| |/ / __/ _ \| _ \/ __| __|
\__ \ | |/ _ \ (__| ' <| _| (_) | / (__| _|
|___/ |_/_/ \_\___|_|\_\_| \___/|_|_\\___|___|
embedded.connectivity.solutions===============
Description: LoRa MAC commands
License: Revised BSD License, see LICENSE.TXT file include in the project
Maintainer: Miguel Luis ( Semtech ), Daniel Jaeckle ( STACKFORCE ), Johannes Bruder ( STACKFORCE )
*/
#include "utilities.h"
#include "LoRaMacCommands.h"
#include "LoRaMacConfirmQueue.h"
/*!
* Number of MAC Command slots
*/
#define NUM_OF_MAC_COMMANDS 15
/*!
* Size of the CID field of MAC commands
*/
#define CID_FIELD_SIZE 1
/*!
* Mac Commands list structure
*/
typedef struct sMacCommandsList
{
/*
* First element of MAC command list.
*/
MacCommand_t* First;
/*
* Last element of MAC command list.
*/
MacCommand_t* Last;
} MacCommandsList_t;
/*!
* LoRaMac Commands Context structure
*/
typedef struct sLoRaMacCommandsCtx
{
/*
* List of MAC command elements
*/
MacCommandsList_t MacCommandList;
/*
* Buffer to store MAC command elements
*/
MacCommand_t MacCommandSlots[NUM_OF_MAC_COMMANDS];
/*
* Size of all MAC commands serialized as buffer
*/
size_t SerializedCmdsSize;
} LoRaMacCommandsCtx_t;
/*!
* Callback function to notify the upper layer about context change
*/
static LoRaMacCommandsNvmEvent CommandsNvmCtxChanged;
/*!
* Non-volatile module context.
*/
static LoRaMacCommandsCtx_t NvmCtx;
/* Memory management functions */
/*!
* \brief Determines if a MAC command slot is free
*
* \param[IN] slot - Slot to check
* \retval - Status of the operation
*/
static bool IsSlotFree( const MacCommand_t* slot )
{
uint8_t* mem = ( uint8_t* )slot;
for( uint16_t size = 0; size < sizeof( MacCommand_t ); size++ )
{
if( mem[size] != 0x00 )
{
return false;
}
}
return true;
}
/*!
* \brief Allocates a new MAC command memory slot
*
* \retval - Pointer to slot
*/
static MacCommand_t* MallocNewMacCommandSlot( void )
{
uint8_t itr = 0;
while( IsSlotFree( ( const MacCommand_t* )&NvmCtx.MacCommandSlots[itr] ) == false )
{
itr++;
if( itr == NUM_OF_MAC_COMMANDS )
{
return 0;
}
}
return &NvmCtx.MacCommandSlots[itr];
}
/*!
* \brief Free memory slot
*
* \param[IN] slot - Slot to free
*
* \retval - Status of the operation
*/
static bool FreeMacCommandSlot( MacCommand_t* slot )
{
if( slot == 0 )
{
return false;
}
memset1( ( uint8_t* )slot, 0x00, sizeof( MacCommand_t ) );
return true;
}
/* Linked list functions */
/*!
* \brief Initialize list
*
* \param[IN] list - List that shall be initialized
* \retval - Status of the operation
*/
static bool LinkedListInit( MacCommandsList_t* list )
{
if( list == 0 )
{
return false;
}
list->First = 0;
list->Last = 0;
return true;
}
/*!
* \brief Add an element to the list
*
* \param[IN] list - List where the element shall be added.
* \param[IN] element - Element to add
* \retval - Status of the operation
*/
static bool LinkedListAdd( MacCommandsList_t* list, MacCommand_t* element )
{
if( ( list == 0 ) && ( element == 0 ) )
{
return false;
}
// Check if this is the first entry to enter the list.
if( list->First == 0 )
{
list->First = element;
}
// Check if the last entry exists and update its next point.
if( list->Last )
{
list->Last->Next = element;
}
// Update the next point of this entry.
element->Next = 0;
// Update the last entry of the list.
list->Last = element;
return true;
}
/*!
* \brief Return the previous element in the list.
*
* \param[IN] list - List
* \param[IN] element - Element where the previous element shall be searched
* \retval - Status of the operation
*/
static MacCommand_t* LinkedListGetPrevious( MacCommandsList_t* list, MacCommand_t* element )
{
if( ( list == 0 ) && ( element == 0 ) )
{
return NULL;
}
MacCommand_t* curElement;
// Start at the head of the list
curElement = list->First;
// When current element is the first of the list, there's no previous element so we can return NULL immediately.
if( element != curElement )
{
// Loop through all elements until the end is reached or the next of current is the current element.
while( ( curElement != NULL ) && ( curElement->Next != element ) )
{
curElement = curElement->Next;
}
}
else
{
curElement = NULL;
}
return curElement;
}
/*!
* \brief Remove an element from the list
*
* \param[IN] list - List where the element shall be removed from.
* \param[IN] element - Element to remove
* \retval - Status of the operation
*/
static bool LinkedListRemove( MacCommandsList_t* list, MacCommand_t* element )
{
if( ( list == 0 ) && ( element == 0 ) )
{
return false;
}
MacCommand_t* PrevElement = LinkedListGetPrevious( list, element );
if( list->First == element )
{
list->First = element->Next;
}
if( list->Last == element )
{
list->Last = PrevElement;
}
if( PrevElement != NULL )
{
PrevElement->Next = element->Next;
}
element->Next = NULL;
return true;
}
/*
* \brief Determines if a MAC command is sticky or not
*
* \param[IN] cid - MAC command identifier
*
* \retval - Status of the operation
*/
static bool IsSticky( uint8_t cid )
{
switch( cid )
{
case MOTE_MAC_DL_CHANNEL_ANS:
case MOTE_MAC_RX_PARAM_SETUP_ANS:
case MOTE_MAC_RX_TIMING_SETUP_ANS:
return true;
default:
return false;
}
}
/*
* \brief Wrapper function for the NvmCtx
*/
static void NvmCtxCallback( void )
{
if( CommandsNvmCtxChanged != NULL )
{
CommandsNvmCtxChanged( );
}
}
LoRaMacCommandStatus_t LoRaMacCommandsInit( LoRaMacCommandsNvmEvent commandsNvmCtxChanged )
{
// Initialize with default
memset1( ( uint8_t* )&NvmCtx, 0, sizeof( NvmCtx ) );
LinkedListInit( &NvmCtx.MacCommandList );
// Assign callback
CommandsNvmCtxChanged = commandsNvmCtxChanged;
return LORAMAC_COMMANDS_SUCCESS;
}
LoRaMacCommandStatus_t LoRaMacCommandsRestoreNvmCtx( void* commandsNvmCtx )
{
// Restore module context
if( commandsNvmCtx != NULL )
{
memcpy1( ( uint8_t* )&NvmCtx, ( uint8_t* )commandsNvmCtx, sizeof( NvmCtx ) );
return LORAMAC_COMMANDS_SUCCESS;
}
else
{
return LORAMAC_COMMANDS_ERROR_NPE;
}
}
void* LoRaMacCommandsGetNvmCtx( size_t* commandsNvmCtxSize )
{
*commandsNvmCtxSize = sizeof( NvmCtx );
return &NvmCtx;
}
LoRaMacCommandStatus_t LoRaMacCommandsAddCmd( uint8_t cid, uint8_t* payload, size_t payloadSize )
{
if( payload == 0 )
{
return LORAMAC_COMMANDS_ERROR_NPE;
}
MacCommand_t* newCmd;
// Allocate a memory slot
newCmd = MallocNewMacCommandSlot( );
if( newCmd == 0 )
{
return LORAMAC_COMMANDS_ERROR_MEMORY;
}
// Add it to the list of Mac commands
if( LinkedListAdd( &NvmCtx.MacCommandList, newCmd ) == false )
{
return LORAMAC_COMMANDS_ERROR;
}
// Set Values
newCmd->CID = cid;
newCmd->PayloadSize = payloadSize;
memcpy1( ( uint8_t* )newCmd->Payload, payload, payloadSize );
newCmd->IsSticky = IsSticky( cid );
NvmCtx.SerializedCmdsSize += ( CID_FIELD_SIZE + payloadSize );
NvmCtxCallback( );
return LORAMAC_COMMANDS_SUCCESS;
}
LoRaMacCommandStatus_t LoRaMacCommandsRemoveCmd( MacCommand_t* macCmd )
{
if( macCmd == NULL )
{
return LORAMAC_COMMANDS_ERROR_NPE;
}
// Remove the Mac command element from MacCommandList
if( LinkedListRemove( &NvmCtx.MacCommandList, macCmd ) == false )
{
return LORAMAC_COMMANDS_ERROR_CMD_NOT_FOUND;
}
NvmCtx.SerializedCmdsSize -= ( CID_FIELD_SIZE + macCmd->PayloadSize );
// Free the MacCommand Slot
if( FreeMacCommandSlot( macCmd ) == false )
{
return LORAMAC_COMMANDS_ERROR;
}
NvmCtxCallback( );
return LORAMAC_COMMANDS_SUCCESS;
}
LoRaMacCommandStatus_t LoRaMacCommandsGetCmd( uint8_t cid, MacCommand_t** macCmd )
{
MacCommand_t* curElement;
// Start at the head of the list
curElement = NvmCtx.MacCommandList.First;
// Loop through all elements until we find the element with the given CID
while( ( curElement != NULL ) && ( curElement->CID != cid ) )
{
curElement = curElement->Next;
}
// Update the pointer anyway
*macCmd = curElement;
// Handle error in case if we reached the end without finding it.
if( curElement == NULL )
{
return LORAMAC_COMMANDS_ERROR_CMD_NOT_FOUND;
}
return LORAMAC_COMMANDS_SUCCESS;
}
LoRaMacCommandStatus_t LoRaMacCommandsRemoveNoneStickyCmds( void )
{
MacCommand_t* curElement;
MacCommand_t* nexElement;
// Start at the head of the list
curElement = NvmCtx.MacCommandList.First;
// Loop through all elements
while( curElement != NULL )
{
if( curElement->IsSticky == false )
{
nexElement = curElement->Next;
LoRaMacCommandsRemoveCmd( curElement );
curElement = nexElement;
}
else
{
curElement = curElement->Next;
}
}
NvmCtxCallback( );
return LORAMAC_COMMANDS_SUCCESS;
}
LoRaMacCommandStatus_t LoRaMacCommandsRemoveStickyAnsCmds( void )
{
MacCommand_t* curElement;
MacCommand_t* nexElement;
// Start at the head of the list
curElement = NvmCtx.MacCommandList.First;
// Loop through all elements
while( curElement != NULL )
{
nexElement = curElement->Next;
if( IsSticky( curElement->CID ) == true )
{
LoRaMacCommandsRemoveCmd( curElement );
}
curElement = nexElement;
}
NvmCtxCallback( );
return LORAMAC_COMMANDS_SUCCESS;
}
LoRaMacCommandStatus_t LoRaMacCommandsGetSizeSerializedCmds( size_t* size )
{
if( size == NULL )
{
return LORAMAC_COMMANDS_ERROR_NPE;
}
*size = NvmCtx.SerializedCmdsSize;
return LORAMAC_COMMANDS_SUCCESS;
}
LoRaMacCommandStatus_t LoRaMacCommandsSerializeCmds( size_t availableSize, size_t* effectiveSize, uint8_t* buffer )
{
MacCommand_t* curElement = NvmCtx.MacCommandList.First;
MacCommand_t* nextElement;
uint8_t itr = 0;
if( ( buffer == NULL ) || ( effectiveSize == NULL ) )
{
return LORAMAC_COMMANDS_ERROR_NPE;
}
// Loop through all elements which fits into the buffer
while( curElement != NULL )
{
// If the next MAC command still fits into the buffer, add it.
if( ( availableSize - itr ) >= ( CID_FIELD_SIZE + curElement->PayloadSize ) )
{
buffer[itr++] = curElement->CID;
memcpy1( &buffer[itr], curElement->Payload, curElement->PayloadSize );
itr += curElement->PayloadSize;
}
else
{
break;
}
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;
}
LoRaMacCommandStatus_t LoRaMacCommandsStickyCmdsPending( bool* cmdsPending )
{
if( cmdsPending == NULL )
{
return LORAMAC_COMMANDS_ERROR_NPE;
}
MacCommand_t* curElement;
curElement = NvmCtx.MacCommandList.First;
*cmdsPending = false;
// Loop through all elements
while( curElement != NULL )
{
if( curElement->IsSticky == true )
{
// Found one sticky MAC command
*cmdsPending = true;
return LORAMAC_COMMANDS_SUCCESS;
}
curElement = curElement->Next;
}
return LORAMAC_COMMANDS_SUCCESS;
}

View File

@@ -0,0 +1,218 @@
/*!
* \file LoRaMacCommands.h
*
* \brief LoRa MAC commands
*
* \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_COMMANDS_H__
#define __LORAMAC_COMMANDS_H__
#include <stdint.h>
#include <stddef.h>
#include "LoRaMacTypes.h"
/*
* Number of MAC Command slots
*/
#define LORAMAC_COMMADS_MAX_NUM_OF_PARAMS 2
/*!
* LoRaWAN MAC Command element
*/
typedef struct sMacCommand MacCommand_t;
struct sMacCommand
{
/*!
* The pointer to the next MAC Command element in the list
*/
MacCommand_t* Next;
/*!
* MAC command identifier
*/
uint8_t CID;
/*!
* MAC command payload
*/
uint8_t Payload[LORAMAC_COMMADS_MAX_NUM_OF_PARAMS];
/*!
* Size of MAC command payload
*/
size_t PayloadSize;
/*!
* Indicates if it's a sticky MAC command
*/
bool IsSticky;
};
/*!
* LoRaMac Commands Status
*/
typedef enum eLoRaMacCommandsStatus
{
/*!
* No error occurred
*/
LORAMAC_COMMANDS_SUCCESS = 0,
/*!
* Null pointer exception
*/
LORAMAC_COMMANDS_ERROR_NPE,
/*!
* There is no memory left to add a further MAC command
*/
LORAMAC_COMMANDS_ERROR_MEMORY,
/*!
* MAC command not found.
*/
LORAMAC_COMMANDS_ERROR_CMD_NOT_FOUND,
/*!
* Unknown or corrupted command error occurred.
*/
LORAMAC_COMMANDS_ERROR_UNKNOWN_CMD,
/*!
* Undefined Error occurred
*/
LORAMAC_COMMANDS_ERROR,
}LoRaMacCommandStatus_t;
/*!
* Signature of callback function to be called by this module when the
* non-volatile needs to be saved.
*/
typedef void ( *LoRaMacCommandsNvmEvent )( void );
/*!
* \brief Initialization of LoRaMac MAC commands module
*
* \param[IN] commandsNvmCtxChanged - Callback function which will be called when the
* non-volatile context needs to be saved.
*
* \retval - Status of the operation
*/
LoRaMacCommandStatus_t LoRaMacCommandsInit( LoRaMacCommandsNvmEvent commandsNvmCtxChanged );
/*!
* Restores the internal non-volatile context from passed pointer.
*
* \param[IN] commandsNvmCtx - Pointer to non-volatile MAC commands module context to be restored.
*
* \retval - Status of the operation
*/
LoRaMacCommandStatus_t LoRaMacCommandsRestoreNvmCtx( void* commandsNvmCtx );
/*!
* Returns a pointer to the internal non-volatile context.
*
* \param[IN] commandsNvmCtxSize - Size of the module non-volatile context
*
* \retval - Points to a structure where the module store its non-volatile context
*/
void* LoRaMacCommandsGetNvmCtx( size_t* commandsNvmCtxSize );
/*!
* \brief Adds a new MAC command to be sent.
*
* \param[IN] cid - MAC command identifier
* \param[IN] payload - MAC command payload containing parameters
* \param[IN] payloadSize - Size of MAC command payload
*
* \retval - Status of the operation
*/
LoRaMacCommandStatus_t LoRaMacCommandsAddCmd( uint8_t cid, uint8_t* payload, size_t payloadSize );
/*!
* \brief Remove a MAC command.
*
* \param[OUT] cmd - MAC command
*
* \retval - Status of the operation
*/
LoRaMacCommandStatus_t LoRaMacCommandsRemoveCmd( MacCommand_t* macCmd );
/*!
* \brief Get the MAC command with corresponding CID.
*
* \param[IN] cid - MAC command identifier
* \param[OUT] cmd - MAC command
*
* \retval - Status of the operation
*/
LoRaMacCommandStatus_t LoRaMacCommandsGetCmd( uint8_t cid, MacCommand_t** macCmd );
/*!
* \brief Remove all none sticky MAC commands.
*
* \retval - Status of the operation
*/
LoRaMacCommandStatus_t LoRaMacCommandsRemoveNoneStickyCmds( void );
/*!
* \brief Remove all sticky answer MAC commands.
*
* \retval - Status of the operation
*/
LoRaMacCommandStatus_t LoRaMacCommandsRemoveStickyAnsCmds( void );
/*!
* \brief Get size of all MAC commands serialized as buffer
*
* \param[out] size - Available size of memory for MAC commands
*
* \retval - Status of the operation
*/
LoRaMacCommandStatus_t LoRaMacCommandsGetSizeSerializedCmds( size_t* size );
/*!
* \brief Get as many as possible MAC commands serialized
*
* \param[IN] availableSize - Available size of memory for MAC commands
* \param[out] effectiveSize - Size of memory which was effectively used for serializing.
* \param[out] buffer - Destination data buffer
*
* \retval - Status of the operation
*/
LoRaMacCommandStatus_t LoRaMacCommandsSerializeCmds( size_t availableSize, size_t* effectiveSize, uint8_t* buffer );
/*!
* \brief Determines if there are sticky MAC commands pending.
*
* \param[IN] cmdsPending - Indicates if there are sticky MAC commands in the queue.
*
* \retval - Status of the operation
*/
LoRaMacCommandStatus_t LoRaMacCommandsStickyCmdsPending( bool* cmdsPending );
/*! \} addtogroup LORAMAC */
#endif // __LORAMAC_COMMANDS_H__

View File

@@ -0,0 +1,344 @@
/*
/ _____) _ | |
( (____ _____ ____ _| |_ _____ ____| |__
\____ \| ___ | (_ _) ___ |/ ___) _ \
_____) ) ____| | | || |_| ____( (___| | | |
(______/|_____)_|_|_| \__)_____)\____)_| |_|
(C)2013 Semtech
___ _____ _ ___ _ _____ ___ ___ ___ ___
/ __|_ _/_\ / __| |/ / __/ _ \| _ \/ __| __|
\__ \ | |/ _ \ (__| ' <| _| (_) | / (__| _|
|___/ |_/_/ \_\___|_|\_\_| \___/|_|_\\___|___|
embedded.connectivity.solutions===============
Description: LoRa MAC confirm queue implementation
License: Revised BSD License, see LICENSE.TXT file include in the project
Maintainer: Miguel Luis ( Semtech ), Gregory Cristian ( Semtech ) and Daniel Jaeckle ( STACKFORCE )
*/
#include <stdint.h>
#include <stdbool.h>
#include <stddef.h>
#include "timer.h"
#include "utilities.h"
#include "LoRaMac.h"
#include "LoRaMacConfirmQueue.h"
/*
* LoRaMac Confirm Queue Context NVM structure
*/
typedef struct sLoRaMacConfirmQueueNvmCtx
{
/*!
* MlmeConfirm queue data structure
*/
MlmeConfirmQueue_t MlmeConfirmQueue[LORA_MAC_MLME_CONFIRM_QUEUE_LEN];
/*!
* Counts the number of MlmeConfirms to process
*/
uint8_t MlmeConfirmQueueCnt;
/*!
* Variable which holds a common status
*/
LoRaMacEventInfoStatus_t CommonStatus;
} LoRaMacConfirmQueueNvmCtx_t;
/*
* LoRaMac Confirm Queue Context structure
*/
typedef struct sLoRaMacConfirmQueueCtx
{
/*!
* LoRaMac callback function primitives
*/
LoRaMacPrimitives_t* Primitives;
/*!
* Pointer to the first element of the ring buffer
*/
MlmeConfirmQueue_t* BufferStart;
/*!
* Pointer to the last element of the ring buffer
*/
MlmeConfirmQueue_t* BufferEnd;
/*
* Callback function to notify the upper layer about context change
*/
LoRaMacConfirmQueueNvmEvent LoRaMacConfirmQueueNvmEvent;
/*!
* Non-volatile module context.
*/
LoRaMacConfirmQueueNvmCtx_t* ConfirmQueueNvmCtx;
} LoRaMacConfirmQueueCtx_t;
/*
* Non-volatile module context.
*/
static LoRaMacConfirmQueueNvmCtx_t ConfirmQueueNvmCtx;
/*
* Module context.
*/
static LoRaMacConfirmQueueCtx_t ConfirmQueueCtx;
static MlmeConfirmQueue_t* IncreaseBufferPointer( MlmeConfirmQueue_t* bufferPointer )
{
if( bufferPointer == &ConfirmQueueCtx.ConfirmQueueNvmCtx->MlmeConfirmQueue[LORA_MAC_MLME_CONFIRM_QUEUE_LEN - 1] )
{
// Reset to the first element
bufferPointer = ConfirmQueueCtx.ConfirmQueueNvmCtx->MlmeConfirmQueue;
}
else
{
// Increase
bufferPointer++;
}
return bufferPointer;
}
static MlmeConfirmQueue_t* DecreaseBufferPointer( MlmeConfirmQueue_t* bufferPointer )
{
if( bufferPointer == ConfirmQueueCtx.ConfirmQueueNvmCtx->MlmeConfirmQueue )
{
// Reset to the last element
bufferPointer = &ConfirmQueueCtx.ConfirmQueueNvmCtx->MlmeConfirmQueue[LORA_MAC_MLME_CONFIRM_QUEUE_LEN - 1];
}
else
{
bufferPointer--;
}
return bufferPointer;
}
static MlmeConfirmQueue_t* GetElement( Mlme_t request, MlmeConfirmQueue_t* bufferStart, MlmeConfirmQueue_t* bufferEnd )
{
MlmeConfirmQueue_t* element = bufferStart;
while( element != bufferEnd )
{
if( element->Request == request )
{
// We have found the element
return element;
}
else
{
element = IncreaseBufferPointer( element );
}
}
return NULL;
}
void LoRaMacConfirmQueueInit( LoRaMacPrimitives_t* primitives, LoRaMacConfirmQueueNvmEvent confirmQueueNvmCtxChanged )
{
ConfirmQueueCtx.Primitives = primitives;
// Assign nvm context
ConfirmQueueCtx.ConfirmQueueNvmCtx = &ConfirmQueueNvmCtx;
// Init counter
ConfirmQueueCtx.ConfirmQueueNvmCtx->MlmeConfirmQueueCnt = 0;
// Init buffer
ConfirmQueueCtx.BufferStart = ConfirmQueueCtx.ConfirmQueueNvmCtx->MlmeConfirmQueue;
ConfirmQueueCtx.BufferEnd = ConfirmQueueCtx.ConfirmQueueNvmCtx->MlmeConfirmQueue;
memset1( ( uint8_t* )ConfirmQueueCtx.ConfirmQueueNvmCtx->MlmeConfirmQueue, 0xFF, sizeof( ConfirmQueueCtx.ConfirmQueueNvmCtx->MlmeConfirmQueue ) );
// Common status
ConfirmQueueCtx.ConfirmQueueNvmCtx->CommonStatus = LORAMAC_EVENT_INFO_STATUS_ERROR;
// Assign callback
ConfirmQueueCtx.LoRaMacConfirmQueueNvmEvent = confirmQueueNvmCtxChanged;
}
bool LoRaMacConfirmQueueRestoreNvmCtx( void* confirmQueueNvmCtx )
{
// Restore module context
if( confirmQueueNvmCtx != NULL )
{
memcpy1( ( uint8_t* )&ConfirmQueueNvmCtx, ( uint8_t* ) confirmQueueNvmCtx, sizeof( ConfirmQueueNvmCtx ) );
return true;
}
else
{
return false;
}
}
void* LoRaMacConfirmQueueGetNvmCtx( size_t* confirmQueueNvmCtxSize )
{
*confirmQueueNvmCtxSize = sizeof( ConfirmQueueNvmCtx );
return &ConfirmQueueNvmCtx;
}
bool LoRaMacConfirmQueueAdd( MlmeConfirmQueue_t* mlmeConfirm )
{
if( ConfirmQueueCtx.ConfirmQueueNvmCtx->MlmeConfirmQueueCnt >= LORA_MAC_MLME_CONFIRM_QUEUE_LEN )
{
// Protect the buffer against overwrites
return false;
}
// Add the element to the ring buffer
ConfirmQueueCtx.BufferEnd->Request = mlmeConfirm->Request;
ConfirmQueueCtx.BufferEnd->Status = mlmeConfirm->Status;
ConfirmQueueCtx.BufferEnd->RestrictCommonReadyToHandle = mlmeConfirm->RestrictCommonReadyToHandle;
ConfirmQueueCtx.BufferEnd->ReadyToHandle = false;
// Increase counter
ConfirmQueueCtx.ConfirmQueueNvmCtx->MlmeConfirmQueueCnt++;
// Update end pointer
ConfirmQueueCtx.BufferEnd = IncreaseBufferPointer( ConfirmQueueCtx.BufferEnd );
return true;
}
bool LoRaMacConfirmQueueRemoveLast( void )
{
if( ConfirmQueueCtx.ConfirmQueueNvmCtx->MlmeConfirmQueueCnt == 0 )
{
return false;
}
// Increase counter
ConfirmQueueCtx.ConfirmQueueNvmCtx->MlmeConfirmQueueCnt--;
// Update start pointer
ConfirmQueueCtx.BufferEnd = DecreaseBufferPointer( ConfirmQueueCtx.BufferEnd );
return true;
}
bool LoRaMacConfirmQueueRemoveFirst( void )
{
if( ConfirmQueueCtx.ConfirmQueueNvmCtx->MlmeConfirmQueueCnt == 0 )
{
return false;
}
// Increase counter
ConfirmQueueCtx.ConfirmQueueNvmCtx->MlmeConfirmQueueCnt--;
// Update start pointer
ConfirmQueueCtx.BufferStart = IncreaseBufferPointer( ConfirmQueueCtx.BufferStart );
return true;
}
void LoRaMacConfirmQueueSetStatus( LoRaMacEventInfoStatus_t status, Mlme_t request )
{
MlmeConfirmQueue_t* element = NULL;
if( ConfirmQueueCtx.ConfirmQueueNvmCtx->MlmeConfirmQueueCnt > 0 )
{
element = GetElement( request, ConfirmQueueCtx.BufferStart, ConfirmQueueCtx.BufferEnd );
if( element != NULL )
{
element->Status = status;
element->ReadyToHandle = true;
}
}
}
LoRaMacEventInfoStatus_t LoRaMacConfirmQueueGetStatus( Mlme_t request )
{
MlmeConfirmQueue_t* element = NULL;
if( ConfirmQueueCtx.ConfirmQueueNvmCtx->MlmeConfirmQueueCnt > 0 )
{
element = GetElement( request, ConfirmQueueCtx.BufferStart, ConfirmQueueCtx.BufferEnd );
if( element != NULL )
{
return element->Status;
}
}
return LORAMAC_EVENT_INFO_STATUS_ERROR;
}
void LoRaMacConfirmQueueSetStatusCmn( LoRaMacEventInfoStatus_t status )
{
MlmeConfirmQueue_t* element = ConfirmQueueCtx.BufferStart;
ConfirmQueueCtx.ConfirmQueueNvmCtx->CommonStatus = status;
if( ConfirmQueueCtx.ConfirmQueueNvmCtx->MlmeConfirmQueueCnt > 0 )
{
do
{
element->Status = status;
// Set the status if it is allowed to set it with a call to
// LoRaMacConfirmQueueSetStatusCmn.
if( element->RestrictCommonReadyToHandle == false )
{
element->ReadyToHandle = true;
}
element = IncreaseBufferPointer( element );
}while( element != ConfirmQueueCtx.BufferEnd );
}
}
LoRaMacEventInfoStatus_t LoRaMacConfirmQueueGetStatusCmn( void )
{
return ConfirmQueueCtx.ConfirmQueueNvmCtx->CommonStatus;
}
bool LoRaMacConfirmQueueIsCmdActive( Mlme_t request )
{
if( GetElement( request, ConfirmQueueCtx.BufferStart, ConfirmQueueCtx.BufferEnd ) != NULL )
{
return true;
}
return false;
}
void LoRaMacConfirmQueueHandleCb( MlmeConfirm_t* mlmeConfirm )
{
uint8_t nbElements = ConfirmQueueCtx.ConfirmQueueNvmCtx->MlmeConfirmQueueCnt;
bool readyToHandle = false;
MlmeConfirmQueue_t mlmeConfirmToStore;
for( uint8_t i = 0; i < nbElements; i++ )
{
mlmeConfirm->MlmeRequest = ConfirmQueueCtx.BufferStart->Request;
mlmeConfirm->Status = ConfirmQueueCtx.BufferStart->Status;
readyToHandle = ConfirmQueueCtx.BufferStart->ReadyToHandle;
if( readyToHandle == true )
{
ConfirmQueueCtx.Primitives->MacMlmeConfirm( mlmeConfirm );
}
else
{
// The request is not processed yet. Store the state.
mlmeConfirmToStore.Request = ConfirmQueueCtx.BufferStart->Request;
mlmeConfirmToStore.Status = ConfirmQueueCtx.BufferStart->Status;
mlmeConfirmToStore.RestrictCommonReadyToHandle = ConfirmQueueCtx.BufferStart->RestrictCommonReadyToHandle;
}
// Increase the pointer afterwards to prevent overwrites
LoRaMacConfirmQueueRemoveFirst( );
if( readyToHandle == false )
{
// Add a request which has not been finished again to the queue
LoRaMacConfirmQueueAdd( &mlmeConfirmToStore );
}
}
}
uint8_t LoRaMacConfirmQueueGetCnt( void )
{
return ConfirmQueueCtx.ConfirmQueueNvmCtx->MlmeConfirmQueueCnt;
}
bool LoRaMacConfirmQueueIsFull( void )
{
if( ConfirmQueueCtx.ConfirmQueueNvmCtx->MlmeConfirmQueueCnt >= LORA_MAC_MLME_CONFIRM_QUEUE_LEN )
{
return true;
}
else
{
return false;
}
}

View File

@@ -0,0 +1,195 @@
/*!
* \file LoRaMacConfirmQueue.h
*
* \brief LoRa MAC confirm queue implementation
*
* \copyright Revised BSD License, see section \ref LICENSE.
*
* \code
* ______ _
* / _____) _ | |
* ( (____ _____ ____ _| |_ _____ ____| |__
* \____ \| ___ | (_ _) ___ |/ ___) _ \
* _____) ) ____| | | || |_| ____( (___| | | |
* (______/|_____)_|_|_| \__)_____)\____)_| |_|
* (C)2013 Semtech
*
* ___ _____ _ ___ _ _____ ___ ___ ___ ___
* / __|_ _/_\ / __| |/ / __/ _ \| _ \/ __| __|
* \__ \ | |/ _ \ (__| ' <| _| (_) | / (__| _|
* |___/ |_/_/ \_\___|_|\_\_| \___/|_|_\\___|___|
* embedded.connectivity.solutions===============
*
* \endcode
*
* \author Miguel Luis ( Semtech )
*
* \author Gregory Cristian ( Semtech )
*
* \author Daniel Jaeckle ( STACKFORCE )
*
* \defgroup LORAMACCONFIRMQUEUE LoRa MAC confirm queue implementation
* This module specifies the API implementation of the LoRaMAC confirm queue.
* The confirm queue is implemented with as a ring buffer. The number of
* elements can be defined with \ref LORA_MAC_MLME_CONFIRM_QUEUE_LEN. The
* current implementation does not support multiple elements of the same
* Mlme_t type.
* \{
*/
#ifndef __LORAMAC_CONFIRMQUEUE_H__
#define __LORAMAC_CONFIRMQUEUE_H__
#include <stdbool.h>
#include <stdint.h>
#include "LoRaMac.h"
/*!
* LoRaMac MLME-Confirm queue length
*/
#define LORA_MAC_MLME_CONFIRM_QUEUE_LEN 5
/*!
* Structure to hold multiple MLME request confirm data
*/
typedef struct sMlmeConfirmQueue
{
/*!
* Holds the previously performed MLME-Request
*/
Mlme_t Request;
/*!
* Status of the operation
*/
LoRaMacEventInfoStatus_t Status;
/*!
* Set to true, if the request is ready to be handled
*/
bool ReadyToHandle;
/*!
* Set to true, if it is not permitted to set the ReadyToHandle variable
* with a function call to LoRaMacConfirmQueueSetStatusCmn.
*/
bool RestrictCommonReadyToHandle;
}MlmeConfirmQueue_t;
/*!
* Signature of callback function to be called by this module when the
* non-volatile needs to be saved.
*/
typedef void ( *LoRaMacConfirmQueueNvmEvent )( void );
/*!
* \brief Initializes the confirm queue
*
* \param [IN] primitives - Pointer to the LoRaMac primitives.
*
* \param [IN] confirmQueueNvmCtxChanged - Callback function which will be called when the
* non-volatile context needs to be saved.
*/
void LoRaMacConfirmQueueInit( LoRaMacPrimitives_t* primitives, LoRaMacConfirmQueueNvmEvent confirmQueueNvmCtxChanged );
/*!
* Restores the internal non-volatile context from passed pointer.
*
* \param [IN] confirmQueueNvmCtx - Pointer to non-volatile class B module context to be restored.
*
* \retval [true - operation was successful, false - operation failed]
*/
bool LoRaMacConfirmQueueRestoreNvmCtx( void* confirmQueueNvmCtx );
/*!
* Returns a pointer to the internal non-volatile context.
*
* \param [IN] confirmQueueNvmCtxSize - Size of the module non-volatile context
*
* \retval - Points to a structure where the module store its non-volatile context
*/
void* LoRaMacConfirmQueueGetNvmCtx( size_t* confirmQueueNvmCtxSize );
/*!
* \brief Adds an element to the confirm queue.
*
* \param [IN] mlmeConfirm - Pointer to the element to add.
*
* \retval [true - operation was successful, false - operation failed]
*/
bool LoRaMacConfirmQueueAdd( MlmeConfirmQueue_t* mlmeConfirm );
/*!
* \brief Removes the last element which was added into the queue.
*
* \retval [true - operation was successful, false - operation failed]
*/
bool LoRaMacConfirmQueueRemoveLast( void );
/*!
* \brief Removes the first element which was added to the confirm queue.
*
* \retval [true - operation was successful, false - operation failed]
*/
bool LoRaMacConfirmQueueRemoveFirst( void );
/*!
* \brief Sets the status of an element.
*
* \param [IN] status - The status to set.
*
* \param [IN] request - The related request to set the status.
*/
void LoRaMacConfirmQueueSetStatus( LoRaMacEventInfoStatus_t status, Mlme_t request );
/*!
* \brief Gets the status of an element.
*
* \param [IN] request - The request to query the status.
*
* \retval The status of the related MlmeRequest.
*/
LoRaMacEventInfoStatus_t LoRaMacConfirmQueueGetStatus( Mlme_t request );
/*!
* \brief Sets a common status for all elements in the queue.
*
* \param [IN] status - The status to set.
*/
void LoRaMacConfirmQueueSetStatusCmn( LoRaMacEventInfoStatus_t status );
/*!
* \brief Gets the common status of all elements.
*
* \retval The common status of all elements.
*/
LoRaMacEventInfoStatus_t LoRaMacConfirmQueueGetStatusCmn( void );
/*!
* \brief Verifies if a request is in the queue and active.
*
* \param [IN] request - The request to verify.
*
* \retval [true - element is in the queue, false - element is not in the queue].
*/
bool LoRaMacConfirmQueueIsCmdActive( Mlme_t request );
/*!
* \brief Handles all callbacks of active requests
*
* \param [IN] mlmeConfirm - Pointer to the generic mlmeConfirm structure.
*/
void LoRaMacConfirmQueueHandleCb( MlmeConfirm_t* mlmeConfirm );
/*!
* \brief Query number of elements in the queue.
*
* \retval Number of elements.
*/
uint8_t LoRaMacConfirmQueueGetCnt( void );
/*!
* \brief Verify if the confirm queue is full.
*
* \retval [true - queue is full, false - queue is not full].
*/
bool LoRaMacConfirmQueueIsFull( void );
#endif // __LORAMAC_CONFIRMQUEUE_H__

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,320 @@
/*!
* \file LoRaMacCrypto.h
*
* \brief LoRa MAC layer cryptographic functionality implementation
*
* \copyright Revised BSD License, see section \ref LICENSE.
*
* \code
* ______ _
* / _____) _ | |
* ( (____ _____ ____ _| |_ _____ ____| |__
* \____ \| ___ | (_ _) ___ |/ ___) _ \
* _____) ) ____| | | || |_| ____( (___| | | |
* (______/|_____)_|_|_| \__)_____)\____)_| |_|
* (C)2013-2017 Semtech
*
* ___ _____ _ ___ _ _____ ___ ___ ___ ___
* / __|_ _/_\ / __| |/ / __/ _ \| _ \/ __| __|
* \__ \ | |/ _ \ (__| ' <| _| (_) | / (__| _|
* |___/ |_/_/ \_\___|_|\_\_| \___/|_|_\\___|___|
* embedded.connectivity.solutions===============
*
* \endcode
*
* \author Miguel Luis ( Semtech )
*
* \author Gregory Cristian ( Semtech )
*
* \author Daniel Jaeckle ( STACKFORCE )
*
* \author Johannes Bruder ( STACKFORCE )
*
* addtogroup LORAMAC
* \{
*
*/
#ifndef __LORAMAC_CRYPTO_H__
#define __LORAMAC_CRYPTO_H__
#include <stdlib.h>
#include <stdint.h>
#include <stdbool.h>
#include "utilities.h"
#include "LoRaMacTypes.h"
#include "LoRaMacMessageTypes.h"
/*
* Initial value of the frame counters
*/
#define FCNT_DOWN_INITAL_VALUE 0xFFFFFFFF
/*!
* LoRaMac Cryto Status
*/
typedef enum eLoRaMacCryptoStatus
{
/*!
* No error occurred
*/
LORAMAC_CRYPTO_SUCCESS = 0,
/*!
* MIC does not match
*/
LORAMAC_CRYPTO_FAIL_MIC,
/*!
* Address does not match
*/
LORAMAC_CRYPTO_FAIL_ADDRESS,
/*!
* JoinNonce was not greater than previous one.
*/
LORAMAC_CRYPTO_FAIL_JOIN_NONCE,
/*!
* RJcount0 reached 2^16-1
*/
LORAMAC_CRYPTO_FAIL_RJCOUNT0_OVERFLOW,
/*!
* FCNT_ID is not supported
*/
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
*/
LORAMAC_CRYPTO_FAIL_PARAM,
/*!
* Null pointer exception
*/
LORAMAC_CRYPTO_ERROR_NPE,
/*!
* Invalid key identifier exception
*/
LORAMAC_CRYPTO_ERROR_INVALID_KEY_ID,
/*!
* Invalid address identifier exception
*/
LORAMAC_CRYPTO_ERROR_INVALID_ADDR_ID,
/*!
* Invalid LoRaWAN specification version
*/
LORAMAC_CRYPTO_ERROR_INVALID_VERSION,
/*!
* Incompatible buffer size
*/
LORAMAC_CRYPTO_ERROR_BUF_SIZE,
/*!
* The secure element reports an error
*/
LORAMAC_CRYPTO_ERROR_SECURE_ELEMENT_FUNC,
/*!
* Error from parser reported
*/
LORAMAC_CRYPTO_ERROR_PARSER,
/*!
* Error from serializer reported
*/
LORAMAC_CRYPTO_ERROR_SERIALIZER,
/*!
* RJcount1 reached 2^16-1 which should never happen
*/
LORAMAC_CRYPTO_ERROR_RJCOUNT1_OVERFLOW,
/*!
* Undefined Error occurred
*/
LORAMAC_CRYPTO_ERROR,
}LoRaMacCryptoStatus_t;
/*!
* Signature of callback function to be called by the LoRaMac Crypto module when the
* non-volatile context have to be stored. It is also possible to save the entire
* crypto module context.
*
*/
typedef void ( *LoRaMacCryptoNvmEvent )( void );
/*!
* Initialization of LoRaMac Crypto module
* It sets initial values of volatile variables and assigns the non-volatile context.
*
* \param[IN] cryptoNvmCtxChanged - Callback function which will be called when the
* non-volatile context have to be stored.
* \retval - Status of the operation
*/
LoRaMacCryptoStatus_t LoRaMacCryptoInit( LoRaMacCryptoNvmEvent cryptoNvmCtxChanged );
/*!
* Sets the LoRaWAN specification version to be used.
*
* \warning This function should be used for ABP only. In case of OTA the version will be set automatically.
*
* \param[IN] version - LoRaWAN specification version to be used.
*
* \retval - Status of the operation
*/
LoRaMacCryptoStatus_t LoRaMacCryptoSetLrWanVersion( Version_t version );
/*!
* Restores the internal nvm context from passed pointer.
*
* \param[IN] cryptoNmvCtx - Pointer to non-volatile crypto module context to be restored.
* \retval - Status of the operation
*/
LoRaMacCryptoStatus_t LoRaMacCryptoRestoreNvmCtx( void* cryptoNvmCtx );
/*!
* Returns a pointer to the internal non-volatile context.
*
* \param[IN] cryptoNvmCtxSize - Size of the module non-volatile context
* \retval - Points to a structure where the module store its non-volatile context
*/
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
*
* \param[IN] keyID - Key identifier
* \param[IN] key - Key value (16 byte), if its a multicast key it must be encrypted with McKEKey
* \retval - Status of the operation
*/
LoRaMacCryptoStatus_t LoRaMacCryptoSetKey( KeyIdentifier_t keyID, uint8_t* key );
/*!
* Prepares the join-request message.
* It computes the mic and add it to the message.
*
* \param[IN/OUT] macMsg - Join-request message object
* \retval - Status of the operation
*/
LoRaMacCryptoStatus_t LoRaMacCryptoPrepareJoinRequest( LoRaMacMessageJoinRequest_t* macMsg );
/*!
* Prepares a rejoin-request type 1 message.
* It computes the mic and add it to the message.
*
* \param[IN/OUT] macMsg - Rejoin message object
* \retval - Status of the operation
*/
LoRaMacCryptoStatus_t LoRaMacCryptoPrepareReJoinType1( LoRaMacMessageReJoinType1_t* macMsg );
/*!
* Prepares a rejoin-request type 0 or 2 message.
* It computes the mic and add it to the message.
*
* \param[IN/OUT] macMsg - Rejoin message object
* \retval - Status of the operation
*/
LoRaMacCryptoStatus_t LoRaMacCryptoPrepareReJoinType0or2( LoRaMacMessageReJoinType0or2_t* macMsg );
/*!
* Handles the join-accept message.
* It decrypts the message, verifies the MIC and if successful derives the session keys.
*
* \param[IN] joinReqType - Type of last join-request or rejoin which triggered the join-accept response
* \param[IN] joinEUI - Join server EUI (8 byte)
* \param[IN/OUT] macMsg - Join-accept message object
* \retval - Status of the operation
*/
LoRaMacCryptoStatus_t LoRaMacCryptoHandleJoinAccept( JoinReqIdentifier_t joinReqType, uint8_t* joinEUI, LoRaMacMessageJoinAccept_t* macMsg );
/*!
* Secures a message (encryption + integrity).
*
* \param[IN] fCntUp - Uplink sequence counter
* \param[IN] txDr - Data rate used for the transmission
* \param[IN] txCh - Index of the channel used for the transmission
* \param[IN/OUT] macMsg - Data message object
* \retval - Status of the operation
*/
LoRaMacCryptoStatus_t LoRaMacCryptoSecureMessage( uint32_t fCntUp, uint8_t txDr, uint8_t txCh, LoRaMacMessageData_t* macMsg );
/*!
* Unsecures a message (decryption + integrity verification).
*
* \param[IN] addrID - Address identifier
* \param[IN] address - Address
* \param[IN] fCntID - Frame counter identifier
* \param[IN] fCntDown - Downlink sequence counter
* \param[IN/OUT] macMsg - Data message object
* \retval - Status of the operation
*/
LoRaMacCryptoStatus_t LoRaMacCryptoUnsecureMessage( AddressIdentifier_t addrID, uint32_t address, FCntIdentifier_t fCntID, uint32_t fCntDown, LoRaMacMessageData_t* macMsg );
/*!
* Derives the McRootKey from the GenAppKey or AppKey.
*
* 1.0.x
* McRootKey = aes128_encrypt(GenAppKey , 0x00 | pad16)
*
* 1.1.x
* McRootKey = aes128_encrypt(AppKey , 0x20 | pad16)
*
* \param[IN] keyID - Key identifier of the root key to use to perform the derivation ( GenAppKey or AppKey )
* \retval - Status of the operation
*/
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
*
* McAppSKey = aes128_encrypt(McKey, 0x01 | McAddr | pad16)
* McNwkSKey = aes128_encrypt(McKey, 0x02 | McAddr | pad16)
*
* \param[IN] addrID - Address identifier to select the multicast group
* \param[IN] mcAddr - Multicast group address (4 bytes)
* \retval - Status of the operation
*/
LoRaMacCryptoStatus_t LoRaMacCryptoDeriveMcSessionKeyPair( AddressIdentifier_t addrID, uint32_t mcAddr );
/*! \} addtogroup LORAMAC */
#endif // __LORAMAC_CRYPTO_H__

View File

@@ -0,0 +1,170 @@
/*!
* \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

@@ -0,0 +1,186 @@
/*!
* \file LoRaMacHeaderTypes.h
*
* \brief LoRa MAC layer header type definitions
*
* \copyright Revised BSD License, see section \ref LICENSE.
*
* \code
* ______ _
* / _____) _ | |
* ( (____ _____ ____ _| |_ _____ ____| |__
* \____ \| ___ | (_ _) ___ |/ ___) _ \
* _____) ) ____| | | || |_| ____( (___| | | |
* (______/|_____)_|_|_| \__)_____)\____)_| |_|
* (C)2013 Semtech
*
* ___ _____ _ ___ _ _____ ___ ___ ___ ___
* / __|_ _/_\ / __| |/ / __/ _ \| _ \/ __| __|
* \__ \ | |/ _ \ (__| ' <| _| (_) | / (__| _|
* |___/ |_/_/ \_\___|_|\_\_| \___/|_|_\\___|___|
* embedded.connectivity.solutions===============
*
* \endcode
*
* \author Miguel Luis ( Semtech )
*
* \author Gregory Cristian ( Semtech )
*
* \author Daniel Jaeckle ( STACKFORCE )
*
* \author Johannes Bruder ( STACKFORCE )
*
* addtogroup LORAMAC
* \{
*
*/
#ifndef __LORAMAC_HEADER_TYPES_H__
#define __LORAMAC_HEADER_TYPES_H__
#include <stdint.h>
/*! Frame header (FHDR) maximum field size */
#define LORAMAC_FHDR_MAX_FIELD_SIZE 22
/*! FHDR Device address field size */
#define LORAMAC_FHDR_DEV_ADD_FIELD_SIZE 4
/*! FHDR Frame control field size */
#define LORAMAC_FHDR_F_CTRL_FIELD_SIZE 1
/*! FHDR Frame control field size */
#define LORAMAC_FHDR_F_CNT_FIELD_SIZE 2
/*! FOpts maximum field size */
#define LORAMAC_FHDR_F_OPTS_MAX_FIELD_SIZE 15
/*!
* LoRaMAC field definition of DLSettings
*
* LoRaWAN Specification V1.0.2, chapter 5.4
*/
typedef union uLoRaMacDLSettings
{
/*!
* Byte-access to the bits
*/
uint8_t Value;
/*!
* Structure containing single access to header bits
*/
struct sDLSettingsBits
{
/*!
* Data rate of a downlink using the second receive window
*/
uint8_t RX2DataRate : 4;
/*!
* Offset between up and downlink datarate of first reception slot
*/
uint8_t RX1DRoffset : 3;
/*!
* Indicates network server LoRaWAN implementation version 1.1 or later.
*/
uint8_t OptNeg : 1;
}Bits;
}LoRaMacDLSettings_t;
/*!
* LoRaMAC header field definition (MHDR field)
*
* LoRaWAN Specification V1.0.2, chapter 4.2
*/
typedef union uLoRaMacHeader
{
/*!
* Byte-access to the bits
*/
uint8_t Value;
/*!
* Structure containing single access to header bits
*/
struct sMacHeaderBits
{
/*!
* Major version
*/
uint8_t Major : 2;
/*!
* RFU
*/
uint8_t RFU : 3;
/*!
* Message type
*/
uint8_t MType : 3;
}Bits;
}LoRaMacHeader_t;
/*!
* LoRaMAC frame control field definition (FCtrl)
*
* LoRaWAN Specification V1.0.2, chapter 4.3.1
*/
typedef union uLoRaMacFrameCtrl
{
/*!
* Byte-access to the bits
*/
uint8_t Value;
/*!
* Structure containing single access to bits
*/
struct sCtrlBits
{
/*!
* Frame options length
*/
uint8_t FOptsLen : 4;
/*!
* Frame pending bit
*/
uint8_t FPending : 1;
/*!
* Message acknowledge bit
*/
uint8_t Ack : 1;
/*!
* ADR acknowledgment request bit
*/
uint8_t AdrAckReq : 1;
/*!
* ADR control in frame header
*/
uint8_t Adr : 1;
}Bits;
}LoRaMacFrameCtrl_t;
/*!
* LoRaMac Frame header (FHDR)
*
* LoRaWAN Specification V1.0.2, chapter 4.3.1
*/
typedef struct sLoRaMacFrameHeader
{
/*!
* Device address
*/
uint32_t DevAddr;
/*!
* Frame control field
*/
LoRaMacFrameCtrl_t FCtrl;
/*!
* Frame counter
*/
uint16_t FCnt;
/*!
* FOpts field may transport MAC commands (opt. 0-15 Bytes)
*/
uint8_t FOpts[LORAMAC_FHDR_F_OPTS_MAX_FIELD_SIZE];
}LoRaMacFrameHeader_t;
/*! \} addtogroup LORAMAC */
#endif // __LORAMAC_HEADER_TYPES_H__

View File

@@ -0,0 +1,327 @@
/*!
* \file LoRaMacMessageTypes.h
*
* \brief LoRa MAC layer message type definitions
*
* \copyright Revised BSD License, see section \ref LICENSE.
*
* \code
* ______ _
* / _____) _ | |
* ( (____ _____ ____ _| |_ _____ ____| |__
* \____ \| ___ | (_ _) ___ |/ ___) _ \
* _____) ) ____| | | || |_| ____( (___| | | |
* (______/|_____)_|_|_| \__)_____)\____)_| |_|
* (C)2013 Semtech
*
* ___ _____ _ ___ _ _____ ___ ___ ___ ___
* / __|_ _/_\ / __| |/ / __/ _ \| _ \/ __| __|
* \__ \ | |/ _ \ (__| ' <| _| (_) | / (__| _|
* |___/ |_/_/ \_\___|_|\_\_| \___/|_|_\\___|___|
* embedded.connectivity.solutions===============
*
* \endcode
*
* \author Miguel Luis ( Semtech )
*
* \author Gregory Cristian ( Semtech )
*
* \author Daniel Jaeckle ( STACKFORCE )
*
* \author Johannes Bruder ( STACKFORCE )
*
* addtogroup LORAMAC
* \{
*
*/
#ifndef __LORAMAC_MESSAGE_TYPES_H__
#define __LORAMAC_MESSAGE_TYPES_H__
#include <stdint.h>
#include "LoRaMacHeaderTypes.h"
/*! MAC header field size */
#define LORAMAC_MHDR_FIELD_SIZE 1
/*! Join EUI field size */
#define LORAMAC_JOIN_EUI_FIELD_SIZE 8
/*! Device EUI field size */
#define LORAMAC_DEV_EUI_FIELD_SIZE 8
/*! Join-server nonce field size */
#define LORAMAC_JOIN_NONCE_FIELD_SIZE 3
/*! Network ID field size */
#define LORAMAC_NET_ID_FIELD_SIZE 3
/*! Port field size */
#define LORAMAC_F_PORT_FIELD_SIZE 1
/*! CFList field size */
#define LORAMAC_C_FLIST_FIELD_SIZE 16
/*! MIC field size */
#define LORAMAC_MIC_FIELD_SIZE 4
/*! Join-request message size */
#define LORAMAC_JOIN_REQ_MSG_SIZE 23
/*! ReJoin-request type 1 message size */
#define LORAMAC_RE_JOIN_1_MSG_SIZE 24
/*! ReJoin-request type 0 or 2 message size */
#define LORAMAC_RE_JOIN_0_2_MSG_SIZE 19
/*!
* LoRaMac type for Join-request message
*/
typedef struct sLoRaMacMessageJoinRequest
{
/*!
* Serialized message buffer
*/
uint8_t* Buffer;
/*!
* Size of serialized message buffer
*/
uint8_t BufSize;
/*!
* MAC header
*/
LoRaMacHeader_t MHDR;
/*!
* Join EUI
*/
uint8_t JoinEUI[LORAMAC_JOIN_EUI_FIELD_SIZE];
/*!
* Device EUI
*/
uint8_t DevEUI[LORAMAC_DEV_EUI_FIELD_SIZE];
/*!
* Device Nonce
*/
uint16_t DevNonce;
/*!
* Message integrity code (MIC)
*/
uint32_t MIC;
}LoRaMacMessageJoinRequest_t;
/*!
* LoRaMac type for rejoin-request type 1 message
*/
typedef struct sLoRaMacMessageReJoinType1
{
/*!
* Serialized message buffer
*/
uint8_t* Buffer;
/*!
* Size of serialized message buffer
*/
uint8_t BufSize;
/*!
* MAC header
*/
LoRaMacHeader_t MHDR;
/*!
* Rejoin-request type ( 1 )
*/
uint8_t ReJoinType;
/*!
* Join EUI
*/
uint8_t JoinEUI[LORAMAC_JOIN_EUI_FIELD_SIZE];
/*!
* Device EUI
*/
uint8_t DevEUI[LORAMAC_DEV_EUI_FIELD_SIZE];
/*!
* ReJoin Type 1 counter
*/
uint16_t RJcount1;
/*!
* Message integrity code (MIC)
*/
uint32_t MIC;
}LoRaMacMessageReJoinType1_t;
/*!
* LoRaMac type for rejoin-request type 0 or 2 message
*/
typedef struct sLoRaMacMessageReJoinType0or2
{
/*!
* Serialized message buffer
*/
uint8_t* Buffer;
/*!
* Size of serialized message buffer
*/
uint8_t BufSize;
/*!
* MAC header
*/
LoRaMacHeader_t MHDR;
/*!
* Rejoin-request type ( 0 or 2 )
*/
uint8_t ReJoinType;
/*!
* Network ID ( 3 bytes )
*/
uint8_t NetID[LORAMAC_NET_ID_FIELD_SIZE];
/*!
* Device EUI
*/
uint8_t DevEUI[LORAMAC_DEV_EUI_FIELD_SIZE];
/*!
* ReJoin Type 0 and 2 frame counter
*/
uint16_t RJcount0;
/*!
* Message integrity code (MIC)
*/
uint32_t MIC;
}LoRaMacMessageReJoinType0or2_t;
/*!
* LoRaMac type for Join-accept message
*/
typedef struct sLoRaMacMessageJoinAccept
{
/*!
* Serialized message buffer
*/
uint8_t* Buffer;
/*!
* Size of serialized message buffer
*/
uint8_t BufSize;
/*!
* MAC header
*/
LoRaMacHeader_t MHDR;
/*!
* Server Nonce ( 3 bytes )
*/
uint8_t JoinNonce[LORAMAC_JOIN_NONCE_FIELD_SIZE];
/*!
* Network ID ( 3 bytes )
*/
uint8_t NetID[LORAMAC_NET_ID_FIELD_SIZE];
/*!
* Device address
*/
uint32_t DevAddr;
/*!
* Device address
*/
LoRaMacDLSettings_t DLSettings;
/*!
* Delay between TX and RX
*/
uint8_t RxDelay;
/*!
* List of channel frequencies (opt.)
*/
uint8_t CFList[16];
/*!
* Message integrity code (MIC)
*/
uint32_t MIC;
}LoRaMacMessageJoinAccept_t;
/*!
* LoRaMac type for Data MAC messages
* (Unconfirmed Data Up, Confirmed Data Up, Unconfirmed Data Down, Confirmed Data Down)
*/
typedef struct sLoRaMacMessageData
{
/*!
* Serialized message buffer
*/
uint8_t* Buffer;
/*!
* Size of serialized message buffer
*/
uint8_t BufSize;
/*!
* MAC header
*/
LoRaMacHeader_t MHDR;
/*!
* Frame header (FHDR)
*/
LoRaMacFrameHeader_t FHDR;
/*!
* Port field (opt.)
*/
uint8_t FPort;
/*!
* Frame payload may contain MAC commands or data (opt.)
*/
uint8_t* FRMPayload;
/*!
* Size of frame payload (not included in LoRaMac messages)
*/
uint8_t FRMPayloadSize;
/*!
* Message integrity code (MIC)
*/
uint32_t MIC;
}LoRaMacMessageData_t;
/*!
* LoRaMac message type enumerator
*/
typedef enum eLoRaMacMessageType
{
/*!
* Join-request message
*/
LORAMAC_MSG_TYPE_JOIN_REQUEST,
/*!
* Rejoin-request type 1 message
*/
LORAMAC_MSG_TYPE_RE_JOIN_1,
/*!
* Rejoin-request type 1 message
*/
LORAMAC_MSG_TYPE_RE_JOIN_0_2,
/*!
* Join-accept message
*/
LORAMAC_MSG_TYPE_JOIN_ACCEPT,
/*!
* Data MAC messages
*/
LORAMAC_MSG_TYPE_DATA,
/*!
* Undefined message type
*/
LORAMAC_MSG_TYPE_UNDEF,
}LoRaMacMessageType_t;
/*!
* LoRaMac general message type
*/
typedef struct sLoRaMacMessage
{
LoRaMacMessageType_t Type;
union uMessage
{
LoRaMacMessageJoinRequest_t JoinReq;
LoRaMacMessageReJoinType1_t ReJoin1;
LoRaMacMessageReJoinType0or2_t ReJoin0or2;
LoRaMacMessageJoinAccept_t JoinAccept;
LoRaMacMessageData_t Data;
}Message;
}LoRaMacMessage_t;
/*! \} addtogroup LORAMAC */
#endif // __LORAMAC_MESSAGE_TYPES_H__

View File

@@ -0,0 +1,118 @@
/*
/ _____) _ | |
( (____ _____ ____ _| |_ _____ ____| |__
\____ \| ___ | (_ _) ___ |/ ___) _ \
_____) ) ____| | | || |_| ____( (___| | | |
(______/|_____)_|_|_| \__)_____)\____)_| |_|
(C)2013 Semtech
___ _____ _ ___ _ _____ ___ ___ ___ ___
/ __|_ _/_\ / __| |/ / __/ _ \| _ \/ __| __|
\__ \ | |/ _ \ (__| ' <| _| (_) | / (__| _|
|___/ |_/_/ \_\___|_|\_\_| \___/|_|_\\___|___|
embedded.connectivity.solutions===============
Description: LoRa MAC layer message parser functionality implementation
License: Revised BSD License, see LICENSE.TXT file include in the project
Maintainer: Miguel Luis ( Semtech ), Gregory Cristian ( Semtech ),
Daniel Jaeckle ( STACKFORCE ), Johannes Bruder ( STACKFORCE )
*/
#include "LoRaMacParser.h"
#include "utilities.h"
LoRaMacParserStatus_t LoRaMacParserJoinAccept( LoRaMacMessageJoinAccept_t* macMsg )
{
if( ( macMsg == 0 ) || ( macMsg->Buffer == 0 ) )
{
return LORAMAC_PARSER_ERROR_NPE;
}
uint16_t bufItr = 0;
macMsg->MHDR.Value = macMsg->Buffer[bufItr++];
memcpy1( macMsg->JoinNonce, &macMsg->Buffer[bufItr], 3 );
bufItr = bufItr + 3;
memcpy1( macMsg->NetID, &macMsg->Buffer[bufItr], 3 );
bufItr = bufItr + 3;
macMsg->DevAddr = ( uint32_t ) macMsg->Buffer[bufItr++];
macMsg->DevAddr |= ( ( uint32_t ) macMsg->Buffer[bufItr++] << 8 );
macMsg->DevAddr |= ( ( uint32_t ) macMsg->Buffer[bufItr++] << 16 );
macMsg->DevAddr |= ( ( uint32_t ) macMsg->Buffer[bufItr++] << 24 );
macMsg->DLSettings.Value = macMsg->Buffer[bufItr++];
macMsg->RxDelay = macMsg->Buffer[bufItr++];
if( ( macMsg->BufSize - LORAMAC_MIC_FIELD_SIZE - bufItr ) == LORAMAC_C_FLIST_FIELD_SIZE )
{
memcpy1( macMsg->CFList, &macMsg->Buffer[bufItr], LORAMAC_C_FLIST_FIELD_SIZE );
bufItr = bufItr + LORAMAC_C_FLIST_FIELD_SIZE;
}
else if( ( macMsg->BufSize - LORAMAC_MIC_FIELD_SIZE - bufItr ) > 0 )
{
return LORAMAC_PARSER_FAIL;
}
macMsg->MIC = ( uint32_t ) macMsg->Buffer[bufItr++];
macMsg->MIC |= ( ( uint32_t ) macMsg->Buffer[bufItr++] << 8 );
macMsg->MIC |= ( ( uint32_t ) macMsg->Buffer[bufItr++] << 16 );
macMsg->MIC |= ( ( uint32_t ) macMsg->Buffer[bufItr++] << 24 );
return LORAMAC_PARSER_SUCCESS;
}
LoRaMacParserStatus_t LoRaMacParserData( LoRaMacMessageData_t* macMsg )
{
if( ( macMsg == 0 ) || ( macMsg->Buffer == 0 ) )
{
return LORAMAC_PARSER_ERROR_NPE;
}
uint16_t bufItr = 0;
macMsg->MHDR.Value = macMsg->Buffer[bufItr++];
macMsg->FHDR.DevAddr = macMsg->Buffer[bufItr++];
macMsg->FHDR.DevAddr |= ( ( uint32_t ) macMsg->Buffer[bufItr++] << 8 );
macMsg->FHDR.DevAddr |= ( ( uint32_t ) macMsg->Buffer[bufItr++] << 16 );
macMsg->FHDR.DevAddr |= ( ( uint32_t ) macMsg->Buffer[bufItr++] << 24 );
macMsg->FHDR.FCtrl.Value = macMsg->Buffer[bufItr++];
macMsg->FHDR.FCnt = macMsg->Buffer[bufItr++];
macMsg->FHDR.FCnt |= macMsg->Buffer[bufItr++] << 8;
if( macMsg->FHDR.FCtrl.Bits.FOptsLen <= 15 )
{
memcpy1( macMsg->FHDR.FOpts, &macMsg->Buffer[bufItr], macMsg->FHDR.FCtrl.Bits.FOptsLen );
bufItr = bufItr + macMsg->FHDR.FCtrl.Bits.FOptsLen;
}
else
{
return LORAMAC_PARSER_FAIL;
}
// Initialize anyway with zero.
macMsg->FPort = 0;
macMsg->FRMPayloadSize = 0;
if( ( macMsg->BufSize - bufItr - LORAMAC_MIC_FIELD_SIZE ) > 0 )
{
macMsg->FPort = macMsg->Buffer[bufItr++];
macMsg->FRMPayloadSize = ( macMsg->BufSize - bufItr - LORAMAC_MIC_FIELD_SIZE );
memcpy1( macMsg->FRMPayload, &macMsg->Buffer[bufItr], macMsg->FRMPayloadSize );
bufItr = bufItr + macMsg->FRMPayloadSize;
}
macMsg->MIC = ( uint32_t ) macMsg->Buffer[( macMsg->BufSize - LORAMAC_MIC_FIELD_SIZE )];
macMsg->MIC |= ( ( uint32_t ) macMsg->Buffer[( macMsg->BufSize - LORAMAC_MIC_FIELD_SIZE ) + 1] << 8 );
macMsg->MIC |= ( ( uint32_t ) macMsg->Buffer[( macMsg->BufSize - LORAMAC_MIC_FIELD_SIZE ) + 2] << 16 );
macMsg->MIC |= ( ( uint32_t ) macMsg->Buffer[( macMsg->BufSize - LORAMAC_MIC_FIELD_SIZE ) + 3] << 24 );
return LORAMAC_PARSER_SUCCESS;
}

View File

@@ -0,0 +1,86 @@
/*!
* \file LoRaMacParser.h
*
* \brief LoRa MAC layer message parser functionality implementation
*
* \copyright Revised BSD License, see section \ref LICENSE.
*
* \code
* ______ _
* / _____) _ | |
* ( (____ _____ ____ _| |_ _____ ____| |__
* \____ \| ___ | (_ _) ___ |/ ___) _ \
* _____) ) ____| | | || |_| ____( (___| | | |
* (______/|_____)_|_|_| \__)_____)\____)_| |_|
* (C)2013 Semtech
*
* ___ _____ _ ___ _ _____ ___ ___ ___ ___
* / __|_ _/_\ / __| |/ / __/ _ \| _ \/ __| __|
* \__ \ | |/ _ \ (__| ' <| _| (_) | / (__| _|
* |___/ |_/_/ \_\___|_|\_\_| \___/|_|_\\___|___|
* embedded.connectivity.solutions===============
*
* \endcode
*
* \author Miguel Luis ( Semtech )
*
* \author Gregory Cristian ( Semtech )
*
* \author Daniel Jaeckle ( STACKFORCE )
*
* \author Johannes Bruder ( STACKFORCE )
*
* addtogroup LORAMAC
* \{
*
*/
#ifndef __LORAMAC_PARSER_H__
#define __LORAMAC_PARSER_H__
#include <stdint.h>
#include "LoRaMacMessageTypes.h"
/*!
* LoRaMac Parser Status
*/
typedef enum eLoRaMacParserStatus
{
/*!
* No error occurred
*/
LORAMAC_PARSER_SUCCESS = 0,
/*!
* Failure during parsing occurred
*/
LORAMAC_PARSER_FAIL,
/*!
* Null pointer exception
*/
LORAMAC_PARSER_ERROR_NPE,
/*!
* Undefined Error occurred
*/
LORAMAC_PARSER_ERROR,
}LoRaMacParserStatus_t;
/*!
* Parse a serialized join-accept message and fills the structured object.
*
* \param[IN/OUT] macMsg - Join-accept message object
* \retval - Status of the operation
*/
LoRaMacParserStatus_t LoRaMacParserJoinAccept( LoRaMacMessageJoinAccept_t *macMsg );
/*!
* Parse a serialized data message and fills the structured object.
*
* \param[IN/OUT] macMsg - Data message object
* \retval - Status of the operation
*/
LoRaMacParserStatus_t LoRaMacParserData( LoRaMacMessageData_t *macMsg );
/*! \} addtogroup LORAMAC */
#endif // __LORAMAC_PARSER_H__

View File

@@ -0,0 +1,183 @@
/*
/ _____) _ | |
( (____ _____ ____ _| |_ _____ ____| |__
\____ \| ___ | (_ _) ___ |/ ___) _ \
_____) ) ____| | | || |_| ____( (___| | | |
(______/|_____)_|_|_| \__)_____)\____)_| |_|
(C)2013 Semtech
___ _____ _ ___ _ _____ ___ ___ ___ ___
/ __|_ _/_\ / __| |/ / __/ _ \| _ \/ __| __|
\__ \ | |/ _ \ (__| ' <| _| (_) | / (__| _|
|___/ |_/_/ \_\___|_|\_\_| \___/|_|_\\___|___|
embedded.connectivity.solutions===============
Description: LoRa MAC layer message serializer functionality implementation
License: Revised BSD License, see LICENSE.TXT file include in the project
Maintainer: Miguel Luis ( Semtech ), Gregory Cristian ( Semtech ),
Daniel Jaeckle ( STACKFORCE ), Johannes Bruder ( STACKFORCE )
*/
#include "LoRaMacSerializer.h"
#include "utilities.h"
LoRaMacSerializerStatus_t LoRaMacSerializerJoinRequest( LoRaMacMessageJoinRequest_t* macMsg )
{
if( ( macMsg == 0 ) || ( macMsg->Buffer == 0 ) )
{
return LORAMAC_SERIALIZER_ERROR_NPE;
}
uint16_t bufItr = 0;
// Check macMsg->BufSize
if( macMsg->BufSize < LORAMAC_JOIN_REQ_MSG_SIZE )
{
return LORAMAC_SERIALIZER_ERROR_BUF_SIZE;
}
macMsg->Buffer[bufItr++] = macMsg->MHDR.Value;
memcpyr( &macMsg->Buffer[bufItr], macMsg->JoinEUI, LORAMAC_JOIN_EUI_FIELD_SIZE );
bufItr += LORAMAC_JOIN_EUI_FIELD_SIZE;
memcpyr( &macMsg->Buffer[bufItr], macMsg->DevEUI, LORAMAC_DEV_EUI_FIELD_SIZE );
bufItr += LORAMAC_DEV_EUI_FIELD_SIZE;
macMsg->Buffer[bufItr++] = macMsg->DevNonce & 0xFF;
macMsg->Buffer[bufItr++] = ( macMsg->DevNonce >> 8 ) & 0xFF;
macMsg->Buffer[bufItr++] = macMsg->MIC & 0xFF;
macMsg->Buffer[bufItr++] = ( macMsg->MIC >> 8 ) & 0xFF;
macMsg->Buffer[bufItr++] = ( macMsg->MIC >> 16 ) & 0xFF;
macMsg->Buffer[bufItr++] = ( macMsg->MIC >> 24 ) & 0xFF;
macMsg->BufSize = bufItr;
return LORAMAC_SERIALIZER_SUCCESS;
}
LoRaMacSerializerStatus_t LoRaMacSerializerReJoinType1( LoRaMacMessageReJoinType1_t* macMsg )
{
if( ( macMsg == 0 ) || ( macMsg->Buffer == 0 ) )
{
return LORAMAC_SERIALIZER_ERROR_NPE;
}
uint16_t bufItr = 0;
// Check macMsg->BufSize
if( macMsg->BufSize < LORAMAC_RE_JOIN_1_MSG_SIZE )
{
return LORAMAC_SERIALIZER_ERROR_BUF_SIZE;
}
macMsg->Buffer[bufItr++] = macMsg->MHDR.Value;
macMsg->Buffer[bufItr++] = macMsg->ReJoinType;
memcpyr( &macMsg->Buffer[bufItr], macMsg->JoinEUI, LORAMAC_JOIN_EUI_FIELD_SIZE );
bufItr += LORAMAC_JOIN_EUI_FIELD_SIZE;
memcpyr( &macMsg->Buffer[bufItr], macMsg->DevEUI, LORAMAC_DEV_EUI_FIELD_SIZE );
bufItr += LORAMAC_DEV_EUI_FIELD_SIZE;
macMsg->Buffer[bufItr++] = macMsg->RJcount1 & 0xFF;
macMsg->Buffer[bufItr++] = ( macMsg->RJcount1 >> 8 ) & 0xFF;
return LORAMAC_SERIALIZER_SUCCESS;
}
LoRaMacSerializerStatus_t LoRaMacSerializerReJoinType0or2( LoRaMacMessageReJoinType0or2_t* macMsg )
{
if( ( macMsg == 0 ) || ( macMsg->Buffer == 0 ) )
{
return LORAMAC_SERIALIZER_ERROR_NPE;
}
uint16_t bufItr = 0;
// Check macMsg->BufSize
if( macMsg->BufSize < LORAMAC_RE_JOIN_0_2_MSG_SIZE )
{
return LORAMAC_SERIALIZER_ERROR_BUF_SIZE;
}
macMsg->Buffer[bufItr++] = macMsg->MHDR.Value;
macMsg->Buffer[bufItr++] = macMsg->ReJoinType;
memcpy1( &macMsg->Buffer[bufItr], macMsg->NetID, LORAMAC_NET_ID_FIELD_SIZE );
bufItr += LORAMAC_NET_ID_FIELD_SIZE;
memcpyr( &macMsg->Buffer[bufItr], macMsg->DevEUI, LORAMAC_DEV_EUI_FIELD_SIZE );
bufItr += LORAMAC_DEV_EUI_FIELD_SIZE;
macMsg->Buffer[bufItr++] = macMsg->RJcount0 & 0xFF;
macMsg->Buffer[bufItr++] = ( macMsg->RJcount0 >> 8 ) & 0xFF;
return LORAMAC_SERIALIZER_SUCCESS;
}
LoRaMacSerializerStatus_t LoRaMacSerializerData( LoRaMacMessageData_t* macMsg )
{
if( ( macMsg == 0 ) || ( macMsg->Buffer == 0 ) )
{
return LORAMAC_SERIALIZER_ERROR_NPE;
}
uint16_t bufItr = 0;
// Check macMsg->BufSize
uint16_t computedBufSize = LORAMAC_MHDR_FIELD_SIZE
+ LORAMAC_FHDR_DEV_ADD_FIELD_SIZE
+ LORAMAC_FHDR_F_CTRL_FIELD_SIZE
+ LORAMAC_FHDR_F_CNT_FIELD_SIZE;
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 )
{
return LORAMAC_SERIALIZER_ERROR_BUF_SIZE;
}
macMsg->Buffer[bufItr++] = macMsg->MHDR.Value;
macMsg->Buffer[bufItr++] = ( macMsg->FHDR.DevAddr ) & 0xFF;
macMsg->Buffer[bufItr++] = ( macMsg->FHDR.DevAddr >> 8 ) & 0xFF;
macMsg->Buffer[bufItr++] = ( macMsg->FHDR.DevAddr >> 16 ) & 0xFF;
macMsg->Buffer[bufItr++] = ( macMsg->FHDR.DevAddr >> 24 ) & 0xFF;
macMsg->Buffer[bufItr++] = macMsg->FHDR.FCtrl.Value;
macMsg->Buffer[bufItr++] = macMsg->FHDR.FCnt & 0xFF;
macMsg->Buffer[bufItr++] = ( macMsg->FHDR.FCnt >> 8 ) & 0xFF;
memcpy1( &macMsg->Buffer[bufItr], macMsg->FHDR.FOpts, macMsg->FHDR.FCtrl.Bits.FOptsLen );
bufItr = bufItr + macMsg->FHDR.FCtrl.Bits.FOptsLen;
if( macMsg->FRMPayloadSize > 0 )
{
macMsg->Buffer[bufItr++] = macMsg->FPort;
}
memcpy1( &macMsg->Buffer[bufItr], macMsg->FRMPayload, macMsg->FRMPayloadSize );
bufItr = bufItr + macMsg->FRMPayloadSize;
macMsg->Buffer[bufItr++] = macMsg->MIC & 0xFF;
macMsg->Buffer[bufItr++] = ( macMsg->MIC >> 8 ) & 0xFF;
macMsg->Buffer[bufItr++] = ( macMsg->MIC >> 16 ) & 0xFF;
macMsg->Buffer[bufItr++] = ( macMsg->MIC >> 24 ) & 0xFF;
macMsg->BufSize = bufItr;
return LORAMAC_SERIALIZER_SUCCESS;
}

View File

@@ -0,0 +1,101 @@
/*!
* \file LoRaMacSerializer.h
*
* \brief LoRa MAC layer message serializer functionality implementation
*
* \copyright Revised BSD License, see section \ref LICENSE.
*
* \code
* ______ _
* / _____) _ | |
* ( (____ _____ ____ _| |_ _____ ____| |__
* \____ \| ___ | (_ _) ___ |/ ___) _ \
* _____) ) ____| | | || |_| ____( (___| | | |
* (______/|_____)_|_|_| \__)_____)\____)_| |_|
* (C)2013 Semtech
*
* ___ _____ _ ___ _ _____ ___ ___ ___ ___
* / __|_ _/_\ / __| |/ / __/ _ \| _ \/ __| __|
* \__ \ | |/ _ \ (__| ' <| _| (_) | / (__| _|
* |___/ |_/_/ \_\___|_|\_\_| \___/|_|_\\___|___|
* embedded.connectivity.solutions===============
*
* \endcode
*
* \author Miguel Luis ( Semtech )
*
* \author Gregory Cristian ( Semtech )
*
* \author Daniel Jaeckle ( STACKFORCE )
*
* \author Johannes Bruder ( STACKFORCE )
*
* addtogroup LORAMAC
* \{
*
*/
#ifndef __LORAMAC_SERIALIZER_H__
#define __LORAMAC_SERIALIZER_H__
#include <stdint.h>
#include "LoRaMacMessageTypes.h"
/*!
* LoRaMac Serializer Status
*/
typedef enum eLoRaMacSerializerStatus
{
/*!
* No error occurred
*/
LORAMAC_SERIALIZER_SUCCESS = 0,
/*!
* Null pointer exception
*/
LORAMAC_SERIALIZER_ERROR_NPE,
/*!
* Incompatible buffer size
*/
LORAMAC_SERIALIZER_ERROR_BUF_SIZE,
/*!
* Undefined Error occurred
*/
LORAMAC_SERIALIZER_ERROR,
}LoRaMacSerializerStatus_t;
/*!
* Creates serialized MAC message of structured object.
*
* \param[IN/OUT] macMsg - Join-request message object
* \retval - Status of the operation
*/
LoRaMacSerializerStatus_t LoRaMacSerializerJoinRequest( LoRaMacMessageJoinRequest_t* macMsg );
/*!
* Creates serialized MAC message of structured object.
*
* \param[IN/OUT] macMsg - Join-request message object
* \retval - Status of the operation
*/
LoRaMacSerializerStatus_t LoRaMacSerializerReJoinType1( LoRaMacMessageReJoinType1_t* macMsg );
/*!
* Creates serialized MAC message of structured object.
*
* \param[IN/OUT] macMsg - Join-request message object
* \retval - Status of the operation
*/
LoRaMacSerializerStatus_t LoRaMacSerializerReJoinType0or2( LoRaMacMessageReJoinType0or2_t* macMsg );
/*!
* Creates serialized MAC message of structured object.
*
* \param[IN/OUT] macMsg - Data message object
* \retval - Status of the operation
*/
LoRaMacSerializerStatus_t LoRaMacSerializerData( LoRaMacMessageData_t* macMsg );
/*! \} addtogroup LORAMAC */
#endif // __LORAMAC_SERIALIZER_H__

View File

@@ -0,0 +1,51 @@
/*!
* \file LoRaMacTest.h
*
* \brief LoRa MAC layer test function implementation
*
* \copyright Revised BSD License, see section \ref LICENSE.
*
* \code
* ______ _
* / _____) _ | |
* ( (____ _____ ____ _| |_ _____ ____| |__
* \____ \| ___ | (_ _) ___ |/ ___) _ \
* _____) ) ____| | | || |_| ____( (___| | | |
* (______/|_____)_|_|_| \__)_____)\____)_| |_|
* (C)2013-2017 Semtech
*
* ___ _____ _ ___ _ _____ ___ ___ ___ ___
* / __|_ _/_\ / __| |/ / __/ _ \| _ \/ __| __|
* \__ \ | |/ _ \ (__| ' <| _| (_) | / (__| _|
* |___/ |_/_/ \_\___|_|\_\_| \___/|_|_\\___|___|
* embedded.connectivity.solutions===============
*
* \endcode
*
* \author Miguel Luis ( Semtech )
*
* \author Gregory Cristian ( Semtech )
*
* \author Daniel Jaeckle ( STACKFORCE )
*
* \defgroup LORAMACTEST LoRa MAC layer test function implementation
* This module specifies the API implementation of test function of the LoRaMAC layer.
* The functions in this file are only for testing purposes only.
* \{
*/
#ifndef __LORAMACTEST_H__
#define __LORAMACTEST_H__
/*!
* \brief Enabled or disables the duty cycle
*
* \details This is a test function. It shall be used for testing purposes only.
* Changing this attribute may lead to a non-conformance LoRaMac operation.
*
* \param [IN] enable - Enabled or disables the duty cycle
*/
void LoRaMacTestSetDutyCycleOn( bool enable );
/*! \} defgroup LORAMACTEST */
#endif // __LORAMACTEST_H__

View File

@@ -0,0 +1,655 @@
/*!
* \file LoRaMacTypes.h
*
* \brief LoRa MAC layer internal types definition. Please do not include in application sources.
*
* \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_TYPES_H__
#define __LORAMAC_TYPES_H__
#include <stdint.h>
#include <stdbool.h>
#include "timer.h"
/*!
* Start value for unicast keys enumeration
*/
#define LORAMAC_CRYPTO_UNICAST_KEYS 0
/*!
* Start value for multicast keys enumeration
*/
#define LORAMAC_CRYPTO_MULTICAST_KEYS 127
typedef union Version_u
{
struct Version_s
{
uint8_t Rfu;
uint8_t Revision;
uint8_t Minor;
uint8_t Major;
}Fields;
uint32_t Value;
}Version_t;
/*!
* 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.
*
* Note: The naming is implementation specific since there is no definition
* in the LoRaWAN specification included.
*/
typedef enum eFType
{
/*!
* Frame type A
*
* FOptsLen > 0, Fopt present, FPort > 0, FRMPayload present
*/
FRAME_TYPE_A,
/*!
* Frame type B
*
* FOptsLen > 0, Fopt present, FPort not present, FRMPayload not present
*/
FRAME_TYPE_B,
/*!
* Frame type C
*
* FOptsLen = 0, Fopt not present, FPort = 0 , FRMPayload containing MAC commands
*/
FRAME_TYPE_C,
/*!
* Frame type D
*
* FOptsLen = 0, Fopt not present, FPort > 0 , FRMPayload present
*/
FRAME_TYPE_D,
}FType_t;
/*!
* LoRaWAN Frame counter identifier.
*/
typedef enum eFCntIdentifier
{
/*!
* Uplink frame counter which is incremented with each uplink.
*/
FCNT_UP = 0,
/*!
* Network downlink frame counter which is incremented with each downlink on FPort 0
* or when the FPort field is missing.
*/
N_FCNT_DOWN,
/*!
* Application downlink frame counter which is incremented with each downlink
* on a port different than 0.
*/
A_FCNT_DOWN,
/*!
* In case if the device is connected to a LoRaWAN 1.0 Server,
* this counter is used for every kind of downlink frame.
*/
FCNT_DOWN,
/*!
* Multicast downlink counter for index 0
*/
MC_FCNT_DOWN_0,
/*!
* Multicast downlink counter for index 1
*/
MC_FCNT_DOWN_1,
/*!
* Multicast downlink counter for index 2
*/
MC_FCNT_DOWN_2,
/*!
* Multicast downlink counter for index 3
*/
MC_FCNT_DOWN_3,
}FCntIdentifier_t;
/*!
* LoRaMac Key identifier
*/
typedef enum eKeyIdentifier
{
/*!
* Application root key
*/
APP_KEY = 0,
/*!
* Application root key
* Used to derive McRootKey for 1.0.x devices
*/
GEN_APP_KEY,
/*!
* Network root key
*/
NWK_KEY,
/*!
* Join session integrity key
*/
J_S_INT_KEY,
/*!
* Join session encryption key
*/
J_S_ENC_KEY,
/*!
* Forwarding Network session integrity key
*/
F_NWK_S_INT_KEY,
/*!
* Serving Network session integrity key
*/
S_NWK_S_INT_KEY,
/*!
* Network session encryption key
*/
NWK_S_ENC_KEY,
/*!
* Application session key
*/
APP_S_KEY,
/*!
* Multicast root key
*/
MC_ROOT_KEY,
/*!
* Multicast key encryption key
*/
MC_KE_KEY = LORAMAC_CRYPTO_MULTICAST_KEYS,
/*!
* Multicast root key index 0
*/
MC_KEY_0,
/*!
* Multicast Application session key index 0
*/
MC_APP_S_KEY_0,
/*!
* Multicast Network session key index 0
*/
MC_NWK_S_KEY_0,
/*!
* Multicast root key index 1
*/
MC_KEY_1,
/*!
* Multicast Application session key index 1
*/
MC_APP_S_KEY_1,
/*!
* Multicast Network session key index 1
*/
MC_NWK_S_KEY_1,
/*!
* Multicast root key index 2
*/
MC_KEY_2,
/*!
* Multicast Application session key index 2
*/
MC_APP_S_KEY_2,
/*!
* Multicast Network session key index 2
*/
MC_NWK_S_KEY_2,
/*!
* Multicast root key index 3
*/
MC_KEY_3,
/*!
* Multicast Application session key index 3
*/
MC_APP_S_KEY_3,
/*!
* Multicast Network session key index 3
*/
MC_NWK_S_KEY_3,
/*!
* Zero key for slot randomization in class B
*/
SLOT_RAND_ZERO_KEY,
/*!
* No Key
*/
NO_KEY,
}KeyIdentifier_t;
/*!
* LoRaMac Crypto address identifier
*/
typedef enum eAddressIdentifier
{
/*!
* Multicast Address for index 0
*/
MULTICAST_0_ADDR = 0,
/*!
* Multicast Address for index 1
*/
MULTICAST_1_ADDR = 1,
/*!
* Multicast Address for index 2
*/
MULTICAST_2_ADDR = 2,
/*!
* Multicast Address for index 3
*/
MULTICAST_3_ADDR = 3,
/*!
* Unicast End-device address
*/
UNICAST_DEV_ADDR = 4,
}AddressIdentifier_t;
/*
* Multicast Rx window parameters
*/
typedef union uMcRxParams
{
struct
{
/*!
* Reception frequency of the ping slot windows
*/
uint32_t Frequency;
/*!
* Datarate of the ping slot
*/
int8_t Datarate;
/*!
* This parameter is necessary for class B operation. It defines the
* periodicity of the multicast downlink slots
*/
uint16_t Periodicity;
}ClassB;
struct
{
/*!
* Reception frequency of the ping slot windows
*/
uint32_t Frequency;
/*!
* Datarate of the ping slot
*/
int8_t Datarate;
}ClassC;
}McRxParams_t;
/*!
* Multicast channel
*/
typedef struct sMcChannelParams
{
/*!
* 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;
/*!
* Encrypted multicast key
*/
uint8_t *McKeyE;
/*!
* 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
* calculated as follows:
* PingNb = 128 / ( 1 << periodicity ), where
* 0 <= periodicity <= 7
*/
uint8_t PingNb;
/*!
* Period of the multicast slots. The variable can be
* calculated as follows:
* PingPeriod = 4096 / PingNb
*/
uint16_t PingPeriod;
/*!
* Ping offset of the multicast channel for Class B
*/
uint16_t PingOffset;
}MulticastCtx_t;
/*!
* LoRaMac join-request / rejoin type identifier
*/
typedef enum eJoinReqIdentifier
{
/*!
* Rejoin type 0
*/
REJOIN_REQ_0 = 0x00,
/*!
* Rejoin type 1
*/
REJOIN_REQ_1 = 0x01,
/*!
* Rejoin type 2
*/
REJOIN_REQ_2 = 0x02,
/*!
* Join-request
*/
JOIN_REQ = 0xFF,
}JoinReqIdentifier_t;
/*!
* LoRaMAC mote MAC commands
*
* LoRaWAN Specification V1.1.0, chapter 5, table 4
*/
typedef enum eLoRaMacMoteCmd
{
/*!
* LinkCheckReq
*/
MOTE_MAC_LINK_CHECK_REQ = 0x02,
/*!
* LinkADRAns
*/
MOTE_MAC_LINK_ADR_ANS = 0x03,
/*!
* DutyCycleAns
*/
MOTE_MAC_DUTY_CYCLE_ANS = 0x04,
/*!
* RXParamSetupAns
*/
MOTE_MAC_RX_PARAM_SETUP_ANS = 0x05,
/*!
* DevStatusAns
*/
MOTE_MAC_DEV_STATUS_ANS = 0x06,
/*!
* NewChannelAns
*/
MOTE_MAC_NEW_CHANNEL_ANS = 0x07,
/*!
* RXTimingSetupAns
*/
MOTE_MAC_RX_TIMING_SETUP_ANS = 0x08,
/*!
* TXParamSetupAns
*/
MOTE_MAC_TX_PARAM_SETUP_ANS = 0x09,
/*!
* DlChannelAns
*/
MOTE_MAC_DL_CHANNEL_ANS = 0x0A,
/*!
* DeviceTimeReq
*/
MOTE_MAC_DEVICE_TIME_REQ = 0x0D,
/*!
* PingSlotInfoReq
*/
MOTE_MAC_PING_SLOT_INFO_REQ = 0x10,
/*!
* PingSlotFreqAns
*/
MOTE_MAC_PING_SLOT_FREQ_ANS = 0x11,
/*!
* BeaconTimingReq
*/
MOTE_MAC_BEACON_TIMING_REQ = 0x12,
/*!
* BeaconFreqAns
*/
MOTE_MAC_BEACON_FREQ_ANS = 0x13,
}LoRaMacMoteCmd_t;
/*!
* LoRaMAC server MAC commands
*
* LoRaWAN Specification V1.1.0 chapter 5, table 4
*/
typedef enum eLoRaMacSrvCmd
{
/*!
* ResetInd
*/
SRV_MAC_RESET_CONF = 0x01,
/*!
* LinkCheckAns
*/
SRV_MAC_LINK_CHECK_ANS = 0x02,
/*!
* LinkADRReq
*/
SRV_MAC_LINK_ADR_REQ = 0x03,
/*!
* DutyCycleReq
*/
SRV_MAC_DUTY_CYCLE_REQ = 0x04,
/*!
* RXParamSetupReq
*/
SRV_MAC_RX_PARAM_SETUP_REQ = 0x05,
/*!
* DevStatusReq
*/
SRV_MAC_DEV_STATUS_REQ = 0x06,
/*!
* NewChannelReq
*/
SRV_MAC_NEW_CHANNEL_REQ = 0x07,
/*!
* RXTimingSetupReq
*/
SRV_MAC_RX_TIMING_SETUP_REQ = 0x08,
/*!
* NewChannelReq
*/
SRV_MAC_TX_PARAM_SETUP_REQ = 0x09,
/*!
* DlChannelReq
*/
SRV_MAC_DL_CHANNEL_REQ = 0x0A,
/*!
* DeviceTimeAns
*/
SRV_MAC_DEVICE_TIME_ANS = 0x0D,
/*!
* PingSlotInfoAns
*/
SRV_MAC_PING_SLOT_INFO_ANS = 0x10,
/*!
* PingSlotChannelReq
*/
SRV_MAC_PING_SLOT_CHANNEL_REQ = 0x11,
/*!
* BeaconTimingAns
*/
SRV_MAC_BEACON_TIMING_ANS = 0x12,
/*!
* BeaconFreqReq
*/
SRV_MAC_BEACON_FREQ_REQ = 0x13,
}LoRaMacSrvCmd_t;
/*!
* LoRaMAC band parameters definition
*/
typedef struct sBand
{
/*!
* Duty cycle
*/
uint16_t DCycle;
/*!
* Maximum Tx power
*/
int8_t TxMaxPower;
/*!
* Time stamp of the last JoinReq Tx frame.
*/
TimerTime_t LastJoinTxDoneTime;
/*!
* Time stamp of the last Tx frame
*/
TimerTime_t LastTxDoneTime;
/*!
* Holds the time where the device is off
*/
TimerTime_t TimeOff;
}Band_t;
/*!
* LoRaMAC frame types
*
* LoRaWAN Specification V1.0.2, chapter 4.2.1, table 1
*/
typedef enum eLoRaMacFrameType
{
/*!
* LoRaMAC join request frame
*/
FRAME_TYPE_JOIN_REQ = 0x00,
/*!
* LoRaMAC join accept frame
*/
FRAME_TYPE_JOIN_ACCEPT = 0x01,
/*!
* LoRaMAC unconfirmed up-link frame
*/
FRAME_TYPE_DATA_UNCONFIRMED_UP = 0x02,
/*!
* LoRaMAC unconfirmed down-link frame
*/
FRAME_TYPE_DATA_UNCONFIRMED_DOWN = 0x03,
/*!
* LoRaMAC confirmed up-link frame
*/
FRAME_TYPE_DATA_CONFIRMED_UP = 0x04,
/*!
* LoRaMAC confirmed down-link frame
*/
FRAME_TYPE_DATA_CONFIRMED_DOWN = 0x05,
/*!
* LoRaMAC proprietary frame
*/
FRAME_TYPE_PROPRIETARY = 0x07,
}LoRaMacFrameType_t;
/*!
* LoRaMAC Battery level indicator
*/
typedef enum eLoRaMacBatteryLevel
{
/*!
* External power source
*/
BAT_LEVEL_EXT_SRC = 0x00,
/*!
* Battery level empty
*/
BAT_LEVEL_EMPTY = 0x01,
/*!
* Battery level full
*/
BAT_LEVEL_FULL = 0xFE,
/*!
* Battery level - no measurement available
*/
BAT_LEVEL_NO_MEASURE = 0xFF,
}LoRaMacBatteryLevel_t;
#endif // __LORAMAC_TYPES_H__

View File

@@ -0,0 +1,56 @@
/**
******************************************************************************
* @file lora_mac_version.h
* @author MCD Application Team
* @brief Identifies the version of loramac on github
******************************************************************************
* @attention
*
* <h2><center>&copy; Copyright (c) 2019 STMicroelectronics.
* All rights reserved.</center></h2>
*
* This software component is licensed by ST under BSD 3-Clause license,
* the "License"; You may not use this file except in compliance with the
* License. You may obtain a copy of the License at:
* opensource.org/licenses/BSD-3-Clause
*
******************************************************************************
*/
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef __LORA_MAC_VERSION_H__
#define __LORA_MAC_VERSION_H__
#ifdef __cplusplus
extern "C" {
#endif
/* Includes ------------------------------------------------------------------*/
/* Exported constants --------------------------------------------------------*/
/*the 4 MSBs define the version based on Github version */
/*https://github.com/Lora-net/LoRaMac-node/wiki/LoRaMAC-node-Wiki*/
/* version 4.4.2-rc.5 from develop branch */
/*#define LORA_MAC_VERSION (uint32_t) 0x44250000*/
#define __LORA_MAC_VERSION_MAIN (0x04U) /*!< [31:24] main version */
#define __LORA_MAC_VERSION_SUB1 (0x04U) /*!< [23:16] sub1 version */
#define __LORA_MAC_VERSION_SUB2 (0x02U) /*!< [15:8] sub2 version */
#define __LORA_MAC_VERSION_RC (0x00U) /*!< [7:0] release candidate */
#define __LORA_MAC_VERSION ((__LORA_MAC_VERSION_MAIN <<24)\
|(__LORA_MAC_VERSION_SUB1 << 16)\
|(__LORA_MAC_VERSION_SUB2 << 8 )\
|(__LORA_MAC_VERSION_RC))
/* Exported types ------------------------------------------------------------*/
/* External variables --------------------------------------------------------*/
/* Exported macros -----------------------------------------------------------*/
/* Exported functions ------------------------------------------------------- */
#ifdef __cplusplus
}
#endif
#endif /*__LORA_MAC_VERSION_H__*/
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,546 @@
/*!
* \file RegionAS923.h
*
* \brief Region definition for AS923
*
* \copyright Revised BSD License, see section \ref LICENSE.
*
* \code
* ______ _
* / _____) _ | |
* ( (____ _____ ____ _| |_ _____ ____| |__
* \____ \| ___ | (_ _) ___ |/ ___) _ \
* _____) ) ____| | | || |_| ____( (___| | | |
* (______/|_____)_|_|_| \__)_____)\____)_| |_|
* (C)2013-2017 Semtech
*
* ___ _____ _ ___ _ _____ ___ ___ ___ ___
* / __|_ _/_\ / __| |/ / __/ _ \| _ \/ __| __|
* \__ \ | |/ _ \ (__| ' <| _| (_) | / (__| _|
* |___/ |_/_/ \_\___|_|\_\_| \___/|_|_\\___|___|
* embedded.connectivity.solutions===============
*
* \endcode
*
* \author Miguel Luis ( Semtech )
*
* \author Gregory Cristian ( Semtech )
*
* \author Daniel Jaeckle ( STACKFORCE )
*
* \author Johannes Bruder ( STACKFORCE )
*
* \defgroup REGIONAS923 Region AS923
* Implementation according to LoRaWAN Specification v1.0.2.
* \{
*/
#ifndef __REGION_AS923_H__
#define __REGION_AS923_H__
#include "region/Region.h"
/*!
* LoRaMac maximum number of channels
*/
#define AS923_MAX_NB_CHANNELS 16
/*!
* Number of default channels
*/
#define AS923_NUMB_DEFAULT_CHANNELS 2
/*!
* Number of channels to apply for the CF list
*/
#define AS923_NUMB_CHANNELS_CF_LIST 5
/*!
* Minimal datarate that can be used by the node
*/
#define AS923_TX_MIN_DATARATE DR_0
/*!
* Maximal datarate that can be used by the node
*/
#define AS923_TX_MAX_DATARATE DR_7
/*!
* Minimal datarate that can be used by the node
*/
#define AS923_RX_MIN_DATARATE DR_0
/*!
* Maximal datarate that can be used by the node
*/
#define AS923_RX_MAX_DATARATE DR_7
/*!
* Default datarate used by the node
*/
#define AS923_DEFAULT_DATARATE DR_2
/*!
* The minimum datarate which is used when the
* dwell time is limited.
*/
#define AS923_DWELL_LIMIT_DATARATE DR_2
/*!
* Minimal Rx1 receive datarate offset
*/
#define AS923_MIN_RX1_DR_OFFSET 0
/*!
* Maximal Rx1 receive datarate offset
*/
#define AS923_MAX_RX1_DR_OFFSET 7
/*!
* Default Rx1 receive datarate offset
*/
#define AS923_DEFAULT_RX1_DR_OFFSET 0
/*!
* Minimal Tx output power that can be used by the node
*/
#define AS923_MIN_TX_POWER TX_POWER_7
/*!
* Maximal Tx output power that can be used by the node
*/
#define AS923_MAX_TX_POWER TX_POWER_0
/*!
* Default Tx output power used by the node
*/
#define AS923_DEFAULT_TX_POWER TX_POWER_0
/*!
* Default uplink dwell time configuration
*/
#define AS923_DEFAULT_UPLINK_DWELL_TIME 1
/*!
* Default downlink dwell time configuration
*/
#define AS923_DEFAULT_DOWNLINK_DWELL_TIME 1
/*!
* Default Max EIRP
*/
#define AS923_DEFAULT_MAX_EIRP 16.0f
/*!
* Default antenna gain
*/
#define AS923_DEFAULT_ANTENNA_GAIN 2.15f
/*!
* ADR Ack limit
*/
#define AS923_ADR_ACK_LIMIT 64
/*!
* ADR Ack delay
*/
#define AS923_ADR_ACK_DELAY 32
/*!
* Enabled or disabled the duty cycle
*/
#define AS923_DUTY_CYCLE_ENABLED 0
/*!
* Maximum RX window duration
*/
#define AS923_MAX_RX_WINDOW 3000
/*!
* Receive delay 1
*/
#define AS923_RECEIVE_DELAY1 1000
/*!
* Receive delay 2
*/
#define AS923_RECEIVE_DELAY2 2000
/*!
* Join accept delay 1
*/
#define AS923_JOIN_ACCEPT_DELAY1 5000
/*!
* Join accept delay 2
*/
#define AS923_JOIN_ACCEPT_DELAY2 6000
/*!
* Maximum frame counter gap
*/
#define AS923_MAX_FCNT_GAP 16384
/*!
* Ack timeout
*/
#define AS923_ACKTIMEOUT 2000
/*!
* Random ack timeout limits
*/
#define AS923_ACK_TIMEOUT_RND 1000
#if ( AS923_DEFAULT_DATARATE > DR_5 )
#error "A default DR higher than DR_5 may lead to connectivity loss."
#endif
/*!
* Second reception window channel frequency definition.
*/
#define AS923_RX_WND_2_FREQ 923200000
/*!
* Second reception window channel datarate definition.
*/
#define AS923_RX_WND_2_DR DR_2
/*
* CLASS B
*/
/*!
* Beacon frequency
*/
#define AS923_BEACON_CHANNEL_FREQ 923400000
/*!
* Payload size of a beacon frame
*/
#define AS923_BEACON_SIZE 17
/*!
* Size of RFU 1 field
*/
#define AS923_RFU1_SIZE 2
/*!
* Size of RFU 2 field
*/
#define AS923_RFU2_SIZE 0
/*!
* Datarate of the beacon channel
*/
#define AS923_BEACON_CHANNEL_DR DR_3
/*!
* Bandwith of the beacon channel
*/
#define AS923_BEACON_CHANNEL_BW 0
/*!
* Ping slot channel datarate
*/
#define AS923_PING_SLOT_CHANNEL_DR DR_3
/*!
* Maximum number of bands
*/
#define AS923_MAX_NB_BANDS 1
/*!
* Band 0 definition
* { DutyCycle, TxMaxPower, LastJoinTxDoneTime, LastTxDoneTime, TimeOff }
*/
#define AS923_BAND0 { 100, AS923_MAX_TX_POWER, 0, 0, 0 } // 1.0 %
/*!
* LoRaMac default channel 1
* Channel = { Frequency [Hz], RX1 Frequency [Hz], { ( ( DrMax << 4 ) | DrMin ) }, Band }
*/
#define AS923_LC1 { 923200000, 0, { ( ( DR_5 << 4 ) | DR_0 ) }, 0 }
/*!
* LoRaMac default channel 2
* Channel = { Frequency [Hz], RX1 Frequency [Hz], { ( ( DrMax << 4 ) | DrMin ) }, Band }
*/
#define AS923_LC2 { 923400000, 0, { ( ( DR_5 << 4 ) | DR_0 ) }, 0 }
/*!
* LoRaMac channels which are allowed for the join procedure
*/
#define AS923_JOIN_CHANNELS ( uint16_t )( LC( 1 ) | LC( 2 ) )
/*!
* RSSI threshold for a free channel [dBm]
*/
#define AS923_RSSI_FREE_TH -85
/*!
* Specifies the time the node performs a carrier sense
*/
#define AS923_CARRIER_SENSE_TIME 6
/*!
* Data rates table definition
*/
static const uint8_t DataratesAS923[] = { 12, 11, 10, 9, 8, 7, 7, 50 };
/*!
* Bandwidths table definition in Hz
*/
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.
* The table is valid for the dwell time configuration of 0 for uplinks and downlinks.
*/
static const uint8_t MaxPayloadOfDatarateDwell0AS923[] = { 51, 51, 51, 115, 242, 242, 242, 242 };
/*!
* Maximum payload with respect to the datarate index. Can operate with repeater.
* The table is valid for the dwell time configuration of 0 for uplinks and downlinks. The table provides
* repeater support.
*/
static const uint8_t MaxPayloadOfDatarateRepeaterDwell0AS923[] = { 51, 51, 51, 115, 222, 222, 222, 222 };
/*!
* Maximum payload with respect to the datarate index. Can operate with and without repeater.
* The table proides repeater support. The table is only valid for uplinks.
*/
static const uint8_t MaxPayloadOfDatarateDwell1UpAS923[] = { 0, 0, 11, 53, 125, 242, 242, 242 };
/*!
* Maximum payload with respect to the datarate index. Can operate with and without repeater.
* The table proides repeater support. The table is only valid for downlinks.
*/
static const uint8_t MaxPayloadOfDatarateDwell1DownAS923[] = { 0, 0, 11, 53, 126, 242, 242, 242 };
/*!
* Effective datarate offsets for receive window 1.
*/
static const int8_t EffectiveRx1DrOffsetAS923[] = { 0, 1, 2, 3, 4, 5, -1, -2 };
/*!
* \brief The function gets a value of a specific phy attribute.
*
* \param [IN] getPhy Pointer to the function parameters.
*
* \retval Returns a structure containing the PHY parameter.
*/
PhyParam_t RegionAS923GetPhyParam( GetPhyParams_t* getPhy );
/*!
* \brief Updates the last TX done parameters of the current channel.
*
* \param [IN] txDone Pointer to the function parameters.
*/
void RegionAS923SetBandTxDone( SetBandTxDoneParams_t* txDone );
/*!
* \brief Initializes the channels masks and the channels.
*
* \param [IN] type Sets the initialization type.
*/
void RegionAS923InitDefaults( InitDefaultsParams_t* params );
/*!
* \brief Returns a pointer to the internal context and its size.
*
* \param [OUT] params Pointer to the function parameters.
*
* \retval Points to a structure where the module store its non-volatile context.
*/
void* RegionAS923GetNvmCtx( GetNvmCtxParams_t* params );
/*!
* \brief Verifies a parameter.
*
* \param [IN] verify Pointer to the function parameters.
*
* \param [IN] type Sets the initialization type.
*
* \retval Returns true, if the parameter is valid.
*/
bool RegionAS923Verify( VerifyParams_t* verify, PhyAttribute_t phyAttribute );
/*!
* \brief The function parses the input buffer and sets up the channels of the
* CF list.
*
* \param [IN] applyCFList Pointer to the function parameters.
*/
void RegionAS923ApplyCFList( ApplyCFListParams_t* applyCFList );
/*!
* \brief Sets a channels mask.
*
* \param [IN] chanMaskSet Pointer to the function parameters.
*
* \retval Returns true, if the channels mask could be set.
*/
bool RegionAS923ChanMaskSet( ChanMaskSetParams_t* chanMaskSet );
/*!
* Computes the Rx window timeout and offset.
*
* \param [IN] datarate Rx window datarate index to be used
*
* \param [IN] minRxSymbols Minimum required number of symbols to detect an Rx frame.
*
* \param [IN] rxError System maximum timing error of the receiver. In milliseconds
* The receiver will turn on in a [-rxError : +rxError] ms
* interval around RxOffset
*
* \param [OUT]rxConfigParams Returns updated WindowTimeout and WindowOffset fields.
*/
void RegionAS923ComputeRxWindowParameters( int8_t datarate, uint8_t minRxSymbols, uint32_t rxError, RxConfigParams_t *rxConfigParams );
/*!
* \brief Configuration of the RX windows.
*
* \param [IN] rxConfig Pointer to the function parameters.
*
* \param [OUT] datarate The datarate index which was set.
*
* \retval Returns true, if the configuration was applied successfully.
*/
bool RegionAS923RxConfig( RxConfigParams_t* rxConfig, int8_t* datarate );
/*!
* \brief TX configuration.
*
* \param [IN] txConfig Pointer to the function parameters.
*
* \param [OUT] txPower The tx power index which was set.
*
* \param [OUT] txTimeOnAir The time-on-air of the frame.
*
* \retval Returns true, if the configuration was applied successfully.
*/
bool RegionAS923TxConfig( TxConfigParams_t* txConfig, int8_t* txPower, TimerTime_t* txTimeOnAir );
/*!
* \brief The function processes a Link ADR Request.
*
* \param [IN] linkAdrReq Pointer to the function parameters.
*
* \retval Returns the status of the operation, according to the LoRaMAC specification.
*/
uint8_t RegionAS923LinkAdrReq( LinkAdrReqParams_t* linkAdrReq, int8_t* drOut, int8_t* txPowOut, uint8_t* nbRepOut, uint8_t* nbBytesParsed );
/*!
* \brief The function processes a RX Parameter Setup Request.
*
* \param [IN] rxParamSetupReq Pointer to the function parameters.
*
* \retval Returns the status of the operation, according to the LoRaMAC specification.
*/
uint8_t RegionAS923RxParamSetupReq( RxParamSetupReqParams_t* rxParamSetupReq );
/*!
* \brief The function processes a Channel Request.
*
* \param [IN] newChannelReq Pointer to the function parameters.
*
* \retval Returns the status of the operation, according to the LoRaMAC specification.
*/
uint8_t RegionAS923NewChannelReq( NewChannelReqParams_t* newChannelReq );
/*!
* \brief The function processes a TX ParamSetup Request.
*
* \param [IN] txParamSetupReq Pointer to the function parameters.
*
* \retval Returns the status of the operation, according to the LoRaMAC specification.
* Returns -1, if the functionality is not implemented. In this case, the end node
* shall not process the command.
*/
int8_t RegionAS923TxParamSetupReq( TxParamSetupReqParams_t* txParamSetupReq );
/*!
* \brief The function processes a DlChannel Request.
*
* \param [IN] dlChannelReq Pointer to the function parameters.
*
* \retval Returns the status of the operation, according to the LoRaMAC specification.
*/
uint8_t RegionAS923DlChannelReq( DlChannelReqParams_t* dlChannelReq );
/*!
* \brief Alternates the datarate of the channel for the join request.
*
* \param [IN] currentDr Current datarate.
*
* \retval Datarate to apply.
*/
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
*
* \param [OUT] channel Next channel to use for TX.
*
* \param [OUT] time Time to wait for the next transmission according to the duty
* cycle.
*
* \param [OUT] aggregatedTimeOff Updates the aggregated time off.
*
* \retval Function status [1: OK, 0: Unable to find a channel on the current datarate]
*/
LoRaMacStatus_t RegionAS923NextChannel( NextChanParams_t* nextChanParams, uint8_t* channel, TimerTime_t* time, TimerTime_t* aggregatedTimeOff );
/*!
* \brief Adds a channel.
*
* \param [IN] channelAdd Pointer to the function parameters.
*
* \retval Status of the operation.
*/
LoRaMacStatus_t RegionAS923ChannelAdd( ChannelAddParams_t* channelAdd );
/*!
* \brief Removes a channel.
*
* \param [IN] channelRemove Pointer to the function parameters.
*
* \retval Returns true, if the channel was removed successfully.
*/
bool RegionAS923ChannelsRemove( ChannelRemoveParams_t* channelRemove );
/*!
* \brief Sets the radio into continuous wave mode.
*
* \param [IN] continuousWave Pointer to the function parameters.
*/
void RegionAS923SetContinuousWave( ContinuousWaveParams_t* continuousWave );
/*!
* \brief Computes new datarate according to the given offset
*
* \param [IN] downlinkDwellTime Downlink dwell time configuration. 0: No limit, 1: 400ms
*
* \param [IN] dr Current datarate
*
* \param [IN] drOffset Offset to be applied
*
* \retval newDr Computed datarate.
*/
uint8_t RegionAS923ApplyDrOffset( uint8_t downlinkDwellTime, int8_t dr, int8_t drOffset );
/*!
* \brief Sets the radio into beacon reception mode
*
* \param [IN] rxBeaconSetup Pointer to the function parameters
*/
void RegionAS923RxBeaconSetup( RxBeaconSetup_t* rxBeaconSetup, uint8_t* outDr );
/*! \} defgroup REGIONAS923 */
#endif // __REGION_AS923_H__

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,540 @@
/*!
* \file RegionAU915.h
*
* \brief Region definition for AU915
*
* \copyright Revised BSD License, see section \ref LICENSE.
*
* \code
* ______ _
* / _____) _ | |
* ( (____ _____ ____ _| |_ _____ ____| |__
* \____ \| ___ | (_ _) ___ |/ ___) _ \
* _____) ) ____| | | || |_| ____( (___| | | |
* (______/|_____)_|_|_| \__)_____)\____)_| |_|
* (C)2013-2017 Semtech
*
* ___ _____ _ ___ _ _____ ___ ___ ___ ___
* / __|_ _/_\ / __| |/ / __/ _ \| _ \/ __| __|
* \__ \ | |/ _ \ (__| ' <| _| (_) | / (__| _|
* |___/ |_/_/ \_\___|_|\_\_| \___/|_|_\\___|___|
* embedded.connectivity.solutions===============
*
* \endcode
*
* \author Miguel Luis ( Semtech )
*
* \author Gregory Cristian ( Semtech )
*
* \author Daniel Jaeckle ( STACKFORCE )
*
* \author Johannes Bruder ( STACKFORCE )
*
* \defgroup REGIONAU915 Region AU915
* Implementation according to LoRaWAN Specification v1.0.2.
* \{
*/
#ifndef __REGION_AU915_H__
#define __REGION_AU915_H__
#include "region/Region.h"
/*!
* LoRaMac maximum number of channels
*/
#define AU915_MAX_NB_CHANNELS 72
/*!
* Minimal datarate that can be used by the node
*/
#define AU915_TX_MIN_DATARATE DR_0
/*!
* Maximal datarate that can be used by the node
*/
#define AU915_TX_MAX_DATARATE DR_13
/*!
* Minimal datarate that can be used by the node
*/
#define AU915_RX_MIN_DATARATE DR_8
/*!
* Maximal datarate that can be used by the node
*/
#define AU915_RX_MAX_DATARATE DR_13
/*!
* Default datarate used by the node
*/
#define AU915_DEFAULT_DATARATE DR_2
/*!
* The minimum datarate which is used when the
* dwell time is limited.
*/
#define AU915_DWELL_LIMIT_DATARATE DR_2
/*!
* Minimal Rx1 receive datarate offset
*/
#define AU915_MIN_RX1_DR_OFFSET 0
/*!
* Maximal Rx1 receive datarate offset
*/
#define AU915_MAX_RX1_DR_OFFSET 6
/*!
* Default Rx1 receive datarate offset
*/
#define AU915_DEFAULT_RX1_DR_OFFSET 0
/*!
* Minimal Tx output power that can be used by the node
*/
#define AU915_MIN_TX_POWER TX_POWER_14
/*!
* Maximal Tx output power that can be used by the node
*/
#define AU915_MAX_TX_POWER TX_POWER_0
/*!
* Default Tx output power used by the node
*/
#define AU915_DEFAULT_TX_POWER TX_POWER_0
/*!
* Default uplink dwell time configuration
*/
#define AU915_DEFAULT_UPLINK_DWELL_TIME 1
/*!
* Default downlink dwell time configuration
*/
#define AU915_DEFAULT_DOWNLINK_DWELL_TIME 0
/*!
* Default Max EIRP
*/
#define AU915_DEFAULT_MAX_EIRP 30.0f
/*!
* Default antenna gain
*/
#define AU915_DEFAULT_ANTENNA_GAIN 2.15f
/*!
* ADR Ack limit
*/
#define AU915_ADR_ACK_LIMIT 64
/*!
* ADR Ack delay
*/
#define AU915_ADR_ACK_DELAY 32
/*!
* Enabled or disabled the duty cycle
*/
#define AU915_DUTY_CYCLE_ENABLED 0
/*!
* Maximum RX window duration
*/
#define AU915_MAX_RX_WINDOW 3000
/*!
* Receive delay 1
*/
#define AU915_RECEIVE_DELAY1 1000
/*!
* Receive delay 2
*/
#define AU915_RECEIVE_DELAY2 2000
/*!
* Join accept delay 1
*/
#define AU915_JOIN_ACCEPT_DELAY1 5000
/*!
* Join accept delay 2
*/
#define AU915_JOIN_ACCEPT_DELAY2 6000
/*!
* Maximum frame counter gap
*/
#define AU915_MAX_FCNT_GAP 16384
/*!
* Ack timeout
*/
#define AU915_ACKTIMEOUT 2000
/*!
* Random ack timeout limits
*/
#define AU915_ACK_TIMEOUT_RND 1000
/*!
* Second reception window channel frequency definition.
*/
#define AU915_RX_WND_2_FREQ 923300000
/*!
* Second reception window channel datarate definition.
*/
#define AU915_RX_WND_2_DR DR_8
/*
* CLASS B
*/
/*!
* Beacon frequency
*/
#define AU915_BEACON_CHANNEL_FREQ 923300000
/*!
* Beacon frequency channel stepwidth
*/
#define AU915_BEACON_CHANNEL_STEPWIDTH 600000
/*!
* Number of possible beacon channels
*/
#define AU915_BEACON_NB_CHANNELS 8
/*!
* Payload size of a beacon frame
*/
#define AU915_BEACON_SIZE 19
/*!
* Size of RFU 1 field
*/
#define AU915_RFU1_SIZE 3
/*!
* Size of RFU 2 field
*/
#define AU915_RFU2_SIZE 1
/*!
* Datarate of the beacon channel
*/
#define AU915_BEACON_CHANNEL_DR DR_10
/*!
* Bandwith of the beacon channel
*/
#define AU915_BEACON_CHANNEL_BW 2
/*!
* Ping slot channel datarate
*/
#define AU915_PING_SLOT_CHANNEL_DR DR_10
/*!
* LoRaMac maximum number of bands
*/
#define AU915_MAX_NB_BANDS 1
/*!
* Band 0 definition
* { DutyCycle, TxMaxPower, LastJoinTxDoneTime, LastTxDoneTime, TimeOff }
*/
#define AU915_BAND0 { 1, AU915_MAX_TX_POWER, 0, 0, 0 } // 100.0 %
/*!
* Defines the first channel for RX window 1 for US band
*/
#define AU915_FIRST_RX1_CHANNEL ( (uint32_t) 923300000 )
/*!
* Defines the last channel for RX window 1 for US band
*/
#define AU915_LAST_RX1_CHANNEL ( (uint32_t) 927500000 )
/*!
* Defines the step width of the channels for RX window 1
*/
#define AU915_STEPWIDTH_RX1_CHANNEL ( (uint32_t) 600000 )
/*!
* Data rates table definition
*/
static const uint8_t DataratesAU915[] = { 12, 11, 10, 9, 8, 7, 8, 0, 12, 11, 10, 9, 8, 7, 0, 0 };
/*!
* Bandwidths table definition in Hz
*/
static const uint32_t BandwidthsAU915[] = { 125000, 125000, 125000, 125000, 125000, 125000, 500000, 0, 500000, 500000, 500000, 500000, 500000, 500000, 0, 0 };
/*!
* Up/Down link data rates offset definition
*/
static const int8_t DatarateOffsetsAU915[7][6] =
{
{ DR_8 , DR_8 , DR_8 , DR_8 , DR_8 , DR_8 }, // DR_0
{ DR_9 , DR_8 , DR_8 , DR_8 , DR_8 , DR_8 }, // DR_1
{ DR_10, DR_9 , DR_8 , DR_8 , DR_8 , DR_8 }, // DR_2
{ DR_11, DR_10, DR_9 , DR_8 , DR_8 , DR_8 }, // DR_3
{ DR_12, DR_11, DR_10, DR_9 , DR_8 , DR_8 }, // DR_4
{ DR_13, DR_12, DR_11, DR_10, DR_9 , DR_8 }, // DR_5
{ DR_13, DR_13, DR_12, DR_11, DR_10, DR_9 }, // DR_6
};
/*!
* Maximum payload with respect to the datarate index. Cannot operate with repeater.
* 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, 0, 53, 129, 242, 242, 242, 242 };
/*!
* Maximum payload with respect to the datarate index. Can operate with repeater.
* The table is valid for the dwell time configuration of 0 for uplinks. The table provides
* repeater support.
*/
static const uint8_t MaxPayloadOfDatarateRepeaterDwell0AU915[] = { 51, 51, 51, 115, 222, 222, 222, 0, 33, 109, 222, 222, 222, 222 };
/*!
* Maximum payload with respect to the datarate index. Cannot operate with repeater.
* 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, 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, 109, 222, 222, 222, 222 };
/*!
* \brief The function gets a value of a specific phy attribute.
*
* \param [IN] getPhy Pointer to the function parameters.
*
* \retval Returns a structure containing the PHY parameter.
*/
PhyParam_t RegionAU915GetPhyParam( GetPhyParams_t* getPhy );
/*!
* \brief Updates the last TX done parameters of the current channel.
*
* \param [IN] txDone Pointer to the function parameters.
*/
void RegionAU915SetBandTxDone( SetBandTxDoneParams_t* txDone );
/*!
* \brief Initializes the channels masks and the channels.
*
* \param [IN] type Sets the initialization type.
*/
void RegionAU915InitDefaults( InitDefaultsParams_t* params );
/*!
* \brief Returns a pointer to the internal context and its size.
*
* \param [OUT] params Pointer to the function parameters.
*
* \retval Points to a structure where the module store its non-volatile context.
*/
void* RegionAU915GetNvmCtx( GetNvmCtxParams_t* params );
/*!
* \brief Verifies a parameter.
*
* \param [IN] verify Pointer to the function parameters.
*
* \param [IN] type Sets the initialization type.
*
* \retval Returns true, if the parameter is valid.
*/
bool RegionAU915Verify( VerifyParams_t* verify, PhyAttribute_t phyAttribute );
/*!
* \brief The function parses the input buffer and sets up the channels of the
* CF list.
*
* \param [IN] applyCFList Pointer to the function parameters.
*/
void RegionAU915ApplyCFList( ApplyCFListParams_t* applyCFList );
/*!
* \brief Sets a channels mask.
*
* \param [IN] chanMaskSet Pointer to the function parameters.
*
* \retval Returns true, if the channels mask could be set.
*/
bool RegionAU915ChanMaskSet( ChanMaskSetParams_t* chanMaskSet );
/*!
* Computes the Rx window timeout and offset.
*
* \param [IN] datarate Rx window datarate index to be used
*
* \param [IN] minRxSymbols Minimum required number of symbols to detect an Rx frame.
*
* \param [IN] rxError System maximum timing error of the receiver. In milliseconds
* The receiver will turn on in a [-rxError : +rxError] ms
* interval around RxOffset
*
* \param [OUT]rxConfigParams Returns updated WindowTimeout and WindowOffset fields.
*/
void RegionAU915ComputeRxWindowParameters( int8_t datarate, uint8_t minRxSymbols, uint32_t rxError, RxConfigParams_t *rxConfigParams );
/*!
* \brief Configuration of the RX windows.
*
* \param [IN] rxConfig Pointer to the function parameters.
*
* \param [OUT] datarate The datarate index which was set.
*
* \retval Returns true, if the configuration was applied successfully.
*/
bool RegionAU915RxConfig( RxConfigParams_t* rxConfig, int8_t* datarate );
/*!
* \brief TX configuration.
*
* \param [IN] txConfig Pointer to the function parameters.
*
* \param [OUT] txPower The tx power index which was set.
*
* \param [OUT] txTimeOnAir The time-on-air of the frame.
*
* \retval Returns true, if the configuration was applied successfully.
*/
bool RegionAU915TxConfig( TxConfigParams_t* txConfig, int8_t* txPower, TimerTime_t* txTimeOnAir );
/*!
* \brief The function processes a Link ADR Request.
*
* \param [IN] linkAdrReq Pointer to the function parameters.
*
* \retval Returns the status of the operation, according to the LoRaMAC specification.
*/
uint8_t RegionAU915LinkAdrReq( LinkAdrReqParams_t* linkAdrReq, int8_t* drOut, int8_t* txPowOut, uint8_t* nbRepOut, uint8_t* nbBytesParsed );
/*!
* \brief The function processes a RX Parameter Setup Request.
*
* \param [IN] rxParamSetupReq Pointer to the function parameters.
*
* \retval Returns the status of the operation, according to the LoRaMAC specification.
*/
uint8_t RegionAU915RxParamSetupReq( RxParamSetupReqParams_t* rxParamSetupReq );
/*!
* \brief The function processes a Channel Request.
*
* \param [IN] newChannelReq Pointer to the function parameters.
*
* \retval Returns the status of the operation, according to the LoRaMAC specification.
*/
uint8_t RegionAU915NewChannelReq( NewChannelReqParams_t* newChannelReq );
/*!
* \brief The function processes a TX ParamSetup Request.
*
* \param [IN] txParamSetupReq Pointer to the function parameters.
*
* \retval Returns the status of the operation, according to the LoRaMAC specification.
* Returns -1, if the functionality is not implemented. In this case, the end node
* shall not process the command.
*/
int8_t RegionAU915TxParamSetupReq( TxParamSetupReqParams_t* txParamSetupReq );
/*!
* \brief The function processes a DlChannel Request.
*
* \param [IN] dlChannelReq Pointer to the function parameters.
*
* \retval Returns the status of the operation, according to the LoRaMAC specification.
*/
uint8_t RegionAU915DlChannelReq( DlChannelReqParams_t* dlChannelReq );
/*!
* \brief Alternates the datarate of the channel for the join request.
*
* \param [IN] currentDr Current datarate.
*
* \retval Datarate to apply.
*/
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
*
* \param [OUT] channel Next channel to use for TX.
*
* \param [OUT] time Time to wait for the next transmission according to the duty
* cycle.
*
* \param [OUT] aggregatedTimeOff Updates the aggregated time off.
*
* \retval Function status [1: OK, 0: Unable to find a channel on the current datarate]
*/
LoRaMacStatus_t RegionAU915NextChannel( NextChanParams_t* nextChanParams, uint8_t* channel, TimerTime_t* time, TimerTime_t* aggregatedTimeOff );
/*!
* \brief Adds a channel.
*
* \param [IN] channelAdd Pointer to the function parameters.
*
* \retval Status of the operation.
*/
LoRaMacStatus_t RegionAU915ChannelAdd( ChannelAddParams_t* channelAdd );
/*!
* \brief Removes a channel.
*
* \param [IN] channelRemove Pointer to the function parameters.
*
* \retval Returns true, if the channel was removed successfully.
*/
bool RegionAU915ChannelsRemove( ChannelRemoveParams_t* channelRemove );
/*!
* \brief Sets the radio into continuous wave mode.
*
* \param [IN] continuousWave Pointer to the function parameters.
*/
void RegionAU915SetContinuousWave( ContinuousWaveParams_t* continuousWave );
/*!
* \brief Computes new datarate according to the given offset
*
* \param [IN] downlinkDwellTime Downlink dwell time configuration. 0: No limit, 1: 400ms
*
* \param [IN] dr Current datarate
*
* \param [IN] drOffset Offset to be applied
*
* \retval newDr Computed datarate.
*/
uint8_t RegionAU915ApplyDrOffset( uint8_t downlinkDwellTime, int8_t dr, int8_t drOffset );
/*!
* \brief Sets the radio into beacon reception mode
*
* \param [IN] rxBeaconSetup Pointer to the function parameters
*/
void RegionAU915RxBeaconSetup( RxBeaconSetup_t* rxBeaconSetup, uint8_t* outDr );
/*! \} defgroup REGIONAU915 */
#endif // __REGION_AU915_H__

View File

@@ -0,0 +1,845 @@
/*!
* \file RegionCN470.c
*
* \brief Region implementation for CN470
*
* \copyright Revised BSD License, see section \ref LICENSE.
*
* \code
* ______ _
* / _____) _ | |
* ( (____ _____ ____ _| |_ _____ ____| |__
* \____ \| ___ | (_ _) ___ |/ ___) _ \
* _____) ) ____| | | || |_| ____( (___| | | |
* (______/|_____)_|_|_| \__)_____)\____)_| |_|
* (C)2013-2017 Semtech
*
* ___ _____ _ ___ _ _____ ___ ___ ___ ___
* / __|_ _/_\ / __| |/ / __/ _ \| _ \/ __| __|
* \__ \ | |/ _ \ (__| ' <| _| (_) | / (__| _|
* |___/ |_/_/ \_\___|_|\_\_| \___/|_|_\\___|___|
* embedded.connectivity.solutions===============
*
* \endcode
*
* \author Miguel Luis ( Semtech )
*
* \author Gregory Cristian ( Semtech )
*
* \author Daniel Jaeckle ( STACKFORCE )
*/
#include "utilities.h"
#include "RegionCommon.h"
#include "RegionCN470.h"
#include "lorawan_conf.h"
#include "mw_log_conf.h"
// Definitions
#define CHANNELS_MASK_SIZE 6
/*!
* Region specific context
*/
typedef struct sRegionCN470NvmCtx
{
/*!
* LoRaMAC channels
*/
ChannelParams_t Channels[ CN470_MAX_NB_CHANNELS ];
/*!
* LoRaMac bands
*/
Band_t Bands[ CN470_MAX_NB_BANDS ];
/*!
* LoRaMac channels mask
*/
uint16_t ChannelsMask[ CHANNELS_MASK_SIZE ];
/*!
* LoRaMac channels default mask
*/
uint16_t ChannelsDefaultMask[ CHANNELS_MASK_SIZE ];
}RegionCN470NvmCtx_t;
/*
* Non-volatile module context.
*/
static RegionCN470NvmCtx_t NvmCtx;
// Static functions
static int8_t GetNextLowerTxDr( int8_t dr, int8_t minDr )
{
uint8_t nextLowerDr = 0;
if( dr == minDr )
{
nextLowerDr = minDr;
}
else
{
nextLowerDr = dr - 1;
}
return nextLowerDr;
}
static uint32_t GetBandwidth( uint32_t drIndex )
{
switch( BandwidthsCN470[drIndex] )
{
default:
case 125000:
return 0;
case 250000:
return 1;
case 500000:
return 2;
}
}
static int8_t LimitTxPower( int8_t txPower, int8_t maxBandTxPower, int8_t datarate, uint16_t* channelsMask )
{
int8_t txPowerResult = txPower;
// Limit tx power to the band max
txPowerResult = MAX( txPower, maxBandTxPower );
return txPowerResult;
}
static bool VerifyRfFreq( uint32_t freq )
{
// Check radio driver support
if( Radio.CheckRfFrequency( freq ) == false )
{
return false;
}
// Rx frequencies
if( ( freq < CN470_FIRST_RX1_CHANNEL ) ||
( freq > CN470_LAST_RX1_CHANNEL ) ||
( ( ( freq - ( uint32_t ) CN470_FIRST_RX1_CHANNEL ) % ( uint32_t ) CN470_STEPWIDTH_RX1_CHANNEL ) != 0 ) )
{
return false;
}
// Test for frequency range - take RX and TX freqencies into account
if( ( freq < 470300000 ) || ( freq > 509700000 ) )
{
return false;
}
return true;
}
static uint8_t CountNbOfEnabledChannels( uint8_t datarate, uint16_t* channelsMask, ChannelParams_t* channels, Band_t* bands, uint8_t* enabledChannels, uint8_t* delayTx )
{
uint8_t nbEnabledChannels = 0;
uint8_t delayTransmission = 0;
for( uint8_t i = 0, k = 0; i < CN470_MAX_NB_CHANNELS; i += 16, k++ )
{
for( uint8_t j = 0; j < 16; j++ )
{
if( ( channelsMask[k] & ( 1 << j ) ) != 0 )
{
if( channels[i + j].Frequency == 0 )
{ // Check if the channel is enabled
continue;
}
if( RegionCommonValueInRange( datarate, channels[i + j].DrRange.Fields.Min,
channels[i + j].DrRange.Fields.Max ) == false )
{ // Check if the current channel selection supports the given datarate
continue;
}
if( bands[channels[i + j].Band].TimeOff > 0 )
{ // Check if the band is available for transmission
delayTransmission++;
continue;
}
enabledChannels[nbEnabledChannels++] = i + j;
}
}
}
*delayTx = delayTransmission;
return nbEnabledChannels;
}
PhyParam_t RegionCN470GetPhyParam( GetPhyParams_t* getPhy )
{
PhyParam_t phyParam = { 0 };
switch( getPhy->Attribute )
{
case PHY_MIN_RX_DR:
{
phyParam.Value = CN470_RX_MIN_DATARATE;
break;
}
case PHY_MIN_TX_DR:
{
phyParam.Value = CN470_TX_MIN_DATARATE;
break;
}
case PHY_DEF_TX_DR:
{
phyParam.Value = CN470_DEFAULT_DATARATE;
break;
}
case PHY_NEXT_LOWER_TX_DR:
{
phyParam.Value = GetNextLowerTxDr( getPhy->Datarate, CN470_TX_MIN_DATARATE );
break;
}
case PHY_MAX_TX_POWER:
{
phyParam.Value = CN470_MAX_TX_POWER;
break;
}
case PHY_DEF_TX_POWER:
{
phyParam.Value = CN470_DEFAULT_TX_POWER;
break;
}
case PHY_DEF_ADR_ACK_LIMIT:
{
phyParam.Value = CN470_ADR_ACK_LIMIT;
break;
}
case PHY_DEF_ADR_ACK_DELAY:
{
phyParam.Value = CN470_ADR_ACK_DELAY;
break;
}
case PHY_MAX_PAYLOAD:
{
phyParam.Value = MaxPayloadOfDatarateCN470[getPhy->Datarate];
break;
}
case PHY_MAX_PAYLOAD_REPEATER:
{
phyParam.Value = MaxPayloadOfDatarateRepeaterCN470[getPhy->Datarate];
break;
}
case PHY_DUTY_CYCLE:
{
phyParam.Value = CN470_DUTY_CYCLE_ENABLED;
break;
}
case PHY_MAX_RX_WINDOW:
{
phyParam.Value = CN470_MAX_RX_WINDOW;
break;
}
case PHY_RECEIVE_DELAY1:
{
phyParam.Value = CN470_RECEIVE_DELAY1;
break;
}
case PHY_RECEIVE_DELAY2:
{
phyParam.Value = CN470_RECEIVE_DELAY2;
break;
}
case PHY_JOIN_ACCEPT_DELAY1:
{
phyParam.Value = CN470_JOIN_ACCEPT_DELAY1;
break;
}
case PHY_JOIN_ACCEPT_DELAY2:
{
phyParam.Value = CN470_JOIN_ACCEPT_DELAY2;
break;
}
case PHY_MAX_FCNT_GAP:
{
phyParam.Value = CN470_MAX_FCNT_GAP;
break;
}
case PHY_ACK_TIMEOUT:
{
phyParam.Value = ( CN470_ACKTIMEOUT + randr( -CN470_ACK_TIMEOUT_RND, CN470_ACK_TIMEOUT_RND ) );
break;
}
case PHY_DEF_DR1_OFFSET:
{
phyParam.Value = CN470_DEFAULT_RX1_DR_OFFSET;
break;
}
case PHY_DEF_RX2_FREQUENCY:
{
phyParam.Value = CN470_RX_WND_2_FREQ;
break;
}
case PHY_DEF_RX2_DR:
{
phyParam.Value = CN470_RX_WND_2_DR;
break;
}
case PHY_CHANNELS_MASK:
{
phyParam.ChannelsMask = NvmCtx.ChannelsMask;
break;
}
case PHY_CHANNELS_DEFAULT_MASK:
{
phyParam.ChannelsMask = NvmCtx.ChannelsDefaultMask;
break;
}
case PHY_MAX_NB_CHANNELS:
{
phyParam.Value = CN470_MAX_NB_CHANNELS;
break;
}
case PHY_CHANNELS:
{
phyParam.Channels = NvmCtx.Channels;
break;
}
case PHY_DEF_UPLINK_DWELL_TIME:
case PHY_DEF_DOWNLINK_DWELL_TIME:
{
phyParam.Value = 0;
break;
}
case PHY_DEF_MAX_EIRP:
{
phyParam.fValue = CN470_DEFAULT_MAX_EIRP;
break;
}
case PHY_DEF_ANTENNA_GAIN:
{
phyParam.fValue = CN470_DEFAULT_ANTENNA_GAIN;
break;
}
case PHY_BEACON_FORMAT:
{
phyParam.BeaconFormat.BeaconSize = CN470_BEACON_SIZE;
phyParam.BeaconFormat.Rfu1Size = CN470_RFU1_SIZE;
phyParam.BeaconFormat.Rfu2Size = CN470_RFU2_SIZE;
break;
}
case PHY_BEACON_CHANNEL_DR:
{
phyParam.Value = CN470_BEACON_CHANNEL_DR;
break;
}
case PHY_BEACON_CHANNEL_STEPWIDTH:
{
phyParam.Value = CN470_BEACON_CHANNEL_STEPWIDTH;
break;
}
case PHY_BEACON_NB_CHANNELS:
{
phyParam.Value = CN470_BEACON_NB_CHANNELS;
break;
}
case PHY_PING_SLOT_CHANNEL_DR:
{
phyParam.Value = CN470_PING_SLOT_CHANNEL_DR;
break;
}
default:
{
break;
}
}
return phyParam;
}
void RegionCN470SetBandTxDone( SetBandTxDoneParams_t* txDone )
{
RegionCommonSetBandTxDone( txDone->Joined, &NvmCtx.Bands[NvmCtx.Channels[txDone->Channel].Band], txDone->LastTxDoneTime );
}
void RegionCN470InitDefaults( InitDefaultsParams_t* params )
{
Band_t bands[CN470_MAX_NB_BANDS] =
{
CN470_BAND0
};
switch( params->Type )
{
case INIT_TYPE_INIT:
{
// Initialize bands
memcpy1( ( uint8_t* )NvmCtx.Bands, ( uint8_t* )bands, sizeof( Band_t ) * CN470_MAX_NB_BANDS );
// Channels
// 125 kHz channels
for( uint8_t i = 0; i < CN470_MAX_NB_CHANNELS; i++ )
{
NvmCtx.Channels[i].Frequency = 470300000 + i * 200000;
NvmCtx.Channels[i].DrRange.Value = ( DR_5 << 4 ) | DR_0;
NvmCtx.Channels[i].Band = 0;
}
// Initialize the channels default mask
NvmCtx.ChannelsDefaultMask[0] = 0xFFFF;
NvmCtx.ChannelsDefaultMask[1] = 0xFFFF;
NvmCtx.ChannelsDefaultMask[2] = 0xFFFF;
NvmCtx.ChannelsDefaultMask[3] = 0xFFFF;
NvmCtx.ChannelsDefaultMask[4] = 0xFFFF;
NvmCtx.ChannelsDefaultMask[5] = 0xFFFF;
// Update the channels mask
RegionCommonChanMaskCopy( NvmCtx.ChannelsMask, NvmCtx.ChannelsDefaultMask, 6 );
break;
}
case INIT_TYPE_RESTORE_CTX:
{
if( params->NvmCtx != 0 )
{
memcpy1( (uint8_t*) &NvmCtx, (uint8_t*) params->NvmCtx, sizeof( NvmCtx ) );
}
break;
}
case INIT_TYPE_RESTORE_DEFAULT_CHANNELS:
{
// Restore channels default mask
RegionCommonChanMaskCopy( NvmCtx.ChannelsMask, NvmCtx.ChannelsDefaultMask, 6 );
break;
}
default:
{
break;
}
}
}
void* RegionCN470GetNvmCtx( GetNvmCtxParams_t* params )
{
params->nvmCtxSize = sizeof( RegionCN470NvmCtx_t );
return &NvmCtx;
}
bool RegionCN470Verify( VerifyParams_t* verify, PhyAttribute_t phyAttribute )
{
switch( phyAttribute )
{
case PHY_FREQUENCY:
{
return VerifyRfFreq( verify->Frequency );
}
case PHY_TX_DR:
case PHY_DEF_TX_DR:
{
return RegionCommonValueInRange( verify->DatarateParams.Datarate, CN470_TX_MIN_DATARATE, CN470_TX_MAX_DATARATE );
}
case PHY_RX_DR:
{
return RegionCommonValueInRange( verify->DatarateParams.Datarate, CN470_RX_MIN_DATARATE, CN470_RX_MAX_DATARATE );
}
case PHY_DEF_TX_POWER:
case PHY_TX_POWER:
{
// Remark: switched min and max!
return RegionCommonValueInRange( verify->TxPower, CN470_MAX_TX_POWER, CN470_MIN_TX_POWER );
}
case PHY_DUTY_CYCLE:
{
return CN470_DUTY_CYCLE_ENABLED;
}
default:
return false;
}
}
void RegionCN470ApplyCFList( ApplyCFListParams_t* applyCFList )
{
// Size of the optional CF list must be 16 byte
if( applyCFList->Size != 16 )
{
return;
}
// Last byte CFListType must be 0x01 to indicate the CFList contains a series of ChMask fields
if( applyCFList->Payload[15] != 0x01 )
{
return;
}
// ChMask0 - ChMask5 must be set (every ChMask has 16 bit)
for( uint8_t chMaskItr = 0, cntPayload = 0; chMaskItr <= 5; chMaskItr++, cntPayload+=2 )
{
NvmCtx.ChannelsMask[chMaskItr] = (uint16_t) (0x00FF & applyCFList->Payload[cntPayload]);
NvmCtx.ChannelsMask[chMaskItr] |= (uint16_t) (applyCFList->Payload[cntPayload+1] << 8);
}
}
bool RegionCN470ChanMaskSet( ChanMaskSetParams_t* chanMaskSet )
{
switch( chanMaskSet->ChannelsMaskType )
{
case CHANNELS_MASK:
{
RegionCommonChanMaskCopy( NvmCtx.ChannelsMask, chanMaskSet->ChannelsMaskIn, 6 );
break;
}
case CHANNELS_DEFAULT_MASK:
{
RegionCommonChanMaskCopy( NvmCtx.ChannelsDefaultMask, chanMaskSet->ChannelsMaskIn, 6 );
break;
}
default:
return false;
}
return true;
}
void RegionCN470ComputeRxWindowParameters( int8_t datarate, uint8_t minRxSymbols, uint32_t rxError, RxConfigParams_t *rxConfigParams )
{
double tSymbol = 0.0;
// Get the datarate, perform a boundary check
rxConfigParams->Datarate = MIN( datarate, CN470_RX_MAX_DATARATE );
rxConfigParams->Bandwidth = GetBandwidth( rxConfigParams->Datarate );
tSymbol = RegionCommonComputeSymbolTimeLoRa( DataratesCN470[rxConfigParams->Datarate], BandwidthsCN470[rxConfigParams->Datarate] );
RegionCommonComputeRxWindowParameters( tSymbol, minRxSymbols, rxError, Radio.GetWakeupTime( ), &rxConfigParams->WindowTimeout, &rxConfigParams->WindowOffset );
}
bool RegionCN470RxConfig( RxConfigParams_t* rxConfig, int8_t* datarate )
{
int8_t dr = rxConfig->Datarate;
uint8_t maxPayload = 0;
int8_t phyDr = 0;
uint32_t frequency = rxConfig->Frequency;
const char *slotStrings[] = { "1", "2", "C", "Multi_C", "P", "Multi_P" };
if( Radio.GetStatus( ) != RF_IDLE )
{
return false;
}
if( rxConfig->RxSlot == RX_SLOT_WIN_1 )
{
// Apply window 1 frequency
frequency = CN470_FIRST_RX1_CHANNEL + ( rxConfig->Channel % 48 ) * CN470_STEPWIDTH_RX1_CHANNEL;
}
// Read the physical datarate from the datarates table
phyDr = DataratesCN470[dr];
Radio.SetChannel( frequency );
// Radio configuration
Radio.SetRxConfig( MODEM_LORA, rxConfig->Bandwidth, phyDr, 1, 0, 8, rxConfig->WindowTimeout, false, 0, false, 0, 0, true, rxConfig->RxContinuous );
if( rxConfig->RepeaterSupport == true )
{
maxPayload = MaxPayloadOfDatarateRepeaterCN470[dr];
}
else
{
maxPayload = MaxPayloadOfDatarateCN470[dr];
}
Radio.SetMaxPayloadLength( MODEM_LORA, maxPayload + LORA_MAC_FRMPAYLOAD_OVERHEAD );
if ( rxConfig->RxSlot < RX_SLOT_NONE )
{
MW_LOG( "RX_%s on freq %d Hz at DR %d\n\r", slotStrings[rxConfig->RxSlot], frequency, dr );
}
else
{
MW_LOG( "RX on freq %d Hz at DR %d\n\r", frequency, dr );
}
*datarate = (uint8_t) dr;
return true;
}
bool RegionCN470TxConfig( TxConfigParams_t* txConfig, int8_t* txPower, TimerTime_t* txTimeOnAir )
{
int8_t phyDr = DataratesCN470[txConfig->Datarate];
int8_t txPowerLimited = LimitTxPower( txConfig->TxPower, NvmCtx.Bands[NvmCtx.Channels[txConfig->Channel].Band].TxMaxPower, txConfig->Datarate, NvmCtx.ChannelsMask );
int8_t phyTxPower = 0;
// Calculate physical TX power
phyTxPower = RegionCommonComputeTxPower( txPowerLimited, txConfig->MaxEirp, txConfig->AntennaGain );
// Setup the radio frequency
Radio.SetChannel( NvmCtx.Channels[txConfig->Channel].Frequency );
Radio.SetTxConfig( MODEM_LORA, phyTxPower, 0, 0, phyDr, 1, 8, false, true, 0, 0, false, 4000 );
MW_LOG( "TX on freq %d Hz at DR %d\n\r", NvmCtx.Channels[txConfig->Channel].Frequency, txConfig->Datarate );
// Setup maximum payload lenght of the radio driver
Radio.SetMaxPayloadLength( MODEM_LORA, txConfig->PktLen );
// Get the time-on-air of the next tx frame
*txTimeOnAir = Radio.TimeOnAir( MODEM_LORA, txConfig->PktLen );
*txPower = txPowerLimited;
return true;
}
uint8_t RegionCN470LinkAdrReq( LinkAdrReqParams_t* linkAdrReq, int8_t* drOut, int8_t* txPowOut, uint8_t* nbRepOut, uint8_t* nbBytesParsed )
{
uint8_t status = 0x07;
RegionCommonLinkAdrParams_t linkAdrParams;
uint8_t nextIndex = 0;
uint8_t bytesProcessed = 0;
uint16_t channelsMask[6] = { 0, 0, 0, 0, 0, 0 };
GetPhyParams_t getPhy;
PhyParam_t phyParam;
RegionCommonLinkAdrReqVerifyParams_t linkAdrVerifyParams;
// Initialize local copy of channels mask
RegionCommonChanMaskCopy( channelsMask, NvmCtx.ChannelsMask, 6 );
while( bytesProcessed < linkAdrReq->PayloadSize )
{
// Get ADR request parameters
nextIndex = RegionCommonParseLinkAdrReq( &( linkAdrReq->Payload[bytesProcessed] ), &linkAdrParams );
if( nextIndex == 0 )
break; // break loop, since no more request has been found
// Update bytes processed
bytesProcessed += nextIndex;
// Revert status, as we only check the last ADR request for the channel mask KO
status = 0x07;
if( linkAdrParams.ChMaskCtrl == 6 )
{
// Enable all 125 kHz channels
channelsMask[0] = 0xFFFF;
channelsMask[1] = 0xFFFF;
channelsMask[2] = 0xFFFF;
channelsMask[3] = 0xFFFF;
channelsMask[4] = 0xFFFF;
channelsMask[5] = 0xFFFF;
}
else if( linkAdrParams.ChMaskCtrl == 7 )
{
status &= 0xFE; // Channel mask KO
}
else
{
for( uint8_t i = 0; i < 16; i++ )
{
if( ( ( linkAdrParams.ChMask & ( 1 << i ) ) != 0 ) &&
( NvmCtx.Channels[linkAdrParams.ChMaskCtrl * 16 + i].Frequency == 0 ) )
{// Trying to enable an undefined channel
status &= 0xFE; // Channel mask KO
}
}
channelsMask[linkAdrParams.ChMaskCtrl] = linkAdrParams.ChMask;
}
}
// Get the minimum possible datarate
getPhy.Attribute = PHY_MIN_TX_DR;
getPhy.UplinkDwellTime = linkAdrReq->UplinkDwellTime;
phyParam = RegionCN470GetPhyParam( &getPhy );
linkAdrVerifyParams.Status = status;
linkAdrVerifyParams.AdrEnabled = linkAdrReq->AdrEnabled;
linkAdrVerifyParams.Datarate = linkAdrParams.Datarate;
linkAdrVerifyParams.TxPower = linkAdrParams.TxPower;
linkAdrVerifyParams.NbRep = linkAdrParams.NbRep;
linkAdrVerifyParams.CurrentDatarate = linkAdrReq->CurrentDatarate;
linkAdrVerifyParams.CurrentTxPower = linkAdrReq->CurrentTxPower;
linkAdrVerifyParams.CurrentNbRep = linkAdrReq->CurrentNbRep;
linkAdrVerifyParams.NbChannels = CN470_MAX_NB_CHANNELS;
linkAdrVerifyParams.ChannelsMask = channelsMask;
linkAdrVerifyParams.MinDatarate = ( int8_t )phyParam.Value;
linkAdrVerifyParams.MaxDatarate = CN470_TX_MAX_DATARATE;
linkAdrVerifyParams.Channels = NvmCtx.Channels;
linkAdrVerifyParams.MinTxPower = CN470_MIN_TX_POWER;
linkAdrVerifyParams.MaxTxPower = CN470_MAX_TX_POWER;
linkAdrVerifyParams.Version = linkAdrReq->Version;
// Verify the parameters and update, if necessary
status = RegionCommonLinkAdrReqVerifyParams( &linkAdrVerifyParams, &linkAdrParams.Datarate, &linkAdrParams.TxPower, &linkAdrParams.NbRep );
// Update channelsMask if everything is correct
if( status == 0x07 )
{
// Copy Mask
RegionCommonChanMaskCopy( NvmCtx.ChannelsMask, channelsMask, 6 );
}
// Update status variables
*drOut = linkAdrParams.Datarate;
*txPowOut = linkAdrParams.TxPower;
*nbRepOut = linkAdrParams.NbRep;
*nbBytesParsed = bytesProcessed;
return status;
}
uint8_t RegionCN470RxParamSetupReq( RxParamSetupReqParams_t* rxParamSetupReq )
{
uint8_t status = 0x07;
// Verify radio frequency
if( VerifyRfFreq( rxParamSetupReq->Frequency ) == false )
{
status &= 0xFE; // Channel frequency KO
}
// Verify datarate
if( RegionCommonValueInRange( rxParamSetupReq->Datarate, CN470_RX_MIN_DATARATE, CN470_RX_MAX_DATARATE ) == false )
{
status &= 0xFD; // Datarate KO
}
// Verify datarate offset
if( RegionCommonValueInRange( rxParamSetupReq->DrOffset, CN470_MIN_RX1_DR_OFFSET, CN470_MAX_RX1_DR_OFFSET ) == false )
{
status &= 0xFB; // Rx1DrOffset range KO
}
return status;
}
uint8_t RegionCN470NewChannelReq( NewChannelReqParams_t* newChannelReq )
{
// Datarate and frequency KO
return 0;
}
int8_t RegionCN470TxParamSetupReq( TxParamSetupReqParams_t* txParamSetupReq )
{
return -1;
}
uint8_t RegionCN470DlChannelReq( DlChannelReqParams_t* dlChannelReq )
{
return 0;
}
int8_t RegionCN470AlternateDr( int8_t currentDr, AlternateDrType_t type )
{
return currentDr;
}
void RegionCN470CalcBackOff( CalcBackOffParams_t* calcBackOff )
{
RegionCommonCalcBackOffParams_t calcBackOffParams;
calcBackOffParams.Channels = NvmCtx.Channels;
calcBackOffParams.Bands = NvmCtx.Bands;
calcBackOffParams.LastTxIsJoinRequest = calcBackOff->LastTxIsJoinRequest;
calcBackOffParams.Joined = calcBackOff->Joined;
calcBackOffParams.DutyCycleEnabled = calcBackOff->DutyCycleEnabled;
calcBackOffParams.Channel = calcBackOff->Channel;
calcBackOffParams.ElapsedTime = calcBackOff->ElapsedTime;
calcBackOffParams.TxTimeOnAir = calcBackOff->TxTimeOnAir;
RegionCommonCalcBackOff( &calcBackOffParams );
}
LoRaMacStatus_t RegionCN470NextChannel( NextChanParams_t* nextChanParams, uint8_t* channel, TimerTime_t* time, TimerTime_t* aggregatedTimeOff )
{
uint8_t nbEnabledChannels = 0;
uint8_t delayTx = 0;
uint8_t enabledChannels[CN470_MAX_NB_CHANNELS] = { 0 };
TimerTime_t nextTxDelay = 0;
// Count 125kHz channels
if( RegionCommonCountChannels( NvmCtx.ChannelsMask, 0, 6 ) == 0 )
{ // Reactivate default channels
NvmCtx.ChannelsMask[0] = 0xFFFF;
NvmCtx.ChannelsMask[1] = 0xFFFF;
NvmCtx.ChannelsMask[2] = 0xFFFF;
NvmCtx.ChannelsMask[3] = 0xFFFF;
NvmCtx.ChannelsMask[4] = 0xFFFF;
NvmCtx.ChannelsMask[5] = 0xFFFF;
}
TimerTime_t elapsed = TimerGetElapsedTime( nextChanParams->LastAggrTx );
if( ( nextChanParams->LastAggrTx == 0 ) || ( nextChanParams->AggrTimeOff <= elapsed ) )
{
// 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
nbEnabledChannels = CountNbOfEnabledChannels( nextChanParams->Datarate,
NvmCtx.ChannelsMask, NvmCtx.Channels,
NvmCtx.Bands, enabledChannels, &delayTx );
}
else
{
delayTx++;
nextTxDelay = nextChanParams->AggrTimeOff - elapsed;
}
if( nbEnabledChannels > 0 )
{
// We found a valid channel
*channel = enabledChannels[randr( 0, nbEnabledChannels - 1 )];
*time = 0;
return LORAMAC_STATUS_OK;
}
else
{
if( delayTx > 0 )
{
// Delay transmission due to AggregatedTimeOff or to a band time off
*time = nextTxDelay;
return LORAMAC_STATUS_DUTYCYCLE_RESTRICTED;
}
// Datarate not supported by any channel
*time = 0;
return LORAMAC_STATUS_NO_CHANNEL_FOUND;
}
}
LoRaMacStatus_t RegionCN470ChannelAdd( ChannelAddParams_t* channelAdd )
{
return LORAMAC_STATUS_PARAMETER_INVALID;
}
bool RegionCN470ChannelsRemove( ChannelRemoveParams_t* channelRemove )
{
return LORAMAC_STATUS_PARAMETER_INVALID;
}
void RegionCN470SetContinuousWave( ContinuousWaveParams_t* continuousWave )
{
int8_t txPowerLimited = LimitTxPower( continuousWave->TxPower, NvmCtx.Bands[NvmCtx.Channels[continuousWave->Channel].Band].TxMaxPower, continuousWave->Datarate, NvmCtx.ChannelsMask );
int8_t phyTxPower = 0;
uint32_t frequency = NvmCtx.Channels[continuousWave->Channel].Frequency;
// Calculate physical TX power
phyTxPower = RegionCommonComputeTxPower( txPowerLimited, continuousWave->MaxEirp, continuousWave->AntennaGain );
Radio.SetTxContinuousWave( frequency, phyTxPower, continuousWave->Timeout );
}
uint8_t RegionCN470ApplyDrOffset( uint8_t downlinkDwellTime, int8_t dr, int8_t drOffset )
{
int8_t datarate = dr - drOffset;
if( datarate < 0 )
{
datarate = DR_0;
}
return datarate;
}
void RegionCN470RxBeaconSetup( RxBeaconSetup_t* rxBeaconSetup, uint8_t* outDr )
{
RegionCommonRxBeaconSetupParams_t regionCommonRxBeaconSetup;
regionCommonRxBeaconSetup.Datarates = DataratesCN470;
regionCommonRxBeaconSetup.Frequency = rxBeaconSetup->Frequency;
regionCommonRxBeaconSetup.BeaconSize = CN470_BEACON_SIZE;
regionCommonRxBeaconSetup.BeaconDatarate = CN470_BEACON_CHANNEL_DR;
regionCommonRxBeaconSetup.BeaconChannelBW = CN470_BEACON_CHANNEL_BW;
regionCommonRxBeaconSetup.RxTime = rxBeaconSetup->RxTime;
regionCommonRxBeaconSetup.SymbolTimeout = rxBeaconSetup->SymbolTimeout;
RegionCommonRxBeaconSetup( &regionCommonRxBeaconSetup );
// Store downlink datarate
*outDr = CN470_BEACON_CHANNEL_DR;
}

View File

@@ -0,0 +1,494 @@
/*!
* \file RegionCN470.h
*
* \brief Region definition for CN470
*
* \copyright Revised BSD License, see section \ref LICENSE.
*
* \code
* ______ _
* / _____) _ | |
* ( (____ _____ ____ _| |_ _____ ____| |__
* \____ \| ___ | (_ _) ___ |/ ___) _ \
* _____) ) ____| | | || |_| ____( (___| | | |
* (______/|_____)_|_|_| \__)_____)\____)_| |_|
* (C)2013-2017 Semtech
*
* ___ _____ _ ___ _ _____ ___ ___ ___ ___
* / __|_ _/_\ / __| |/ / __/ _ \| _ \/ __| __|
* \__ \ | |/ _ \ (__| ' <| _| (_) | / (__| _|
* |___/ |_/_/ \_\___|_|\_\_| \___/|_|_\\___|___|
* embedded.connectivity.solutions===============
*
* \endcode
*
* \author Miguel Luis ( Semtech )
*
* \author Gregory Cristian ( Semtech )
*
* \author Daniel Jaeckle ( STACKFORCE )
*
* \author Johannes Bruder ( STACKFORCE )
*
* \defgroup REGIONCN470 Region CN470
* Implementation according to LoRaWAN Specification v1.0.2.
* \{
*/
#ifndef __REGION_CN470_H__
#define __REGION_CN470_H__
#include "region/Region.h"
/*!
* LoRaMac maximum number of channels
*/
#define CN470_MAX_NB_CHANNELS 96
/*!
* Minimal datarate that can be used by the node
*/
#define CN470_TX_MIN_DATARATE DR_0
/*!
* Maximal datarate that can be used by the node
*/
#define CN470_TX_MAX_DATARATE DR_5
/*!
* Minimal datarate that can be used by the node
*/
#define CN470_RX_MIN_DATARATE DR_0
/*!
* Maximal datarate that can be used by the node
*/
#define CN470_RX_MAX_DATARATE DR_5
/*!
* Default datarate used by the node
*/
#define CN470_DEFAULT_DATARATE DR_0
/*!
* Minimal Rx1 receive datarate offset
*/
#define CN470_MIN_RX1_DR_OFFSET 0
/*!
* Maximal Rx1 receive datarate offset
*/
#define CN470_MAX_RX1_DR_OFFSET 3
/*!
* Default Rx1 receive datarate offset
*/
#define CN470_DEFAULT_RX1_DR_OFFSET 0
/*!
* Minimal Tx output power that can be used by the node
*/
#define CN470_MIN_TX_POWER TX_POWER_7
/*!
* Maximal Tx output power that can be used by the node
*/
#define CN470_MAX_TX_POWER TX_POWER_0
/*!
* Default Tx output power used by the node
*/
#define CN470_DEFAULT_TX_POWER TX_POWER_0
/*!
* Default Max EIRP
*/
#define CN470_DEFAULT_MAX_EIRP 19.15f
/*!
* Default antenna gain
*/
#define CN470_DEFAULT_ANTENNA_GAIN 2.15f
/*!
* ADR Ack limit
*/
#define CN470_ADR_ACK_LIMIT 64
/*!
* ADR Ack delay
*/
#define CN470_ADR_ACK_DELAY 32
/*!
* Enabled or disabled the duty cycle
*/
#define CN470_DUTY_CYCLE_ENABLED 0
/*!
* Maximum RX window duration
*/
#define CN470_MAX_RX_WINDOW 3000
/*!
* Receive delay 1
*/
#define CN470_RECEIVE_DELAY1 1000
/*!
* Receive delay 2
*/
#define CN470_RECEIVE_DELAY2 2000
/*!
* Join accept delay 1
*/
#define CN470_JOIN_ACCEPT_DELAY1 5000
/*!
* Join accept delay 2
*/
#define CN470_JOIN_ACCEPT_DELAY2 6000
/*!
* Maximum frame counter gap
*/
#define CN470_MAX_FCNT_GAP 16384
/*!
* Ack timeout
*/
#define CN470_ACKTIMEOUT 2000
/*!
* Random ack timeout limits
*/
#define CN470_ACK_TIMEOUT_RND 1000
/*!
* Second reception window channel frequency definition.
*/
#define CN470_RX_WND_2_FREQ 505300000
/*!
* Second reception window channel datarate definition.
*/
#define CN470_RX_WND_2_DR DR_0
/*
* CLASS B
*/
/*!
* Beacon frequency
*/
#define CN470_BEACON_CHANNEL_FREQ 508300000
/*!
* Beacon frequency channel stepwidth
*/
#define CN470_BEACON_CHANNEL_STEPWIDTH 200000
/*!
* Number of possible beacon channels
*/
#define CN470_BEACON_NB_CHANNELS 8
/*!
* Payload size of a beacon frame
*/
#define CN470_BEACON_SIZE 19
/*!
* Size of RFU 1 field
*/
#define CN470_RFU1_SIZE 3
/*!
* Size of RFU 2 field
*/
#define CN470_RFU2_SIZE 1
/*!
* Datarate of the beacon channel
*/
#define CN470_BEACON_CHANNEL_DR DR_2
/*!
* Bandwith of the beacon channel
*/
#define CN470_BEACON_CHANNEL_BW 0
/*!
* Ping slot channel datarate
*/
#define CN470_PING_SLOT_CHANNEL_DR DR_2
/*!
* LoRaMac maximum number of bands
*/
#define CN470_MAX_NB_BANDS 1
/*!
* Band 0 definition
* { DutyCycle, TxMaxPower, LastJoinTxDoneTime, LastTxDoneTime, TimeOff }
*/
#define CN470_BAND0 { 1, CN470_MAX_TX_POWER, 0, 0, 0 } // 100.0 %
/*!
* Defines the first channel for RX window 1 for CN470 band
*/
#define CN470_FIRST_RX1_CHANNEL ( (uint32_t) 500300000 )
/*!
* Defines the last channel for RX window 1 for CN470 band
*/
#define CN470_LAST_RX1_CHANNEL ( (uint32_t) 509700000 )
/*!
* Defines the step width of the channels for RX window 1
*/
#define CN470_STEPWIDTH_RX1_CHANNEL ( (uint32_t) 200000 )
/*!
* Data rates table definition
*/
static const uint8_t DataratesCN470[] = { 12, 11, 10, 9, 8, 7 };
/*!
* Bandwidths table definition in Hz
*/
static const uint32_t BandwidthsCN470[] = { 125000, 125000, 125000, 125000, 125000, 125000 };
/*!
* Maximum payload with respect to the datarate index. Cannot operate with repeater.
*/
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.
*
* \param [IN] getPhy Pointer to the function parameters.
*
* \retval Returns a structure containing the PHY parameter.
*/
PhyParam_t RegionCN470GetPhyParam( GetPhyParams_t* getPhy );
/*!
* \brief Updates the last TX done parameters of the current channel.
*
* \param [IN] txDone Pointer to the function parameters.
*/
void RegionCN470SetBandTxDone( SetBandTxDoneParams_t* txDone );
/*!
* \brief Initializes the channels masks and the channels.
*
* \param [IN] type Sets the initialization type.
*/
void RegionCN470InitDefaults( InitDefaultsParams_t* params );
/*!
* \brief Returns a pointer to the internal context and its size.
*
* \param [OUT] params Pointer to the function parameters.
*
* \retval Points to a structure where the module store its non-volatile context.
*/
void* RegionCN470GetNvmCtx( GetNvmCtxParams_t* params );
/*!
* \brief Verifies a parameter.
*
* \param [IN] verify Pointer to the function parameters.
*
* \param [IN] type Sets the initialization type.
*
* \retval Returns true, if the parameter is valid.
*/
bool RegionCN470Verify( VerifyParams_t* verify, PhyAttribute_t phyAttribute );
/*!
* \brief The function parses the input buffer and sets up the channels of the
* CF list.
*
* \param [IN] applyCFList Pointer to the function parameters.
*/
void RegionCN470ApplyCFList( ApplyCFListParams_t* applyCFList );
/*!
* \brief Sets a channels mask.
*
* \param [IN] chanMaskSet Pointer to the function parameters.
*
* \retval Returns true, if the channels mask could be set.
*/
bool RegionCN470ChanMaskSet( ChanMaskSetParams_t* chanMaskSet );
/*!
* Computes the Rx window timeout and offset.
*
* \param [IN] datarate Rx window datarate index to be used
*
* \param [IN] minRxSymbols Minimum required number of symbols to detect an Rx frame.
*
* \param [IN] rxError System maximum timing error of the receiver. In milliseconds
* The receiver will turn on in a [-rxError : +rxError] ms
* interval around RxOffset
*
* \param [OUT]rxConfigParams Returns updated WindowTimeout and WindowOffset fields.
*/
void RegionCN470ComputeRxWindowParameters( int8_t datarate, uint8_t minRxSymbols, uint32_t rxError, RxConfigParams_t *rxConfigParams );
/*!
* \brief Configuration of the RX windows.
*
* \param [IN] rxConfig Pointer to the function parameters.
*
* \param [OUT] datarate The datarate index which was set.
*
* \retval Returns true, if the configuration was applied successfully.
*/
bool RegionCN470RxConfig( RxConfigParams_t* rxConfig, int8_t* datarate );
/*!
* \brief TX configuration.
*
* \param [IN] txConfig Pointer to the function parameters.
*
* \param [OUT] txPower The tx power index which was set.
*
* \param [OUT] txTimeOnAir The time-on-air of the frame.
*
* \retval Returns true, if the configuration was applied successfully.
*/
bool RegionCN470TxConfig( TxConfigParams_t* txConfig, int8_t* txPower, TimerTime_t* txTimeOnAir );
/*!
* \brief The function processes a Link ADR Request.
*
* \param [IN] linkAdrReq Pointer to the function parameters.
*
* \retval Returns the status of the operation, according to the LoRaMAC specification.
*/
uint8_t RegionCN470LinkAdrReq( LinkAdrReqParams_t* linkAdrReq, int8_t* drOut, int8_t* txPowOut, uint8_t* nbRepOut, uint8_t* nbBytesParsed );
/*!
* \brief The function processes a RX Parameter Setup Request.
*
* \param [IN] rxParamSetupReq Pointer to the function parameters.
*
* \retval Returns the status of the operation, according to the LoRaMAC specification.
*/
uint8_t RegionCN470RxParamSetupReq( RxParamSetupReqParams_t* rxParamSetupReq );
/*!
* \brief The function processes a Channel Request.
*
* \param [IN] newChannelReq Pointer to the function parameters.
*
* \retval Returns the status of the operation, according to the LoRaMAC specification.
*/
uint8_t RegionCN470NewChannelReq( NewChannelReqParams_t* newChannelReq );
/*!
* \brief The function processes a TX ParamSetup Request.
*
* \param [IN] txParamSetupReq Pointer to the function parameters.
*
* \retval Returns the status of the operation, according to the LoRaMAC specification.
* Returns -1, if the functionality is not implemented. In this case, the end node
* shall not process the command.
*/
int8_t RegionCN470TxParamSetupReq( TxParamSetupReqParams_t* txParamSetupReq );
/*!
* \brief The function processes a DlChannel Request.
*
* \param [IN] dlChannelReq Pointer to the function parameters.
*
* \retval Returns the status of the operation, according to the LoRaMAC specification.
*/
uint8_t RegionCN470DlChannelReq( DlChannelReqParams_t* dlChannelReq );
/*!
* \brief Alternates the datarate of the channel for the join request.
*
* \param [IN] currentDr Current datarate.
*
* \retval Datarate to apply.
*/
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
*
* \param [OUT] channel Next channel to use for TX.
*
* \param [OUT] time Time to wait for the next transmission according to the duty
* cycle.
*
* \param [OUT] aggregatedTimeOff Updates the aggregated time off.
*
* \retval Function status [1: OK, 0: Unable to find a channel on the current datarate]
*/
LoRaMacStatus_t RegionCN470NextChannel( NextChanParams_t* nextChanParams, uint8_t* channel, TimerTime_t* time, TimerTime_t* aggregatedTimeOff );
/*!
* \brief Adds a channel.
*
* \param [IN] channelAdd Pointer to the function parameters.
*
* \retval Status of the operation.
*/
LoRaMacStatus_t RegionCN470ChannelAdd( ChannelAddParams_t* channelAdd );
/*!
* \brief Removes a channel.
*
* \param [IN] channelRemove Pointer to the function parameters.
*
* \retval Returns true, if the channel was removed successfully.
*/
bool RegionCN470ChannelsRemove( ChannelRemoveParams_t* channelRemove );
/*!
* \brief Sets the radio into continuous wave mode.
*
* \param [IN] continuousWave Pointer to the function parameters.
*/
void RegionCN470SetContinuousWave( ContinuousWaveParams_t* continuousWave );
/*!
* \brief Computes new datarate according to the given offset
*
* \param [IN] downlinkDwellTime Downlink dwell time configuration. 0: No limit, 1: 400ms
*
* \param [IN] dr Current datarate
*
* \param [IN] drOffset Offset to be applied
*
* \retval newDr Computed datarate.
*/
uint8_t RegionCN470ApplyDrOffset( uint8_t downlinkDwellTime, int8_t dr, int8_t drOffset );
/*!
* \brief Sets the radio into beacon reception mode
*
* \param [IN] rxBeaconSetup Pointer to the function parameters
*/
void RegionCN470RxBeaconSetup( RxBeaconSetup_t* rxBeaconSetup, uint8_t* outDr );
/*! \} defgroup REGIONCN470 */
#endif // __REGION_CN470_H__

View File

@@ -0,0 +1,895 @@
/*!
* \file RegionCN470ALIALI.c
*
* \brief Region implementation for CN470ALIALI
*
* \copyright Revised BSD License, see section \ref LICENSE.
*
* \code
* ______ _
* / _____) _ | |
* ( (____ _____ ____ _| |_ _____ ____| |__
* \____ \| ___ | (_ _) ___ |/ ___) _ \
* _____) ) ____| | | || |_| ____( (___| | | |
* (______/|_____)_|_|_| \__)_____)\____)_| |_|
* (C)2013-2017 Semtech
*
* ___ _____ _ ___ _ _____ ___ ___ ___ ___
* / __|_ _/_\ / __| |/ / __/ _ \| _ \/ __| __|
* \__ \ | |/ _ \ (__| ' <| _| (_) | / (__| _|
* |___/ |_/_/ \_\___|_|\_\_| \___/|_|_\\___|___|
* embedded.connectivity.solutions===============
*
* \endcode
*
* \author Miguel Luis ( Semtech )
*
* \author Gregory Cristian ( Semtech )
*
* \author Daniel Jaeckle ( STACKFORCE )
*/
#include "utilities.h"
#include "RegionCommon.h"
#include "RegionCN470ALI.h"
#include "lorawan_conf.h"
#include "mw_log_conf.h"
// Definitions
#define CHANNELS_MASK_SIZE 6
/*!
* Region specific context
*/
typedef struct sRegionCN470ALINvmCtx
{
/*!
* LoRaMAC channels
*/
ChannelParams_t Channels[ CN470ALI_MAX_NB_CHANNELS ];
/*!
* LoRaMac bands
*/
Band_t Bands[ CN470ALI_MAX_NB_BANDS ];
/*!
* LoRaMac channels mask
*/
uint16_t ChannelsMask[ CHANNELS_MASK_SIZE ];
/*!
* LoRaMac channels default mask
*/
uint16_t ChannelsDefaultMask[ CHANNELS_MASK_SIZE ];
}RegionCN470ALINvmCtx_t;
/*
* Non-volatile module context.
*/
static RegionCN470ALINvmCtx_t NvmCtx;
// Static functions
static int8_t GetNextLowerTxDr( int8_t dr, int8_t minDr )
{
uint8_t nextLowerDr = 0;
if( dr == minDr )
{
nextLowerDr = minDr;
}
else
{
nextLowerDr = dr - 1;
}
return nextLowerDr;
}
static uint32_t GetBandwidth( uint32_t drIndex )
{
switch( BandwidthsCN470ALI[drIndex] )
{
default:
case 125000:
return 0;
case 250000:
return 1;
case 500000:
return 2;
}
}
static int8_t LimitTxPower( int8_t txPower, int8_t maxBandTxPower, int8_t datarate, uint16_t* channelsMask )
{
int8_t txPowerResult = txPower;
// Limit tx power to the band max
txPowerResult = MAX( txPower, maxBandTxPower );
return txPowerResult;
}
static bool VerifyRfFreq( uint32_t freq )
{
// Check radio driver support
if( Radio.CheckRfFrequency( freq ) == false )
{
return false;
}
#if ((ALI_DOWNLINK_FREQ == ALI_FREQ470_S) || (ALI_DOWNLINK_FREQ == ALI_FREQ480_D))
// Rx frequencies
if((freq < 503500000) && (freq >476500000))
{
return false;
}
#endif
// Rx frequencies
if( ( freq < CN470ALI_FIRST_RX1_CHANNEL ) ||
( freq > CN470ALI_LAST_RX1_CHANNEL ) ||
( ( ( freq - ( uint32_t ) CN470ALI_FIRST_RX1_CHANNEL ) % ( uint32_t ) CN470ALI_STEPWIDTH_RX1_CHANNEL ) != 0 ) )
{
return false;
}
// Test for frequency range - take RX and TX freqencies into account
if( ( freq < 470300000 ) || ( freq > 509700000 ) )
{
return false;
}
return true;
}
static uint8_t CountNbOfEnabledChannels( uint8_t datarate, uint16_t* channelsMask, ChannelParams_t* channels, Band_t* bands, uint8_t* enabledChannels, uint8_t* delayTx )
{
uint8_t nbEnabledChannels = 0;
uint8_t delayTransmission = 0;
for( uint8_t i = 0, k = 0; i < CN470ALI_MAX_NB_CHANNELS; i += 16, k++ )
{
for( uint8_t j = 0; j < 16; j++ )
{
if( ( channelsMask[k] & ( 1 << j ) ) != 0 )
{
if( channels[i + j].Frequency == 0 )
{ // Check if the channel is enabled
continue;
}
if( RegionCommonValueInRange( datarate, channels[i + j].DrRange.Fields.Min,
channels[i + j].DrRange.Fields.Max ) == false )
{ // Check if the current channel selection supports the given datarate
continue;
}
if( bands[channels[i + j].Band].TimeOff > 0 )
{ // Check if the band is available for transmission
delayTransmission++;
continue;
}
enabledChannels[nbEnabledChannels++] = i + j;
}
}
}
*delayTx = delayTransmission;
return nbEnabledChannels;
}
PhyParam_t RegionCN470ALIGetPhyParam( GetPhyParams_t* getPhy )
{
PhyParam_t phyParam = { 0 };
switch( getPhy->Attribute )
{
case PHY_MIN_RX_DR:
{
phyParam.Value = CN470ALI_RX_MIN_DATARATE;
break;
}
case PHY_MIN_TX_DR:
{
phyParam.Value = CN470ALI_TX_MIN_DATARATE;
break;
}
case PHY_DEF_TX_DR:
{
phyParam.Value = CN470ALI_DEFAULT_DATARATE;
break;
}
case PHY_NEXT_LOWER_TX_DR:
{
/*next low speed*/
phyParam.Value = GetNextLowerTxDr( getPhy->Datarate, DR_0);
break;
}
case PHY_MAX_TX_POWER:
{
phyParam.Value = CN470ALI_MAX_TX_POWER;
break;
}
case PHY_DEF_TX_POWER:
{
phyParam.Value = CN470ALI_DEFAULT_TX_POWER;
break;
}
case PHY_DEF_ADR_ACK_LIMIT:
{
phyParam.Value = CN470ALI_ADR_ACK_LIMIT;
break;
}
case PHY_DEF_ADR_ACK_DELAY:
{
phyParam.Value = CN470ALI_ADR_ACK_DELAY;
break;
}
case PHY_MAX_PAYLOAD:
{
phyParam.Value = MaxPayloadOfDatarateCN470ALI[getPhy->Datarate];
break;
}
case PHY_MAX_PAYLOAD_REPEATER:
{
phyParam.Value = MaxPayloadOfDatarateRepeaterCN470ALI[getPhy->Datarate];
break;
}
case PHY_DUTY_CYCLE:
{
phyParam.Value = CN470ALI_DUTY_CYCLE_ENABLED;
break;
}
case PHY_MAX_RX_WINDOW:
{
phyParam.Value = CN470ALI_MAX_RX_WINDOW;
break;
}
case PHY_RECEIVE_DELAY1:
{
phyParam.Value = CN470ALI_RECEIVE_DELAY1;
break;
}
case PHY_RECEIVE_DELAY2:
{
phyParam.Value = CN470ALI_RECEIVE_DELAY2;
break;
}
case PHY_JOIN_ACCEPT_DELAY1:
{
phyParam.Value = CN470ALI_JOIN_ACCEPT_DELAY1;
break;
}
case PHY_JOIN_ACCEPT_DELAY2:
{
phyParam.Value = CN470ALI_JOIN_ACCEPT_DELAY2;
break;
}
case PHY_MAX_FCNT_GAP:
{
phyParam.Value = CN470ALI_MAX_FCNT_GAP;
break;
}
case PHY_ACK_TIMEOUT:
{
/*===============================ALI_Region==============================================*/
phyParam.Value = ( CN470ALI_ACKTIMEOUT)+ randr( -CN470ALI_ACK_TIMEOUT_RND, CN470ALI_ACK_TIMEOUT_RND );
/*=======================================================================================*/
break;
}
case PHY_DEF_DR1_OFFSET:
{
phyParam.Value = CN470ALI_DEFAULT_RX1_DR_OFFSET;
break;
}
case PHY_DEF_RX2_FREQUENCY:
{
phyParam.Value = CN470ALI_RX_WND_2_FREQ;
break;
}
case PHY_DEF_RX2_DR:
{
phyParam.Value = CN470ALI_RX_WND_2_DR;
break;
}
case PHY_CHANNELS_MASK:
{
phyParam.ChannelsMask = NvmCtx.ChannelsMask;
break;
}
case PHY_CHANNELS_DEFAULT_MASK:
{
phyParam.ChannelsMask = NvmCtx.ChannelsDefaultMask;
break;
}
case PHY_MAX_NB_CHANNELS:
{
phyParam.Value = CN470ALI_MAX_NB_CHANNELS;
break;
}
case PHY_CHANNELS:
{
phyParam.Channels = NvmCtx.Channels;
break;
}
case PHY_DEF_UPLINK_DWELL_TIME:
case PHY_DEF_DOWNLINK_DWELL_TIME:
{
phyParam.Value = 0;
break;
}
case PHY_DEF_MAX_EIRP:
{
phyParam.fValue = CN470ALI_DEFAULT_MAX_EIRP;
break;
}
case PHY_DEF_ANTENNA_GAIN:
{
phyParam.fValue = CN470ALI_DEFAULT_ANTENNA_GAIN;
break;
}
case PHY_BEACON_FORMAT:
{
phyParam.BeaconFormat.BeaconSize = CN470ALI_BEACON_SIZE;
phyParam.BeaconFormat.Rfu1Size = CN470ALI_RFU1_SIZE;
phyParam.BeaconFormat.Rfu2Size = CN470ALI_RFU2_SIZE;
break;
}
case PHY_BEACON_CHANNEL_DR:
{
phyParam.Value = CN470ALI_BEACON_CHANNEL_DR;
break;
}
case PHY_BEACON_CHANNEL_STEPWIDTH:
{
phyParam.Value = CN470ALI_BEACON_CHANNEL_STEPWIDTH;
break;
}
case PHY_BEACON_NB_CHANNELS:
{
phyParam.Value = CN470ALI_BEACON_NB_CHANNELS;
break;
}
case PHY_PING_SLOT_CHANNEL_DR:
{
phyParam.Value = CN470ALI_PING_SLOT_CHANNEL_DR;
break;
}
default:
{
break;
}
}
return phyParam;
}
void RegionCN470ALISetBandTxDone( SetBandTxDoneParams_t* txDone )
{
RegionCommonSetBandTxDone( txDone->Joined, &NvmCtx.Bands[NvmCtx.Channels[txDone->Channel].Band], txDone->LastTxDoneTime );
}
void RegionCN470ALIInitDefaults( InitDefaultsParams_t* params )
{
Band_t bands[CN470ALI_MAX_NB_BANDS] =
{
CN470ALI_BAND0
};
switch( params->Type )
{
case INIT_TYPE_INIT:
{
// Initialize bands
memcpy1( ( uint8_t* )NvmCtx.Bands, ( uint8_t* )bands, sizeof( Band_t ) * CN470ALI_MAX_NB_BANDS );
/*===============================ALI_Region==============================================*/
// Channels
// 125 kHz channels
#if (ALI_DOWNLINK_FREQ == ALI_FREQ470_S)||(ALI_DOWNLINK_FREQ == ALI_FREQ470_D)
for( uint8_t i = 0; i < 32; i++ )
{
NvmCtx.Channels[i].Frequency = 470300000 + i * 200000;
NvmCtx.Channels[i].DrRange.Value = ( DR_5 << 4 ) | DR_0;
NvmCtx.Channels[i].Band = 0;
}
for( uint8_t i = 32; i < CN470ALI_MAX_NB_CHANNELS; i++ )
{
NvmCtx.Channels[i].Frequency = 470300000 + (i + (166-32)) * 200000;
NvmCtx.Channels[i].DrRange.Value = ( DR_5 << 4 ) | DR_0;
NvmCtx.Channels[i].Band = 0;
}
#else
for(i=0; i<CN470ALI_MAX_NB_CHANNELS; i++)
{
Channels[i].Frequency = 470300000 + (i + 68) * 200000;
Channels[i].DrRange.Value = ( DR_5 << 4 ) | DR_0;
Channels[i].Band = 0;
}
#endif
// Initialize the channels default mask
NvmCtx.ChannelsDefaultMask[0] = 0xFFFF;
NvmCtx.ChannelsDefaultMask[1] = 0xFFFF;
NvmCtx.ChannelsDefaultMask[2] = 0xFFFF;
NvmCtx.ChannelsDefaultMask[3] = 0xFFFF;
NvmCtx.ChannelsDefaultMask[4] = 0;
NvmCtx.ChannelsDefaultMask[5] = 0;
/*=======================================================================================*/
// Update the channels mask
RegionCommonChanMaskCopy( NvmCtx.ChannelsMask, NvmCtx.ChannelsDefaultMask, 6 );
break;
}
case INIT_TYPE_RESTORE_CTX:
{
if( params->NvmCtx != 0 )
{
memcpy1( (uint8_t*) &NvmCtx, (uint8_t*) params->NvmCtx, sizeof( NvmCtx ) );
}
break;
}
case INIT_TYPE_RESTORE_DEFAULT_CHANNELS:
{
// Restore channels default mask
RegionCommonChanMaskCopy( NvmCtx.ChannelsMask, NvmCtx.ChannelsDefaultMask, 6 );
break;
}
default:
{
break;
}
}
}
void* RegionCN470ALIGetNvmCtx( GetNvmCtxParams_t* params )
{
params->nvmCtxSize = sizeof( RegionCN470ALINvmCtx_t );
return &NvmCtx;
}
bool RegionCN470ALIVerify( VerifyParams_t* verify, PhyAttribute_t phyAttribute )
{
switch( phyAttribute )
{
case PHY_FREQUENCY:
{
return VerifyRfFreq( verify->Frequency );
}
case PHY_TX_DR:
case PHY_DEF_TX_DR:
{
return RegionCommonValueInRange( verify->DatarateParams.Datarate, CN470ALI_TX_MIN_DATARATE, CN470ALI_TX_MAX_DATARATE );
}
case PHY_RX_DR:
{
return RegionCommonValueInRange( verify->DatarateParams.Datarate, CN470ALI_RX_MIN_DATARATE, CN470ALI_RX_MAX_DATARATE );
}
case PHY_DEF_TX_POWER:
case PHY_TX_POWER:
{
// Remark: switched min and max!
return RegionCommonValueInRange( verify->TxPower, CN470ALI_MAX_TX_POWER, CN470ALI_MIN_TX_POWER );
}
case PHY_DUTY_CYCLE:
{
return CN470ALI_DUTY_CYCLE_ENABLED;
}
default:
return false;
}
}
void RegionCN470ALIApplyCFList( ApplyCFListParams_t* applyCFList )
{
// Size of the optional CF list must be 16 byte
if( applyCFList->Size != 16 )
{
return;
}
// Last byte CFListType must be 0x01 to indicate the CFList contains a series of ChMask fields
if( applyCFList->Payload[15] != 0x01 )
{
return;
}
// ChMask0 - ChMask5 must be set (every ChMask has 16 bit)
for( uint8_t chMaskItr = 0, cntPayload = 0; chMaskItr <= 5; chMaskItr++, cntPayload+=2 )
{
NvmCtx.ChannelsMask[chMaskItr] = (uint16_t) (0x00FF & applyCFList->Payload[cntPayload]);
NvmCtx.ChannelsMask[chMaskItr] |= (uint16_t) (applyCFList->Payload[cntPayload+1] << 8);
}
}
bool RegionCN470ALIChanMaskSet( ChanMaskSetParams_t* chanMaskSet )
{
switch( chanMaskSet->ChannelsMaskType )
{
case CHANNELS_MASK:
{
RegionCommonChanMaskCopy( NvmCtx.ChannelsMask, chanMaskSet->ChannelsMaskIn, 6 );
break;
}
case CHANNELS_DEFAULT_MASK:
{
RegionCommonChanMaskCopy( NvmCtx.ChannelsDefaultMask, chanMaskSet->ChannelsMaskIn, 6 );
break;
}
default:
return false;
}
return true;
}
void RegionCN470ALIComputeRxWindowParameters( int8_t datarate, uint8_t minRxSymbols, uint32_t rxError, RxConfigParams_t *rxConfigParams )
{
double tSymbol = 0.0;
// Get the datarate, perform a boundary check
rxConfigParams->Datarate = MIN( datarate, CN470ALI_RX_MAX_DATARATE );
rxConfigParams->Bandwidth = GetBandwidth( rxConfigParams->Datarate );
tSymbol = RegionCommonComputeSymbolTimeLoRa( DataratesCN470ALI[rxConfigParams->Datarate], BandwidthsCN470ALI[rxConfigParams->Datarate] );
RegionCommonComputeRxWindowParameters( tSymbol, minRxSymbols, rxError, Radio.GetWakeupTime( ), &rxConfigParams->WindowTimeout, &rxConfigParams->WindowOffset );
}
bool RegionCN470ALIRxConfig( RxConfigParams_t* rxConfig, int8_t* datarate )
{
int8_t dr = rxConfig->Datarate;
uint8_t maxPayload = 0;
int8_t phyDr = 0;
uint32_t frequency = rxConfig->Frequency;
const char *slotStrings[] = { "1", "2", "C", "Multi_C", "P", "Multi_P" };
if( Radio.GetStatus( ) != RF_IDLE )
{
return false;
}
if( rxConfig->RxSlot == RX_SLOT_WIN_1 )
{
#if (ALI_DOWNLINK_FREQ == ALI_FREQ470_S || ALI_DOWNLINK_FREQ == ALI_FREQ480_D)
if(rxConfig->Channel <32)
frequency = CN470ALI_FIRST_RX1_CHANNEL + ( rxConfig->Channel % 64 ) * CN470ALI_STEPWIDTH_RX1_CHANNEL;
else
frequency = (uint32_t)503500000 + ((rxConfig->Channel-32) % 64 ) * CN470ALI_STEPWIDTH_RX1_CHANNEL;
#else
// Apply window 1 frequency
frequency = CN470ALI_FIRST_RX1_CHANNEL + ( rxConfig->Channel % 64 ) * CN470ALI_STEPWIDTH_RX1_CHANNEL;
#endif
}
// Read the physical datarate from the datarates table
phyDr = DataratesCN470ALI[dr];
Radio.SetChannel( frequency );
// Radio configuration
Radio.SetRxConfig( MODEM_LORA, rxConfig->Bandwidth, phyDr, 1, 0, 8, rxConfig->WindowTimeout, false, 0, false, 0, 0, true, rxConfig->RxContinuous );
if( rxConfig->RepeaterSupport == true )
{
maxPayload = MaxPayloadOfDatarateRepeaterCN470ALI[dr];
}
else
{
maxPayload = MaxPayloadOfDatarateCN470ALI[dr];
}
Radio.SetMaxPayloadLength( MODEM_LORA, maxPayload + LORA_MAC_FRMPAYLOAD_OVERHEAD );
if ( rxConfig->RxSlot < RX_SLOT_NONE )
{
MW_LOG( "RX_%s on freq %d Hz at DR %d\n\r", slotStrings[rxConfig->RxSlot], frequency, dr );
}
else
{
MW_LOG( "RX on freq %d Hz at DR %d\n\r", frequency, dr );
}
*datarate = (uint8_t) dr;
return true;
}
bool RegionCN470ALITxConfig( TxConfigParams_t* txConfig, int8_t* txPower, TimerTime_t* txTimeOnAir )
{
int8_t phyDr = DataratesCN470ALI[txConfig->Datarate];
int8_t txPowerLimited = LimitTxPower( txConfig->TxPower, NvmCtx.Bands[NvmCtx.Channels[txConfig->Channel].Band].TxMaxPower, txConfig->Datarate, NvmCtx.ChannelsMask );
int8_t phyTxPower = 0;
// Calculate physical TX power
phyTxPower = RegionCommonComputeTxPower( txPowerLimited, txConfig->MaxEirp, txConfig->AntennaGain );
// Setup the radio frequency
Radio.SetChannel( NvmCtx.Channels[txConfig->Channel].Frequency );
Radio.SetTxConfig( MODEM_LORA, phyTxPower, 0, 0, phyDr, 1, 8, false, true, 0, 0, false, 4000 );
MW_LOG( "TX on freq %d Hz at DR %d,TxPower %d\n\r", NvmCtx.Channels[txConfig->Channel].Frequency, txConfig->Datarate ,phyTxPower);
// Setup maximum payload lenght of the radio driver
Radio.SetMaxPayloadLength( MODEM_LORA, txConfig->PktLen );
// Get the time-on-air of the next tx frame
*txTimeOnAir = Radio.TimeOnAir( MODEM_LORA, txConfig->PktLen );
*txPower = txPowerLimited;
return true;
}
uint8_t RegionCN470ALILinkAdrReq( LinkAdrReqParams_t* linkAdrReq, int8_t* drOut, int8_t* txPowOut, uint8_t* nbRepOut, uint8_t* nbBytesParsed )
{
uint8_t status = 0x07;
RegionCommonLinkAdrParams_t linkAdrParams;
uint8_t nextIndex = 0;
uint8_t bytesProcessed = 0;
uint16_t channelsMask[6] = { 0, 0, 0, 0, 0, 0 };
GetPhyParams_t getPhy;
PhyParam_t phyParam;
RegionCommonLinkAdrReqVerifyParams_t linkAdrVerifyParams;
// Initialize local copy of channels mask
RegionCommonChanMaskCopy( channelsMask, NvmCtx.ChannelsMask, 6 );
while( bytesProcessed < linkAdrReq->PayloadSize )
{
// Get ADR request parameters
nextIndex = RegionCommonParseLinkAdrReq( &( linkAdrReq->Payload[bytesProcessed] ), &linkAdrParams );
if( nextIndex == 0 )
break; // break loop, since no more request has been found
// Update bytes processed
bytesProcessed += nextIndex;
// Revert status, as we only check the last ADR request for the channel mask KO
status = 0x07;
/*===============================ALI_Region==============================================*/
if( linkAdrParams.ChMaskCtrl >4 )
{
status &= 0xFE; // Channel mask KO
}
else if( linkAdrParams.ChMaskCtrl == 4)
{
// Enable all 125 kHz channels
channelsMask[0] = 0xFFFF;
channelsMask[1] = 0xFFFF;
channelsMask[2] = 0xFFFF;
channelsMask[3] = 0xFFFF;
channelsMask[4] = 0;
channelsMask[5] = 0;
}
else
{
for( uint8_t i = 0; i < 16; i++ )
{
if( ( ( linkAdrParams.ChMask & ( 1 << i ) ) != 0 ) &&
( NvmCtx.Channels[linkAdrParams.ChMaskCtrl * 16 + i].Frequency == 0 ) )
{// Trying to enable an undefined channel
status &= 0xFE; // Channel mask KO
}
}
channelsMask[linkAdrParams.ChMaskCtrl] = linkAdrParams.ChMask;
}
}
/*========================================================================================*/
// Get the minimum possible datarate
getPhy.Attribute = PHY_MIN_TX_DR;
getPhy.UplinkDwellTime = linkAdrReq->UplinkDwellTime;
phyParam = RegionCN470ALIGetPhyParam( &getPhy );
linkAdrVerifyParams.Status = status;
linkAdrVerifyParams.AdrEnabled = linkAdrReq->AdrEnabled;
linkAdrVerifyParams.Datarate = linkAdrParams.Datarate;
linkAdrVerifyParams.TxPower = linkAdrParams.TxPower;
linkAdrVerifyParams.NbRep = linkAdrParams.NbRep;
linkAdrVerifyParams.CurrentDatarate = linkAdrReq->CurrentDatarate;
linkAdrVerifyParams.CurrentTxPower = linkAdrReq->CurrentTxPower;
linkAdrVerifyParams.CurrentNbRep = linkAdrReq->CurrentNbRep;
linkAdrVerifyParams.NbChannels = CN470ALI_MAX_NB_CHANNELS;
linkAdrVerifyParams.ChannelsMask = channelsMask;
linkAdrVerifyParams.MinDatarate = ( int8_t )phyParam.Value;
linkAdrVerifyParams.MaxDatarate = CN470ALI_TX_MAX_DATARATE;
linkAdrVerifyParams.Channels = NvmCtx.Channels;
linkAdrVerifyParams.MinTxPower = CN470ALI_MIN_TX_POWER;
linkAdrVerifyParams.MaxTxPower = CN470ALI_MAX_TX_POWER;
linkAdrVerifyParams.Version = linkAdrReq->Version;
// Verify the parameters and update, if necessary
status = RegionCommonLinkAdrReqVerifyParams( &linkAdrVerifyParams, &linkAdrParams.Datarate, &linkAdrParams.TxPower, &linkAdrParams.NbRep );
// Update channelsMask if everything is correct
if( status == 0x07 )
{
// Copy Mask
RegionCommonChanMaskCopy( NvmCtx.ChannelsMask, channelsMask, 6 );
}
// Update status variables
*drOut = linkAdrParams.Datarate;
*txPowOut = linkAdrParams.TxPower;
*nbRepOut = linkAdrParams.NbRep;
*nbBytesParsed = bytesProcessed;
return status;
}
uint8_t RegionCN470ALIRxParamSetupReq( RxParamSetupReqParams_t* rxParamSetupReq )
{
uint8_t status = 0x07;
// Verify radio frequency
if( VerifyRfFreq( rxParamSetupReq->Frequency ) == false )
{
status &= 0xFE; // Channel frequency KO
}
// Verify datarate
if( RegionCommonValueInRange( rxParamSetupReq->Datarate, CN470ALI_RX_MIN_DATARATE, CN470ALI_RX_MAX_DATARATE ) == false )
{
status &= 0xFD; // Datarate KO
}
// Verify datarate offset
if( RegionCommonValueInRange( rxParamSetupReq->DrOffset, CN470ALI_MIN_RX1_DR_OFFSET, CN470ALI_MAX_RX1_DR_OFFSET ) == false )
{
status &= 0xFB; // Rx1DrOffset range KO
}
return status;
}
uint8_t RegionCN470ALINewChannelReq( NewChannelReqParams_t* newChannelReq )
{
// Datarate and frequency KO
return 0;
}
int8_t RegionCN470ALITxParamSetupReq( TxParamSetupReqParams_t* txParamSetupReq )
{
return -1;
}
uint8_t RegionCN470ALIDlChannelReq( DlChannelReqParams_t* dlChannelReq )
{
return 0;
}
/*===============================ALI_Region==============================================*/
int8_t RegionCN470ALIAlternateDr( int8_t currentDr, AlternateDrType_t type )
{
static uint16_t JoinRequestTrials;
if(ALTERNATE_DR == type)
{
++JoinRequestTrials;
return ((JoinRequestTrials%2) ? DR_2 : DR_3);
}
return currentDr;
}
/*=======================================================================================*/
void RegionCN470ALICalcBackOff( 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 RegionCN470ALINextChannel( NextChanParams_t* nextChanParams, uint8_t* channel, TimerTime_t* time, TimerTime_t* aggregatedTimeOff )
{
uint8_t nbEnabledChannels = 0;
uint8_t delayTx = 0;
uint8_t enabledChannels[CN470ALI_MAX_NB_CHANNELS] = { 0 };
TimerTime_t nextTxDelay = 0;
// Count 125kHz channels
if( RegionCommonCountChannels( NvmCtx.ChannelsMask, 0, 6 ) == 0 )
{ // Reactivate default channels
NvmCtx.ChannelsMask[0] = 0xFFFF;
NvmCtx.ChannelsMask[1] = 0xFFFF;
NvmCtx.ChannelsMask[2] = 0xFFFF;
NvmCtx.ChannelsMask[3] = 0xFFFF;
NvmCtx.ChannelsMask[4] = 0;
NvmCtx.ChannelsMask[5] = 0;
}
TimerTime_t elapsed = TimerGetElapsedTime( nextChanParams->LastAggrTx );
if( ( nextChanParams->LastAggrTx == 0 ) || ( nextChanParams->AggrTimeOff <= elapsed ) )
{
// Reset Aggregated time off
*aggregatedTimeOff = 0;
// Update bands Time OFF
nextTxDelay = RegionCommonUpdateBandTimeOff( nextChanParams->Joined, nextChanParams->DutyCycleEnabled, NvmCtx.Bands, CN470ALI_MAX_NB_BANDS );
// Search how many channels are enabled
nbEnabledChannels = CountNbOfEnabledChannels( nextChanParams->Datarate,
NvmCtx.ChannelsMask, NvmCtx.Channels,
NvmCtx.Bands, enabledChannels, &delayTx );
}
else
{
delayTx++;
nextTxDelay = nextChanParams->AggrTimeOff - elapsed;
}
if( nbEnabledChannels > 0 )
{
// We found a valid channel
*channel = enabledChannels[randr( 0, nbEnabledChannels - 1 )];
*time = 0;
return LORAMAC_STATUS_OK;
}
else
{
if( delayTx > 0 )
{
// Delay transmission due to AggregatedTimeOff or to a band time off
*time = nextTxDelay;
return LORAMAC_STATUS_DUTYCYCLE_RESTRICTED;
}
// Datarate not supported by any channel
*time = 0;
return LORAMAC_STATUS_NO_CHANNEL_FOUND;
}
}
LoRaMacStatus_t RegionCN470ALIChannelAdd( ChannelAddParams_t* channelAdd )
{
return LORAMAC_STATUS_PARAMETER_INVALID;
}
bool RegionCN470ALIChannelsRemove( ChannelRemoveParams_t* channelRemove )
{
return LORAMAC_STATUS_PARAMETER_INVALID;
}
void RegionCN470ALISetContinuousWave( ContinuousWaveParams_t* continuousWave )
{
int8_t txPowerLimited = LimitTxPower( continuousWave->TxPower, NvmCtx.Bands[NvmCtx.Channels[continuousWave->Channel].Band].TxMaxPower, continuousWave->Datarate, NvmCtx.ChannelsMask );
int8_t phyTxPower = 0;
uint32_t frequency = NvmCtx.Channels[continuousWave->Channel].Frequency;
// Calculate physical TX power
phyTxPower = RegionCommonComputeTxPower( txPowerLimited, continuousWave->MaxEirp, continuousWave->AntennaGain );
Radio.SetTxContinuousWave( frequency, phyTxPower, continuousWave->Timeout );
}
uint8_t RegionCN470ALIApplyDrOffset( uint8_t downlinkDwellTime, int8_t dr, int8_t drOffset )
{
int8_t datarate = dr - drOffset;
if( datarate < 0 )
{
datarate = DR_0;
}
return datarate;
}
void RegionCN470ALIRxBeaconSetup( RxBeaconSetup_t* rxBeaconSetup, uint8_t* outDr )
{
RegionCommonRxBeaconSetupParams_t regionCommonRxBeaconSetup;
regionCommonRxBeaconSetup.Datarates = DataratesCN470ALI;
regionCommonRxBeaconSetup.Frequency = rxBeaconSetup->Frequency;
regionCommonRxBeaconSetup.BeaconSize = CN470ALI_BEACON_SIZE;
regionCommonRxBeaconSetup.BeaconDatarate = CN470ALI_BEACON_CHANNEL_DR;
regionCommonRxBeaconSetup.BeaconChannelBW = CN470ALI_BEACON_CHANNEL_BW;
regionCommonRxBeaconSetup.RxTime = rxBeaconSetup->RxTime;
regionCommonRxBeaconSetup.SymbolTimeout = rxBeaconSetup->SymbolTimeout;
RegionCommonRxBeaconSetup( &regionCommonRxBeaconSetup );
// Store downlink datarate
*outDr = CN470ALI_BEACON_CHANNEL_DR;
}

View File

@@ -0,0 +1,594 @@
/*!
* \file RegionCN470ALI.h
*
* \brief Region definition for CN470ALI
*
* \copyright Revised BSD License, see section \ref LICENSE.
*
* \code
* ______ _
* / _____) _ | |
* ( (____ _____ ____ _| |_ _____ ____| |__
* \____ \| ___ | (_ _) ___ |/ ___) _ \
* _____) ) ____| | | || |_| ____( (___| | | |
* (______/|_____)_|_|_| \__)_____)\____)_| |_|
* (C)2013-2017 Semtech
*
* ___ _____ _ ___ _ _____ ___ ___ ___ ___
* / __|_ _/_\ / __| |/ / __/ _ \| _ \/ __| __|
* \__ \ | |/ _ \ (__| ' <| _| (_) | / (__| _|
* |___/ |_/_/ \_\___|_|\_\_| \___/|_|_\\___|___|
* embedded.connectivity.solutions===============
*
* \endcode
*
* \author Miguel Luis ( Semtech )
*
* \author Gregory Cristian ( Semtech )
*
* \author Daniel Jaeckle ( STACKFORCE )
*
* \author Johannes Bruder ( STACKFORCE )
*
* \defgroup REGIONCN470ALI Region CN470ALI
* Implementation according to LoRaWAN Specification v1.0.2.
* \{
*/
#ifndef __REGION_CN470ALI_H__
#define __REGION_CN470ALI_H__
#include "region/Region.h"
#define ALI_FREQ470_S (0)
#define ALI_FREQ470_D (1)
#define ALI_FREQ480_S (3)
#define ALI_FREQ480_D (4)
/*table[1] for CN470ALID and CN480ALIS*/
#define ALI_RX_WND_2_FREQ_1A1D_1B1S 485300000
#define ALI_RX_WND_2_FREQ_1A2D_1B2S 486900000
#define ALI_RX_WND_2_FREQ_2A1D_2B1S 488500000
#define ALI_RX_WND_2_FREQ_2A2D_2B2S 490100000
#define ALI_RX_WND_2_FREQ_3B1D_3A1S 491700000
#define ALI_RX_WND_2_FREQ_3B2D_3A2S 493300000
#define ALI_RX_WND_2_FREQ_4B1D_4A1S 494900000
#define ALI_RX_WND_2_FREQ_4B2D_4A2S 496500000
/*table[2] for CN470ALIS and CN480ALID*/
#define ALI_RX_WND_2_FREQ_1A1S_1B1D 471700000
#define ALI_RX_WND_2_FREQ_1A2S_1B2D 473300000
#define ALI_RX_WND_2_FREQ_2A1S_2B1D 474900000
#define ALI_RX_WND_2_FREQ_2A2S_2B2D 476500000
#define ALI_RX_WND_2_FREQ_3B1S_3A1D 504900000
#define ALI_RX_WND_2_FREQ_3B2S_3A2D 506500000
#define ALI_RX_WND_2_FREQ_4B1S_4A1D 508100000
#define ALI_RX_WND_2_FREQ_4B2S_4A2D 509700000
/*TODO: add beacon freq*/
#define ALI_DOWNLINK_FREQ ALI_FREQ470_S
#define ALI_RX2WIN_FREQ ALI_RX_WND_2_FREQ_1A2S_1B2D
#define ALI_BEACON_FREQ
/*error msg*/
#if ((ALI_DOWNLINK_FREQ == ALI_FREQ470_D)||(ALI_DOWNLINK_FREQ == ALI_FREQ480_S))
#if (ALI_RX2WIN_FREQ < ALI_RX_WND_2_FREQ_1A1D_1B1S) ||((ALI_RX2WIN_FREQ > ALI_RX_WND_2_FREQ_4B2D_4A2S))
#error ======>Incorrect ALI_RX2WIN_FREQ , you should use the value in table[1]
#endif
#else
#if ((ALI_RX2WIN_FREQ < ALI_RX_WND_2_FREQ_1A1S_1B1D)||(ALI_RX2WIN_FREQ > ALI_RX_WND_2_FREQ_4B2S_4A2D))
#error ======>Incorrect ALI_RX2WIN_FREQ , you should use the value in table[2]
#endif
#if ((ALI_RX2WIN_FREQ > ALI_RX_WND_2_FREQ_2A2S_2B2D) && (ALI_RX2WIN_FREQ < ALI_RX_WND_2_FREQ_3B1S_3A1D))
##error ======>Incorrect ALI_RX2WIN_FREQ , you should use the value in table[2]
#endif
#endif
#ifndef ALI_DOWNLINK_FREQ
#error ALI_DOWNLINK_FREQ not defined
#endif
#ifndef ALI_RX2WIN_FREQ
#erorr ALI_RX2WIN_FREQ not defined
#endif
/*!
* LoRaMac maximum number of channels
*/
#define CN470ALI_MAX_NB_CHANNELS 64
/*!
* Minimal datarate that can be used by the node
*/
#define CN470ALI_TX_MIN_DATARATE DR_0
/*!
* Maximal datarate that can be used by the node
*/
#define CN470ALI_TX_MAX_DATARATE DR_5
/*!
* Minimal datarate that can be used by the node
*/
#define CN470ALI_RX_MIN_DATARATE DR_0
/*!
* Maximal datarate that can be used by the node
*/
#define CN470ALI_RX_MAX_DATARATE DR_5
/*!
* Default datarate used by the node
*/
/*===============================ALI_Region==============================================*/
#define CN470ALI_DEFAULT_DATARATE DR_2//primitive_cn470 DR_0
/*=======================================================================================*/
/*!
* Minimal Rx1 receive datarate offset
*/
#define CN470ALI_MIN_RX1_DR_OFFSET 0
/*!
* Maximal Rx1 receive datarate offset
*/
#define CN470ALI_MAX_RX1_DR_OFFSET 3
/*!
* Default Rx1 receive datarate offset
*/
#define CN470ALI_DEFAULT_RX1_DR_OFFSET 0
/*!
* Minimal Tx output power that can be used by the node
*/
#define CN470ALI_MIN_TX_POWER TX_POWER_7
/*!
* Maximal Tx output power that can be used by the node
*/
#define CN470ALI_MAX_TX_POWER TX_POWER_0
/*!
* Default Tx output power used by the node
*/
#define CN470ALI_DEFAULT_TX_POWER TX_POWER_0
/*!
* Default Max EIRP
*/
#define CN470ALI_DEFAULT_MAX_EIRP 19.15f
/*!
* Default antenna gain
*/
#define CN470ALI_DEFAULT_ANTENNA_GAIN 2.15f
/*!
* ADR Ack limit
*/
#define CN470ALI_ADR_ACK_LIMIT 64
/*!
* ADR Ack delay
*/
#define CN470ALI_ADR_ACK_DELAY 32
/*!
* Enabled or disabled the duty cycle
*/
#define CN470ALI_DUTY_CYCLE_ENABLED 0
/*!
* Maximum RX window duration
*/
#define CN470ALI_MAX_RX_WINDOW 3000
/*!
* Receive delay 1
*/
#define CN470ALI_RECEIVE_DELAY1 1000
/*!
* Receive delay 2
*/
#define CN470ALI_RECEIVE_DELAY2 2000
/*!
* Join accept delay 1
*/
#define CN470ALI_JOIN_ACCEPT_DELAY1 5000
/*!
* Join accept delay 2
*/
#define CN470ALI_JOIN_ACCEPT_DELAY2 6000
/*!
* Maximum frame counter gap
*/
#define CN470ALI_MAX_FCNT_GAP 16384
/*!
* Ack timeout
*/
#define CN470ALI_ACKTIMEOUT 5500
/*!
* Random ack timeout limits
*/
#define CN470ALI_ACK_TIMEOUT_RND 500
/*!
* Second reception window channel datarate definition.
*/
#define CN470ALI_RX_WND_2_DR DR_0
/*
* CLASS B
*/
/*!
* Beacon frequency
*/
#define CN470ALI_BEACON_CHANNEL_FREQ 485500000
/*!
* Beacon frequency channel stepwidth
*/
#define CN470ALI_BEACON_CHANNEL_STEPWIDTH 200000
/*!
* Number of possible beacon channels
*/
#define CN470ALI_BEACON_NB_CHANNELS 8
/*!
* Payload size of a beacon frame
*/
#define CN470ALI_BEACON_SIZE 19
/*!
* Size of RFU 1 field
*/
#define CN470ALI_RFU1_SIZE 3
/*!
* Size of RFU 2 field
*/
#define CN470ALI_RFU2_SIZE 1
/*!
* Datarate of the beacon channel
*/
#define CN470ALI_BEACON_CHANNEL_DR DR_2
/*!
* Bandwith of the beacon channel
*/
#define CN470ALI_BEACON_CHANNEL_BW 0
/*!
* Ping slot channel datarate
*/
#define CN470ALI_PING_SLOT_CHANNEL_DR DR_2
/*!
* LoRaMac maximum number of bands
*/
#define CN470ALI_MAX_NB_BANDS 1
/*!
* Band 0 definition
* { DutyCycle, TxMaxPower, LastJoinTxDoneTime, LastTxDoneTime, TimeOff }
*/
#define CN470ALI_BAND0 { 1, CN470ALI_MAX_TX_POWER, 0, 0, 0 } // 100.0 %
#ifdef ALI_DOWNLINK_FREQ
#if (ALI_DOWNLINK_FREQ == ALI_FREQ470_S || ALI_DOWNLINK_FREQ == ALI_FREQ480_D)
/*!
* Defines the first channel for RX window 1 for CN470ALI band
*/
#define CN470ALI_FIRST_RX1_CHANNEL ( (uint32_t) 470300000 )
/*!
* Defines the last channel for RX window 1 for CN470ALI band
*/
#define CN470ALI_LAST_RX1_CHANNEL ( (uint32_t) 509700000 )
/*!
* Defines the step width of the channels for RX window 1
*/
#define CN470ALI_STEPWIDTH_RX1_CHANNEL ( (uint32_t) 200000 )
/*!
* Second reception window channel frequency definition.
*/
#define CN470ALI_RX_WND_2_FREQ ((uint32_t)ALI_RX2WIN_FREQ)
#elif (ALI_DOWNLINK_FREQ == ALI_FREQ470_D || ALI_DOWNLINK_FREQ == ALI_FREQ480_S)
/*!
* Defines the first channel for RX window 1 for CN470ALI band
*/
#define CN470ALI_FIRST_RX1_CHANNEL ( (uint32_t) 483900000 )
/*!
* Defines the last channel for RX window 1 for CN470ALI band
*/
#define CN470ALI_LAST_RX1_CHANNEL ( (uint32_t) 496500000 )
/*!
* Defines the step width of the channels for RX window 1
*/
#define CN470ALI_STEPWIDTH_RX1_CHANNEL ( (uint32_t) 200000 )
/*!
* Second reception window channel frequency definition.
*/
#define CN470ALI_RX_WND_2_FREQ ((uint32_t)ALI_RX2WIN_FREQ)
#else
#error ALI_DOWNLINK_FREQ not existed
#endif //===============================================================================>
#else
#error ALI_DOWNLINK_FREQ not define
#endif
/*!
* Data rates table definition
*/
static const uint8_t DataratesCN470ALI[] = { 12, 11, 10, 9, 8, 7 };
/*!
* Bandwidths table definition in Hz
*/
static const uint32_t BandwidthsCN470ALI[] = { 125000, 125000, 125000, 125000, 125000, 125000 };
/*!
* Maximum payload with respect to the datarate index. Cannot operate with repeater.
*/
static const uint8_t MaxPayloadOfDatarateCN470ALI[] = { 51+1, 51+1, 51+1, 115+1, 242+1, 242+1 };
/*!
* Maximum payload with respect to the datarate index. Can operate with repeater.
*/
static const uint8_t MaxPayloadOfDatarateRepeaterCN470ALI[] = { 51+1, 51+1, 51+1, 115+1, 222+1, 222+1 };
/*!
* \brief The function gets a value of a specific phy attribute.
*
* \param [IN] getPhy Pointer to the function parameters.
*
* \retval Returns a structure containing the PHY parameter.
*/
PhyParam_t RegionCN470ALIGetPhyParam( GetPhyParams_t* getPhy );
/*!
* \brief Updates the last TX done parameters of the current channel.
*
* \param [IN] txDone Pointer to the function parameters.
*/
void RegionCN470ALISetBandTxDone( SetBandTxDoneParams_t* txDone );
/*!
* \brief Initializes the channels masks and the channels.
*
* \param [IN] type Sets the initialization type.
*/
void RegionCN470ALIInitDefaults( InitDefaultsParams_t* params );
/*!
* \brief Returns a pointer to the internal context and its size.
*
* \param [OUT] params Pointer to the function parameters.
*
* \retval Points to a structure where the module store its non-volatile context.
*/
void* RegionCN470ALIGetNvmCtx( GetNvmCtxParams_t* params );
/*!
* \brief Verifies a parameter.
*
* \param [IN] verify Pointer to the function parameters.
*
* \param [IN] type Sets the initialization type.
*
* \retval Returns true, if the parameter is valid.
*/
bool RegionCN470ALIVerify( VerifyParams_t* verify, PhyAttribute_t phyAttribute );
/*!
* \brief The function parses the input buffer and sets up the channels of the
* CF list.
*
* \param [IN] applyCFList Pointer to the function parameters.
*/
void RegionCN470ALIApplyCFList( ApplyCFListParams_t* applyCFList );
/*!
* \brief Sets a channels mask.
*
* \param [IN] chanMaskSet Pointer to the function parameters.
*
* \retval Returns true, if the channels mask could be set.
*/
bool RegionCN470ALIChanMaskSet( ChanMaskSetParams_t* chanMaskSet );
/*!
* Computes the Rx window timeout and offset.
*
* \param [IN] datarate Rx window datarate index to be used
*
* \param [IN] minRxSymbols Minimum required number of symbols to detect an Rx frame.
*
* \param [IN] rxError System maximum timing error of the receiver. In milliseconds
* The receiver will turn on in a [-rxError : +rxError] ms
* interval around RxOffset
*
* \param [OUT]rxConfigParams Returns updated WindowTimeout and WindowOffset fields.
*/
void RegionCN470ALIComputeRxWindowParameters( int8_t datarate, uint8_t minRxSymbols, uint32_t rxError, RxConfigParams_t *rxConfigParams );
/*!
* \brief Configuration of the RX windows.
*
* \param [IN] rxConfig Pointer to the function parameters.
*
* \param [OUT] datarate The datarate index which was set.
*
* \retval Returns true, if the configuration was applied successfully.
*/
bool RegionCN470ALIRxConfig( RxConfigParams_t* rxConfig, int8_t* datarate );
/*!
* \brief TX configuration.
*
* \param [IN] txConfig Pointer to the function parameters.
*
* \param [OUT] txPower The tx power index which was set.
*
* \param [OUT] txTimeOnAir The time-on-air of the frame.
*
* \retval Returns true, if the configuration was applied successfully.
*/
bool RegionCN470ALITxConfig( TxConfigParams_t* txConfig, int8_t* txPower, TimerTime_t* txTimeOnAir );
/*!
* \brief The function processes a Link ADR Request.
*
* \param [IN] linkAdrReq Pointer to the function parameters.
*
* \retval Returns the status of the operation, according to the LoRaMAC specification.
*/
uint8_t RegionCN470ALILinkAdrReq( LinkAdrReqParams_t* linkAdrReq, int8_t* drOut, int8_t* txPowOut, uint8_t* nbRepOut, uint8_t* nbBytesParsed );
/*!
* \brief The function processes a RX Parameter Setup Request.
*
* \param [IN] rxParamSetupReq Pointer to the function parameters.
*
* \retval Returns the status of the operation, according to the LoRaMAC specification.
*/
uint8_t RegionCN470ALIRxParamSetupReq( RxParamSetupReqParams_t* rxParamSetupReq );
/*!
* \brief The function processes a Channel Request.
*
* \param [IN] newChannelReq Pointer to the function parameters.
*
* \retval Returns the status of the operation, according to the LoRaMAC specification.
*/
uint8_t RegionCN470ALINewChannelReq( NewChannelReqParams_t* newChannelReq );
/*!
* \brief The function processes a TX ParamSetup Request.
*
* \param [IN] txParamSetupReq Pointer to the function parameters.
*
* \retval Returns the status of the operation, according to the LoRaMAC specification.
* Returns -1, if the functionality is not implemented. In this case, the end node
* shall not process the command.
*/
int8_t RegionCN470ALITxParamSetupReq( TxParamSetupReqParams_t* txParamSetupReq );
/*!
* \brief The function processes a DlChannel Request.
*
* \param [IN] dlChannelReq Pointer to the function parameters.
*
* \retval Returns the status of the operation, according to the LoRaMAC specification.
*/
uint8_t RegionCN470ALIDlChannelReq( DlChannelReqParams_t* dlChannelReq );
/*!
* \brief Alternates the datarate of the channel for the join request.
*
* \param [IN] currentDr Current datarate.
*
* \retval Datarate to apply.
*/
int8_t RegionCN470ALIAlternateDr( int8_t currentDr, AlternateDrType_t type );
/*!
* \brief Calculates the back-off time.
*
* \param [IN] calcBackOff Pointer to the function parameters.
*/
void RegionCN470ALICalcBackOff( CalcBackOffParams_t* calcBackOff );
/*!
* \brief Searches and set the next random available channel
*
* \param [OUT] channel Next channel to use for TX.
*
* \param [OUT] time Time to wait for the next transmission according to the duty
* cycle.
*
* \param [OUT] aggregatedTimeOff Updates the aggregated time off.
*
* \retval Function status [1: OK, 0: Unable to find a channel on the current datarate]
*/
LoRaMacStatus_t RegionCN470ALINextChannel( NextChanParams_t* nextChanParams, uint8_t* channel, TimerTime_t* time, TimerTime_t* aggregatedTimeOff );
/*!
* \brief Adds a channel.
*
* \param [IN] channelAdd Pointer to the function parameters.
*
* \retval Status of the operation.
*/
LoRaMacStatus_t RegionCN470ALIChannelAdd( ChannelAddParams_t* channelAdd );
/*!
* \brief Removes a channel.
*
* \param [IN] channelRemove Pointer to the function parameters.
*
* \retval Returns true, if the channel was removed successfully.
*/
bool RegionCN470ALIChannelsRemove( ChannelRemoveParams_t* channelRemove );
/*!
* \brief Sets the radio into continuous wave mode.
*
* \param [IN] continuousWave Pointer to the function parameters.
*/
void RegionCN470ALISetContinuousWave( ContinuousWaveParams_t* continuousWave );
/*!
* \brief Computes new datarate according to the given offset
*
* \param [IN] downlinkDwellTime Downlink dwell time configuration. 0: No limit, 1: 400ms
*
* \param [IN] dr Current datarate
*
* \param [IN] drOffset Offset to be applied
*
* \retval newDr Computed datarate.
*/
uint8_t RegionCN470ALIApplyDrOffset( uint8_t downlinkDwellTime, int8_t dr, int8_t drOffset );
/*!
* \brief Sets the radio into beacon reception mode
*
* \param [IN] rxBeaconSetup Pointer to the function parameters
*/
void RegionCN470ALIRxBeaconSetup( RxBeaconSetup_t* rxBeaconSetup, uint8_t* outDr );
/*! \} defgroup REGIONCN470ALI */
#endif // __REGION_CN470ALI_H__

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,508 @@
/*!
* \file RegionCN779.h
*
* \brief Region definition for CN779
*
* \copyright Revised BSD License, see section \ref LICENSE.
*
* \code
* ______ _
* / _____) _ | |
* ( (____ _____ ____ _| |_ _____ ____| |__
* \____ \| ___ | (_ _) ___ |/ ___) _ \
* _____) ) ____| | | || |_| ____( (___| | | |
* (______/|_____)_|_|_| \__)_____)\____)_| |_|
* (C)2013-2017 Semtech
*
* ___ _____ _ ___ _ _____ ___ ___ ___ ___
* / __|_ _/_\ / __| |/ / __/ _ \| _ \/ __| __|
* \__ \ | |/ _ \ (__| ' <| _| (_) | / (__| _|
* |___/ |_/_/ \_\___|_|\_\_| \___/|_|_\\___|___|
* embedded.connectivity.solutions===============
*
* \endcode
*
* \author Miguel Luis ( Semtech )
*
* \author Gregory Cristian ( Semtech )
*
* \author Daniel Jaeckle ( STACKFORCE )
*
* \author Johannes Bruder ( STACKFORCE )
*
* \defgroup REGIONCN779 Region CN779
* Implementation according to LoRaWAN Specification v1.0.2.
* \{
*/
#ifndef __REGION_CN779_H__
#define __REGION_CN779_H__
#include "region/Region.h"
/*!
* LoRaMac maximum number of channels
*/
#define CN779_MAX_NB_CHANNELS 16
/*!
* Number of default channels
*/
#define CN779_NUMB_DEFAULT_CHANNELS 3
/*!
* Number of channels to apply for the CF list
*/
#define CN779_NUMB_CHANNELS_CF_LIST 5
/*!
* Minimal datarate that can be used by the node
*/
#define CN779_TX_MIN_DATARATE DR_0
/*!
* Maximal datarate that can be used by the node
*/
#define CN779_TX_MAX_DATARATE DR_7
/*!
* Minimal datarate that can be used by the node
*/
#define CN779_RX_MIN_DATARATE DR_0
/*!
* Maximal datarate that can be used by the node
*/
#define CN779_RX_MAX_DATARATE DR_7
/*!
* Default datarate used by the node
*/
#define CN779_DEFAULT_DATARATE DR_0
/*!
* Minimal Rx1 receive datarate offset
*/
#define CN779_MIN_RX1_DR_OFFSET 0
/*!
* Maximal Rx1 receive datarate offset
*/
#define CN779_MAX_RX1_DR_OFFSET 5
/*!
* Default Rx1 receive datarate offset
*/
#define CN779_DEFAULT_RX1_DR_OFFSET 0
/*!
* Minimal Tx output power that can be used by the node
*/
#define CN779_MIN_TX_POWER TX_POWER_5
/*!
* Maximal Tx output power that can be used by the node
*/
#define CN779_MAX_TX_POWER TX_POWER_0
/*!
* Default Tx output power used by the node
*/
#define CN779_DEFAULT_TX_POWER TX_POWER_0
/*!
* Default Max EIRP
*/
#define CN779_DEFAULT_MAX_EIRP 12.15f
/*!
* Default antenna gain
*/
#define CN779_DEFAULT_ANTENNA_GAIN 2.15f
/*!
* ADR Ack limit
*/
#define CN779_ADR_ACK_LIMIT 64
/*!
* ADR Ack delay
*/
#define CN779_ADR_ACK_DELAY 32
/*!
* Enabled or disabled the duty cycle
*/
#define CN779_DUTY_CYCLE_ENABLED 1
/*!
* Maximum RX window duration
*/
#define CN779_MAX_RX_WINDOW 3000
/*!
* Receive delay 1
*/
#define CN779_RECEIVE_DELAY1 1000
/*!
* Receive delay 2
*/
#define CN779_RECEIVE_DELAY2 2000
/*!
* Join accept delay 1
*/
#define CN779_JOIN_ACCEPT_DELAY1 5000
/*!
* Join accept delay 2
*/
#define CN779_JOIN_ACCEPT_DELAY2 6000
/*!
* Maximum frame counter gap
*/
#define CN779_MAX_FCNT_GAP 16384
/*!
* Ack timeout
*/
#define CN779_ACKTIMEOUT 2000
/*!
* Random ack timeout limits
*/
#define CN779_ACK_TIMEOUT_RND 1000
/*!
* Verification of default datarate
*/
#if ( CN779_DEFAULT_DATARATE > DR_5 )
#error "A default DR higher than DR_5 may lead to connectivity loss."
#endif
/*!
* Second reception window channel frequency definition.
*/
#define CN779_RX_WND_2_FREQ 786000000
/*!
* Second reception window channel datarate definition.
*/
#define CN779_RX_WND_2_DR DR_0
/*
* CLASS B
*/
/*!
* Beacon frequency
*/
#define CN779_BEACON_CHANNEL_FREQ 785000000
/*!
* Payload size of a beacon frame
*/
#define CN779_BEACON_SIZE 17
/*!
* Size of RFU 1 field
*/
#define CN779_RFU1_SIZE 2
/*!
* Size of RFU 2 field
*/
#define CN779_RFU2_SIZE 0
/*!
* Datarate of the beacon channel
*/
#define CN779_BEACON_CHANNEL_DR DR_3
/*!
* Bandwith of the beacon channel
*/
#define CN779_BEACON_CHANNEL_BW 0
/*!
* Ping slot channel datarate
*/
#define CN779_PING_SLOT_CHANNEL_DR DR_3
/*!
* LoRaMac maximum number of bands
*/
#define CN779_MAX_NB_BANDS 1
/*!
* Band 0 definition
* { DutyCycle, TxMaxPower, LastJoinTxDoneTime, LastTxDoneTime, TimeOff }
*/
#define CN779_BAND0 { 100, CN779_MAX_TX_POWER, 0, 0, 0 } // 1.0 %
/*!
* LoRaMac default channel 1
* Channel = { Frequency [Hz], RX1 Frequency [Hz], { ( ( DrMax << 4 ) | DrMin ) }, Band }
*/
#define CN779_LC1 { 779500000, 0, { ( ( DR_5 << 4 ) | DR_0 ) }, 0 }
/*!
* LoRaMac default channel 2
* Channel = { Frequency [Hz], RX1 Frequency [Hz], { ( ( DrMax << 4 ) | DrMin ) }, Band }
*/
#define CN779_LC2 { 779700000, 0, { ( ( DR_5 << 4 ) | DR_0 ) }, 0 }
/*!
* LoRaMac default channel 3
* Channel = { Frequency [Hz], RX1 Frequency [Hz], { ( ( DrMax << 4 ) | DrMin ) }, Band }
*/
#define CN779_LC3 { 779900000, 0, { ( ( DR_5 << 4 ) | DR_0 ) }, 0 }
/*!
* LoRaMac channels which are allowed for the join procedure
*/
#define CN779_JOIN_CHANNELS ( uint16_t )( LC( 1 ) | LC( 2 ) | LC( 3 ) )
/*!
* Data rates table definition
*/
static const uint8_t DataratesCN779[] = { 12, 11, 10, 9, 8, 7, 7, 50 };
/*!
* Bandwidths table definition in Hz
*/
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.
*/
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.
*
* \param [IN] getPhy Pointer to the function parameters.
*
* \retval Returns a structure containing the PHY parameter.
*/
PhyParam_t RegionCN779GetPhyParam( GetPhyParams_t* getPhy );
/*!
* \brief Updates the last TX done parameters of the current channel.
*
* \param [IN] txDone Pointer to the function parameters.
*/
void RegionCN779SetBandTxDone( SetBandTxDoneParams_t* txDone );
/*!
* \brief Initializes the channels masks and the channels.
*
* \param [IN] type Sets the initialization type.
*/
void RegionCN779InitDefaults( InitDefaultsParams_t* params );
/*!
* \brief Returns a pointer to the internal context and its size.
*
* \param [OUT] params Pointer to the function parameters.
*
* \retval Points to a structure where the module store its non-volatile context.
*/
void* RegionCN779GetNvmCtx( GetNvmCtxParams_t* params );
/*!
* \brief Verifies a parameter.
*
* \param [IN] verify Pointer to the function parameters.
*
* \param [IN] type Sets the initialization type.
*
* \retval Returns true, if the parameter is valid.
*/
bool RegionCN779Verify( VerifyParams_t* verify, PhyAttribute_t phyAttribute );
/*!
* \brief The function parses the input buffer and sets up the channels of the
* CF list.
*
* \param [IN] applyCFList Pointer to the function parameters.
*/
void RegionCN779ApplyCFList( ApplyCFListParams_t* applyCFList );
/*!
* \brief Sets a channels mask.
*
* \param [IN] chanMaskSet Pointer to the function parameters.
*
* \retval Returns true, if the channels mask could be set.
*/
bool RegionCN779ChanMaskSet( ChanMaskSetParams_t* chanMaskSet );
/*!
* Computes the Rx window timeout and offset.
*
* \param [IN] datarate Rx window datarate index to be used
*
* \param [IN] minRxSymbols Minimum required number of symbols to detect an Rx frame.
*
* \param [IN] rxError System maximum timing error of the receiver. In milliseconds
* The receiver will turn on in a [-rxError : +rxError] ms
* interval around RxOffset
*
* \param [OUT]rxConfigParams Returns updated WindowTimeout and WindowOffset fields.
*/
void RegionCN779ComputeRxWindowParameters( int8_t datarate, uint8_t minRxSymbols, uint32_t rxError, RxConfigParams_t *rxConfigParams );
/*!
* \brief Configuration of the RX windows.
*
* \param [IN] rxConfig Pointer to the function parameters.
*
* \param [OUT] datarate The datarate index which was set.
*
* \retval Returns true, if the configuration was applied successfully.
*/
bool RegionCN779RxConfig( RxConfigParams_t* rxConfig, int8_t* datarate );
/*!
* \brief TX configuration.
*
* \param [IN] txConfig Pointer to the function parameters.
*
* \param [OUT] txPower The tx power index which was set.
*
* \param [OUT] txTimeOnAir The time-on-air of the frame.
*
* \retval Returns true, if the configuration was applied successfully.
*/
bool RegionCN779TxConfig( TxConfigParams_t* txConfig, int8_t* txPower, TimerTime_t* txTimeOnAir );
/*!
* \brief The function processes a Link ADR Request.
*
* \param [IN] linkAdrReq Pointer to the function parameters.
*
* \retval Returns the status of the operation, according to the LoRaMAC specification.
*/
uint8_t RegionCN779LinkAdrReq( LinkAdrReqParams_t* linkAdrReq, int8_t* drOut, int8_t* txPowOut, uint8_t* nbRepOut, uint8_t* nbBytesParsed );
/*!
* \brief The function processes a RX Parameter Setup Request.
*
* \param [IN] rxParamSetupReq Pointer to the function parameters.
*
* \retval Returns the status of the operation, according to the LoRaMAC specification.
*/
uint8_t RegionCN779RxParamSetupReq( RxParamSetupReqParams_t* rxParamSetupReq );
/*!
* \brief The function processes a Channel Request.
*
* \param [IN] newChannelReq Pointer to the function parameters.
*
* \retval Returns the status of the operation, according to the LoRaMAC specification.
*/
uint8_t RegionCN779NewChannelReq( NewChannelReqParams_t* newChannelReq );
/*!
* \brief The function processes a TX ParamSetup Request.
*
* \param [IN] txParamSetupReq Pointer to the function parameters.
*
* \retval Returns the status of the operation, according to the LoRaMAC specification.
* Returns -1, if the functionality is not implemented. In this case, the end node
* shall not process the command.
*/
int8_t RegionCN779TxParamSetupReq( TxParamSetupReqParams_t* txParamSetupReq );
/*!
* \brief The function processes a DlChannel Request.
*
* \param [IN] dlChannelReq Pointer to the function parameters.
*
* \retval Returns the status of the operation, according to the LoRaMAC specification.
*/
uint8_t RegionCN779DlChannelReq( DlChannelReqParams_t* dlChannelReq );
/*!
* \brief Alternates the datarate of the channel for the join request.
*
* \param [IN] currentDr Current datarate.
*
* \retval Datarate to apply.
*/
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
*
* \param [OUT] channel Next channel to use for TX.
*
* \param [OUT] time Time to wait for the next transmission according to the duty
* cycle.
*
* \param [OUT] aggregatedTimeOff Updates the aggregated time off.
*
* \retval Function status [1: OK, 0: Unable to find a channel on the current datarate]
*/
LoRaMacStatus_t RegionCN779NextChannel( NextChanParams_t* nextChanParams, uint8_t* channel, TimerTime_t* time, TimerTime_t* aggregatedTimeOff );
/*!
* \brief Adds a channel.
*
* \param [IN] channelAdd Pointer to the function parameters.
*
* \retval Status of the operation.
*/
LoRaMacStatus_t RegionCN779ChannelAdd( ChannelAddParams_t* channelAdd );
/*!
* \brief Removes a channel.
*
* \param [IN] channelRemove Pointer to the function parameters.
*
* \retval Returns true, if the channel was removed successfully.
*/
bool RegionCN779ChannelsRemove( ChannelRemoveParams_t* channelRemove );
/*!
* \brief Sets the radio into continuous wave mode.
*
* \param [IN] continuousWave Pointer to the function parameters.
*/
void RegionCN779SetContinuousWave( ContinuousWaveParams_t* continuousWave );
/*!
* \brief Computes new datarate according to the given offset
*
* \param [IN] downlinkDwellTime Downlink dwell time configuration. 0: No limit, 1: 400ms
*
* \param [IN] dr Current datarate
*
* \param [IN] drOffset Offset to be applied
*
* \retval newDr Computed datarate.
*/
uint8_t RegionCN779ApplyDrOffset( uint8_t downlinkDwellTime, int8_t dr, int8_t drOffset );
/*!
* \brief Sets the radio into beacon reception mode
*
* \param [IN] rxBeaconSetup Pointer to the function parameters
*/
void RegionCN779RxBeaconSetup( RxBeaconSetup_t* rxBeaconSetup, uint8_t* outDr );
/*! \} defgroup REGIONCN779 */
#endif // __REGION_CN779_H__

View File

@@ -0,0 +1,387 @@
/*!
* \file RegionCommon.c
*
* \brief LoRa MAC common region implementation
*
* \copyright Revised BSD License, see section \ref LICENSE.
*
* \code
* ______ _
* / _____) _ | |
* ( (____ _____ ____ _| |_ _____ ____| |__
* \____ \| ___ | (_ _) ___ |/ ___) _ \
* _____) ) ____| | | || |_| ____( (___| | | |
* (______/|_____)_|_|_| \__)_____)\____)_| |_|
* (C)2013-2017 Semtech
*
* ___ _____ _ ___ _ _____ ___ ___ ___ ___
* / __|_ _/_\ / __| |/ / __/ _ \| _ \/ __| __|
* \__ \ | |/ _ \ (__| ' <| _| (_) | / (__| _|
* |___/ |_/_/ \_\___|_|\_\_| \___/|_|_\\___|___|
* embedded.connectivity.solutions===============
*
* \endcode
*
* \author Miguel Luis ( Semtech )
*
* \author Gregory Cristian ( Semtech )
*
* \author Daniel Jaeckle ( STACKFORCE )
*/
#include <math.h>
#include "radio.h"
#include "utilities.h"
#include "RegionCommon.h"
#define BACKOFF_DC_1_HOUR 100
#define BACKOFF_DC_10_HOURS 1000
#define BACKOFF_DC_24_HOURS 10000
static uint8_t CountChannels( uint16_t mask, uint8_t nbBits )
{
uint8_t nbActiveBits = 0;
for( uint8_t j = 0; j < nbBits; j++ )
{
if( ( mask & ( 1 << j ) ) == ( 1 << j ) )
{
nbActiveBits++;
}
}
return nbActiveBits;
}
uint16_t RegionCommonGetJoinDc( TimerTime_t elapsedTime )
{
uint16_t dutyCycle = 0;
if( elapsedTime < 3600000 )
{
dutyCycle = BACKOFF_DC_1_HOUR;
}
else if( elapsedTime < ( 3600000 + 36000000 ) )
{
dutyCycle = BACKOFF_DC_10_HOURS;
}
else
{
dutyCycle = BACKOFF_DC_24_HOURS;
}
return dutyCycle;
}
bool RegionCommonChanVerifyDr( uint8_t nbChannels, uint16_t* channelsMask, int8_t dr, int8_t minDr, int8_t maxDr, ChannelParams_t* channels )
{
if( RegionCommonValueInRange( dr, minDr, maxDr ) == 0 )
{
return false;
}
for( uint8_t i = 0, k = 0; i < nbChannels; i += 16, k++ )
{
for( uint8_t j = 0; j < 16; j++ )
{
if( ( ( channelsMask[k] & ( 1 << j ) ) != 0 ) )
{// Check datarate validity for enabled channels
if( RegionCommonValueInRange( dr, ( channels[i + j].DrRange.Fields.Min & 0x0F ),
( channels[i + j].DrRange.Fields.Max & 0x0F ) ) == 1 )
{
// At least 1 channel has been found we can return OK.
return true;
}
}
}
}
return false;
}
uint8_t RegionCommonValueInRange( int8_t value, int8_t min, int8_t max )
{
if( ( value >= min ) && ( value <= max ) )
{
return 1;
}
return 0;
}
bool RegionCommonChanDisable( uint16_t* channelsMask, uint8_t id, uint8_t maxChannels )
{
uint8_t index = id / 16;
if( ( index > ( maxChannels / 16 ) ) || ( id >= maxChannels ) )
{
return false;
}
// Deactivate channel
channelsMask[index] &= ~( 1 << ( id % 16 ) );
return true;
}
uint8_t RegionCommonCountChannels( uint16_t* channelsMask, uint8_t startIdx, uint8_t stopIdx )
{
uint8_t nbChannels = 0;
if( channelsMask == NULL )
{
return 0;
}
for( uint8_t i = startIdx; i < stopIdx; i++ )
{
nbChannels += CountChannels( channelsMask[i], 16 );
}
return nbChannels;
}
void RegionCommonChanMaskCopy( uint16_t* channelsMaskDest, uint16_t* channelsMaskSrc, uint8_t len )
{
if( ( channelsMaskDest != NULL ) && ( channelsMaskSrc != NULL ) )
{
for( uint8_t i = 0; i < len; i++ )
{
channelsMaskDest[i] = channelsMaskSrc[i];
}
}
}
void RegionCommonSetBandTxDone( bool joined, Band_t* band, TimerTime_t lastTxDone )
{
if( joined == true )
{
band->LastTxDoneTime = lastTxDone;
}
else
{
band->LastTxDoneTime = lastTxDone;
band->LastJoinTxDoneTime = lastTxDone;
}
}
TimerTime_t RegionCommonUpdateBandTimeOff( bool joined, bool dutyCycle, Band_t* bands, uint8_t nbBands )
{
TimerTime_t nextTxDelay = TIMERTIME_T_MAX;
// Update bands Time OFF
for( uint8_t i = 0; i < nbBands; i++ )
{
if( joined == false )
{
TimerTime_t elapsedJoin = TimerGetElapsedTime( bands[i].LastJoinTxDoneTime );
TimerTime_t elapsedTx = TimerGetElapsedTime( bands[i].LastTxDoneTime );
TimerTime_t txDoneTime = MAX( elapsedJoin,
( dutyCycle == true ) ? elapsedTx : 0 );
if( bands[i].TimeOff <= txDoneTime )
{
bands[i].TimeOff = 0;
}
if( bands[i].TimeOff != 0 )
{
nextTxDelay = MIN( bands[i].TimeOff - txDoneTime, nextTxDelay );
}
}
else
{
if( dutyCycle == true )
{
TimerTime_t elapsed = TimerGetElapsedTime( bands[i].LastTxDoneTime );
if( bands[i].TimeOff <= elapsed )
{
bands[i].TimeOff = 0;
}
if( bands[i].TimeOff != 0 )
{
nextTxDelay = MIN( bands[i].TimeOff - elapsed, nextTxDelay );
}
}
else
{
nextTxDelay = 0;
bands[i].TimeOff = 0;
}
}
}
return ( nextTxDelay == TIMERTIME_T_MAX ) ? 0 : nextTxDelay;
}
uint8_t RegionCommonParseLinkAdrReq( uint8_t* payload, RegionCommonLinkAdrParams_t* linkAdrParams )
{
uint8_t retIndex = 0;
if( payload[0] == SRV_MAC_LINK_ADR_REQ )
{
// Parse datarate and tx power
linkAdrParams->Datarate = payload[1];
linkAdrParams->TxPower = linkAdrParams->Datarate & 0x0F;
linkAdrParams->Datarate = ( linkAdrParams->Datarate >> 4 ) & 0x0F;
// Parse ChMask
linkAdrParams->ChMask = ( uint16_t )payload[2];
linkAdrParams->ChMask |= ( uint16_t )payload[3] << 8;
// Parse ChMaskCtrl and nbRep
linkAdrParams->NbRep = payload[4];
linkAdrParams->ChMaskCtrl = ( linkAdrParams->NbRep >> 4 ) & 0x07;
linkAdrParams->NbRep &= 0x0F;
// LinkAdrReq has 4 bytes length + 1 byte CMD
retIndex = 5;
}
return retIndex;
}
uint8_t RegionCommonLinkAdrReqVerifyParams( RegionCommonLinkAdrReqVerifyParams_t* verifyParams, int8_t* dr, int8_t* txPow, uint8_t* nbRep )
{
uint8_t status = verifyParams->Status;
int8_t datarate = verifyParams->Datarate;
int8_t txPower = verifyParams->TxPower;
int8_t nbRepetitions = verifyParams->NbRep;
// Handle the case when ADR is off.
if( verifyParams->AdrEnabled == false )
{
// When ADR is off, we are allowed to change the channels mask
nbRepetitions = verifyParams->CurrentNbRep;
datarate = verifyParams->CurrentDatarate;
txPower = verifyParams->CurrentTxPower;
}
if( status != 0 )
{
// Verify datarate. The variable phyParam. Value contains the minimum allowed datarate.
if( RegionCommonChanVerifyDr( verifyParams->NbChannels, verifyParams->ChannelsMask, datarate,
verifyParams->MinDatarate, verifyParams->MaxDatarate, verifyParams->Channels ) == false )
{
status &= 0xFD; // Datarate KO
}
// Verify tx power
if( RegionCommonValueInRange( txPower, verifyParams->MaxTxPower, verifyParams->MinTxPower ) == 0 )
{
// Verify if the maximum TX power is exceeded
if( verifyParams->MaxTxPower > txPower )
{ // Apply maximum TX power. Accept TX power.
txPower = verifyParams->MaxTxPower;
}
else
{
status &= 0xFB; // TxPower KO
}
}
}
// If the status is ok, verify the NbRep
if( status == 0x07 )
{
if( nbRepetitions == 0 )
{ // Restore the default value according to the LoRaWAN specification
nbRepetitions = 1;
}
}
// Apply changes
*dr = datarate;
*txPow = txPower;
*nbRep = nbRepetitions;
return status;
}
double RegionCommonComputeSymbolTimeLoRa( uint8_t phyDr, uint32_t bandwidth )
{
return ( ( double )( 1 << phyDr ) / ( double )bandwidth ) * 1000;
}
double RegionCommonComputeSymbolTimeFsk( uint8_t phyDr )
{
return ( 8.0 / ( double )phyDr ); // 1 symbol equals 1 byte
}
void RegionCommonComputeRxWindowParameters( double tSymbol, uint8_t minRxSymbols, uint32_t rxError, uint32_t wakeUpTime, uint32_t* windowTimeout, int32_t* windowOffset )
{
*windowTimeout = MAX( ( uint32_t )ceil( ( ( 2 * minRxSymbols - 8 ) * tSymbol + 2 * rxError ) / tSymbol ), minRxSymbols ); // Computed number of symbols
*windowOffset = ( int32_t )ceil( ( 4.0 * tSymbol ) - ( ( *windowTimeout * tSymbol ) / 2.0 ) - wakeUpTime );
}
int8_t RegionCommonComputeTxPower( int8_t txPowerIndex, float maxEirp, float antennaGain )
{
int8_t phyTxPower = 0;
phyTxPower = ( int8_t )floor( ( maxEirp - ( txPowerIndex * 2U ) ) - antennaGain );
return phyTxPower;
}
void RegionCommonCalcBackOff( RegionCommonCalcBackOffParams_t* calcBackOffParams )
{
uint8_t bandIdx = calcBackOffParams->Channels[calcBackOffParams->Channel].Band;
uint16_t dutyCycle = calcBackOffParams->Bands[bandIdx].DCycle;
uint16_t joinDutyCycle = 0;
// Reset time-off to initial value.
calcBackOffParams->Bands[bandIdx].TimeOff = 0;
if( calcBackOffParams->Joined == false )
{
// Get the join duty cycle
joinDutyCycle = RegionCommonGetJoinDc( calcBackOffParams->ElapsedTime );
// Apply the most restricting duty cycle
dutyCycle = MAX( dutyCycle, joinDutyCycle );
// Reset the timeoff if the last frame was not a join request and when the duty cycle is not enabled
if( ( calcBackOffParams->DutyCycleEnabled == false ) && ( calcBackOffParams->LastTxIsJoinRequest == false ) )
{
// This is the case when the duty cycle is off and the last uplink frame was not a join.
// This could happen in case of a rejoin, e.g. in compliance test mode.
// In this special case we have to set the time off to 0, since the join duty cycle shall only
// be applied after the first join request.
calcBackOffParams->Bands[bandIdx].TimeOff = 0;
}
else
{
// Apply band time-off.
calcBackOffParams->Bands[bandIdx].TimeOff = calcBackOffParams->TxTimeOnAir * dutyCycle - calcBackOffParams->TxTimeOnAir;
}
}
else
{
if( calcBackOffParams->DutyCycleEnabled == true )
{
calcBackOffParams->Bands[bandIdx].TimeOff = calcBackOffParams->TxTimeOnAir * dutyCycle - calcBackOffParams->TxTimeOnAir;
}
else
{
calcBackOffParams->Bands[bandIdx].TimeOff = 0;
}
}
}
void RegionCommonRxBeaconSetup( RegionCommonRxBeaconSetupParams_t* rxBeaconSetupParams )
{
bool rxContinuous = true;
uint8_t datarate;
// Set the radio into sleep mode
Radio.Sleep( );
// Setup frequency and payload length
Radio.SetChannel( rxBeaconSetupParams->Frequency );
Radio.SetMaxPayloadLength( MODEM_LORA, rxBeaconSetupParams->BeaconSize );
// Check the RX continuous mode
if( rxBeaconSetupParams->RxTime != 0 )
{
rxContinuous = false;
}
// Get region specific datarate
datarate = rxBeaconSetupParams->Datarates[rxBeaconSetupParams->BeaconDatarate];
// Setup radio
Radio.SetRxConfig( MODEM_LORA, rxBeaconSetupParams->BeaconChannelBW, datarate,
1, 0, 10, rxBeaconSetupParams->SymbolTimeout, true, rxBeaconSetupParams->BeaconSize, false, 0, 0, false, rxContinuous );
Radio.Rx( rxBeaconSetupParams->RxTime );
}

View File

@@ -0,0 +1,421 @@
/*!
* \file RegionCommon.h
*
* \brief Region independent implementations which are common to all regions.
*
* \copyright Revised BSD License, see section \ref LICENSE.
*
* \code
* ______ _
* / _____) _ | |
* ( (____ _____ ____ _| |_ _____ ____| |__
* \____ \| ___ | (_ _) ___ |/ ___) _ \
* _____) ) ____| | | || |_| ____( (___| | | |
* (______/|_____)_|_|_| \__)_____)\____)_| |_|
* (C)2013-2017 Semtech
*
* ___ _____ _ ___ _ _____ ___ ___ ___ ___
* / __|_ _/_\ / __| |/ / __/ _ \| _ \/ __| __|
* \__ \ | |/ _ \ (__| ' <| _| (_) | / (__| _|
* |___/ |_/_/ \_\___|_|\_\_| \___/|_|_\\___|___|
* embedded.connectivity.solutions===============
*
* \endcode
*
* \author Miguel Luis ( Semtech )
*
* \author Gregory Cristian ( Semtech )
*
* \author Daniel Jaeckle ( STACKFORCE )
*
* \author Johannes Bruder ( STACKFORCE )
*
* \defgroup REGIONCOMMON Common region implementation
* Region independent implementations which are common to all regions.
* \{
*/
#ifndef __REGIONCOMMON_H__
#define __REGIONCOMMON_H__
#include "utilities.h"
#include "radio.h"
#include "LoRaMacTypes.h"
#include "region/Region.h"
typedef struct sRegionCommonLinkAdrParams
{
/*!
* Number of repetitions.
*/
uint8_t NbRep;
/*!
* Datarate.
*/
int8_t Datarate;
/*!
* Tx power.
*/
int8_t TxPower;
/*!
* Channels mask control field.
*/
uint8_t ChMaskCtrl;
/*!
* Channels mask field.
*/
uint16_t ChMask;
}RegionCommonLinkAdrParams_t;
typedef struct sRegionCommonLinkAdrReqVerifyParams
{
/*!
* LoRaWAN specification Version
*/
Version_t Version;
/*!
* The current status of the AdrLinkRequest.
*/
uint8_t Status;
/*!
* Set to true, if ADR is enabled.
*/
bool AdrEnabled;
/*!
* The datarate the AdrLinkRequest wants to set.
*/
int8_t Datarate;
/*!
* The TX power the AdrLinkRequest wants to set.
*/
int8_t TxPower;
/*!
* The number of repetitions the AdrLinkRequest wants to set.
*/
uint8_t NbRep;
/*!
* The current datarate the node is using.
*/
int8_t CurrentDatarate;
/*!
* The current TX power the node is using.
*/
int8_t CurrentTxPower;
/*!
* The current number of repetitions the node is using.
*/
int8_t CurrentNbRep;
/*!
* The number of channels.
*/
uint8_t NbChannels;
/*!
* Pointer to the first element of the channels mask.
*/
uint16_t* ChannelsMask;
/*!
* The minimum possible datarate.
*/
int8_t MinDatarate;
/*!
* The maximum possible datarate.
*/
int8_t MaxDatarate;
/*!
* Pointer to the channels.
*/
ChannelParams_t* Channels;
/*!
* The minimum possible TX power.
*/
int8_t MinTxPower;
/*!
* The maximum possible TX power.
*/
int8_t MaxTxPower;
}RegionCommonLinkAdrReqVerifyParams_t;
typedef struct sRegionCommonCalcBackOffParams
{
/*!
* A pointer to region specific channels.
*/
ChannelParams_t* Channels;
/*!
* A pointer to region specific bands.
*/
Band_t* Bands;
/*!
* Set to true, if the last uplink was a join request.
*/
bool LastTxIsJoinRequest;
/*!
* Set to true, if the node is joined.
*/
bool Joined;
/*!
* Set to true, if the duty cycle is enabled.
*/
bool DutyCycleEnabled;
/*!
* The current channel.
*/
uint8_t Channel;
/*!
* The elapsed time since initialization.
*/
TimerTime_t ElapsedTime;
/*!
* The time on air of the last Tx frame.
*/
TimerTime_t TxTimeOnAir;
}RegionCommonCalcBackOffParams_t;
typedef struct sRegionCommonRxBeaconSetupParams
{
/*!
* A pointer to the available datarates.
*/
const uint8_t* Datarates;
/*!
* Frequency
*/
uint32_t Frequency;
/*!
* The size of the beacon frame.
*/
uint8_t BeaconSize;
/*!
* The datarate of the beacon.
*/
uint8_t BeaconDatarate;
/*!
* The channel bandwidth of the beacon.
*/
uint8_t BeaconChannelBW;
/*!
* The RX time.
*/
uint32_t RxTime;
/*!
* The symbol timeout of the RX procedure.
*/
uint16_t SymbolTimeout;
}RegionCommonRxBeaconSetupParams_t;
/*!
* \brief Calculates the join duty cycle.
* This is a generic function and valid for all regions.
*
* \param [IN] elapsedTime Elapsed time since the start of the device.
*
* \retval Duty cycle restriction.
*/
uint16_t RegionCommonGetJoinDc( TimerTime_t elapsedTime );
/*!
* \brief Verifies, if a value is in a given range.
* This is a generic function and valid for all regions.
*
* \param [IN] value Value to verify, if it is in range.
*
* \param [IN] min Minimum possible value.
*
* \param [IN] max Maximum possible value.
*
* \retval Returns 1 if the value is in range, otherwise 0.
*/
uint8_t RegionCommonValueInRange( int8_t value, int8_t min, int8_t max );
/*!
* \brief Verifies, if a datarate is available on an active channel.
* This is a generic function and valid for all regions.
*
* \param [IN] nbChannels Number of channels.
*
* \param [IN] channelsMask The channels mask of the region.
*
* \param [IN] dr The datarate to verify.
*
* \param [IN] minDr Minimum datarate.
*
* \param [IN] maxDr Maximum datarate.
*
* \param [IN] channels The channels of the region.
*
* \retval Returns true if the datarate is supported, false if not.
*/
bool RegionCommonChanVerifyDr( uint8_t nbChannels, uint16_t* channelsMask, int8_t dr,
int8_t minDr, int8_t maxDr, ChannelParams_t* channels );
/*!
* \brief Disables a channel in a given channels mask.
* This is a generic function and valid for all regions.
*
* \param [IN] channelsMask The channels mask of the region.
*
* \param [IN] id The id of the channels mask to disable.
*
* \param [IN] maxChannels Maximum number of channels.
*
* \retval Returns true if the channel could be disabled, false if not.
*/
bool RegionCommonChanDisable( uint16_t* channelsMask, uint8_t id, uint8_t maxChannels );
/*!
* \brief Counts the number of active channels in a given channels mask.
* This is a generic function and valid for all regions.
*
* \param [IN] channelsMask The channels mask of the region.
*
* \param [IN] startIdx Start index.
*
* \param [IN] stopIdx Stop index ( the channels of this index will not be counted ).
*
* \retval Returns the number of active channels.
*/
uint8_t RegionCommonCountChannels( uint16_t* channelsMask, uint8_t startIdx, uint8_t stopIdx );
/*!
* \brief Copy a channels mask.
* This is a generic function and valid for all regions.
*
* \param [IN] channelsMaskDest The destination channels mask.
*
* \param [IN] channelsMaskSrc The source channels mask.
*
* \param [IN] len The index length to copy.
*/
void RegionCommonChanMaskCopy( uint16_t* channelsMaskDest, uint16_t* channelsMaskSrc, uint8_t len );
/*!
* \brief Sets the last tx done property.
* This is a generic function and valid for all regions.
*
* \param [IN] joined Set to true, if the node has joined the network
*
* \param [IN] band The band to be updated.
*
* \param [IN] lastTxDone The time of the last TX done.
*/
void RegionCommonSetBandTxDone( bool joined, Band_t* band, TimerTime_t lastTxDone );
/*!
* \brief Updates the time-offs of the bands.
* 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] dutyCycle Set to true, if the duty cycle is enabled.
*
* \param [IN] bands A pointer to the bands.
*
* \param [IN] nbBands The number of bands available.
*
* \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 );
/*!
* \brief Parses the parameter of an LinkAdrRequest.
* This is a generic function and valid for all regions.
*
* \param [IN] payload Pointer to the payload containing the MAC commands. The payload
* must contain the CMD identifier, following by the parameters.
*
* \param [OUT] parseLinkAdr The function fills the structure with the ADR parameters.
*
* \retval Returns the length of the ADR request, if a request was found. Otherwise, the
* function returns 0.
*/
uint8_t RegionCommonParseLinkAdrReq( uint8_t* payload, RegionCommonLinkAdrParams_t* parseLinkAdr );
/*!
* \brief Verifies and updates the datarate, the TX power and the number of repetitions
* of a LinkAdrRequest. This depends on the configuration of ADR also.
*
* \param [IN] verifyParams Pointer to a structure containing input parameters.
*
* \param [OUT] dr The updated datarate.
*
* \param [OUT] txPow The updated TX power.
*
* \param [OUT] nbRep The updated number of repetitions.
*
* \retval Returns the status according to the LinkAdrRequest definition.
*/
uint8_t RegionCommonLinkAdrReqVerifyParams( RegionCommonLinkAdrReqVerifyParams_t* verifyParams, int8_t* dr, int8_t* txPow, uint8_t* nbRep );
/*!
* \brief Computes the symbol time for LoRa modulation.
*
* \param [IN] phyDr Physical datarate to use.
*
* \param [IN] bandwidth Bandwidth to use.
*
* \retval Returns the symbol time.
*/
double RegionCommonComputeSymbolTimeLoRa( uint8_t phyDr, uint32_t bandwidth );
/*!
* \brief Computes the symbol time for FSK modulation.
*
* \param [IN] phyDr Physical datarate to use.
*
* \param [IN] bandwidth Bandwidth to use.
*
* \retval Returns the symbol time.
*/
double RegionCommonComputeSymbolTimeFsk( uint8_t phyDr );
/*!
* \brief Computes the RX window timeout and the RX window offset.
*
* \param [IN] tSymbol Symbol timeout.
*
* \param [IN] minRxSymbols Minimum required number of symbols to detect an Rx frame.
*
* \param [IN] rxError System maximum timing error of the receiver. In milliseconds
* The receiver will turn on in a [-rxError : +rxError] ms interval around RxOffset.
*
* \param [IN] wakeUpTime Wakeup time of the system.
*
* \param [OUT] windowTimeout RX window timeout.
*
* \param [OUT] windowOffset RX window time offset to be applied to the RX delay.
*/
void RegionCommonComputeRxWindowParameters( double tSymbol, uint8_t minRxSymbols, uint32_t rxError, uint32_t wakeUpTime, uint32_t* windowTimeout, int32_t* windowOffset );
/*!
* \brief Computes the txPower, based on the max EIRP and the antenna gain.
*
* \remark US915 region uses a conducted power as input value for maxEirp.
* Thus, the antennaGain parameter must be set to 0.
*
* \param [IN] txPower TX power index.
*
* \param [IN] maxEirp Maximum EIRP.
*
* \param [IN] antennaGain Antenna gain. Referenced to the isotropic antenna.
* Value is in dBi. ( antennaGain[dBi] = measuredAntennaGain[dBd] + 2.15 )
*
* \retval Returns the physical TX power.
*/
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.
*
* \param [IN] rxBeaconSetupParams A pointer to the input parameters.
*/
void RegionCommonRxBeaconSetup( RegionCommonRxBeaconSetupParams_t* rxBeaconSetupParams );
/*! \} defgroup REGIONCOMMON */
#endif // __REGIONCOMMON_H__

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,509 @@
/*!
* \file RegionEU433.h
*
* \brief Region definition for EU433
*
* \copyright Revised BSD License, see section \ref LICENSE.
*
* \code
* ______ _
* / _____) _ | |
* ( (____ _____ ____ _| |_ _____ ____| |__
* \____ \| ___ | (_ _) ___ |/ ___) _ \
* _____) ) ____| | | || |_| ____( (___| | | |
* (______/|_____)_|_|_| \__)_____)\____)_| |_|
* (C)2013-2017 Semtech
*
* ___ _____ _ ___ _ _____ ___ ___ ___ ___
* / __|_ _/_\ / __| |/ / __/ _ \| _ \/ __| __|
* \__ \ | |/ _ \ (__| ' <| _| (_) | / (__| _|
* |___/ |_/_/ \_\___|_|\_\_| \___/|_|_\\___|___|
* embedded.connectivity.solutions===============
*
* \endcode
*
* \author Miguel Luis ( Semtech )
*
* \author Gregory Cristian ( Semtech )
*
* \author Daniel Jaeckle ( STACKFORCE )
*
* \author Johannes Bruder ( STACKFORCE )
*
* \defgroup REGIONEU433 Region EU433
* Implementation according to LoRaWAN Specification v1.0.2.
* \{
*/
#ifndef __REGION_EU433_H__
#define __REGION_EU433_H__
#include "region/Region.h"
/*!
* LoRaMac maximum number of channels
*/
#define EU433_MAX_NB_CHANNELS 16
/*!
* Number of default channels
*/
#define EU433_NUMB_DEFAULT_CHANNELS 3
/*!
* Number of channels to apply for the CF list
*/
#define EU433_NUMB_CHANNELS_CF_LIST 5
/*!
* Minimal datarate that can be used by the node
*/
#define EU433_TX_MIN_DATARATE DR_0
/*!
* Maximal datarate that can be used by the node
*/
#define EU433_TX_MAX_DATARATE DR_7
/*!
* Minimal datarate that can be used by the node
*/
#define EU433_RX_MIN_DATARATE DR_0
/*!
* Maximal datarate that can be used by the node
*/
#define EU433_RX_MAX_DATARATE DR_7
/*!
* Default datarate used by the node
*/
#define EU433_DEFAULT_DATARATE DR_0
/*!
* Minimal Rx1 receive datarate offset
*/
#define EU433_MIN_RX1_DR_OFFSET 0
/*!
* Maximal Rx1 receive datarate offset
*/
#define EU433_MAX_RX1_DR_OFFSET 5
/*!
* Default Rx1 receive datarate offset
*/
#define EU433_DEFAULT_RX1_DR_OFFSET 0
/*!
* Minimal Tx output power that can be used by the node
*/
#define EU433_MIN_TX_POWER TX_POWER_5
/*!
* Maximal Tx output power that can be used by the node
*/
#define EU433_MAX_TX_POWER TX_POWER_0
/*!
* Default Tx output power used by the node
*/
#define EU433_DEFAULT_TX_POWER TX_POWER_0
/*!
* Default Max EIRP
*/
#define EU433_DEFAULT_MAX_EIRP 12.15f
/*!
* Default antenna gain
*/
#define EU433_DEFAULT_ANTENNA_GAIN 2.15f
/*!
* ADR Ack limit
*/
#define EU433_ADR_ACK_LIMIT 64
/*!
* ADR Ack delay
*/
#define EU433_ADR_ACK_DELAY 32
/*!
* Enabled or disabled the duty cycle
*/
#define EU433_DUTY_CYCLE_ENABLED 1
/*!
* Maximum RX window duration
*/
#define EU433_MAX_RX_WINDOW 3000
/*!
* Receive delay 1
*/
#define EU433_RECEIVE_DELAY1 1000
/*!
* Receive delay 2
*/
#define EU433_RECEIVE_DELAY2 2000
/*!
* Join accept delay 1
*/
#define EU433_JOIN_ACCEPT_DELAY1 5000
/*!
* Join accept delay 2
*/
#define EU433_JOIN_ACCEPT_DELAY2 6000
/*!
* Maximum frame counter gap
*/
#define EU433_MAX_FCNT_GAP 16384
/*!
* Ack timeout
*/
#define EU433_ACKTIMEOUT 2000
/*!
* Random ack timeout limits
*/
#define EU433_ACK_TIMEOUT_RND 1000
/*!
* Verification of default datarate
*/
#if ( EU433_DEFAULT_DATARATE > DR_5 )
#error "A default DR higher than DR_5 may lead to connectivity loss."
#endif
/*!
* Second reception window channel frequency definition.
*/
#define EU433_RX_WND_2_FREQ 434665000
/*!
* Second reception window channel datarate definition.
*/
#define EU433_RX_WND_2_DR DR_0
/*!
* LoRaMac maximum number of bands
*/
#define EU433_MAX_NB_BANDS 1
/*
* CLASS B
*/
/*!
* Beacon frequency
*/
#define EU433_BEACON_CHANNEL_FREQ 434665000
/*!
* Payload size of a beacon frame
*/
#define EU433_BEACON_SIZE 17
/*!
* Size of RFU 1 field
*/
#define EU433_RFU1_SIZE 2
/*!
* Size of RFU 2 field
*/
#define EU433_RFU2_SIZE 0
/*!
* Datarate of the beacon channel
*/
#define EU433_BEACON_CHANNEL_DR DR_3
/*!
* Bandwith of the beacon channel
*/
#define EU433_BEACON_CHANNEL_BW 0
/*!
* Ping slot channel datarate
*/
#define EU433_PING_SLOT_CHANNEL_DR DR_3
/*!
* Band 0 definition
* { DutyCycle, TxMaxPower, LastJoinTxDoneTime, LastTxDoneTime, TimeOff }
*/
#define EU433_BAND0 { 100, EU433_MAX_TX_POWER, 0, 0, 0 } // 1.0 %
/*!
* LoRaMac default channel 1
* Channel = { Frequency [Hz], RX1 Frequency [Hz], { ( ( DrMax << 4 ) | DrMin ) }, Band }
*/
#define EU433_LC1 { 433175000, 0, { ( ( DR_5 << 4 ) | DR_0 ) }, 0 }
/*!
* LoRaMac default channel 2
* Channel = { Frequency [Hz], RX1 Frequency [Hz], { ( ( DrMax << 4 ) | DrMin ) }, Band }
*/
#define EU433_LC2 { 433375000, 0, { ( ( DR_5 << 4 ) | DR_0 ) }, 0 }
/*!
* LoRaMac default channel 3
* Channel = { Frequency [Hz], RX1 Frequency [Hz], { ( ( DrMax << 4 ) | DrMin ) }, Band }
*/
#define EU433_LC3 { 433575000, 0, { ( ( DR_5 << 4 ) | DR_0 ) }, 0 }
/*!
* LoRaMac channels which are allowed for the join procedure
*/
#define EU433_JOIN_CHANNELS ( uint16_t )( LC( 1 ) | LC( 2 ) | LC( 3 ) )
/*!
* Data rates table definition
*/
static const uint8_t DataratesEU433[] = { 12, 11, 10, 9, 8, 7, 7, 50 };
/*!
* Bandwidths table definition in Hz
*/
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.
*/
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.
*
* \param [IN] getPhy Pointer to the function parameters.
*
* \retval Returns a structure containing the PHY parameter.
*/
PhyParam_t RegionEU433GetPhyParam( GetPhyParams_t* getPhy );
/*!
* \brief Updates the last TX done parameters of the current channel.
*
* \param [IN] txDone Pointer to the function parameters.
*/
void RegionEU433SetBandTxDone( SetBandTxDoneParams_t* txDone );
/*!
* \brief Initializes the channels masks and the channels.
*
* \param [IN] type Sets the initialization type.
*/
void RegionEU433InitDefaults( InitDefaultsParams_t* params );
/*!
* \brief Returns a pointer to the internal context and its size.
*
* \param [OUT] params Pointer to the function parameters.
*
* \retval Points to a structure where the module store its non-volatile context.
*/
void* RegionEU433GetNvmCtx( GetNvmCtxParams_t* params );
/*!
* \brief Verifies a parameter.
*
* \param [IN] verify Pointer to the function parameters.
*
* \param [IN] type Sets the initialization type.
*
* \retval Returns true, if the parameter is valid.
*/
bool RegionEU433Verify( VerifyParams_t* verify, PhyAttribute_t phyAttribute );
/*!
* \brief The function parses the input buffer and sets up the channels of the
* CF list.
*
* \param [IN] applyCFList Pointer to the function parameters.
*/
void RegionEU433ApplyCFList( ApplyCFListParams_t* applyCFList );
/*!
* \brief Sets a channels mask.
*
* \param [IN] chanMaskSet Pointer to the function parameters.
*
* \retval Returns true, if the channels mask could be set.
*/
bool RegionEU433ChanMaskSet( ChanMaskSetParams_t* chanMaskSet );
/*!
* Computes the Rx window timeout and offset.
*
* \param [IN] datarate Rx window datarate index to be used
*
* \param [IN] minRxSymbols Minimum required number of symbols to detect an Rx frame.
*
* \param [IN] rxError System maximum timing error of the receiver. In milliseconds
* The receiver will turn on in a [-rxError : +rxError] ms
* interval around RxOffset
*
* \param [OUT]rxConfigParams Returns updated WindowTimeout and WindowOffset fields.
*/
void RegionEU433ComputeRxWindowParameters( int8_t datarate, uint8_t minRxSymbols, uint32_t rxError, RxConfigParams_t *rxConfigParams );
/*!
* \brief Configuration of the RX windows.
*
* \param [IN] rxConfig Pointer to the function parameters.
*
* \param [OUT] datarate The datarate index which was set.
*
* \retval Returns true, if the configuration was applied successfully.
*/
bool RegionEU433RxConfig( RxConfigParams_t* rxConfig, int8_t* datarate );
/*!
* \brief TX configuration.
*
* \param [IN] txConfig Pointer to the function parameters.
*
* \param [OUT] txPower The tx power index which was set.
*
* \param [OUT] txTimeOnAir The time-on-air of the frame.
*
* \retval Returns true, if the configuration was applied successfully.
*/
bool RegionEU433TxConfig( TxConfigParams_t* txConfig, int8_t* txPower, TimerTime_t* txTimeOnAir );
/*!
* \brief The function processes a Link ADR Request.
*
* \param [IN] linkAdrReq Pointer to the function parameters.
*
* \retval Returns the status of the operation, according to the LoRaMAC specification.
*/
uint8_t RegionEU433LinkAdrReq( LinkAdrReqParams_t* linkAdrReq, int8_t* drOut, int8_t* txPowOut, uint8_t* nbRepOut, uint8_t* nbBytesParsed );
/*!
* \brief The function processes a RX Parameter Setup Request.
*
* \param [IN] rxParamSetupReq Pointer to the function parameters.
*
* \retval Returns the status of the operation, according to the LoRaMAC specification.
*/
uint8_t RegionEU433RxParamSetupReq( RxParamSetupReqParams_t* rxParamSetupReq );
/*!
* \brief The function processes a Channel Request.
*
* \param [IN] newChannelReq Pointer to the function parameters.
*
* \retval Returns the status of the operation, according to the LoRaMAC specification.
*/
uint8_t RegionEU433NewChannelReq( NewChannelReqParams_t* newChannelReq );
/*!
* \brief The function processes a TX ParamSetup Request.
*
* \param [IN] txParamSetupReq Pointer to the function parameters.
*
* \retval Returns the status of the operation, according to the LoRaMAC specification.
* Returns -1, if the functionality is not implemented. In this case, the end node
* shall not process the command.
*/
int8_t RegionEU433TxParamSetupReq( TxParamSetupReqParams_t* txParamSetupReq );
/*!
* \brief The function processes a DlChannel Request.
*
* \param [IN] dlChannelReq Pointer to the function parameters.
*
* \retval Returns the status of the operation, according to the LoRaMAC specification.
*/
uint8_t RegionEU433DlChannelReq( DlChannelReqParams_t* dlChannelReq );
/*!
* \brief Alternates the datarate of the channel for the join request.
*
* \param [IN] currentDr Current datarate.
*
* \retval Datarate to apply.
*/
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
*
* \param [OUT] channel Next channel to use for TX.
*
* \param [OUT] time Time to wait for the next transmission according to the duty
* cycle.
*
* \param [OUT] aggregatedTimeOff Updates the aggregated time off.
*
* \retval Function status [1: OK, 0: Unable to find a channel on the current datarate]
*/
LoRaMacStatus_t RegionEU433NextChannel( NextChanParams_t* nextChanParams, uint8_t* channel, TimerTime_t* time, TimerTime_t* aggregatedTimeOff );
/*!
* \brief Adds a channel.
*
* \param [IN] channelAdd Pointer to the function parameters.
*
* \retval Status of the operation.
*/
LoRaMacStatus_t RegionEU433ChannelAdd( ChannelAddParams_t* channelAdd );
/*!
* \brief Removes a channel.
*
* \param [IN] channelRemove Pointer to the function parameters.
*
* \retval Returns true, if the channel was removed successfully.
*/
bool RegionEU433ChannelsRemove( ChannelRemoveParams_t* channelRemove );
/*!
* \brief Sets the radio into continuous wave mode.
*
* \param [IN] continuousWave Pointer to the function parameters.
*/
void RegionEU433SetContinuousWave( ContinuousWaveParams_t* continuousWave );
/*!
* \brief Computes new datarate according to the given offset
*
* \param [IN] downlinkDwellTime Downlink dwell time configuration. 0: No limit, 1: 400ms
*
* \param [IN] dr Current datarate
*
* \param [IN] drOffset Offset to be applied
*
* \retval newDr Computed datarate.
*/
uint8_t RegionEU433ApplyDrOffset( uint8_t downlinkDwellTime, int8_t dr, int8_t drOffset );
/*!
* \brief Sets the radio into beacon reception mode
*
* \param [IN] rxBeaconSetup Pointer to the function parameters
*/
void RegionEU433RxBeaconSetup( RxBeaconSetup_t* rxBeaconSetup, uint8_t* outDr );
/*! \} defgroup REGIONEU433 */
#endif // __REGION_EU433_H__

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,536 @@
/*!
* \file RegionEU868.h
*
* \brief Region definition for EU868
*
* \copyright Revised BSD License, see section \ref LICENSE.
*
* \code
* ______ _
* / _____) _ | |
* ( (____ _____ ____ _| |_ _____ ____| |__
* \____ \| ___ | (_ _) ___ |/ ___) _ \
* _____) ) ____| | | || |_| ____( (___| | | |
* (______/|_____)_|_|_| \__)_____)\____)_| |_|
* (C)2013-2017 Semtech
*
* ___ _____ _ ___ _ _____ ___ ___ ___ ___
* / __|_ _/_\ / __| |/ / __/ _ \| _ \/ __| __|
* \__ \ | |/ _ \ (__| ' <| _| (_) | / (__| _|
* |___/ |_/_/ \_\___|_|\_\_| \___/|_|_\\___|___|
* embedded.connectivity.solutions===============
*
* \endcode
*
* \author Miguel Luis ( Semtech )
*
* \author Gregory Cristian ( Semtech )
*
* \author Daniel Jaeckle ( STACKFORCE )
*
* \author Johannes Bruder ( STACKFORCE )
*
* \defgroup REGIONEU868 Region EU868
* Implementation according to LoRaWAN Specification v1.0.2.
* \{
*/
#ifndef __REGION_EU868_H__
#define __REGION_EU868_H__
#include "region/Region.h"
/*!
* LoRaMac maximum number of channels
*/
#define EU868_MAX_NB_CHANNELS 16
/*!
* Number of default channels
*/
#define EU868_NUMB_DEFAULT_CHANNELS 3
/*!
* Number of channels to apply for the CF list
*/
#define EU868_NUMB_CHANNELS_CF_LIST 5
/*!
* Minimal datarate that can be used by the node
*/
#define EU868_TX_MIN_DATARATE DR_0
/*!
* Maximal datarate that can be used by the node
*/
#define EU868_TX_MAX_DATARATE DR_7
/*!
* Minimal datarate that can be used by the node
*/
#define EU868_RX_MIN_DATARATE DR_0
/*!
* Maximal datarate that can be used by the node
*/
#define EU868_RX_MAX_DATARATE DR_7
/*!
* Default datarate used by the node
*/
#define EU868_DEFAULT_DATARATE DR_0
/*!
* Minimal Rx1 receive datarate offset
*/
#define EU868_MIN_RX1_DR_OFFSET 0
/*!
* Maximal Rx1 receive datarate offset
*/
#define EU868_MAX_RX1_DR_OFFSET 5
/*!
* Default Rx1 receive datarate offset
*/
#define EU868_DEFAULT_RX1_DR_OFFSET 0
/*!
* Minimal Tx output power that can be used by the node
*/
#define EU868_MIN_TX_POWER TX_POWER_7
/*!
* Maximal Tx output power that can be used by the node
*/
#define EU868_MAX_TX_POWER TX_POWER_0
/*!
* Default Tx output power used by the node
*/
#define EU868_DEFAULT_TX_POWER TX_POWER_0
/*!
* Default Max EIRP
*/
#define EU868_DEFAULT_MAX_EIRP 16.0f
/*!
* Default antenna gain
*/
#define EU868_DEFAULT_ANTENNA_GAIN 2.15f
/*!
* ADR Ack limit
*/
#define EU868_ADR_ACK_LIMIT 64
/*!
* ADR Ack delay
*/
#define EU868_ADR_ACK_DELAY 32
/*!
* Enabled or disabled the duty cycle
*/
#define EU868_DUTY_CYCLE_ENABLED 1
/*!
* Maximum RX window duration
*/
#define EU868_MAX_RX_WINDOW 3000
/*!
* Receive delay 1
*/
#define EU868_RECEIVE_DELAY1 1000
/*!
* Receive delay 2
*/
#define EU868_RECEIVE_DELAY2 2000
/*!
* Join accept delay 1
*/
#define EU868_JOIN_ACCEPT_DELAY1 5000
/*!
* Join accept delay 2
*/
#define EU868_JOIN_ACCEPT_DELAY2 6000
/*!
* Maximum frame counter gap
*/
#define EU868_MAX_FCNT_GAP 16384
/*!
* Ack timeout
*/
#define EU868_ACKTIMEOUT 2000
/*!
* Random ack timeout limits
*/
#define EU868_ACK_TIMEOUT_RND 1000
#if ( EU868_DEFAULT_DATARATE > DR_5 )
#error "A default DR higher than DR_5 may lead to connectivity loss."
#endif
/*!
* Second reception window channel frequency definition.
*/
#define EU868_RX_WND_2_FREQ 869525000
/*!
* Second reception window channel datarate definition.
*/
#define EU868_RX_WND_2_DR DR_0
/*
* CLASS B
*/
/*!
* Beacon frequency
*/
#define EU868_BEACON_CHANNEL_FREQ 869525000
/*!
* Payload size of a beacon frame
*/
#define EU868_BEACON_SIZE 17
/*!
* Size of RFU 1 field
*/
#define EU868_RFU1_SIZE 2
/*!
* Size of RFU 2 field
*/
#define EU868_RFU2_SIZE 0
/*!
* Datarate of the beacon channel
*/
#define EU868_BEACON_CHANNEL_DR DR_3
/*!
* Bandwith of the beacon channel
*/
#define EU868_BEACON_CHANNEL_BW 0
/*!
* Ping slot channel datarate
*/
#define EU868_PING_SLOT_CHANNEL_DR DR_3
/*!
* Maximum number of bands
*/
#define EU868_MAX_NB_BANDS 6
/*!
* Band 0 definition
* { DutyCycle, TxMaxPower, LastJoinTxDoneTime, LastTxDoneTime, TimeOff }
*/
#define EU868_BAND0 { 100 , EU868_MAX_TX_POWER, 0, 0, 0 } // 1.0 %
/*!
* Band 1 definition
* { DutyCycle, TxMaxPower, LastJoinTxDoneTime, LastTxDoneTime, TimeOff }
*/
#define EU868_BAND1 { 100 , EU868_MAX_TX_POWER, 0, 0, 0 } // 1.0 %
/*!
* Band 2 definition
* Band = { DutyCycle, TxMaxPower, LastJoinTxDoneTime, LastTxDoneTime, TimeOff }
*/
#define EU868_BAND2 { 1000, EU868_MAX_TX_POWER, 0, 0, 0 } // 0.1 %
/*!
* Band 3 definition
* Band = { DutyCycle, TxMaxPower, LastJoinTxDoneTime, LastTxDoneTime, TimeOff }
*/
#define EU868_BAND3 { 10 , EU868_MAX_TX_POWER, 0, 0, 0 } // 10.0 %
/*!
* Band 4 definition
* Band = { DutyCycle, TxMaxPower, LastJoinTxDoneTime, LastTxDoneTime, TimeOff }
*/
#define EU868_BAND4 { 100 , EU868_MAX_TX_POWER, 0, 0, 0 } // 1.0 %
/*!
* Band 5 definition
* Band = { DutyCycle, TxMaxPower, LastJoinTxDoneTime, LastTxDoneTime, TimeOff }
*/
#define EU868_BAND5 { 1000, EU868_MAX_TX_POWER, 0, 0, 0 } // 0.1 %
/*!
* LoRaMac default channel 1
* Channel = { Frequency [Hz], RX1 Frequency [Hz], { ( ( DrMax << 4 ) | DrMin ) }, Band }
*/
#define EU868_LC1 { 868100000, 0, { ( ( DR_5 << 4 ) | DR_0 ) }, 1 }
/*!
* LoRaMac default channel 2
* Channel = { Frequency [Hz], RX1 Frequency [Hz], { ( ( DrMax << 4 ) | DrMin ) }, Band }
*/
#define EU868_LC2 { 868300000, 0, { ( ( DR_5 << 4 ) | DR_0 ) }, 1 }
/*!
* LoRaMac default channel 3
* Channel = { Frequency [Hz], RX1 Frequency [Hz], { ( ( DrMax << 4 ) | DrMin ) }, Band }
*/
#define EU868_LC3 { 868500000, 0, { ( ( DR_5 << 4 ) | DR_0 ) }, 1 }
/*!
* LoRaMac channels which are allowed for the join procedure
*/
#define EU868_JOIN_CHANNELS ( uint16_t )( LC( 1 ) | LC( 2 ) | LC( 3 ) )
/*!
* Data rates table definition
*/
static const uint8_t DataratesEU868[] = { 12, 11, 10, 9, 8, 7, 7, 50 };
/*!
* Bandwidths table definition in Hz
*/
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.
*/
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.
*
* \param [IN] getPhy Pointer to the function parameters.
*
* \retval Returns a structure containing the PHY parameter.
*/
PhyParam_t RegionEU868GetPhyParam( GetPhyParams_t* getPhy );
/*!
* \brief Updates the last TX done parameters of the current channel.
*
* \param [IN] txDone Pointer to the function parameters.
*/
void RegionEU868SetBandTxDone( SetBandTxDoneParams_t* txDone );
/*!
* \brief Initializes the channels masks and the channels.
*
* \param [IN] type Sets the initialization type.
*/
void RegionEU868InitDefaults( InitDefaultsParams_t* params );
/*!
* \brief Returns a pointer to the internal context and its size.
*
* \param [OUT] params Pointer to the function parameters.
*
* \retval Points to a structure where the module store its non-volatile context.
*/
void* RegionEU868GetNvmCtx( GetNvmCtxParams_t* params );
/*!
* \brief Verifies a parameter.
*
* \param [IN] verify Pointer to the function parameters.
*
* \param [IN] type Sets the initialization type.
*
* \retval Returns true, if the parameter is valid.
*/
bool RegionEU868Verify( VerifyParams_t* verify, PhyAttribute_t phyAttribute );
/*!
* \brief The function parses the input buffer and sets up the channels of the
* CF list.
*
* \param [IN] applyCFList Pointer to the function parameters.
*/
void RegionEU868ApplyCFList( ApplyCFListParams_t* applyCFList );
/*!
* \brief Sets a channels mask.
*
* \param [IN] chanMaskSet Pointer to the function parameters.
*
* \retval Returns true, if the channels mask could be set.
*/
bool RegionEU868ChanMaskSet( ChanMaskSetParams_t* chanMaskSet );
/*!
* Computes the Rx window timeout and offset.
*
* \param [IN] datarate Rx window datarate index to be used
*
* \param [IN] minRxSymbols Minimum required number of symbols to detect an Rx frame.
*
* \param [IN] rxError System maximum timing error of the receiver. In milliseconds
* The receiver will turn on in a [-rxError : +rxError] ms
* interval around RxOffset
*
* \param [OUT]rxConfigParams Returns updated WindowTimeout and WindowOffset fields.
*/
void RegionEU868ComputeRxWindowParameters( int8_t datarate, uint8_t minRxSymbols, uint32_t rxError, RxConfigParams_t *rxConfigParams );
/*!
* \brief Configuration of the RX windows.
*
* \param [IN] rxConfig Pointer to the function parameters.
*
* \param [OUT] datarate The datarate index which was set.
*
* \retval Returns true, if the configuration was applied successfully.
*/
bool RegionEU868RxConfig( RxConfigParams_t* rxConfig, int8_t* datarate );
/*!
* \brief TX configuration.
*
* \param [IN] txConfig Pointer to the function parameters.
*
* \param [OUT] txPower The tx power index which was set.
*
* \param [OUT] txTimeOnAir The time-on-air of the frame.
*
* \retval Returns true, if the configuration was applied successfully.
*/
bool RegionEU868TxConfig( TxConfigParams_t* txConfig, int8_t* txPower, TimerTime_t* txTimeOnAir );
/*!
* \brief The function processes a Link ADR Request.
*
* \param [IN] linkAdrReq Pointer to the function parameters.
*
* \retval Returns the status of the operation, according to the LoRaMAC specification.
*/
uint8_t RegionEU868LinkAdrReq( LinkAdrReqParams_t* linkAdrReq, int8_t* drOut, int8_t* txPowOut, uint8_t* nbRepOut, uint8_t* nbBytesParsed );
/*!
* \brief The function processes a RX Parameter Setup Request.
*
* \param [IN] rxParamSetupReq Pointer to the function parameters.
*
* \retval Returns the status of the operation, according to the LoRaMAC specification.
*/
uint8_t RegionEU868RxParamSetupReq( RxParamSetupReqParams_t* rxParamSetupReq );
/*!
* \brief The function processes a Channel Request.
*
* \param [IN] newChannelReq Pointer to the function parameters.
*
* \retval Returns the status of the operation, according to the LoRaMAC specification.
*/
uint8_t RegionEU868NewChannelReq( NewChannelReqParams_t* newChannelReq );
/*!
* \brief The function processes a TX ParamSetup Request.
*
* \param [IN] txParamSetupReq Pointer to the function parameters.
*
* \retval Returns the status of the operation, according to the LoRaMAC specification.
* Returns -1, if the functionality is not implemented. In this case, the end node
* shall not process the command.
*/
int8_t RegionEU868TxParamSetupReq( TxParamSetupReqParams_t* txParamSetupReq );
/*!
* \brief The function processes a DlChannel Request.
*
* \param [IN] dlChannelReq Pointer to the function parameters.
*
* \retval Returns the status of the operation, according to the LoRaMAC specification.
*/
uint8_t RegionEU868DlChannelReq( DlChannelReqParams_t* dlChannelReq );
/*!
* \brief Alternates the datarate of the channel for the join request.
*
* \param [IN] currentDr Current datarate.
*
* \retval Datarate to apply.
*/
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
*
* \param [OUT] channel Next channel to use for TX.
*
* \param [OUT] time Time to wait for the next transmission according to the duty
* cycle.
*
* \param [OUT] aggregatedTimeOff Updates the aggregated time off.
*
* \retval Function status [1: OK, 0: Unable to find a channel on the current datarate]
*/
LoRaMacStatus_t RegionEU868NextChannel( NextChanParams_t* nextChanParams, uint8_t* channel, TimerTime_t* time, TimerTime_t* aggregatedTimeOff );
/*!
* \brief Adds a channel.
*
* \param [IN] channelAdd Pointer to the function parameters.
*
* \retval Status of the operation.
*/
LoRaMacStatus_t RegionEU868ChannelAdd( ChannelAddParams_t* channelAdd );
/*!
* \brief Removes a channel.
*
* \param [IN] channelRemove Pointer to the function parameters.
*
* \retval Returns true, if the channel was removed successfully.
*/
bool RegionEU868ChannelsRemove( ChannelRemoveParams_t* channelRemove );
/*!
* \brief Sets the radio into continuous wave mode.
*
* \param [IN] continuousWave Pointer to the function parameters.
*/
void RegionEU868SetContinuousWave( ContinuousWaveParams_t* continuousWave );
/*!
* \brief Computes new datarate according to the given offset
*
* \param [IN] downlinkDwellTime Downlink dwell time configuration. 0: No limit, 1: 400ms
*
* \param [IN] dr Current datarate
*
* \param [IN] drOffset Offset to be applied
*
* \retval newDr Computed datarate.
*/
uint8_t RegionEU868ApplyDrOffset( uint8_t downlinkDwellTime, int8_t dr, int8_t drOffset );
/*!
* \brief Sets the radio into beacon reception mode
*
* \param [IN] rxBeaconSetup Pointer to the function parameters
*/
void RegionEU868RxBeaconSetup( RxBeaconSetup_t* rxBeaconSetup, uint8_t* outDr );
/*! \} defgroup REGIONEU868 */
#endif // __REGION_EU868_H__

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,511 @@
/*!
* \file RegionIN865.h
*
* \brief Region definition for IN865
*
* \copyright Revised BSD License, see section \ref LICENSE.
*
* \code
* ______ _
* / _____) _ | |
* ( (____ _____ ____ _| |_ _____ ____| |__
* \____ \| ___ | (_ _) ___ |/ ___) _ \
* _____) ) ____| | | || |_| ____( (___| | | |
* (______/|_____)_|_|_| \__)_____)\____)_| |_|
* (C)2013-2017 Semtech
*
* ___ _____ _ ___ _ _____ ___ ___ ___ ___
* / __|_ _/_\ / __| |/ / __/ _ \| _ \/ __| __|
* \__ \ | |/ _ \ (__| ' <| _| (_) | / (__| _|
* |___/ |_/_/ \_\___|_|\_\_| \___/|_|_\\___|___|
* embedded.connectivity.solutions===============
*
* \endcode
*
* \author Miguel Luis ( Semtech )
*
* \author Gregory Cristian ( Semtech )
*
* \author Daniel Jaeckle ( STACKFORCE )
*
* \author Johannes Bruder ( STACKFORCE )
*
* \defgroup REGIONIN865 Region IN865
* Implementation according to LoRaWAN Specification v1.0.2.
* \{
*/
#ifndef __REGION_IN865_H__
#define __REGION_IN865_H__
#include "region/Region.h"
/*!
* LoRaMac maximum number of channels
*/
#define IN865_MAX_NB_CHANNELS 16
/*!
* Number of default channels
*/
#define IN865_NUMB_DEFAULT_CHANNELS 3
/*!
* Number of channels to apply for the CF list
*/
#define IN865_NUMB_CHANNELS_CF_LIST 5
/*!
* Minimal datarate that can be used by the node
*/
#define IN865_TX_MIN_DATARATE DR_0
/*!
* Maximal datarate that can be used by the node
*/
#define IN865_TX_MAX_DATARATE DR_7
/*!
* Minimal datarate that can be used by the node
*/
#define IN865_RX_MIN_DATARATE DR_0
/*!
* Maximal datarate that can be used by the node
*/
#define IN865_RX_MAX_DATARATE DR_7
/*!
* Default datarate used by the node
*/
#define IN865_DEFAULT_DATARATE DR_0
/*!
* Minimal Rx1 receive datarate offset
*/
#define IN865_MIN_RX1_DR_OFFSET 0
/*!
* Maximal Rx1 receive datarate offset
*/
#define IN865_MAX_RX1_DR_OFFSET 7
/*!
* Default Rx1 receive datarate offset
*/
#define IN865_DEFAULT_RX1_DR_OFFSET 0
/*!
* Minimal Tx output power that can be used by the node
*/
#define IN865_MIN_TX_POWER TX_POWER_10
/*!
* Maximal Tx output power that can be used by the node
*/
#define IN865_MAX_TX_POWER TX_POWER_0
/*!
* Default Tx output power used by the node
*/
#define IN865_DEFAULT_TX_POWER TX_POWER_0
/*!
* Default Max EIRP
*/
#define IN865_DEFAULT_MAX_EIRP 30.0f
/*!
* Default antenna gain
*/
#define IN865_DEFAULT_ANTENNA_GAIN 2.15f
/*!
* ADR Ack limit
*/
#define IN865_ADR_ACK_LIMIT 64
/*!
* ADR Ack delay
*/
#define IN865_ADR_ACK_DELAY 32
/*!
* Enabled or disabled the duty cycle
*/
#define IN865_DUTY_CYCLE_ENABLED 1
/*!
* Maximum RX window duration
*/
#define IN865_MAX_RX_WINDOW 3000
/*!
* Receive delay 1
*/
#define IN865_RECEIVE_DELAY1 1000
/*!
* Receive delay 2
*/
#define IN865_RECEIVE_DELAY2 2000
/*!
* Join accept delay 1
*/
#define IN865_JOIN_ACCEPT_DELAY1 5000
/*!
* Join accept delay 2
*/
#define IN865_JOIN_ACCEPT_DELAY2 6000
/*!
* Maximum frame counter gap
*/
#define IN865_MAX_FCNT_GAP 16384
/*!
* Ack timeout
*/
#define IN865_ACKTIMEOUT 2000
/*!
* Random ack timeout limits
*/
#define IN865_ACK_TIMEOUT_RND 1000
#if ( IN865_DEFAULT_DATARATE > DR_5 )
#error "A default DR higher than DR_5 may lead to connectivity loss."
#endif
/*!
* Second reception window channel frequency definition.
*/
#define IN865_RX_WND_2_FREQ 866550000
/*!
* Second reception window channel datarate definition.
*/
#define IN865_RX_WND_2_DR DR_2
/*
* CLASS B
*/
/*!
* Beacon frequency
*/
#define IN865_BEACON_CHANNEL_FREQ 866550000
/*!
* Payload size of a beacon frame
*/
#define IN865_BEACON_SIZE 19
/*!
* Size of RFU 1 field
*/
#define IN865_RFU1_SIZE 1
/*!
* Size of RFU 2 field
*/
#define IN865_RFU2_SIZE 3
/*!
* Datarate of the beacon channel
*/
#define IN865_BEACON_CHANNEL_DR DR_4
/*!
* Bandwith of the beacon channel
*/
#define IN865_BEACON_CHANNEL_BW 0
/*!
* Ping slot channel datarate
*/
#define IN865_PING_SLOT_CHANNEL_DR DR_4
/*!
* Maximum number of bands
*/
#define IN865_MAX_NB_BANDS 1
/*!
* Band 0 definition
* { DutyCycle, TxMaxPower, LastJoinTxDoneTime, LastTxDoneTime, TimeOff }
*/
#define IN865_BAND0 { 1 , IN865_MAX_TX_POWER, 0, 0, 0 } // 100.0 %
/*!
* LoRaMac default channel 1
* Channel = { Frequency [Hz], RX1 Frequency [Hz], { ( ( DrMax << 4 ) | DrMin ) }, Band }
*/
#define IN865_LC1 { 865062500, 0, { ( ( DR_5 << 4 ) | DR_0 ) }, 0 }
/*!
* LoRaMac default channel 2
* Channel = { Frequency [Hz], RX1 Frequency [Hz], { ( ( DrMax << 4 ) | DrMin ) }, Band }
*/
#define IN865_LC2 { 865402500, 0, { ( ( DR_5 << 4 ) | DR_0 ) }, 0 }
/*!
* LoRaMac default channel 3
* Channel = { Frequency [Hz], RX1 Frequency [Hz], { ( ( DrMax << 4 ) | DrMin ) }, Band }
*/
#define IN865_LC3 { 865985000, 0, { ( ( DR_5 << 4 ) | DR_0 ) }, 0 }
/*!
* LoRaMac channels which are allowed for the join procedure
*/
#define IN865_JOIN_CHANNELS ( uint16_t )( LC( 1 ) | LC( 2 ) | LC( 3 ) )
/*!
* Data rates table definition
*/
static const uint8_t DataratesIN865[] = { 12, 11, 10, 9, 8, 7, 7, 50 };
/*!
* Bandwidths table definition in Hz
*/
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.
*/
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.
*/
static const int8_t EffectiveRx1DrOffsetIN865[] = { 0, 1, 2, 3, 4, 5, -1, -2 };
/*!
* \brief The function gets a value of a specific phy attribute.
*
* \param [IN] getPhy Pointer to the function parameters.
*
* \retval Returns a structure containing the PHY parameter.
*/
PhyParam_t RegionIN865GetPhyParam( GetPhyParams_t* getPhy );
/*!
* \brief Updates the last TX done parameters of the current channel.
*
* \param [IN] txDone Pointer to the function parameters.
*/
void RegionIN865SetBandTxDone( SetBandTxDoneParams_t* txDone );
/*!
* \brief Initializes the channels masks and the channels.
*
* \param [IN] type Sets the initialization type.
*/
void RegionIN865InitDefaults( InitDefaultsParams_t* params );
/*!
* \brief Returns a pointer to the internal context and its size.
*
* \param [OUT] params Pointer to the function parameters.
*
* \retval Points to a structure where the module store its non-volatile context.
*/
void* RegionIN865GetNvmCtx( GetNvmCtxParams_t* params );
/*!
* \brief Verifies a parameter.
*
* \param [IN] verify Pointer to the function parameters.
*
* \param [IN] type Sets the initialization type.
*
* \retval Returns true, if the parameter is valid.
*/
bool RegionIN865Verify( VerifyParams_t* verify, PhyAttribute_t phyAttribute );
/*!
* \brief The function parses the input buffer and sets up the channels of the
* CF list.
*
* \param [IN] applyCFList Pointer to the function parameters.
*/
void RegionIN865ApplyCFList( ApplyCFListParams_t* applyCFList );
/*!
* \brief Sets a channels mask.
*
* \param [IN] chanMaskSet Pointer to the function parameters.
*
* \retval Returns true, if the channels mask could be set.
*/
bool RegionIN865ChanMaskSet( ChanMaskSetParams_t* chanMaskSet );
/*!
* Computes the Rx window timeout and offset.
*
* \param [IN] datarate Rx window datarate index to be used
*
* \param [IN] minRxSymbols Minimum required number of symbols to detect an Rx frame.
*
* \param [IN] rxError System maximum timing error of the receiver. In milliseconds
* The receiver will turn on in a [-rxError : +rxError] ms
* interval around RxOffset
*
* \param [OUT]rxConfigParams Returns updated WindowTimeout and WindowOffset fields.
*/
void RegionIN865ComputeRxWindowParameters( int8_t datarate, uint8_t minRxSymbols, uint32_t rxError, RxConfigParams_t *rxConfigParams );
/*!
* \brief Configuration of the RX windows.
*
* \param [IN] rxConfig Pointer to the function parameters.
*
* \param [OUT] datarate The datarate index which was set.
*
* \retval Returns true, if the configuration was applied successfully.
*/
bool RegionIN865RxConfig( RxConfigParams_t* rxConfig, int8_t* datarate );
/*!
* \brief TX configuration.
*
* \param [IN] txConfig Pointer to the function parameters.
*
* \param [OUT] txPower The tx power index which was set.
*
* \param [OUT] txTimeOnAir The time-on-air of the frame.
*
* \retval Returns true, if the configuration was applied successfully.
*/
bool RegionIN865TxConfig( TxConfigParams_t* txConfig, int8_t* txPower, TimerTime_t* txTimeOnAir );
/*!
* \brief The function processes a Link ADR Request.
*
* \param [IN] linkAdrReq Pointer to the function parameters.
*
* \retval Returns the status of the operation, according to the LoRaMAC specification.
*/
uint8_t RegionIN865LinkAdrReq( LinkAdrReqParams_t* linkAdrReq, int8_t* drOut, int8_t* txPowOut, uint8_t* nbRepOut, uint8_t* nbBytesParsed );
/*!
* \brief The function processes a RX Parameter Setup Request.
*
* \param [IN] rxParamSetupReq Pointer to the function parameters.
*
* \retval Returns the status of the operation, according to the LoRaMAC specification.
*/
uint8_t RegionIN865RxParamSetupReq( RxParamSetupReqParams_t* rxParamSetupReq );
/*!
* \brief The function processes a Channel Request.
*
* \param [IN] newChannelReq Pointer to the function parameters.
*
* \retval Returns the status of the operation, according to the LoRaMAC specification.
*/
uint8_t RegionIN865NewChannelReq( NewChannelReqParams_t* newChannelReq );
/*!
* \brief The function processes a TX ParamSetup Request.
*
* \param [IN] txParamSetupReq Pointer to the function parameters.
*
* \retval Returns the status of the operation, according to the LoRaMAC specification.
* Returns -1, if the functionality is not implemented. In this case, the end node
* shall not process the command.
*/
int8_t RegionIN865TxParamSetupReq( TxParamSetupReqParams_t* txParamSetupReq );
/*!
* \brief The function processes a DlChannel Request.
*
* \param [IN] dlChannelReq Pointer to the function parameters.
*
* \retval Returns the status of the operation, according to the LoRaMAC specification.
*/
uint8_t RegionIN865DlChannelReq( DlChannelReqParams_t* dlChannelReq );
/*!
* \brief Alternates the datarate of the channel for the join request.
*
* \param [IN] currentDr Current datarate.
*
* \retval Datarate to apply.
*/
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
*
* \param [OUT] channel Next channel to use for TX.
*
* \param [OUT] time Time to wait for the next transmission according to the duty
* cycle.
*
* \param [OUT] aggregatedTimeOff Updates the aggregated time off.
*
* \retval Function status [1: OK, 0: Unable to find a channel on the current datarate]
*/
LoRaMacStatus_t RegionIN865NextChannel( NextChanParams_t* nextChanParams, uint8_t* channel, TimerTime_t* time, TimerTime_t* aggregatedTimeOff );
/*!
* \brief Adds a channel.
*
* \param [IN] channelAdd Pointer to the function parameters.
*
* \retval Status of the operation.
*/
LoRaMacStatus_t RegionIN865ChannelAdd( ChannelAddParams_t* channelAdd );
/*!
* \brief Removes a channel.
*
* \param [IN] channelRemove Pointer to the function parameters.
*
* \retval Returns true, if the channel was removed successfully.
*/
bool RegionIN865ChannelsRemove( ChannelRemoveParams_t* channelRemove );
/*!
* \brief Sets the radio into continuous wave mode.
*
* \param [IN] continuousWave Pointer to the function parameters.
*/
void RegionIN865SetContinuousWave( ContinuousWaveParams_t* continuousWave );
/*!
* \brief Computes new datarate according to the given offset
*
* \param [IN] downlinkDwellTime Downlink dwell time configuration. 0: No limit, 1: 400ms
*
* \param [IN] dr Current datarate
*
* \param [IN] drOffset Offset to be applied
*
* \retval newDr Computed datarate.
*/
uint8_t RegionIN865ApplyDrOffset( uint8_t downlinkDwellTime, int8_t dr, int8_t drOffset );
/*!
* \brief Sets the radio into beacon reception mode
*
* \param [IN] rxBeaconSetup Pointer to the function parameters
*/
void RegionIN865RxBeaconSetup( RxBeaconSetup_t* rxBeaconSetup, uint8_t* outDr );
/*! \} defgroup REGIONIN865 */
#endif // __REGION_IN865_H__

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,521 @@
/*!
* \file RegionKR920.h
*
* \brief Region definition for KR920
*
* \copyright Revised BSD License, see section \ref LICENSE.
*
* \code
* ______ _
* / _____) _ | |
* ( (____ _____ ____ _| |_ _____ ____| |__
* \____ \| ___ | (_ _) ___ |/ ___) _ \
* _____) ) ____| | | || |_| ____( (___| | | |
* (______/|_____)_|_|_| \__)_____)\____)_| |_|
* (C)2013-2017 Semtech
*
* ___ _____ _ ___ _ _____ ___ ___ ___ ___
* / __|_ _/_\ / __| |/ / __/ _ \| _ \/ __| __|
* \__ \ | |/ _ \ (__| ' <| _| (_) | / (__| _|
* |___/ |_/_/ \_\___|_|\_\_| \___/|_|_\\___|___|
* embedded.connectivity.solutions===============
*
* \endcode
*
* \author Miguel Luis ( Semtech )
*
* \author Gregory Cristian ( Semtech )
*
* \author Daniel Jaeckle ( STACKFORCE )
*
* \author Johannes Bruder ( STACKFORCE )
*
* \defgroup REGIONKR920 Region KR920
* Implementation according to LoRaWAN Specification v1.0.2.
* \{
*/
#ifndef __REGION_KR920_H__
#define __REGION_KR920_H__
#include "region/Region.h"
/*!
* LoRaMac maximum number of channels
*/
#define KR920_MAX_NB_CHANNELS 16
/*!
* Number of default channels
*/
#define KR920_NUMB_DEFAULT_CHANNELS 3
/*!
* Number of channels to apply for the CF list
*/
#define KR920_NUMB_CHANNELS_CF_LIST 5
/*!
* Minimal datarate that can be used by the node
*/
#define KR920_TX_MIN_DATARATE DR_0
/*!
* Maximal datarate that can be used by the node
*/
#define KR920_TX_MAX_DATARATE DR_5
/*!
* Minimal datarate that can be used by the node
*/
#define KR920_RX_MIN_DATARATE DR_0
/*!
* Maximal datarate that can be used by the node
*/
#define KR920_RX_MAX_DATARATE DR_5
/*!
* Default datarate used by the node
*/
#define KR920_DEFAULT_DATARATE DR_0
/*!
* Minimal Rx1 receive datarate offset
*/
#define KR920_MIN_RX1_DR_OFFSET 0
/*!
* Maximal Rx1 receive datarate offset
*/
#define KR920_MAX_RX1_DR_OFFSET 5
/*!
* Default Rx1 receive datarate offset
*/
#define KR920_DEFAULT_RX1_DR_OFFSET 0
/*!
* Minimal Tx output power that can be used by the node
*/
#define KR920_MIN_TX_POWER TX_POWER_7
/*!
* Maximal Tx output power that can be used by the node
*/
#define KR920_MAX_TX_POWER TX_POWER_0
/*!
* Default Tx output power used by the node
*/
#define KR920_DEFAULT_TX_POWER TX_POWER_0
/*!
* Default Max EIRP for frequency 920.9 MHz - 921.9 MHz
*/
#define KR920_DEFAULT_MAX_EIRP_LOW 10.0f
/*!
* Default Max EIRP for frequency 922.1 MHz - 923.3 MHz
*/
#define KR920_DEFAULT_MAX_EIRP_HIGH 14.0f
/*!
* Default antenna gain
*/
#define KR920_DEFAULT_ANTENNA_GAIN 2.15f
/*!
* ADR Ack limit
*/
#define KR920_ADR_ACK_LIMIT 64
/*!
* ADR Ack delay
*/
#define KR920_ADR_ACK_DELAY 32
/*!
* Enabled or disabled the duty cycle
*/
#define KR920_DUTY_CYCLE_ENABLED 0
/*!
* Maximum RX window duration
*/
#define KR920_MAX_RX_WINDOW 4000
/*!
* Receive delay 1
*/
#define KR920_RECEIVE_DELAY1 1000
/*!
* Receive delay 2
*/
#define KR920_RECEIVE_DELAY2 2000
/*!
* Join accept delay 1
*/
#define KR920_JOIN_ACCEPT_DELAY1 5000
/*!
* Join accept delay 2
*/
#define KR920_JOIN_ACCEPT_DELAY2 6000
/*!
* Maximum frame counter gap
*/
#define KR920_MAX_FCNT_GAP 16384
/*!
* Ack timeout
*/
#define KR920_ACKTIMEOUT 2000
/*!
* Random ack timeout limits
*/
#define KR920_ACK_TIMEOUT_RND 1000
#if ( KR920_DEFAULT_DATARATE > DR_5 )
#error "A default DR higher than DR_5 may lead to connectivity loss."
#endif
/*!
* Second reception window channel frequency definition.
*/
#define KR920_RX_WND_2_FREQ 921900000
/*!
* Second reception window channel datarate definition.
*/
#define KR920_RX_WND_2_DR DR_0
/*
* CLASS B
*/
/*!
* Beacon frequency
*/
#define KR920_BEACON_CHANNEL_FREQ 923100000
/*!
* Payload size of a beacon frame
*/
#define KR920_BEACON_SIZE 17
/*!
* Size of RFU 1 field
*/
#define KR920_RFU1_SIZE 2
/*!
* Size of RFU 2 field
*/
#define KR920_RFU2_SIZE 0
/*!
* Datarate of the beacon channel
*/
#define KR920_BEACON_CHANNEL_DR DR_3
/*!
* Bandwith of the beacon channel
*/
#define KR920_BEACON_CHANNEL_BW 0
/*!
* Ping slot channel datarate
*/
#define KR920_PING_SLOT_CHANNEL_DR DR_3
/*!
* Maximum number of bands
*/
#define KR920_MAX_NB_BANDS 1
/*!
* Band 0 definition
* { DutyCycle, TxMaxPower, LastJoinTxDoneTime, LastTxDoneTime, TimeOff }
*/
#define KR920_BAND0 { 1 , KR920_MAX_TX_POWER, 0, 0, 0 } // 100.0 %
/*!
* LoRaMac default channel 1
* Channel = { Frequency [Hz], RX1 Frequency [Hz], { ( ( DrMax << 4 ) | DrMin ) }, Band }
*/
#define KR920_LC1 { 922100000, 0, { ( ( DR_5 << 4 ) | DR_0 ) }, 0 }
/*!
* LoRaMac default channel 2
* Channel = { Frequency [Hz], RX1 Frequency [Hz], { ( ( DrMax << 4 ) | DrMin ) }, Band }
*/
#define KR920_LC2 { 922300000, 0, { ( ( DR_5 << 4 ) | DR_0 ) }, 0 }
/*!
* LoRaMac default channel 3
* Channel = { Frequency [Hz], RX1 Frequency [Hz], { ( ( DrMax << 4 ) | DrMin ) }, Band }
*/
#define KR920_LC3 { 922500000, 0, { ( ( DR_5 << 4 ) | DR_0 ) }, 0 }
/*!
* LoRaMac channels which are allowed for the join procedure
*/
#define KR920_JOIN_CHANNELS ( uint16_t )( LC( 1 ) | LC( 2 ) | LC( 3 ) )
/*!
* RSSI threshold for a free channel [dBm]
*/
#define KR920_RSSI_FREE_TH -65
/*!
* Specifies the time the node performs a carrier sense
*/
#define KR920_CARRIER_SENSE_TIME 6
/*!
* Data rates table definition
*/
static const uint8_t DataratesKR920[] = { 12, 11, 10, 9, 8, 7 };
/*!
* Bandwidths table definition in Hz
*/
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.
*/
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.
*
* \param [IN] getPhy Pointer to the function parameters.
*
* \retval Returns a structure containing the PHY parameter.
*/
PhyParam_t RegionKR920GetPhyParam( GetPhyParams_t* getPhy );
/*!
* \brief Updates the last TX done parameters of the current channel.
*
* \param [IN] txDone Pointer to the function parameters.
*/
void RegionKR920SetBandTxDone( SetBandTxDoneParams_t* txDone );
/*!
* \brief Initializes the channels masks and the channels.
*
* \param [IN] type Sets the initialization type.
*/
void RegionKR920InitDefaults( InitDefaultsParams_t* params );
/*!
* \brief Returns a pointer to the internal context and its size.
*
* \param [OUT] params Pointer to the function parameters.
*
* \retval Points to a structure where the module store its non-volatile context.
*/
void* RegionKR920GetNvmCtx( GetNvmCtxParams_t* params );
/*!
* \brief Verifies a parameter.
*
* \param [IN] verify Pointer to the function parameters.
*
* \param [IN] type Sets the initialization type.
*
* \retval Returns true, if the parameter is valid.
*/
bool RegionKR920Verify( VerifyParams_t* verify, PhyAttribute_t phyAttribute );
/*!
* \brief The function parses the input buffer and sets up the channels of the
* CF list.
*
* \param [IN] applyCFList Pointer to the function parameters.
*/
void RegionKR920ApplyCFList( ApplyCFListParams_t* applyCFList );
/*!
* \brief Sets a channels mask.
*
* \param [IN] chanMaskSet Pointer to the function parameters.
*
* \retval Returns true, if the channels mask could be set.
*/
bool RegionKR920ChanMaskSet( ChanMaskSetParams_t* chanMaskSet );
/*!
* Computes the Rx window timeout and offset.
*
* \param [IN] datarate Rx window datarate index to be used
*
* \param [IN] minRxSymbols Minimum required number of symbols to detect an Rx frame.
*
* \param [IN] rxError System maximum timing error of the receiver. In milliseconds
* The receiver will turn on in a [-rxError : +rxError] ms
* interval around RxOffset
*
* \param [OUT]rxConfigParams Returns updated WindowTimeout and WindowOffset fields.
*/
void RegionKR920ComputeRxWindowParameters( int8_t datarate, uint8_t minRxSymbols, uint32_t rxError, RxConfigParams_t *rxConfigParams );
/*!
* \brief Configuration of the RX windows.
*
* \param [IN] rxConfig Pointer to the function parameters.
*
* \param [OUT] datarate The datarate index which was set.
*
* \retval Returns true, if the configuration was applied successfully.
*/
bool RegionKR920RxConfig( RxConfigParams_t* rxConfig, int8_t* datarate );
/*!
* \brief TX configuration.
*
* \param [IN] txConfig Pointer to the function parameters.
*
* \param [OUT] txPower The tx power index which was set.
*
* \param [OUT] txTimeOnAir The time-on-air of the frame.
*
* \retval Returns true, if the configuration was applied successfully.
*/
bool RegionKR920TxConfig( TxConfigParams_t* txConfig, int8_t* txPower, TimerTime_t* txTimeOnAir );
/*!
* \brief The function processes a Link ADR Request.
*
* \param [IN] linkAdrReq Pointer to the function parameters.
*
* \retval Returns the status of the operation, according to the LoRaMAC specification.
*/
uint8_t RegionKR920LinkAdrReq( LinkAdrReqParams_t* linkAdrReq, int8_t* drOut, int8_t* txPowOut, uint8_t* nbRepOut, uint8_t* nbBytesParsed );
/*!
* \brief The function processes a RX Parameter Setup Request.
*
* \param [IN] rxParamSetupReq Pointer to the function parameters.
*
* \retval Returns the status of the operation, according to the LoRaMAC specification.
*/
uint8_t RegionKR920RxParamSetupReq( RxParamSetupReqParams_t* rxParamSetupReq );
/*!
* \brief The function processes a Channel Request.
*
* \param [IN] newChannelReq Pointer to the function parameters.
*
* \retval Returns the status of the operation, according to the LoRaMAC specification.
*/
uint8_t RegionKR920NewChannelReq( NewChannelReqParams_t* newChannelReq );
/*!
* \brief The function processes a TX ParamSetup Request.
*
* \param [IN] txParamSetupReq Pointer to the function parameters.
*
* \retval Returns the status of the operation, according to the LoRaMAC specification.
* Returns -1, if the functionality is not implemented. In this case, the end node
* shall not process the command.
*/
int8_t RegionKR920TxParamSetupReq( TxParamSetupReqParams_t* txParamSetupReq );
/*!
* \brief The function processes a DlChannel Request.
*
* \param [IN] dlChannelReq Pointer to the function parameters.
*
* \retval Returns the status of the operation, according to the LoRaMAC specification.
*/
uint8_t RegionKR920DlChannelReq( DlChannelReqParams_t* dlChannelReq );
/*!
* \brief Alternates the datarate of the channel for the join request.
*
* \param [IN] currentDr current datarate.
*
* \retval Datarate to apply.
*/
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
*
* \param [OUT] channel Next channel to use for TX.
*
* \param [OUT] time Time to wait for the next transmission according to the duty
* cycle.
*
* \param [OUT] aggregatedTimeOff Updates the aggregated time off.
*
* \retval Function status [1: OK, 0: Unable to find a channel on the current datarate]
*/
LoRaMacStatus_t RegionKR920NextChannel( NextChanParams_t* nextChanParams, uint8_t* channel, TimerTime_t* time, TimerTime_t* aggregatedTimeOff );
/*!
* \brief Adds a channel.
*
* \param [IN] channelAdd Pointer to the function parameters.
*
* \retval Status of the operation.
*/
LoRaMacStatus_t RegionKR920ChannelAdd( ChannelAddParams_t* channelAdd );
/*!
* \brief Removes a channel.
*
* \param [IN] channelRemove Pointer to the function parameters.
*
* \retval Returns true, if the channel was removed successfully.
*/
bool RegionKR920ChannelsRemove( ChannelRemoveParams_t* channelRemove );
/*!
* \brief Sets the radio into continuous wave mode.
*
* \param [IN] continuousWave Pointer to the function parameters.
*/
void RegionKR920SetContinuousWave( ContinuousWaveParams_t* continuousWave );
/*!
* \brief Computes new datarate according to the given offset
*
* \param [IN] downlinkDwellTime Downlink dwell time configuration. 0: No limit, 1: 400ms
*
* \param [IN] dr Current datarate
*
* \param [IN] drOffset Offset to be applied
*
* \retval newDr Computed datarate.
*/
uint8_t RegionKR920ApplyDrOffset( uint8_t downlinkDwellTime, int8_t dr, int8_t drOffset );
/*!
* \brief Sets the radio into beacon reception mode
*
* \param [IN] rxBeaconSetup Pointer to the function parameters
*/
void RegionKR920RxBeaconSetup( RxBeaconSetup_t* rxBeaconSetup, uint8_t* outDr );
/*! \} defgroup REGIONKR920 */
#endif // __REGION_KR920_H__

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,500 @@
/*!
* \file RegionRU864.h
*
* \brief Region definition for RU864
*
* \copyright Revised BSD License, see section \ref LICENSE.
*
* \code
* ______ _
* / _____) _ | |
* ( (____ _____ ____ _| |_ _____ ____| |__
* \____ \| ___ | (_ _) ___ |/ ___) _ \
* _____) ) ____| | | || |_| ____( (___| | | |
* (______/|_____)_|_|_| \__)_____)\____)_| |_|
* (C)2013-2017 Semtech
*
* ___ _____ _ ___ _ _____ ___ ___ ___ ___
* / __|_ _/_\ / __| |/ / __/ _ \| _ \/ __| __|
* \__ \ | |/ _ \ (__| ' <| _| (_) | / (__| _|
* |___/ |_/_/ \_\___|_|\_\_| \___/|_|_\\___|___|
* embedded.connectivity.solutions===============
*
* \endcode
*
* \author Miguel Luis ( Semtech )
*
* \author Gregory Cristian ( Semtech )
*
* \author Daniel Jaeckle ( STACKFORCE )
*
* \defgroup REGIONRU864 Region RU864
* Implementation according to LoRaWAN Specification v1.0.2.
* \{
*/
#ifndef __REGION_RU864_H__
#define __REGION_RU864_H__
#include "LoRaMac.h"
/*!
* LoRaMac maximum number of channels
*/
#define RU864_MAX_NB_CHANNELS 8
/*!
* Number of default channels
*/
#define RU864_NUMB_DEFAULT_CHANNELS 2
/*!
* Number of channels to apply for the CF list
*/
#define RU864_NUMB_CHANNELS_CF_LIST 5
/*!
* Minimal datarate that can be used by the node
*/
#define RU864_TX_MIN_DATARATE DR_0
/*!
* Maximal datarate that can be used by the node
*/
#define RU864_TX_MAX_DATARATE DR_7
/*!
* Minimal datarate that can be used by the node
*/
#define RU864_RX_MIN_DATARATE DR_0
/*!
* Maximal datarate that can be used by the node
*/
#define RU864_RX_MAX_DATARATE DR_7
/*!
* Default datarate used by the node
*/
#define RU864_DEFAULT_DATARATE DR_0
/*!
* Minimal Rx1 receive datarate offset
*/
#define RU864_MIN_RX1_DR_OFFSET 0
/*!
* Maximal Rx1 receive datarate offset
*/
#define RU864_MAX_RX1_DR_OFFSET 5
/*!
* Default Rx1 receive datarate offset
*/
#define RU864_DEFAULT_RX1_DR_OFFSET 0
/*!
* Minimal Tx output power that can be used by the node
*/
#define RU864_MIN_TX_POWER TX_POWER_7
/*!
* Maximal Tx output power that can be used by the node
*/
#define RU864_MAX_TX_POWER TX_POWER_0
/*!
* Default Tx output power used by the node
*/
#define RU864_DEFAULT_TX_POWER TX_POWER_0
/*!
* Default Max EIRP
*/
#define RU864_DEFAULT_MAX_EIRP 16.0f
/*!
* Default antenna gain
*/
#define RU864_DEFAULT_ANTENNA_GAIN 2.15f
/*!
* ADR Ack limit
*/
#define RU864_ADR_ACK_LIMIT 64
/*!
* ADR Ack delay
*/
#define RU864_ADR_ACK_DELAY 32
/*!
* Enabled or disabled the duty cycle
*/
#define RU864_DUTY_CYCLE_ENABLED 1
/*!
* Maximum RX window duration
*/
#define RU864_MAX_RX_WINDOW 3000 //TODO
/*!
* Receive delay 1
*/
#define RU864_RECEIVE_DELAY1 1000
/*!
* Receive delay 2
*/
#define RU864_RECEIVE_DELAY2 2000
/*!
* Join accept delay 1
*/
#define RU864_JOIN_ACCEPT_DELAY1 5000
/*!
* Join accept delay 2
*/
#define RU864_JOIN_ACCEPT_DELAY2 6000
/*!
* Maximum frame counter gap
*/
#define RU864_MAX_FCNT_GAP 16384
/*!
* Ack timeout
*/
#define RU864_ACKTIMEOUT 2000
/*!
* Random ack timeout limits
*/
#define RU864_ACK_TIMEOUT_RND 1000
#if ( RU864_DEFAULT_DATARATE > DR_5 )
#error "A default DR higher than DR_5 may lead to connectivity loss."
#endif
/*!
* Second reception window channel frequency definition.
*/
#define RU864_RX_WND_2_FREQ 869100000
/*!
* Second reception window channel datarate definition.
*/
#define RU864_RX_WND_2_DR DR_0
/*
* CLASS B
*/
/*!
* Beacon frequency
*/
#define RU864_BEACON_CHANNEL_FREQ 869100000
/*!
* Payload size of a beacon frame
*/
#define RU864_BEACON_SIZE 17
/*!
* Size of RFU 1 field
*/
#define RU864_RFU1_SIZE 2
/*!
* Size of RFU 2 field
*/
#define RU864_RFU2_SIZE 0
/*!
* Datarate of the beacon channel
*/
#define RU864_BEACON_CHANNEL_DR DR_3
/*!
* Bandwith of the beacon channel (Index of BandwidthsRU864[])
*/
#define RU864_BEACON_CHANNEL_BW 0
/*!
* Ping slot channel datarate
*/
#define RU864_PING_SLOT_CHANNEL_DR DR_3
/*!
* Maximum number of bands
*/
#define RU864_MAX_NB_BANDS 1
/*!
* Band 0 definition
* { DutyCycle, TxMaxPower, LastJoinTxDoneTime, LastTxDoneTime, TimeOff }
*/
#define RU864_BAND0 { 100 , RU864_MAX_TX_POWER, 0, 0, 0 } // 1.0 %
/*!
* LoRaMac default channel 1
* Channel = { Frequency [Hz], RX1 Frequency [Hz], { ( ( DrMax << 4 ) | DrMin ) }, Band }
*/
#define RU864_LC1 { 868900000, 0, { ( ( DR_5 << 4 ) | DR_0 ) }, 0 }
/*!
* LoRaMac default channel 2
* Channel = { Frequency [Hz], RX1 Frequency [Hz], { ( ( DrMax << 4 ) | DrMin ) }, Band }
*/
#define RU864_LC2 { 869100000, 0, { ( ( DR_5 << 4 ) | DR_0 ) }, 0 }
/*!
* LoRaMac channels which are allowed for the join procedure
*/
#define RU864_JOIN_CHANNELS ( uint16_t )( LC( 1 ) | LC( 2 ) )
/*!
* Data rates table definition
*/
static const uint8_t DataratesRU864[] = { 12, 11, 10, 9, 8, 7, 7, 50 };
/*!
* Bandwidths table definition in Hz
*/
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.
*/
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.
*
* \param [IN] getPhy Pointer to the function parameters.
*
* \retval Returns a structure containing the PHY parameter.
*/
PhyParam_t RegionRU864GetPhyParam( GetPhyParams_t* getPhy );
/*!
* \brief Updates the last TX done parameters of the current channel.
*
* \param [IN] txDone Pointer to the function parameters.
*/
void RegionRU864SetBandTxDone( SetBandTxDoneParams_t* txDone );
/*!
* \brief Initializes the channels masks and the channels.
*
* \param [IN] type Sets the initialization type.
*/
void RegionRU864InitDefaults( InitDefaultsParams_t* params );
/*!
* \brief Returns a pointer to the internal context and its size.
*
* \param [OUT] params Pointer to the function parameters.
*
* \retval Points to a structure where the module store its non-volatile context.
*/
void* RegionRU864GetNvmCtx( GetNvmCtxParams_t* params );
/*!
* \brief Verifies a parameter.
*
* \param [IN] verify Pointer to the function parameters.
*
* \param [IN] type Sets the initialization type.
*
* \retval Returns true, if the parameter is valid.
*/
bool RegionRU864Verify( VerifyParams_t* verify, PhyAttribute_t phyAttribute );
/*!
* \brief The function parses the input buffer and sets up the channels of the
* CF list.
*
* \param [IN] applyCFList Pointer to the function parameters.
*/
void RegionRU864ApplyCFList( ApplyCFListParams_t* applyCFList );
/*!
* \brief Sets a channels mask.
*
* \param [IN] chanMaskSet Pointer to the function parameters.
*
* \retval Returns true, if the channels mask could be set.
*/
bool RegionRU864ChanMaskSet( ChanMaskSetParams_t* chanMaskSet );
/*!
* Computes the Rx window timeout and offset.
*
* \param [IN] datarate Rx window datarate index to be used
*
* \param [IN] minRxSymbols Minimum required number of symbols to detect an Rx frame.
*
* \param [IN] rxError System maximum timing error of the receiver. In milliseconds
* The receiver will turn on in a [-rxError : +rxError] ms
* interval around RxOffset
*
* \param [OUT]rxConfigParams Returns updated WindowTimeout and WindowOffset fields.
*/
void RegionRU864ComputeRxWindowParameters( int8_t datarate, uint8_t minRxSymbols, uint32_t rxError, RxConfigParams_t *rxConfigParams );
/*!
* \brief Configuration of the RX windows.
*
* \param [IN] rxConfig Pointer to the function parameters.
*
* \param [OUT] datarate The datarate index which was set.
*
* \retval Returns true, if the configuration was applied successfully.
*/
bool RegionRU864RxConfig( RxConfigParams_t* rxConfig, int8_t* datarate );
/*!
* \brief TX configuration.
*
* \param [IN] txConfig Pointer to the function parameters.
*
* \param [OUT] txPower The tx power index which was set.
*
* \param [OUT] txTimeOnAir The time-on-air of the frame.
*
* \retval Returns true, if the configuration was applied successfully.
*/
bool RegionRU864TxConfig( TxConfigParams_t* txConfig, int8_t* txPower, TimerTime_t* txTimeOnAir );
/*!
* \brief The function processes a Link ADR Request.
*
* \param [IN] linkAdrReq Pointer to the function parameters.
*
* \retval Returns the status of the operation, according to the LoRaMAC specification.
*/
uint8_t RegionRU864LinkAdrReq( LinkAdrReqParams_t* linkAdrReq, int8_t* drOut, int8_t* txPowOut, uint8_t* nbRepOut, uint8_t* nbBytesParsed );
/*!
* \brief The function processes a RX Parameter Setup Request.
*
* \param [IN] rxParamSetupReq Pointer to the function parameters.
*
* \retval Returns the status of the operation, according to the LoRaMAC specification.
*/
uint8_t RegionRU864RxParamSetupReq( RxParamSetupReqParams_t* rxParamSetupReq );
/*!
* \brief The function processes a Channel Request.
*
* \param [IN] newChannelReq Pointer to the function parameters.
*
* \retval Returns the status of the operation, according to the LoRaMAC specification.
*/
uint8_t RegionRU864NewChannelReq( NewChannelReqParams_t* newChannelReq );
/*!
* \brief The function processes a TX ParamSetup Request.
*
* \param [IN] txParamSetupReq Pointer to the function parameters.
*
* \retval Returns the status of the operation, according to the LoRaMAC specification.
* Returns -1, if the functionality is not implemented. In this case, the end node
* shall not process the command.
*/
int8_t RegionRU864TxParamSetupReq( TxParamSetupReqParams_t* txParamSetupReq );
/*!
* \brief The function processes a DlChannel Request.
*
* \param [IN] dlChannelReq Pointer to the function parameters.
*
* \retval Returns the status of the operation, according to the LoRaMAC specification.
*/
uint8_t RegionRU864DlChannelReq( DlChannelReqParams_t* dlChannelReq );
/*!
* \brief Alternates the datarate of the channel for the join request.
*
* \param [IN] currentDr Current datarate.
*
* \retval Datarate to apply.
*/
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
*
* \param [OUT] channel Next channel to use for TX.
*
* \param [OUT] time Time to wait for the next transmission according to the duty
* cycle.
*
* \param [OUT] aggregatedTimeOff Updates the aggregated time off.
*
* \retval Function status [1: OK, 0: Unable to find a channel on the current datarate]
*/
LoRaMacStatus_t RegionRU864NextChannel( NextChanParams_t* nextChanParams, uint8_t* channel, TimerTime_t* time, TimerTime_t* aggregatedTimeOff );
/*!
* \brief Adds a channel.
*
* \param [IN] channelAdd Pointer to the function parameters.
*
* \retval Status of the operation.
*/
LoRaMacStatus_t RegionRU864ChannelAdd( ChannelAddParams_t* channelAdd );
/*!
* \brief Removes a channel.
*
* \param [IN] channelRemove Pointer to the function parameters.
*
* \retval Returns true, if the channel was removed successfully.
*/
bool RegionRU864ChannelsRemove( ChannelRemoveParams_t* channelRemove );
/*!
* \brief Sets the radio into continuous wave mode.
*
* \param [IN] continuousWave Pointer to the function parameters.
*/
void RegionRU864SetContinuousWave( ContinuousWaveParams_t* continuousWave );
/*!
* \brief Computes new datarate according to the given offset
*
* \param [IN] downlinkDwellTime Downlink dwell time configuration. 0: No limit, 1: 400ms
*
* \param [IN] dr Current datarate
*
* \param [IN] drOffset Offset to be applied
*
* \retval newDr Computed datarate.
*/
uint8_t RegionRU864ApplyDrOffset( uint8_t downlinkDwellTime, int8_t dr, int8_t drOffset );
/*!
* \brief Sets the radio into beacon reception mode
*
* \param [IN] rxBeaconSetup Pointer to the function parameters
*/
void RegionRU864RxBeaconSetup( RxBeaconSetup_t* rxBeaconSetup, uint8_t* outDr );
/*! \} defgroup REGIONRU864 */
#endif // __REGION_RU864_H__

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,506 @@
/*!
* \file RegionUS915.h
*
* \brief Region definition for US915
*
* \copyright Revised BSD License, see section \ref LICENSE.
*
* \code
* ______ _
* / _____) _ | |
* ( (____ _____ ____ _| |_ _____ ____| |__
* \____ \| ___ | (_ _) ___ |/ ___) _ \
* _____) ) ____| | | || |_| ____( (___| | | |
* (______/|_____)_|_|_| \__)_____)\____)_| |_|
* (C)2013-2017 Semtech
*
* ___ _____ _ ___ _ _____ ___ ___ ___ ___
* / __|_ _/_\ / __| |/ / __/ _ \| _ \/ __| __|
* \__ \ | |/ _ \ (__| ' <| _| (_) | / (__| _|
* |___/ |_/_/ \_\___|_|\_\_| \___/|_|_\\___|___|
* embedded.connectivity.solutions===============
*
* \endcode
*
* \author Miguel Luis ( Semtech )
*
* \author Gregory Cristian ( Semtech )
*
* \author Daniel Jaeckle ( STACKFORCE )
*
* \author Johannes Bruder ( STACKFORCE )
*
* \defgroup REGIONUS915 Region US915
* Implementation according to LoRaWAN Specification v1.0.2.
* \{
*/
#ifndef __REGION_US915_H__
#define __REGION_US915_H__
#include "region/Region.h"
/*!
* LoRaMac maximum number of channels
*/
#define US915_MAX_NB_CHANNELS 72
/*!
* Minimal datarate that can be used by the node
*/
#define US915_TX_MIN_DATARATE DR_0
/*!
* Maximal datarate that can be used by the node
*/
#define US915_TX_MAX_DATARATE DR_4
/*!
* Minimal datarate that can be used by the node
*/
#define US915_RX_MIN_DATARATE DR_8
/*!
* Maximal datarate that can be used by the node
*/
#define US915_RX_MAX_DATARATE DR_13
/*!
* Default datarate used by the node
*/
#define US915_DEFAULT_DATARATE DR_0
/*!
* Minimal Rx1 receive datarate offset
*/
#define US915_MIN_RX1_DR_OFFSET 0
/*!
* Maximal Rx1 receive datarate offset
*/
#define US915_MAX_RX1_DR_OFFSET 3
/*!
* Default Rx1 receive datarate offset
*/
#define US915_DEFAULT_RX1_DR_OFFSET 0
/*!
* Minimal Tx output power that can be used by the node
*/
#if (defined(CERTIF_LORAWAN_VERSION) &&(CERTIF_LORAWAN_VERSION == 103))
#define US915_MIN_TX_POWER TX_POWER_14
#else
#define US915_MIN_TX_POWER TX_POWER_10
#endif
/*!
* Maximal Tx output power that can be used by the node
*/
#define US915_MAX_TX_POWER TX_POWER_0
/*!
* Default Tx output power used by the node
*/
#define US915_DEFAULT_TX_POWER TX_POWER_0
/*!
* Default Max ERP
*/
#define US915_DEFAULT_MAX_ERP 30.0f
/*!
* ADR Ack limit
*/
#define US915_ADR_ACK_LIMIT 64
/*!
* ADR Ack delay
*/
#define US915_ADR_ACK_DELAY 32
/*!
* Enabled or disabled the duty cycle
*/
#define US915_DUTY_CYCLE_ENABLED 0
/*!
* Maximum RX window duration
*/
#define US915_MAX_RX_WINDOW 3000
/*!
* Receive delay 1
*/
#define US915_RECEIVE_DELAY1 1000
/*!
* Receive delay 2
*/
#define US915_RECEIVE_DELAY2 2000
/*!
* Join accept delay 1
*/
#define US915_JOIN_ACCEPT_DELAY1 5000
/*!
* Join accept delay 2
*/
#define US915_JOIN_ACCEPT_DELAY2 6000
/*!
* Maximum frame counter gap
*/
#define US915_MAX_FCNT_GAP 16384
/*!
* Ack timeout
*/
#define US915_ACKTIMEOUT 2000
/*!
* Random ack timeout limits
*/
#define US915_ACK_TIMEOUT_RND 1000
/*!
* Second reception window channel frequency definition.
*/
#define US915_RX_WND_2_FREQ 923300000
/*!
* Second reception window channel datarate definition.
*/
#define US915_RX_WND_2_DR DR_8
/*
* CLASS B
*/
/*!
* Beacon frequency
*/
#define US915_BEACON_CHANNEL_FREQ 923300000
/*!
* Beacon frequency channel stepwidth
*/
#define US915_BEACON_CHANNEL_STEPWIDTH 600000
/*!
* Number of possible beacon channels
*/
#define US915_BEACON_NB_CHANNELS 8
/*!
* Payload size of a beacon frame
*/
#define US915_BEACON_SIZE 23
/*!
* Size of RFU 1 field
*/
#define US915_RFU1_SIZE 5
/*!
* Size of RFU 2 field
*/
#define US915_RFU2_SIZE 3
/*!
* Datarate of the beacon channel
*/
#define US915_BEACON_CHANNEL_DR DR_8
/*!
* Bandwith of the beacon channel
*/
#define US915_BEACON_CHANNEL_BW 2
/*!
* Ping slot channel datarate
*/
#define US915_PING_SLOT_CHANNEL_DR DR_8
/*!
* LoRaMac maximum number of bands
*/
#define US915_MAX_NB_BANDS 1
/*!
* Band 0 definition
* { DutyCycle, TxMaxPower, LastJoinTxDoneTime, LastTxDoneTime, TimeOff }
*/
#define US915_BAND0 { 1, US915_MAX_TX_POWER, 0, 0, 0 } // 100.0 %
/*!
* Defines the first channel for RX window 1 for US band
*/
#define US915_FIRST_RX1_CHANNEL ( (uint32_t) 923300000 )
/*!
* Defines the last channel for RX window 1 for US band
*/
#define US915_LAST_RX1_CHANNEL ( (uint32_t) 927500000 )
/*!
* Defines the step width of the channels for RX window 1
*/
#define US915_STEPWIDTH_RX1_CHANNEL ( (uint32_t) 600000 )
/*!
* Data rates table definition
*/
static const uint8_t DataratesUS915[] = { 10, 9, 8, 7, 8, 0, 0, 0, 12, 11, 10, 9, 8, 7, 0, 0 };
/*!
* Bandwidths table definition in Hz
*/
static const uint32_t BandwidthsUS915[] = { 125000, 125000, 125000, 125000, 500000, 0, 0, 0, 500000, 500000, 500000, 500000, 500000, 500000, 0, 0 };
/*!
* Up/Down link data rates offset definition
*/
static const int8_t DatarateOffsetsUS915[5][4] =
{
{ DR_10, DR_9 , DR_8 , DR_8 }, // DR_0
{ DR_11, DR_10, DR_9 , DR_8 }, // DR_1
{ DR_12, DR_11, DR_10, DR_9 }, // DR_2
{ DR_13, DR_12, DR_11, DR_10 }, // DR_3
{ DR_13, DR_13, DR_12, DR_11 }, // DR_4
};
/*!
* Maximum payload with respect to the datarate index. Cannot operate with repeater.
*/
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.
*
* \param [IN] getPhy Pointer to the function parameters.
*
* \retval Returns a structure containing the PHY parameter.
*/
PhyParam_t RegionUS915GetPhyParam( GetPhyParams_t* getPhy );
/*!
* \brief Updates the last TX done parameters of the current channel.
*
* \param [IN] txDone Pointer to the function parameters.
*/
void RegionUS915SetBandTxDone( SetBandTxDoneParams_t* txDone );
/*!
* \brief Initializes the channels masks and the channels.
*
* \param [IN] type Sets the initialization type.
*/
void RegionUS915InitDefaults( InitDefaultsParams_t* params );
/*!
* \brief Returns a pointer to the internal context and its size.
*
* \param [OUT] params Pointer to the function parameters.
*
* \retval Points to a structure where the module store its non-volatile context.
*/
void* RegionUS915GetNvmCtx( GetNvmCtxParams_t* params );
/*!
* \brief Verifies a parameter.
*
* \param [IN] verify Pointer to the function parameters.
*
* \param [IN] type Sets the initialization type.
*
* \retval Returns true, if the parameter is valid.
*/
bool RegionUS915Verify( VerifyParams_t* verify, PhyAttribute_t phyAttribute );
/*!
* \brief The function parses the input buffer and sets up the channels of the
* CF list.
*
* \param [IN] applyCFList Pointer to the function parameters.
*/
void RegionUS915ApplyCFList( ApplyCFListParams_t* applyCFList );
/*!
* \brief Sets a channels mask.
*
* \param [IN] chanMaskSet Pointer to the function parameters.
*
* \retval Returns true, if the channels mask could be set.
*/
bool RegionUS915ChanMaskSet( ChanMaskSetParams_t* chanMaskSet );
/*!
* Computes the Rx window timeout and offset.
*
* \param [IN] datarate Rx window datarate index to be used
*
* \param [IN] minRxSymbols Minimum required number of symbols to detect an Rx frame.
*
* \param [IN] rxError System maximum timing error of the receiver. In milliseconds
* The receiver will turn on in a [-rxError : +rxError] ms
* interval around RxOffset
*
* \param [OUT]rxConfigParams Returns updated WindowTimeout and WindowOffset fields.
*/
void RegionUS915ComputeRxWindowParameters( int8_t datarate, uint8_t minRxSymbols, uint32_t rxError, RxConfigParams_t *rxConfigParams );
/*!
* \brief Configuration of the RX windows.
*
* \param [IN] rxConfig Pointer to the function parameters.
*
* \param [OUT] datarate The datarate index which was set.
*
* \retval Returns true, if the configuration was applied successfully.
*/
bool RegionUS915RxConfig( RxConfigParams_t* rxConfig, int8_t* datarate );
/*!
* \brief TX configuration.
*
* \param [IN] txConfig Pointer to the function parameters.
*
* \param [OUT] txPower The tx power index which was set.
*
* \param [OUT] txTimeOnAir The time-on-air of the frame.
*
* \retval Returns true, if the configuration was applied successfully.
*/
bool RegionUS915TxConfig( TxConfigParams_t* txConfig, int8_t* txPower, TimerTime_t* txTimeOnAir );
/*!
* \brief The function processes a Link ADR Request.
*
* \param [IN] linkAdrReq Pointer to the function parameters.
*
* \retval Returns the status of the operation, according to the LoRaMAC specification.
*/
uint8_t RegionUS915LinkAdrReq( LinkAdrReqParams_t* linkAdrReq, int8_t* drOut, int8_t* txPowOut, uint8_t* nbRepOut, uint8_t* nbBytesParsed );
/*!
* \brief The function processes a RX Parameter Setup Request.
*
* \param [IN] rxParamSetupReq Pointer to the function parameters.
*
* \retval Returns the status of the operation, according to the LoRaMAC specification.
*/
uint8_t RegionUS915RxParamSetupReq( RxParamSetupReqParams_t* rxParamSetupReq );
/*!
* \brief The function processes a Channel Request.
*
* \param [IN] newChannelReq Pointer to the function parameters.
*
* \retval Returns the status of the operation, according to the LoRaMAC specification.
*/
uint8_t RegionUS915NewChannelReq( NewChannelReqParams_t* newChannelReq );
/*!
* \brief The function processes a TX ParamSetup Request.
*
* \param [IN] txParamSetupReq Pointer to the function parameters.
*
* \retval Returns the status of the operation, according to the LoRaMAC specification.
* Returns -1, if the functionality is not implemented. In this case, the end node
* shall not process the command.
*/
int8_t RegionUS915TxParamSetupReq( TxParamSetupReqParams_t* txParamSetupReq );
/*!
* \brief The function processes a DlChannel Request.
*
* \param [IN] dlChannelReq Pointer to the function parameters.
*
* \retval Returns the status of the operation, according to the LoRaMAC specification.
*/
uint8_t RegionUS915DlChannelReq( DlChannelReqParams_t* dlChannelReq );
/*!
* \brief Alternates the datarate of the channel for the join request.
*
* \param [IN] currentDr Current datarate.
*
* \param [IN] type Alternation type.
*
* \retval Datarate to apply.
*/
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
*
* \param [OUT] channel Next channel to use for TX.
*
* \param [OUT] time Time to wait for the next transmission according to the duty
* cycle.
*
* \param [OUT] aggregatedTimeOff Updates the aggregated time off.
*
* \retval Function status [1: OK, 0: Unable to find a channel on the current datarate]
*/
LoRaMacStatus_t RegionUS915NextChannel( NextChanParams_t* nextChanParams, uint8_t* channel, TimerTime_t* time, TimerTime_t* aggregatedTimeOff );
/*!
* \brief Adds a channel.
*
* \param [IN] channelAdd Pointer to the function parameters.
*
* \retval Status of the operation.
*/
LoRaMacStatus_t RegionUS915ChannelAdd( ChannelAddParams_t* channelAdd );
/*!
* \brief Removes a channel.
*
* \param [IN] channelRemove Pointer to the function parameters.
*
* \retval Returns true, if the channel was removed successfully.
*/
bool RegionUS915ChannelsRemove( ChannelRemoveParams_t* channelRemove );
/*!
* \brief Sets the radio into continuous wave mode.
*
* \param [IN] continuousWave Pointer to the function parameters.
*/
void RegionUS915SetContinuousWave( ContinuousWaveParams_t* continuousWave );
/*!
* \brief Computes new datarate according to the given offset
*
* \param [IN] downlinkDwellTime Downlink dwell time configuration. 0: No limit, 1: 400ms
*
* \param [IN] dr Current datarate
*
* \param [IN] drOffset Offset to be applied
*
* \retval newDr Computed datarate.
*/
uint8_t RegionUS915ApplyDrOffset( uint8_t downlinkDwellTime, int8_t dr, int8_t drOffset );
/*!
* \brief Sets the radio into beacon reception mode
*
* \param [IN] rxBeaconSetup Pointer to the function parameters
*/
void RegionUS915RxBeaconSetup( RxBeaconSetup_t* rxBeaconSetup, uint8_t* outDr );
/*! \} defgroup REGIONUS915 */
#endif // __REGION_US915_H__

View File

@@ -0,0 +1,207 @@
/*!
* \file secure-element.h
*
* \brief Secure Element driver API
*
* \copyright Revised BSD License, see section \ref LICENSE.
*
* \code
* ______ _
* / _____) _ | |
* ( (____ _____ ____ _| |_ _____ ____| |__
* \____ \| ___ | (_ _) ___ |/ ___) _ \
* _____) ) ____| | | || |_| ____( (___| | | |
* (______/|_____)_|_|_| \__)_____)\____)_| |_|
* (C)2013 Semtech
*
* ___ _____ _ ___ _ _____ ___ ___ ___ ___
* / __|_ _/_\ / __| |/ / __/ _ \| _ \/ __| __|
* \__ \ | |/ _ \ (__| ' <| _| (_) | / (__| _|
* |___/ |_/_/ \_\___|_|\_\_| \___/|_|_\\___|___|
* embedded.connectivity.solutions===============
*
* \endcode
*
* \author Miguel Luis ( Semtech )
*
* \author Gregory Cristian ( Semtech )
*
* \author Daniel Jaeckle ( STACKFORCE )
*
* \author Johannes Bruder ( STACKFORCE )
*
* \defgroup SECUREELEMENT Secure Element API Definition
*
* \{
*
*/
#ifndef __SECURE_ELEMENT_H__
#define __SECURE_ELEMENT_H__
#include <stdint.h>
#include "LoRaMacCrypto.h"
#define SE_EUI_SIZE 16
/*!
* Return values.
*/
typedef enum eSecureElementStatus
{
/*!
* No error occurred
*/
SECURE_ELEMENT_SUCCESS = 0,
/*!
* CMAC does not match
*/
SECURE_ELEMENT_FAIL_CMAC,
/*!
* Null pointer exception
*/
SECURE_ELEMENT_ERROR_NPE,
/*!
* Invalid key identifier exception
*/
SECURE_ELEMENT_ERROR_INVALID_KEY_ID,
/*!
* Invalid LoRaWAN specification version
*/
SECURE_ELEMENT_ERROR_INVALID_LORAWAM_SPEC_VERSION,
/*!
* Incompatible buffer size
*/
SECURE_ELEMENT_ERROR_BUF_SIZE,
/*!
* Undefined Error occurred
*/
SECURE_ELEMENT_ERROR,
}SecureElementStatus_t;
/*!
* Signature of callback function to be called by the Secure Element driver when the
* non volatile context have to be stored.
*
*/
typedef void ( *SecureElementNvmEvent )( void );
/*!
* Initialization of Secure Element driver
*
* \param[IN] seNvmCtxChanged - Callback function which will be called when the
* non-volatile context have to be stored.
* \retval - Status of the operation
*/
SecureElementStatus_t SecureElementInit( SecureElementNvmEvent seNvmCtxChanged );
/*!
* Restores the internal nvm context from passed pointer.
*
* \param[IN] seNvmCtx - Pointer to non-volatile module context to be restored.
* \retval - Status of the operation
*/
SecureElementStatus_t SecureElementRestoreNvmCtx( void* seNvmCtx );
/*!
* Returns a pointer to the internal non-volatile context.
*
* \param[IN] seNvmCtxSize - Size of the module non volatile context
* \retval - Points to a structure where the module store its non volatile context
*/
void* SecureElementGetNvmCtx( size_t* seNvmCtxSize );
/*!
* Sets a key
*
* \param[IN] keyID - Key identifier
* \param[IN] key - Key value
* \retval - Status of the operation
*/
SecureElementStatus_t SecureElementSetKey( KeyIdentifier_t keyID, uint8_t* key );
/*!
* Computes a CMAC of a message using provided initial Bx block
*
* \param[IN] micBxBuffer - Buffer containing the initial Bx block
* \param[IN] buffer - Data buffer
* \param[IN] size - Data buffer size
* \param[IN] keyID - Key identifier to determine the AES key to be used
* \param[OUT] cmac - Computed cmac
* \retval - Status of the operation
*/
SecureElementStatus_t SecureElementComputeAesCmac( uint8_t* micBxBuffer, uint8_t* buffer, uint16_t size, KeyIdentifier_t keyID, uint32_t* cmac );
/*!
* Verifies a CMAC (computes and compare with expected cmac)
*
* \param[IN] buffer - Data buffer
* \param[IN] size - Data buffer size
* \param[in] expectedCmac - Expected cmac
* \param[IN] keyID - Key identifier to determine the AES key to be used
* \retval - Status of the operation
*/
SecureElementStatus_t SecureElementVerifyAesCmac( uint8_t* buffer, uint16_t size, uint32_t expectedCmac, KeyIdentifier_t keyID );
/*!
* Encrypt a buffer
*
* \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] encBuffer - Encrypted buffer
* \retval - Status of the operation
*/
SecureElementStatus_t SecureElementAesEncrypt( uint8_t* buffer, uint16_t size, KeyIdentifier_t keyID, uint8_t* encBuffer );
/*!
* Derives and store a key
*
* \param[IN] version - LoRaWAN specification version currently in use.
* \param[IN] input - Input data from which the key is derived ( 16 byte )
* \param[IN] rootKeyID - Key identifier of the root key to use to perform the derivation
* \param[IN] targetKeyID - Key identifier of the key which will be derived
* \retval - Status of the operation
*/
SecureElementStatus_t SecureElementDeriveAndStoreKey( Version_t version, uint8_t* input, KeyIdentifier_t rootKeyID, KeyIdentifier_t targetKeyID );
/*!
* Generates a random number
*
* \param[OUT] randomNum - 32 bit random number
* \retval - Status of the operation
*/
SecureElementStatus_t SecureElementRandomNumber( uint32_t* randomNum );
/*!
* Sets the DevEUI
*
* \param[IN] devEui - Pointer to the 16-byte devEUI
* \retval - Status of the operation
*/
SecureElementStatus_t SecureElementSetDevEui( uint8_t* devEui );
/*!
* Gets the DevEUI
*
* \retval - Pointer to the 16-byte devEUI
*/
uint8_t* SecureElementGetDevEui( void );
/*!
* Sets the JoinEUI
*
* \param[IN] joinEui - Pointer to the 16-byte joinEui
* \retval - Status of the operation
*/
SecureElementStatus_t SecureElementSetJoinEui( uint8_t* joinEui );
/*!
* Gets the DevEUI
*
* \retval - Pointer to the 16-byte joinEui
*/
uint8_t* SecureElementGetJoinEui( void );
/*! \} defgroup SECUREELEMENT */
#endif // __SECURE_ELEMENT_H__

View File

@@ -0,0 +1,56 @@
/**
******************************************************************************
* @file app_conf_template.h
* @author MCD Application Team
* @brief applic configuration, e.g. : debug, trace, low power, sensors
* @note this is a template: the app_conf.h shall be defined in the Project/...
******************************************************************************
* @attention
*
* <h2><center>&copy; Copyright (c) 2019 STMicroelectronics.
* All rights reserved.</center></h2>
*
* This software component is licensed by ST under BSD 3-Clause license,
* the "License"; You may not use this file except in compliance with the
* License. You may obtain a copy of the License at:
* opensource.org/licenses/BSD-3-Clause
*
******************************************************************************
*/
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef __APP_CONF_H__
#define __APP_CONF_H__
#ifdef __cplusplus
extern "C" {
#endif
/* Includes ------------------------------------------------------------------*/
/* Exported types ------------------------------------------------------------*/
/* Exported constants --------------------------------------------------------*/
/* LoraWAN application configuration (Mw is configured by lorawan_conf.h) */
#define ACTIVE_REGION LORAMAC_REGION_EU868
#define HYBRID_ENABLED 0
#define LORAMAC_CLASSB_ACTIVE 0 /* 0 if not active, 1 if active */
/* Enable trace logs. Note verbose level can be selected in app_system.h */
#define APP_LOG_ENABLED 1
#define DEBUGGER_ON 0 /* if ON (=1) it enables the debbugger plus 4 dgb pins */
/* if OFF (=0) the debugger is OFF (lower consumption) */
/* External variables --------------------------------------------------------*/
/* Exported macros -----------------------------------------------------------*/
/* Defines -------------------------------------------------------------------*/
/* Exported functions ------------------------------------------------------- */
#ifdef __cplusplus
}
#endif
#endif /* __APP_CONF_H__ */
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/

View File

@@ -0,0 +1,62 @@
/**
******************************************************************************
* @file app_system_template.h
* @author MCD Application Team
* @brief function prototypes for app_system.c file
* @note this is a template: the app_conf.h shall be defined in the Project/...
******************************************************************************
* @attention
*
* <h2><center>&copy; Copyright (c) 2019 STMicroelectronics.
* All rights reserved.</center></h2>
*
* This software component is licensed by ST under BSD 3-Clause license,
* the "License"; You may not use this file except in compliance with the
* License. You may obtain a copy of the License at:
* opensource.org/licenses/BSD-3-Clause
*
******************************************************************************
*/
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef __APP_SYSTEM_H__
#define __APP_SYSTEM_H__
#ifdef __cplusplus
extern "C" {
#endif
/* Includes ------------------------------------------------------------------*/
#include <stdint.h>
#include "app_conf.h"
#include "trace.h"
/* Exported types ------------------------------------------------------------*/
/* Exported constants --------------------------------------------------------*/
#define VERBOSE_LEVEL VLEVEL_L
/* External variables --------------------------------------------------------*/
/* Exported macros -----------------------------------------------------------*/
#define APP_PPRINTF(...) do{ } while( 0!= TraceSend(0, 0, __VA_ARGS__) ) //Polling Mode
#define APP_TPRINTF(...) do{ {TraceSend(1, 0, __VA_ARGS__);} }while(0); //with timestamp
#define APP_PRINTF(...) do{ {TraceSend(0, 0, __VA_ARGS__);} }while(0);
#if defined (APP_LOG_ENABLED) && (APP_LOG_ENABLED == 1)
#define APP_LOG(TS,VL,...) do{ {TraceSend(TS, VL, __VA_ARGS__);} }while(0);
#elif defined (APP_LOG_ENABLED) && (APP_LOG_ENABLED == 0) /* APP_LOG disabled */
#define APP_LOG(TS,VL,...)
#else
#error "APP_LOG_ENABLED not defined or out of range <0,1>"
#endif
/* Defines -------------------------------------------------------------------*/
/* Exported functions ------------------------------------------------------- */
#ifdef __cplusplus
}
#endif
#endif /* __APP_SYSTEM_H__ */
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/

View File

@@ -0,0 +1,433 @@
/******************************************************************************
* @file lora-test.c
* @author MCD Application Team
* @brief lora API to drive the lora state Machine
******************************************************************************
* @attention
*
* <h2><center>&copy; Copyright (c) 2019 STMicroelectronics.
* All rights reserved.</center></h2>
*
* This software component is licensed by ST under BSD 3-Clause license,
* the "License"; You may not use this file except in compliance with the
* License. You may obtain a copy of the License at:
* opensource.org/licenses/BSD-3-Clause
*
******************************************************************************
*/
/* Includes ------------------------------------------------------------------*/
#include "stddef.h"
//#include "lorawan_conf.h" /* Don't remove: needed for LORAMAC_CLASSB_ENABLED */
//#include "mw_log_conf.h"
#include "LoRaMac.h"
#include "LoRaMacTest.h"
#include "lora.h"
/* Private typedef -----------------------------------------------------------*/
typedef struct ComplianceTest_s
{
bool Running;
uint8_t State;
LoraConfirm_t IsTxConfirmed;
uint8_t DataBufferSize;
uint8_t DataBuffer[242]; /* max possible payload */
uint16_t DownLinkCounter;
bool LinkCheck;
uint8_t DemodMargin;
uint8_t NbGateways;
} ComplianceTest_t;
typedef enum
{
CERTIF_TX_PROCESS = 0,
CERTIF_RX_PROCESS
} requestProcess_t;
/* Private define ------------------------------------------------------------*/
#define TEST_TX_DUTYCYCLE 5000
/* Private variables ---------------------------------------------------------*/
static requestProcess_t requested_process_id;
/*!
* Timer to handle the application data transmission duty cycle
*/
static TimerEvent_t CertifTxNextPacketTimer;
static ComplianceTest_t certifParam;
static LoraConfirm_t IsTxConfirmed;
static bool AdrEnableInit;
static McpsIndication_t *CertifMcpsIndication;
static MlmeReqJoin_t *CertifJoinParameters;
/* Private functions ---------------------------------------------------------*/
static bool CERTIF_running(void);
static void CERTIF_DownLinkIncrement(void);
static void CERTIF_linkCheck(MlmeConfirm_t *mlmeConfirm);
static void CERTIF_rx_request(McpsIndication_t *mcpsIndication, MlmeReqJoin_t *JoinParameters);
static void CERTIF_rx(McpsIndication_t *mcpsIndication, MlmeReqJoin_t *JoinParameters);
static bool CERTIF_tx(void);
static void OnCertifTxNextPacketTimerEvent(void *context);
static void (*CertifProcessNotify)(void);
static LoRaCertifCallback_t certifCb =
{
CERTIF_running,
CERTIF_DownLinkIncrement,
CERTIF_linkCheck,
CERTIF_rx_request,
};
/* Exported functions definition---------------------------------------------------------*/
void CERTIF_Init(void (*CERTIF_ProcessNotify)(void))
{
/*initialises Callback into the Lora.c layer*/
LORA_TestInit(&certifCb);
/*Register TestProcessNotify callback*/
CertifProcessNotify = CERTIF_ProcessNotify;
}
void CERTIF_Process(void)
{
switch (requested_process_id)
{
case CERTIF_TX_PROCESS:
CERTIF_tx();
break;
case CERTIF_RX_PROCESS:
CERTIF_rx(CertifMcpsIndication, CertifJoinParameters);
break;
default:
break;
}
}
static bool CERTIF_running(void)
{
return certifParam.Running;
}
static void CERTIF_DownLinkIncrement(void)
{
certifParam.DownLinkCounter++;
}
static void CERTIF_linkCheck(MlmeConfirm_t *mlmeConfirm)
{
certifParam.LinkCheck = true;
certifParam.DemodMargin = mlmeConfirm->DemodMargin;
certifParam.NbGateways = mlmeConfirm->NbGateways;
}
static bool CERTIF_tx(void)
{
McpsReq_t mcpsReq;
LoRaMacTxInfo_t txInfo;
#if (ACTIVE_REGION == LORAMAC_REGION_US915)
bool abortTx = false;
#endif /* ACTIVE_REGION == LORAMAC_REGION_US915 */
if (certifParam.LinkCheck == true)
{
certifParam.LinkCheck = false;
certifParam.DataBufferSize = 3;
certifParam.DataBuffer[0] = 5;
certifParam.DataBuffer[1] = certifParam.DemodMargin;
certifParam.DataBuffer[2] = certifParam.NbGateways;
certifParam.State = 1;
}
else
{
switch (certifParam.State)
{
case 4:
certifParam.State = 1;
break;
case 1:
certifParam.DataBufferSize = 2;
certifParam.DataBuffer[0] = certifParam.DownLinkCounter >> 8;
certifParam.DataBuffer[1] = certifParam.DownLinkCounter;
break;
}
}
if (LoRaMacQueryTxPossible(certifParam.DataBufferSize, &txInfo) != LORAMAC_STATUS_OK)
{
#if (ACTIVE_REGION == LORAMAC_REGION_US915)
abortTx = true; /* Do not send empty frame as some testers do not support it */
#else
// Send empty frame in order to flush MAC commands
mcpsReq.Type = MCPS_UNCONFIRMED;
mcpsReq.Req.Unconfirmed.fBuffer = NULL;
mcpsReq.Req.Unconfirmed.fBufferSize = 0;
mcpsReq.Req.Unconfirmed.Datarate = DR_0;
#endif /* ACTIVE_REGION == LORAMAC_REGION_US915 */
}
else
{
if (IsTxConfirmed == LORAWAN_UNCONFIRMED_MSG)
{
mcpsReq.Type = MCPS_UNCONFIRMED;
mcpsReq.Req.Unconfirmed.fPort = CERTIF_PORT;
mcpsReq.Req.Unconfirmed.fBufferSize = certifParam.DataBufferSize;
mcpsReq.Req.Unconfirmed.fBuffer = &(certifParam.DataBuffer);
mcpsReq.Req.Unconfirmed.Datarate = DR_0;
}
else
{
mcpsReq.Type = MCPS_CONFIRMED;
mcpsReq.Req.Confirmed.fPort = CERTIF_PORT;
mcpsReq.Req.Confirmed.fBufferSize = certifParam.DataBufferSize;
mcpsReq.Req.Confirmed.fBuffer = &(certifParam.DataBuffer);
mcpsReq.Req.Confirmed.NbTrials = 8;
mcpsReq.Req.Confirmed.Datarate = DR_0;
}
}
/*cerification test on-going*/
TimerStart(&CertifTxNextPacketTimer);
#if (ACTIVE_REGION == LORAMAC_REGION_US915)
if (abortTx == true)
{
return true;
}
#endif /* ACTIVE_REGION == LORAMAC_REGION_US915 */
if (LoRaMacMcpsRequest(&mcpsReq) == LORAMAC_STATUS_OK)
{
return false;
}
return true;
}
static void CERTIF_rx_request(McpsIndication_t *mcpsIndication, MlmeReqJoin_t *JoinParameters)
{
CertifMcpsIndication = mcpsIndication;
CertifJoinParameters = JoinParameters;
requested_process_id = CERTIF_RX_PROCESS;
CertifProcessNotify();
}
static void CERTIF_rx(McpsIndication_t *mcpsIndication, MlmeReqJoin_t *JoinParameters)
{
if (certifParam.Running == false)
{
// Check compliance test enable command (i)
if ((mcpsIndication->BufferSize == 4) &&
(mcpsIndication->Buffer[0] == 0x01) &&
(mcpsIndication->Buffer[1] == 0x01) &&
(mcpsIndication->Buffer[2] == 0x01) &&
(mcpsIndication->Buffer[3] == 0x01))
{
MibRequestConfirm_t mibReq;
IsTxConfirmed = LORAWAN_UNCONFIRMED_MSG;
certifParam.DataBufferSize = 2;
certifParam.DownLinkCounter = 0;
certifParam.LinkCheck = false;
certifParam.DemodMargin = 0;
certifParam.NbGateways = 0;
certifParam.Running = true;
certifParam.State = 1;
mibReq.Type = MIB_ADR;
LoRaMacMibGetRequestConfirm(&mibReq);
AdrEnableInit = mibReq.Param.AdrEnable;
mibReq.Type = MIB_ADR;
mibReq.Param.AdrEnable = true;
LoRaMacMibSetRequestConfirm(&mibReq);
if ( (ACTIVE_REGION == LORAMAC_REGION_EU868)
|| (ACTIVE_REGION == LORAMAC_REGION_RU864)
|| (ACTIVE_REGION == LORAMAC_REGION_CN779)
|| (ACTIVE_REGION == LORAMAC_REGION_EU433))
{
LoRaMacTestSetDutyCycleOn(false);
}
TimerInit(&CertifTxNextPacketTimer, OnCertifTxNextPacketTimerEvent);
TimerSetValue(&CertifTxNextPacketTimer, TEST_TX_DUTYCYCLE);
/*confirm test mode activation */
CERTIF_tx();
}
}
else
{
certifParam.State = mcpsIndication->Buffer[0];
switch (certifParam.State)
{
case 0: // Check compliance test disable command (ii)
{
certifParam.DownLinkCounter = 0;
certifParam.Running = false;
MibRequestConfirm_t mibReq;
mibReq.Type = MIB_ADR;
mibReq.Param.AdrEnable = AdrEnableInit;
LoRaMacMibSetRequestConfirm(&mibReq);
if ( (ACTIVE_REGION == LORAMAC_REGION_EU868)
|| (ACTIVE_REGION == LORAMAC_REGION_RU864)
|| (ACTIVE_REGION == LORAMAC_REGION_CN779)
|| (ACTIVE_REGION == LORAMAC_REGION_EU433))
{
LoRaMacTestSetDutyCycleOn(true);
}
break;
}
case 1: // (iii, iv)
certifParam.DataBufferSize = 2;
break;
case 2: // Enable confirmed messages (v)
IsTxConfirmed = LORAWAN_CONFIRMED_MSG;
certifParam.State = 1;
break;
case 3: // Disable confirmed messages (vi)
IsTxConfirmed = LORAWAN_UNCONFIRMED_MSG;
certifParam.State = 1;
break;
case 4: // (vii)
certifParam.DataBufferSize = mcpsIndication->BufferSize;
certifParam.DataBuffer[0] = 4;
for (uint8_t i = 1; i < certifParam.DataBufferSize; i++)
{
certifParam.DataBuffer[i] = mcpsIndication->Buffer[i] + 1;
}
break;
case 5: // (viii)
{
MlmeReq_t mlmeReq;
mlmeReq.Type = MLME_LINK_CHECK;
LoRaMacMlmeRequest(&mlmeReq);
break;
}
case 6: // (ix)
{
MlmeReq_t mlmeReq;
// Disable TestMode and revert back to normal operation
certifParam.DownLinkCounter = 0;
certifParam.Running = false;
MibRequestConfirm_t mibReq;
mibReq.Type = MIB_ADR;
mibReq.Param.AdrEnable = AdrEnableInit;
LoRaMacMibSetRequestConfirm(&mibReq);
mlmeReq.Type = MLME_JOIN;
mlmeReq.Req.Join = *JoinParameters;
LoRaMacMlmeRequest(&mlmeReq);
break;
}
case 7: // (x)
{
if (mcpsIndication->BufferSize == 3)
{
MlmeReq_t mlmeReq;
mlmeReq.Type = MLME_TXCW;
mlmeReq.Req.TxCw.Timeout = (uint16_t)((mcpsIndication->Buffer[1] << 8) | mcpsIndication->Buffer[2]);
LoRaMacMlmeRequest(&mlmeReq);
}
else if (mcpsIndication->BufferSize == 7)
{
MlmeReq_t mlmeReq;
mlmeReq.Type = MLME_TXCW_1;
mlmeReq.Req.TxCw.Timeout = (uint16_t)((mcpsIndication->Buffer[1] << 8) | mcpsIndication->Buffer[2]);
mlmeReq.Req.TxCw.Frequency = (uint32_t)((mcpsIndication->Buffer[3] << 16) | (mcpsIndication->Buffer[4] << 8) | mcpsIndication->Buffer[5]) * 100;
mlmeReq.Req.TxCw.Power = mcpsIndication->Buffer[6];
LoRaMacMlmeRequest(&mlmeReq);
}
certifParam.State = 1;
break;
}
case 8: // Send DeviceTimeReq
{
MlmeReq_t mlmeReq;
mlmeReq.Type = MLME_DEVICE_TIME;
LoRaMacMlmeRequest(&mlmeReq);
break;
}
#if defined (LORAMAC_CLASSB_ACTIVE) && ( LORAMAC_CLASSB_ACTIVE == 1 )
case 9: // Switch end device Class
{
MibRequestConfirm_t mibReq;
mibReq.Type = MIB_DEVICE_CLASS;
// CLASS_A = 0, CLASS_B = 1, CLASS_C = 2
mibReq.Param.Class = (DeviceClass_t)mcpsIndication->Buffer[1];
LoRaMacMibSetRequestConfirm(&mibReq);
break;
}
case 10: // Send PingSlotInfoReq
{
MlmeReq_t mlmeReq;
mlmeReq.Type = MLME_PING_SLOT_INFO;
mlmeReq.Req.PingSlotInfo.PingSlot.Value = mcpsIndication->Buffer[1];
LoRaMacMlmeRequest(&mlmeReq);
break;
}
case 11: // Send BeaconTimingReq
{
MlmeReq_t mlmeReq;
mlmeReq.Type = MLME_BEACON_TIMING;
LoRaMacMlmeRequest(&mlmeReq);
break;
}
#elif !defined (LORAMAC_CLASSB_ACTIVE)
#error LORAMAC_CLASSB_ACTIVE not defined
#endif
default:
break;
}
}
if (certifParam.Running == false)
{
/*certification test stops*/
TimerStop(&CertifTxNextPacketTimer);
}
}
/*!
* \brief Function executed on TxNextPacket Timeout event
*/
static void OnCertifTxNextPacketTimerEvent(void *context)
{
requested_process_id = CERTIF_TX_PROCESS;
CertifProcessNotify();
}
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/

View File

@@ -0,0 +1,72 @@
/******************************************************************************
* @file lora_test.h
* @author MCD Application Team
* @brief lora API to drive the lora state Machine
******************************************************************************
* @attention
*
* <h2><center>&copy; Copyright (c) 2019 STMicroelectronics.
* All rights reserved.</center></h2>
*
* This software component is licensed by ST under BSD 3-Clause license,
* the "License"; You may not use this file except in compliance with the
* License. You may obtain a copy of the License at:
* opensource.org/licenses/BSD-3-Clause
*
******************************************************************************
*/
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef __LORA_TEST_H__
#define __LORA_TEST_H__
#ifdef __cplusplus
extern "C" {
#endif
/* Includes ------------------------------------------------------------------*/
/* Exported constants --------------------------------------------------------*/
#define CERTIF_PORT 224
/* Exported types ------------------------------------------------------------*/
/* External variables --------------------------------------------------------*/
/* Exported macros -----------------------------------------------------------*/
/* Exported functions ------------------------------------------------------- */
/**
* @brief Certification Initialisation
* @param [IN] Notification call back to the appl that a CERTIF_Process must be called
* @retval none
*/
void CERTIF_Init(void (*CERTIF_ProcessNotify)(void));
/**
* @brief CERTIF_Process to be called when a CERTIF_ProcessNotify callback is generated
* @param [IN] none
* @retval none
*/
void CERTIF_Process(void);
/* Lora Test callbacks*/
typedef struct sLoRaCertifCallback
{
bool (*running)(void);
void (*DownLinkIncrement)(void);
void (*linkCheck)(MlmeConfirm_t *mlmeConfirm);
void (*rx)(McpsIndication_t *mcpsIndication, MlmeReqJoin_t *JoinParameters);
} LoRaCertifCallback_t;
#ifdef __cplusplus
}
#endif
#endif /*__LORA_TEST_H__*/
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/

View File

@@ -0,0 +1,985 @@
/*
_/_/_/ _/_/_/ _/_/_/ _/_/_/ _/ _/ _/_/_/ _/ _/ _/_/_/_/
_/ _/ _/ _/ _/ _/_/ _/ _/ _/ _/ _/
_/_/_/ _/ _/_/ _/ _/ _/ _/ _/ _/_/ _/_/_/_/ _/_/_/
_/ _/ _/ _/ _/ _/ _/_/ _/ _/ _/ _/ _/
_/ _/ _/_/_/ _/_/_/ _/_/_/ _/ _/ _/_/_/ _/ _/ _/
(C)2020/5/20 RisingHF, all rights reserved.
Lorawan API
*/
#include "timer.h"
#include "LoRaMac.h"
#include "LoRaMacTest.h"
#include "lora.h"
#include "app_system.h"
#include "lorawan_info.h"
#include "stm32_mem.h"
typedef struct
{
lw_state_t otaa; /*< ENABLE if over the air activation, DISABLE otherwise */
lw_state_t duty_cycle; /*< ENABLE if dutycyle is on, DISABLE otherwise */
uint8_t DevEui[8]; /*< Device EUI */
uint8_t JoinEui[8]; /*< Join Eui */
uint8_t AppKey[16]; /*< Application Key */
uint8_t NwkKey[16]; /*< Application Key */
uint8_t NwkSEncKey[16]; /*< Network Session Key */
uint8_t AppSKey[16]; /*< Application Session Key */
uint8_t FNwkSIntKey[16]; /*< Application Session Key */
uint8_t SNwkSIntKey[16]; /*< Application Session Key */
int16_t Rssi; /*< Rssi of the received packet */
int8_t Snr; /*< Snr of the received packet */
uint8_t application_port; /*< Application port we will receive to */
LoraConfirm_t ReqAck; /*< ENABLE if acknowledge is requested */
int8_t TxDatarate;
}lorawan_configuration_t;
/*!
* LoRa State Machine states
*/
typedef struct slorawan_param
{
bool adr_enable; /*Activation state of adaptativeDatarate*/
bool enable_public_network; /*Enable or disable a public network*/
int8_t tx_datarate; /*Uplink datarate, if AdrEnable is off*/
uint8_t confirm_retry; /*the uplink confirm frame retry times*/
LoRaMacRegion_t active_region; /*region to open*/
uint32_t dev_addr;
} lw_param_t;
static lorawan_configuration_t lw_config =
{
.otaa = LORA_ENABLE,
.duty_cycle = LORA_ENABLE,
.DevEui = LORAWAN_DEVICE_EUI,
.JoinEui = LORAWAN_JOIN_EUI,
.AppKey = LORAWAN_APP_KEY,
.NwkKey = LORAWAN_NWK_KEY,
.NwkSEncKey = LORAWAN_NWK_S_ENC_KEY,
.AppSKey = LORAWAN_APP_S_KEY,
.FNwkSIntKey = LORAWAN_F_NWK_S_INT_KEY,
.SNwkSIntKey = LORAWAN_S_NWK_S_INT_KEY,
.Rssi = 0,
.Snr = 0,
.ReqAck = LORAWAN_UNCONFIRMED_MSG,
.TxDatarate = 0
};
static lw_param_t lw_param_init =
{
.adr_enable = 0,
.tx_datarate =DR_0,
.confirm_retry = 2,
.enable_public_network = LORAWAN_PUBLIC_NETWORK,
.active_region = LORAWAN_DEFAULT_ACTIVE_REGION,
.dev_addr = LORAWAN_DEVICE_ADDRESS
};
/*!
* Select either Device_Time_req or Beacon_Time_Req following LoRaWAN version
* - Device_Time_req Available for V1.0.3 or later
* - Beacon_time_Req Available for V1.0.2 and before
*/
#define USE_DEVICE_TIMING
#include "LoRaMacTest.h"
/*for classB=============================================================*/
#ifndef LORAMAC_CLASSB_ACTIVE
#error LORAMAC_CLASSB_ACTIVE not defined ( shall be <0 or 1> )
#endif /* LORAMAC_CLASSB_ACTIVE */
#if ( LORAMAC_CLASSB_ACTIVE == 1 )
/*!
* Default ping slots periodicity
*
* \remark periodicity is equal to 2^LORAWAN_DEFAULT_PING_SLOT_PERIODICITY seconds
* example: 2^3 = 8 seconds. The end-device will open an Rx slot every 8 seconds.
*/
#define LORAWAN_DEFAULT_PING_SLOT_PERIODICITY 0
static uint8_t DefaultPingSlotPeriodicity;
#endif /* LORAMAC_CLASSB_ACTIVE */
/*=============================================================*/
#define HEX16(X) X[0],X[1], X[2],X[3], X[4],X[5], X[6],X[7],X[8],X[9], X[10],X[11], X[12],X[13], X[14],X[15]
#define HEX8(X) X[0],X[1], X[2],X[3], X[4],X[5], X[6],X[7]
static MlmeReqJoin_t JoinParameters;
/* Dummy data sent periodically to let the tester respond with start test command*/
static TimerEvent_t TxcertifTimer;
/* Private macro -------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/
/* Private function prototypes -----------------------------------------------*/
/*for classB=============================================================*/
#if ( LORAMAC_CLASSB_ACTIVE == 1 )
static LoraErrorStatus lw_beacon_req(void);
static LoraErrorStatus lw_pingslot_req(void);
#if defined( USE_DEVICE_TIMING )
static LoraErrorStatus lw_device_time_req(void);
#else
static LoraErrorStatus lw_beacon_time_req(void);
#endif /* USE_DEVICE_TIMING */
#endif /* LORAMAC_CLASSB_ACTIVE */
/*======================================================================*/
static LoRaMacPrimitives_t LoRaMacPrimitives;
static LoRaMacCallback_t LoRaMacCallbacks;
static MibRequestConfirm_t mibReq;
static LoRaMainCallback_t *LoRaMainCallbacks;
/* Private user code ---------------------------------------------------------*/
/*!
* \brief MCPS-Confirm event function
*
* \param [IN] McpsConfirm - Pointer to the confirm structure,
* containing confirm attributes.
*/
static void McpsConfirm(McpsConfirm_t *mcpsConfirm)
{
lw_app_data_t app_data = {0};
if (mcpsConfirm->Status == LORAMAC_EVENT_INFO_STATUS_OK)
{
switch (mcpsConfirm->McpsRequest)
{
case MCPS_UNCONFIRMED:
case MCPS_CONFIRMED:
{
// Check Datarate
// Check TxPower
// Check AckReceived
// Check NbTrials
break;
}
case MCPS_PROPRIETARY:
{
break;
}
default:
break;
}
}
app_data.ack = mcpsConfirm->AckReceived;
LoRaMainCallbacks->app_events(APP_TX_DONE_EVENT,&app_data);
}
/*!
* \brief MCPS-Indication event function
*
* \param [IN] mcpsIndication - Pointer to the indication structure,
* containing indication attributes.
*/
static void McpsIndication(McpsIndication_t *mcpsIndication)
{
lw_app_data_t app_data ={0};
if(mcpsIndication->Status != LORAMAC_EVENT_INFO_STATUS_OK)
{
return;
}
switch (mcpsIndication->McpsIndication)
{
case MCPS_UNCONFIRMED:
{
break;
}
case MCPS_CONFIRMED:
{
break;
}
case MCPS_PROPRIETARY:
{
break;
}
case MCPS_MULTICAST:
{
break;
}
default:
break;
}
// Check Buffer
// Check BufferSize
// Check Rssi
// Check Snr
// Check RxSlot
if(mcpsIndication->RxData == true)
{
app_data.port = mcpsIndication->Port;
app_data.size = mcpsIndication->BufferSize;
app_data.buff = mcpsIndication->Buffer;
app_data.fpending = mcpsIndication->FramePending;
lw_config.Rssi = mcpsIndication->Rssi;
lw_config.Snr = mcpsIndication->Snr;
LoRaMainCallbacks->app_events(APP_RX_EVENT,&app_data);
}
}
/*!
* \brief MLME-Confirm event function
*
* \param [IN] MlmeConfirm - Pointer to the confirm structure,
* containing confirm attributes.
*/
static void MlmeConfirm(MlmeConfirm_t *mlmeConfirm)
{
#if (LORAMAC_CLASSB_ACTIVE == 1)
MibRequestConfirm_t mibReq;
#endif /* LORAMAC_CLASSB_ACTIVE */
switch (mlmeConfirm->MlmeRequest)
{
case MLME_JOIN:
{
if(mlmeConfirm->Status == LORAMAC_EVENT_INFO_STATUS_OK)
{
// Status is OK, node has joined the network
LoRaMainCallbacks->app_events(APP_JOINED_EVENT,NULL);
#if ( LORAMAC_CLASSB_ACTIVE == 1 )
#if defined( USE_DEVICE_TIMING )
lw_device_time_req();
#else
lw_beacon_time_req();
#endif /* USE_DEVICE_TIMING */
#endif /* LORAMAC_CLASSB_ACTIVE */
}
else
{
// Join was not successful. Try to join again
lw_join();
}
break;
}
case MLME_LINK_CHECK:
{
if (mlmeConfirm->Status == LORAMAC_EVENT_INFO_STATUS_OK)
{
}
break;
}
#if ( LORAMAC_CLASSB_ACTIVE == 1 )
case MLME_BEACON_ACQUISITION:
{
if(mlmeConfirm->Status == LORAMAC_EVENT_INFO_STATUS_OK)
{
/* Beacon has been acquired */
/* REquest Server for Ping Slot */
lw_pingslot_req();
}
else
{
/* Beacon not acquired */
/* Search again */
/* we can check if the MAC has received a time reference for the beacon*/
/* in this case do either a Device_Time_Req or a Beacon_Timing_req*/
lw_beacon_req();
}
break;
}
case MLME_PING_SLOT_INFO:
{
if(mlmeConfirm->Status == LORAMAC_EVENT_INFO_STATUS_OK)
{
/* class B is now ativated*/
mibReq.Type = MIB_DEVICE_CLASS;
mibReq.Param.Class = CLASS_B;
LoRaMacMibSetRequestConfirm(&mibReq);
if((lw_param_init.active_region == LORAMAC_REGION_AU915) || (lw_param_init.active_region == LORAMAC_REGION_US915))
{
mibReq.Type = MIB_PING_SLOT_DATARATE;
mibReq.Param.PingSlotDatarate = DR_8;
LoRaMacMibSetRequestConfirm(&mibReq);
}
/*notify upper layer*/
/*ClassB*/
DeviceClass_t cur_class =CLASS_B;
LoRaMainCallbacks->app_events(APP_CONFIRM_ClASS_EVENT,&cur_class);
}
else
{
lw_pingslot_req();
}
break;
}
#if defined( USE_DEVICE_TIMING )
case MLME_DEVICE_TIME:
{
if (mlmeConfirm->Status != LORAMAC_EVENT_INFO_STATUS_OK)
{
lw_device_time_req();
}
}
#endif /* USE_DEVICE_TIMING */
#endif /* LORAMAC_CLASSB_ACTIVE */
default:
break;
}
}
/*!
* \brief MLME-Indication event function
*
* \param [IN] MlmeIndication - Pointer to the indication structure.
*/
static void MlmeIndication(MlmeIndication_t *MlmeIndication)
{
lw_app_data_t app_data ={0};
#if ( LORAMAC_CLASSB_ACTIVE == 1 )
MibRequestConfirm_t mibReq;
#endif /* LORAMAC_CLASSB_ACTIVE */
switch (MlmeIndication->MlmeIndication)
{
case MLME_SCHEDULE_UPLINK:
{
app_data.fpending = 1;
// The MAC signals that we shall provide an uplink as soon as possible
LoRaMainCallbacks->app_events(APP_RX_EVENT,&app_data);
break;
}
#if ( LORAMAC_CLASSB_ACTIVE == 1 )
case MLME_BEACON_LOST:
{
// Switch to class A again
mibReq.Type = MIB_DEVICE_CLASS;
mibReq.Param.Class = CLASS_A;
LoRaMacMibSetRequestConfirm(&mibReq);
lw_beacon_req();
break;
}
case MLME_BEACON:
{
if(MlmeIndication->Status == LORAMAC_EVENT_INFO_STATUS_BEACON_LOCKED)
{
APP_LOG("BEACON RECEIVED\n\r");
}
else
{
APP_LOG("BEACON NOT RECEIVED\n\r");
}
break;
}
#endif /* LORAMAC_CLASSB_ACTIVE */
default:
break;
}
}
/**
* lorawan init
*/
void lw_init(LoRaMainCallback_t *callbacks)
{
LoRaMacInfo_t *LoRaMacRegionInfo;
LoraMacInfo_Init();
LoRaMacRegionInfo = LoraMacInfo_GetPtr();
if(LoRaMacRegionInfo->Region == 0)
{
APP_PRINTF("error: At leats one region shall be defined in the MW: check lorawan_conf.h \n\r");
while(1) {} /* At leats one region shall be defined in MW */
}
#if ( LORAMAC_CLASSB_ACTIVE == 1 )
if(LoRaMacRegionInfo->ClassB != 1)
{
APP_PRINTF("error: ClassB is not defined in the MW: set lorawan_conf.h accordingly\n\r");
while(1) {} /* error: ClassB is not defined in the MW*/
}
#elif ( LORAMAC_CLASSB_ACTIVE == 0 )
if(LoRaMacRegionInfo->ClassB != 0)
{
APP_PRINTF("error: missmatch between applic and MW CLASSB defines: set lorawan_conf.h according to app_conf.h\n\r");
while(1) {} /* error: ClassB should not be defined in the MW*/
}
#endif /* LORAMAC_CLASSB_ACTIVE */
/* init the main call backs*/
LoRaMainCallbacks = callbacks;
#if (STATIC_DEVICE_EUI != 1)
LoRaMainCallbacks->BoardGetUniqueId(lw_config.DevEui);
#endif
#if (STATIC_DEVICE_ADDRESS != 1)
// Choose a "pseudo-random" device address
lw_param_init.dev_addr = LoRaMainCallbacks->BoardGetRandomSeed();
#endif
LoRaMacPrimitives.MacMcpsConfirm = McpsConfirm;
LoRaMacPrimitives.MacMcpsIndication = McpsIndication;
LoRaMacPrimitives.MacMlmeConfirm = MlmeConfirm;
LoRaMacPrimitives.MacMlmeIndication = MlmeIndication;
LoRaMacCallbacks.GetBatteryLevel = LoRaMainCallbacks->BoardGetBatteryLevel;
LoRaMacCallbacks.GetTemperatureLevel = LoRaMainCallbacks->BoardGetTemperatureLevel;
LoRaMacCallbacks.MacProcessNotify = LoRaMainCallbacks->MacProcessNotify;
if(0U != ((1<<(lw_param_init.active_region))& (LoRaMacRegionInfo->Region)))
{
LoRaMacInitialization(&LoRaMacPrimitives, &LoRaMacCallbacks, lw_param_init.active_region);
}
else
{
APP_PRINTF("error: Region is not defined in the MW: set lorawan_conf.h accordingly\n\r");
while(1) {} /* error: Region is not defined in the MW */
}
if((lw_param_init.active_region == LORAMAC_REGION_CN470)||(lw_param_init.active_region == LORAMAC_REGION_CN470ALI))
{
uint16_t channelMask[] = {0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000};
if(lw_param_init.active_region == LORAMAC_REGION_CN470){
channelMask[0] = 0x00FF;
}
else{
channelMask[0] = 0xFF00;
}
mibReq.Type = MIB_CHANNELS_MASK;
mibReq.Param.ChannelsMask = channelMask;
LoRaMacMibSetRequestConfirm(&mibReq);
mibReq.Type = MIB_CHANNELS_DEFAULT_MASK;
mibReq.Param.ChannelsDefaultMask = channelMask;
LoRaMacMibSetRequestConfirm(&mibReq);
}
lw_config_otaa_set(lw_config.otaa);
mibReq.Type = MIB_DEV_EUI;
mibReq.Param.DevEui = lw_config.DevEui;
LoRaMacMibSetRequestConfirm(&mibReq);
mibReq.Type = MIB_JOIN_EUI;
mibReq.Param.JoinEui = lw_config.JoinEui;
LoRaMacMibSetRequestConfirm(&mibReq);
mibReq.Type = MIB_ADR;
mibReq.Param.AdrEnable = lw_param_init.adr_enable;
LoRaMacMibSetRequestConfirm(&mibReq);
mibReq.Type = MIB_PUBLIC_NETWORK;
mibReq.Param.EnablePublicNetwork = lw_param_init.enable_public_network;
LoRaMacMibSetRequestConfirm(&mibReq);
mibReq.Type = MIB_APP_KEY;
mibReq.Param.AppKey = lw_config.AppKey;
LoRaMacMibSetRequestConfirm(&mibReq);
mibReq.Type = MIB_NWK_KEY;
mibReq.Param.NwkKey = lw_config.NwkKey;
LoRaMacMibSetRequestConfirm(&mibReq);
mibReq.Type = MIB_DEVICE_CLASS;
mibReq.Param.Class = CLASS_A;
LoRaMacMibSetRequestConfirm(&mibReq);
if((lw_param_init.active_region == LORAMAC_REGION_EU868)
|| (lw_param_init.active_region == LORAMAC_REGION_RU864)
|| (lw_param_init.active_region == LORAMAC_REGION_CN779)
|| (lw_param_init.active_region == LORAMAC_REGION_EU433))
{
LoRaMacTestSetDutyCycleOn(true);
lw_config.duty_cycle = LORA_ENABLE;
}
else
{
lw_config.duty_cycle = LORA_DISABLE;
}
mibReq.Type = MIB_SYSTEM_MAX_RX_ERROR;
mibReq.Param.SystemMaxRxError = 20;
LoRaMacMibSetRequestConfirm(&mibReq);
#if ( LORAMAC_CLASSB_ACTIVE == 1 )
if (LoRaMacRegionInfo->ClassB == 1)
{
DefaultPingSlotPeriodicity = LORAWAN_DEFAULT_PING_SLOT_PERIODICITY;
}
#endif /* LORAMAC_CLASSB_ACTIVE */
/*set Mac statein Idle*/
LoRaMacStart();
}
LoRaMacStatus_t lw_join(void)
{
LoRaMacStatus_t status;
if (lw_config.otaa == LORA_ENABLE)
{
MlmeReq_t mlmeReq;
mlmeReq.Type = MLME_JOIN;
mlmeReq.Req.Join.Datarate = lw_param_init.tx_datarate;
JoinParameters = mlmeReq.Req.Join;
status = LoRaMacMlmeRequest(&mlmeReq);
}
else
{
/*no Join in abp*/
status = LORAMAC_STATUS_BUSY;
}
return status;
}
LoraFlagStatus lw_join_status(void)
{
MibRequestConfirm_t mibReq;
mibReq.Type = MIB_NETWORK_ACTIVATION;
LoRaMacMibGetRequestConfirm(&mibReq);
if(mibReq.Param.NetworkActivation == ACTIVATION_TYPE_NONE)
{
return LORA_RESET;
}
else
{
return LORA_SET;
}
}
LoRaMacStatus_t lw_current_chmask_get(LWChannel_mask_t* ch)
{
mibReq.Type = MIB_CHANNELS_MASK;
mibReq.Param.ChannelsMask = (uint16_t*)ch;
LoRaMacStatus_t sta = LoRaMacMibGetRequestConfirm(&mibReq);
if(LORAMAC_STATUS_OK == sta)
{
for(uint8_t i=0;i<6;i++)
{
ch->mask[i] = mibReq.Param.ChannelsMask[i];
}
}
return sta;
}
LoRaMacStatus_t lw_current_chmask_set(const LWChannel_mask_t* ch)
{
static bool only;
if(only == false)
{
only = true;
mibReq.Type = MIB_CHANNELS_DEFAULT_MASK;
mibReq.Param.ChannelsDefaultMask = (uint16_t*)ch;
LoRaMacMibSetRequestConfirm(&mibReq);
}
mibReq.Type = MIB_CHANNELS_MASK;
mibReq.Param.ChannelsMask = (uint16_t*)ch;
return LoRaMacMibSetRequestConfirm(&mibReq);
}
LoRaMacStatus_t lw_rxwin2_ch_set(const RxChannelParams_t* rx2_ch)
{
LoRaMacStatus_t sta;
mibReq.Type = MIB_RX2_CHANNEL;
mibReq.Param.Rx2Channel.Frequency = rx2_ch->Frequency;
mibReq.Param.Rx2Channel.Datarate = rx2_ch->Datarate;
sta = LoRaMacMibSetRequestConfirm(&mibReq);
return sta;
}
LoRaMacStatus_t lw_rxwin2_ch_get(RxChannelParams_t* rx2_ch)
{
LoRaMacStatus_t sta;
mibReq.Type = MIB_RX2_CHANNEL;
sta = LoRaMacMibGetRequestConfirm(&mibReq);
if(LORAMAC_STATUS_OK == sta)
{
*rx2_ch = mibReq.Param.Rx2Channel;
}
return sta;
}
LoRaMacStatus_t lw_adr_set(lw_state_t sta)
{
LoRaMacStatus_t n_sta=0;
mibReq.Type = MIB_ADR;
mibReq.Param.AdrEnable = sta ;
n_sta = LoRaMacMibSetRequestConfirm(&mibReq);
if(LORAMAC_STATUS_OK == n_sta){
lw_param_init.adr_enable = sta;
}
return n_sta;
}
LoRaMacStatus_t lw_send(lw_app_data_t *app_data, LoraConfirm_t IsTxConfirmed)
{
McpsReq_t mcpsReq;
LoRaMacTxInfo_t txInfo;
if(LoRaMacQueryTxPossible(app_data->size, &txInfo) != LORAMAC_STATUS_OK)
{
// Send empty frame in order to flush MAC commands
mcpsReq.Type = MCPS_UNCONFIRMED;
mcpsReq.Req.Unconfirmed.fBuffer = NULL;
mcpsReq.Req.Unconfirmed.fBufferSize = 0;
mcpsReq.Req.Unconfirmed.Datarate = lw_config_tx_datarate_get() ;
}
else
{
if (IsTxConfirmed == LORAWAN_UNCONFIRMED_MSG)
{
mcpsReq.Type = MCPS_UNCONFIRMED;
mcpsReq.Req.Unconfirmed.fPort = app_data->port;
mcpsReq.Req.Unconfirmed.fBufferSize = app_data->size;
mcpsReq.Req.Unconfirmed.fBuffer = app_data->buff;
mcpsReq.Req.Unconfirmed.Datarate = lw_config_tx_datarate_get() ;
}
else
{
mcpsReq.Type = MCPS_CONFIRMED;
mcpsReq.Req.Confirmed.fPort = app_data->port;
mcpsReq.Req.Confirmed.fBufferSize = app_data->size;
mcpsReq.Req.Confirmed.fBuffer = app_data->buff;
mcpsReq.Req.Confirmed.NbTrials = lw_confirm_retry_get();
mcpsReq.Req.Confirmed.Datarate = lw_config_tx_datarate_get() ;
}
}
return LoRaMacMcpsRequest(&mcpsReq);
}
#if ( LORAMAC_CLASSB_ACTIVE == 1 )
#if defined( USE_DEVICE_TIMING )
static LoRaMacStatus_t lw_device_time_req(void)
{
MlmeReq_t mlmeReq;
mlmeReq.Type = MLME_DEVICE_TIME;
return LoRaMacMlmeRequest(&mlmeReq);
}
#else
static LoRaMacStatus_t lw_beacon_time_req(void)
{
MlmeReq_t mlmeReq;
mlmeReq.Type = MLME_BEACON_TIMING;
return LoRaMacMlmeRequest(&mlmeReq);
}
#endif /* USE_DEVICE_TIMING */
static LoRaMacStatus_t lw_beacon_req(void)
{
MlmeReq_t mlmeReq;
mlmeReq.Type = MLME_BEACON_ACQUISITION;
return LoRaMacMlmeRequest(&mlmeReq);
}
static LoRaMacStatus_t lw_pingslot_req(void)
{
MlmeReq_t mlmeReq;
mlmeReq.Type = MLME_LINK_CHECK;
LoRaMacMlmeRequest(&mlmeReq);
mlmeReq.Type = MLME_PING_SLOT_INFO;
mlmeReq.Req.PingSlotInfo.PingSlot.Fields.Periodicity = DefaultPingSlotPeriodicity;
mlmeReq.Req.PingSlotInfo.PingSlot.Fields.RFU = 0;
return LoRaMacMlmeRequest(&mlmeReq);
}
#endif /* LORAMAC_CLASSB_ACTIVE */
LoRaMacStatus_t lw_request_class(DeviceClass_t newClass)
{
LoRaMacStatus_t Errorstatus = LORAMAC_STATUS_OK;
MibRequestConfirm_t mibReq;
DeviceClass_t currentClass;
mibReq.Type = MIB_DEVICE_CLASS;
LoRaMacMibGetRequestConfirm(&mibReq);
currentClass = mibReq.Param.Class;
/*attempt to swicth only if class update*/
if(currentClass != newClass)
{
switch(newClass)
{
case CLASS_A:
{
mibReq.Param.Class = CLASS_A;
Errorstatus = LoRaMacMibSetRequestConfirm(&mibReq);
if(Errorstatus == LORAMAC_STATUS_OK)
{
DeviceClass_t cur_class =CLASS_A;
LoRaMainCallbacks->app_events(APP_CONFIRM_ClASS_EVENT,&cur_class);
}
break;
}
case CLASS_B:
{
#if (LORAMAC_CLASSB_ACTIVE == 1)
if(currentClass != CLASS_A)
{
Errorstatus = LORAMAC_STATUS_ERROR;
}
/*switch is not instantanuous*/
Errorstatus = lw_beacon_req();
#else
APP_PRINTF("warning: LORAMAC_CLASSB_ACTIVE has not been defined at compilation\n\r");
#endif /* LORAMAC_CLASSB_ACTIVE */
break;
}
case CLASS_C:
{
if (currentClass != CLASS_A)
{
Errorstatus = LORAMAC_STATUS_ERROR;
}
/*switch is instantanuous*/
mibReq.Param.Class = CLASS_C;
Errorstatus = LoRaMacMibSetRequestConfirm(&mibReq);
if(Errorstatus == LORAMAC_STATUS_OK)
{
DeviceClass_t cur_class =CLASS_C;
LoRaMainCallbacks->app_events(APP_CONFIRM_ClASS_EVENT,&cur_class);
}
break;
}
default:
break;
}
}
return Errorstatus;
}
DeviceClass_t lw_get_current_class(void)
{
MibRequestConfirm_t mibReq;
mibReq.Type = MIB_DEVICE_CLASS;
LoRaMacMibGetRequestConfirm(&mibReq);
return mibReq.Param.Class;
}
void lw_config_otaa_set(lw_state_t otaa)
{
lw_config.otaa = otaa;
if (lw_config.otaa == LORA_ENABLE)
{
APP_PPRINTF("OTAA Mode enabled\n\r");
APP_PPRINTF("DevEui= %02X-%02X-%02X-%02X-%02X-%02X-%02X-%02X\n\r", HEX8(lw_config.DevEui));
APP_PPRINTF("JoinEui= %02X-%02X-%02X-%02X-%02X-%02X-%02X-%02X\n\r", HEX8(lw_config.JoinEui));
APP_PPRINTF("AppKey= %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X\n\r", HEX16(lw_config.AppKey));
mibReq.Type = MIB_NETWORK_ACTIVATION;
mibReq.Param.NetworkActivation = ACTIVATION_TYPE_NONE;
LoRaMacMibSetRequestConfirm(&mibReq);
}
else
{
APP_PPRINTF("ABP Mode enabled\n\r");
APP_PPRINTF("DevEui= %02X-%02X-%02X-%02X-%02X-%02X-%02X-%02X\n\r", HEX8(lw_config.DevEui));
APP_PPRINTF("DevAdd= %08X\n\r", lw_param_init.dev_addr) ;
APP_PPRINTF("NwkSKey= %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X\n\r", HEX16(lw_config.NwkSEncKey));
APP_PPRINTF("AppSKey= %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X\n\r", HEX16(lw_config.AppSKey));
mibReq.Type = MIB_NET_ID;
mibReq.Param.NetID = LORAWAN_NETWORK_ID;
LoRaMacMibSetRequestConfirm(&mibReq);
mibReq.Type = MIB_DEV_ADDR;
mibReq.Param.DevAddr = lw_param_init.dev_addr;
LoRaMacMibSetRequestConfirm(&mibReq);
mibReq.Type = MIB_F_NWK_S_INT_KEY;
mibReq.Param.FNwkSIntKey = lw_config.FNwkSIntKey;
LoRaMacMibSetRequestConfirm(&mibReq);
mibReq.Type = MIB_S_NWK_S_INT_KEY;
mibReq.Param.SNwkSIntKey = lw_config.SNwkSIntKey;
LoRaMacMibSetRequestConfirm(&mibReq);
mibReq.Type = MIB_NWK_S_ENC_KEY;
mibReq.Param.NwkSEncKey = lw_config.NwkSEncKey;
LoRaMacMibSetRequestConfirm(&mibReq);
mibReq.Type = MIB_APP_S_KEY;
mibReq.Param.AppSKey = lw_config.AppSKey;
LoRaMacMibSetRequestConfirm(&mibReq);
mibReq.Type = MIB_NETWORK_ACTIVATION;
mibReq.Param.NetworkActivation = ACTIVATION_TYPE_ABP;
LoRaMacMibSetRequestConfirm(&mibReq);
// Enable legacy mode to operate according to LoRaWAN Spec. 1.0.3
Version_t abpLrWanVersion;
abpLrWanVersion.Fields.Major = 1;
abpLrWanVersion.Fields.Minor = 0;
abpLrWanVersion.Fields.Revision = 3;
abpLrWanVersion.Fields.Rfu = 0;
mibReq.Type = MIB_ABP_LORAWAN_VERSION;
mibReq.Param.AbpLrWanVersion = abpLrWanVersion;
LoRaMacMibSetRequestConfirm(&mibReq);
}
}
lw_state_t lw_config_otaa_get(void)
{
return lw_config.otaa;
}
void lw_confirm_retry_set(uint8_t retry)
{
lw_param_init.confirm_retry = retry;
}
uint8_t lw_confirm_retry_get(void)
{
return lw_param_init.confirm_retry;
}
void lw_config_duty_cycle_set(lw_state_t duty_cycle)
{
lw_config.duty_cycle = duty_cycle;
LoRaMacTestSetDutyCycleOn((duty_cycle == LORA_ENABLE) ? 1 : 0);
}
lw_state_t lw_config_duty_cycle_get(void)
{
return lw_config.duty_cycle;
}
uint8_t *lw_config_deveui_get(void)
{
return lw_config.DevEui;
}
uint8_t *lw_config_joineui_get(void)
{
return lw_config.JoinEui;
}
void lw_config_joineui_set(uint8_t joineui[8])
{
UTIL_MEM_cpy_8(lw_config.JoinEui, joineui, sizeof(lw_config.JoinEui));
mibReq.Type = MIB_JOIN_EUI;
mibReq.Param.JoinEui = lw_config.JoinEui;
LoRaMacMibSetRequestConfirm(&mibReq);
}
uint8_t *lw_config_appkey_get(void)
{
return lw_config.AppKey;
}
void lw_config_appkey_set(uint8_t appkey[16])
{
UTIL_MEM_cpy_8(lw_config.AppKey, appkey, sizeof(lw_config.AppKey));
UTIL_MEM_cpy_8(lw_config.NwkKey, appkey, sizeof(lw_config.NwkKey));
mibReq.Type = MIB_APP_KEY;
mibReq.Param.AppKey = lw_config.AppKey;
LoRaMacMibSetRequestConfirm(&mibReq);
mibReq.Type = MIB_NWK_KEY;
mibReq.Param.NwkKey = lw_config.NwkKey;
LoRaMacMibSetRequestConfirm(&mibReq);
}
void lw_config_reqack_set(LoraConfirm_t reqack)
{
lw_config.ReqAck = reqack;
}
LoraConfirm_t lw_config_reqack_get(void)
{
return lw_config.ReqAck;
}
int8_t lw_config_snr_get(void)
{
return lw_config.Snr;
}
int16_t lw_config_rssi_get(void)
{
return lw_config.Rssi;
}
void lw_config_tx_datarate_set(int8_t TxDataRate)
{
lw_config.TxDatarate = TxDataRate;
}
int8_t lw_config_tx_datarate_get(void)
{
return lw_config.TxDatarate;
}
LoRaMacRegion_t lora_region_get(void)
{
return lw_param_init.active_region;
}
#if ( LORAMAC_CLASSB_ACTIVE == 1 )
LoRaMacClassBNvmCtx_t* lw_get_classBCtx(void)
{
mibReq.Type = MIB_NVM_CTXS;
LoRaMacMibGetRequestConfirm( &mibReq );
return ( LoRaMacClassBNvmCtx_t*) mibReq.Param.Contexts->ClassBNvmCtx;
}
uint8_t lw_get_pingslot_periodicity(void)
{
return DefaultPingSlotPeriodicity;
}
void lw_set_pingslot_periodicity(uint8_t PingSlotPeriodicity)
{
DefaultPingSlotPeriodicity= PingSlotPeriodicity;
}
#endif /* LORAMAC_CLASSB_ACTIVE */
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/

View File

@@ -0,0 +1,407 @@
/**
******************************************************************************
* @file lora.h
* @author MCD Application Team
* @brief lora API to drive the lora state Machine
******************************************************************************
* @attention
*
* <h2><center>&copy; Copyright (c) 2019 STMicroelectronics.
* All rights reserved.</center></h2>
*
* This software component is licensed by ST under BSD 3-Clause license,
* the "License"; You may not use this file except in compliance with the
* License. You may obtain a copy of the License at:
* opensource.org/licenses/BSD-3-Clause
*
******************************************************************************
*/
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef __LORA_H__
#define __LORA_H__
#ifdef __cplusplus
extern "C" {
#endif
/* Includes ------------------------------------------------------------------*/
#include "Commissioning.h"
#include "LoRaMac.h"
#include "app_conf.h"
#if defined (LORAMAC_CLASSB_ACTIVE) && ( LORAMAC_CLASSB_ACTIVE == 1 )
#include "LoRaMacClassB.h"
#elif !defined (LORAMAC_CLASSB_ACTIVE)
#error LORAMAC_CLASSB_ACTIVE not defined
#endif /* LORAMAC_CLASSB_ACTIVE */
#include "region/Region.h"
/* Exported constants --------------------------------------------------------*/
/*!
* LoRaWAN confirmed messages
*/
#define LORAWAN_ADR_ON 1
#define LORAWAN_ADR_OFF 0
/* Exported types ------------------------------------------------------------*/
/*!
* Application Data structure
*/
typedef struct
{
/*point to the LoRa App data buffer*/
uint8_t *buff;
/*LoRa App data buffer size*/
uint8_t size;
/*Port on which the LoRa App is data is sent/ received*/
uint8_t port;
uint8_t ack;
uint8_t fpending;
} lw_app_data_t;
typedef enum
{
LORA_RESET = 0,
LORA_SET = !LORA_RESET
} LoraFlagStatus;
typedef enum
{
LORA_DISABLE = 0,
LORA_ENABLE = !LORA_DISABLE
} lw_state_t;
typedef enum
{
LORA_ERROR = -1,
LORA_SUCCESS = 0
} LoraErrorStatus;
typedef enum
{
LORAWAN_UNCONFIRMED_MSG = 0,
LORAWAN_CONFIRMED_MSG = !LORAWAN_UNCONFIRMED_MSG
} LoraConfirm_t;
typedef enum
{
LORA_TRUE = 0,
LORA_FALSE = !LORA_TRUE
} LoraBool_t;
typedef enum
{
APP_RX_EVENT,
APP_JOINED_EVENT,
APP_CONFIRM_ClASS_EVENT,
APP_TX_DONE_EVENT,
}APP_EVENT_t;
/* Lora Main callbacks*/
typedef struct sLoRaMainCallback
{
/*!
* @brief mac event callback
*
* @retval null
*/
void (*app_events)(APP_EVENT_t evt,const void* param);
/*!
*\brief Will be called each time a Radio IRQ is handled by the MAC
* layer.
*
*\warning Runs in a IRQ context. Should only change variables state.
*/
void (*MacProcessNotify)(void);
/*!
* @brief Get the current battery level
*
* @retval value battery level ( 0: very low, 254: fully charged )
*/
uint8_t (*BoardGetBatteryLevel)(void);
/*!
* \brief Get the current temperature
*
* \retval value temperature in degreeCelcius( q7.8 )
*/
uint16_t (*BoardGetTemperatureLevel)(void);
/*!
* @brief Gets the board 64 bits unique ID
*
* @param [IN] id Pointer to an array that will contain the Unique ID
*/
void (*BoardGetUniqueId)(uint8_t *id);
/*!
* Returns a pseudo random seed generated using the MCU Unique ID
*
* @retval seed Generated pseudo random seed
*/
uint32_t (*BoardGetRandomSeed)(void);
} LoRaMainCallback_t;
typedef struct
{
uint16_t mask[6];
}LWChannel_mask_t;
/* External variables --------------------------------------------------------*/
/* Exported macros -----------------------------------------------------------*/
/* Exported functions ------------------------------------------------------- */
/**
* @brief Lora Initialisation
* @param [IN] LoRaMainCallback_t
* @param [IN] application parmaters
* @retval none
*/
void lw_init(LoRaMainCallback_t *callbacks);
/**
* @brief run Lora classA state Machine
* @param [IN] none
* @retval none
*/
LoRaMacStatus_t lw_send(lw_app_data_t *AppData, LoraConfirm_t IsTxConfirmed);
/**
* @brief Join a Lora Network in classA
* @Note if the device is ABP, this is a pass through functon
* @param [IN] none
* @retval none
*/
LoRaMacStatus_t lw_join(void);
/**
* @brief Check whether the Device is joined to the network
* @param [IN] none
* @retval returns LORA_SET if joined
*/
LoraFlagStatus lw_join_status(void);
/*=====================================================================
if you want to use the Api below , you must call them after LORA_Init
because it has been made Initialization configuration
======================================================================*/
/**
* @brief Enable or Disable ADR
* @param [IN] lw_state_t
* @retval returns req state
*/
LoRaMacStatus_t lw_adr_set(lw_state_t sta);
/**
* @brief uplink confirm retry times setting
* @param [IN] times
* @retval returns req state
*/
void lw_confirm_retry_set(uint8_t retry);
/**
* @brief return uplink confirm retry times
* @param [IN] null
* @retval times
*/
uint8_t lw_confirm_retry_get(void);
/**
* @brief set the currnt chmask
* @param [IN] LWChannel_mask_t
* @retval status
*/
LoRaMacStatus_t lw_current_chmask_set(const LWChannel_mask_t* ch);
/**
* @brief return the currnt chmask
* @param [IN] LWChannel_mask_t
* @retval status
*/
LoRaMacStatus_t lw_current_chmask_get(LWChannel_mask_t* ch);
/**
* @brief set Rx win2 datarate and freq , there are default configuration in region parameter
* @param [IN] RxChannelParams_t
* @retval status
*/
LoRaMacStatus_t lw_rxwin2_ch_set(const RxChannelParams_t* rx2_ch);
/**
* @brief get Rx win2 datarate and freq
* @param [IN] RxChannelParams_t
* @retval status
*/
LoRaMacStatus_t lw_rxwin2_ch_get(RxChannelParams_t* rx2_ch);
/**
* @brief change Lora Class
* @Note callback LORA_ConfirmClass informs upper layer that the change has occured
* @Note Only switch from class A to class B/C OR from class B/C to class A is allowed
* @Attention can be calld only in LORA_ClassSwitchSlot or LORA_RxData callbacks
* @param [IN] DeviceClass_t NewClass
* @retval LoraErrorStatus
*/
LoRaMacStatus_t lw_request_class(DeviceClass_t newClass);
/**
* @brief get the current Lora Class
* @param [IN] DeviceClass_t NewClass
* @retval None
*/
DeviceClass_t lw_get_current_class(void);
/**
* @brief Set join activation process: OTAA vs ABP
* @param Over The Air Activation status to set: enable or disable
* @retval None
*/
void lw_config_otaa_set(lw_state_t otaa);
/**
* @brief Get join activation process: OTAA vs ABP
* @param None
* @retval ENABLE if OTAA is used, DISABLE if ABP is used
*/
lw_state_t lw_config_otaa_get(void);
/**
* @brief Set duty cycle: ENABLE or DISABLE
* @param Duty cycle to set: enable or disable
* @retval None
*/
void lw_config_duty_cycle_set(lw_state_t duty_cycle);
/**
* @brief Get Duty cycle: OTAA vs ABP
* @param None
* @retval ENABLE / DISABLE
*/
lw_state_t lw_config_duty_cycle_get(void);
/**
* @brief Get Device EUI
* @param None
* @retval DevEUI
*/
uint8_t *lw_config_deveui_get(void);
/**
* @brief Get Join Eui
* @param None
* @retval JoinEUI
*/
uint8_t *lw_config_joineui_get(void);
/**
* @brief Set Join Eui
* @param JoinEUI
* @retval Nonoe
*/
void lw_config_joineui_set(uint8_t joineui[8]);
/**
* @brief Get Application Key
* @param None
* @retval AppKey
*/
uint8_t *lw_config_appkey_get(void);
/**
* @brief Set Application Key
* @param AppKey
* @retval None
*/
void lw_config_appkey_set(uint8_t appkey[16]);
/**
* @brief Set whether or not acknowledgement is required
* @param ENABLE or DISABLE
* @retval None
*/
void lw_config_reqack_set(LoraConfirm_t reqack);
/**
* @brief Get whether or not acknowledgement is required
* @param None
* @retval ENABLE or DISABLE
*/
LoraConfirm_t lw_config_reqack_get(void);
/**
* @brief Get the SNR of the last received data
* @param None
* @retval SNR
*/
int8_t lw_config_snr_get(void);
/**
* @brief Get the RSSI of the last received data
* @param None
* @retval RSSI
*/
int16_t lw_config_rssi_get(void);
/**
* @brief set tx datarate
* @param None
* @retval The application port
*/
void lw_config_tx_datarate_set(int8_t TxDataRate);
/**
* @brief get tx datarate
* @param None
* @retval tx datarate
*/
int8_t lw_config_tx_datarate_get(void);
/**
* @brief get LoRaMac region
* @param None
* @retval LoRaMac region
*/
LoRaMacRegion_t lw_region_get(void);
#if defined (LORAMAC_CLASSB_ACTIVE) && ( LORAMAC_CLASSB_ACTIVE == 1 )
LoRaMacClassBNvmCtx_t* LORA_Get_ClassBCtx(void);
uint8_t LORA_Get_PingSlotPeriodicity(void);
void LORA_Set_PingSlotPeriodicity(uint8_t PingSlotPeriodicity);
#elif !defined (LORAMAC_CLASSB_ACTIVE)
#error LORAMAC_CLASSB_ACTIVE not defined
#endif
#ifdef __cplusplus
}
#endif
#ifdef __cplusplus
}
#endif
#endif /*__LORA_H__*/
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/

View File

@@ -0,0 +1,96 @@
/**
******************************************************************************
* @file lorawan_info.c
* @author MCD Application Team
* @brief To give info to the application about LoraWAN configuration
******************************************************************************
* @attention
*
* <h2><center>&copy; Copyright (c) 2019 STMicroelectronics.
* All rights reserved.</center></h2>
*
* This software component is licensed by ST under BSD 3-Clause license,
* the "License"; You may not use this file except in compliance with the
* License. You may obtain a copy of the License at:
* opensource.org/licenses/BSD-3-Clause
*
******************************************************************************
*/
/* Includes ------------------------------------------------------------------*/
#include "lorawan_info.h"
#include "LoRaMac.h"
/* Private typedef -----------------------------------------------------------*/
/* Private define ------------------------------------------------------------*/
/* Private macro -------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/
/* Private function prototypes -----------------------------------------------*/
/* Exported variables --------------------------------------------------------*/
LoRaMacInfo_t LoRaMacInfoTable;
/* Exported functions --------------------------------------------------------*/
/**
* @brief initialises the LoraMacInfo capabilities table
* @param none
* @retval none
*/
void LoraMacInfo_Init(void)
{
LoRaMacInfoTable.Region = 0;
#ifdef REGION_AS923
LoRaMacInfoTable.Region |= (1<<LORAMAC_REGION_AS923) ;
#endif
#ifdef REGION_AU915
LoRaMacInfoTable.Region |= (1<<LORAMAC_REGION_AU915) ;
#endif
#ifdef REGION_CN470
LoRaMacInfoTable.Region |= (1<<LORAMAC_REGION_CN470) ;
#endif
#ifdef REGION_CN470ALI
LoRaMacInfoTable.Region |= (1<<LORAMAC_REGION_CN470ALI);
#endif
#ifdef REGION_CN779
LoRaMacInfoTable.Region |= (1<<LORAMAC_REGION_CN779) ;
#endif
#ifdef REGION_EU433
LoRaMacInfoTable.Region |= (1<<LORAMAC_REGION_EU433) ;
#endif
#ifdef REGION_EU868
LoRaMacInfoTable.Region |= (1<<LORAMAC_REGION_EU868) ;
#endif
#ifdef REGION_KR920
LoRaMacInfoTable.Region |= (1<<LORAMAC_REGION_KR920) ;
#endif
#ifdef REGION_IN865
LoRaMacInfoTable.Region |= (1<<LORAMAC_REGION_IN865) ;
#endif
#ifdef REGION_US915
LoRaMacInfoTable.Region |= (1<<LORAMAC_REGION_US915) ;
#endif
#ifdef REGION_RU864
LoRaMacInfoTable.Region |= (1<<LORAMAC_REGION_RU864) ;
#endif
#ifdef LORAMAC_CLASSB_ENABLED
LoRaMacInfoTable.ClassB = 1;
#else
LoRaMacInfoTable.ClassB = 0;
#endif
return;
}
/**
* @brief returns the pointer to the LoraMacInfo capabilities table
* @param none
* @retval LoRaMacInfoTable pointer
*/
LoRaMacInfo_t* LoraMacInfo_GetPtr(void)
{
return &LoRaMacInfoTable;
}
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/

View File

@@ -0,0 +1,67 @@
/**
******************************************************************************
* @file lorawan_info.h
* @author MCD Application Team
* @brief To give info to the application about LoraWAN configuration
******************************************************************************
* @attention
*
* <h2><center>&copy; Copyright (c) 2019 STMicroelectronics.
* All rights reserved.</center></h2>
*
* This software component is licensed by ST under BSD 3-Clause license,
* the "License"; You may not use this file except in compliance with the
* License. You may obtain a copy of the License at:
* opensource.org/licenses/BSD-3-Clause
*
******************************************************************************
*/
#ifndef __LORAWAN_INFO_H__
#define __LORAWAN_INFO_H__
#ifdef __cplusplus
extern "C" {
#endif
/* Includes ------------------------------------------------------------------*/
#include <stdint.h>
/* Exported constants --------------------------------------------------------*/
/* Exported types ------------------------------------------------------------*/
/*!
* To give info to the application about LoraWAN capability
* it can depend how it has been compiled (e.g. compiled regions ...)
* Params should be better uint32_t foe easier alignment with info_table concept
*/
typedef struct
{
uint32_t Region; /*!< Combination of regions compiled on MW */
uint32_t ClassB; /*!< 0: not compiled in Mw, 1 : compiled in MW */
}LoRaMacInfo_t;
/* External variables --------------------------------------------------------*/
/* Exported macros -----------------------------------------------------------*/
/* Exported functions ------------------------------------------------------- */
/**
* @brief initialises the LoraMacInfo table
* @param none
* @retval none
*/
void LoraMacInfo_Init(void);
/**
* @brief returns the pointer to the LoraMacInfo table
* @param none
* @retval LoRaMacInfoTable pointer
*/
LoRaMacInfo_t* LoraMacInfo_GetPtr(void);
#ifdef __cplusplus
}
#endif
#endif // __LORAWAN_INFO_H__

View File

@@ -0,0 +1,56 @@
/**
******************************************************************************
* @file app_conf_template.h
* @author MCD Application Team
* @brief applic configuration, e.g. : debug, trace, low power, sensors
* @note this is a template: the app_conf.h shall be defined in the Project/...
******************************************************************************
* @attention
*
* <h2><center>&copy; Copyright (c) 2019 STMicroelectronics.
* All rights reserved.</center></h2>
*
* This software component is licensed by ST under BSD 3-Clause license,
* the "License"; You may not use this file except in compliance with the
* License. You may obtain a copy of the License at:
* opensource.org/licenses/BSD-3-Clause
*
******************************************************************************
*/
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef __APP_CONF_H__
#define __APP_CONF_H__
#ifdef __cplusplus
extern "C" {
#endif
/* Includes ------------------------------------------------------------------*/
/* Exported types ------------------------------------------------------------*/
/* Exported constants --------------------------------------------------------*/
/* LoraWAN application configuration (Mw is configured by lorawan_conf.h) */
#define ACTIVE_REGION LORAMAC_REGION_EU868
#define HYBRID_ENABLED 0
#define LORAMAC_CLASSB_ACTIVE 0 /* 0 if not active, 1 if active */
/* Enable trace logs. Note verbose level can be selected in app_system.h */
#define APP_LOG_ENABLED 1
#define DEBUGGER_ON 0 /* if ON (=1) it enables the debbugger plus 4 dgb pins */
/* if OFF (=0) the debugger is OFF (lower consumption) */
/* External variables --------------------------------------------------------*/
/* Exported macros -----------------------------------------------------------*/
/* Defines -------------------------------------------------------------------*/
/* Exported functions ------------------------------------------------------- */
#ifdef __cplusplus
}
#endif
#endif /* __APP_CONF_H__ */
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/

View File

@@ -0,0 +1,62 @@
/**
******************************************************************************
* @file app_system_template.h
* @author MCD Application Team
* @brief function prototypes for app_system.c file
* @note this is a template: the app_conf.h shall be defined in the Project/...
******************************************************************************
* @attention
*
* <h2><center>&copy; Copyright (c) 2019 STMicroelectronics.
* All rights reserved.</center></h2>
*
* This software component is licensed by ST under BSD 3-Clause license,
* the "License"; You may not use this file except in compliance with the
* License. You may obtain a copy of the License at:
* opensource.org/licenses/BSD-3-Clause
*
******************************************************************************
*/
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef __APP_SYSTEM_H__
#define __APP_SYSTEM_H__
#ifdef __cplusplus
extern "C" {
#endif
/* Includes ------------------------------------------------------------------*/
#include <stdint.h>
#include "app_conf.h"
#include "trace.h"
/* Exported types ------------------------------------------------------------*/
/* Exported constants --------------------------------------------------------*/
#define VERBOSE_LEVEL VLEVEL_L
/* External variables --------------------------------------------------------*/
/* Exported macros -----------------------------------------------------------*/
#define APP_PPRINTF(...) do{ } while( 0!= TraceSend(0, 0, __VA_ARGS__) ) //Polling Mode
#define APP_TPRINTF(...) do{ {TraceSend(1, 0, __VA_ARGS__);} }while(0); //with timestamp
#define APP_PRINTF(...) do{ {TraceSend(0, 0, __VA_ARGS__);} }while(0);
#if defined (APP_LOG_ENABLED) && (APP_LOG_ENABLED == 1)
#define APP_LOG(TS,VL,...) do{ {TraceSend(TS, VL, __VA_ARGS__);} }while(0);
#elif defined (APP_LOG_ENABLED) && (APP_LOG_ENABLED == 0) /* APP_LOG disabled */
#define APP_LOG(TS,VL,...)
#else
#error "APP_LOG_ENABLED not defined or out of range <0,1>"
#endif
/* Defines -------------------------------------------------------------------*/
/* Exported functions ------------------------------------------------------- */
#ifdef __cplusplus
}
#endif
#endif /* __APP_SYSTEM_H__ */
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/

View File

@@ -0,0 +1,417 @@
/******************************************************************************
* @file lora-test.c
* @author MCD Application Team
* @brief lora API to drive the lora state Machine
******************************************************************************
* @attention
*
* <h2><center>&copy; Copyright (c) 2019 STMicroelectronics.
* All rights reserved.</center></h2>
*
* This software component is licensed by ST under BSD 3-Clause license,
* the "License"; You may not use this file except in compliance with the
* License. You may obtain a copy of the License at:
* opensource.org/licenses/BSD-3-Clause
*
******************************************************************************
*/
/* Includes ------------------------------------------------------------------*/
#include "stddef.h"
//#include "lorawan_conf.h" /* Don't remove: needed for LORAMAC_CLASSB_ENABLED */
//#include "mw_log_conf.h"
#include "LoRaMac.h"
#include "LoRaMacTest.h"
#include "lora.h"
/* Private typedef -----------------------------------------------------------*/
typedef struct ComplianceTest_s
{
bool Running;
uint8_t State;
LoraConfirm_t IsTxConfirmed;
uint8_t DataBufferSize;
uint8_t DataBuffer[242]; /* max possible payload */
uint16_t DownLinkCounter;
bool LinkCheck;
uint8_t DemodMargin;
uint8_t NbGateways;
} ComplianceTest_t;
typedef enum
{
CERTIF_TX_PROCESS = 0,
CERTIF_RX_PROCESS
} requestProcess_t;
/* Private define ------------------------------------------------------------*/
#define TEST_TX_DUTYCYCLE 5000
/* Private variables ---------------------------------------------------------*/
static requestProcess_t requested_process_id;
/*!
* Timer to handle the application data transmission duty cycle
*/
static TimerEvent_t CertifTxNextPacketTimer;
static ComplianceTest_t certifParam;
static LoraConfirm_t IsTxConfirmed;
static bool AdrEnableInit;
static McpsIndication_t *CertifMcpsIndication;
static MlmeReqJoin_t *CertifJoinParameters;
/* Private functions ---------------------------------------------------------*/
static bool CERTIF_running(void);
static void CERTIF_DownLinkIncrement(void);
static void CERTIF_linkCheck(MlmeConfirm_t *mlmeConfirm);
static void CERTIF_rx_request(McpsIndication_t *mcpsIndication, MlmeReqJoin_t *JoinParameters);
static void CERTIF_rx(McpsIndication_t *mcpsIndication, MlmeReqJoin_t *JoinParameters);
static bool CERTIF_tx(void);
static void OnCertifTxNextPacketTimerEvent(void *context);
static void (*CertifProcessNotify)(void);
static LoRaCertifCallback_t certifCb =
{
CERTIF_running,
CERTIF_DownLinkIncrement,
CERTIF_linkCheck,
CERTIF_rx_request,
};
/* Exported functions definition---------------------------------------------------------*/
void CERTIF_Init(void (*CERTIF_ProcessNotify)(void))
{
/*initialises Callback into the Lora.c layer*/
LORA_TestInit(&certifCb);
/*Register TestProcessNotify callback*/
CertifProcessNotify = CERTIF_ProcessNotify;
}
void CERTIF_Process(void)
{
switch (requested_process_id)
{
case CERTIF_TX_PROCESS:
CERTIF_tx();
break;
case CERTIF_RX_PROCESS:
CERTIF_rx(CertifMcpsIndication, CertifJoinParameters);
break;
default:
break;
}
}
static bool CERTIF_running(void)
{
return certifParam.Running;
}
static void CERTIF_DownLinkIncrement(void)
{
certifParam.DownLinkCounter++;
}
static void CERTIF_linkCheck(MlmeConfirm_t *mlmeConfirm)
{
certifParam.LinkCheck = true;
certifParam.DemodMargin = mlmeConfirm->DemodMargin;
certifParam.NbGateways = mlmeConfirm->NbGateways;
}
static bool CERTIF_tx(void)
{
McpsReq_t mcpsReq;
LoRaMacTxInfo_t txInfo;
if (certifParam.LinkCheck == true)
{
certifParam.LinkCheck = false;
certifParam.DataBufferSize = 3;
certifParam.DataBuffer[0] = 5;
certifParam.DataBuffer[1] = certifParam.DemodMargin;
certifParam.DataBuffer[2] = certifParam.NbGateways;
certifParam.State = 1;
}
else
{
switch (certifParam.State)
{
case 4:
certifParam.State = 1;
break;
case 1:
certifParam.DataBufferSize = 2;
certifParam.DataBuffer[0] = certifParam.DownLinkCounter >> 8;
certifParam.DataBuffer[1] = certifParam.DownLinkCounter;
break;
}
}
if (LoRaMacQueryTxPossible(certifParam.DataBufferSize, &txInfo) != LORAMAC_STATUS_OK)
{
// Send empty frame in order to flush MAC commands
mcpsReq.Type = MCPS_UNCONFIRMED;
mcpsReq.Req.Unconfirmed.fBuffer = NULL;
mcpsReq.Req.Unconfirmed.fBufferSize = 0;
mcpsReq.Req.Unconfirmed.Datarate = DR_0;
}
else
{
if (IsTxConfirmed == LORAWAN_UNCONFIRMED_MSG)
{
mcpsReq.Type = MCPS_UNCONFIRMED;
mcpsReq.Req.Unconfirmed.fPort = CERTIF_PORT;
mcpsReq.Req.Unconfirmed.fBufferSize = certifParam.DataBufferSize;
mcpsReq.Req.Unconfirmed.fBuffer = &(certifParam.DataBuffer);
mcpsReq.Req.Unconfirmed.Datarate = DR_0;
}
else
{
mcpsReq.Type = MCPS_CONFIRMED;
mcpsReq.Req.Confirmed.fPort = CERTIF_PORT;
mcpsReq.Req.Confirmed.fBufferSize = certifParam.DataBufferSize;
mcpsReq.Req.Confirmed.fBuffer = &(certifParam.DataBuffer);
mcpsReq.Req.Confirmed.NbTrials = 8;
mcpsReq.Req.Confirmed.Datarate = DR_0;
}
}
/*cerification test on-going*/
TimerStart(&CertifTxNextPacketTimer);
if (LoRaMacMcpsRequest(&mcpsReq) == LORAMAC_STATUS_OK)
{
return false;
}
return true;
}
static void CERTIF_rx_request(McpsIndication_t *mcpsIndication, MlmeReqJoin_t *JoinParameters)
{
CertifMcpsIndication = mcpsIndication;
CertifJoinParameters = JoinParameters;
requested_process_id = CERTIF_RX_PROCESS;
CertifProcessNotify();
}
static void CERTIF_rx(McpsIndication_t *mcpsIndication, MlmeReqJoin_t *JoinParameters)
{
if (certifParam.Running == false)
{
// Check compliance test enable command (i)
if ((mcpsIndication->BufferSize == 4) &&
(mcpsIndication->Buffer[0] == 0x01) &&
(mcpsIndication->Buffer[1] == 0x01) &&
(mcpsIndication->Buffer[2] == 0x01) &&
(mcpsIndication->Buffer[3] == 0x01))
{
MibRequestConfirm_t mibReq;
IsTxConfirmed = LORAWAN_UNCONFIRMED_MSG;
certifParam.DataBufferSize = 2;
certifParam.DownLinkCounter = 0;
certifParam.LinkCheck = false;
certifParam.DemodMargin = 0;
certifParam.NbGateways = 0;
certifParam.Running = true;
certifParam.State = 1;
mibReq.Type = MIB_ADR;
LoRaMacMibGetRequestConfirm(&mibReq);
AdrEnableInit = mibReq.Param.AdrEnable;
mibReq.Type = MIB_ADR;
mibReq.Param.AdrEnable = true;
LoRaMacMibSetRequestConfirm(&mibReq);
if ( (ACTIVE_REGION == LORAMAC_REGION_EU868)
|| (ACTIVE_REGION == LORAMAC_REGION_RU864)
|| (ACTIVE_REGION == LORAMAC_REGION_CN779)
|| (ACTIVE_REGION == LORAMAC_REGION_EU433))
{
LoRaMacTestSetDutyCycleOn(false);
}
TimerInit(&CertifTxNextPacketTimer, OnCertifTxNextPacketTimerEvent);
TimerSetValue(&CertifTxNextPacketTimer, TEST_TX_DUTYCYCLE);
/*confirm test mode activation */
CERTIF_tx();
}
}
else
{
certifParam.State = mcpsIndication->Buffer[0];
switch (certifParam.State)
{
case 0: // Check compliance test disable command (ii)
{
certifParam.DownLinkCounter = 0;
certifParam.Running = false;
MibRequestConfirm_t mibReq;
mibReq.Type = MIB_ADR;
mibReq.Param.AdrEnable = AdrEnableInit;
LoRaMacMibSetRequestConfirm(&mibReq);
if ( (ACTIVE_REGION == LORAMAC_REGION_EU868)
|| (ACTIVE_REGION == LORAMAC_REGION_RU864)
|| (ACTIVE_REGION == LORAMAC_REGION_CN779)
|| (ACTIVE_REGION == LORAMAC_REGION_EU433))
{
LoRaMacTestSetDutyCycleOn(true);
}
break;
}
case 1: // (iii, iv)
certifParam.DataBufferSize = 2;
break;
case 2: // Enable confirmed messages (v)
IsTxConfirmed = LORAWAN_CONFIRMED_MSG;
certifParam.State = 1;
break;
case 3: // Disable confirmed messages (vi)
IsTxConfirmed = LORAWAN_UNCONFIRMED_MSG;
certifParam.State = 1;
break;
case 4: // (vii)
certifParam.DataBufferSize = mcpsIndication->BufferSize;
certifParam.DataBuffer[0] = 4;
for (uint8_t i = 1; i < certifParam.DataBufferSize; i++)
{
certifParam.DataBuffer[i] = mcpsIndication->Buffer[i] + 1;
}
break;
case 5: // (viii)
{
MlmeReq_t mlmeReq;
mlmeReq.Type = MLME_LINK_CHECK;
LoRaMacMlmeRequest(&mlmeReq);
break;
}
case 6: // (ix)
{
MlmeReq_t mlmeReq;
// Disable TestMode and revert back to normal operation
certifParam.DownLinkCounter = 0;
certifParam.Running = false;
MibRequestConfirm_t mibReq;
mibReq.Type = MIB_ADR;
mibReq.Param.AdrEnable = AdrEnableInit;
LoRaMacMibSetRequestConfirm(&mibReq);
mlmeReq.Type = MLME_JOIN;
mlmeReq.Req.Join = *JoinParameters;
LoRaMacMlmeRequest(&mlmeReq);
break;
}
case 7: // (x)
{
if (mcpsIndication->BufferSize == 3)
{
MlmeReq_t mlmeReq;
mlmeReq.Type = MLME_TXCW;
mlmeReq.Req.TxCw.Timeout = (uint16_t)((mcpsIndication->Buffer[1] << 8) | mcpsIndication->Buffer[2]);
LoRaMacMlmeRequest(&mlmeReq);
}
else if (mcpsIndication->BufferSize == 7)
{
MlmeReq_t mlmeReq;
mlmeReq.Type = MLME_TXCW_1;
mlmeReq.Req.TxCw.Timeout = (uint16_t)((mcpsIndication->Buffer[1] << 8) | mcpsIndication->Buffer[2]);
mlmeReq.Req.TxCw.Frequency = (uint32_t)((mcpsIndication->Buffer[3] << 16) | (mcpsIndication->Buffer[4] << 8) | mcpsIndication->Buffer[5]) * 100;
mlmeReq.Req.TxCw.Power = mcpsIndication->Buffer[6];
LoRaMacMlmeRequest(&mlmeReq);
}
certifParam.State = 1;
break;
}
case 8: // Send DeviceTimeReq
{
MlmeReq_t mlmeReq;
mlmeReq.Type = MLME_DEVICE_TIME;
LoRaMacMlmeRequest(&mlmeReq);
break;
}
#if defined (LORAMAC_CLASSB_ACTIVE) && ( LORAMAC_CLASSB_ACTIVE == 1 )
case 9: // Switch end device Class
{
MibRequestConfirm_t mibReq;
mibReq.Type = MIB_DEVICE_CLASS;
// CLASS_A = 0, CLASS_B = 1, CLASS_C = 2
mibReq.Param.Class = (DeviceClass_t)mcpsIndication->Buffer[1];
LoRaMacMibSetRequestConfirm(&mibReq);
break;
}
case 10: // Send PingSlotInfoReq
{
MlmeReq_t mlmeReq;
mlmeReq.Type = MLME_PING_SLOT_INFO;
mlmeReq.Req.PingSlotInfo.PingSlot.Value = mcpsIndication->Buffer[1];
LoRaMacMlmeRequest(&mlmeReq);
break;
}
case 11: // Send BeaconTimingReq
{
MlmeReq_t mlmeReq;
mlmeReq.Type = MLME_BEACON_TIMING;
LoRaMacMlmeRequest(&mlmeReq);
break;
}
#elif !defined (LORAMAC_CLASSB_ACTIVE)
#error LORAMAC_CLASSB_ACTIVE not defined
#endif
default:
break;
}
}
if (certifParam.Running == false)
{
/*certification test stops*/
TimerStop(&CertifTxNextPacketTimer);
}
}
/*!
* \brief Function executed on TxNextPacket Timeout event
*/
static void OnCertifTxNextPacketTimerEvent(void *context)
{
requested_process_id = CERTIF_TX_PROCESS;
CertifProcessNotify();
}
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/

View File

@@ -0,0 +1,71 @@
/******************************************************************************
* @file lora_test.h
* @author MCD Application Team
* @brief lora API to drive the lora state Machine
******************************************************************************
* @attention
*
* <h2><center>&copy; Copyright (c) 2019 STMicroelectronics.
* All rights reserved.</center></h2>
*
* This software component is licensed by ST under BSD 3-Clause license,
* the "License"; You may not use this file except in compliance with the
* License. You may obtain a copy of the License at:
* opensource.org/licenses/BSD-3-Clause
*
******************************************************************************
*/
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef __LORA_TEST_H__
#define __LORA_TEST_H__
#ifdef __cplusplus
extern "C" {
#endif
/* Includes ------------------------------------------------------------------*/
/* Exported constants --------------------------------------------------------*/
#define CERTIF_PORT 224
/* Exported types ------------------------------------------------------------*/
/* External variables --------------------------------------------------------*/
/* Exported macros -----------------------------------------------------------*/
/* Exported functions ------------------------------------------------------- */
/**
* @brief Certification Initialisation
* @param [IN] Notification call back to the appl that a CERTIF_Process must be called
* @retval none
*/
void CERTIF_Init(void (*CERTIF_ProcessNotify)(void));
/**
* @brief CERTIF_Process to be called when a CERTIF_ProcessNotify callback is generated
* @param [IN] none
* @retval none
*/
void CERTIF_Process(void);
/* Lora Test callbacks*/
typedef struct sLoRaCertifCallback
{
bool (*running)(void);
void (*DownLinkIncrement)(void);
void (*linkCheck)(MlmeConfirm_t *mlmeConfirm);
void (*rx)(McpsIndication_t *mcpsIndication, MlmeReqJoin_t *JoinParameters);
} LoRaCertifCallback_t;
#ifdef __cplusplus
}
#endif
#endif /*__LORA_TEST_H__*/
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,403 @@
/**
******************************************************************************
* @file lora.h
* @author MCD Application Team
* @brief lora API to drive the lora state Machine
******************************************************************************
* @attention
*
* <h2><center>&copy; Copyright (c) 2019 STMicroelectronics.
* All rights reserved.</center></h2>
*
* This software component is licensed by ST under BSD 3-Clause license,
* the "License"; You may not use this file except in compliance with the
* License. You may obtain a copy of the License at:
* opensource.org/licenses/BSD-3-Clause
*
******************************************************************************
*/
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef __LORA_H__
#define __LORA_H__
#ifdef __cplusplus
extern "C" {
#endif
/* Includes ------------------------------------------------------------------*/
#include "Commissioning.h"
#include "LoRaMac.h"
#include "app_conf.h"
#if defined (LORAMAC_CLASSB_ACTIVE) && ( LORAMAC_CLASSB_ACTIVE == 1 )
#include "LoRaMacClassB.h"
#elif !defined (LORAMAC_CLASSB_ACTIVE)
#error LORAMAC_CLASSB_ACTIVE not defined
#endif /* LORAMAC_CLASSB_ACTIVE */
#include "region/Region.h"
#include "lora-test.h"
/* Exported constants --------------------------------------------------------*/
/*!
* LoRaWAN confirmed messages
*/
#define LORAWAN_ADR_ON 1
#define LORAWAN_ADR_OFF 0
/* Exported types ------------------------------------------------------------*/
/*!
* Application Data structure
*/
typedef struct
{
/*point to the LoRa App data buffer*/
uint8_t *Buff;
/*LoRa App data buffer size*/
uint8_t BuffSize;
/*Port on which the LoRa App is data is sent/ received*/
uint8_t Port;
} lora_AppData_t;
typedef enum
{
LORA_RESET = 0,
LORA_SET = !LORA_RESET
} LoraFlagStatus;
typedef enum
{
LORA_DISABLE = 0,
LORA_ENABLE = !LORA_DISABLE
} LoraState_t;
typedef enum
{
LORA_ERROR = -1,
LORA_SUCCESS = 0
} LoraErrorStatus;
typedef enum
{
LORAWAN_UNCONFIRMED_MSG = 0,
LORAWAN_CONFIRMED_MSG = !LORAWAN_UNCONFIRMED_MSG
} LoraConfirm_t;
typedef enum
{
LORA_TRUE = 0,
LORA_FALSE = !LORA_TRUE
} LoraBool_t;
/*!
* LoRa State Machine states
*/
typedef enum eTxEventType
{
/*!
* @brief AppdataTransmition issue based on timer every TxDutyCycleTime
*/
TX_ON_TIMER,
/*!
* @brief AppdataTransmition external event plugged on OnSendEvent( )
*/
TX_ON_EVENT
} TxEventType_t;
/*!
* LoRa State Machine states
*/
typedef struct sLoRaParam
{
/*!
* @brief Activation state of adaptativeDatarate
*/
bool AdrEnable;
/*!
* @brief Uplink datarate, if AdrEnable is off
*/
int8_t TxDatarate;
/*!
* @brief Enable or disable a public network
*/
bool EnablePublicNetwork;
/*!
* @brief region to open
*/
LoRaMacRegion_t ActiveRegion;
} LoRaParam_t;
/* Lora Main callbacks*/
typedef struct sLoRaMainCallback
{
/*!
* @brief Get the current battery level
*
* @retval value battery level ( 0: very low, 254: fully charged )
*/
uint8_t (*BoardGetBatteryLevel)(void);
/*!
* \brief Get the current temperature
*
* \retval value temperature in degreeCelcius( q7.8 )
*/
uint16_t (*BoardGetTemperatureLevel)(void);
/*!
* @brief Gets the board 64 bits unique ID
*
* @param [IN] id Pointer to an array that will contain the Unique ID
*/
void (*BoardGetUniqueId)(uint8_t *id);
/*!
* Returns a pseudo random seed generated using the MCU Unique ID
*
* @retval seed Generated pseudo random seed
*/
uint32_t (*BoardGetRandomSeed)(void);
/*!
* @brief Process Rx Data received from Lora network
*
* @param [IN] AppData structure
*
*/
void (*LORA_RxData)(lora_AppData_t *AppData);
/*!
* @brief callback indicating EndNode has jsu joiny
*
* @param [IN] None
*/
void (*LORA_HasJoined)(void);
/*!
* @brief Confirms the class change
*
* @param [IN] AppData is a buffer to process
*
* @param [IN] port is a Application port on wicth Appdata will be sent
*
* @param [IN] length is the number of recieved bytes
*/
void (*LORA_ConfirmClass)(DeviceClass_t Class);
/*!
* @brief callback indicating an uplink transmission is needed to allow
* a pending downlink transmission
*
* @param [IN] None
*/
void (*LORA_TxNeeded)(void);
/*!
*\brief Will be called each time a Radio IRQ is handled by the MAC
* layer.
*
*\warning Runs in a IRQ context. Should only change variables state.
*/
void (*MacProcessNotify)(void);
/*!
* @brief callback indicating a downlink transmission providing
* an acknowledgment for an uplink confirmed data message transmission
*
* @param [IN] None
*/
void (*LORA_McpsDataConfirm)(void);
} LoRaMainCallback_t;
/* External variables --------------------------------------------------------*/
/* Exported macros -----------------------------------------------------------*/
/* Exported functions ------------------------------------------------------- */
/**
* @brief Lora Initialisation
* @param [IN] LoRaMainCallback_t
* @param [IN] application parmaters
* @retval none
*/
void LORA_Init(LoRaMainCallback_t *callbacks, LoRaParam_t *LoRaParam);
/**
* @brief Lora Certif Initialisation (Registers CB)
* @param [IN] LoRaCertifCallback_t
* @retval none
*/
void LORA_TestInit(LoRaCertifCallback_t *callbacks);
/**
* @brief run Lora classA state Machine
* @param [IN] none
* @retval none
*/
LoraErrorStatus LORA_send(lora_AppData_t *AppData, LoraConfirm_t IsTxConfirmed);
/**
* @brief Join a Lora Network in classA
* @Note if the device is ABP, this is a pass through functon
* @param [IN] none
* @retval none
*/
LoraErrorStatus LORA_Join(void);
/**
* @brief Check whether the Device is joined to the network
* @param [IN] none
* @retval returns LORA_SET if joined
*/
LoraFlagStatus LORA_JoinStatus(void);
/**
* @brief change Lora Class
* @Note callback LORA_ConfirmClass informs upper layer that the change has occured
* @Note Only switch from class A to class B/C OR from class B/C to class A is allowed
* @Attention can be calld only in LORA_ClassSwitchSlot or LORA_RxData callbacks
* @param [IN] DeviceClass_t NewClass
* @retval LoraErrorStatus
*/
LoraErrorStatus LORA_RequestClass(DeviceClass_t newClass);
/**
* @brief get the current Lora Class
* @param [IN] DeviceClass_t NewClass
* @retval None
*/
void LORA_GetCurrentClass(DeviceClass_t *currentClass);
/**
* @brief Set join activation process: OTAA vs ABP
* @param Over The Air Activation status to set: enable or disable
* @retval None
*/
void lora_config_otaa_set(LoraState_t otaa);
/**
* @brief Get join activation process: OTAA vs ABP
* @param None
* @retval ENABLE if OTAA is used, DISABLE if ABP is used
*/
LoraState_t lora_config_otaa_get(void);
/**
* @brief Set duty cycle: ENABLE or DISABLE
* @param Duty cycle to set: enable or disable
* @retval None
*/
void lora_config_duty_cycle_set(LoraState_t duty_cycle);
/**
* @brief Get Duty cycle: OTAA vs ABP
* @param None
* @retval ENABLE / DISABLE
*/
LoraState_t lora_config_duty_cycle_get(void);
/**
* @brief Get Device EUI
* @param None
* @retval DevEUI
*/
uint8_t *lora_config_deveui_get(void);
/**
* @brief Get Join Eui
* @param None
* @retval JoinEUI
*/
uint8_t *lora_config_joineui_get(void);
/**
* @brief Set Join Eui
* @param JoinEUI
* @retval Nonoe
*/
void lora_config_joineui_set(uint8_t joineui[8]);
/**
* @brief Get Application Key
* @param None
* @retval AppKey
*/
uint8_t *lora_config_appkey_get(void);
/**
* @brief Set Application Key
* @param AppKey
* @retval None
*/
void lora_config_appkey_set(uint8_t appkey[16]);
/**
* @brief Set whether or not acknowledgement is required
* @param ENABLE or DISABLE
* @retval None
*/
void lora_config_reqack_set(LoraConfirm_t reqack);
/**
* @brief Get whether or not acknowledgement is required
* @param None
* @retval ENABLE or DISABLE
*/
LoraConfirm_t lora_config_reqack_get(void);
/**
* @brief Get the SNR of the last received data
* @param None
* @retval SNR
*/
int8_t lora_config_snr_get(void);
/**
* @brief Get the RSSI of the last received data
* @param None
* @retval RSSI
*/
int16_t lora_config_rssi_get(void);
/**
* @brief Launch LoraWan certification tests
* @param None
* @retval The application port
*/
void lora_wan_certif(void);
/**
* @brief set tx datarate
* @param None
* @retval The application port
*/
void lora_config_tx_datarate_set(int8_t TxDataRate);
/**
* @brief get tx datarate
* @param None
* @retval tx datarate
*/
int8_t lora_config_tx_datarate_get(void);
/**
* @brief get LoRaMac region
* @param None
* @retval LoRaMac region
*/
LoRaMacRegion_t lora_region_get(void);
#if defined (LORAMAC_CLASSB_ACTIVE) && ( LORAMAC_CLASSB_ACTIVE == 1 )
LoRaMacClassBNvmCtx_t* LORA_Get_ClassBCtx(void);
uint8_t LORA_Get_PingSlotPeriodicity(void);
void LORA_Set_PingSlotPeriodicity(uint8_t PingSlotPeriodicity);
#elif !defined (LORAMAC_CLASSB_ACTIVE)
#error LORAMAC_CLASSB_ACTIVE not defined
#endif
#ifdef __cplusplus
}
#endif
#endif /*__LORA_H__*/
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/

View File

@@ -0,0 +1,94 @@
/**
******************************************************************************
* @file lorawan_info.c
* @author MCD Application Team
* @brief To give info to the application about LoraWAN configuration
******************************************************************************
* @attention
*
* <h2><center>&copy; Copyright (c) 2019 STMicroelectronics.
* All rights reserved.</center></h2>
*
* This software component is licensed by ST under BSD 3-Clause license,
* the "License"; You may not use this file except in compliance with the
* License. You may obtain a copy of the License at:
* opensource.org/licenses/BSD-3-Clause
*
******************************************************************************
*/
/* Includes ------------------------------------------------------------------*/
#include "lorawan_info.h"
#include "LoRaMac.h"
/* Private typedef -----------------------------------------------------------*/
/* Private define ------------------------------------------------------------*/
/* Private macro -------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/
/* Private function prototypes -----------------------------------------------*/
/* Exported variables --------------------------------------------------------*/
LoRaMacInfo_t LoRaMacInfoTable;
/* Exported functions --------------------------------------------------------*/
/**
* @brief initialises the LoraMacInfo capabilities table
* @param none
* @retval none
*/
void LoraMacInfo_Init(void)
{
LoRaMacInfoTable.Region = 0;
#ifdef REGION_AS923
LoRaMacInfoTable.Region |= (1<<LORAMAC_REGION_AS923) ;
#endif
#ifdef REGION_AU915
LoRaMacInfoTable.Region |= (1<<LORAMAC_REGION_AU915) ;
#endif
#ifdef REGION_CN470
LoRaMacInfoTable.Region |= (1<<LORAMAC_REGION_CN470) ;
#endif
#ifdef REGION_CN779
LoRaMacInfoTable.Region |= (1<<LORAMAC_REGION_CN779) ;
#endif
#ifdef REGION_EU433
LoRaMacInfoTable.Region |= (1<<LORAMAC_REGION_EU433) ;
#endif
#ifdef REGION_EU868
LoRaMacInfoTable.Region |= (1<<LORAMAC_REGION_EU868) ;
#endif
#ifdef REGION_KR920
LoRaMacInfoTable.Region |= (1<<LORAMAC_REGION_KR920) ;
#endif
#ifdef REGION_IN865
LoRaMacInfoTable.Region |= (1<<LORAMAC_REGION_IN865) ;
#endif
#ifdef REGION_US915
LoRaMacInfoTable.Region |= (1<<LORAMAC_REGION_US915) ;
#endif
#ifdef REGION_RU864
LoRaMacInfoTable.Region |= (1<<LORAMAC_REGION_RU864) ;
#endif
#ifdef LORAMAC_CLASSB_ENABLED
LoRaMacInfoTable.ClassB = 1;
#else
LoRaMacInfoTable.ClassB = 0;
#endif
return;
}
/**
* @brief returns the pointer to the LoraMacInfo capabilities table
* @param none
* @retval LoRaMacInfoTable pointer
*/
LoRaMacInfo_t* LoraMacInfo_GetPtr(void)
{
return &LoRaMacInfoTable;
}
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/

View File

@@ -0,0 +1,67 @@
/**
******************************************************************************
* @file lorawan_info.h
* @author MCD Application Team
* @brief To give info to the application about LoraWAN configuration
******************************************************************************
* @attention
*
* <h2><center>&copy; Copyright (c) 2019 STMicroelectronics.
* All rights reserved.</center></h2>
*
* This software component is licensed by ST under BSD 3-Clause license,
* the "License"; You may not use this file except in compliance with the
* License. You may obtain a copy of the License at:
* opensource.org/licenses/BSD-3-Clause
*
******************************************************************************
*/
#ifndef __LORAWAN_INFO_H__
#define __LORAWAN_INFO_H__
#ifdef __cplusplus
extern "C" {
#endif
/* Includes ------------------------------------------------------------------*/
#include <stdint.h>
/* Exported constants --------------------------------------------------------*/
/* Exported types ------------------------------------------------------------*/
/*!
* To give info to the application about LoraWAN capability
* it can depend how it has been compiled (e.g. compiled regions ...)
* Params should be better uint32_t foe easier alignment with info_table concept
*/
typedef struct
{
uint32_t Region; /*!< Combination of regions compiled on MW */
uint32_t ClassB; /*!< 0: not compiled in Mw, 1 : compiled in MW */
}LoRaMacInfo_t;
/* External variables --------------------------------------------------------*/
/* Exported macros -----------------------------------------------------------*/
/* Exported functions ------------------------------------------------------- */
/**
* @brief initialises the LoraMacInfo table
* @param none
* @retval none
*/
void LoraMacInfo_Init(void);
/**
* @brief returns the pointer to the LoraMacInfo table
* @param none
* @retval LoRaMacInfoTable pointer
*/
LoRaMacInfo_t* LoraMacInfo_GetPtr(void);
#ifdef __cplusplus
}
#endif
#endif // __LORAWAN_INFO_H__

View File

@@ -0,0 +1,94 @@
/*
/ _____) _ | |
( (____ _____ ____ _| |_ _____ ____| |__
\____ \| ___ | (_ _) ___ |/ ___) _ \
_____) ) ____| | | || |_| ____( (___| | | |
(______/|_____)_|_|_| \__)_____)\____)_| |_|
(C)2013 Semtech
Description: Helper functions implementation
License: Revised BSD License, see LICENSE.TXT file include in the project
Maintainer: Miguel Luis and Gregory Cristian
*/
/**
******************************************************************************
*
* Portions COPYRIGHT 2019 STMicroelectronics
*
* @file utilities.c
* @author MCD Application Team
* @brief Helper functions implementation
******************************************************************************
*/
#include "utilities.h"
/*!
* Redefinition of rand() and srand() standard C functions.
* These functions are redefined in order to get the same behavior across
* different compiler toolchains implementations.
*/
// Standard random functions redefinition start
#define RAND_LOCAL_MAX 2147483647L
static uint32_t next = 1;
int32_t rand1( void )
{
return ( ( next = next * 1103515245L + 12345L ) % RAND_LOCAL_MAX );
}
void srand1( uint32_t seed )
{
next = seed;
}
// Standard random functions redefinition end
int32_t randr( int32_t min, int32_t max )
{
return ( int32_t )rand1( ) % ( max - min + 1 ) + min;
}
void memcpy1( uint8_t *dst, const uint8_t *src, uint16_t size )
{
while( size-- )
{
*dst++ = *src++;
}
}
void memcpyr( uint8_t *dst, const uint8_t *src, uint16_t size )
{
dst = dst + ( size - 1 );
while( size-- )
{
*dst-- = *src++;
}
}
void memset1( uint8_t *dst, uint8_t value, uint16_t size )
{
while( size-- )
{
*dst++ = value;
}
}
int8_t Nibble2HexChar( uint8_t a )
{
if( a < 10 )
{
return '0' + a;
}
else if( a < 16 )
{
return 'A' + ( a - 10 );
}
else
{
return '?';
}
}
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/

View File

@@ -0,0 +1,136 @@
/*
/ _____) _ | |
( (____ _____ ____ _| |_ _____ ____| |__
\____ \| ___ | (_ _) ___ |/ ___) _ \
_____) ) ____| | | || |_| ____( (___| | | |
(______/|_____)_|_|_| \__)_____)\____)_| |_|
(C)2013 Semtech
Description: Helper functions implementation
License: Revised BSD License, see LICENSE.TXT file include in the project
Maintainer: Miguel Luis and Gregory Cristian
*/
/**
******************************************************************************
*
* Portions COPYRIGHT 2019 STMicroelectronics
*
* @file utilities.h
* @author MCD Application Team
* @brief Header for driver utilities.c module
******************************************************************************
*/
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef __UTILITIES_H__
#define __UTILITIES_H__
/* Includes ------------------------------------------------------------------*/
#include <stdint.h>
#include "utilities_conf.h"
/* Exported types ------------------------------------------------------------*/
/* Exported constants --------------------------------------------------------*/
/* External variables --------------------------------------------------------*/
/* Exported macros -----------------------------------------------------------*/
/* Defines -------------------------------------------------------------------*/
#define TIMERTIME_T_MAX ( ( uint32_t )~0 )
/*!
* @brief Returns the minimum value between a and b
*
* @param [IN] a 1st value
* @param [IN] b 2nd value
* @retval minValue Minimum value
*/
#ifndef MIN
#define MIN( a, b ) ( ( ( a ) < ( b ) ) ? ( a ) : ( b ) )
#endif
/*!
* @brief Returns the maximum value between a and b
*
* @param [IN] a 1st value
* @param [IN] b 2nd value
* @retval maxValue Maximum value
*/
#ifndef MAX
#define MAX( a, b ) ( ( ( a ) > ( b ) ) ? ( a ) : ( b ) )
#endif
/*!
* @brief Returns 2 raised to the power of n
*
* @param [IN] n power value
* @retval result of raising 2 to the power n
*/
#define POW2( n ) ( 1 << n )
/*!
* @brief Initializes the pseudo random generator initial value
* @param [IN] seed Pseudo random generator initial value
* @retval none
*/
void srand1( uint32_t seed );
/*!
* @brief Computes a random number between min and max
* @param [IN] min range minimum value
* @param [IN] max range maximum value
* @retval random random value in range min..max
*/
int32_t randr( int32_t min, int32_t max );
/*!
* @brief Computes a random number
* @param none
* @retval random value in range min..max
*/
int32_t rand1( void );
/*!
* @brief Copies size elements of src array to dst array
* @remark STM32 Standard memcpy function only works on pointers that are aligned
* @param [OUT] dst Destination array
* @param [IN] src Source array
* @param [IN] size Number of bytes to be copied
* @retval none
*/
void memcpy1( uint8_t *dst, const uint8_t *src, uint16_t size );
/*!
* @brief Copies size elements of src array to dst array reversing the byte order
* @param [OUT] dst Destination array
* @param [IN] src Source array
* @param [IN] size Number of bytes to be copied
* @retval none
*/
void memcpyr( uint8_t *dst, const uint8_t *src, uint16_t size );
/*!
* @brief Set size elements of dst array with value
* @remark STM32 Standard memset function only works on pointers that are aligned
* @param [OUT] dst Destination array
* @param [IN] value Default value
* @param [IN] size Number of bytes to be copied
* @retval none
*/
void memset1( uint8_t *dst, uint8_t value, uint16_t size );
/*!
* @brief Converts a nibble to an hexadecimal character
* @param [IN] a Nibble to be converted
* @retval hexChar Converted hexadecimal character
*/
int8_t Nibble2HexChar( uint8_t a );
#endif // __UTILITIES_H__

View File

@@ -0,0 +1,771 @@
# LoRaWAN endpoint stack implementation and example projects
______ _
/ _____) _ | |
( (____ _____ ____ _| |_ _____ ____| |__
\____ \| ___ | (_ _) ___ |/ ___) _ \
_____) ) ____| | | || |_| ____( (___| | | |
(______/|_____)_|_|_| \__)_____)\____)_| |_|
(C)2013-2019 Semtech
___ _____ _ ___ _ _____ ___ ___ ___ ___
/ __|_ _/_\ / __| |/ / __/ _ \| _ \/ __| __|
\__ \ | |/ _ \ (__| ' <| _| (_) | / (__| _|
|___/ |_/_/ \_\___|_|\_\_| \___/|_|_\\___|___|
embedded.connectivity.solutions===============
## Introduction
The aim of this project is to show an example of the endpoint LoRaWAN stack implementation.
This project has 3 active branches in place. The **[master](https://github.com/Lora-net/LoRaMac-node/tree/master)** branch which provides the latest released source code ([v4.4.2](https://github.com/Lora-net/LoRaMac-node/releases/tag/v4.4.2)), the **[develop](https://github.com/Lora-net/LoRaMac-node/tree/develop)** branch which provides the current source code development status to be released next ([Milestone 4.4.3](https://github.com/Lora-net/LoRaMac-node/milestone/4)) and the **[feature/5.0.0](https://github.com/Lora-net/LoRaMac-node/tree/feature/5.0.0)** branch which provides a preview of the current source code development status for [LoRaWAN Specification v1.1](https://lora-alliance.org/resource-hub/lorawantm-specification-v11) specification.([Milestone 5.0.0](https://github.com/Lora-net/LoRaMac-node/milestone/3))
* The [master](https://github.com/Lora-net/LoRaMac-node/tree/master) branch implementation is based on [LoRaWAN Specification v1.0.3](https://lora-alliance.org/resource-hub/lorawantm-specification-v103) and [LoRaWAN Regional Parameters v1.0.3revA](https://www.lora-alliance.org/resource-hub/lorawantm-regional-parameters-v103reva) specifications.
ClassA, ClassB and ClassC end-device classes are fully implemented.
* The [develop](https://github.com/Lora-net/LoRaMac-node/tree/develop) branch implementation is based on [LoRaWAN Specification v1.0.3](https://lora-alliance.org/resource-hub/lorawantm-specification-v103) and [LoRaWAN Regional Parameters v1.0.3revA](https://lora-alliance.org/resource-hub/lorawan-regional-parameters-v103reva) specifications.
ClassA, ClassB and ClassC end-device classes are fully implemented.
* The [feature/5.0.0](https://github.com/Lora-net/LoRaMac-node/tree/feature/5.0.0) branch implementation is based on [LoRaWAN Specification v1.1](https://lora-alliance.org/resource-hub/lorawantm-specification-v11) and [LoRaWAN Regional Parameters v1.1rB](https://lora-alliance.org/resource-hub/lorawantm-regional-parameters-v11rb) specifications.
ClassA, ClassB and ClassC end-device classes are fully implemented.
This project also provides SX1272/73, SX1276/77/78/79 and SX1261/2 radio drivers.
For each currently supported platform example applications are provided.
* **LoRaMac/classA**: ClassA end-device example application.
* **LoRaMac/classB**: ClassB end-device example application.
* **LoRaMac/classC**: ClassC end-device example application.
* **LoRaMac/fuota-test-01**: FUOTA test scenario 01 end-device example application. (Based on provided application common packages)
* **LoRaMac/periodic-uplink-lpp**: ClassA/B/C end-device example application. Periodically uplinks a frame using the Cayenne LPP protocol. (Based on provided application common packages)
* **ping-pong**: Point to point RF link example application.
* **rx-sensi**: Example application useful to measure the radio sensitivity level using an RF generator.
* **tx-cw**: Example application to show how to generate an RF Continuous Wave transmission.
**Note**: *Each LoRaWAN application example (LoRaMac/classX) includes an implementation of the LoRa-Alliance; LoRaWAN certification protocol.*
**Note**: *The LoRaWAN stack API documentation can be found at: http://stackforce.github.io/LoRaMac-doc/*
## Supported platforms
This project currently provides support for the below platforms.
This project can be ported to other platforms using different MCU than the ones currently supported.
The [Porting Guide](http://stackforce.github.io/LoRaMac-doc/_p_o_r_t_i_n_g__g_u_i_d_e.html) document provides guide lines on how to port the project to other platforms.
* NAMote72
* [NAMote72 platform documentation](Doc/NAMote72-platform.md)
* NucleoLxxx - Discovery kit
* [NucleoLxxx and Discovery kit platforms documentation](Doc/NucleoLxxx-platform.md)
* SKiM880B, SKiM980A, SKiM881AXL
* [SKiM88xx platforms documentation](Doc/SKiM88xx-platform.md)
* SAML21
* [SAML21 platform documentation](Doc/SAML21-platform.md)
## Usage
A CMAKE building system is used in order to generate the right set of files to compile and debug the different projects.
Further information can be found in [Development environment](Doc/development-environment.md) document.
## Acknowledgments
The mbed (https://mbed.org/) project was used at the beginning as source of
inspiration.
This program uses the AES algorithm implementation (http://www.gladman.me.uk/) by Brian Gladman.
This program uses the CMAC algorithm implementation
(http://www.cse.chalmers.se/research/group/dcs/masters/contikisec/) by Lander Casado, Philippas Tsigas.
## Changelog
### 2019-07-19, V4.4.2
* General
1. Release based on "LoRaWAN specification 1.0.3" and "LoRaWAN Regional Parameters v1.0.3revA"
2. Examples application refactoring plus the addition of the application status display on the serial port. (921600-8-N-1)
3. Added new refactored application examples
* Added LoRa-Alliance defined application layer protocols support. Only FUOTA test scenario 01 required features are currently implemented.
- "Clock Synchronization" package
- "Fragmented data block transport" package
- "Remote multicast setup" package
4. Added a NVM context management module. (Disabled by default)
5. Added secure-element support
6. Refactored timer.c/h, rtc-driver.c/h and added a systime.c/h module.
7. Functions in ISR context have been moved to main context
8. Replaced BoardDisableIrq and BoardEnableIrq functions by CRITICAL_SECTION_BEGIN and CRITICAL_SECTION_END respectively.
9. Added B-L072Z-LRWAN1 platform support.
10. Added NucleoL476 platform support.
11. Added IMST new platforms.
12. Removed SensorNode platform support
13. Removed MoteII platform support
14. Removed LoRaMote platform support
15. Applied SX1272 and SX1276 radios errata note 3.1 to the radio drivers implementation.
16. Fix printf/scanf functions when GCC is used as compiler.
* LoRaWAN
1. GitHub reported issues corrections. Please refer to [Release Version 4.4.2](https://github.com/Lora-net/LoRaMac-node/milestone/2)
2. Heavily refactored the LoRaMac.c/h implementation.
3. Added RU864 region support.
4. Removed US915-Hybrid region support
5. Added ClassB support.
6. Added a callback to notify the upper layer to call LoRaMacProcess function
7. Implemented the support for RxC windows (ClassC) required by the application layer protocols.
8. Changed multicast channels handling according to the application layer protocols.
**LoRaWAN pre-certification results**
Please refer to [Releases pre-certification-results](https://github.com/Lora-net/LoRaMac-node/wiki/releases-pre-certification-results) document for further information.
### 2018-03-07, V4.4.1
* General
1. Release based on "LoRaWAN specification 1.0.2" and "LoRaWAN Regional Parameters v1.0.2rB"
2. Added SX126x radio support.
3. Added NucleoL073 and NucleoL152 board platforms support.
4. Added Microchip/Atmel SAML21 Xplained Pro hardware platform support.
5. Added CMAKE build system support
6. Removed CoIDE projects support
7. Removed Keil projects support
* LoRaWAN
1. GitHub reported issues corrections. Please refer to [Release Version 4.4.1](https://github.com/Lora-net/LoRaMac-node/milestone/1)
**LoRaWAN pre-certification results**
Please refer to [Releases pre-certification-results](https://github.com/Lora-net/LoRaMac-node/wiki/releases-pre-certification-results) document for further information.
### 2017-09-08, V4.4.0
* General
1. First release based on "LoRaWAN specification 1.0.2" and "LoRaWAN Regional Parameters v1.0.2rB"
2. This version has passed the LoRa-Alliance compliance tests for the regions shown in the below table.
3. GitHub reported issues corrections.
4. Updated radio driver to perform the LBT carrier sense continuously for a given period of time.
* LoRaWAN
1. GitHub reported issues corrections.
2. Updated implementation to support 1.0.2 specification additions.
3. Added the support for all "LoRaWAN Regional Parameters v1.0.2rB" document defined regions.
**LoRaWAN pre-certification results**
Please refer to [Releases pre-certification-results](https://github.com/Lora-net/LoRaMac-node/wiki/releases-pre-certification-results) document for further information.
### 2017-04-19, V4.3.2
* General (Last release based on LoRaWAN specification 1.0.1)
1. This version has passed EU868 and US915 LoRa-Alliance compliance tests.
2. GitHub reported issues corrections.
3. Added an algorithm to automatically compute the Rx windows parameters. (Window symbolTimeout and Offset from downlink expected time)
4. Added a workaround to reset the radio in case a TxTimeout occurs.
5. Modified FSK modem handling to use the provided symbolTimeout (1 symbol equals 1 byte) when in RxSingle mode.
6. Added newly defined TxCw(Tx Continuous Wave) certification protocol command.
7. Added a fix for an overflow issue that could happen with NmeaStringSize variable.
8. Improved GpioMcuInit function to first configure the output pin state before activating the pin.
* LoRaWAN
1. GitHub reported issues corrections.
2. Changed the AdrAckCounter handling as expected by the test houses.
3. Fix an issue where the node stopped transmitting.
4. Removed useless LoRaMacPayload buffer.
5. MAC layer indications handling simplification.
6. Relocate parameter settings from ResetMacParameters to the initialization.
**LoRaWAN pre-certification results**
Please refer to [Releases pre-certification-results](https://github.com/Lora-net/LoRaMac-node/wiki/releases-pre-certification-results) document for further information.
### 2017-02-27, V4.3.1
* General
1. This version has passed EU868 and US915 LoRa-Alliance compliance tests.
2. Update the MAC layer in order to be LoRaWAN version 1.0.1 compliant (Mainly US915 bug fixes)
3. Removed api-v3 support from the project.
4. GitHub reported issues corrections.
5. Updated SensorNode projects according to the new MCU reference STM32L151CBU6. Bigger memories.
6. Addition of MoteII platform based on the IMST module iM881A (STM32L051C8)
7. Addition of NAMote72 platform
8. Correct compliance test protocol command 0x06 behavior
9. Added TxCw (Tx continuous wave) LoRaWAN compliance protocol command.
10. Added TxContinuousWave support to the radio drivers.
11. Updated ST HAL drivers.
* STM32L1xx_HAL-Driver : V1.2.0
* STM32L0xx_HAL_Driver : V1.7.0
* LoRaWAN
1. US band corrections in order to pass the LoRaWAN certification.
2. GitHub reported issues corrections.
3. Add region CN470 support.
**LoRaWAN pre-certification results**
Please refer to [Releases pre-certification-results](https://github.com/Lora-net/LoRaMac-node/wiki/releases-pre-certification-results) document for further information.
### 2016-06-22, V4.3.0
* General
1. This version has passed all LoRa-Alliance compliance tests.
2. Update the MAC layer in order to be LoRaWAN version 1.0.1 compliant
3. Applied to all application files the certification protocol change for LoRaWAN 1.0.1 compliance tests.
**REMARK**: api-v3 application files aren't updated.
4. Add radio RX_TIMEOUT irq clear into the irq handler.
5. Removed the end less loop from HAL_UART_ErrorCallback.
6. Update of the STM32L0 HAL to version 1.6.0
7. Consolidated the line endings across all project files.
Windows line endings has been choose for almost every file.
* LoRaWAN
1. Updated maximum payload size for US band.
2. Update datarate offset table for US band.
3. Make MAC commands sticky
4. Add retransmission back-off
5. Remove the TxPower limitation for US band on LoRaMacMibSetRequestConfirm function. The power will be limited anyway when the SendFrameOnChannel functions is called.
6. Issue(#81): Bug fix in function LoRaMacMlmeRequest case MLME_JOIN. Function will return LORAMAC_STATUS_BUSY in case the MAC is in status MAC_TX_DELAYED.
7. Add debug pin support to LoRaMote platform.
8. Updated and improved MPL3115 device driver.
9. Issue(#83): Bug fix in parameter validation
10. Issue(#84): Fix issue of CalibrateTimer function.
11. RTC driver major update
12. Applied pull request #87.
13. Add a function to verify the RX frequency of window 2 for US band.
14. Issue(#88): Bug fix in function PrepareFrame where repeated MAC commands were not handled correctly.
15. Bug fix in OnRadioRxDone. Node now drops frames on port 0 with fOpts > 0.
16. Bug fix in OnRadioRxDone. Node now receives frames with fOpts > 0 when no payload is present.
**LoRaWAN pre-certification results**
Please refer to [Releases pre-certification-results](https://github.com/Lora-net/LoRaMac-node/wiki/releases-pre-certification-results) document for further information.
### 2016-05-13, V4.2.0
* General
1. This version has passed all LoRa-Alliance compliance tests.
2. Update STM32L1xx_HAL_Driver version to 1.5. Update related drivers and implementations accordingly.
**REMARK**: This change implies that the time base had to be changed from microseconds to milliseconds.
3. Corrected the frequency check condition for // ERRATA 2.1 - Sensitivity Optimization with a 500 kHz Bandwidth
4. Optimize radio drivers regarding FSK PER
5. Resolve issue when calling SX127xInit function more than once
6. Add a definition for the LoRaWAN device address. Add an IEEE_OUI for the LoRaWAN device EUI.
7. Add a definition for the default datarate.
8. Issue(#66) correction of functions SX1276SetOpMode and SX1272SetOpMode.
9. Issue(#68): Fix for low level RF switch control.
10. Increase RTC tick frequency for higher resolution.
11. Update the radio wake up time.
* LoRaWAN
1. Issue(#56) correction
2. Update channel mask handling for US915 hybrid mode to support any block in the channel mask.
3. Issue(#63) correct the maximum payload length in RX mode.
4. Fix Tx power setting loss for repeated join requests on US band.
5. Introduce individual MIN and MAX datarates for RX and TX.
6. Add the possibility to set and get the ChannelsDefaultDatarate.
7. Optimization of the RX symbol timeout.
8. Issue(#59): Add the possibility to set the uplink and downlink counter.
9. Replace definition LORAMAC_DEFAULT_DATARATE by ChannelsDefaultDatarate in LoRaMacChannelAdd.
10. Issue(#72): Fix of possible array overrun in LoRaMacChannelRemove.
11. Introduce a new status MAC_RX_ABORT. Reset MAC_TX_RUNNING only in OnMacStateCheckTimerEvent.
12. Accept MAC information of duplicated, confirmed downlinks.
13. Issue(#74): Drop frames with a downlink counter difference greater or equal to MAX_FCNT_GAP.
**LoRaWAN pre-certification results**
Please refer to [Releases pre-certification-results](https://github.com/Lora-net/LoRaMac-node/wiki/releases-pre-certification-results) document for further information.
### 2016-03-10, V4.1.0
* General
1. This version has passed all mandatory LoRa-Alliance compliance tests.
*One of the optional tests is unsuccessful (FSK downlinks PER on Rx1 and Rx2 windows) and is currently under investigation.*
2. Removed support for Raisonance Ride7 IDE (Reduces the amount of work to be done at each new release)
3. Removed the Bleeper-72 and Bleeper-76 platforms support as these are now deprecated.
4. Application state machine. Relocate setting sleep state and update the duty cycle in compliance test mode.
5. Bug fix in TimerIrqHandler. Now, it is possible to insert timers in callback.
6. Changed TimerHwDelayMs function to be re-entrant.
7. Corrected FSK modem packets bigger than 64 bytes handling (Issue #36)
* LoRaWAN
1. Rename attribute nbRetries to NbTrials in structure McpsReqConfirmed_t. (Issue #37)
2. Updated implementation of SetNextChannel. Added enabling default channels in case of join request. (Issue #39)
3. Add missing documentation about MIB_REPEATER_SUPPORT. (Issue #42).
4. Add a new LoRaMacState to allow adding channels during TX procedure. (Issue #43)
5. Relocate the activation of LoRaMacFlags.Bits.McpsInd in OnRadioRxDone.
6. Add a new function PrepareRxDoneAbort to prepare a break-out of OnRadioRxDone in case of an error
7. Activate default channels in case all others are disabled. (Issue #39)
8. Bug fix in setting the default channel in case none is enabled.
9. SRV_MAC_NEW_CHANNEL_REQ MAC command added a fix to the macIndex variable on US915 band.
10. Start the MacStateCheckTimer in OnRxDone and related error cases with a short interval to handle events promptly. (Issue #44)
11. Reset status of NodeAckRequested if we received an ACK or in case of timeout.
12. Removed additional EU868 channels from the LoRaWAN implementation files. GitHub (Issue #49)
The creation of these additional channels has been moved to the application example.
13. Improved and corrected AdrNextDr function.
### 2015-12-18, V4.0.0
* General
1. STACKFORCE new API integration
2. Reverse the EUIs arrays in the MAC layer.
3. LoRaWAN certification protocol implementation
4. All reported issues and Pull requests have been addressed.
### 2015-10-06, V3.4.1
* General
1. Bug fixes
* LoRaWAN
1. Corrected downlink counter roll over management when several downlinks were missed.
2. Corrected the Radio maximum payload length management. Radio was filtering received frames with a length bigger than the transmitted one.
3. Applied Pull request #22 solution proposition.
### 2015-10-30, V3.4.0
* General
1. Changed all applications in order to have preprocessing definitions on top of the files and added relevant comments
2. Applications LED control is no more done into the timer callback functions but instead on the main while loop.
3. Added TimerStop function calls to each timer event callback.
4. Corrected timings comments. Timing values are most of the time us based.
5. Changed types names for stdint.h names. Helps on code portability
6. Renamed rand and srand to rand1 and srand1. Helps on code portability
7. Added some missing variables casts. Helps on code portability
8. Removed NULL definition from board.h
9. Added const variable attribute when necessary to functions prototypes
10. Moved ID1, ID2 and ID3 definition from board.h to board.c, usb-cdc-board.c and usb-dfu-board.c
11. Removed the definition of RAND_SEED. It has been replaced by a function named BoardGetRandomSeed
12. Renamed BoardMeasureBatterieLevel to BoardGetBatteryLevel
13. Added SetMaxPayloadLength API function to SX1272 and SX1276 radio drivers
14. Changed the name of Radio API Status function to GetStatus
15. AES/CMAC Changed types names for stdint.h names. Helps on code portability (Issue #20)
16. Moved __ffs function from utilities.h to spi-board.c. This function is only used there.
17. Utilities.c removed fputc function redefinition.
18. Replaced the usage of __IO attribute by volatile.
* LoRaWAN
1. Added support for the US915 band (Normal mode and hybrid mode. Hybrid mode is a temporary configuration up until servers support it automatically) (Issue #16)
2. Corrected and simplified the downlink sequence counter management.
3. Removed the usage of PACKED attribute for data structures.
4. Renamed LoRaMacEvent_t into LoRaMacCallbacks_t and added a function pointer for getting battery level status
5. Renamed LoRaMacSetDutyCycleOn into LoRaMacSetTestDutyCycleOn
6. Renamed LoRaMacSetMicTest into LoRaMacTestSetMic
7. Increased the PHY buffer size to 250
8. Removed IsChannelFree check on LoRaMacSetNextChannel function. LoRaWAN is an ALHOA protocol. (Pull request #8)
9. LoRaMacEventInfo.TxDatarate now returns LoRaWAN datarate (DR0 -> DR7) instead of (SF12 -> DF7)
10. Corrected channel mask management for EU868 band.
11. Corrected LoRaMacPrepareFrame behavior function when no applicative payload is present.
12. LoRaMac-board.h now implements the settings for the PHY layers specified by LoRaWAN 1.0 specification. ( EU433, CN780, EU868, US915 ) (Issue #19)
13. Added LORAMAC_MIN_RX1_DR_OFFSET and LORAMAC_MAX_RX1_DR_OFFSET definitions to LoRaMac-board.h. Can be different upon used PHY layer
14. Added the limitation of output power according to the number of enabled channels for US915 band.
15. Added the limitation of the applicative payload length according to the datarate. Does not yet take in account the MAC commands buffer. (Issue #15)
16. Corrected MacCommandBufferIndex management. (Issue #18)
### 2015-08-07, v3.3.0
* General
1. Added the support for LoRaWAN Class C devices.
2. Implemented the radios errata note workarounds. SX1276 errata 2.3 "Receiver Spurious Reception of a LoRa Signal" is not yet implemented.
3. Increased FSK SyncWord timeout value in order to listen for longer time if a down link is available or not. Makes FSK downlink more reliable.
4. Increased the UART USB FIFO buffer size in order to handle bigger chunks of data.
* LoRaWAN
1. Renamed data rates as per LoRaWAN specification.
2. Added the support for LoRaWAN Class C devices.
3. Handling of the MAC commands was done incorrectly the condition to verify the length of the buffer has changed from < to <=.
4. Added the possibility to change the channel mask and number of repetitions trough SRV_MAC_LINK_ADR_REQ command when ADR is disabled.
5. Corrected Rx1DrOffset management. In previous version DR1 was missing for all offsets.
6. Changed confirmed messages function to use default datarate when ADR control is off.
7. After a Join accept the node falls back to the default datarate. Enables the user to Join a network using a different datarate from its own default one.
8. Corrected default FSK channel frequency.
9. Solved a firmware freezing when one of the following situations arrived in OnRxDone callback: bad address, bad MIC, bad frame. (Pull request #10)
10. Moved the MAC commands processing to the right places. FOpts field before the Payload and Port 0 just after the decryption. (Pull request #9)
11. Weird conditions to check datarate on cmd mac SRV_MAC_NEW_CHANNEL_REQ (Pull request #7)
12. Ignore join accept message if already joined (Pull request #6)
13. Channel index verification should use OR on SRV_MAC_NEW_CHANNEL_REQ command (Pull request #5)
14. Corrected the CFList management on JoinAccept. The for loop indexes were wrong. (Pull request #4)
15. Correction of AES key size (Pull request #3)
### 2015-04-30, v3.2.0
* General
1. Updated LoRaMac implementation according to LoRaWAN R1.0 specification
2. General cosmetics corrections
3. Added the support of packed structures when using IAR tool chain
4. Timers: Added a function to get the time in us.
5. Timers: Added a typedef for time variables (TimerTime_t)
6. Radios: Changed the TimeOnAir radio function to return a uint32_t value instead of a double. The value is in us.
7. Radios: Corrected the 250 kHz bandwidth choice for the FSK modem
8. GPS: Added a function that returns if the GPS has a fix or not.
9. GPS: Changed the GetPosition functions to return a latitude and longitude of 0 and altitude of 65535 when no GPS fix.
* LoRaWAN
1. Removed support for previous LoRaMac/LoRaWAN specifications
2. Added missing MAC commands and updated others when necessary
* Corrected the Port 0 MAC commands decryption
* Changed the way the upper layer is notified. Now it is only notified
when all the operations are finished.
When a ClassA Tx cycle starts a timer is launched to check every second if everything is finished.
* Added a new parameter to LoRaMacEventFlags structure that indicates on which Rx window the data has been received.
* Added a new parameter to LoRaMacEventFlags structure that indicates if there is applicative data on the received payload.
* Corrected ADR MAC command behavior
* DutyCycle enforcement implementation (EU868 PHY only)
**REMARK 1** *The regulatory duty cycle enforcement is enabled by default
which means that for lower data rates the node may not transmit a new
frame as quickly as requested.
The formula used to compute the node idle time is*
*Toff = TimeOnAir / DutyCycle - TxTimeOnAir*
*Example:*
*A device just transmitted a 0.5 s long frame on one default channel.
This channel is in a sub-band allowing 1% duty-cycle. Therefore this
whole sub-band (868 MHz - 868.6 MHz) will be unavailable for 49.5 s.*
**REMARK 2** *The duty cycle enforcement can be disabled for test
purposes by calling the LoRaMacSetDutyCycleOn function with false
parameter.*
* Implemented aggregated duty cycle management
* Added a function to create new channels
* Implemented the missing features on the JoinAccept MAC command
* Updated LoRaMacJoinDecrypt function to handle the CFList field.
3. Due to duty cycle management the applicative API has changed.
All applications must be updated accordingly.
4. Added the possibility to chose to use either public or private networks
### 2015-01-30, v3.1.0
* General
1. Started to add support for CooCox CoIDE Integrated Development Environment.
Currently only LoRaMote and SensorNode platform projects are available.
2. Updated GCC compiler linker scripts.
3. Added the support of different tool chains for the HardFault_Handler function.
4. Corrected Radio drivers I&Q signals inversion to be possible in Rx and in Tx.
Added some missing radio state machine initialization.
5. Changed the RSSI values type from int8_t to int16_t. We can have RSSI values below -128 dBm.
6. Corrected SNR computation on RxDone interrupt.
7. Updated radio API to support FHSS and CAD handling.
8. Corrected in SetRxConfig function the FSK modem preamble register name.
9. Added an invalid bandwidth to the Bandwidths table in order to avoid an error
when selecting 250 kHz bandwidth when using FSK modem.
10. Corrected RTC alarm setup which could be set to an invalid date.
11. Added another timer in order increment the tick counter without blocking the normal timer count.
12. Added the possibility to switch between low power timers and normal timers on the fly.
13. I2C driver corrected the 2 bytes internal address management.
Corrected buffer read function when more that 1 byte was to be read.
Added a function to wait for the I2C bus to become IDLE.
14. Added an I2C EEPROM driver.
15. Corrected and improved USB Virtual COM Port management files.
Corrected the USB CDC and USB UART drivers.
16. Added the possibility to analyze a hard fault interrupt.
* LoRaMac
1. Corrected RxWindow2 Datarate management.
2. SrvAckRequested variable was never reset.
3. Corrected tstIndoor applications for LoRaMac R3.0 support.
4. LoRaMac added the possibility to configure almost all the MAC parameters.
5. Corrected the LoRaMacSetNextChannel function.
6. Corrected the port 0 MAC command decoding.
7. Changed all structures declarations to be packed.
8. Corrected the Acknowledgment retries management when only 1 trial is needed.
Before the device was issuing at least 2 trials.
9. Corrected server mac new channel req answer.
10. Added the functions to read the Up and Down Link sequence counters.
11. Corrected SRV_MAC_RX2_SETUP_REQ frequency handling. Added a 100 multiplication.
12. Corrected SRV_MAC_NEW_CHANNEL_REQ. Removed the DutyCycle parameter decoding.
13. Automatically activate the channel once it is created.
14. Corrected NbRepTimeoutTimer initial value. RxWindow2Delay already contains RxWindow1Delay in it.
### 2014-07-18, v3.0.0
* General
1. Added to Radio API the possibility to select the modem.
2. Corrected RSSI reading formulas as well as changed the RSSI and SNR values from double to int8_t type.
3. Changed radio callbacks events to timeout when it is a timeout event and error when it is a CRC error.
4. Radio API updated.
5. Updated ping-pong applications.
6. Updated tx-cw applications.
7. Updated LoRaMac applications in order to handle LoRaMac returned functions calls status.
8. Updated LoRaMac applications to toggle LED2 each time there is an application payload down link.
9. Updated tstIndoor application to handle correctly more than 6 channels.
10. Changed the MPL3115 altitude variable from unsigned to signed value.
11. Replaced the usage of pow(2, n) by defining POW2 functions. Saves ~2 KBytes of code.
12. Corrected an issue potentially arriving when LOW_POWER_MODE_ENABLE wasn't defined.
A timer interrupt could be generated while the TimerList could already be emptied.
* LoRaMac
1. Implemented LoRaMac specification R3.0 changes.
2. MAC commands implemented
* LinkCheckReq **YES**
* LinkCheckAns **YES**
* LinkADRReq **YES**
* LinkADRAns **YES**
* DutyCycleReq **YES**
* DutyCycleAns **YES**
* Rx2SetupReq **YES**
* Rx2SetupAns **YES**
* DevStatusReq **YES**
* DevStatusAns **YES**
* JoinReq **YES**
* JoinAccept **YES**
* NewChannelReq **YES**
* NewChannelAns **YES**
3. Features implemented
* Possibility to shut-down the device **YES**
Possible by issuing DutyCycleReq MAC command.
* Duty cycle management enforcement **NO**
* Acknowledgments retries **YES**
* Unconfirmed messages retries **YES**
### 2014-07-10, v2.3.RC2
* General
1. Corrected all radios antenna switch low power mode handling.
2. SX1276: Corrected antenna switch control.
### 2014-06-06, v2.3.RC1
* General
1. Added the support for SX1276 radio.
2. Radio continuous reception mode correction.
3. Radio driver RxDone callback function API has changed ( size parameter is no more a pointer).
Previous function prototype:
void ( *RxDone )( uint8_t *payload, uint16_t *size, double rssi, double snr, uint8_t rawSnr );
New function prototype:
void ( *RxDone )( uint8_t *payload, uint16_t size, double rssi, double snr, uint8_t rawSnr );
4. Added Bleeper-76 and SensorNode platforms support.
5. Added to the radio drivers a function that generates a random value from
RSSI readings.
6. Added a project to transmit a continuous wave and a project to measure the
the radio sensitivity.
7. Added a bootloader project for the LoRaMote and SensorNode platforms.
8. The LoRaMac application for Bleeper platforms now sends the Selector and LED status plus the sensors values.
* The application payload for the Bleeper platforms is as follows:
LoRaMac port 1:
{ 0xX0/0xX1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }
---------- ---------- ---------- ---------- ----
| | | | |
SELECTOR/LED PRESSURE TEMPERATURE ALTITUDE BATTERY
MSB nibble = SELECTOR (barometric)
LSB bit = LED
9. Redefined rand() and srand() standard C functions. These functions are
redefined in order to get the same behavior across different compiler
tool chains implementations.
10. GPS driver improvements. Made independent of the board platform.
11. Simplified the RTC management.
12. Added a function to the timer driver that checks if a timer is already in
the list or not.
13. Added the UART Overrun bit exception handling to the UART driver.
14. Removed dependency of spi-board files to the "__builtin_ffs" function.
This function is only available on GNU compiler tool suite. Removed --gnu
compiler option from Keil projects. Added own __ffs function
implementation to utilities.h file.
15. Removed obsolete class1 devices support.
16. Known bugs correction.
* LoRaMac
1. MAC commands implemented
* LinkCheckReq **YES**
* LinkCheckAns **YES**
* LinkADRReq **YES**
* LinkADRAns **YES**
* DutyCycleReq **YES** (LoRaMac specification R2.2.1)
* DutyCycleAns **YES** (LoRaMac specification R2.2.1)
* Rx2SetupReq **YES** (LoRaMac specification R2.2.1)
* Rx2SetupAns **YES** (LoRaMac specification R2.2.1)
* DevStatusReq **YES**
* DevStatusAns **YES**
* JoinReq **YES**
* JoinAccept **YES** (LoRaMac specification R2.2.1)
* NewChannelReq **YES** (LoRaMac specification R2.2.1)
* NewChannelAns **YES** (LoRaMac specification R2.2.1)
2. Features implemented
* Possibility to shut-down the device **YES**
Possible by issuing DutyCycleReq MAC command.
* Duty cycle management enforcement **NO**
* Acknowledgments retries **WORK IN PROGRESS**
Not fully debugged. Disabled by default.
* Unconfirmed messages retries **WORK IN PROGRESS** (LoRaMac specification R2.2.1)
3. Implemented LoRaMac specification R2.2.1 changes.
4. Due to new specification the LoRaMacInitNwkIds LoRaMac API function had
to be modified.
Previous function prototype:
void LoRaMacInitNwkIds( uint32_t devAddr, uint8_t *nwkSKey, uint8_t *appSKey );
New function prototype:
void LoRaMacInitNwkIds( uint32_t netID, uint32_t devAddr, uint8_t *nwkSKey, uint8_t *appSKey );
5. Changed the LoRaMac channels management.
6. LoRaMac channels definition has been moved to LoRaMac-board.h file
located in each specific board directory.
### 2014-04-07, v2.2.0
* General
1. Added IMST SK-iM880A starter kit board support to the project.
* The application payload for the SK-iM880A platform is as follows:
LoRaMac port 3:
{ 0x00/0x01, 0x00, 0x00, 0x00 }
---------- ----- ----------
| | |
LED POTI VDD
2. Ping-Pong applications have been split per supported board.
3. Corrected the SX1272 output power management.
Added a variable to store the current Radio channel.
Added missing FSK bit definition.
4. Made fifo functions coding style coherent with the project.
5. UART driver is now independent of the used MCU
### 2014-03-28, v2.1.0
* General
1. The timers and RTC management has been rewritten.
2. Improved the UART and UP501 GPS drivers.
3. Corrected GPIO pin names management.
4. Corrected the antenna switch management in the SX1272 driver.
5. Added to the radio driver the possibility to choose the preamble length
and rxSingle symbol timeout in reception.
6. Added Hex coder selector driver for the Bleeper board.
7. Changed copyright Unicode character to (C) in all source files.
* LoRaMac
1. MAC commands implemented
* LinkCheckReq **YES**
* LinkCheckAns **YES**
* LinkADRReq **YES**
* LinkADRAns **YES**
* DevStatusReq **YES**
* DevStatusAns **YES**
* JoinReq **YES**
* JoinAccept **YES**
2. Added acknowledgments retries management.
Split the LoRaMacSendOnChannel function in LoRaMacPrepareFrame and
LoRaMacSendFrameOnChannel. LoRaMacSendOnChannel now calls the 2 newly
defined functions.
**WARNING**: By default the acknowledgment retries specific code isn't
enabled. The current http://iot.semtech.com server version doesn't support
it.
3. Corrected issues on JoinRequest and JoinAccept MAC commands.
Added LORAMAC_EVENT_INFO_STATUS_MAC_ERROR event info status.
### 2014-02-21, v2.0.0
* General
1. The LoRaMac applications now sends the LED status plus the sensors values.
For the LoRaMote platform the application also sends the GPS coordinates.
* The application payload for the Bleeper platform is as follows:
LoRaMac port 1:
{ 0x00/0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }
---------- ---------- ---------- ---------- ----
| | | | |
LED PRESSURE TEMPERATURE ALTITUDE BATTERY
(barometric)
* The application payload for the LoRaMote platform is as follows:
LoRaMac port 2:
{ 0x00/0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }
---------- ---------- ---------- ---------- ---- ---------------- ---------------- ----------
| | | | | | | |
LED PRESSURE TEMPERATURE ALTITUDE BATTERY LATITUDE LONGITUDE ALTITUDE
(barometric) (gps)
2. Adapted applications to the new MAC layer API.
3. Added sensors drivers implementation.
4. Corrected new or known issues.
* LoRaMac
1. MAC commands implemented
* LinkCheckReq **YES**
* LinkCheckAns **YES**
* LinkADRReq **YES**
* LinkADRAns **YES**
* DevStatusReq **YES**
* DevStatusAns **YES**
* JoinReq **YES (Not tested)**
* JoinAccept **YES (Not tested)**
2. New MAC layer application API implementation.
* Timers and RTC.
1. Still some issues. They will be corrected on next revisions of the firmware.
### 2014-01-24, v1.1.0
* LoRaMac
1. MAC commands implemented
* LinkCheckReq **NO**
* LinkCheckAns **NO**
* LinkADRReq **YES**
* LinkADRAns **YES**
* DevStatusReq **YES**
* DevStatusAns **YES**
2. Implemented an application LED control
If the server sends on port 1 an application payload of one byte with
the following contents:
0: LED off
1: LED on
The node transmits periodically on port 1 the LED status on 1st byte and
the message "Hello World!!!!" the array looks like:
{ 0, 'H', 'e', 'l', 'l', 'o', ' ', 'W', 'o', 'r', 'l', 'd', '!', '!', '!', '!' }
* Timers and RTC.
1. Corrected issues existing in the previous version
2. Known bugs are:
* There is an issue when launching an asynchronous Timer. Will be solved
in a future version
### 2014-01-20, v1.1.RC1
* Added Doc directory. The directory contains:
1. LoRa MAC specification
2. Bleeper board schematic
* LoRaMac has been updated according to Release1 of the specification. Main changes are:
1. MAC API changed.
2. Frame format.
3. ClassA first ADR implementation.
4. MAC commands implemented
* LinkCheckReq **NO**
* LinkCheckAns **NO**
* LinkADRReq **YES**
* LinkADRAns **NO**
* DevStatusReq **NO**
* DevStatusAns **NO**
* Timers and RTC rewriting. Known bugs are:
1. The Radio wakeup time is taken in account for all timings.
2. When opening the second reception window the microcontroller sometimes doesn't enter in low power mode.
### 2013-11-28, v1.0.0
* Initial version of the LoRa MAC node firmware implementation.

View File

@@ -0,0 +1,212 @@
@verbatim
******************************************************************************
* @file st_readme.txt
* @author MCD Application Team
* @brief This file lists the main modification done by STMicroelectronics on
* LoRa for integration with STM32Cube solution.
* For more details on LoRa implementation on STM32Cube, please refer
* to UM2073 "STM32 LORA Expansion Package for STM32Cube "
******************************************************************************
* @attention
*
* <h2><center>&copy; Copyright (c) 2019 STMicroelectronics.
* All rights reserved.</center></h2>
*
* This software component is licensed by ST under BSD 3-Clause license,
* the "License"; You may not use this file except in compliance with the
* License. You may obtain a copy of the License at:
* opensource.org/licenses/BSD-3-Clause
*
******************************************************************************
@endverbatim
### V1.2.4/28-Nov-2019 ###
===============================
+ Implements LoRa Mac from Semtech/StackForce develop branch (31-Oct-2019 commits, version 4.4.2)
+ Patterns/basic and Patterns/modem directory structure change
+ update files license
+ certification obtained with LoRAWAN version v1.0.2 in the following regions:
- EU868
- IN865
- KR920
- AS923
- US915
### V1.2.3/20-Sept-2019 ###
===============================
+ Implements LoRa Mac from Semtech/StackForce develop branch (17-Jun-2019 commits, 4.4.2 release candidate)
https://github.com/Lora-net/LoRaMac-node/tree/6231a5d65806142a6f887e6183227b8da9e49238
+ Various bug fixes and enhancements
+ Removed inclusions of radio.h, utilities.h, etc. from loraMac.h API
+ Lora.c/h and lora-test.c/h moved from Certifications/ to Patterns/Basic
### V1.2.2/17-June-2019 ###
===============================
+ Trace logging & LoRa Mac version display updates
+ Some function prototypes added
### V1.2.1/13-December-2018 ###
===============================
+ Implements LoRa Mac 4.4.2-rc.5 from Semtech/StackForce develop branch
### V1.2.0/10-July-2018 ###
===============================
+ Implements LoRa Mac 4.4.2-rc.1 from Semtech/StackForce develop branch
+ Supports Class B
+ Features secure element API
+ Added RU864 region
+ Removed US915-Hybrid
### V1.1.5/30-March-2018 ###
===============================
+ Implements LoRa Mac 4.4.1 from Semtech/StackForce
### V1.1.4/08-January-2018 ###
===============================
+ Bug fix in McpsIndication related to downlink Application data buffer
### V1.1.3/20-December-2017 ###
===============================
+ Implements LoRa Mac from Semtech/StackForce develop branch (10-Oct-2017 commits, 4.4.1 release candidate)
https://github.com/Lora-net/LoRaMac-node/tree/ae0c9cc5d53ebbc11437dfe9711a1c3a1114dc5f
+ Merge pull request #302 from nestorayuso/patch-3
### V1.1.2/08-September-2017 ###
===============================
+ Implements LoRa Mac 4.4.0 release from Semtech/StackForce
https://github.com/Lora-net/LoRaMac-node/tree/f42be67be402a40b3586724800771bfe13fb18e6
+ AckTimeoutRetriesCounter must be reset every time a new request (unconfirmed or confirmed) is performed.
+ Added verification for the power parameter in order to check that it is greater or equal to 0.
+ Enhancement for regions without FSK modulation support.
+ Bug fix for RX window 2 in class c mode.
+ AdrAckReq bit must be set to false as soon as we reach the lowest datarate.
+ MacCommandsBufferIndex must be reset when the mac commands are being sent on port 0.
+ Fixed RegionCommonSetBandTxDone in order to also update band->LastTxDoneTime when performing the Join procedure.
+ Added verification of payload size for Unconfirmed and Confirmed messages depending on Dwell time.
+ Added missing Rx1 timeout handling.
+ Updated all regions to use MAX output power by default.
+ Merge remote-tracking branch 'origin/develop' into develop
+ Bug fix in KR920 - update the maxEIRP calculation for continuous wave
+ Bug fix in IN865 - Update the band of the default channels
+ Bug fix in AS923 - for RX use always the payload limitation of dwell 0
+ Update function RegionCommonChanVerifyDr. Perform an 'AND' operation for security
+ Move the verification of ADR parameters into the common section. Update all regions with the related changes
+ Update comment for function RegionLinkAdrReq
+ Apply variables to data structure LinkAdrReqParams_t
+ Bug fix for KR920
+ Rename data structure LinkAdrParams_t
+ Issue(#238): Apply missing variable in sSetBandTxDoneParams
+ Bug fix in processing MAC commands for case SRV_MAC_TX_PARAM_SETUP_REQ.
+ Isse(#238): Apply missing variable in struct sBand
+ Update the MAC to enable the server to control the Channels Mask and the number of transmissions even ADR is off
+ Issue(#238): Update the backoff procedure for all regions. Move code parts into the common section
+ Update implementation to allow automatic MAC answers on port 0
+ Issue(#253): Delete all preconfigured channels when performing a join request
+ Initialize variable phyParam in functions RegionXXGetPhyParam
+ Remove assert_param from the radio drivers
+ Synchronize function RegionXXTxConfig
+ Update carrier sense functionality for LBT
+ Issue(#259): Update comment for variable HasLoopedThroughMain
+ Issue(#257): Fix typo in OnRxWindow2TimerEvent
+ Change scientific notation to numeric notation
+ Merge pull request #260 from clmklk/AU915
+ AU915: update Datarate limits according to LoRaWan 1.0.2rB
+ AU915: update Downstream datarate table according to LoRaWan 1.0.2rB
+ Merge pull request #225 from OpenChirp/patch_1
### V1.1.1/01-June-2017 ###
===============================
+ Implements LoRa Mac from Semtech/StackForce develop branch (30-May-2017 commits, 4.4.0 release candidate)
https://github.com/Lora-net/LoRaMac-node/tree/e2f35db75c1b449379d3b520c2d4e5922a9f5c81
+ Issue(235): Update functions RegionXXNextChannel.
+ Issue(238): Update initialization value of nextTxDelay.
+ Issue(234): Report back the aggregated time off.
+ Issue(232): Relocate function call to CalculateBackOff.
+ Issue(239): Update band TX power to the maximum.
+ Update LimitTxPower for US915.
+ Bug fix in function RegionCN470Verify.
+ Bug fix in function RegionAU915Verify.
+ Issue(229): Fix issue when receiving frames in second RX2 in Class C.
+ Add a ommand to get the next lower datarate.
+ Group initializations
+ Update regional definitions of KR920.
+ Update regional definitions of EU868.
+ Issue(239): Update regional definitions of AU915.
+ Update regional definitions of AU915.
+ Update regional definitions of AS923.
+ Update TX power computations.
+ Remove duplicated call to ApplyDrOffset in function RegionRxConfig.
+ Relocate the datarate, up- and downlink dwell time into a structure.
+ Change API of RegionGetPhyParam and the related functions.
+ Bug fix in function LoRaMacQueryTxPossible.
+ Apply patch for dwell time and minimum datarate.
+ Change the default datarate to DR_2 for AS923.
+ Take dwell time for ADR calculations and datarate settings into account.
+ Update LoRaMacQueryTxPossible to reset the MAC commands buffer.
+ Issue(#221): Add the dwell time in function ValidatePayloadLength.
+ Increase the transmission and reception timeout for KR920.
+ Bug fix in functions OnRxWindowXTimerEvent.
+ Remove datarate assignment.
+ Setup the downlink and uplink dwell time default value to 1.
+ Add frequency range check for AS923
+ Issue(#221): Bug fix in max payload size calculation.
+ GitHub reported issues corrections.
+ Changed the AdrAckCounter handling as expected by the test houses.
+ Fix an issue where the node stopped transmitting.
+ Removed useless LoRaMacPayload buffer.
+ MAC layer indications handling simplification.
+ Relocate parameter settings from ResetMacParameters to the initialization.
### V1.1.0/27-February-2017 ###
===============================
+ Implements LoRa Mac 4.4.0 from Semtech/StackForce from the develop branch
### V1.0.3/01-January-2017 ###
===============================
+ Read date between 2 successive read time to make sure date is ok
### V1.0.2/15-November-2016 ###
===============================
+ Corrected 1 bug in LoRaMac-board.h: RX_WND_2_CHANNEL for EU is now back at DR_0
+ Corrected 1 bug in LoRaMac.c for dataRate adaptation
### V1.0.1/15-September-2016 ###
===============================
+ Implements LoRa Mac 4.3.0 from Semtech/StackForce
### V1.0.0/01-July-2016 ###
===============================
+ First R1.0.0 customized version for STM32Cube solution.
+ Comissioning_template.h in /Conf contains all Lora Ids to connect on LoRa network
It is provided as a template. It must be moved to /Projects/inc/ as Comissioning.h
+ All files in Conf/src are provided as template and must be copied in /Projects/src.
+ All files in Conf/inc are provided as template and must be copied in /Projects/inc.
#if 0 and #endif must be removed to enable the template in the user directory
+ Implements LoRa Mac 4.2.0 from Semtech/StackForce
+ \Lora\Mac\LoRaMac.c : replace floating exponent e3 and e6 by int number
+ \Lora\Utilities\delay.c : cast uint32_t
+ Modified intensively timeServer.c
+ new low layer interfacing Cube HAL (hw_rtc.c, hw_gpio.c and hw_spi.c)
+ added lora.c as an interface layer to ease product integration
* <h3><center>&copy; COPYRIGHT STMicroelectronics</center></h3>
*/

View File

@@ -0,0 +1,25 @@
--- Revised BSD License ---
Copyright (c) 2013, SEMTECH S.A.
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 Semtech corporation 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 SEMTECH S.A. 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.

View File

@@ -0,0 +1,418 @@
/*
/ _____) _ | |
( (____ _____ ____ _| |_ _____ ____| |__
\____ \| ___ | (_ _) ___ |/ ___) _ \
_____) ) ____| | | || |_| ____( (___| | | |
(______/|_____)_|_|_| \__)_____)\____)_| |_|
(C)2013 Semtech
Description: Generic radio driver definition
License: Revised BSD License, see LICENSE.TXT file include in the project
Maintainer: Miguel Luis and Gregory Cristian
*/
/**
******************************************************************************
*
* Portions COPYRIGHT 2019 STMicroelectronics
*
* @file radio.h
* @author MCD Application Team
* @brief generic radio driver definition
******************************************************************************
*/
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef __RADIO_H__
#define __RADIO_H__
/* Includes ------------------------------------------------------------------*/
#include <stdint.h>
#include <stdbool.h>
/* Private typedef -----------------------------------------------------------*/
/*!
* Radio driver supported modems
*/
typedef enum
{
MODEM_FSK = 0,
MODEM_LORA,
MODEM_BPSK,
MODEM_SIGFOX_TX,
MODEM_SIGFOX_RX,
}RadioModems_t;
/*!
* Radio driver internal state machine states definition
*/
typedef enum
{
RF_IDLE = 0, //!< The radio is idle
RF_RX_RUNNING, //!< The radio is in reception state
RF_TX_RUNNING, //!< The radio is in transmission state
RF_CAD, //!< The radio is doing channel activity detection
}RadioState_t;
/*!
* \brief Radio driver callback functions
*/
typedef struct
{
/*!
* \brief Tx Done callback prototype.
*/
void ( *TxDone )( void );
/*!
* \brief Tx Timeout callback prototype.
*/
void ( *TxTimeout )( void );
/*!
* \brief Rx Done callback prototype.
*
* \param [IN] payload Received buffer pointer
* \param [IN] size Received buffer size
* \param [IN] rssi RSSI value computed while receiving the frame [dBm]
* \param [IN] snr SNR value computed while receiving the frame [dB]
* FSK : N/A ( set to 0 )
* LoRa: SNR value in dB
*/
void ( *RxDone )( uint8_t *payload, uint16_t size, int16_t rssi, int8_t snr );
/*!
* \brief Rx Timeout callback prototype.
*/
void ( *RxTimeout )( void );
/*!
* \brief Rx Error callback prototype.
*/
void ( *RxError )( void );
/*!
* \brief FHSS Change Channel callback prototype.
*
* \param [IN] currentChannel Index number of the current channel
*/
void ( *FhssChangeChannel )( uint8_t currentChannel );
/*!
* \brief CAD Done callback prototype.
*
* \param [IN] channelDetected Channel Activity detected during the CAD
*/
void ( *CadDone ) ( bool channelActivityDetected );
}RadioEvents_t;
/*!
* \brief Radio driver definition
*/
struct Radio_s
{
/*!
* \brief Initializes the io
*/
// void ( *IoInit )( void );
/*!
* \brief Deinitializes the io
*/
// void ( *IoDeInit )( void );
/*!
* \brief Initializes the radio
*
* \param [IN] events Structure containing the driver callback functions
* \param [OUT] returns radioWakeUpTime
*/
uint32_t ( *Init )( RadioEvents_t *events );
/*!
* Return current radio status
*
* \param status Radio status.[RF_IDLE, RF_RX_RUNNING, RF_TX_RUNNING]
*/
RadioState_t ( *GetStatus )( void );
/*!
* \brief Configures the radio with the given modem
*
* \param [IN] modem Modem to be used [0: FSK, 1: LoRa]
*/
void ( *SetModem )( RadioModems_t modem );
/*!
* \brief Sets the channel frequency
*
* \param [IN] freq Channel RF frequency
*/
void ( *SetChannel )( uint32_t freq );
/*!
* \brief Checks if the channel is free for the given time
*
* \param [IN] modem Radio modem to be used [0: FSK, 1: LoRa]
* \param [IN] freq Channel RF frequency
* \param [IN] rssiThresh RSSI threshold
* \param [IN] maxCarrierSenseTime Max time while the RSSI is measured
*
* \retval isFree [true: Channel is free, false: Channel is not free]
*/
bool ( *IsChannelFree )( RadioModems_t modem, uint32_t freq, int16_t rssiThresh, uint32_t maxCarrierSenseTime );
/*!
* \brief Generates a 32 bits random value based on the RSSI readings
*
* \remark This function sets the radio in LoRa modem mode and disables
* all interrupts.
* After calling this function either Radio.SetRxConfig or
* Radio.SetTxConfig functions must be called.
*
* \retval randomValue 32 bits random value
*/
uint32_t ( *Random )( void );
/*!
* \brief Sets the reception parameters
*
* \param [IN] modem Radio modem to be used [0: FSK, 1: LoRa]
* \param [IN] bandwidth Sets the bandwidth
* FSK : >= 2600 and <= 250000 Hz
* LoRa: [0: 125 kHz, 1: 250 kHz,
* 2: 500 kHz, 3: Reserved]
* \param [IN] datarate Sets the Datarate
* FSK : 600..300000 bits/s
* LoRa: [6: 64, 7: 128, 8: 256, 9: 512,
* 10: 1024, 11: 2048, 12: 4096 chips]
* \param [IN] coderate Sets the coding rate (LoRa only)
* FSK : N/A ( set to 0 )
* LoRa: [1: 4/5, 2: 4/6, 3: 4/7, 4: 4/8]
* \param [IN] bandwidthAfc Sets the AFC Bandwidth (FSK only)
* FSK : >= 2600 and <= 250000 Hz
* LoRa: N/A ( set to 0 )
* \param [IN] preambleLen Sets the Preamble length
* FSK : Number of bytes
* LoRa: Length in symbols (the hardware adds 4 more symbols)
* \param [IN] symbTimeout Sets the RxSingle timeout value
* FSK : timeout in number of bytes
* LoRa: timeout in symbols
* \param [IN] fixLen Fixed length packets [0: variable, 1: fixed]
* \param [IN] payloadLen Sets payload length when fixed length is used
* \param [IN] crcOn Enables/Disables the CRC [0: OFF, 1: ON]
* \param [IN] freqHopOn Enables disables the intra-packet frequency hopping
* FSK : N/A ( set to 0 )
* LoRa: [0: OFF, 1: ON]
* \param [IN] hopPeriod Number of symbols between each hop
* FSK : N/A ( set to 0 )
* LoRa: Number of symbols
* \param [IN] iqInverted Inverts IQ signals (LoRa only)
* FSK : N/A ( set to 0 )
* LoRa: [0: not inverted, 1: inverted]
* \param [IN] rxContinuous Sets the reception in continuous mode
* [false: single mode, true: continuous mode]
*/
void ( *SetRxConfig )( RadioModems_t modem, uint32_t bandwidth,
uint32_t datarate, uint8_t coderate,
uint32_t bandwidthAfc, uint16_t preambleLen,
uint16_t symbTimeout, bool fixLen,
uint8_t payloadLen,
bool crcOn, bool freqHopOn, uint8_t hopPeriod,
bool iqInverted, bool rxContinuous );
/*!
* \brief Sets the transmission parameters
*
* \param [IN] modem Radio modem to be used [0: FSK, 1: LoRa]
* \param [IN] power Sets the output power [dBm]
* \param [IN] fdev Sets the frequency deviation (FSK only)
* FSK : [Hz]
* LoRa: 0
* \param [IN] bandwidth Sets the bandwidth (LoRa only)
* FSK : 0
* LoRa: [0: 125 kHz, 1: 250 kHz,
* 2: 500 kHz, 3: Reserved]
* \param [IN] datarate Sets the Datarate
* FSK : 600..300000 bits/s
* LoRa: [6: 64, 7: 128, 8: 256, 9: 512,
* 10: 1024, 11: 2048, 12: 4096 chips]
* \param [IN] coderate Sets the coding rate (LoRa only)
* FSK : N/A ( set to 0 )
* LoRa: [1: 4/5, 2: 4/6, 3: 4/7, 4: 4/8]
* \param [IN] preambleLen Sets the preamble length
* FSK : Number of bytes
* LoRa: Length in symbols (the hardware adds 4 more symbols)
* \param [IN] fixLen Fixed length packets [0: variable, 1: fixed]
* \param [IN] crcOn Enables disables the CRC [0: OFF, 1: ON]
* \param [IN] freqHopOn Enables disables the intra-packet frequency hopping
* FSK : N/A ( set to 0 )
* LoRa: [0: OFF, 1: ON]
* \param [IN] hopPeriod Number of symbols between each hop
* FSK : N/A ( set to 0 )
* LoRa: Number of symbols
* \param [IN] iqInverted Inverts IQ signals (LoRa only)
* FSK : N/A ( set to 0 )
* LoRa: [0: not inverted, 1: inverted]
* \param [IN] timeout Transmission timeout [ms]
*/
void ( *SetTxConfig )( RadioModems_t modem, int8_t power, uint32_t fdev,
uint32_t bandwidth, uint32_t datarate,
uint8_t coderate, uint16_t preambleLen,
bool fixLen, bool crcOn, bool freqHopOn,
uint8_t hopPeriod, bool iqInverted, uint32_t timeout );
/*!
* \brief Checks if the given RF frequency is supported by the hardware
*
* \param [IN] frequency RF frequency to be checked
* \retval isSupported [true: supported, false: unsupported]
*/
bool ( *CheckRfFrequency )( uint32_t frequency );
/*!
* \brief Computes the packet time on air in ms for the given payload
*
* \Remark Can only be called once SetRxConfig or SetTxConfig have been called
*
* \param [IN] modem Radio modem to be used [0: FSK, 1: LoRa]
* \param [IN] pktLen Packet payload length
*
* \retval airTime Computed airTime (ms) for the given packet payload length
*/
uint32_t ( *TimeOnAir )( RadioModems_t modem, uint8_t pktLen );
/*!
* \brief Sends the buffer of size. Prepares the packet to be sent and sets
* the radio in transmission
*
* \param [IN]: buffer Buffer pointer
* \param [IN]: size Buffer size
*/
void ( *Send )( uint8_t *buffer, uint8_t size );
/*!
* \brief Sets the radio in sleep mode
*/
void ( *Sleep )( void );
/*!
* \brief Sets the radio in standby mode
*/
void ( *Standby )( void );
/*!
* \brief Sets the radio in reception mode for the given time
* \param [IN] timeout Reception timeout [ms]
* [0: continuous, others timeout]
*/
void ( *Rx )( uint32_t timeout );
/*!
* \brief Start a Channel Activity Detection
*/
void ( *StartCad )( void );
/*!
* \brief Sets the radio in continuous wave transmission mode
*
* \param [IN]: freq Channel RF frequency
* \param [IN]: power Sets the output power [dBm]
* \param [IN]: time Transmission mode timeout [s]
*/
void ( *SetTxContinuousWave )( uint32_t freq, int8_t power, uint16_t time );
/*!
* \brief Reads the current RSSI value
*
* \retval rssiValue Current RSSI value in [dBm]
*/
int16_t ( *Rssi )( RadioModems_t modem );
/*!
* \brief Writes the radio register at the specified address
*
* \param [IN]: addr Register address
* \param [IN]: data New register value
*/
void ( *Write )( uint16_t addr, uint8_t data );
/*!
* \brief Reads the radio register at the specified address
*
* \param [IN]: addr Register address
* \retval data Register value
*/
uint8_t ( *Read )( uint16_t addr );
/*!
* \brief Writes multiple radio registers starting at address
*
* \param [IN] addr First Radio register address
* \param [IN] buffer Buffer containing the new register's values
* \param [IN] size Number of registers to be written
*/
// void ( *WriteBuffer )( uint16_t addr, uint8_t *buffer, uint8_t size );
/*!
* \brief Reads multiple radio registers starting at address
*
* \param [IN] addr First Radio register address
* \param [OUT] buffer Buffer where to copy the registers data
* \param [IN] size Number of registers to be read
*/
// void ( *ReadBuffer )( uint16_t addr, uint8_t *buffer, uint8_t size );
/*!
* \brief Sets the maximum payload length.
*
* \param [IN] modem Radio modem to be used [0: FSK, 1: LoRa]
* \param [IN] max Maximum payload length in bytes
*/
void ( *SetMaxPayloadLength )( RadioModems_t modem, uint8_t max );
/*!
* \brief Sets the network to public or private. Updates the sync byte.
*
* \remark Applies to LoRa modem only
*
* \param [IN] enable if true, it enables a public network
*/
void ( *SetPublicNetwork )( bool enable );
/*!
* \brief Gets the time required for the board plus radio to get out of sleep.[ms]
*
* \retval time Radio plus board wakeup time in ms.
*/
uint32_t ( *GetWakeupTime )( void );
/*!
* \brief Process radio irq
*/
void ( *IrqProcess )( void );
/*
* The next functions are available only on SX126x radios.
*/
/*!
* \brief Sets the radio in reception mode with Max LNA gain for the given time
*
* \remark Available on SX126x radios only.
*
* \param [IN] timeout Reception timeout [ms]
* [0: continuous, others timeout]
*/
void ( *RxBoosted )( uint32_t timeout );
/*!
* \brief Sets the Rx duty cycle management parameters
*
* \remark Available on SX126x radios only.
*
* \param [in] rxTime Structure describing reception timeout value
* \param [in] sleepTime Structure describing sleep timeout value
*/
void ( *SetRxDutyCycle ) ( uint32_t rxTime, uint32_t sleepTime );
/*!
* @brief Sets the Transmitter in continuous PRBS mode
*
* \remark power and datarate shall be configured prior calling TxPrbs
*/
void (*TxPrbs) ( void );
/*!
* @brief Sets the Transmitter in continuous unmodulated Carrier mode
*/
void (*TxCw) ( void );
};
/*!
* \brief Radio driver
*
* \remark This variable is defined and initialized in the specific radio
* board implementation
*/
extern const struct Radio_s Radio;
/* Private defines -----------------------------------------------------------*/
/* Private macros ------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/
/* Global variables ----------------------------------------------------------*/
/* Private function prototypes -----------------------------------------------*/
/* Functions Definition ------------------------------------------------------*/
#endif // __RADIO_H__
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/

View File

@@ -0,0 +1,61 @@
/**
******************************************************************************
* @file mw_log_conf.h
* @author MCD Application Team
* @brief Interface layer CM4 System to MBMUX (Mailbox Multiplexer)
******************************************************************************
* @attention
*
* <h2><center>&copy; Copyright (c) 2019 STMicroelectronics.
* All rights reserved.</center></h2>
*
* This software component is licensed by ST under BSD 3-Clause license,
* the "License"; You may not use this file except in compliance with the
* License. You may obtain a copy of the License at:
* opensource.org/licenses/BSD-3-Clause
*
******************************************************************************
*/
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef __MW_LOG_CONF_H__
#define __MW_LOG_CONF_H__
#ifdef __cplusplus
extern "C" {
#endif
/* Includes ------------------------------------------------------------------*/
#include <stdint.h>
#include "trace.h"
/* Exported types ------------------------------------------------------------*/
/* Exported constants --------------------------------------------------------*/
#define MW_LOG_ENABLED
/* Exported macro ------------------------------------------------------------*/
#ifdef MW_LOG_ENABLED
#define PPRINTF(...) do{ } while( 0!= TraceSend(TIME_STAMP_OFF, 0, __VA_ARGS__) ) //Polling Mode
#define TPRINTF(...) do{ {TraceSend(TIME_STAMP_ON, 0, __VA_ARGS__);} }while(0)//with timestamp
#define PRINTF(...) do{ {TraceSend(TIME_STAMP_OFF, 0, __VA_ARGS__);} }while(0)
#define MW_LOG(VL, TS, ...) do{ {TraceSend(TS, VL, __VA_ARGS__);} }while(0)
#else
#define PPRINTF(...)
#define TPRINTF(...)
#define PRINTF(...)
#define MW_LOG(VL, TS, ...)
#endif
/* Exported functions ------------------------------------------------------- */
#ifdef __cplusplus
}
#endif
#endif /*__MW_LOG_CONF_H__ */
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,51 @@
/*******************************************************************************
* @file radio_conf.h
* @author MCD Application Team
* @brief driver sx1276 board (sx1276mb1mas for EU and sx1276mb1las for US)
******************************************************************************
* @attention
*
* <h2><center>&copy; Copyright (c) 2019 STMicroelectronics.
* All rights reserved.</center></h2>
*
* This software component is licensed by ST under BSD 3-Clause license,
* the "License"; You may not use this file except in compliance with the
* License. You may obtain a copy of the License at:
* opensource.org/licenses/BSD-3-Clause
*
******************************************************************************
*/
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef __RADIO_CONF_H__
#define __RADIO_CONF_H__
#ifdef __cplusplus
extern "C" {
#endif
/* Includes ------------------------------------------------------------------*/
#include "platform.h"
/* Exported types ------------------------------------------------------------*/
/* Defines ------------------------*/
#define RADIO_RX_BUF_SIZE 255
/* Function mapping */
#define RADIO_DELAY_MS HAL_Delay
#define RADIO_MEMSET8( dest, value, size ) UTIL_MEM_cpy_8( dest, value, size)
#define LET_SUBGHZ_MW_USING_DGB_LINE1_PIN
#define LET_SUBGHZ_MW_USING_DGB_LINE2_PIN
/* Exported constants --------------------------------------------------------*/
/* External variables --------------------------------------------------------*/
/* Exported macros -----------------------------------------------------------*/
/* Exported functions ------------------------------------------------------- */
#ifdef __cplusplus
}
#endif
#endif /* __RADIO_CONF_H__*/
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/

View File

@@ -0,0 +1,56 @@
/******************************************************************************
* @file radio_mw_version.h
* @author MCD Application Team
* @brief defines the radio driver version
******************************************************************************
* @attention
*
* <h2><center>&copy; Copyright (c) 2019 STMicroelectronics.
* All rights reserved.</center></h2>
*
* This software component is licensed by ST under BSD 3-Clause license,
* the "License"; You may not use this file except in compliance with the
* License. You may obtain a copy of the License at:
* opensource.org/licenses/BSD-3-Clause
*
******************************************************************************
*/
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef __RADIO_MW_VERSION_H__
#define __RADIO_MW_VERSION_H__
#ifdef __cplusplus
extern "C" {
#endif
/* Includes ------------------------------------------------------------------*/
/* Exported constants --------------------------------------------------------*/
/* __SUBGH_RADIO_TYPE: 0x01 WTM32WL
0x61 sx126x
0x72 sx1272
0x76 sx1276 */
#define __SUBGH_RADIO_TYPE (0x01U) /*!< [31:24] main version */
#define __SUBGH_MW_VERSION_MAIN (0x01U) /*!< [23:16] main version */
#define __SUBGH_MW_VERSION_SUB1 (0x00U) /*!< [15:8] sub1 version */
#define __SUBGH_MW_VERSION_SUB2 (0x00U) /*!< [7:0] sub2 version */
#define __SUBGH_MW_VERSION ((__SUBGH_RADIO_TYPE <<24)\
|(__SUBGH_MW_VERSION_MAIN << 16)\
|(__SUBGH_MW_VERSION_SUB1 << 8 )\
|(__SUBGH_MW_VERSION_SUB2))
/* Exported types ------------------------------------------------------------*/
/* External variables --------------------------------------------------------*/
/* Exported macros -----------------------------------------------------------*/
/* Exported functions ------------------------------------------------------- */
#ifdef __cplusplus
}
#endif
#endif /*__RADIO_MW_VERSION_H__*/
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/

View File

@@ -0,0 +1,142 @@
/**
******************************************************************************
* @file adc.c
* @author MCD Application Team
* @brief configuration of the ADC instances
******************************************************************************
* @attention
*
* <h2><center>&copy; Copyright (c) 2019 STMicroelectronics.
* All rights reserved.</center></h2>
*
* This software component is licensed by ST under Ultimate Liberty license
* SLA0044, the "License"; You may not use this file except in compliance with
* the License. You may obtain a copy of the License at:
* www.st.com/SLA0044
*
******************************************************************************
*/
/* Includes ------------------------------------------------------------------*/
#include "platform.h"
#include "adc.h"
#include "dma.h"
#ifdef HAL_ADC_MODULE_ENABLED
/* USER CODE BEGIN 0 */
/* USER CODE END 0 */
ADC_HandleTypeDef hadc1;
DMA_HandleTypeDef hdma_adc1;
/* Private function prototypes -----------------------------------------------*/
/* Functions Definition ------------------------------------------------------*/
/**
* @brief ADC1 Initialization Function
* @param None
* @retval None
*/
void MX_ADC1_Init(void)
{
/* USER CODE BEGIN ADC1_Init 0 */
/* USER CODE END ADC1_Init 0 */
/* USER CODE BEGIN ADC1_Init 1 */
/* USER CODE END ADC1_Init 1 */
/** Common config
*/
hadc1.Instance = ADC1;
hadc1.Init.ClockPrescaler = ADC_CLOCK_SYNC_PCLK_DIV2;
hadc1.Init.Resolution = ADC_RESOLUTION_12B;
hadc1.Init.DataAlign = ADC_DATAALIGN_RIGHT;
hadc1.Init.ScanConvMode = ADC_SCAN_DISABLE; /* Sequencer set to fully configurable: only the rank 1 is enabled (no scan sequence on several ranks) */
hadc1.Init.EOCSelection = ADC_EOC_SINGLE_CONV;
hadc1.Init.ContinuousConvMode = DISABLE; /* Continuous mode disabled to have only 1 conversion at each conversion trig */
hadc1.Init.NbrOfConversion = 1; /* Parameter discarded because sequencer is disabled. Parameter relevancy depending on setting of parameter "ScanConvMode" */
hadc1.Init.DiscontinuousConvMode = DISABLE; /* Parameter discarded because sequencer is disabled */
hadc1.Init.ExternalTrigConv = ADC_SOFTWARE_START; /* Software start to trig the 1st conversion manually, without external event */
hadc1.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_NONE; /* Parameter discarded because trig of conversion by software start (no external event) */
hadc1.Init.DMAContinuousRequests = DISABLE; /* ADC with DMA transfer: continuous requests to DMA disabled (default state) since DMA is not used in this example. */
hadc1.Init.Overrun = ADC_OVR_DATA_OVERWRITTEN;
hadc1.Init.SamplingTimeCommon1 = LL_ADC_SAMPLINGTIME_160CYCLES_5;
hadc1.Init.OversamplingMode = DISABLE;
hadc1.Init.TriggerFrequencyMode = ADC_TRIGGER_FREQ_HIGH;
if (HAL_ADC_Init(&hadc1) != HAL_OK)
{
Error_Handler();
}
if (HAL_ADCEx_Calibration_Start(&hadc1) != HAL_OK)
{
Error_Handler();
}
/* USER CODE BEGIN ADC1_Init 2 */
/* USER CODE END ADC1_Init 2 */
}
/**
* @brief ADC MSP Initialization
* This function configures the hardware resources used in this example
* @param hadc: ADC handle pointer
* @retval None
*/
void HAL_ADC_MspInit(ADC_HandleTypeDef *hadc)
{
/*##-1- Enable peripherals and GPIO Clocks #################################*/
/* Enable clock of GPIO associated to the peripheral channels */
/* Enable clock of ADCx peripheral (core clock) */
__HAL_RCC_ADC_CLK_ENABLE();
/* Note: In case of usage of asynchronous clock for ADC, with ADC setting */
/* "AdcHandle.Init.ClockPrescaler = ADC_CLOCK_ASYNC_DIVx", */
/* the clock source has to be enabled at RCC top level using function */
/* "HAL_RCCEx_PeriphCLKConfig()" or macro "__HAL_RCC_ADC_CONFIG()" */
/* (refer to comments in driver file header). */
/*##-4- Configure the NVIC #################################################*/
/* NVIC configuration for ADC interrupt */
/* Priority: high-priority */
}
/**
* @brief ADC MSP De-Initialization
* This function freeze the hardware resources used in this example
* @param hadc: ADC handle pointer
* @retval None
*/
void HAL_ADC_MspDeInit(ADC_HandleTypeDef *hadc)
{
if (hadc->Instance == ADC1)
{
/* USER CODE BEGIN ADC1_MspDeInit 0 */
/* USER CODE END ADC1_MspDeInit 0 */
/* Peripheral clock disable */
__HAL_RCC_ADC_CLK_DISABLE();
/**ADC1 GPIO Configuration
PC3 ------> ADC1_IN4
*/
/* USER CODE BEGIN ADC1_MspDeInit 1 */
/* USER CODE END ADC1_MspDeInit 1 */
}
}
#endif
/* USER CODE BEGIN 1 */
/* USER CODE END 1 */
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/

View File

@@ -0,0 +1,179 @@
/**
******************************************************************************
* @file adc_if.c
* @author MCD Application Team
* @brief Read status related to the chip (battery level, VREF, chip temperature)
******************************************************************************
* @attention
*
* <h2><center>&copy; Copyright (c) 2019 STMicroelectronics.
* All rights reserved.</center></h2>
*
* This software component is licensed by ST under Ultimate Liberty license
* SLA0044, the "License"; You may not use this file except in compliance with
* the License. You may obtain a copy of the License at:
* www.st.com/SLA0044
*
******************************************************************************
*/
/* Includes ------------------------------------------------------------------*/
#include "adc_if.h"
#include "app_system.h"
#ifdef HAL_ADC_MODULE_ENABLED
#include "adc.h"
#endif
/* External variables ---------------------------------------------------------*/
#ifdef HAL_ADC_MODULE_ENABLED
extern ADC_HandleTypeDef hadc1;
#endif
/* Private typedef -----------------------------------------------------------*/
/* Private define ------------------------------------------------------------*/
/*from dtatsheet*/
#define TEMPSENSOR_TYP_CAL1_V (( int32_t) 760) /* Internal temperature sensor, parameter V30 (unit: mV). Refer to device datasheet for min/typ/max values. */
#define TEMPSENSOR_TYP_AVGSLOPE (( int32_t) 2500) /* Internal temperature sensor, parameter Avg_Slope (unit: uV/DegCelsius). Refer to device datasheet for min/typ/max values. */
#define TEMPSENSOR_CAL_VREF ((uint32_t) 3000) /* Vdda value with which temperature sensor has been calibrated in production (+-10 mV). */
/* Private macro -------------------------------------------------------------*/
#define __LL_ADC_CALC_VREFANALOG_VOLTAGE_TEMPORARY(__VREFINT_ADC_DATA__,\
__ADC_RESOLUTION__) \
(((uint32_t)(*VREFINT_CAL_ADDR) * VREFINT_CAL_VREF) \
/ __LL_ADC_CONVERT_DATA_RESOLUTION((__VREFINT_ADC_DATA__), \
(__ADC_RESOLUTION__), \
LL_ADC_RESOLUTION_12B) \
)
/* Private variables ---------------------------------------------------------*/
/* Private function prototypes -----------------------------------------------*/
static uint32_t ADC_ReadChannels(uint32_t channel);
/* Functions Definition ------------------------------------------------------*/
/**
* @brief This function initializes the ADC
* @param none
* @retval none
*/
void SYS_InitMeasurement(void)
{
hadc1.Instance = ADC1;
}
void SYS_DeInitMeasurement(void)
{
}
int16_t SYS_GetTemperatureLevel(void)
{
int16_t temperatureDegreeC = 6400; /*25degreeC in q7.8*/
#ifdef HAL_ADC_MODULE_ENABLED
uint32_t measuredLevel = 0;
uint16_t batteryLevelmV = SYS_GetBatteryLevel();
measuredLevel = ADC_ReadChannels(ADC_CHANNEL_TEMPSENSOR);
/* #warning "to be replaced by __LL_ADC_CALC_TEMPERATURE when calibration data will be set in prod"*/
temperatureDegreeC = __LL_ADC_CALC_TEMPERATURE_TYP_PARAMS(TEMPSENSOR_TYP_AVGSLOPE,
TEMPSENSOR_TYP_CAL1_V,
TEMPSENSOR_CAL1_TEMP,
batteryLevelmV,
measuredLevel,
LL_ADC_RESOLUTION_12B);
/*to be replaced */
APP_LOG("temp= %d\n\r", temperatureDegreeC);
/* from int16 to q8.7*/
temperatureDegreeC <<= 8;
#endif /* HAL_ADC_MODULE_ENABLED */
return (int16_t) temperatureDegreeC;
}
/**
* @brief This function return the battery level
* @param none
* @retval the battery level in mV
*/
uint16_t SYS_GetBatteryLevel(void)
{
uint16_t batteryLevelmV = 3300;
#ifdef HAL_ADC_MODULE_ENABLED
uint32_t measuredLevel = 0;
measuredLevel = ADC_ReadChannels(ADC_CHANNEL_VREFINT);
if (measuredLevel == 0)
{
batteryLevelmV = 0;
}
else
{
batteryLevelmV = (3300 * 1510) / measuredLevel;
/* #warning "to be replaced by __LL_ADC_CALC_VREFANALOG_VOLTAGE when calibration data will be set in prod" */
}
#endif /* HAL_ADC_MODULE_ENABLED */
return batteryLevelmV;
}
/* Private function definition -----------------------------------------------*/
/**
* @brief This function reads the ADC channel
* @param Channel
* @retval Value
*/
static uint32_t ADC_ReadChannels(uint32_t channel)
{
uint32_t ADCxConvertedValues = 0;
#ifdef HAL_ADC_MODULE_ENABLED
ADC_ChannelConfTypeDef sConfig = {0};
MX_ADC1_Init();
/** Configure Regular Channel */
sConfig.Channel = channel;
sConfig.Rank = ADC_REGULAR_RANK_1;
sConfig.SamplingTime = ADC_SAMPLINGTIME_COMMON_1;
if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK)
{
Error_Handler();
}
if (HAL_ADC_Start(&hadc1) != HAL_OK)
{
/* Start Error */
Error_Handler();
}
/** Wait for end of conversion */
HAL_ADC_PollForConversion(&hadc1, HAL_MAX_DELAY);
/* Workaround for tempsensor value*/
if (channel == ADC_CHANNEL_TEMPSENSOR)
{
if (HAL_ADC_Start(&hadc1) != HAL_OK)
{
/* Start Error */
Error_Handler();
}
/** Wait for end of conversion */
HAL_ADC_PollForConversion(&hadc1, HAL_MAX_DELAY);
}
/** Wait for end of conversion */
HAL_ADC_Stop(&hadc1) ; /* it calls also ADC_Disable() */
ADCxConvertedValues = HAL_ADC_GetValue(&hadc1);
HAL_ADC_DeInit(&hadc1);
#endif /* HAL_ADC_MODULE_ENABLED */
return ADCxConvertedValues;
}
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/

View File

@@ -0,0 +1,56 @@
/**
******************************************************************************
* @file dma.c
* @author MCD Application Team
* @brief configuration of all the requested memory to memory DMA transfers
******************************************************************************
* @attention
*
* <h2><center>&copy; Copyright (c) 2019 STMicroelectronics.
* All rights reserved.</center></h2>
*
* This software component is licensed by ST under Ultimate Liberty license
* SLA0044, the "License"; You may not use this file except in compliance with
* the License. You may obtain a copy of the License at:
* www.st.com/SLA0044
*
******************************************************************************
*/
/* Includes ------------------------------------------------------------------*/
#include "dma.h"
/* USER CODE BEGIN 0 */
/* USER CODE END 0 */
/*----------------------------------------------------------------------------*/
/* Configure DMA */
/*----------------------------------------------------------------------------*/
/* USER CODE BEGIN 1 */
/* USER CODE END 1 */
/**
* Enable DMA controller clock
*/
void MX_DMA_Init(void)
{
/* DMA controller clock enable */
__HAL_RCC_DMA1_CLK_ENABLE();
#ifdef HAL_ADC_MODULE_ENABLED
/* DMA interrupt init */
/* DMA1_Channel1_IRQn interrupt configuration */
HAL_NVIC_SetPriority(DMA1_Channel1_IRQn, 1, 0);
HAL_NVIC_EnableIRQ(DMA1_Channel1_IRQn);
#endif
/* DMA1_Channel7_IRQn interrupt configuration */
HAL_NVIC_SetPriority(DMA1_Channel7_IRQn, 1, 0);
HAL_NVIC_EnableIRQ(DMA1_Channel7_IRQn);
}
/* USER CODE BEGIN 2 */
/* USER CODE END 2 */
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/

View File

@@ -29,9 +29,9 @@ void board_init(void)
{
HAL_Init();
SystemClock_Config();
MX_LPUART1_UART_Init();
MX_USART1_UART_Init();
MX_USART2_UART_Init();
SystemApp_Init();
MX_LoRaWAN_Init();
}
/**
@@ -75,6 +75,7 @@ void SystemClock_Config(void)
}
}
/* USER CODE BEGIN 4 */
/* USER CODE END 4 */

Some files were not shown because too many files have changed in this diff Show More