mirror of
https://github.com/Ai-Thinker-Open/Ai-Thinker-Open_RTL8710BX_ALIOS_SDK.git
synced 2026-07-04 01:45:39 +00:00
rel_1.6.0 init
This commit is contained in:
commit
27b3e2883d
19359 changed files with 8093121 additions and 0 deletions
2
Living_SDK/kernel/protocols/lorawan/README.md
Normal file
2
Living_SDK/kernel/protocols/lorawan/README.md
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
#lib_lorawan
|
||||
This is lib_lorawan component.
|
||||
115
Living_SDK/kernel/protocols/lorawan/commissioning.h
Normal file
115
Living_SDK/kernel/protocols/lorawan/commissioning.h
Normal file
|
|
@ -0,0 +1,115 @@
|
|||
/*
|
||||
/ _____) _ | |
|
||||
( (____ _____ ____ _| |_ _____ ____| |__
|
||||
\____ \| ___ | (_ _) ___ |/ ___) _ \
|
||||
_____) ) ____| | | || |_| ____( (___| | | |
|
||||
(______/|_____)_|_|_| \__)_____)\____)_| |_|
|
||||
(C)2015 Semtech
|
||||
|
||||
Description: End device commissioning parameters
|
||||
|
||||
License: Revised BSD License, see LICENSE.TXT file include in the project
|
||||
|
||||
Maintainer: Miguel Luis and Gregory Cristian
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2015-2017 Alibaba Group Holding Limited
|
||||
*/
|
||||
|
||||
#ifndef __LORA_COMMISSIONING_H__
|
||||
#define __LORA_COMMISSIONING_H__
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* Exported types ------------------------------------------------------------*/
|
||||
/* Exported constants --------------------------------------------------------*/
|
||||
/* External variables --------------------------------------------------------*/
|
||||
/* Exported macros -----------------------------------------------------------*/
|
||||
/* Exported functions ------------------------------------------------------- */
|
||||
/**
|
||||
* When set to 1 the application uses the Over-the-Air activation procedure
|
||||
* When set to 0 the application uses the Personalization activation procedure
|
||||
*/
|
||||
#define OVER_THE_AIR_ACTIVATION 1
|
||||
|
||||
/**
|
||||
* Indicates if the end-device is to be connected to a private or public network
|
||||
*/
|
||||
#define LORAWAN_PUBLIC_NETWORK true
|
||||
|
||||
/**
|
||||
* When set to 1 DevEui is LORAWAN_DEVICE_EUI
|
||||
* When set to 0 DevEui is automatically generated by calling
|
||||
* BoardGetUniqueId function
|
||||
*/
|
||||
#define STATIC_DEVICE_EUI 1
|
||||
|
||||
/**
|
||||
* Mote device IEEE EUI (big endian)
|
||||
*
|
||||
* \remark see STATIC_DEVICE_EUI comments
|
||||
*/
|
||||
#define LORAWAN_DEVICE_EUI { 0xd8, 0x96, 0xe0, 0xff, 0x00, 0x00, 0x02, 0x2a }
|
||||
|
||||
/**
|
||||
* Application IEEE EUI (big endian)
|
||||
*/
|
||||
#define LORAWAN_APPLICATION_EUI { 0xd8, 0x96, 0xe0, 0xe0, 0x00, 0x00, 0xda, 0xb0 }
|
||||
|
||||
/**
|
||||
* AES encryption/decryption cipher application key
|
||||
*/
|
||||
#define LORAWAN_APPLICATION_KEY { 0xDC, 0x61, 0x6E, 0xC9, 0xC0, 0x8E, 0x10, 0xAB, 0x47, 0x61, 0x6A, 0xB0, 0x35, 0x37, 0xA7, 0x53 }
|
||||
/**
|
||||
* Current network ID
|
||||
*/
|
||||
#define LORAWAN_NETWORK_ID ( uint32_t )0
|
||||
|
||||
/**
|
||||
* When set to 1 DevAdd is LORAWAN_DEVICE_ADDRESS
|
||||
* When set to 0 DevAdd is automatically generated using
|
||||
* a pseudo random generator seeded with a value derived from
|
||||
* BoardUniqueId value
|
||||
*/
|
||||
#define STATIC_DEVICE_ADDRESS 0
|
||||
/**
|
||||
* Device address on the network (big endian)
|
||||
*
|
||||
* \remark see STATIC_DEVICE_ADDRESS comments
|
||||
*/
|
||||
#define LORAWAN_DEVICE_ADDRESS ( uint32_t )0x0100000a
|
||||
|
||||
/**
|
||||
* AES encryption/decryption cipher network session key
|
||||
*/
|
||||
#define LORAWAN_NWKSKEY { 0x2B, 0x7E, 0x15, 0x16, 0x28, 0xAE, 0xD2, 0xA6, 0xAB, 0xF7, 0x15, 0x88, 0x09, 0xCF, 0x4F, 0x3C }
|
||||
|
||||
/**
|
||||
* AES encryption/decryption cipher application session key
|
||||
*/
|
||||
#define LORAWAN_APPSKEY { 0x2B, 0x7E, 0x15, 0x16, 0x28, 0xAE, 0xD2, 0xA6, 0xAB, 0xF7, 0x15, 0x88, 0x09, 0xCF, 0x4F, 0x3C }
|
||||
|
||||
/**
|
||||
* Multicast address
|
||||
*/
|
||||
#define LORAWAN_MULTICAST_ADDRESS 0x06344bf2
|
||||
|
||||
/**
|
||||
* AES encryption/decryption cipher network session key for multicast
|
||||
*/
|
||||
#define LORAWAN_MULTICAST_NWKSKEY { 0x65, 0xe4, 0x48, 0x3d, 0xe3, 0xa9, 0xce, 0xb1, 0x50, 0xd8, 0x86, 0xf3, 0x61, 0x46, 0x02, 0xb5 }
|
||||
|
||||
/**
|
||||
* AES encryption/decryption cipher application session key for multicast
|
||||
*/
|
||||
#define LORAWAN_MULTICAST_APPSKEY { 0xc2, 0x65, 0x67, 0xa3, 0xec, 0xd3, 0x96, 0x67, 0xd6, 0x23, 0xf8, 0x7a, 0xe1, 0x6c, 0x12, 0x23 }
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __LORA_COMMISSIONING_H__ */
|
||||
151
Living_SDK/kernel/protocols/lorawan/linkwan/include/linkwan.h
Normal file
151
Living_SDK/kernel/protocols/lorawan/linkwan/include/linkwan.h
Normal file
|
|
@ -0,0 +1,151 @@
|
|||
/*
|
||||
* Copyright (C) 2015-2017 Alibaba Group Holding Limited
|
||||
*/
|
||||
|
||||
#ifndef LINKWAN_H
|
||||
#define LINKWAN_H
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include "linkwan_config.h"
|
||||
|
||||
#define JOINREQ_NBTRIALS 3
|
||||
|
||||
typedef enum node_mode_s
|
||||
{
|
||||
NODE_MODE_NORMAL = 0,
|
||||
NODE_MODE_REPEATER = 1, // Alibaba Node Repeater
|
||||
NODE_MODE_AUTOSWITCH = 2, // switch between normal and repeater
|
||||
} node_mode_t;
|
||||
|
||||
typedef enum node_freq_type_s
|
||||
{
|
||||
FREQ_TYPE_INTER = 0, // uplink and downlink use different frequencies
|
||||
FREQ_TYPE_INTRA = 1, // uplink and downlink use same frequencies
|
||||
FREQ_TYPE_MAX,
|
||||
} node_freq_type_t;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
VALID_LORA_CONFIG = 0xbeef,
|
||||
INVALID_LORA_CONFIG = 0xfffe,
|
||||
};
|
||||
|
||||
typedef struct lora_config_s
|
||||
{
|
||||
uint32_t freqband;
|
||||
int8_t datarate;
|
||||
uint16_t flag;
|
||||
} lora_config_t;
|
||||
|
||||
typedef struct lora_dev_s
|
||||
{
|
||||
uint8_t dev_eui[8];
|
||||
uint8_t app_eui[8];
|
||||
uint8_t app_key[16];
|
||||
int8_t class;
|
||||
uint8_t mode; // normal or repeater
|
||||
uint16_t mask;
|
||||
uint16_t flag;
|
||||
} lora_dev_t;
|
||||
|
||||
typedef enum join_method_s
|
||||
{
|
||||
STORED_JOIN_METHOD = 0,
|
||||
DEF_JOIN_METHOD = 1,
|
||||
SCAN_JOIN_METHOD = 2,
|
||||
JOIN_METHOD_NUM
|
||||
} join_method_t;
|
||||
|
||||
#ifdef CONFIG_DEBUG_LINKWAN
|
||||
#include "debug.h"
|
||||
#define DBG_LINKWAN(...) PRINTF(__VA_ARGS__)
|
||||
#else
|
||||
#define DBG_LINKWAN(...)
|
||||
#define LORA_LOG(...)
|
||||
#endif
|
||||
|
||||
typedef enum eTxEventType
|
||||
{
|
||||
TX_ON_TIMER,
|
||||
TX_ON_EVENT,
|
||||
TX_ON_NONE
|
||||
} TxEventType_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint8_t *Buff;
|
||||
uint8_t BuffSize;
|
||||
uint8_t Port;
|
||||
} lora_AppData_t;
|
||||
|
||||
typedef struct sLoRaMainCallback
|
||||
{
|
||||
uint8_t (*BoardGetBatteryLevel)(void);
|
||||
void (*BoardGetUniqueId)(uint8_t *id);
|
||||
uint32_t (*BoardGetRandomSeed)(void);
|
||||
void (*LoraTxData)(lora_AppData_t *AppData);
|
||||
void (*LoraRxData)(lora_AppData_t *AppData);
|
||||
} LoRaMainCallback_t;
|
||||
|
||||
typedef struct sLoRaParam
|
||||
{
|
||||
TxEventType_t TxEvent;
|
||||
uint32_t TxDutyCycleTime;
|
||||
bool AdrEnable;
|
||||
int8_t TxDatarate;
|
||||
bool EnablePublicNetwork;
|
||||
uint8_t NbTrials;
|
||||
} LoRaParam_t;
|
||||
|
||||
typedef enum eDevicState
|
||||
{
|
||||
DEVICE_STATE_INIT,
|
||||
DEVICE_STATE_JOIN,
|
||||
DEVICE_STATE_JOINED,
|
||||
DEVICE_STATE_SEND,
|
||||
DEVICE_STATE_SEND_MAC,
|
||||
DEVICE_STATE_CYCLE,
|
||||
DEVICE_STATE_SLEEP
|
||||
} DeviceState_t;
|
||||
|
||||
bool set_lora_freqband_mask(uint16_t mask);
|
||||
uint16_t get_lora_freqband_mask(void);
|
||||
|
||||
bool set_lora_dev_eui(uint8_t *eui);
|
||||
bool set_lora_app_eui(uint8_t *eui);
|
||||
bool set_lora_app_key(uint8_t *key);
|
||||
|
||||
node_freq_type_t get_lora_freq_type(void);
|
||||
bool set_lora_tx_datarate(int8_t datarate);
|
||||
int8_t get_lora_tx_datarate(void);
|
||||
|
||||
bool set_lora_adr(int state);
|
||||
int get_lora_adr(void);
|
||||
|
||||
bool set_lora_class(int8_t class);
|
||||
int8_t get_lora_class(void);
|
||||
|
||||
bool set_lora_tx_cfm_flag(int confirmed);
|
||||
int get_lora_tx_cfm_flag(void);
|
||||
|
||||
bool set_lora_tx_cfm_trials(uint8_t trials);
|
||||
uint8_t get_lora_tx_cfm_trials(void);
|
||||
|
||||
bool set_lora_state(DeviceState_t state);
|
||||
|
||||
bool set_lora_tx_dutycycle(uint32_t dutycycle);
|
||||
uint32_t get_lora_tx_dutycycle(void);
|
||||
|
||||
bool tx_lora_data(void);
|
||||
lora_AppData_t *get_lora_data(void);
|
||||
void tx_lora_mac_req(void);
|
||||
|
||||
// for linkWAN test
|
||||
bool set_lora_tx_len(uint16_t len);
|
||||
uint8_t get_lora_tx_len(void);
|
||||
|
||||
bool send_lora_link_check(void);
|
||||
|
||||
#endif /* LINKWAN_H */
|
||||
|
|
@ -0,0 +1,31 @@
|
|||
/*
|
||||
* Copyright (C) 2015-2017 Alibaba Group Holding Limited
|
||||
*/
|
||||
|
||||
#ifndef LINKWAN_AT_H
|
||||
#define LINKWAN_AT_H
|
||||
|
||||
#define LORA_AT_HELP "AT+?" // help
|
||||
#define LORA_AT_RM "AT+RM" // rm stored lora info
|
||||
|
||||
#define LORA_AT_APPEUI "AT+APPEUI" // app eui
|
||||
#define LORA_AT_APPKEY "AT+APPKEY" // app key
|
||||
#define LORA_AT_DEUI "AT+DEUI" // device eui
|
||||
|
||||
#define LORA_AT_DR "AT+DR" // datarate
|
||||
#define LORA_AT_ADR "AT+ADR" // ADR
|
||||
#define LORA_AT_CLASS "AT+CLASS" // class
|
||||
#define LORA_AT_SCANMASK "AT+SMASK" // scan mask
|
||||
|
||||
#define LORA_AT_CFM "AT+CFM" // confirmation mode
|
||||
#define LORA_AT_CFMTRIALS "AT+CTRIALS" // cfm trials
|
||||
#define LORA_AT_JOIN "AT+JOIN" // join network
|
||||
|
||||
#define LORA_AT_DCS "AT+DCS" // dutycycle
|
||||
#define LORA_AT_TXSIZE "AT+TXSIZE" // tx size
|
||||
#define LORA_AT_LINKCHK "AT+LINKCHK" // link check req
|
||||
|
||||
void linkwan_serial_input(uint8_t cmd);
|
||||
int linkwan_serial_output(uint8_t *buffer, int len);
|
||||
|
||||
#endif
|
||||
|
|
@ -0,0 +1,10 @@
|
|||
/*
|
||||
* Copyright (C) 2015-2017 Alibaba Group Holding Limited
|
||||
*/
|
||||
|
||||
#ifndef LINKWAN_CONFIG_H
|
||||
|
||||
#define LORAWAN_APP_DATA_BUFF_SIZE 128
|
||||
#define LINKWAN_APP_DATA_SIZE 51
|
||||
|
||||
#endif
|
||||
907
Living_SDK/kernel/protocols/lorawan/linkwan/linkwan.c
Normal file
907
Living_SDK/kernel/protocols/lorawan/linkwan/linkwan.c
Normal file
|
|
@ -0,0 +1,907 @@
|
|||
/*
|
||||
* Copyright (C) 2015-2017 Alibaba Group Holding Limited
|
||||
*/
|
||||
|
||||
#include "linkwan.h"
|
||||
#include "commissioning.h"
|
||||
#include "utilities.h"
|
||||
#include "LoRaMac.h"
|
||||
#include "Region.h"
|
||||
#include "RegionCN470A.h"
|
||||
#include "timeServer.h"
|
||||
#include "radio.h"
|
||||
#ifdef AOS_KV
|
||||
#include <assert.h>
|
||||
#include "kvmgr.h"
|
||||
#endif
|
||||
|
||||
static uint8_t tx_buf[LORAWAN_APP_DATA_BUFF_SIZE];
|
||||
static lora_AppData_t tx_data = { tx_buf, 1, 0 };
|
||||
static uint8_t rx_buf[LORAWAN_APP_DATA_BUFF_SIZE];
|
||||
static lora_AppData_t rx_data = { rx_buf, 0, 0 };
|
||||
static uint8_t tx_size = 1;
|
||||
|
||||
static LoRaMacPrimitives_t LoRaMacPrimitives;
|
||||
static LoRaMacCallback_t LoRaMacCallbacks;
|
||||
static LoRaMainCallback_t *app_callbacks;
|
||||
static MibRequestConfirm_t mibReq;
|
||||
|
||||
static int8_t is_tx_confirmed = ENABLE;
|
||||
static bool next_tx = true;
|
||||
static uint8_t num_trials = 8;
|
||||
static bool rejoin_flag = true;
|
||||
|
||||
static uint32_t g_ack_index = 0;
|
||||
static uint32_t g_msg_index = 0;
|
||||
|
||||
static uint8_t g_freqband_num = 0;
|
||||
|
||||
static LoRaParam_t lora_param = {
|
||||
TX_ON_NONE, 0, true, DR_0, LORAWAN_PUBLIC_NETWORK, JOINREQ_NBTRIALS
|
||||
};
|
||||
|
||||
static TimerEvent_t TxNextPacketTimer;
|
||||
volatile static DeviceState_t device_state = DEVICE_STATE_INIT;
|
||||
|
||||
lora_config_t g_lora_config = { 1, DR_5, INVALID_LORA_CONFIG };
|
||||
lora_dev_t g_lora_dev = { LORAWAN_DEVICE_EUI, LORAWAN_APPLICATION_EUI,
|
||||
LORAWAN_APPLICATION_KEY, CLASS_A,
|
||||
NODE_MODE_NORMAL, 0xffff,
|
||||
VALID_LORA_CONFIG };
|
||||
node_freq_type_t g_freq_type = FREQ_TYPE_INTRA;
|
||||
join_method_t g_join_method;
|
||||
|
||||
static void start_dutycycle_timer(void);
|
||||
|
||||
static bool send_frame(void)
|
||||
{
|
||||
McpsReq_t mcpsReq;
|
||||
LoRaMacTxInfo_t txInfo;
|
||||
|
||||
if (tx_data.BuffSize > LINKWAN_APP_DATA_SIZE) {
|
||||
tx_data.BuffSize = LINKWAN_APP_DATA_SIZE;
|
||||
}
|
||||
|
||||
if (LoRaMacQueryTxPossible(tx_data.BuffSize, &txInfo) !=
|
||||
LORAMAC_STATUS_OK) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (is_tx_confirmed == DISABLE) {
|
||||
mcpsReq.Type = MCPS_UNCONFIRMED;
|
||||
mcpsReq.Req.Unconfirmed.fPort = tx_data.Port;
|
||||
mcpsReq.Req.Unconfirmed.fBuffer = tx_data.Buff;
|
||||
mcpsReq.Req.Unconfirmed.fBufferSize = tx_data.BuffSize;
|
||||
mcpsReq.Req.Unconfirmed.Datarate = lora_param.TxDatarate;
|
||||
} else {
|
||||
mcpsReq.Type = MCPS_CONFIRMED;
|
||||
mcpsReq.Req.Confirmed.fPort = tx_data.Port;
|
||||
mcpsReq.Req.Confirmed.fBuffer = tx_data.Buff;
|
||||
mcpsReq.Req.Confirmed.fBufferSize = tx_data.BuffSize;
|
||||
mcpsReq.Req.Confirmed.NbTrials = num_trials;
|
||||
mcpsReq.Req.Confirmed.Datarate = lora_param.TxDatarate;
|
||||
}
|
||||
|
||||
if (LoRaMacMcpsRequest(&mcpsReq) == LORAMAC_STATUS_OK) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static void prepare_tx_frame(void)
|
||||
{
|
||||
if (lora_param.TxEvent == TX_ON_TIMER) {
|
||||
app_callbacks->LoraTxData(&tx_data);
|
||||
}
|
||||
}
|
||||
|
||||
static void on_tx_next_packet_timer_event(void)
|
||||
{
|
||||
MibRequestConfirm_t mib_req;
|
||||
LoRaMacStatus_t status;
|
||||
|
||||
TimerStop(&TxNextPacketTimer);
|
||||
|
||||
mib_req.Type = MIB_NETWORK_JOINED;
|
||||
status = LoRaMacMibGetRequestConfirm(&mib_req);
|
||||
|
||||
if (status == LORAMAC_STATUS_OK) {
|
||||
if (mib_req.Param.IsNetworkJoined == true) {
|
||||
device_state = DEVICE_STATE_SEND;
|
||||
} else {
|
||||
rejoin_flag = true;
|
||||
device_state = DEVICE_STATE_JOIN;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void reset_join_state(void)
|
||||
{
|
||||
if (g_lora_config.flag == VALID_LORA_CONFIG) {
|
||||
g_lora_config.flag = INVALID_LORA_CONFIG;
|
||||
#ifdef AOS_KV
|
||||
aos_kv_set("lora", &g_lora_config, sizeof(g_lora_config));
|
||||
#endif
|
||||
}
|
||||
device_state = DEVICE_STATE_JOIN;
|
||||
}
|
||||
|
||||
static void store_lora_config(void)
|
||||
{
|
||||
MibRequestConfirm_t mib_req;
|
||||
LoRaMacStatus_t status;
|
||||
uint32_t freqband;
|
||||
int8_t datarate;
|
||||
|
||||
mib_req.Type = MIB_FREQ_BAND;
|
||||
status = LoRaMacMibGetRequestConfirm(&mib_req);
|
||||
if (status == LORAMAC_STATUS_OK) {
|
||||
freqband = mib_req.Param.freqband;
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
|
||||
mib_req.Type = MIB_CHANNELS_DATARATE;
|
||||
status = LoRaMacMibGetRequestConfirm(&mib_req);
|
||||
if (status == LORAMAC_STATUS_OK) {
|
||||
datarate = mib_req.Param.ChannelsDatarate;
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
|
||||
g_lora_config.freqband = freqband;
|
||||
g_lora_config.datarate = datarate;
|
||||
g_lora_config.flag = VALID_LORA_CONFIG;
|
||||
#ifdef AOS_KV
|
||||
aos_kv_set("lora", &g_lora_config, sizeof(g_lora_config));
|
||||
#endif
|
||||
}
|
||||
|
||||
static void mcps_confirm(McpsConfirm_t *mcpsConfirm)
|
||||
{
|
||||
if (mcpsConfirm->Status == LORAMAC_EVENT_INFO_STATUS_OK) {
|
||||
switch (mcpsConfirm->McpsRequest) {
|
||||
case MCPS_UNCONFIRMED: {
|
||||
// Check Datarate
|
||||
// Check TxPower
|
||||
break;
|
||||
}
|
||||
case MCPS_CONFIRMED: {
|
||||
// Check Datarate
|
||||
// Check TxPower
|
||||
// Check AckReceived
|
||||
// Check NbTrials
|
||||
break;
|
||||
}
|
||||
case MCPS_PROPRIETARY: {
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
switch (mcpsConfirm->McpsRequest) {
|
||||
case MCPS_UNCONFIRMED: {
|
||||
// Check Datarate
|
||||
// Check TxPower
|
||||
break;
|
||||
}
|
||||
case MCPS_CONFIRMED: {
|
||||
// Check Datarate
|
||||
// Check TxPower
|
||||
// Check AckReceived
|
||||
// Check NbTrials
|
||||
|
||||
reset_join_state();
|
||||
g_join_method = DEF_JOIN_METHOD;
|
||||
DBG_LINKWAN("Not receive Ack,Start to Join...\r\n");
|
||||
break;
|
||||
}
|
||||
case MCPS_PROPRIETARY: {
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
next_tx = true;
|
||||
}
|
||||
|
||||
static void McpsIndication(McpsIndication_t *mcpsIndication)
|
||||
{
|
||||
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: {
|
||||
DBG_LINKWAN("MCPS_MULTICAST\n");
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
// Check Multicast
|
||||
// Check Port
|
||||
// Check Datarate
|
||||
// Check FramePending
|
||||
// Check Buffer
|
||||
// Check BufferSize
|
||||
// Check Rssi
|
||||
// Check Snr
|
||||
// Check RxSlot
|
||||
DBG_LINKWAN("rssi = %d, snr = %d, datarate = %d\r\n", mcpsIndication->Rssi,
|
||||
mcpsIndication->Snr, mcpsIndication->RxDatarate);
|
||||
|
||||
if (mcpsIndication->RxData == true) {
|
||||
switch (mcpsIndication->Port) {
|
||||
case 224:
|
||||
break;
|
||||
default:
|
||||
rx_data.Port = mcpsIndication->Port;
|
||||
rx_data.BuffSize = mcpsIndication->BufferSize;
|
||||
memcpy1(rx_data.Buff, mcpsIndication->Buffer, rx_data.BuffSize);
|
||||
app_callbacks->LoraRxData(&rx_data);
|
||||
break;
|
||||
}
|
||||
#ifdef CONFIG_DEBUG_LINKWAN
|
||||
} else if (mcpsIndication->AckReceived) {
|
||||
DBG_LINKWAN("rx, ACK, index %d\r\n", g_ack_index++);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
static uint32_t generate_rejoin_delay(void)
|
||||
{
|
||||
uint32_t rejoin_delay = 0;
|
||||
|
||||
while (rejoin_delay < 8000) {
|
||||
rejoin_delay += (Radio.Random() % 250);
|
||||
}
|
||||
|
||||
return rejoin_delay;
|
||||
}
|
||||
|
||||
static uint8_t get_freqband_num(void)
|
||||
{
|
||||
for (uint8_t i = 0; i < 16; i++) {
|
||||
if ((get_lora_freqband_mask() & (1 << i)) && i != 1) {
|
||||
g_freqband_num++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void MlmeConfirm(MlmeConfirm_t *mlmeConfirm)
|
||||
{
|
||||
uint32_t rejoin_delay;
|
||||
|
||||
switch (mlmeConfirm->MlmeRequest) {
|
||||
case MLME_JOIN: {
|
||||
if (mlmeConfirm->Status == LORAMAC_EVENT_INFO_STATUS_OK) {
|
||||
// Status is OK, node has joined the network
|
||||
device_state = DEVICE_STATE_JOINED;
|
||||
} else {
|
||||
// Join was not successful. Try to join again
|
||||
reset_join_state();
|
||||
if (g_join_method != SCAN_JOIN_METHOD) {
|
||||
g_join_method = (g_join_method + 1) % JOIN_METHOD_NUM;
|
||||
rejoin_delay = generate_rejoin_delay();
|
||||
if (g_join_method == SCAN_JOIN_METHOD) {
|
||||
get_freqband_num();
|
||||
}
|
||||
}
|
||||
|
||||
if (g_freqband_num == 0) {
|
||||
if (g_join_method == DEF_JOIN_METHOD) {
|
||||
g_join_method = (g_join_method + 1) % JOIN_METHOD_NUM;
|
||||
rejoin_delay = generate_rejoin_delay();
|
||||
get_freqband_num();
|
||||
} else {
|
||||
g_join_method = DEF_JOIN_METHOD;
|
||||
rejoin_delay = 60 * 60 * 1000; // 1 hour
|
||||
DBG_LINKWAN("Wait 1 hour for new round of scan\r\n");
|
||||
}
|
||||
} else {
|
||||
g_freqband_num--;
|
||||
rejoin_delay = generate_rejoin_delay();
|
||||
}
|
||||
TimerSetValue(&TxNextPacketTimer, rejoin_delay);
|
||||
TimerStart(&TxNextPacketTimer);
|
||||
rejoin_flag = false;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case MLME_LINK_CHECK: {
|
||||
if (mlmeConfirm->Status == LORAMAC_EVENT_INFO_STATUS_OK) {
|
||||
// Check DemodMargin
|
||||
// Check NbGateways
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
next_tx = true;
|
||||
}
|
||||
|
||||
static char *get_class_name(int8_t class)
|
||||
{
|
||||
if (g_lora_dev.class == CLASS_B) {
|
||||
return "class_b";
|
||||
} else if (g_lora_dev.class == CLASS_C) {
|
||||
return "class_c";
|
||||
} else {
|
||||
g_lora_dev.class = CLASS_A;
|
||||
return "class_a";
|
||||
}
|
||||
}
|
||||
|
||||
void lora_init(LoRaMainCallback_t *callbacks)
|
||||
{
|
||||
device_state = DEVICE_STATE_INIT;
|
||||
app_callbacks = callbacks;
|
||||
|
||||
#ifdef AOS_KV
|
||||
assert(aos_kv_init() == 0);
|
||||
#endif
|
||||
#ifdef CONFIG_LINKWAN_AT
|
||||
extern void linkwan_at_init(void);
|
||||
linkwan_at_init();
|
||||
#endif
|
||||
}
|
||||
|
||||
static void print_dev_addr(void)
|
||||
{
|
||||
#if (OVER_THE_AIR_ACTIVATION != 0)
|
||||
DBG_LINKWAN("OTAA\r\n");
|
||||
DBG_LINKWAN("DevEui= %02X-%02X-%02X-%02X-%02X-%02X-%02X-%02X\r\n",
|
||||
g_lora_dev.dev_eui[0], g_lora_dev.dev_eui[1],
|
||||
g_lora_dev.dev_eui[2], g_lora_dev.dev_eui[3],
|
||||
g_lora_dev.dev_eui[4], g_lora_dev.dev_eui[5],
|
||||
g_lora_dev.dev_eui[6], g_lora_dev.dev_eui[7]);
|
||||
DBG_LINKWAN("AppEui= %02X-%02X-%02X-%02X-%02X-%02X-%02X-%02X\r\n",
|
||||
g_lora_dev.app_eui[0], g_lora_dev.app_eui[1],
|
||||
g_lora_dev.app_eui[2], g_lora_dev.app_eui[3],
|
||||
g_lora_dev.app_eui[4], g_lora_dev.app_eui[5],
|
||||
g_lora_dev.app_eui[6], g_lora_dev.app_eui[7]);
|
||||
DBG_LINKWAN(
|
||||
"AppKey= "
|
||||
"%02X-%02X-%02X-%02X-%02X-%02X-%02X-%02X-%02X-%02X-%02X-%02X-%02X-%02X-%"
|
||||
"02X-%02X\r\n",
|
||||
g_lora_dev.app_key[0], g_lora_dev.app_key[1], g_lora_dev.app_key[2],
|
||||
g_lora_dev.app_key[3], g_lora_dev.app_key[4], g_lora_dev.app_key[5],
|
||||
g_lora_dev.app_key[6], g_lora_dev.app_key[7], g_lora_dev.app_key[8],
|
||||
g_lora_dev.app_key[9], g_lora_dev.app_key[10], g_lora_dev.app_key[11],
|
||||
g_lora_dev.app_key[12], g_lora_dev.app_key[13], g_lora_dev.app_key[14],
|
||||
g_lora_dev.app_key[15]);
|
||||
#else
|
||||
DBG_LINKWAN("ABP\r\n");
|
||||
DBG_LINKWAN("DevAdd= %08X\n\r", DevAddr);
|
||||
DBG_LINKWAN("DevEui= %02X-%02X-%02X-%02X-%02X-%02X-%02X-%02X\r\n",
|
||||
g_lora_dev.dev_eui[0], g_lora_dev.dev_eui[1],
|
||||
g_lora_dev.dev_eui[2], g_lora_dev.dev_eui[3],
|
||||
g_lora_dev.dev_eui[4], g_lora_dev.dev_eui[5],
|
||||
g_lora_dev.dev_eui[6], g_lora_dev.dev_eui[7]);
|
||||
DBG_LINKWAN("NwkSKey= %02X", NwkSKey[0]);
|
||||
for (int i = 1; i < 16; i++) {
|
||||
DBG_LINKWAN(" %02X", NwkSKey[i]);
|
||||
};
|
||||
DBG_LINKWAN("\r\n");
|
||||
DBG_LINKWAN("AppSKey= %02X", AppSKey[0]);
|
||||
for (int i = 1; i < 16; i++) {
|
||||
DBG_LINKWAN(" %02X", AppSKey[i]);
|
||||
};
|
||||
DBG_LINKWAN("\r\n");
|
||||
#endif
|
||||
|
||||
DBG_LINKWAN("class type %s\r\n", get_class_name(g_lora_dev.class));
|
||||
DBG_LINKWAN("freq type %s\r\n",
|
||||
g_freq_type == FREQ_TYPE_INTER ? "inter" : "intra");
|
||||
DBG_LINKWAN("scan chn mask 0x%04x\r\n", g_lora_dev.mask);
|
||||
}
|
||||
|
||||
void lora_fsm(void)
|
||||
{
|
||||
#ifdef CONFIG_LINKWAN
|
||||
int len = sizeof(g_lora_config);
|
||||
int ret;
|
||||
lora_config_t lora_config;
|
||||
lora_dev_t lora_dev;
|
||||
#endif
|
||||
|
||||
while (1) {
|
||||
#ifdef CONFIG_LINKWAN_AT
|
||||
extern void process_linkwan_at(void);
|
||||
process_linkwan_at();
|
||||
#endif
|
||||
|
||||
switch (device_state) {
|
||||
case DEVICE_STATE_INIT: {
|
||||
#ifdef AOS_KV
|
||||
memset(&lora_config, 0, sizeof(lora_config));
|
||||
len = sizeof(g_lora_config);
|
||||
aos_kv_get("lora", &lora_config, &len);
|
||||
if (lora_config.flag == VALID_LORA_CONFIG) {
|
||||
memcpy(&g_lora_config, &lora_config, sizeof(g_lora_config));
|
||||
}
|
||||
memset(&lora_dev, 0, sizeof(lora_dev));
|
||||
len = sizeof(g_lora_dev);
|
||||
aos_kv_get("lora_dev", &lora_dev, &len);
|
||||
if (lora_dev.flag == VALID_LORA_CONFIG) {
|
||||
memcpy(&g_lora_dev, &lora_dev, sizeof(g_lora_dev));
|
||||
}
|
||||
#endif
|
||||
if (g_lora_dev.dev_eui[5] & 0x1) {
|
||||
g_freq_type = FREQ_TYPE_INTER;
|
||||
}
|
||||
print_dev_addr();
|
||||
|
||||
if (g_lora_config.flag == VALID_LORA_CONFIG) {
|
||||
g_join_method = STORED_JOIN_METHOD;
|
||||
} else {
|
||||
g_join_method = DEF_JOIN_METHOD;
|
||||
}
|
||||
|
||||
LoRaMacPrimitives.MacMcpsConfirm = mcps_confirm;
|
||||
LoRaMacPrimitives.MacMcpsIndication = McpsIndication;
|
||||
LoRaMacPrimitives.MacMlmeConfirm = MlmeConfirm;
|
||||
LoRaMacCallbacks.GetBatteryLevel =
|
||||
app_callbacks->BoardGetBatteryLevel;
|
||||
#if defined(REGION_AS923)
|
||||
LoRaMacInitialization(&LoRaMacPrimitives, &LoRaMacCallbacks,
|
||||
LORAMAC_REGION_AS923);
|
||||
#elif defined(REGION_AS923)
|
||||
LoRaMacInitialization(&LoRaMacPrimitives, &LoRaMacCallbacks,
|
||||
LORAMAC_REGION_AU915);
|
||||
#elif defined(REGION_CN470)
|
||||
LoRaMacInitialization(&LoRaMacPrimitives, &LoRaMacCallbacks,
|
||||
LORAMAC_REGION_CN470);
|
||||
#elif defined(REGION_CN779)
|
||||
LoRaMacInitialization(&LoRaMacPrimitives, &LoRaMacCallbacks,
|
||||
LORAMAC_REGION_CN779);
|
||||
#elif defined(REGION_EU433)
|
||||
LoRaMacInitialization(&LoRaMacPrimitives, &LoRaMacCallbacks,
|
||||
LORAMAC_REGION_EU433);
|
||||
#elif defined(REGION_IN865)
|
||||
LoRaMacInitialization(&LoRaMacPrimitives, &LoRaMacCallbacks,
|
||||
LORAMAC_REGION_IN865);
|
||||
#elif defined(REGION_EU868)
|
||||
LoRaMacInitialization(&LoRaMacPrimitives, &LoRaMacCallbacks,
|
||||
LORAMAC_REGION_EU868);
|
||||
#elif defined(REGION_KR920)
|
||||
LoRaMacInitialization(&LoRaMacPrimitives, &LoRaMacCallbacks,
|
||||
LORAMAC_REGION_KR920);
|
||||
#elif defined(REGION_US915)
|
||||
LoRaMacInitialization(&LoRaMacPrimitives, &LoRaMacCallbacks,
|
||||
LORAMAC_REGION_US915);
|
||||
#elif defined(REGION_US915_HYBRID)
|
||||
LoRaMacInitialization(&LoRaMacPrimitives, &LoRaMacCallbacks,
|
||||
LORAMAC_REGION_US915_HYBRID);
|
||||
#elif defined(REGION_CN470A)
|
||||
LoRaMacInitialization(&LoRaMacPrimitives, &LoRaMacCallbacks,
|
||||
LORAMAC_REGION_CN470A);
|
||||
#else
|
||||
#error "Please define a region in the compiler options."
|
||||
#endif
|
||||
TimerInit(&TxNextPacketTimer, on_tx_next_packet_timer_event);
|
||||
|
||||
mibReq.Type = MIB_ADR;
|
||||
mibReq.Param.AdrEnable = lora_param.AdrEnable;
|
||||
LoRaMacMibSetRequestConfirm(&mibReq);
|
||||
|
||||
mibReq.Type = MIB_PUBLIC_NETWORK;
|
||||
mibReq.Param.EnablePublicNetwork =
|
||||
lora_param.EnablePublicNetwork;
|
||||
LoRaMacMibSetRequestConfirm(&mibReq);
|
||||
|
||||
mibReq.Type = MIB_DEVICE_CLASS;
|
||||
mibReq.Param.Class = g_lora_dev.class;
|
||||
LoRaMacMibSetRequestConfirm(&mibReq);
|
||||
|
||||
#if defined(REGION_EU868)
|
||||
lora_config_duty_cycle_set(LORAWAN_DUTYCYCLE_ON ? ENABLE
|
||||
: DISABLE);
|
||||
|
||||
#if (USE_SEMTECH_DEFAULT_CHANNEL_LINEUP == 1)
|
||||
LoRaMacChannelAdd(3, (ChannelParams_t)LC4);
|
||||
LoRaMacChannelAdd(4, (ChannelParams_t)LC5);
|
||||
LoRaMacChannelAdd(5, (ChannelParams_t)LC6);
|
||||
LoRaMacChannelAdd(6, (ChannelParams_t)LC7);
|
||||
LoRaMacChannelAdd(7, (ChannelParams_t)LC8);
|
||||
LoRaMacChannelAdd(8, (ChannelParams_t)LC9);
|
||||
LoRaMacChannelAdd(9, (ChannelParams_t)LC10);
|
||||
|
||||
mibReq.Type = MIB_RX2_DEFAULT_CHANNEL;
|
||||
mibReq.Param.Rx2DefaultChannel =
|
||||
(Rx2ChannelParams_t){ 869525000, DR_3 };
|
||||
LoRaMacMibSetRequestConfirm(&mibReq);
|
||||
|
||||
mibReq.Type = MIB_RX2_CHANNEL;
|
||||
mibReq.Param.Rx2Channel =
|
||||
(Rx2ChannelParams_t){ 869525000, DR_3 };
|
||||
LoRaMacMibSetRequestConfirm(&mibReq);
|
||||
#endif
|
||||
|
||||
#endif
|
||||
device_state = DEVICE_STATE_JOIN;
|
||||
break;
|
||||
}
|
||||
|
||||
case DEVICE_STATE_JOIN: {
|
||||
#if (OVER_THE_AIR_ACTIVATION != 0)
|
||||
MlmeReq_t mlmeReq;
|
||||
|
||||
mlmeReq.Type = MLME_JOIN;
|
||||
mlmeReq.Req.Join.DevEui = g_lora_dev.dev_eui;
|
||||
mlmeReq.Req.Join.AppEui = g_lora_dev.app_eui;
|
||||
mlmeReq.Req.Join.AppKey = g_lora_dev.app_key;
|
||||
|
||||
mlmeReq.Req.Join.method = g_join_method;
|
||||
if (g_join_method == STORED_JOIN_METHOD) {
|
||||
mlmeReq.Req.Join.freqband = g_lora_config.freqband;
|
||||
mlmeReq.Req.Join.datarate = g_lora_config.datarate;
|
||||
mlmeReq.Req.Join.NbTrials = 3;
|
||||
} else {
|
||||
mlmeReq.Req.Join.NbTrials = 2;
|
||||
}
|
||||
|
||||
if (next_tx == true && rejoin_flag == true) {
|
||||
if (LoRaMacMlmeRequest(&mlmeReq) == LORAMAC_STATUS_OK) {
|
||||
next_tx = false;
|
||||
}
|
||||
DBG_LINKWAN("Start to Join, method %d, nb_trials:%d\r\n",
|
||||
g_join_method, mlmeReq.Req.Join.NbTrials);
|
||||
}
|
||||
device_state = DEVICE_STATE_SLEEP;
|
||||
#else
|
||||
mibReq.Type = MIB_NET_ID;
|
||||
mibReq.Param.NetID = LORAWAN_NETWORK_ID;
|
||||
LoRaMacMibSetRequestConfirm(&mibReq);
|
||||
|
||||
mibReq.Type = MIB_DEV_ADDR;
|
||||
mibReq.Param.DevAddr = DevAddr;
|
||||
LoRaMacMibSetRequestConfirm(&mibReq);
|
||||
|
||||
mibReq.Type = MIB_NWK_SKEY;
|
||||
mibReq.Param.NwkSKey = NwkSKey;
|
||||
LoRaMacMibSetRequestConfirm(&mibReq);
|
||||
|
||||
mibReq.Type = MIB_APP_SKEY;
|
||||
mibReq.Param.AppSKey = AppSKey;
|
||||
LoRaMacMibSetRequestConfirm(&mibReq);
|
||||
|
||||
mibReq.Type = MIB_NETWORK_JOINED;
|
||||
mibReq.Param.IsNetworkJoined = true;
|
||||
LoRaMacMibSetRequestConfirm(&mibReq);
|
||||
|
||||
device_state = DEVICE_STATE_SEND;
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
case DEVICE_STATE_JOINED: {
|
||||
DBG_LINKWAN("Joined\n\r");
|
||||
store_lora_config();
|
||||
device_state = DEVICE_STATE_SEND;
|
||||
break;
|
||||
}
|
||||
case DEVICE_STATE_SEND: {
|
||||
if (next_tx == true) {
|
||||
prepare_tx_frame();
|
||||
next_tx = send_frame();
|
||||
}
|
||||
if (lora_param.TxEvent == TX_ON_TIMER) {
|
||||
start_dutycycle_timer();
|
||||
} else if (lora_param.TxEvent == TX_ON_EVENT) {
|
||||
lora_param.TxEvent = TX_ON_NONE;
|
||||
}
|
||||
device_state = DEVICE_STATE_SLEEP;
|
||||
break;
|
||||
}
|
||||
case DEVICE_STATE_SEND_MAC: {
|
||||
if (next_tx == true) {
|
||||
tx_data.BuffSize = 0;
|
||||
next_tx = send_frame();
|
||||
}
|
||||
device_state = DEVICE_STATE_SLEEP;
|
||||
break;
|
||||
}
|
||||
case DEVICE_STATE_SLEEP: {
|
||||
// Wake up through events
|
||||
#ifndef LOW_POWER_DISABLE
|
||||
LowPower_Handler();
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
device_state = DEVICE_STATE_INIT;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
DeviceState_t lora_getDeviceState(void)
|
||||
{
|
||||
return device_state;
|
||||
}
|
||||
|
||||
node_freq_type_t get_lora_freq_type(void)
|
||||
{
|
||||
return g_freq_type;
|
||||
}
|
||||
|
||||
bool set_lora_tx_datarate(int8_t datarate)
|
||||
{
|
||||
if (datarate >= CN470A_TX_MIN_DATARATE &&
|
||||
datarate <= CN470A_TX_MAX_DATARATE && get_lora_adr() == 0) {
|
||||
lora_param.TxDatarate = datarate;
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
int8_t get_lora_tx_datarate(void)
|
||||
{
|
||||
return lora_param.TxDatarate;
|
||||
}
|
||||
|
||||
bool set_lora_adr(int state)
|
||||
{
|
||||
LoRaMacStatus_t status;
|
||||
MibRequestConfirm_t mib_req;
|
||||
bool ret = false;
|
||||
|
||||
if (state == 0) {
|
||||
mib_req.Param.AdrEnable = false;
|
||||
} else {
|
||||
mib_req.Param.AdrEnable = true;
|
||||
}
|
||||
mib_req.Type = MIB_ADR;
|
||||
status = LoRaMacMibSetRequestConfirm(&mib_req);
|
||||
if (status == LORAMAC_STATUS_OK) {
|
||||
ret = true;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
int get_lora_adr(void)
|
||||
{
|
||||
MibRequestConfirm_t mib_req;
|
||||
|
||||
mib_req.Type = MIB_ADR;
|
||||
LoRaMacMibGetRequestConfirm(&mib_req);
|
||||
if (mib_req.Param.AdrEnable == true) {
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void start_dutycycle_timer(void)
|
||||
{
|
||||
MibRequestConfirm_t mib_req;
|
||||
LoRaMacStatus_t status;
|
||||
|
||||
TimerStop(&TxNextPacketTimer);
|
||||
mib_req.Type = MIB_NETWORK_JOINED;
|
||||
status = LoRaMacMibGetRequestConfirm(&mib_req);
|
||||
if (status == LORAMAC_STATUS_OK) {
|
||||
if (mib_req.Param.IsNetworkJoined == true &&
|
||||
lora_param.TxEvent == TX_ON_TIMER &&
|
||||
lora_param.TxDutyCycleTime != 0) {
|
||||
TimerSetValue(&TxNextPacketTimer, lora_param.TxDutyCycleTime);
|
||||
TimerStart(&TxNextPacketTimer);
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (lora_param.TxDutyCycleTime == 0 && lora_param.TxEvent == TX_ON_TIMER) {
|
||||
lora_param.TxEvent = TX_ON_NONE;
|
||||
}
|
||||
}
|
||||
|
||||
bool set_lora_tx_dutycycle(uint32_t dutycycle)
|
||||
{
|
||||
if (dutycycle != 0 && dutycycle < 1000) {
|
||||
dutycycle = 1000;
|
||||
}
|
||||
|
||||
lora_param.TxDutyCycleTime = dutycycle;
|
||||
TimerStop(&TxNextPacketTimer);
|
||||
if (dutycycle == 0) {
|
||||
lora_param.TxEvent = TX_ON_NONE;
|
||||
} else {
|
||||
lora_param.TxEvent = TX_ON_TIMER;
|
||||
start_dutycycle_timer();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
uint32_t get_lora_tx_dutycycle(void)
|
||||
{
|
||||
return lora_param.TxDutyCycleTime;
|
||||
}
|
||||
|
||||
lora_AppData_t *get_lora_data(void)
|
||||
{
|
||||
if (next_tx == true) {
|
||||
return &tx_data;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
bool tx_lora_data(void)
|
||||
{
|
||||
MibRequestConfirm_t mib_req;
|
||||
LoRaMacStatus_t status;
|
||||
|
||||
if (next_tx == false) {
|
||||
return false;
|
||||
}
|
||||
|
||||
mib_req.Type = MIB_NETWORK_JOINED;
|
||||
status = LoRaMacMibGetRequestConfirm(&mib_req);
|
||||
if (status == LORAMAC_STATUS_OK) {
|
||||
if (mib_req.Param.IsNetworkJoined == true) {
|
||||
TimerStop(&TxNextPacketTimer);
|
||||
lora_param.TxEvent = TX_ON_EVENT;
|
||||
device_state = DEVICE_STATE_SEND;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool set_lora_tx_cfm_flag(int confirmed)
|
||||
{
|
||||
is_tx_confirmed = confirmed;
|
||||
return true;
|
||||
}
|
||||
|
||||
int get_lora_tx_cfm_flag(void)
|
||||
{
|
||||
return is_tx_confirmed;
|
||||
}
|
||||
|
||||
bool set_lora_tx_cfm_trials(uint8_t trials)
|
||||
{
|
||||
num_trials = trials;
|
||||
return true;
|
||||
}
|
||||
|
||||
uint8_t get_lora_tx_cfm_trials(void)
|
||||
{
|
||||
return num_trials;
|
||||
}
|
||||
|
||||
bool set_lora_state(DeviceState_t state)
|
||||
{
|
||||
if (device_state == DEVICE_STATE_SLEEP) {
|
||||
TimerStop(&TxNextPacketTimer);
|
||||
}
|
||||
device_state = state;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool set_lora_class(int8_t class)
|
||||
{
|
||||
if (class >= CLASS_A && class <= CLASS_C) {
|
||||
g_lora_dev.class = class;
|
||||
g_lora_dev.flag = VALID_LORA_CONFIG;
|
||||
#ifdef AOS_KV
|
||||
aos_kv_set("lora_dev", &g_lora_dev, sizeof(g_lora_dev));
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
int8_t get_lora_class(void)
|
||||
{
|
||||
return g_lora_dev.class;
|
||||
}
|
||||
|
||||
bool set_lora_dev_eui(uint8_t *eui)
|
||||
{
|
||||
memcpy(g_lora_dev.dev_eui, eui, 8);
|
||||
g_lora_dev.flag = VALID_LORA_CONFIG;
|
||||
#ifdef AOS_KV
|
||||
aos_kv_set("lora_dev", &g_lora_dev, sizeof(g_lora_dev));
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
|
||||
uint8_t *get_lora_dev_eui(void)
|
||||
{
|
||||
return g_lora_dev.dev_eui;
|
||||
}
|
||||
|
||||
bool set_lora_app_eui(uint8_t *eui)
|
||||
{
|
||||
memcpy(g_lora_dev.app_eui, eui, 8);
|
||||
g_lora_dev.flag = VALID_LORA_CONFIG;
|
||||
#ifdef AOS_KV
|
||||
aos_kv_set("lora_dev", &g_lora_dev, sizeof(g_lora_dev));
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
|
||||
uint8_t *get_lora_app_eui(void)
|
||||
{
|
||||
return g_lora_dev.app_eui;
|
||||
}
|
||||
|
||||
bool set_lora_app_key(uint8_t *key)
|
||||
{
|
||||
memcpy(g_lora_dev.app_key, key, 16);
|
||||
g_lora_dev.flag = VALID_LORA_CONFIG;
|
||||
#ifdef AOS_KV
|
||||
aos_kv_set("lora_dev", &g_lora_dev, sizeof(g_lora_dev));
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
|
||||
uint8_t *get_lora_app_key(void)
|
||||
{
|
||||
return g_lora_dev.app_key;
|
||||
}
|
||||
|
||||
bool set_lora_freqband_mask(uint16_t mask)
|
||||
{
|
||||
g_lora_dev.mask = mask;
|
||||
#ifdef AOS_KV
|
||||
aos_kv_set("lora_dev", &g_lora_dev, sizeof(g_lora_dev));
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
|
||||
uint16_t get_lora_freqband_mask(void)
|
||||
{
|
||||
return g_lora_dev.mask;
|
||||
}
|
||||
|
||||
void tx_lora_mac_req(void)
|
||||
{
|
||||
if (device_state != DEVICE_STATE_SEND) {
|
||||
device_state = DEVICE_STATE_SEND_MAC;
|
||||
}
|
||||
}
|
||||
|
||||
// for linkWAN test
|
||||
bool set_lora_tx_len(uint16_t len)
|
||||
{
|
||||
if (len <= LORAWAN_APP_DATA_BUFF_SIZE) {
|
||||
tx_size = len;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
uint8_t get_lora_tx_len(void)
|
||||
{
|
||||
return tx_size;
|
||||
}
|
||||
|
||||
bool send_lora_link_check(void)
|
||||
{
|
||||
MlmeReq_t mlmeReq;
|
||||
|
||||
mlmeReq.Type = MLME_LINK_CHECK;
|
||||
if (next_tx == true) {
|
||||
if (LoRaMacMlmeRequest(&mlmeReq) == LORAMAC_STATUS_OK) {
|
||||
next_tx = false;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
338
Living_SDK/kernel/protocols/lorawan/linkwan/linkwan_at.c
Normal file
338
Living_SDK/kernel/protocols/lorawan/linkwan/linkwan_at.c
Normal file
|
|
@ -0,0 +1,338 @@
|
|||
/*
|
||||
* Copyright (C) 2015-2017 Alibaba Group Holding Limited
|
||||
*/
|
||||
|
||||
#include "LoRaMac.h"
|
||||
#include "Region.h"
|
||||
#include "linkwan.h"
|
||||
#include "linkwan_at.h"
|
||||
|
||||
#define ATCMD_SIZE 64
|
||||
uint8_t atcmd[ATCMD_SIZE];
|
||||
uint16_t atcmd_index = 0;
|
||||
|
||||
static int hex2bin(const char *hex, uint8_t *bin, uint16_t bin_length)
|
||||
{
|
||||
uint16_t hex_length = strlen(hex);
|
||||
const char *hex_end = hex + hex_length;
|
||||
uint8_t *cur = bin;
|
||||
uint8_t num_chars = hex_length & 1;
|
||||
uint8_t byte = 0;
|
||||
|
||||
if ((hex_length + 1) / 2 > bin_length) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
while (hex < hex_end) {
|
||||
if ('A' <= *hex && *hex <= 'F') {
|
||||
byte |= 10 + (*hex - 'A');
|
||||
} else if ('a' <= *hex && *hex <= 'f') {
|
||||
byte |= 10 + (*hex - 'a');
|
||||
} else if ('0' <= *hex && *hex <= '9') {
|
||||
byte |= *hex - '0';
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
hex++;
|
||||
num_chars++;
|
||||
|
||||
if (num_chars >= 2) {
|
||||
num_chars = 0;
|
||||
*cur++ = byte;
|
||||
byte = 0;
|
||||
} else {
|
||||
byte <<= 4;
|
||||
}
|
||||
}
|
||||
return cur - bin;
|
||||
}
|
||||
|
||||
// this can be in intrpt context
|
||||
void linkwan_serial_input(uint8_t cmd)
|
||||
{
|
||||
if ((cmd >= '0' && cmd <= '9') || (cmd >= 'a' && cmd <= 'z') ||
|
||||
(cmd >= 'A' && cmd <= 'Z') || cmd == '?' || cmd == '+') {
|
||||
atcmd[atcmd_index++] = cmd;
|
||||
} else if (cmd == '\r' || cmd == '\n') {
|
||||
atcmd[atcmd_index] = '\0';
|
||||
}
|
||||
|
||||
if (atcmd_index > ATCMD_SIZE) {
|
||||
atcmd_index = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void process_linkwan_at(void)
|
||||
{
|
||||
bool ret = false;
|
||||
int value;
|
||||
MibRequestConfirm_t mibReq;
|
||||
LoRaMacStatus_t status;
|
||||
uint8_t length;
|
||||
uint8_t buf[16];
|
||||
|
||||
if (atcmd_index == 0 || atcmd[atcmd_index] != '\0') {
|
||||
return;
|
||||
}
|
||||
if (strncmp(atcmd, LORA_AT_HELP, strlen(LORA_AT_HELP)) == 0) {
|
||||
snprintf(atcmd, ATCMD_SIZE, "\r\n%s\r\n", LORA_AT_HELP);
|
||||
linkwan_serial_output(atcmd, strlen(atcmd));
|
||||
snprintf(atcmd, ATCMD_SIZE, "%s\r\n", LORA_AT_RM);
|
||||
linkwan_serial_output(atcmd, strlen(atcmd));
|
||||
snprintf(atcmd, ATCMD_SIZE, "%s\r\n", LORA_AT_APPEUI);
|
||||
linkwan_serial_output(atcmd, strlen(atcmd));
|
||||
snprintf(atcmd, ATCMD_SIZE, "%s\r\n", LORA_AT_APPKEY);
|
||||
linkwan_serial_output(atcmd, strlen(atcmd));
|
||||
snprintf(atcmd, ATCMD_SIZE, "%s\r\n", LORA_AT_DEUI);
|
||||
linkwan_serial_output(atcmd, strlen(atcmd));
|
||||
snprintf(atcmd, ATCMD_SIZE, "%s\r\n", LORA_AT_DR);
|
||||
linkwan_serial_output(atcmd, strlen(atcmd));
|
||||
snprintf(atcmd, ATCMD_SIZE, "%s\r\n", LORA_AT_ADR);
|
||||
linkwan_serial_output(atcmd, strlen(atcmd));
|
||||
snprintf(atcmd, ATCMD_SIZE, "%s\r\n", LORA_AT_CLASS);
|
||||
linkwan_serial_output(atcmd, strlen(atcmd));
|
||||
snprintf(atcmd, ATCMD_SIZE, "%s\r\n", LORA_AT_SCANMASK);
|
||||
linkwan_serial_output(atcmd, strlen(atcmd));
|
||||
snprintf(atcmd, ATCMD_SIZE, "%s\r\n", LORA_AT_CFM);
|
||||
linkwan_serial_output(atcmd, strlen(atcmd));
|
||||
snprintf(atcmd, ATCMD_SIZE, "%s\r\n", LORA_AT_CFMTRIALS);
|
||||
linkwan_serial_output(atcmd, strlen(atcmd));
|
||||
snprintf(atcmd, ATCMD_SIZE, "%s\r\n", LORA_AT_JOIN);
|
||||
linkwan_serial_output(atcmd, strlen(atcmd));
|
||||
snprintf(atcmd, ATCMD_SIZE, "%s\r\n", LORA_AT_DCS);
|
||||
linkwan_serial_output(atcmd, strlen(atcmd));
|
||||
snprintf(atcmd, ATCMD_SIZE, "%s\r\n", LORA_AT_TXSIZE);
|
||||
linkwan_serial_output(atcmd, strlen(atcmd));
|
||||
snprintf(atcmd, ATCMD_SIZE, "%s\r\n", LORA_AT_LINKCHK);
|
||||
linkwan_serial_output(atcmd, strlen(atcmd));
|
||||
return;
|
||||
} else if (strncmp(atcmd, LORA_AT_APPEUI, strlen(LORA_AT_APPEUI)) == 0) {
|
||||
if (atcmd_index == strlen(LORA_AT_APPEUI)) {
|
||||
uint8_t *eui = get_lora_app_eui();
|
||||
ret = true;
|
||||
snprintf(atcmd, ATCMD_SIZE, "\r\n%s %02x%02x%02x%02x%02x%02x%02x%02x\r\n", \
|
||||
LORA_AT_APPEUI, eui[0], eui[1], eui[2], eui[3], eui[4], eui[5], eui[6], eui[7]);
|
||||
} else if (atcmd_index == (strlen(LORA_AT_APPEUI) + 16)) {
|
||||
length = hex2bin(&atcmd[strlen(LORA_AT_APPEUI)], buf, 8);
|
||||
if (length == 8) {
|
||||
ret = set_lora_app_eui(buf);
|
||||
if (ret == true) {
|
||||
snprintf(atcmd, ATCMD_SIZE, "\r\n%s %02x%02x%02x%02x%02x%02x%02x%02x\r\n", \
|
||||
LORA_AT_APPEUI, buf[0], buf[1], buf[2], buf[3], buf[4], buf[5], buf[6], buf[7]);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (ret == false) {
|
||||
snprintf(atcmd, ATCMD_SIZE, "\r\n%s ERROR\r\n", LORA_AT_APPEUI);
|
||||
}
|
||||
} else if (strncmp(atcmd, LORA_AT_APPKEY, strlen(LORA_AT_APPKEY)) == 0) {
|
||||
if (atcmd_index == strlen(LORA_AT_APPKEY)) {
|
||||
uint8_t *key = get_lora_app_key();
|
||||
ret = true;
|
||||
snprintf(atcmd, ATCMD_SIZE, "\r\n%s %02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x\r\n", \
|
||||
LORA_AT_APPKEY, key[0], key[1], key[2], key[3], key[4], key[5], key[6], key[7],
|
||||
key[8], key[9], key[10], key[11], key[12], key[13], key[14], key[15]);
|
||||
} else if (atcmd_index == (strlen(LORA_AT_APPKEY) + 32)) {
|
||||
length = hex2bin(&atcmd[strlen(LORA_AT_APPKEY)], buf, 16);
|
||||
if (length == 16) {
|
||||
ret = set_lora_app_key(buf);
|
||||
if (ret == true) {
|
||||
snprintf(atcmd, ATCMD_SIZE, "\r\n%s %02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x\r\n", \
|
||||
LORA_AT_APPKEY, buf[0], buf[1], buf[2], buf[3], buf[4], buf[5], buf[6], buf[7],
|
||||
buf[8], buf[9], buf[10], buf[11], buf[12], buf[13], buf[14], buf[15]);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (ret == false) {
|
||||
snprintf(atcmd, ATCMD_SIZE, "\r\n%s ERROR\r\n", LORA_AT_APPKEY);
|
||||
}
|
||||
} else if (strncmp(atcmd, LORA_AT_DEUI, strlen(LORA_AT_DEUI)) == 0) {
|
||||
if (atcmd_index == strlen(LORA_AT_DEUI)) {
|
||||
uint8_t *eui = get_lora_dev_eui();
|
||||
ret = true;
|
||||
snprintf(atcmd, ATCMD_SIZE, "\r\n%s %02x%02x%02x%02x%02x%02x%02x%02x\r\n", \
|
||||
LORA_AT_DEUI, eui[0], eui[1], eui[2], eui[3], eui[4], eui[5], eui[6], eui[7]);
|
||||
} else if (atcmd_index == (strlen(LORA_AT_DEUI) + 16)) {
|
||||
length = hex2bin(&atcmd[strlen(LORA_AT_DEUI)], buf, 8);
|
||||
if (length == 8) {
|
||||
ret = set_lora_dev_eui(buf);
|
||||
if (ret == true) {
|
||||
snprintf(atcmd, ATCMD_SIZE, "\r\n%s %02x%02x%02x%02x%02x%02x%02x%02x\r\n", \
|
||||
LORA_AT_DEUI, buf[0], buf[1], buf[2], buf[3], buf[4], buf[5], buf[6], buf[7]);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (ret == false) {
|
||||
snprintf(atcmd, ATCMD_SIZE, "\r\n%s ERROR\r\n", LORA_AT_DEUI);
|
||||
}
|
||||
} else if (strncmp(atcmd, LORA_AT_RM, strlen(LORA_AT_RM)) == 0) {
|
||||
aos_kv_del("lora");
|
||||
aos_kv_del("lora_dev");
|
||||
ret = true;
|
||||
snprintf(atcmd, ATCMD_SIZE, "\r\n%s OK\r\n", LORA_AT_RM);
|
||||
} else if (strncmp(atcmd, LORA_AT_DR, strlen(LORA_AT_DR)) == 0) {
|
||||
int8_t datarate;
|
||||
if (atcmd_index == strlen(LORA_AT_DR)) {
|
||||
ret = true;
|
||||
datarate = get_lora_tx_datarate();
|
||||
snprintf(atcmd, ATCMD_SIZE, "\r\n%s %d\r\n", LORA_AT_DR, datarate);
|
||||
} else if (atcmd_index == (strlen(LORA_AT_DR) + 1)) {
|
||||
datarate = strtol(atcmd + strlen(LORA_AT_DR), NULL, 0);
|
||||
ret = set_lora_tx_datarate(datarate);
|
||||
if (ret == true) {
|
||||
snprintf(atcmd, ATCMD_SIZE, "\r\n%s %d\r\n", LORA_AT_DR, datarate);
|
||||
}
|
||||
}
|
||||
if (ret == false) {
|
||||
snprintf(atcmd, ATCMD_SIZE, "\r\n%s ERROR\r\n", LORA_AT_DR);
|
||||
}
|
||||
} else if (strncmp(atcmd, LORA_AT_ADR, strlen(LORA_AT_ADR)) == 0) {
|
||||
int adr;
|
||||
if (atcmd_index == strlen(LORA_AT_ADR)) {
|
||||
ret = true;
|
||||
adr = get_lora_adr();
|
||||
snprintf(atcmd, ATCMD_SIZE, "\r\n%s %d\r\n", LORA_AT_ADR, adr);
|
||||
} else if (atcmd_index == (strlen(LORA_AT_ADR) + 1)) {
|
||||
adr = strtol(atcmd + strlen(LORA_AT_ADR), NULL, 0);
|
||||
ret = set_lora_adr(adr);
|
||||
if (ret == true) {
|
||||
snprintf(atcmd, ATCMD_SIZE, "\r\n%s %d\r\n", LORA_AT_ADR, adr);
|
||||
}
|
||||
}
|
||||
if (ret == false) {
|
||||
snprintf(atcmd, ATCMD_SIZE, "\r\n%s ERROR\r\n", LORA_AT_ADR);
|
||||
}
|
||||
} else if (strncmp(atcmd, LORA_AT_CLASS, strlen(LORA_AT_CLASS)) == 0) {
|
||||
int8_t class;
|
||||
if (atcmd_index == strlen(LORA_AT_CLASS)) {
|
||||
ret = true;
|
||||
class = get_lora_class();
|
||||
snprintf(atcmd, ATCMD_SIZE, "\r\n%s %d\r\n", LORA_AT_CLASS, class);
|
||||
} else if (atcmd_index == (strlen(LORA_AT_CLASS) + 1)) {
|
||||
class = strtol(atcmd + strlen(LORA_AT_CLASS), NULL, 0);
|
||||
if (class == 0) {
|
||||
ret = set_lora_class(CLASS_A);
|
||||
} else if (class == 2) {
|
||||
ret = set_lora_class(CLASS_C);
|
||||
}
|
||||
if (ret == true) {
|
||||
snprintf(atcmd, ATCMD_SIZE, "\r\n%s %d\r\n", LORA_AT_CLASS, class);
|
||||
atcmd_index = strlen(atcmd);
|
||||
}
|
||||
}
|
||||
if (ret == false) {
|
||||
snprintf(atcmd, ATCMD_SIZE, "\r\n%s ERROR\r\n", LORA_AT_CLASS);
|
||||
}
|
||||
} else if (strncmp(atcmd, LORA_AT_CFM, strlen(LORA_AT_CFM)) == 0) {
|
||||
int cfm;
|
||||
if (atcmd_index == strlen(LORA_AT_CFM)) {
|
||||
ret = true;
|
||||
cfm = get_lora_tx_cfm_flag();
|
||||
snprintf(atcmd, ATCMD_SIZE, "\r\n%s %d\r\n", LORA_AT_CFM, cfm);
|
||||
} else if (atcmd_index == (strlen(LORA_AT_CFM) + 1)) {
|
||||
cfm = strtol(atcmd + strlen(LORA_AT_CFM), NULL, 0);
|
||||
ret = set_lora_tx_cfm_flag(cfm);
|
||||
if (ret == true) {
|
||||
snprintf(atcmd, ATCMD_SIZE, "\r\n%s %d\r\n", LORA_AT_CFM, cfm);
|
||||
}
|
||||
}
|
||||
if (ret == false) {
|
||||
snprintf(atcmd, ATCMD_SIZE, "\r\n%s ERROR\r\n", LORA_AT_CFM);
|
||||
}
|
||||
} else if (strncmp(atcmd, LORA_AT_CFMTRIALS, strlen(LORA_AT_CFMTRIALS)) == 0) {
|
||||
uint8_t trials;
|
||||
if (atcmd_index == strlen(LORA_AT_CFMTRIALS)) {
|
||||
ret = true;
|
||||
trials = get_lora_tx_cfm_trials();
|
||||
snprintf(atcmd, ATCMD_SIZE, "\r\n%s %d\r\n", LORA_AT_CFMTRIALS, trials);
|
||||
} else if (atcmd_index > strlen(LORA_AT_CFMTRIALS)) {
|
||||
trials = strtol(atcmd + strlen(LORA_AT_CFMTRIALS), NULL, 0);
|
||||
ret = set_lora_tx_cfm_trials(trials);
|
||||
if (ret == true) {
|
||||
snprintf(atcmd, ATCMD_SIZE, "\r\n%s %d\r\n", LORA_AT_CFMTRIALS, trials);
|
||||
}
|
||||
}
|
||||
if (ret == false) {
|
||||
snprintf(atcmd, ATCMD_SIZE, "\r\n%s ERROR\r\n", LORA_AT_CFMTRIALS);
|
||||
}
|
||||
} else if (strncmp(atcmd, LORA_AT_JOIN, strlen(LORA_AT_JOIN)) == 0) {
|
||||
ret = set_lora_state(DEVICE_STATE_JOIN);
|
||||
if (ret == true) {
|
||||
snprintf(atcmd, ATCMD_SIZE, "\r\n%s OK\r\n", LORA_AT_JOIN);
|
||||
}
|
||||
if (ret == false) {
|
||||
snprintf(atcmd, ATCMD_SIZE, "\r\n%s ERROR\r\n", LORA_AT_JOIN);
|
||||
}
|
||||
} else if (strncmp(atcmd, LORA_AT_DCS, strlen(LORA_AT_DCS)) == 0) {
|
||||
uint32_t dutycycle;
|
||||
if (atcmd_index == strlen(LORA_AT_DCS)) {
|
||||
ret = true;
|
||||
dutycycle = get_lora_tx_dutycycle();
|
||||
snprintf(atcmd, ATCMD_SIZE, "\r\n%s %d\r\n", LORA_AT_DCS, dutycycle);
|
||||
} else if (atcmd_index > strlen(LORA_AT_DCS)) {
|
||||
dutycycle = strtol(atcmd + strlen(LORA_AT_DCS), NULL, 0);
|
||||
ret = set_lora_tx_dutycycle(dutycycle);
|
||||
if (ret == true) {
|
||||
snprintf(atcmd, ATCMD_SIZE, "\r\n%s %d\r\n", LORA_AT_DCS, dutycycle);
|
||||
}
|
||||
}
|
||||
if (ret == false) {
|
||||
snprintf(atcmd, ATCMD_SIZE, "\r\n%s ERROR\r\n", LORA_AT_DCS);
|
||||
}
|
||||
} else if (strncmp(atcmd, LORA_AT_TXSIZE, strlen(LORA_AT_TXSIZE)) == 0) {
|
||||
uint8_t len;
|
||||
if (atcmd_index == strlen(LORA_AT_TXSIZE)) {
|
||||
ret = true;
|
||||
len = get_lora_tx_len();
|
||||
snprintf(atcmd, ATCMD_SIZE, "\r\n%s %d\r\n", LORA_AT_TXSIZE, len);
|
||||
} else if (atcmd_index > strlen(LORA_AT_TXSIZE)) {
|
||||
len = strtol(atcmd + strlen(LORA_AT_TXSIZE), NULL, 0);
|
||||
ret = set_lora_tx_len(len);
|
||||
if (ret == true) {
|
||||
snprintf(atcmd, ATCMD_SIZE, "\r\n%s %d\r\n", LORA_AT_TXSIZE, len);
|
||||
}
|
||||
}
|
||||
if (ret == false) {
|
||||
snprintf(atcmd, ATCMD_SIZE, "\r\n%s ERROR\r\n", LORA_AT_TXSIZE);
|
||||
}
|
||||
} else if (strncmp(atcmd, LORA_AT_LINKCHK, strlen(LORA_AT_LINKCHK)) == 0) {
|
||||
ret = send_lora_link_check();
|
||||
if (ret == true) {
|
||||
snprintf(atcmd, ATCMD_SIZE, "\r\n%s OK\r\n", LORA_AT_LINKCHK);
|
||||
}
|
||||
if (ret == false) {
|
||||
snprintf(atcmd, ATCMD_SIZE, "\r\n%s ERROR\r\n", LORA_AT_LINKCHK);
|
||||
}
|
||||
} else if (strncmp(atcmd, LORA_AT_SCANMASK, strlen(LORA_AT_SCANMASK)) == 0) {
|
||||
uint8_t mask[2];
|
||||
int length;
|
||||
if (atcmd_index == strlen(LORA_AT_SCANMASK)) {
|
||||
ret = true;
|
||||
snprintf(atcmd, ATCMD_SIZE, "\r\n%s 0x%04x\r\n", LORA_AT_SCANMASK, get_lora_freqband_mask());
|
||||
} else if (atcmd_index > strlen(LORA_AT_SCANMASK)) {
|
||||
length = hex2bin(&atcmd[strlen(LORA_AT_SCANMASK)], (uint8_t *)mask, 2);
|
||||
if (length == 2) {
|
||||
ret = set_lora_freqband_mask(mask[1] | (mask[0] << 8));
|
||||
if (ret == true) {
|
||||
snprintf(atcmd, ATCMD_SIZE, "\r\n%s 0x%04x\r\n", LORA_AT_SCANMASK, get_lora_freqband_mask());
|
||||
}
|
||||
}
|
||||
}
|
||||
if (ret == false) {
|
||||
snprintf(atcmd, ATCMD_SIZE, "\r\n%s ERROR\r\n", LORA_AT_SCANMASK);
|
||||
}
|
||||
} else {
|
||||
snprintf(atcmd, ATCMD_SIZE, "\r\nERROR\r\n");
|
||||
}
|
||||
|
||||
exit:
|
||||
linkwan_serial_output(atcmd, strlen(atcmd));
|
||||
atcmd_index = 0;
|
||||
memset(atcmd, 0xff, ATCMD_SIZE);
|
||||
}
|
||||
|
||||
void linkwan_at_init(void)
|
||||
{
|
||||
atcmd_index = 0;
|
||||
memset(atcmd, 0xff, ATCMD_SIZE);
|
||||
}
|
||||
1184
Living_SDK/kernel/protocols/lorawan/linkwan/region/RegionCN470A.c
Normal file
1184
Living_SDK/kernel/protocols/lorawan/linkwan/region/RegionCN470A.c
Normal file
File diff suppressed because it is too large
Load diff
|
|
@ -0,0 +1,504 @@
|
|||
/*!
|
||||
* \file RegionCN470.h
|
||||
*
|
||||
* \brief Region definition for CN470
|
||||
*
|
||||
* \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 REGIONCN470 Region CN470
|
||||
* Implementation according to LoRaWAN Specification v1.0.2.
|
||||
* \{
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2015-2017 Alibaba Group Holding Limited
|
||||
*/
|
||||
|
||||
#ifndef __REGION_CN470A_H__
|
||||
#define __REGION_CN470A_H__
|
||||
|
||||
/*!
|
||||
* LoRaMac maximum number of channels
|
||||
*/
|
||||
#define CN470A_MAX_NB_CHANNELS 16
|
||||
|
||||
/*!
|
||||
* Number of default channels
|
||||
*/
|
||||
#define CN470A_NUMB_DEFAULT_CHANNELS 8
|
||||
|
||||
/*!
|
||||
* Minimal datarate that can be used by the node
|
||||
*/
|
||||
#define CN470A_TX_MIN_DATARATE DR_0
|
||||
|
||||
/*!
|
||||
* Maximal datarate that can be used by the node
|
||||
*/
|
||||
#define CN470A_TX_MAX_DATARATE DR_5
|
||||
|
||||
/*!
|
||||
* Minimal datarate that can be used by the node
|
||||
*/
|
||||
#define CN470A_RX_MIN_DATARATE DR_0
|
||||
|
||||
/*!
|
||||
* Maximal datarate that can be used by the node
|
||||
*/
|
||||
#define CN470A_RX_MAX_DATARATE DR_5
|
||||
|
||||
/*!
|
||||
* Default datarate used by the node
|
||||
*/
|
||||
#define CN470A_DEFAULT_DATARATE DR_2
|
||||
|
||||
/*!
|
||||
* Minimal Rx1 receive datarate offset
|
||||
*/
|
||||
#define CN470A_MIN_RX1_DR_OFFSET 0
|
||||
|
||||
/*!
|
||||
* Maximal Rx1 receive datarate offset
|
||||
*/
|
||||
#define CN470A_MAX_RX1_DR_OFFSET 5
|
||||
|
||||
/*!
|
||||
* Default Rx1 receive datarate offset
|
||||
*/
|
||||
#define CN470A_DEFAULT_RX1_DR_OFFSET 0
|
||||
|
||||
/*!
|
||||
* Minimal Tx output power that can be used by the node
|
||||
*/
|
||||
#define CN470A_MIN_TX_POWER TX_POWER_7
|
||||
|
||||
/*!
|
||||
* Maximal Tx output power that can be used by the node
|
||||
*/
|
||||
#define CN470A_MAX_TX_POWER TX_POWER_0
|
||||
|
||||
/*!
|
||||
* Default Tx output power used by the node
|
||||
*/
|
||||
#define CN470A_DEFAULT_TX_POWER TX_POWER_0
|
||||
|
||||
/*!
|
||||
* Default Max EIRP
|
||||
*/
|
||||
#define CN470A_DEFAULT_MAX_EIRP 12.15f
|
||||
|
||||
/*!
|
||||
* Default antenna gain
|
||||
*/
|
||||
#define CN470A_DEFAULT_ANTENNA_GAIN 2.15f
|
||||
|
||||
/*!
|
||||
* ADR Ack limit
|
||||
*/
|
||||
#define CN470A_ADR_ACK_LIMIT 64
|
||||
|
||||
/*!
|
||||
* ADR Ack delay
|
||||
*/
|
||||
#define CN470A_ADR_ACK_DELAY 32
|
||||
|
||||
/*!
|
||||
* Enabled or disabled the duty cycle
|
||||
*/
|
||||
#define CN470A_DUTY_CYCLE_ENABLED 0//1
|
||||
|
||||
/*!
|
||||
* Maximum RX window duration
|
||||
*/
|
||||
#define CN470A_MAX_RX_WINDOW 3000
|
||||
|
||||
/*!
|
||||
* Receive delay 1
|
||||
*/
|
||||
#define CN470A_RECEIVE_DELAY1 1000
|
||||
|
||||
/*!
|
||||
* Receive delay 2
|
||||
*/
|
||||
#define CN470A_RECEIVE_DELAY2 2000
|
||||
|
||||
/*!
|
||||
* Join accept delay 1
|
||||
*/
|
||||
#define CN470A_JOIN_ACCEPT_DELAY1 5000
|
||||
|
||||
/*!
|
||||
* Join accept delay 2
|
||||
*/
|
||||
#define CN470A_JOIN_ACCEPT_DELAY2 6000
|
||||
|
||||
/*!
|
||||
* Maximum frame counter gap
|
||||
*/
|
||||
#define CN470A_MAX_FCNT_GAP 16384
|
||||
|
||||
/*!
|
||||
* Ack timeout
|
||||
*/
|
||||
#define CN470A_ACKTIMEOUT 2000
|
||||
|
||||
/*!
|
||||
* Random ack timeout limits
|
||||
*/
|
||||
#define CN470A_ACK_TIMEOUT_RND 1000
|
||||
|
||||
/*!
|
||||
* Verification of default datarate
|
||||
*/
|
||||
#if ( CN470A_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 CN470A_RX_WND_2_FREQ 505300000
|
||||
|
||||
/*!
|
||||
* Second reception window channel datarate definition.
|
||||
*/
|
||||
#define CN470A_RX_WND_2_DR DR_0
|
||||
|
||||
/*!
|
||||
* LoRaMac maximum number of bands
|
||||
*/
|
||||
#define CN470A_MAX_NB_BANDS 1
|
||||
|
||||
/*!
|
||||
* Band 0 definition
|
||||
* { DutyCycle, TxMaxPower, LastTxDoneTime, TimeOff }
|
||||
*/
|
||||
#define CN470A_BAND0 { 1, CN470A_MAX_TX_POWER, 0, 0 }
|
||||
|
||||
/*!
|
||||
* LoRaMac default channel 1
|
||||
* Channel = { Frequency [Hz], RX1 Frequency [Hz], { ( ( DrMax << 4 ) | DrMin ) }, Band }
|
||||
*/
|
||||
#define CN470A_LC1 { 471900000, 0, { ( ( DR_5 << 4 ) | DR_0 ) }, 0 }
|
||||
|
||||
/*!
|
||||
* LoRaMac default channel 2
|
||||
* Channel = { Frequency [Hz], RX1 Frequency [Hz], { ( ( DrMax << 4 ) | DrMin ) }, Band }
|
||||
*/
|
||||
#define CN470A_LC2 { 472100000, 0, { ( ( DR_5 << 4 ) | DR_0 ) }, 0 }
|
||||
|
||||
/*!
|
||||
* LoRaMac default channel 3
|
||||
* Channel = { Frequency [Hz], RX1 Frequency [Hz], { ( ( DrMax << 4 ) | DrMin ) }, Band }
|
||||
*/
|
||||
#define CN470A_LC3 { 472300000, 0, { ( ( DR_5 << 4 ) | DR_0 ) }, 0 }
|
||||
|
||||
/*!
|
||||
* LoRaMac default channel 4
|
||||
* Channel = { Frequency [Hz], RX1 Frequency [Hz], { ( ( DrMax << 4 ) | DrMin ) }, Band }
|
||||
*/
|
||||
#define CN470A_LC4 { 472500000, 0, { ( ( DR_5 << 4 ) | DR_0 ) }, 0 }
|
||||
|
||||
/*!
|
||||
* LoRaMac default channel 5
|
||||
* Channel = { Frequency [Hz], RX1 Frequency [Hz], { ( ( DrMax << 4 ) | DrMin ) }, Band }
|
||||
*/
|
||||
#define CN470A_LC5 { 472700000, 0, { ( ( DR_5 << 4 ) | DR_0 ) }, 0 }
|
||||
|
||||
/*!
|
||||
* LoRaMac default channel 6
|
||||
* Channel = { Frequency [Hz], RX1 Frequency [Hz], { ( ( DrMax << 4 ) | DrMin ) }, Band }
|
||||
*/
|
||||
#define CN470A_LC6 { 472900000, 0, { ( ( DR_5 << 4 ) | DR_0 ) }, 0 }
|
||||
|
||||
/*!
|
||||
* LoRaMac default channel 7
|
||||
* Channel = { Frequency [Hz], RX1 Frequency [Hz], { ( ( DrMax << 4 ) | DrMin ) }, Band }
|
||||
*/
|
||||
#define CN470A_LC7 { 473100000, 0, { ( ( DR_5 << 4 ) | DR_0 ) }, 0 }
|
||||
|
||||
|
||||
/*!
|
||||
* LoRaMac default channel 8
|
||||
* Channel = { Frequency [Hz], RX1 Frequency [Hz], { ( ( DrMax << 4 ) | DrMin ) }, Band }
|
||||
*/
|
||||
#define CN470A_LC8 { 473300000, 0, { ( ( DR_5 << 4 ) | DR_0 ) }, 0 }
|
||||
|
||||
|
||||
/*!
|
||||
* LoRaMac channels which are allowed for the join procedure
|
||||
*/
|
||||
#define CN470A_JOIN_CHANNELS ( uint16_t )( LC( 1 ) | LC( 2 ) | LC( 3 ) | LC( 4 ) | LC( 5 ) | LC( 6 ) |LC( 7 ) | LC( 8 ) )
|
||||
|
||||
/*!
|
||||
* Data rates table definition
|
||||
*/
|
||||
static const uint8_t DataratesCN470A[] = { 12, 11, 10, 9, 8, 7, 7, 50 };
|
||||
|
||||
/*!
|
||||
* Preamble Lenth 2.1s table definition for SF12~7
|
||||
*/
|
||||
static const uint16_t PreambleLenthCN470A[] = { 60, 124, 253, 509, 1022, 2047 };
|
||||
|
||||
|
||||
/*!
|
||||
* Bandwidths table definition in Hz
|
||||
*/
|
||||
static const uint32_t BandwidthsCN470A[] = { 125e3, 125e3, 125e3, 125e3, 125e3, 125e3, 250e3, 0 };
|
||||
|
||||
/*!
|
||||
* Maximum payload with respect to the datarate index. Cannot operate with repeater.
|
||||
*/
|
||||
static const uint8_t MaxPayloadOfDatarateCN470A[] = { 51, 51, 51, 115, 242, 242, 242, 242 };
|
||||
|
||||
/*!
|
||||
* Maximum payload with respect to the datarate index. Can operate with repeater.
|
||||
*/
|
||||
static const uint8_t MaxPayloadOfDatarateRepeaterCN470A[] = { 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 RegionCN470AGetPhyParam( GetPhyParams_t* getPhy );
|
||||
|
||||
/*!
|
||||
* \brief Updates the last TX done parameters of the current channel.
|
||||
*
|
||||
* \param [IN] txDone Pointer to the function parameters.
|
||||
*/
|
||||
void RegionCN470ASetBandTxDone( SetBandTxDoneParams_t* txDone );
|
||||
|
||||
/*!
|
||||
* \brief Initializes the channels masks and the channels.
|
||||
*
|
||||
* \param [IN] type Sets the initialization type.
|
||||
*/
|
||||
void RegionCN470AInitDefaults( InitType_t type );
|
||||
|
||||
/*!
|
||||
* \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 RegionCN470AVerify( 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 RegionCN470AApplyCFList( 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 RegionCN470AChanMaskSet( ChanMaskSetParams_t* chanMaskSet );
|
||||
|
||||
/*!
|
||||
* \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 RegionCN470AAdrNext( AdrNextParams_t* adrNext, int8_t* drOut, int8_t* txPowOut, uint32_t* adrAckCounter );
|
||||
|
||||
/*!
|
||||
* 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 RegionCN470AComputeRxWindowParameters( 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 RegionCN470ARxConfig( 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 RegionCN470ATxConfig( 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 RegionCN470ALinkAdrReq( 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 RegionCN470ARxParamSetupReq( 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 RegionCN470ANewChannelReq( 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 RegionCN470ATxParamSetupReq( 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 RegionCN470ADlChannelReq( DlChannelReqParams_t* dlChannelReq );
|
||||
|
||||
/*
|
||||
* \brief Alternates the datarate of the channel for the join request.
|
||||
*
|
||||
* \param [IN] alternateDr Pointer to the function parameters.
|
||||
*
|
||||
* \retval Datarate to apply.
|
||||
*/
|
||||
int8_t RegionCN470AAlternateDr( AlternateDrParams_t* alternateDr );
|
||||
|
||||
/*!
|
||||
* \brief Calculates the back-off time.
|
||||
*
|
||||
* \param [IN] calcBackOff Pointer to the function parameters.
|
||||
*/
|
||||
void RegionCN470ACalcBackOff( 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]
|
||||
*/
|
||||
bool RegionCN470ANextChannel( 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 RegionCN470AChannelAdd( 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 RegionCN470AChannelsRemove( ChannelRemoveParams_t* channelRemove );
|
||||
|
||||
/*!
|
||||
* \brief Sets the radio into continuous wave mode.
|
||||
*
|
||||
* \param [IN] continuousWave Pointer to the function parameters.
|
||||
*/
|
||||
void RegionCN470ASetContinuousWave( 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 RegionCN470AApplyDrOffset( uint8_t downlinkDwellTime, int8_t dr, int8_t drOffset );
|
||||
|
||||
/*! \} defgroup REGIONCN470A */
|
||||
|
||||
#endif // __REGION_CN470A_H__
|
||||
25
Living_SDK/kernel/protocols/lorawan/lora/LICENSE.txt
Normal file
25
Living_SDK/kernel/protocols/lorawan/lora/LICENSE.txt
Normal 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.
|
||||
3056
Living_SDK/kernel/protocols/lorawan/lora/mac/LoRaMac.c
Normal file
3056
Living_SDK/kernel/protocols/lorawan/lora/mac/LoRaMac.c
Normal file
File diff suppressed because it is too large
Load diff
1933
Living_SDK/kernel/protocols/lorawan/lora/mac/LoRaMac.h
Normal file
1933
Living_SDK/kernel/protocols/lorawan/lora/mac/LoRaMac.h
Normal file
File diff suppressed because it is too large
Load diff
206
Living_SDK/kernel/protocols/lorawan/lora/mac/LoRaMacCrypto.c
Normal file
206
Living_SDK/kernel/protocols/lorawan/lora/mac/LoRaMacCrypto.c
Normal file
|
|
@ -0,0 +1,206 @@
|
|||
/*
|
||||
* Copyright (C) 2015-2017 Alibaba Group Holding Limited
|
||||
*/
|
||||
|
||||
/*
|
||||
/ _____) _ | |
|
||||
( (____ _____ ____ _| |_ _____ ____| |__
|
||||
\____ \| ___ | (_ _) ___ |/ ___) _ \
|
||||
_____) ) ____| | | || |_| ____( (___| | | |
|
||||
(______/|_____)_|_|_| \__)_____)\____)_| |_|
|
||||
(C)2013 Semtech
|
||||
___ _____ _ ___ _ _____ ___ ___ ___ ___
|
||||
/ __|_ _/_\ / __| |/ / __/ _ \| _ \/ __| __|
|
||||
\__ \ | |/ _ \ (__| ' <| _| (_) | / (__| _|
|
||||
|___/ |_/_/ \_\___|_|\_\_| \___/|_|_\\___|___|
|
||||
embedded.connectivity.solutions===============
|
||||
|
||||
Description: LoRa MAC layer 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 <stdlib.h>
|
||||
#include <stdint.h>
|
||||
#include "utilities.h"
|
||||
|
||||
#include "aes.h"
|
||||
#include "cmac.h"
|
||||
|
||||
#include "LoRaMacCrypto.h"
|
||||
|
||||
/*!
|
||||
* CMAC/AES Message Integrity Code (MIC) Block B0 size
|
||||
*/
|
||||
#define LORAMAC_MIC_BLOCK_B0_SIZE 16
|
||||
|
||||
/*!
|
||||
* MIC field computation initial data
|
||||
*/
|
||||
static uint8_t MicBlockB0[] = { 0x49, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
|
||||
};
|
||||
|
||||
/*!
|
||||
* Contains the computed MIC field.
|
||||
*
|
||||
* \remark Only the 4 first bytes are used
|
||||
*/
|
||||
static uint8_t Mic[16];
|
||||
|
||||
/*!
|
||||
* Encryption aBlock and sBlock
|
||||
*/
|
||||
static uint8_t aBlock[] = { 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
|
||||
};
|
||||
static uint8_t sBlock[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
|
||||
};
|
||||
|
||||
/*!
|
||||
* AES computation context variable
|
||||
*/
|
||||
static aes_context AesContext;
|
||||
|
||||
/*!
|
||||
* CMAC computation context variable
|
||||
*/
|
||||
static AES_CMAC_CTX AesCmacCtx[1];
|
||||
|
||||
/*!
|
||||
* \brief Computes the LoRaMAC frame MIC field
|
||||
*
|
||||
* \param [IN] buffer Data buffer
|
||||
* \param [IN] size Data buffer size
|
||||
* \param [IN] key AES key to be used
|
||||
* \param [IN] address Frame address
|
||||
* \param [IN] dir Frame direction [0: uplink, 1: downlink]
|
||||
* \param [IN] sequenceCounter Frame sequence counter
|
||||
* \param [OUT] mic Computed MIC field
|
||||
*/
|
||||
void LoRaMacComputeMic( const uint8_t *buffer, uint16_t size, const uint8_t *key, uint32_t address, uint8_t dir, uint32_t sequenceCounter, uint32_t *mic )
|
||||
{
|
||||
MicBlockB0[5] = dir;
|
||||
|
||||
MicBlockB0[6] = ( address ) & 0xFF;
|
||||
MicBlockB0[7] = ( address >> 8 ) & 0xFF;
|
||||
MicBlockB0[8] = ( address >> 16 ) & 0xFF;
|
||||
MicBlockB0[9] = ( address >> 24 ) & 0xFF;
|
||||
|
||||
MicBlockB0[10] = ( sequenceCounter ) & 0xFF;
|
||||
MicBlockB0[11] = ( sequenceCounter >> 8 ) & 0xFF;
|
||||
MicBlockB0[12] = ( sequenceCounter >> 16 ) & 0xFF;
|
||||
MicBlockB0[13] = ( sequenceCounter >> 24 ) & 0xFF;
|
||||
|
||||
MicBlockB0[15] = size & 0xFF;
|
||||
|
||||
AES_CMAC_Init( AesCmacCtx );
|
||||
|
||||
AES_CMAC_SetKey( AesCmacCtx, key );
|
||||
|
||||
AES_CMAC_Update( AesCmacCtx, MicBlockB0, LORAMAC_MIC_BLOCK_B0_SIZE );
|
||||
|
||||
AES_CMAC_Update( AesCmacCtx, buffer, size & 0xFF );
|
||||
|
||||
AES_CMAC_Final( Mic, AesCmacCtx );
|
||||
|
||||
*mic = ( uint32_t )( ( uint32_t )Mic[3] << 24 | ( uint32_t )Mic[2] << 16 | ( uint32_t )Mic[1] << 8 | ( uint32_t )Mic[0] );
|
||||
}
|
||||
|
||||
void LoRaMacPayloadEncrypt( const uint8_t *buffer, uint16_t size, const uint8_t *key, uint32_t address, uint8_t dir, uint32_t sequenceCounter, uint8_t *encBuffer )
|
||||
{
|
||||
uint16_t i;
|
||||
uint8_t bufferIndex = 0;
|
||||
uint16_t ctr = 1;
|
||||
|
||||
memset1( AesContext.ksch, '\0', 240 );
|
||||
aes_set_key( key, 16, &AesContext );
|
||||
|
||||
aBlock[5] = dir;
|
||||
|
||||
aBlock[6] = ( address ) & 0xFF;
|
||||
aBlock[7] = ( address >> 8 ) & 0xFF;
|
||||
aBlock[8] = ( address >> 16 ) & 0xFF;
|
||||
aBlock[9] = ( address >> 24 ) & 0xFF;
|
||||
|
||||
aBlock[10] = ( sequenceCounter ) & 0xFF;
|
||||
aBlock[11] = ( sequenceCounter >> 8 ) & 0xFF;
|
||||
aBlock[12] = ( sequenceCounter >> 16 ) & 0xFF;
|
||||
aBlock[13] = ( sequenceCounter >> 24 ) & 0xFF;
|
||||
|
||||
while( size >= 16 )
|
||||
{
|
||||
aBlock[15] = ( ( ctr ) & 0xFF );
|
||||
ctr++;
|
||||
aes_encrypt( aBlock, sBlock, &AesContext );
|
||||
for( i = 0; i < 16; i++ )
|
||||
{
|
||||
encBuffer[bufferIndex + i] = buffer[bufferIndex + i] ^ sBlock[i];
|
||||
}
|
||||
size -= 16;
|
||||
bufferIndex += 16;
|
||||
}
|
||||
|
||||
if( size > 0 )
|
||||
{
|
||||
aBlock[15] = ( ( ctr ) & 0xFF );
|
||||
aes_encrypt( aBlock, sBlock, &AesContext );
|
||||
for( i = 0; i < size; i++ )
|
||||
{
|
||||
encBuffer[bufferIndex + i] = buffer[bufferIndex + i] ^ sBlock[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void LoRaMacPayloadDecrypt( const uint8_t *buffer, uint16_t size, const uint8_t *key, uint32_t address, uint8_t dir, uint32_t sequenceCounter, uint8_t *decBuffer )
|
||||
{
|
||||
LoRaMacPayloadEncrypt( buffer, size, key, address, dir, sequenceCounter, decBuffer );
|
||||
}
|
||||
|
||||
void LoRaMacJoinComputeMic( const uint8_t *buffer, uint16_t size, const uint8_t *key, uint32_t *mic )
|
||||
{
|
||||
AES_CMAC_Init( AesCmacCtx );
|
||||
|
||||
AES_CMAC_SetKey( AesCmacCtx, key );
|
||||
|
||||
AES_CMAC_Update( AesCmacCtx, buffer, size & 0xFF );
|
||||
|
||||
AES_CMAC_Final( Mic, AesCmacCtx );
|
||||
|
||||
*mic = ( uint32_t )( ( uint32_t )Mic[3] << 24 | ( uint32_t )Mic[2] << 16 | ( uint32_t )Mic[1] << 8 | ( uint32_t )Mic[0] );
|
||||
}
|
||||
|
||||
void LoRaMacJoinDecrypt( const uint8_t *buffer, uint16_t size, const uint8_t *key, uint8_t *decBuffer )
|
||||
{
|
||||
memset1( AesContext.ksch, '\0', 240 );
|
||||
aes_set_key( key, 16, &AesContext );
|
||||
aes_encrypt( buffer, decBuffer, &AesContext );
|
||||
// Check if optional CFList is included
|
||||
if( size >= 16 )
|
||||
{
|
||||
aes_encrypt( buffer + 16, decBuffer + 16, &AesContext );
|
||||
}
|
||||
}
|
||||
|
||||
void LoRaMacJoinComputeSKeys( const uint8_t *key, const uint8_t *appNonce, uint16_t devNonce, uint8_t *nwkSKey, uint8_t *appSKey )
|
||||
{
|
||||
uint8_t nonce[16];
|
||||
uint8_t *pDevNonce = ( uint8_t * )&devNonce;
|
||||
|
||||
memset1( AesContext.ksch, '\0', 240 );
|
||||
aes_set_key( key, 16, &AesContext );
|
||||
|
||||
memset1( nonce, 0, sizeof( nonce ) );
|
||||
nonce[0] = 0x01;
|
||||
memcpy1( nonce + 1, appNonce, 6 );
|
||||
memcpy1( nonce + 7, pDevNonce, 2 );
|
||||
aes_encrypt( nonce, nwkSKey, &AesContext );
|
||||
|
||||
memset1( nonce, 0, sizeof( nonce ) );
|
||||
nonce[0] = 0x02;
|
||||
memcpy1( nonce + 1, appNonce, 6 );
|
||||
memcpy1( nonce + 7, pDevNonce, 2 );
|
||||
aes_encrypt( nonce, appSKey, &AesContext );
|
||||
}
|
||||
115
Living_SDK/kernel/protocols/lorawan/lora/mac/LoRaMacCrypto.h
Normal file
115
Living_SDK/kernel/protocols/lorawan/lora/mac/LoRaMacCrypto.h
Normal file
|
|
@ -0,0 +1,115 @@
|
|||
/*
|
||||
* Copyright (C) 2015-2017 Alibaba Group Holding Limited
|
||||
*/
|
||||
|
||||
/*!
|
||||
* \file LoRaMacCrypto.h
|
||||
*
|
||||
* \brief LoRa MAC layer cryptography 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 LORAMAC_CRYPTO LoRa MAC layer cryptography implementation
|
||||
* This module covers the implementation of cryptographic functions
|
||||
* of the LoRaMAC layer.
|
||||
* \{
|
||||
*/
|
||||
#ifndef __LORAMAC_CRYPTO_H__
|
||||
#define __LORAMAC_CRYPTO_H__
|
||||
|
||||
/*!
|
||||
* Computes the LoRaMAC frame MIC field
|
||||
*
|
||||
* \param [IN] buffer - Data buffer
|
||||
* \param [IN] size - Data buffer size
|
||||
* \param [IN] key - AES key to be used
|
||||
* \param [IN] address - Frame address
|
||||
* \param [IN] dir - Frame direction [0: uplink, 1: downlink]
|
||||
* \param [IN] sequenceCounter - Frame sequence counter
|
||||
* \param [OUT] mic - Computed MIC field
|
||||
*/
|
||||
void LoRaMacComputeMic( const uint8_t *buffer, uint16_t size, const uint8_t *key, uint32_t address, uint8_t dir, uint32_t sequenceCounter, uint32_t *mic );
|
||||
|
||||
/*!
|
||||
* Computes the LoRaMAC payload encryption
|
||||
*
|
||||
* \param [IN] buffer - Data buffer
|
||||
* \param [IN] size - Data buffer size
|
||||
* \param [IN] key - AES key to be used
|
||||
* \param [IN] address - Frame address
|
||||
* \param [IN] dir - Frame direction [0: uplink, 1: downlink]
|
||||
* \param [IN] sequenceCounter - Frame sequence counter
|
||||
* \param [OUT] encBuffer - Encrypted buffer
|
||||
*/
|
||||
void LoRaMacPayloadEncrypt( const uint8_t *buffer, uint16_t size, const uint8_t *key, uint32_t address, uint8_t dir, uint32_t sequenceCounter, uint8_t *encBuffer );
|
||||
|
||||
/*!
|
||||
* Computes the LoRaMAC payload decryption
|
||||
*
|
||||
* \param [IN] buffer - Data buffer
|
||||
* \param [IN] size - Data buffer size
|
||||
* \param [IN] key - AES key to be used
|
||||
* \param [IN] address - Frame address
|
||||
* \param [IN] dir - Frame direction [0: uplink, 1: downlink]
|
||||
* \param [IN] sequenceCounter - Frame sequence counter
|
||||
* \param [OUT] decBuffer - Decrypted buffer
|
||||
*/
|
||||
void LoRaMacPayloadDecrypt( const uint8_t *buffer, uint16_t size, const uint8_t *key, uint32_t address, uint8_t dir, uint32_t sequenceCounter, uint8_t *decBuffer );
|
||||
|
||||
/*!
|
||||
* Computes the LoRaMAC Join Request frame MIC field
|
||||
*
|
||||
* \param [IN] buffer - Data buffer
|
||||
* \param [IN] size - Data buffer size
|
||||
* \param [IN] key - AES key to be used
|
||||
* \param [OUT] mic - Computed MIC field
|
||||
*/
|
||||
void LoRaMacJoinComputeMic( const uint8_t *buffer, uint16_t size, const uint8_t *key, uint32_t *mic );
|
||||
|
||||
/*!
|
||||
* Computes the LoRaMAC join frame decryption
|
||||
*
|
||||
* \param [IN] buffer - Data buffer
|
||||
* \param [IN] size - Data buffer size
|
||||
* \param [IN] key - AES key to be used
|
||||
* \param [OUT] decBuffer - Decrypted buffer
|
||||
*/
|
||||
void LoRaMacJoinDecrypt( const uint8_t *buffer, uint16_t size, const uint8_t *key, uint8_t *decBuffer );
|
||||
|
||||
/*!
|
||||
* Computes the LoRaMAC join frame decryption
|
||||
*
|
||||
* \param [IN] key - AES key to be used
|
||||
* \param [IN] appNonce - Application nonce
|
||||
* \param [IN] devNonce - Device nonce
|
||||
* \param [OUT] nwkSKey - Network session key
|
||||
* \param [OUT] appSKey - Application session key
|
||||
*/
|
||||
void LoRaMacJoinComputeSKeys( const uint8_t *key, const uint8_t *appNonce, uint16_t devNonce, uint8_t *nwkSKey, uint8_t *appSKey );
|
||||
|
||||
/*! \} defgroup LORAMAC */
|
||||
|
||||
#endif // __LORAMAC_CRYPTO_H__
|
||||
85
Living_SDK/kernel/protocols/lorawan/lora/mac/LoRaMacTest.h
Normal file
85
Living_SDK/kernel/protocols/lorawan/lora/mac/LoRaMacTest.h
Normal file
|
|
@ -0,0 +1,85 @@
|
|||
/*
|
||||
* Copyright (C) 2015-2017 Alibaba Group Holding Limited
|
||||
*/
|
||||
|
||||
/*!
|
||||
* \file LoRaMacTest.h
|
||||
*
|
||||
* \brief LoRa MAC layer test function 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 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 reception windows
|
||||
*
|
||||
* \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 reception windows
|
||||
*/
|
||||
void LoRaMacTestRxWindowsOn( bool enable );
|
||||
|
||||
/*!
|
||||
* \brief Enables the MIC field test
|
||||
*
|
||||
* \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] txPacketCounter - Fixed Tx packet counter value
|
||||
*/
|
||||
void LoRaMacTestSetMic( uint16_t txPacketCounter );
|
||||
|
||||
/*!
|
||||
* \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 );
|
||||
|
||||
/*!
|
||||
* \brief Sets the channel index
|
||||
*
|
||||
* \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] channel - Channel index
|
||||
*/
|
||||
void LoRaMacTestSetChannel( uint8_t channel );
|
||||
|
||||
/*! \} defgroup LORAMACTEST */
|
||||
|
||||
#endif // __LORAMACTEST_H__
|
||||
1117
Living_SDK/kernel/protocols/lorawan/lora/mac/region/Region.c
Normal file
1117
Living_SDK/kernel/protocols/lorawan/lora/mac/region/Region.c
Normal file
File diff suppressed because it is too large
Load diff
1501
Living_SDK/kernel/protocols/lorawan/lora/mac/region/Region.h
Normal file
1501
Living_SDK/kernel/protocols/lorawan/lora/mac/region/Region.h
Normal file
File diff suppressed because it is too large
Load diff
1114
Living_SDK/kernel/protocols/lorawan/lora/mac/region/RegionAS923.c
Normal file
1114
Living_SDK/kernel/protocols/lorawan/lora/mac/region/RegionAS923.c
Normal file
File diff suppressed because it is too large
Load diff
|
|
@ -0,0 +1,507 @@
|
|||
/*
|
||||
* Copyright (C) 2015-2017 Alibaba Group Holding Limited
|
||||
*/
|
||||
|
||||
/*!
|
||||
* \file RegionAS923.h
|
||||
*
|
||||
* \brief Region definition for AS923
|
||||
*
|
||||
* \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 REGIONAS923 Region AS923
|
||||
* Implementation according to LoRaWAN Specification v1.0.2.
|
||||
* \{
|
||||
*/
|
||||
#ifndef __REGION_AS923_H__
|
||||
#define __REGION_AS923_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
|
||||
|
||||
/*!
|
||||
* Maximum number of bands
|
||||
*/
|
||||
#define AS923_MAX_NB_BANDS 1
|
||||
|
||||
/*!
|
||||
* Band 0 definition
|
||||
* { DutyCycle, TxMaxPower, LastTxDoneTime, TimeOff }
|
||||
*/
|
||||
#define AS923_BAND0 { 100, AS923_MAX_TX_POWER, 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( InitType_t type );
|
||||
|
||||
/*!
|
||||
* \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 );
|
||||
|
||||
/*!
|
||||
* \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 RegionAS923AdrNext( AdrNextParams_t* adrNext, int8_t* drOut, int8_t* txPowOut, uint32_t* adrAckCounter );
|
||||
|
||||
/*!
|
||||
* 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] alternateDr Pointer to the function parameters.
|
||||
*
|
||||
* \retval Datarate to apply.
|
||||
*/
|
||||
int8_t RegionAS923AlternateDr( AlternateDrParams_t* alternateDr );
|
||||
|
||||
/*!
|
||||
* \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]
|
||||
*/
|
||||
bool 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 );
|
||||
|
||||
/*! \} defgroup REGIONAS923 */
|
||||
|
||||
#endif // __REGION_AS923_H__
|
||||
|
|
@ -0,0 +1,868 @@
|
|||
/*
|
||||
* Copyright (C) 2015-2017 Alibaba Group Holding Limited
|
||||
*/
|
||||
|
||||
/*
|
||||
/ _____) _ | |
|
||||
( (____ _____ ____ _| |_ _____ ____| |__
|
||||
\____ \| ___ | (_ _) ___ |/ ___) _ \
|
||||
_____) ) ____| | | || |_| ____( (___| | | |
|
||||
(______/|_____)_|_|_| \__)_____)\____)_| |_|
|
||||
(C)2013 Semtech
|
||||
___ _____ _ ___ _ _____ ___ ___ ___ ___
|
||||
/ __|_ _/_\ / __| |/ / __/ _ \| _ \/ __| __|
|
||||
\__ \ | |/ _ \ (__| ' <| _| (_) | / (__| _|
|
||||
|___/ |_/_/ \_\___|_|\_\_| \___/|_|_\\___|___|
|
||||
embedded.connectivity.solutions===============
|
||||
|
||||
Description: LoRa MAC region AU915 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 <stdbool.h>
|
||||
#include <string.h>
|
||||
#include <stdint.h>
|
||||
#include <math.h>
|
||||
|
||||
#include "radio.h"
|
||||
//#include "timer.h"
|
||||
#include "timeServer.h"
|
||||
#include "LoRaMac.h"
|
||||
|
||||
#include "utilities.h"
|
||||
|
||||
#include "Region.h"
|
||||
#include "RegionCommon.h"
|
||||
#include "RegionAU915.h"
|
||||
#include "debug.h"
|
||||
|
||||
// Definitions
|
||||
#define CHANNELS_MASK_SIZE 6
|
||||
|
||||
// Global attributes
|
||||
/*!
|
||||
* LoRaMAC channels
|
||||
*/
|
||||
static ChannelParams_t Channels[AU915_MAX_NB_CHANNELS];
|
||||
|
||||
/*!
|
||||
* LoRaMac bands
|
||||
*/
|
||||
static Band_t Bands[AU915_MAX_NB_BANDS] =
|
||||
{
|
||||
AU915_BAND0
|
||||
};
|
||||
|
||||
/*!
|
||||
* LoRaMac channels mask
|
||||
*/
|
||||
static uint16_t ChannelsMask[CHANNELS_MASK_SIZE];
|
||||
|
||||
/*!
|
||||
* LoRaMac channels remaining
|
||||
*/
|
||||
static uint16_t ChannelsMaskRemaining[CHANNELS_MASK_SIZE];
|
||||
|
||||
/*!
|
||||
* LoRaMac channels default mask
|
||||
*/
|
||||
static uint16_t ChannelsDefaultMask[CHANNELS_MASK_SIZE];
|
||||
|
||||
// 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( BandwidthsAU915[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 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 < AU915_MAX_NB_CHANNELS; i += 16, k++ )
|
||||
{
|
||||
for( uint8_t j = 0; j < 16; j++ )
|
||||
{
|
||||
if( ( channelsMask[k] & ( 1 << j ) ) != 0 )
|
||||
{
|
||||
if( channels[i + j].Frequency == 0 )
|
||||
{ // Check if the channel is enabled
|
||||
continue;
|
||||
}
|
||||
if( RegionCommonValueInRange( datarate, channels[i + j].DrRange.Fields.Min,
|
||||
channels[i + j].DrRange.Fields.Max ) == false )
|
||||
{ // Check if the current channel selection supports the given datarate
|
||||
continue;
|
||||
}
|
||||
if( bands[channels[i + j].Band].TimeOff > 0 )
|
||||
{ // Check if the band is available for transmission
|
||||
delayTransmission++;
|
||||
continue;
|
||||
}
|
||||
enabledChannels[nbEnabledChannels++] = i + j;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
*delayTx = delayTransmission;
|
||||
return nbEnabledChannels;
|
||||
}
|
||||
|
||||
PhyParam_t RegionAU915GetPhyParam( GetPhyParams_t* getPhy )
|
||||
{
|
||||
PhyParam_t phyParam = { 0 };
|
||||
|
||||
switch( getPhy->Attribute )
|
||||
{
|
||||
case PHY_MIN_RX_DR:
|
||||
{
|
||||
phyParam.Value = AU915_RX_MIN_DATARATE;
|
||||
break;
|
||||
}
|
||||
case PHY_MIN_TX_DR:
|
||||
{
|
||||
phyParam.Value = AU915_TX_MIN_DATARATE;
|
||||
break;
|
||||
}
|
||||
case PHY_DEF_TX_DR:
|
||||
{
|
||||
phyParam.Value = AU915_DEFAULT_DATARATE;
|
||||
break;
|
||||
}
|
||||
case PHY_NEXT_LOWER_TX_DR:
|
||||
{
|
||||
phyParam.Value = GetNextLowerTxDr( getPhy->Datarate, AU915_TX_MIN_DATARATE );
|
||||
break;
|
||||
}
|
||||
case PHY_DEF_TX_POWER:
|
||||
{
|
||||
phyParam.Value = AU915_DEFAULT_TX_POWER;
|
||||
break;
|
||||
}
|
||||
case PHY_MAX_PAYLOAD:
|
||||
{
|
||||
phyParam.Value = MaxPayloadOfDatarateAU915[getPhy->Datarate];
|
||||
break;
|
||||
}
|
||||
case PHY_MAX_PAYLOAD_REPEATER:
|
||||
{
|
||||
phyParam.Value = MaxPayloadOfDatarateRepeaterAU915[getPhy->Datarate];
|
||||
break;
|
||||
}
|
||||
case PHY_DUTY_CYCLE:
|
||||
{
|
||||
phyParam.Value = AU915_DUTY_CYCLE_ENABLED;
|
||||
break;
|
||||
}
|
||||
case PHY_MAX_RX_WINDOW:
|
||||
{
|
||||
phyParam.Value = AU915_MAX_RX_WINDOW;
|
||||
break;
|
||||
}
|
||||
case PHY_RECEIVE_DELAY1:
|
||||
{
|
||||
phyParam.Value = AU915_RECEIVE_DELAY1;
|
||||
break;
|
||||
}
|
||||
case PHY_RECEIVE_DELAY2:
|
||||
{
|
||||
phyParam.Value = AU915_RECEIVE_DELAY2;
|
||||
break;
|
||||
}
|
||||
case PHY_JOIN_ACCEPT_DELAY1:
|
||||
{
|
||||
phyParam.Value = AU915_JOIN_ACCEPT_DELAY1;
|
||||
break;
|
||||
}
|
||||
case PHY_JOIN_ACCEPT_DELAY2:
|
||||
{
|
||||
phyParam.Value = AU915_JOIN_ACCEPT_DELAY2;
|
||||
break;
|
||||
}
|
||||
case PHY_MAX_FCNT_GAP:
|
||||
{
|
||||
phyParam.Value = AU915_MAX_FCNT_GAP;
|
||||
break;
|
||||
}
|
||||
case PHY_ACK_TIMEOUT:
|
||||
{
|
||||
phyParam.Value = ( AU915_ACKTIMEOUT + randr( -AU915_ACK_TIMEOUT_RND, AU915_ACK_TIMEOUT_RND ) );
|
||||
break;
|
||||
}
|
||||
case PHY_DEF_DR1_OFFSET:
|
||||
{
|
||||
phyParam.Value = AU915_DEFAULT_RX1_DR_OFFSET;
|
||||
break;
|
||||
}
|
||||
case PHY_DEF_RX2_FREQUENCY:
|
||||
{
|
||||
phyParam.Value = AU915_RX_WND_2_FREQ;
|
||||
break;
|
||||
}
|
||||
case PHY_DEF_RX2_DR:
|
||||
{
|
||||
phyParam.Value = AU915_RX_WND_2_DR;
|
||||
break;
|
||||
}
|
||||
case PHY_CHANNELS_MASK:
|
||||
{
|
||||
phyParam.ChannelsMask = ChannelsMask;
|
||||
break;
|
||||
}
|
||||
case PHY_CHANNELS_DEFAULT_MASK:
|
||||
{
|
||||
phyParam.ChannelsMask = ChannelsDefaultMask;
|
||||
break;
|
||||
}
|
||||
case PHY_MAX_NB_CHANNELS:
|
||||
{
|
||||
phyParam.Value = AU915_MAX_NB_CHANNELS;
|
||||
break;
|
||||
}
|
||||
case PHY_CHANNELS:
|
||||
{
|
||||
phyParam.Channels = 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 = AU915_DEFAULT_MAX_EIRP;
|
||||
break;
|
||||
}
|
||||
case PHY_DEF_ANTENNA_GAIN:
|
||||
{
|
||||
phyParam.fValue = AU915_DEFAULT_ANTENNA_GAIN;
|
||||
break;
|
||||
}
|
||||
case PHY_NB_JOIN_TRIALS:
|
||||
case PHY_DEF_NB_JOIN_TRIALS:
|
||||
{
|
||||
phyParam.Value = 2;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return phyParam;
|
||||
}
|
||||
|
||||
void RegionAU915SetBandTxDone( SetBandTxDoneParams_t* txDone )
|
||||
{
|
||||
RegionCommonSetBandTxDone( txDone->Joined, &Bands[Channels[txDone->Channel].Band], txDone->LastTxDoneTime );
|
||||
}
|
||||
|
||||
void RegionAU915InitDefaults( InitType_t type )
|
||||
{
|
||||
switch( type )
|
||||
{
|
||||
case INIT_TYPE_INIT:
|
||||
{
|
||||
// Channels
|
||||
// 125 kHz channels
|
||||
for( uint8_t i = 0; i < AU915_MAX_NB_CHANNELS - 8; i++ )
|
||||
{
|
||||
Channels[i].Frequency = 915200000 + i * 200000;
|
||||
Channels[i].DrRange.Value = ( DR_5 << 4 ) | DR_0;
|
||||
Channels[i].Band = 0;
|
||||
}
|
||||
// 500 kHz channels
|
||||
for( uint8_t i = AU915_MAX_NB_CHANNELS - 8; i < AU915_MAX_NB_CHANNELS; i++ )
|
||||
{
|
||||
Channels[i].Frequency = 915900000 + ( i - ( AU915_MAX_NB_CHANNELS - 8 ) ) * 1600000;
|
||||
Channels[i].DrRange.Value = ( DR_6 << 4 ) | DR_6;
|
||||
Channels[i].Band = 0;
|
||||
}
|
||||
|
||||
// Initialize channels default mask
|
||||
ChannelsDefaultMask[0] = 0xFFFF;
|
||||
ChannelsDefaultMask[1] = 0xFFFF;
|
||||
ChannelsDefaultMask[2] = 0xFFFF;
|
||||
ChannelsDefaultMask[3] = 0xFFFF;
|
||||
ChannelsDefaultMask[4] = 0x00FF;
|
||||
ChannelsDefaultMask[5] = 0x0000;
|
||||
|
||||
// Copy channels default mask
|
||||
RegionCommonChanMaskCopy( ChannelsMask, ChannelsDefaultMask, 6 );
|
||||
|
||||
// Copy into channels mask remaining
|
||||
RegionCommonChanMaskCopy( ChannelsMaskRemaining, ChannelsMask, 6 );
|
||||
break;
|
||||
}
|
||||
case INIT_TYPE_RESTORE:
|
||||
{
|
||||
// Copy channels default mask
|
||||
RegionCommonChanMaskCopy( ChannelsMask, ChannelsDefaultMask, 6 );
|
||||
|
||||
for( uint8_t i = 0; i < 6; i++ )
|
||||
{ // Copy-And the channels mask
|
||||
ChannelsMaskRemaining[i] &= ChannelsMask[i];
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool RegionAU915Verify( VerifyParams_t* verify, PhyAttribute_t phyAttribute )
|
||||
{
|
||||
switch( phyAttribute )
|
||||
{
|
||||
case PHY_TX_DR:
|
||||
case PHY_DEF_TX_DR:
|
||||
{
|
||||
return RegionCommonValueInRange( verify->DatarateParams.Datarate, AU915_TX_MIN_DATARATE, AU915_TX_MAX_DATARATE );
|
||||
}
|
||||
case PHY_RX_DR:
|
||||
{
|
||||
return RegionCommonValueInRange( verify->DatarateParams.Datarate, AU915_RX_MIN_DATARATE, AU915_RX_MAX_DATARATE );
|
||||
}
|
||||
case PHY_DEF_TX_POWER:
|
||||
case PHY_TX_POWER:
|
||||
{
|
||||
// Remark: switched min and max!
|
||||
return RegionCommonValueInRange( verify->TxPower, AU915_MAX_TX_POWER, AU915_MIN_TX_POWER );
|
||||
}
|
||||
case PHY_DUTY_CYCLE:
|
||||
{
|
||||
return AU915_DUTY_CYCLE_ENABLED;
|
||||
}
|
||||
case PHY_NB_JOIN_TRIALS:
|
||||
{
|
||||
if( verify->NbJoinTrials < 2 )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void RegionAU915ApplyCFList( ApplyCFListParams_t* applyCFList )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
bool RegionAU915ChanMaskSet( ChanMaskSetParams_t* chanMaskSet )
|
||||
{
|
||||
uint8_t nbChannels = RegionCommonCountChannels( chanMaskSet->ChannelsMaskIn, 0, 4 );
|
||||
|
||||
// Check the number of active channels
|
||||
// According to ACMA regulation, we require at least 20 125KHz channels, if
|
||||
// the node shall utilize 125KHz channels.
|
||||
if( ( nbChannels < 20 ) &&
|
||||
( nbChannels > 0 ) )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
switch( chanMaskSet->ChannelsMaskType )
|
||||
{
|
||||
case CHANNELS_MASK:
|
||||
{
|
||||
RegionCommonChanMaskCopy( ChannelsMask, chanMaskSet->ChannelsMaskIn, 6 );
|
||||
|
||||
for( uint8_t i = 0; i < 6; i++ )
|
||||
{ // Copy-And the channels mask
|
||||
ChannelsMaskRemaining[i] &= ChannelsMask[i];
|
||||
}
|
||||
break;
|
||||
}
|
||||
case CHANNELS_DEFAULT_MASK:
|
||||
{
|
||||
RegionCommonChanMaskCopy( ChannelsDefaultMask, chanMaskSet->ChannelsMaskIn, 6 );
|
||||
break;
|
||||
}
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool RegionAU915AdrNext( AdrNextParams_t* adrNext, int8_t* drOut, int8_t* txPowOut, uint32_t* adrAckCounter )
|
||||
{
|
||||
bool adrAckReq = false;
|
||||
int8_t datarate = adrNext->Datarate;
|
||||
int8_t txPower = adrNext->TxPower;
|
||||
GetPhyParams_t getPhy;
|
||||
PhyParam_t phyParam;
|
||||
|
||||
// Report back the adr ack counter
|
||||
*adrAckCounter = adrNext->AdrAckCounter;
|
||||
|
||||
if( adrNext->AdrEnabled == true )
|
||||
{
|
||||
if( datarate == AU915_TX_MIN_DATARATE )
|
||||
{
|
||||
*adrAckCounter = 0;
|
||||
adrAckReq = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
if( adrNext->AdrAckCounter >= AU915_ADR_ACK_LIMIT )
|
||||
{
|
||||
adrAckReq = true;
|
||||
txPower = AU915_MAX_TX_POWER;
|
||||
}
|
||||
else
|
||||
{
|
||||
adrAckReq = false;
|
||||
}
|
||||
if( adrNext->AdrAckCounter >= ( AU915_ADR_ACK_LIMIT + AU915_ADR_ACK_DELAY ) )
|
||||
{
|
||||
if( ( adrNext->AdrAckCounter % AU915_ADR_ACK_DELAY ) == 1 )
|
||||
{
|
||||
// Decrease the datarate
|
||||
getPhy.Attribute = PHY_NEXT_LOWER_TX_DR;
|
||||
getPhy.Datarate = datarate;
|
||||
getPhy.UplinkDwellTime = adrNext->UplinkDwellTime;
|
||||
phyParam = RegionAU915GetPhyParam( &getPhy );
|
||||
datarate = phyParam.Value;
|
||||
|
||||
if( datarate == AU915_TX_MIN_DATARATE )
|
||||
{
|
||||
// We must set adrAckReq to false as soon as we reach the lowest datarate
|
||||
adrAckReq = false;
|
||||
if( adrNext->UpdateChanMask == true )
|
||||
{
|
||||
// Re-enable default channels
|
||||
ChannelsMask[0] = 0xFFFF;
|
||||
ChannelsMask[1] = 0xFFFF;
|
||||
ChannelsMask[2] = 0xFFFF;
|
||||
ChannelsMask[3] = 0xFFFF;
|
||||
ChannelsMask[4] = 0x00FF;
|
||||
ChannelsMask[5] = 0x0000;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
*drOut = datarate;
|
||||
*txPowOut = txPower;
|
||||
return adrAckReq;
|
||||
}
|
||||
|
||||
void RegionAU915ComputeRxWindowParameters( int8_t datarate, uint8_t minRxSymbols, uint32_t rxError, RxConfigParams_t *rxConfigParams )
|
||||
{
|
||||
double tSymbol = 0.0;
|
||||
uint32_t radioWakeUpTime;
|
||||
|
||||
rxConfigParams->Datarate = datarate;
|
||||
rxConfigParams->Bandwidth = GetBandwidth( datarate );
|
||||
|
||||
if( datarate == DR_7 )
|
||||
{ // FSK
|
||||
tSymbol = RegionCommonComputeSymbolTimeFsk( DataratesAU915[datarate] );
|
||||
}
|
||||
else
|
||||
{ // LoRa
|
||||
tSymbol = RegionCommonComputeSymbolTimeLoRa( DataratesAU915[datarate], BandwidthsAU915[datarate] );
|
||||
}
|
||||
|
||||
radioWakeUpTime = Radio.GetRadioWakeUpTime( );
|
||||
RegionCommonComputeRxWindowParameters( tSymbol, minRxSymbols, rxError, radioWakeUpTime, &rxConfigParams->WindowTimeout, &rxConfigParams->WindowOffset );
|
||||
}
|
||||
|
||||
bool RegionAU915RxConfig( RxConfigParams_t* rxConfig, int8_t* datarate )
|
||||
{
|
||||
int8_t dr = rxConfig->Datarate;
|
||||
uint8_t maxPayload = 0;
|
||||
int8_t phyDr = 0;
|
||||
uint32_t frequency = rxConfig->Frequency;
|
||||
|
||||
if( Radio.GetStatus( ) != RF_IDLE )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if( rxConfig->Window == 0 )
|
||||
{
|
||||
// Apply window 1 frequency
|
||||
frequency = AU915_FIRST_RX1_CHANNEL + ( rxConfig->Channel % 8 ) * AU915_STEPWIDTH_RX1_CHANNEL;
|
||||
}
|
||||
|
||||
// Read the physical datarate from the datarates table
|
||||
phyDr = DataratesAU915[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 = MaxPayloadOfDatarateRepeaterAU915[dr];
|
||||
}
|
||||
else
|
||||
{
|
||||
maxPayload = MaxPayloadOfDatarateAU915[dr];
|
||||
}
|
||||
Radio.SetMaxPayloadLength( MODEM_LORA, maxPayload + LORA_MAC_FRMPAYLOAD_OVERHEAD );
|
||||
DBG_PRINTF("RX on freq %d Hz at DR %d\n\r", frequency, dr);
|
||||
|
||||
*datarate = (uint8_t) dr;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool RegionAU915TxConfig( TxConfigParams_t* txConfig, int8_t* txPower, TimerTime_t* txTimeOnAir )
|
||||
{
|
||||
int8_t phyDr = DataratesAU915[txConfig->Datarate];
|
||||
int8_t txPowerLimited = LimitTxPower( txConfig->TxPower, Bands[Channels[txConfig->Channel].Band].TxMaxPower, txConfig->Datarate, ChannelsMask );
|
||||
uint32_t bandwidth = GetBandwidth( txConfig->Datarate );
|
||||
int8_t phyTxPower = 0;
|
||||
|
||||
// Calculate physical TX power
|
||||
phyTxPower = RegionCommonComputeTxPower( txPowerLimited, txConfig->MaxEirp, txConfig->AntennaGain );
|
||||
|
||||
Radio.SetChannel( Channels[txConfig->Channel].Frequency );
|
||||
|
||||
Radio.SetMaxPayloadLength( MODEM_LORA, txConfig->PktLen );
|
||||
Radio.SetTxConfig( MODEM_LORA, phyTxPower, 0, bandwidth, phyDr, 1, 8, false, true, 0, 0, false, 3e3 );
|
||||
DBG_PRINTF("TX on freq %d Hz at DR %d\n\r", Channels[txConfig->Channel].Frequency, txConfig->Datarate);
|
||||
|
||||
*txTimeOnAir = Radio.TimeOnAir( MODEM_LORA, txConfig->PktLen );
|
||||
*txPower = txPowerLimited;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
uint8_t RegionAU915LinkAdrReq( LinkAdrReqParams_t* linkAdrReq, int8_t* drOut, int8_t* txPowOut, uint8_t* nbRepOut, uint8_t* nbBytesParsed )
|
||||
{
|
||||
uint8_t status = 0x07;
|
||||
LinkAdrParams_t linkAdrParams;
|
||||
uint8_t nextIndex = 0;
|
||||
uint8_t bytesProcessed = 0;
|
||||
uint16_t channelsMask[6] = { 0, 0, 0, 0, 0, 0 };
|
||||
|
||||
// Initialize local copy of channels mask
|
||||
RegionCommonChanMaskCopy( channelsMask, ChannelsMask, 6 );
|
||||
|
||||
while( bytesProcessed < linkAdrReq->PayloadSize )
|
||||
{
|
||||
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;
|
||||
// Apply chMask to channels 64 to 71
|
||||
channelsMask[4] = linkAdrParams.ChMask;
|
||||
}
|
||||
else if( linkAdrParams.ChMaskCtrl == 7 )
|
||||
{
|
||||
// Disable all 125 kHz channels
|
||||
channelsMask[0] = 0x0000;
|
||||
channelsMask[1] = 0x0000;
|
||||
channelsMask[2] = 0x0000;
|
||||
channelsMask[3] = 0x0000;
|
||||
// Apply chMask to channels 64 to 71
|
||||
channelsMask[4] = linkAdrParams.ChMask;
|
||||
}
|
||||
else if( linkAdrParams.ChMaskCtrl == 5 )
|
||||
{
|
||||
// RFU
|
||||
status &= 0xFE; // Channel mask KO
|
||||
}
|
||||
else
|
||||
{
|
||||
channelsMask[linkAdrParams.ChMaskCtrl] = linkAdrParams.ChMask;
|
||||
}
|
||||
}
|
||||
|
||||
// FCC 15.247 paragraph F mandates to hop on at least 2 125 kHz channels
|
||||
if( ( linkAdrParams.Datarate < DR_4 ) && ( RegionCommonCountChannels( channelsMask, 0, 4 ) < 2 ) )
|
||||
{
|
||||
status &= 0xFE; // Channel mask KO
|
||||
}
|
||||
|
||||
// Verify datarate
|
||||
if( RegionCommonChanVerifyDr( AU915_MAX_NB_CHANNELS, channelsMask, linkAdrParams.Datarate, AU915_TX_MIN_DATARATE, AU915_TX_MAX_DATARATE, Channels ) == false )
|
||||
{
|
||||
status &= 0xFD; // Datarate KO
|
||||
}
|
||||
|
||||
// Verify tx power
|
||||
if( RegionCommonValueInRange( linkAdrParams.TxPower, AU915_MAX_TX_POWER, AU915_MIN_TX_POWER ) == 0 )
|
||||
{
|
||||
// Verify if the maximum TX power is exceeded
|
||||
if( AU915_MAX_TX_POWER > linkAdrParams.TxPower )
|
||||
{ // Apply maximum TX power. Accept TX power.
|
||||
linkAdrParams.TxPower = AU915_MAX_TX_POWER;
|
||||
}
|
||||
else
|
||||
{
|
||||
status &= 0xFB; // TxPower KO
|
||||
}
|
||||
}
|
||||
|
||||
// Update channelsMask if everything is correct
|
||||
if( status == 0x07 )
|
||||
{
|
||||
if( linkAdrParams.NbRep == 0 )
|
||||
{ // Value of 0 is not allowed, revert to default.
|
||||
linkAdrParams.NbRep = 1;
|
||||
}
|
||||
|
||||
// Copy Mask
|
||||
RegionCommonChanMaskCopy( ChannelsMask, channelsMask, 6 );
|
||||
|
||||
ChannelsMaskRemaining[0] &= ChannelsMask[0];
|
||||
ChannelsMaskRemaining[1] &= ChannelsMask[1];
|
||||
ChannelsMaskRemaining[2] &= ChannelsMask[2];
|
||||
ChannelsMaskRemaining[3] &= ChannelsMask[3];
|
||||
ChannelsMaskRemaining[4] = ChannelsMask[4];
|
||||
ChannelsMaskRemaining[5] = ChannelsMask[5];
|
||||
}
|
||||
|
||||
// Update status variables
|
||||
*drOut = linkAdrParams.Datarate;
|
||||
*txPowOut = linkAdrParams.TxPower;
|
||||
*nbRepOut = linkAdrParams.NbRep;
|
||||
*nbBytesParsed = bytesProcessed;
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
uint8_t RegionAU915RxParamSetupReq( RxParamSetupReqParams_t* rxParamSetupReq )
|
||||
{
|
||||
uint8_t status = 0x07;
|
||||
uint32_t freq = rxParamSetupReq->Frequency;
|
||||
|
||||
// Verify radio frequency
|
||||
if( ( Radio.CheckRfFrequency( freq ) == false ) ||
|
||||
( freq < AU915_FIRST_RX1_CHANNEL ) ||
|
||||
( freq > AU915_LAST_RX1_CHANNEL ) ||
|
||||
( ( ( freq - ( uint32_t ) AU915_FIRST_RX1_CHANNEL ) % ( uint32_t ) AU915_STEPWIDTH_RX1_CHANNEL ) != 0 ) )
|
||||
{
|
||||
status &= 0xFE; // Channel frequency KO
|
||||
}
|
||||
|
||||
// Verify datarate
|
||||
if( RegionCommonValueInRange( rxParamSetupReq->Datarate, AU915_RX_MIN_DATARATE, AU915_RX_MAX_DATARATE ) == false )
|
||||
{
|
||||
status &= 0xFD; // Datarate KO
|
||||
}
|
||||
if( ( RegionCommonValueInRange( rxParamSetupReq->Datarate, DR_5, DR_7 ) == true ) ||
|
||||
( rxParamSetupReq->Datarate > DR_13 ) )
|
||||
{
|
||||
status &= 0xFD; // Datarate KO
|
||||
}
|
||||
|
||||
// Verify datarate offset
|
||||
if( RegionCommonValueInRange( rxParamSetupReq->DrOffset, AU915_MIN_RX1_DR_OFFSET, AU915_MAX_RX1_DR_OFFSET ) == false )
|
||||
{
|
||||
status &= 0xFB; // Rx1DrOffset range KO
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
uint8_t RegionAU915NewChannelReq( NewChannelReqParams_t* newChannelReq )
|
||||
{
|
||||
// Datarate and frequency KO
|
||||
return 0;
|
||||
}
|
||||
|
||||
int8_t RegionAU915TxParamSetupReq( TxParamSetupReqParams_t* txParamSetupReq )
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
uint8_t RegionAU915DlChannelReq( DlChannelReqParams_t* dlChannelReq )
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
int8_t RegionAU915AlternateDr( AlternateDrParams_t* alternateDr )
|
||||
{
|
||||
int8_t datarate = 0;
|
||||
|
||||
// Re-enable 500 kHz default channels
|
||||
ChannelsMask[4] = 0x00FF;
|
||||
|
||||
if( ( alternateDr->NbTrials & 0x01 ) == 0x01 )
|
||||
{
|
||||
datarate = DR_4;
|
||||
}
|
||||
else
|
||||
{
|
||||
datarate = DR_0;
|
||||
}
|
||||
return datarate;
|
||||
}
|
||||
|
||||
void RegionAU915CalcBackOff( CalcBackOffParams_t* calcBackOff )
|
||||
{
|
||||
uint8_t channel = calcBackOff->Channel;
|
||||
uint16_t joinDutyCycle = 0;
|
||||
|
||||
if( calcBackOff->Joined == false )
|
||||
{
|
||||
// Get the join duty cycle
|
||||
joinDutyCycle = RegionCommonGetJoinDc( calcBackOff->ElapsedTime );
|
||||
// Apply band time-off.
|
||||
Bands[Channels[channel].Band].TimeOff = calcBackOff->TxTimeOnAir * joinDutyCycle - calcBackOff->TxTimeOnAir;
|
||||
}
|
||||
else
|
||||
{
|
||||
Bands[Channels[channel].Band].TimeOff = 0;
|
||||
}
|
||||
}
|
||||
|
||||
bool RegionAU915NextChannel( NextChanParams_t* nextChanParams, uint8_t* channel, TimerTime_t* time, TimerTime_t* aggregatedTimeOff )
|
||||
{
|
||||
uint8_t nbEnabledChannels = 0;
|
||||
uint8_t delayTx = 0;
|
||||
uint8_t enabledChannels[AU915_MAX_NB_CHANNELS] = { 0 };
|
||||
TimerTime_t nextTxDelay = 0;
|
||||
|
||||
// Count 125kHz channels
|
||||
if( RegionCommonCountChannels( ChannelsMaskRemaining, 0, 4 ) == 0 )
|
||||
{ // Reactivate default channels
|
||||
RegionCommonChanMaskCopy( ChannelsMaskRemaining, ChannelsMask, 4 );
|
||||
}
|
||||
// Check other channels
|
||||
if( nextChanParams->Datarate >= DR_4 )
|
||||
{
|
||||
if( ( ChannelsMaskRemaining[4] & 0x00FF ) == 0 )
|
||||
{
|
||||
ChannelsMaskRemaining[4] = ChannelsMask[4];
|
||||
}
|
||||
}
|
||||
|
||||
if( nextChanParams->AggrTimeOff <= TimerGetElapsedTime( nextChanParams->LastAggrTx ) )
|
||||
{
|
||||
// Reset Aggregated time off
|
||||
*aggregatedTimeOff = 0;
|
||||
|
||||
// Search how many channels are enabled
|
||||
nbEnabledChannels = CountNbOfEnabledChannels( nextChanParams->Datarate,
|
||||
ChannelsMaskRemaining, Channels,
|
||||
Bands, enabledChannels, &delayTx );
|
||||
}
|
||||
else
|
||||
{
|
||||
delayTx++;
|
||||
nextTxDelay = nextChanParams->AggrTimeOff - TimerGetElapsedTime( nextChanParams->LastAggrTx );
|
||||
}
|
||||
|
||||
if( nbEnabledChannels > 0 )
|
||||
{
|
||||
// We found a valid channel
|
||||
*channel = enabledChannels[randr( 0, nbEnabledChannels - 1 )];
|
||||
// Disable the channel in the mask
|
||||
RegionCommonChanDisable( ChannelsMaskRemaining, *channel, AU915_MAX_NB_CHANNELS - 8 );
|
||||
|
||||
*time = 0;
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
if( delayTx > 0 )
|
||||
{
|
||||
// Delay transmission due to AggregatedTimeOff or to a band time off
|
||||
*time = nextTxDelay;
|
||||
return true;
|
||||
}
|
||||
// Datarate not supported by any channel
|
||||
*time = 0;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
LoRaMacStatus_t RegionAU915ChannelAdd( ChannelAddParams_t* channelAdd )
|
||||
{
|
||||
return LORAMAC_STATUS_PARAMETER_INVALID;
|
||||
}
|
||||
|
||||
bool RegionAU915ChannelsRemove( ChannelRemoveParams_t* channelRemove )
|
||||
{
|
||||
return LORAMAC_STATUS_PARAMETER_INVALID;
|
||||
}
|
||||
|
||||
void RegionAU915SetContinuousWave( ContinuousWaveParams_t* continuousWave )
|
||||
{
|
||||
int8_t txPowerLimited = LimitTxPower( continuousWave->TxPower, Bands[Channels[continuousWave->Channel].Band].TxMaxPower, continuousWave->Datarate, ChannelsMask );
|
||||
int8_t phyTxPower = 0;
|
||||
uint32_t frequency = Channels[continuousWave->Channel].Frequency;
|
||||
|
||||
// Calculate physical TX power
|
||||
phyTxPower = RegionCommonComputeTxPower( txPowerLimited, continuousWave->MaxEirp, continuousWave->AntennaGain );
|
||||
|
||||
Radio.SetTxContinuousWave( frequency, phyTxPower, continuousWave->Timeout );
|
||||
}
|
||||
|
||||
uint8_t RegionAU915ApplyDrOffset( uint8_t downlinkDwellTime, int8_t dr, int8_t drOffset )
|
||||
{
|
||||
int8_t datarate = DatarateOffsetsAU915[dr][drOffset];
|
||||
|
||||
if( datarate < 0 )
|
||||
{
|
||||
datarate = DR_0;
|
||||
}
|
||||
return datarate;
|
||||
}
|
||||
|
|
@ -0,0 +1,459 @@
|
|||
/*
|
||||
* Copyright (C) 2015-2017 Alibaba Group Holding Limited
|
||||
*/
|
||||
|
||||
/*!
|
||||
* \file RegionAU915.h
|
||||
*
|
||||
* \brief Region definition for AU915
|
||||
*
|
||||
* \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 REGIONAU915 Region AU915
|
||||
* Implementation according to LoRaWAN Specification v1.0.2.
|
||||
* \{
|
||||
*/
|
||||
#ifndef __REGION_AU915_H__
|
||||
#define __REGION_AU915_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_6
|
||||
|
||||
/*!
|
||||
* 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_0
|
||||
|
||||
/*!
|
||||
* 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_10
|
||||
|
||||
/*!
|
||||
* 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 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
|
||||
|
||||
/*!
|
||||
* LoRaMac maximum number of bands
|
||||
*/
|
||||
#define AU915_MAX_NB_BANDS 1
|
||||
|
||||
/*!
|
||||
* Band 0 definition
|
||||
* { DutyCycle, TxMaxPower, LastTxDoneTime, TimeOff }
|
||||
*/
|
||||
#define AU915_BAND0 { 1, AU915_MAX_TX_POWER, 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.
|
||||
*/
|
||||
static const uint8_t MaxPayloadOfDatarateAU915[] = { 51, 51, 51, 115, 242, 242, 242, 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 MaxPayloadOfDatarateRepeaterAU915[] = { 51, 51, 51, 115, 222, 222, 222, 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 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( InitType_t type );
|
||||
|
||||
/*!
|
||||
* \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 );
|
||||
|
||||
/*!
|
||||
* \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 RegionAU915AdrNext( AdrNextParams_t* adrNext, int8_t* drOut, int8_t* txPowOut, uint32_t* adrAckCounter );
|
||||
|
||||
/*!
|
||||
* 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] alternateDr Pointer to the function parameters.
|
||||
*
|
||||
* \retval Datarate to apply.
|
||||
*/
|
||||
int8_t RegionAU915AlternateDr( AlternateDrParams_t* alternateDr );
|
||||
|
||||
/*!
|
||||
* \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]
|
||||
*/
|
||||
bool 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 );
|
||||
|
||||
/*! \} defgroup REGIONAU915 */
|
||||
|
||||
#endif // __REGION_AU915_H__
|
||||
|
|
@ -0,0 +1,816 @@
|
|||
/*
|
||||
* Copyright (C) 2015-2017 Alibaba Group Holding Limited
|
||||
*/
|
||||
|
||||
/*
|
||||
/ _____) _ | |
|
||||
( (____ _____ ____ _| |_ _____ ____| |__
|
||||
\____ \| ___ | (_ _) ___ |/ ___) _ \
|
||||
_____) ) ____| | | || |_| ____( (___| | | |
|
||||
(______/|_____)_|_|_| \__)_____)\____)_| |_|
|
||||
(C)2013 Semtech
|
||||
___ _____ _ ___ _ _____ ___ ___ ___ ___
|
||||
/ __|_ _/_\ / __| |/ / __/ _ \| _ \/ __| __|
|
||||
\__ \ | |/ _ \ (__| ' <| _| (_) | / (__| _|
|
||||
|___/ |_/_/ \_\___|_|\_\_| \___/|_|_\\___|___|
|
||||
embedded.connectivity.solutions===============
|
||||
|
||||
Description: LoRa MAC region CN470 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 <stdbool.h>
|
||||
#include <string.h>
|
||||
#include <stdint.h>
|
||||
#include <math.h>
|
||||
|
||||
#include "radio.h"
|
||||
//#include "timer.h"
|
||||
#include "timeServer.h"
|
||||
#include "LoRaMac.h"
|
||||
|
||||
#include "utilities.h"
|
||||
|
||||
#include "Region.h"
|
||||
#include "RegionCommon.h"
|
||||
#include "RegionCN470.h"
|
||||
#include "debug.h"
|
||||
|
||||
// Definitions
|
||||
#define CHANNELS_MASK_SIZE 6
|
||||
|
||||
// Global attributes
|
||||
/*!
|
||||
* LoRaMAC channels
|
||||
*/
|
||||
static ChannelParams_t Channels[CN470_MAX_NB_CHANNELS];
|
||||
|
||||
/*!
|
||||
* LoRaMac bands
|
||||
*/
|
||||
static Band_t Bands[CN470_MAX_NB_BANDS] =
|
||||
{
|
||||
CN470_BAND0
|
||||
};
|
||||
|
||||
/*!
|
||||
* LoRaMac channels mask
|
||||
*/
|
||||
static uint16_t ChannelsMask[CHANNELS_MASK_SIZE];
|
||||
|
||||
/*!
|
||||
* LoRaMac channels default mask
|
||||
*/
|
||||
static uint16_t ChannelsDefaultMask[CHANNELS_MASK_SIZE];
|
||||
|
||||
// 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 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_DEF_TX_POWER:
|
||||
{
|
||||
phyParam.Value = CN470_DEFAULT_TX_POWER;
|
||||
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 = ChannelsMask;
|
||||
break;
|
||||
}
|
||||
case PHY_CHANNELS_DEFAULT_MASK:
|
||||
{
|
||||
phyParam.ChannelsMask = ChannelsDefaultMask;
|
||||
break;
|
||||
}
|
||||
case PHY_MAX_NB_CHANNELS:
|
||||
{
|
||||
phyParam.Value = CN470_MAX_NB_CHANNELS;
|
||||
break;
|
||||
}
|
||||
case PHY_CHANNELS:
|
||||
{
|
||||
phyParam.Channels = 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_NB_JOIN_TRIALS:
|
||||
case PHY_DEF_NB_JOIN_TRIALS:
|
||||
{
|
||||
phyParam.Value = 48;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return phyParam;
|
||||
}
|
||||
|
||||
void RegionCN470SetBandTxDone( SetBandTxDoneParams_t* txDone )
|
||||
{
|
||||
RegionCommonSetBandTxDone( txDone->Joined, &Bands[Channels[txDone->Channel].Band], txDone->LastTxDoneTime );
|
||||
}
|
||||
|
||||
void RegionCN470InitDefaults( InitType_t type )
|
||||
{
|
||||
switch( type )
|
||||
{
|
||||
case INIT_TYPE_INIT:
|
||||
{
|
||||
// Channels
|
||||
// 125 kHz channels
|
||||
for( uint8_t i = 0; i < CN470_MAX_NB_CHANNELS; i++ )
|
||||
{
|
||||
Channels[i].Frequency = 470300000 + i * 200000;
|
||||
Channels[i].DrRange.Value = ( DR_5 << 4 ) | DR_0;
|
||||
Channels[i].Band = 0;
|
||||
}
|
||||
|
||||
// Initialize the channels default mask
|
||||
ChannelsDefaultMask[0] = 0xFFFF;
|
||||
ChannelsDefaultMask[1] = 0xFFFF;
|
||||
ChannelsDefaultMask[2] = 0xFFFF;
|
||||
ChannelsDefaultMask[3] = 0xFFFF;
|
||||
ChannelsDefaultMask[4] = 0xFFFF;
|
||||
ChannelsDefaultMask[5] = 0xFFFF;
|
||||
|
||||
// Update the channels mask
|
||||
RegionCommonChanMaskCopy( ChannelsMask, ChannelsDefaultMask, 6 );
|
||||
break;
|
||||
}
|
||||
case INIT_TYPE_RESTORE:
|
||||
{
|
||||
// Restore channels default mask
|
||||
RegionCommonChanMaskCopy( ChannelsMask, ChannelsDefaultMask, 6 );
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool RegionCN470Verify( VerifyParams_t* verify, PhyAttribute_t phyAttribute )
|
||||
{
|
||||
switch( phyAttribute )
|
||||
{
|
||||
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;
|
||||
}
|
||||
case PHY_NB_JOIN_TRIALS:
|
||||
{
|
||||
if( verify->NbJoinTrials < 48 )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void RegionCN470ApplyCFList( ApplyCFListParams_t* applyCFList )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
bool RegionCN470ChanMaskSet( ChanMaskSetParams_t* chanMaskSet )
|
||||
{
|
||||
switch( chanMaskSet->ChannelsMaskType )
|
||||
{
|
||||
case CHANNELS_MASK:
|
||||
{
|
||||
RegionCommonChanMaskCopy( ChannelsMask, chanMaskSet->ChannelsMaskIn, 6 );
|
||||
break;
|
||||
}
|
||||
case CHANNELS_DEFAULT_MASK:
|
||||
{
|
||||
RegionCommonChanMaskCopy( ChannelsDefaultMask, chanMaskSet->ChannelsMaskIn, 6 );
|
||||
break;
|
||||
}
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool RegionCN470AdrNext( AdrNextParams_t* adrNext, int8_t* drOut, int8_t* txPowOut, uint32_t* adrAckCounter )
|
||||
{
|
||||
bool adrAckReq = false;
|
||||
int8_t datarate = adrNext->Datarate;
|
||||
int8_t txPower = adrNext->TxPower;
|
||||
GetPhyParams_t getPhy;
|
||||
PhyParam_t phyParam;
|
||||
|
||||
// Report back the adr ack counter
|
||||
*adrAckCounter = adrNext->AdrAckCounter;
|
||||
|
||||
if( adrNext->AdrEnabled == true )
|
||||
{
|
||||
if( datarate == CN470_TX_MIN_DATARATE )
|
||||
{
|
||||
*adrAckCounter = 0;
|
||||
adrAckReq = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
if( adrNext->AdrAckCounter >= CN470_ADR_ACK_LIMIT )
|
||||
{
|
||||
adrAckReq = true;
|
||||
txPower = CN470_MAX_TX_POWER;
|
||||
}
|
||||
else
|
||||
{
|
||||
adrAckReq = false;
|
||||
}
|
||||
if( adrNext->AdrAckCounter >= ( CN470_ADR_ACK_LIMIT + CN470_ADR_ACK_DELAY ) )
|
||||
{
|
||||
if( ( adrNext->AdrAckCounter % CN470_ADR_ACK_DELAY ) == 1 )
|
||||
{
|
||||
// Decrease the datarate
|
||||
getPhy.Attribute = PHY_NEXT_LOWER_TX_DR;
|
||||
getPhy.Datarate = datarate;
|
||||
getPhy.UplinkDwellTime = adrNext->UplinkDwellTime;
|
||||
phyParam = RegionCN470GetPhyParam( &getPhy );
|
||||
datarate = phyParam.Value;
|
||||
|
||||
if( datarate == CN470_TX_MIN_DATARATE )
|
||||
{
|
||||
// We must set adrAckReq to false as soon as we reach the lowest datarate
|
||||
adrAckReq = false;
|
||||
if( adrNext->UpdateChanMask == true )
|
||||
{
|
||||
// Re-enable default channels
|
||||
ChannelsMask[0] = 0xFFFF;
|
||||
ChannelsMask[1] = 0xFFFF;
|
||||
ChannelsMask[2] = 0xFFFF;
|
||||
ChannelsMask[3] = 0xFFFF;
|
||||
ChannelsMask[4] = 0xFFFF;
|
||||
ChannelsMask[5] = 0xFFFF;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
*drOut = datarate;
|
||||
*txPowOut = txPower;
|
||||
return adrAckReq;
|
||||
}
|
||||
|
||||
void RegionCN470ComputeRxWindowParameters( int8_t datarate, uint8_t minRxSymbols, uint32_t rxError, RxConfigParams_t *rxConfigParams )
|
||||
{
|
||||
double tSymbol = 0.0;
|
||||
uint32_t radioWakeUpTime;
|
||||
|
||||
rxConfigParams->Datarate = datarate;
|
||||
rxConfigParams->Bandwidth = GetBandwidth( datarate );
|
||||
|
||||
tSymbol = RegionCommonComputeSymbolTimeLoRa( DataratesCN470[datarate], BandwidthsCN470[datarate] );
|
||||
|
||||
radioWakeUpTime = Radio.GetRadioWakeUpTime( );
|
||||
RegionCommonComputeRxWindowParameters( tSymbol, minRxSymbols, rxError, radioWakeUpTime, &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;
|
||||
|
||||
if( Radio.GetStatus( ) != RF_IDLE )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if( rxConfig->Window == 0 )
|
||||
{
|
||||
// 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 );
|
||||
|
||||
*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, Bands[Channels[txConfig->Channel].Band].TxMaxPower, txConfig->Datarate, ChannelsMask );
|
||||
int8_t phyTxPower = 0;
|
||||
|
||||
// Calculate physical TX power
|
||||
phyTxPower = RegionCommonComputeTxPower( txPowerLimited, txConfig->MaxEirp, txConfig->AntennaGain );
|
||||
|
||||
// Setup the radio frequency
|
||||
Radio.SetChannel( Channels[txConfig->Channel].Frequency );
|
||||
|
||||
Radio.SetTxConfig( MODEM_LORA, phyTxPower, 0, 0, phyDr, 1, 8, false, true, 0, 0, false, 3000 );
|
||||
// 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 = txConfig->TxPower;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
uint8_t RegionCN470LinkAdrReq( LinkAdrReqParams_t* linkAdrReq, int8_t* drOut, int8_t* txPowOut, uint8_t* nbRepOut, uint8_t* nbBytesParsed )
|
||||
{
|
||||
uint8_t status = 0x07;
|
||||
LinkAdrParams_t linkAdrParams;
|
||||
uint8_t nextIndex = 0;
|
||||
uint8_t bytesProcessed = 0;
|
||||
uint16_t channelsMask[6] = { 0, 0, 0, 0, 0, 0 };
|
||||
|
||||
// Initialize local copy of channels mask
|
||||
RegionCommonChanMaskCopy( channelsMask, 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 <CN470_MAX_NB_CHANNELS; i++ ) //perry 2017/7/24
|
||||
//for( uint8_t i = 0; i < 16; i++ )
|
||||
{
|
||||
if( ( ( linkAdrParams.ChMask & ( 1 << i ) ) != 0 ) &&
|
||||
( Channels[linkAdrParams.ChMaskCtrl * 16 + i].Frequency == 0 ) )
|
||||
{// Trying to enable an undefined channel
|
||||
status &= 0xFE; // Channel mask KO
|
||||
}
|
||||
}
|
||||
channelsMask[linkAdrParams.ChMaskCtrl] = linkAdrParams.ChMask;
|
||||
}
|
||||
}
|
||||
|
||||
// Verify datarate
|
||||
if( RegionCommonChanVerifyDr( CN470_MAX_NB_CHANNELS, channelsMask, linkAdrParams.Datarate, CN470_TX_MIN_DATARATE, CN470_TX_MAX_DATARATE, Channels ) == false )
|
||||
{
|
||||
status &= 0xFD; // Datarate KO
|
||||
}
|
||||
|
||||
// Verify tx power
|
||||
if( RegionCommonValueInRange( linkAdrParams.TxPower, CN470_MAX_TX_POWER, CN470_MIN_TX_POWER ) == 0 )
|
||||
{
|
||||
// Verify if the maximum TX power is exceeded
|
||||
if( CN470_MAX_TX_POWER > linkAdrParams.TxPower )
|
||||
{ // Apply maximum TX power. Accept TX power.
|
||||
linkAdrParams.TxPower = CN470_MAX_TX_POWER;
|
||||
}
|
||||
else
|
||||
{
|
||||
status &= 0xFB; // TxPower KO
|
||||
}
|
||||
}
|
||||
|
||||
// Update channelsMask if everything is correct
|
||||
if( status == 0x07 )
|
||||
{
|
||||
if( linkAdrParams.NbRep == 0 )
|
||||
{ // Value of 0 is not allowed, revert to default.
|
||||
linkAdrParams.NbRep = 1;
|
||||
}
|
||||
|
||||
// Copy Mask
|
||||
RegionCommonChanMaskCopy( 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;
|
||||
uint32_t freq = rxParamSetupReq->Frequency;
|
||||
|
||||
// Verify radio frequency
|
||||
if( ( Radio.CheckRfFrequency( freq ) == false ) ||
|
||||
( freq < CN470_FIRST_RX1_CHANNEL ) ||
|
||||
( freq > CN470_LAST_RX1_CHANNEL ) ||
|
||||
( ( ( freq - ( uint32_t ) CN470_FIRST_RX1_CHANNEL ) % ( uint32_t ) CN470_STEPWIDTH_RX1_CHANNEL ) != 0 ) )
|
||||
{
|
||||
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( AlternateDrParams_t* alternateDr )
|
||||
{
|
||||
int8_t datarate = 0;
|
||||
|
||||
if( ( alternateDr->NbTrials % 48 ) == 0 )
|
||||
{
|
||||
datarate = DR_0;
|
||||
}
|
||||
else if( ( alternateDr->NbTrials % 32 ) == 0 )
|
||||
{
|
||||
datarate = DR_1;
|
||||
}
|
||||
else if( ( alternateDr->NbTrials % 24 ) == 0 )
|
||||
{
|
||||
datarate = DR_2;
|
||||
}
|
||||
else if( ( alternateDr->NbTrials % 16 ) == 0 )
|
||||
{
|
||||
datarate = DR_3;
|
||||
}
|
||||
else if( ( alternateDr->NbTrials % 8 ) == 0 )
|
||||
{
|
||||
datarate = DR_4;
|
||||
}
|
||||
else
|
||||
{
|
||||
datarate = DR_5;
|
||||
}
|
||||
return datarate;
|
||||
}
|
||||
|
||||
void RegionCN470CalcBackOff( CalcBackOffParams_t* calcBackOff )
|
||||
{
|
||||
uint8_t channel = calcBackOff->Channel;
|
||||
uint16_t joinDutyCycle = 0;
|
||||
|
||||
if( calcBackOff->Joined == false )
|
||||
{
|
||||
// Get the join duty cycle
|
||||
joinDutyCycle = RegionCommonGetJoinDc( calcBackOff->ElapsedTime );
|
||||
// Apply band time-off.
|
||||
Bands[Channels[channel].Band].TimeOff = calcBackOff->TxTimeOnAir * joinDutyCycle - calcBackOff->TxTimeOnAir;
|
||||
}
|
||||
else
|
||||
{
|
||||
Bands[Channels[channel].Band].TimeOff = 0;
|
||||
}
|
||||
}
|
||||
|
||||
bool 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( ChannelsMask, 0, 6 ) == 0 )
|
||||
{ // Reactivate default channels
|
||||
ChannelsMask[0] = 0xFFFF;
|
||||
ChannelsMask[1] = 0xFFFF;
|
||||
ChannelsMask[2] = 0xFFFF;
|
||||
ChannelsMask[3] = 0xFFFF;
|
||||
ChannelsMask[4] = 0xFFFF;
|
||||
ChannelsMask[5] = 0xFFFF;
|
||||
}
|
||||
|
||||
if( nextChanParams->AggrTimeOff <= TimerGetElapsedTime( nextChanParams->LastAggrTx ) )
|
||||
{
|
||||
// Reset Aggregated time off
|
||||
*aggregatedTimeOff = 0;
|
||||
|
||||
// Update bands Time OFF
|
||||
nextTxDelay = RegionCommonUpdateBandTimeOff( nextChanParams->Joined, nextChanParams->DutyCycleEnabled, Bands, CN470_MAX_NB_BANDS );
|
||||
|
||||
// Search how many channels are enabled
|
||||
nbEnabledChannels = CountNbOfEnabledChannels( nextChanParams->Datarate,
|
||||
ChannelsMask, Channels,
|
||||
Bands, enabledChannels, &delayTx );
|
||||
}
|
||||
else
|
||||
{
|
||||
delayTx++;
|
||||
nextTxDelay = nextChanParams->AggrTimeOff - TimerGetElapsedTime( nextChanParams->LastAggrTx );
|
||||
}
|
||||
|
||||
if( nbEnabledChannels > 0 )
|
||||
{
|
||||
// We found a valid channel
|
||||
*channel = enabledChannels[randr( 0, nbEnabledChannels - 1 )];
|
||||
|
||||
*time = 0;
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
if( delayTx > 0 )
|
||||
{
|
||||
// Delay transmission due to AggregatedTimeOff or to a band time off
|
||||
*time = nextTxDelay;
|
||||
return true;
|
||||
}
|
||||
// Datarate not supported by any channel
|
||||
*time = 0;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
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, Bands[Channels[continuousWave->Channel].Band].TxMaxPower, continuousWave->Datarate, ChannelsMask );
|
||||
int8_t phyTxPower = 0;
|
||||
uint32_t frequency = 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;
|
||||
}
|
||||
|
|
@ -0,0 +1,445 @@
|
|||
/*
|
||||
* Copyright (C) 2015-2017 Alibaba Group Holding Limited
|
||||
*/
|
||||
|
||||
/*!
|
||||
* \file RegionCN470.h
|
||||
*
|
||||
* \brief Region definition for CN470
|
||||
*
|
||||
* \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 REGIONCN470 Region CN470
|
||||
* Implementation according to LoRaWAN Specification v1.0.2.
|
||||
* \{
|
||||
*/
|
||||
#ifndef __REGION_CN470_H__
|
||||
#define __REGION_CN470_H__
|
||||
|
||||
/*!
|
||||
* LoRaMac maximum number of channels
|
||||
*/
|
||||
#define CN470_MAX_NB_CHANNELS 8
|
||||
|
||||
/*!
|
||||
* 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
|
||||
|
||||
/*!
|
||||
* LoRaMac maximum number of bands
|
||||
*/
|
||||
#define CN470_MAX_NB_BANDS 1
|
||||
|
||||
/*!
|
||||
* Band 0 definition
|
||||
* { DutyCycle, TxMaxPower, LastTxDoneTime, TimeOff }
|
||||
*/
|
||||
#define CN470_BAND0 { 1, CN470_MAX_TX_POWER, 0, 0 } // 100.0 %
|
||||
|
||||
/*!
|
||||
* Defines the first channel for RX window 1 for CN470 band
|
||||
*/
|
||||
#define CN470_FIRST_RX1_CHANNEL ( (uint32_t) 500.3e6 )
|
||||
|
||||
/*!
|
||||
* Defines the last channel for RX window 1 for CN470 band
|
||||
*/
|
||||
#define CN470_LAST_RX1_CHANNEL ( (uint32_t) 509.7e6 )
|
||||
|
||||
/*!
|
||||
* Defines the step width of the channels for RX window 1
|
||||
*/
|
||||
#define CN470_STEPWIDTH_RX1_CHANNEL ( (uint32_t) 200e3 )
|
||||
|
||||
/*!
|
||||
* 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[] = { 125e3, 125e3, 125e3, 125e3, 125e3, 125e3 };
|
||||
|
||||
/*!
|
||||
* Maximum payload with respect to the datarate index. Cannot operate with repeater.
|
||||
*/
|
||||
static const uint8_t MaxPayloadOfDatarateCN470[] = { 51, 51, 51, 115, 222, 222 };
|
||||
|
||||
/*!
|
||||
* Maximum payload with respect to the datarate index. Can operate with repeater.
|
||||
*/
|
||||
static const uint8_t MaxPayloadOfDatarateRepeaterCN470[] = { 51, 51, 51, 115, 222, 222 };
|
||||
|
||||
/*!
|
||||
* \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( InitType_t type );
|
||||
|
||||
/*!
|
||||
* \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 );
|
||||
|
||||
/*!
|
||||
* \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 RegionCN470AdrNext( AdrNextParams_t* adrNext, int8_t* drOut, int8_t* txPowOut, uint32_t* adrAckCounter );
|
||||
|
||||
/*!
|
||||
* 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] alternateDr Pointer to the function parameters.
|
||||
*
|
||||
* \retval Datarate to apply.
|
||||
*/
|
||||
int8_t RegionCN470AlternateDr( AlternateDrParams_t* alternateDr );
|
||||
|
||||
/*!
|
||||
* \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]
|
||||
*/
|
||||
bool 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 );
|
||||
|
||||
/*! \} defgroup REGIONCN470 */
|
||||
|
||||
#endif // __REGION_CN470_H__
|
||||
1063
Living_SDK/kernel/protocols/lorawan/lora/mac/region/RegionCN779.c
Normal file
1063
Living_SDK/kernel/protocols/lorawan/lora/mac/region/RegionCN779.c
Normal file
File diff suppressed because it is too large
Load diff
|
|
@ -0,0 +1,469 @@
|
|||
/*
|
||||
* Copyright (C) 2015-2017 Alibaba Group Holding Limited
|
||||
*/
|
||||
|
||||
/*!
|
||||
* \file RegionCN779.h
|
||||
*
|
||||
* \brief Region definition for CN779
|
||||
*
|
||||
* \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 REGIONCN779 Region CN779
|
||||
* Implementation according to LoRaWAN Specification v1.0.2.
|
||||
* \{
|
||||
*/
|
||||
#ifndef __REGION_CN779_H__
|
||||
#define __REGION_CN779_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
|
||||
|
||||
/*!
|
||||
* LoRaMac maximum number of bands
|
||||
*/
|
||||
#define CN779_MAX_NB_BANDS 1
|
||||
|
||||
/*!
|
||||
* Band 0 definition
|
||||
* { DutyCycle, TxMaxPower, LastTxDoneTime, TimeOff }
|
||||
*/
|
||||
#define CN779_BAND0 { 100, CN779_MAX_TX_POWER, 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( InitType_t type );
|
||||
|
||||
/*!
|
||||
* \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 );
|
||||
|
||||
/*!
|
||||
* \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 RegionCN779AdrNext( AdrNextParams_t* adrNext, int8_t* drOut, int8_t* txPowOut, uint32_t* adrAckCounter );
|
||||
|
||||
/*!
|
||||
* 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] alternateDr Pointer to the function parameters.
|
||||
*
|
||||
* \retval Datarate to apply.
|
||||
*/
|
||||
int8_t RegionCN779AlternateDr( AlternateDrParams_t* alternateDr );
|
||||
|
||||
/*!
|
||||
* \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]
|
||||
*/
|
||||
bool 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 );
|
||||
|
||||
/*! \} defgroup REGIONCN779 */
|
||||
|
||||
#endif // __REGION_CN779_H__
|
||||
|
|
@ -0,0 +1,248 @@
|
|||
/*
|
||||
* Copyright (C) 2015-2017 Alibaba Group Holding Limited
|
||||
*/
|
||||
|
||||
/*
|
||||
/ _____) _ | |
|
||||
( (____ _____ ____ _| |_ _____ ____| |__
|
||||
\____ \| ___ | (_ _) ___ |/ ___) _ \
|
||||
_____) ) ____| | | || |_| ____( (___| | | |
|
||||
(______/|_____)_|_|_| \__)_____)\____)_| |_|
|
||||
(C)2013 Semtech
|
||||
___ _____ _ ___ _ _____ ___ ___ ___ ___
|
||||
/ __|_ _/_\ / __| |/ / __/ _ \| _ \/ __| __|
|
||||
\__ \ | |/ _ \ (__| ' <| _| (_) | / (__| _|
|
||||
|___/ |_/_/ \_\___|_|\_\_| \___/|_|_\\___|___|
|
||||
embedded.connectivity.solutions===============
|
||||
|
||||
Description: LoRa MAC common region 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 <stdbool.h>
|
||||
#include <string.h>
|
||||
#include <stdint.h>
|
||||
#include <math.h>
|
||||
|
||||
//#include "timer.h"
|
||||
#include "timeServer.h"
|
||||
#include "utilities.h"
|
||||
#include "LoRaMac.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)(-1);
|
||||
|
||||
// Update bands Time OFF
|
||||
for (uint8_t i = 0; i < nbBands; i++) {
|
||||
if (joined == false) {
|
||||
uint32_t txDoneTime = MAX(
|
||||
TimerGetElapsedTime(bands[i].LastJoinTxDoneTime),
|
||||
(dutyCycle == true) ? TimerGetElapsedTime(bands[i].LastTxDoneTime)
|
||||
: 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) {
|
||||
if (bands[i].TimeOff <=
|
||||
TimerGetElapsedTime(bands[i].LastTxDoneTime)) {
|
||||
bands[i].TimeOff = 0;
|
||||
}
|
||||
if (bands[i].TimeOff != 0) {
|
||||
nextTxDelay =
|
||||
MIN(bands[i].TimeOff -
|
||||
TimerGetElapsedTime(bands[i].LastTxDoneTime),
|
||||
nextTxDelay);
|
||||
}
|
||||
} else {
|
||||
nextTxDelay = 0;
|
||||
bands[i].TimeOff = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
return nextTxDelay;
|
||||
}
|
||||
|
||||
uint8_t RegionCommonParseLinkAdrReq(uint8_t *payload,
|
||||
LinkAdrParams_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;
|
||||
}
|
||||
|
||||
DECIMAL RegionCommonComputeSymbolTimeLoRa(uint8_t phyDr, uint32_t bandwidth)
|
||||
{
|
||||
return ((DECIMAL)(1 << phyDr) / (DECIMAL)bandwidth) * 1000;
|
||||
}
|
||||
|
||||
DECIMAL RegionCommonComputeSymbolTimeFsk(uint8_t phyDr)
|
||||
{
|
||||
return ((DECIMAL)8.0 / (DECIMAL)phyDr); // 1 symbol equals 1 byte
|
||||
}
|
||||
|
||||
void RegionCommonComputeRxWindowParameters(
|
||||
DECIMAL tSymbol, uint8_t minRxSymbols, uint32_t rxError, uint32_t wakeUpTime,
|
||||
uint32_t *windowTimeout, int32_t *windowOffset)
|
||||
{
|
||||
*windowTimeout =
|
||||
MAX((uint32_t)ceilf(((2 * minRxSymbols - 8) * tSymbol + 2 * rxError) /
|
||||
tSymbol),
|
||||
minRxSymbols); // Computed number of symbols
|
||||
*windowOffset = (int32_t)ceilf(
|
||||
(4.0f * tSymbol) - ((*windowTimeout * tSymbol) / 2.0f) - wakeUpTime);
|
||||
}
|
||||
|
||||
int8_t RegionCommonComputeTxPower(int8_t txPowerIndex, float maxEirp,
|
||||
float antennaGain)
|
||||
{
|
||||
int8_t phyTxPower = 0;
|
||||
|
||||
phyTxPower = (int8_t)floorf((maxEirp - (txPowerIndex * 2U)) - antennaGain);
|
||||
|
||||
return phyTxPower;
|
||||
}
|
||||
|
|
@ -0,0 +1,267 @@
|
|||
/*
|
||||
* Copyright (C) 2015-2017 Alibaba Group Holding Limited
|
||||
*/
|
||||
|
||||
/*!
|
||||
* \file RegionCommon.h
|
||||
*
|
||||
* \brief Region independent implementations which are common to all
|
||||
* regions.
|
||||
*
|
||||
* \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 REGIONCOMMON Common region implementation
|
||||
* Region independent implementations which are common to all
|
||||
* regions.
|
||||
* \{
|
||||
*/
|
||||
#ifndef __REGIONCOMMON_H__
|
||||
#define __REGIONCOMMON_H__
|
||||
|
||||
#include "precision.h"
|
||||
|
||||
typedef struct sLinkAdrParams
|
||||
{
|
||||
/*!
|
||||
* 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;
|
||||
} LinkAdrParams_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,
|
||||
LinkAdrParams_t *parseLinkAdr);
|
||||
|
||||
/*!
|
||||
* \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.
|
||||
*/
|
||||
DECIMAL 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.
|
||||
*/
|
||||
DECIMAL 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(
|
||||
DECIMAL 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.
|
||||
*
|
||||
* \param [IN] txPower TX power index.
|
||||
*
|
||||
* \param [IN] maxEirp Maximum EIRP.
|
||||
*
|
||||
* \param [IN] antennaGain Antenna gain.
|
||||
*
|
||||
* \retval Returns the physical TX power.
|
||||
*/
|
||||
int8_t RegionCommonComputeTxPower(int8_t txPowerIndex, float maxEirp,
|
||||
float antennaGain);
|
||||
|
||||
/*! \} defgroup REGIONCOMMON */
|
||||
|
||||
#endif // __REGIONCOMMON_H__
|
||||
1063
Living_SDK/kernel/protocols/lorawan/lora/mac/region/RegionEU433.c
Normal file
1063
Living_SDK/kernel/protocols/lorawan/lora/mac/region/RegionEU433.c
Normal file
File diff suppressed because it is too large
Load diff
|
|
@ -0,0 +1,470 @@
|
|||
/*
|
||||
* Copyright (C) 2015-2017 Alibaba Group Holding Limited
|
||||
*/
|
||||
|
||||
/*!
|
||||
* \file RegionEU433.h
|
||||
*
|
||||
* \brief Region definition for EU433
|
||||
*
|
||||
* \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 REGIONEU433 Region EU433
|
||||
* Implementation according to LoRaWAN Specification v1.0.2.
|
||||
* \{
|
||||
*/
|
||||
#ifndef __REGION_EU433_H__
|
||||
#define __REGION_EU433_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
|
||||
|
||||
/*!
|
||||
* Band 0 definition
|
||||
* { DutyCycle, TxMaxPower, LastTxDoneTime, TimeOff }
|
||||
*/
|
||||
#define EU433_BAND0 { 100, EU433_MAX_TX_POWER, 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( InitType_t type );
|
||||
|
||||
/*!
|
||||
* \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 );
|
||||
|
||||
/*!
|
||||
* \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 RegionEU433AdrNext( AdrNextParams_t* adrNext, int8_t* drOut, int8_t* txPowOut, uint32_t* adrAckCounter );
|
||||
|
||||
/*!
|
||||
* 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] alternateDr Pointer to the function parameters.
|
||||
*
|
||||
* \retval Datarate to apply.
|
||||
*/
|
||||
int8_t RegionEU433AlternateDr( AlternateDrParams_t* alternateDr );
|
||||
|
||||
/*!
|
||||
* \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]
|
||||
*/
|
||||
bool 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 );
|
||||
|
||||
/*! \} defgroup REGIONEU433 */
|
||||
|
||||
#endif // __REGION_EU433_H__
|
||||
1094
Living_SDK/kernel/protocols/lorawan/lora/mac/region/RegionEU868.c
Normal file
1094
Living_SDK/kernel/protocols/lorawan/lora/mac/region/RegionEU868.c
Normal file
File diff suppressed because it is too large
Load diff
|
|
@ -0,0 +1,491 @@
|
|||
/*
|
||||
* Copyright (C) 2015-2017 Alibaba Group Holding Limited
|
||||
*/
|
||||
|
||||
/*!
|
||||
* \file RegionEU868.h
|
||||
*
|
||||
* \brief Region definition for EU868
|
||||
*
|
||||
* \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 REGIONEU868 Region EU868
|
||||
* Implementation according to LoRaWAN Specification v1.0.2.
|
||||
* \{
|
||||
*/
|
||||
#ifndef __REGION_EU868_H__
|
||||
#define __REGION_EU868_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
|
||||
|
||||
/*!
|
||||
* Maximum number of bands
|
||||
*/
|
||||
#define EU868_MAX_NB_BANDS 5
|
||||
|
||||
/*!
|
||||
* Band 0 definition
|
||||
* { DutyCycle, TxMaxPower, LastTxDoneTime, TimeOff }
|
||||
*/
|
||||
#define EU868_BAND0 { 100 , EU868_MAX_TX_POWER, 0, 0 } // 1.0 %
|
||||
|
||||
/*!
|
||||
* Band 1 definition
|
||||
* { DutyCycle, TxMaxPower, LastTxDoneTime, TimeOff }
|
||||
*/
|
||||
#define EU868_BAND1 { 100 , EU868_MAX_TX_POWER, 0, 0 } // 1.0 %
|
||||
|
||||
/*!
|
||||
* Band 2 definition
|
||||
* Band = { DutyCycle, TxMaxPower, LastTxDoneTime, TimeOff }
|
||||
*/
|
||||
#define EU868_BAND2 { 1000, EU868_MAX_TX_POWER, 0, 0 } // 0.1 %
|
||||
|
||||
/*!
|
||||
* Band 2 definition
|
||||
* Band = { DutyCycle, TxMaxPower, LastTxDoneTime, TimeOff }
|
||||
*/
|
||||
#define EU868_BAND3 { 10 , EU868_MAX_TX_POWER, 0, 0 } // 10.0 %
|
||||
|
||||
/*!
|
||||
* Band 2 definition
|
||||
* Band = { DutyCycle, TxMaxPower, LastTxDoneTime, TimeOff }
|
||||
*/
|
||||
#define EU868_BAND4 { 100 , EU868_MAX_TX_POWER, 0, 0 } // 1.0 %
|
||||
|
||||
/*!
|
||||
* 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( InitType_t type );
|
||||
|
||||
/*!
|
||||
* \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 );
|
||||
|
||||
/*!
|
||||
* \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 RegionEU868AdrNext( AdrNextParams_t* adrNext, int8_t* drOut, int8_t* txPowOut, uint32_t* adrAckCounter );
|
||||
|
||||
/*!
|
||||
* 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] alternateDr Pointer to the function parameters.
|
||||
*
|
||||
* \retval Datarate to apply.
|
||||
*/
|
||||
int8_t RegionEU868AlternateDr( AlternateDrParams_t* alternateDr );
|
||||
|
||||
/*!
|
||||
* \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]
|
||||
*/
|
||||
bool 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 );
|
||||
|
||||
/*! \} defgroup REGIONEU868 */
|
||||
|
||||
#endif // __REGION_EU868_H__
|
||||
1063
Living_SDK/kernel/protocols/lorawan/lora/mac/region/RegionIN865.c
Normal file
1063
Living_SDK/kernel/protocols/lorawan/lora/mac/region/RegionIN865.c
Normal file
File diff suppressed because it is too large
Load diff
|
|
@ -0,0 +1,472 @@
|
|||
/*
|
||||
* Copyright (C) 2015-2017 Alibaba Group Holding Limited
|
||||
*/
|
||||
|
||||
/*!
|
||||
* \file RegionIN865.h
|
||||
*
|
||||
* \brief Region definition for IN865
|
||||
*
|
||||
* \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 REGIONIN865 Region IN865
|
||||
* Implementation according to LoRaWAN Specification v1.0.2.
|
||||
* \{
|
||||
*/
|
||||
#ifndef __REGION_IN865_H__
|
||||
#define __REGION_IN865_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
|
||||
|
||||
/*!
|
||||
* Maximum number of bands
|
||||
*/
|
||||
#define IN865_MAX_NB_BANDS 1
|
||||
|
||||
/*!
|
||||
* Band 0 definition
|
||||
* { DutyCycle, TxMaxPower, LastTxDoneTime, TimeOff }
|
||||
*/
|
||||
#define IN865_BAND0 { 1 , IN865_MAX_TX_POWER, 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( InitType_t type );
|
||||
|
||||
/*!
|
||||
* \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 );
|
||||
|
||||
/*!
|
||||
* \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 RegionIN865AdrNext( AdrNextParams_t* adrNext, int8_t* drOut, int8_t* txPowOut, uint32_t* adrAckCounter );
|
||||
|
||||
/*!
|
||||
* 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] alternateDr Pointer to the function parameters.
|
||||
*
|
||||
* \retval Datarate to apply.
|
||||
*/
|
||||
int8_t RegionIN865AlternateDr( AlternateDrParams_t* alternateDr );
|
||||
|
||||
/*!
|
||||
* \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]
|
||||
*/
|
||||
bool 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 );
|
||||
|
||||
/*! \} defgroup REGIONIN865 */
|
||||
|
||||
#endif // __REGION_IN865_H__
|
||||
1067
Living_SDK/kernel/protocols/lorawan/lora/mac/region/RegionKR920.c
Normal file
1067
Living_SDK/kernel/protocols/lorawan/lora/mac/region/RegionKR920.c
Normal file
File diff suppressed because it is too large
Load diff
|
|
@ -0,0 +1,482 @@
|
|||
/*
|
||||
* Copyright (C) 2015-2017 Alibaba Group Holding Limited
|
||||
*/
|
||||
|
||||
/*!
|
||||
* \file RegionKR920.h
|
||||
*
|
||||
* \brief Region definition for KR920
|
||||
*
|
||||
* \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 REGIONKR920 Region KR920
|
||||
* Implementation according to LoRaWAN Specification v1.0.2.
|
||||
* \{
|
||||
*/
|
||||
#ifndef __REGION_KR920_H__
|
||||
#define __REGION_KR920_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
|
||||
|
||||
/*!
|
||||
* Maximum number of bands
|
||||
*/
|
||||
#define KR920_MAX_NB_BANDS 1
|
||||
|
||||
/*!
|
||||
* Band 0 definition
|
||||
* { DutyCycle, TxMaxPower, LastTxDoneTime, TimeOff }
|
||||
*/
|
||||
#define KR920_BAND0 { 1 , KR920_MAX_TX_POWER, 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( InitType_t type );
|
||||
|
||||
/*!
|
||||
* \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 );
|
||||
|
||||
/*!
|
||||
* \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 RegionKR920AdrNext( AdrNextParams_t* adrNext, int8_t* drOut, int8_t* txPowOut, uint32_t* adrAckCounter );
|
||||
|
||||
/*!
|
||||
* 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] alternateDr Pointer to the function parameters.
|
||||
*
|
||||
* \retval Datarate to apply.
|
||||
*/
|
||||
int8_t RegionKR920AlternateDr( AlternateDrParams_t* alternateDr );
|
||||
|
||||
/*!
|
||||
* \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]
|
||||
*/
|
||||
bool 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 );
|
||||
|
||||
/*! \} defgroup REGIONKR920 */
|
||||
|
||||
#endif // __REGION_KR920_H__
|
||||
|
|
@ -0,0 +1,972 @@
|
|||
/*
|
||||
* Copyright (C) 2015-2017 Alibaba Group Holding Limited
|
||||
*/
|
||||
|
||||
/*
|
||||
/ _____) _ | |
|
||||
( (____ _____ ____ _| |_ _____ ____| |__
|
||||
\____ \| ___ | (_ _) ___ |/ ___) _ \
|
||||
_____) ) ____| | | || |_| ____( (___| | | |
|
||||
(______/|_____)_|_|_| \__)_____)\____)_| |_|
|
||||
(C)2013 Semtech
|
||||
___ _____ _ ___ _ _____ ___ ___ ___ ___
|
||||
/ __|_ _/_\ / __| |/ / __/ _ \| _ \/ __| __|
|
||||
\__ \ | |/ _ \ (__| ' <| _| (_) | / (__| _|
|
||||
|___/ |_/_/ \_\___|_|\_\_| \___/|_|_\\___|___|
|
||||
embedded.connectivity.solutions===============
|
||||
|
||||
Description: LoRa MAC region US915 Hybrid 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 <stdbool.h>
|
||||
#include <string.h>
|
||||
#include <stdint.h>
|
||||
#include <math.h>
|
||||
|
||||
#include "radio.h"
|
||||
//#include "timer.h"
|
||||
#include "timeServer.h"
|
||||
#include "LoRaMac.h"
|
||||
|
||||
#include "utilities.h"
|
||||
|
||||
#include "Region.h"
|
||||
#include "RegionCommon.h"
|
||||
#include "RegionUS915-Hybrid.h"
|
||||
#include "debug.h"
|
||||
|
||||
// Definitions
|
||||
#define CHANNELS_MASK_SIZE 6
|
||||
|
||||
// Global attributes
|
||||
/*!
|
||||
* LoRaMAC channels
|
||||
*/
|
||||
static ChannelParams_t Channels[US915_HYBRID_MAX_NB_CHANNELS];
|
||||
|
||||
/*!
|
||||
* LoRaMac bands
|
||||
*/
|
||||
static Band_t Bands[US915_HYBRID_MAX_NB_BANDS] =
|
||||
{
|
||||
US915_HYBRID_BAND0
|
||||
};
|
||||
|
||||
/*!
|
||||
* LoRaMac channels mask
|
||||
*/
|
||||
static uint16_t ChannelsMask[CHANNELS_MASK_SIZE];
|
||||
|
||||
/*!
|
||||
* LoRaMac channels remaining
|
||||
*/
|
||||
static uint16_t ChannelsMaskRemaining[CHANNELS_MASK_SIZE];
|
||||
|
||||
/*!
|
||||
* LoRaMac channels default mask
|
||||
*/
|
||||
static uint16_t ChannelsDefaultMask[CHANNELS_MASK_SIZE];
|
||||
|
||||
// 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( BandwidthsUS915_HYBRID[drIndex] )
|
||||
{
|
||||
default:
|
||||
case 125000:
|
||||
return 0;
|
||||
case 250000:
|
||||
return 1;
|
||||
case 500000:
|
||||
return 2;
|
||||
}
|
||||
}
|
||||
|
||||
static void ReenableChannels( uint16_t mask, uint16_t* channelsMask )
|
||||
{
|
||||
uint16_t blockMask = mask;
|
||||
|
||||
for( uint8_t i = 0, j = 0; i < 4; i++, j += 2 )
|
||||
{
|
||||
channelsMask[i] = 0;
|
||||
if( ( blockMask & ( 1 << j ) ) != 0 )
|
||||
{
|
||||
channelsMask[i] |= 0x00FF;
|
||||
}
|
||||
if( ( blockMask & ( 1 << ( j + 1 ) ) ) != 0 )
|
||||
{
|
||||
channelsMask[i] |= 0xFF00;
|
||||
}
|
||||
}
|
||||
channelsMask[4] = blockMask;
|
||||
channelsMask[5] = 0x0000;
|
||||
}
|
||||
|
||||
static uint8_t CountBits( 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;
|
||||
}
|
||||
|
||||
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 );
|
||||
|
||||
if( datarate == DR_4 )
|
||||
{// Limit tx power to max 26dBm
|
||||
txPowerResult = MAX( txPower, TX_POWER_2 );
|
||||
}
|
||||
else
|
||||
{
|
||||
if( RegionCommonCountChannels( channelsMask, 0, 4 ) < 50 )
|
||||
{// Limit tx power to max 21dBm
|
||||
txPowerResult = MAX( txPower, TX_POWER_5 );
|
||||
}
|
||||
}
|
||||
return txPowerResult;
|
||||
}
|
||||
|
||||
static bool ValidateChannelsMask( uint16_t* channelsMask )
|
||||
{
|
||||
bool chanMaskState = false;
|
||||
uint16_t block1 = 0;
|
||||
uint16_t block2 = 0;
|
||||
uint8_t index = 0;
|
||||
uint16_t channelsMaskCpy[6];
|
||||
|
||||
// Copy channels mask to not change the input
|
||||
for( uint8_t i = 0; i < 4; i++ )
|
||||
{
|
||||
channelsMaskCpy[i] = channelsMask[i];
|
||||
}
|
||||
|
||||
for( uint8_t i = 0; i < 4; i++ )
|
||||
{
|
||||
block1 = channelsMaskCpy[i] & 0x00FF;
|
||||
block2 = channelsMaskCpy[i] & 0xFF00;
|
||||
|
||||
if( CountBits( block1, 16 ) > 5 )
|
||||
{
|
||||
channelsMaskCpy[i] &= block1;
|
||||
channelsMaskCpy[4] = 1 << ( i * 2 );
|
||||
chanMaskState = true;
|
||||
index = i;
|
||||
break;
|
||||
}
|
||||
else if( CountBits( block2, 16 ) > 5 )
|
||||
{
|
||||
channelsMaskCpy[i] &= block2;
|
||||
channelsMaskCpy[4] = 1 << ( i * 2 + 1 );
|
||||
chanMaskState = true;
|
||||
index = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Do only change the channel mask, if we have found a valid block.
|
||||
if( chanMaskState == true )
|
||||
{
|
||||
// Copy channels mask back again
|
||||
for( uint8_t i = 0; i < 4; i++ )
|
||||
{
|
||||
channelsMask[i] = channelsMaskCpy[i];
|
||||
|
||||
if( i != index )
|
||||
{
|
||||
channelsMask[i] = 0;
|
||||
}
|
||||
}
|
||||
channelsMask[4] = channelsMaskCpy[4];
|
||||
}
|
||||
return chanMaskState;
|
||||
}
|
||||
|
||||
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 < US915_HYBRID_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 RegionUS915HybridGetPhyParam( GetPhyParams_t* getPhy )
|
||||
{
|
||||
PhyParam_t phyParam = { 0 };
|
||||
|
||||
switch( getPhy->Attribute )
|
||||
{
|
||||
case PHY_MIN_RX_DR:
|
||||
{
|
||||
phyParam.Value = US915_HYBRID_RX_MIN_DATARATE;
|
||||
break;
|
||||
}
|
||||
case PHY_MIN_TX_DR:
|
||||
{
|
||||
phyParam.Value = US915_HYBRID_TX_MIN_DATARATE;
|
||||
break;
|
||||
}
|
||||
case PHY_DEF_TX_DR:
|
||||
{
|
||||
phyParam.Value = US915_HYBRID_DEFAULT_DATARATE;
|
||||
break;
|
||||
}
|
||||
case PHY_NEXT_LOWER_TX_DR:
|
||||
{
|
||||
phyParam.Value = GetNextLowerTxDr( getPhy->Datarate, US915_HYBRID_TX_MIN_DATARATE );
|
||||
break;
|
||||
}
|
||||
case PHY_DEF_TX_POWER:
|
||||
{
|
||||
phyParam.Value = US915_HYBRID_DEFAULT_TX_POWER;
|
||||
break;
|
||||
}
|
||||
case PHY_MAX_PAYLOAD:
|
||||
{
|
||||
phyParam.Value = MaxPayloadOfDatarateUS915_HYBRID[getPhy->Datarate];
|
||||
break;
|
||||
}
|
||||
case PHY_MAX_PAYLOAD_REPEATER:
|
||||
{
|
||||
phyParam.Value = MaxPayloadOfDatarateRepeaterUS915_HYBRID[getPhy->Datarate];
|
||||
break;
|
||||
}
|
||||
case PHY_DUTY_CYCLE:
|
||||
{
|
||||
phyParam.Value = US915_HYBRID_DUTY_CYCLE_ENABLED;
|
||||
break;
|
||||
}
|
||||
case PHY_MAX_RX_WINDOW:
|
||||
{
|
||||
phyParam.Value = US915_HYBRID_MAX_RX_WINDOW;
|
||||
break;
|
||||
}
|
||||
case PHY_RECEIVE_DELAY1:
|
||||
{
|
||||
phyParam.Value = US915_HYBRID_RECEIVE_DELAY1;
|
||||
break;
|
||||
}
|
||||
case PHY_RECEIVE_DELAY2:
|
||||
{
|
||||
phyParam.Value = US915_HYBRID_RECEIVE_DELAY2;
|
||||
break;
|
||||
}
|
||||
case PHY_JOIN_ACCEPT_DELAY1:
|
||||
{
|
||||
phyParam.Value = US915_HYBRID_JOIN_ACCEPT_DELAY1;
|
||||
break;
|
||||
}
|
||||
case PHY_JOIN_ACCEPT_DELAY2:
|
||||
{
|
||||
phyParam.Value = US915_HYBRID_JOIN_ACCEPT_DELAY2;
|
||||
break;
|
||||
}
|
||||
case PHY_MAX_FCNT_GAP:
|
||||
{
|
||||
phyParam.Value = US915_HYBRID_MAX_FCNT_GAP;
|
||||
break;
|
||||
}
|
||||
case PHY_ACK_TIMEOUT:
|
||||
{
|
||||
phyParam.Value = ( US915_HYBRID_ACKTIMEOUT + randr( -US915_HYBRID_ACK_TIMEOUT_RND, US915_HYBRID_ACK_TIMEOUT_RND ) );
|
||||
break;
|
||||
}
|
||||
case PHY_DEF_DR1_OFFSET:
|
||||
{
|
||||
phyParam.Value = US915_HYBRID_DEFAULT_RX1_DR_OFFSET;
|
||||
break;
|
||||
}
|
||||
case PHY_DEF_RX2_FREQUENCY:
|
||||
{
|
||||
phyParam.Value = US915_HYBRID_RX_WND_2_FREQ;
|
||||
break;
|
||||
}
|
||||
case PHY_DEF_RX2_DR:
|
||||
{
|
||||
phyParam.Value = US915_HYBRID_RX_WND_2_DR;
|
||||
break;
|
||||
}
|
||||
case PHY_CHANNELS_MASK:
|
||||
{
|
||||
phyParam.ChannelsMask = ChannelsMask;
|
||||
break;
|
||||
}
|
||||
case PHY_CHANNELS_DEFAULT_MASK:
|
||||
{
|
||||
phyParam.ChannelsMask = ChannelsDefaultMask;
|
||||
break;
|
||||
}
|
||||
case PHY_MAX_NB_CHANNELS:
|
||||
{
|
||||
phyParam.Value = US915_HYBRID_MAX_NB_CHANNELS;
|
||||
break;
|
||||
}
|
||||
case PHY_CHANNELS:
|
||||
{
|
||||
phyParam.Channels = Channels;
|
||||
break;
|
||||
}
|
||||
case PHY_DEF_UPLINK_DWELL_TIME:
|
||||
case PHY_DEF_DOWNLINK_DWELL_TIME:
|
||||
{
|
||||
phyParam.Value = 0;
|
||||
break;
|
||||
}
|
||||
case PHY_DEF_MAX_EIRP:
|
||||
case PHY_DEF_ANTENNA_GAIN:
|
||||
{
|
||||
phyParam.fValue = 0;
|
||||
break;
|
||||
}
|
||||
case PHY_NB_JOIN_TRIALS:
|
||||
case PHY_DEF_NB_JOIN_TRIALS:
|
||||
{
|
||||
phyParam.Value = 2;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return phyParam;
|
||||
}
|
||||
|
||||
void RegionUS915HybridSetBandTxDone( SetBandTxDoneParams_t* txDone )
|
||||
{
|
||||
RegionCommonSetBandTxDone( txDone->Joined, &Bands[Channels[txDone->Channel].Band], txDone->LastTxDoneTime );
|
||||
}
|
||||
|
||||
void RegionUS915HybridInitDefaults( InitType_t type )
|
||||
{
|
||||
switch( type )
|
||||
{
|
||||
case INIT_TYPE_INIT:
|
||||
{
|
||||
// Channels
|
||||
// 125 kHz channels
|
||||
for( uint8_t i = 0; i < US915_HYBRID_MAX_NB_CHANNELS - 8; i++ )
|
||||
{
|
||||
Channels[i].Frequency = 902300000 + i * 200000;
|
||||
Channels[i].DrRange.Value = ( DR_3 << 4 ) | DR_0;
|
||||
Channels[i].Band = 0;
|
||||
}
|
||||
// 500 kHz channels
|
||||
for( uint8_t i = US915_HYBRID_MAX_NB_CHANNELS - 8; i < US915_HYBRID_MAX_NB_CHANNELS; i++ )
|
||||
{
|
||||
Channels[i].Frequency = 903000000 + ( i - ( US915_HYBRID_MAX_NB_CHANNELS - 8 ) ) * 1600000;
|
||||
Channels[i].DrRange.Value = ( DR_4 << 4 ) | DR_4;
|
||||
Channels[i].Band = 0;
|
||||
}
|
||||
|
||||
// ChannelsMask
|
||||
ChannelsDefaultMask[0] = 0x00FF;
|
||||
ChannelsDefaultMask[1] = 0x0000;
|
||||
ChannelsDefaultMask[2] = 0x0000;
|
||||
ChannelsDefaultMask[3] = 0x0000;
|
||||
ChannelsDefaultMask[4] = 0x0001;
|
||||
ChannelsDefaultMask[5] = 0x0000;
|
||||
|
||||
// Copy channels default mask
|
||||
RegionCommonChanMaskCopy( ChannelsMask, ChannelsDefaultMask, 6 );
|
||||
|
||||
// Copy into channels mask remaining
|
||||
RegionCommonChanMaskCopy( ChannelsMaskRemaining, ChannelsMask, 6 );
|
||||
break;
|
||||
}
|
||||
case INIT_TYPE_RESTORE:
|
||||
{
|
||||
ReenableChannels( ChannelsDefaultMask[4], ChannelsMask );
|
||||
|
||||
for( uint8_t i = 0; i < 6; i++ )
|
||||
{ // Copy-And the channels mask
|
||||
ChannelsMaskRemaining[i] &= ChannelsMask[i];
|
||||
}
|
||||
}
|
||||
default:
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool RegionUS915HybridVerify( VerifyParams_t* verify, PhyAttribute_t phyAttribute )
|
||||
{
|
||||
switch( phyAttribute )
|
||||
{
|
||||
case PHY_TX_DR:
|
||||
{
|
||||
return RegionCommonValueInRange( verify->DatarateParams.Datarate, US915_HYBRID_TX_MIN_DATARATE, US915_HYBRID_TX_MAX_DATARATE );
|
||||
}
|
||||
case PHY_DEF_TX_DR:
|
||||
{
|
||||
return RegionCommonValueInRange( verify->DatarateParams.Datarate, DR_0, DR_5 );
|
||||
}
|
||||
case PHY_RX_DR:
|
||||
{
|
||||
return RegionCommonValueInRange( verify->DatarateParams.Datarate, US915_HYBRID_RX_MIN_DATARATE, US915_HYBRID_RX_MAX_DATARATE );
|
||||
}
|
||||
case PHY_DEF_TX_POWER:
|
||||
case PHY_TX_POWER:
|
||||
{
|
||||
// Remark: switched min and max!
|
||||
return RegionCommonValueInRange( verify->TxPower, US915_HYBRID_MAX_TX_POWER, US915_HYBRID_MIN_TX_POWER );
|
||||
}
|
||||
case PHY_DUTY_CYCLE:
|
||||
{
|
||||
return US915_HYBRID_DUTY_CYCLE_ENABLED;
|
||||
}
|
||||
case PHY_NB_JOIN_TRIALS:
|
||||
{
|
||||
if( verify->NbJoinTrials < 2 )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void RegionUS915HybridApplyCFList( ApplyCFListParams_t* applyCFList )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
bool RegionUS915HybridChanMaskSet( ChanMaskSetParams_t* chanMaskSet )
|
||||
{
|
||||
uint8_t nbChannels = RegionCommonCountChannels( chanMaskSet->ChannelsMaskIn, 0, 4 );
|
||||
|
||||
// Check the number of active channels
|
||||
if( ( nbChannels < 2 ) &&
|
||||
( nbChannels > 0 ) )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// Validate the channels mask
|
||||
if( ValidateChannelsMask( chanMaskSet->ChannelsMaskIn ) == false )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
switch( chanMaskSet->ChannelsMaskType )
|
||||
{
|
||||
case CHANNELS_MASK:
|
||||
{
|
||||
RegionCommonChanMaskCopy( ChannelsMask, chanMaskSet->ChannelsMaskIn, 6 );
|
||||
|
||||
for( uint8_t i = 0; i < 6; i++ )
|
||||
{ // Copy-And the channels mask
|
||||
ChannelsMaskRemaining[i] &= ChannelsMask[i];
|
||||
}
|
||||
break;
|
||||
}
|
||||
case CHANNELS_DEFAULT_MASK:
|
||||
{
|
||||
RegionCommonChanMaskCopy( ChannelsDefaultMask, chanMaskSet->ChannelsMaskIn, 6 );
|
||||
break;
|
||||
}
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool RegionUS915HybridAdrNext( AdrNextParams_t* adrNext, int8_t* drOut, int8_t* txPowOut, uint32_t* adrAckCounter )
|
||||
{
|
||||
bool adrAckReq = false;
|
||||
int8_t datarate = adrNext->Datarate;
|
||||
int8_t txPower = adrNext->TxPower;
|
||||
GetPhyParams_t getPhy;
|
||||
PhyParam_t phyParam;
|
||||
|
||||
// Report back the adr ack counter
|
||||
*adrAckCounter = adrNext->AdrAckCounter;
|
||||
|
||||
if( adrNext->AdrEnabled == true )
|
||||
{
|
||||
if( datarate == US915_HYBRID_TX_MIN_DATARATE )
|
||||
{
|
||||
*adrAckCounter = 0;
|
||||
adrAckReq = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
if( adrNext->AdrAckCounter >= US915_HYBRID_ADR_ACK_LIMIT )
|
||||
{
|
||||
adrAckReq = true;
|
||||
txPower = US915_HYBRID_MAX_TX_POWER;
|
||||
}
|
||||
else
|
||||
{
|
||||
adrAckReq = false;
|
||||
}
|
||||
if( adrNext->AdrAckCounter >= ( US915_HYBRID_ADR_ACK_LIMIT + US915_HYBRID_ADR_ACK_DELAY ) )
|
||||
{
|
||||
if( ( adrNext->AdrAckCounter % US915_HYBRID_ADR_ACK_DELAY ) == 1 )
|
||||
{
|
||||
// Decrease the datarate
|
||||
getPhy.Attribute = PHY_NEXT_LOWER_TX_DR;
|
||||
getPhy.Datarate = datarate;
|
||||
getPhy.UplinkDwellTime = adrNext->UplinkDwellTime;
|
||||
phyParam = RegionUS915HybridGetPhyParam( &getPhy );
|
||||
datarate = phyParam.Value;
|
||||
|
||||
if( datarate == US915_HYBRID_TX_MIN_DATARATE )
|
||||
{
|
||||
// We must set adrAckReq to false as soon as we reach the lowest datarate
|
||||
adrAckReq = false;
|
||||
if( adrNext->UpdateChanMask == true )
|
||||
{
|
||||
// Re-enable default channels
|
||||
ReenableChannels( ChannelsMask[4], ChannelsMask );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
*drOut = datarate;
|
||||
*txPowOut = txPower;
|
||||
return adrAckReq;
|
||||
}
|
||||
|
||||
void RegionUS915HybridComputeRxWindowParameters( int8_t datarate, uint8_t minRxSymbols, uint32_t rxError, RxConfigParams_t *rxConfigParams )
|
||||
{
|
||||
double tSymbol = 0.0;
|
||||
uint32_t radioWakeUpTime;
|
||||
|
||||
rxConfigParams->Datarate = datarate;
|
||||
rxConfigParams->Bandwidth = GetBandwidth( datarate );
|
||||
|
||||
if( datarate == DR_7 )
|
||||
{ // FSK
|
||||
tSymbol = RegionCommonComputeSymbolTimeFsk( DataratesUS915_HYBRID[datarate] );
|
||||
}
|
||||
else
|
||||
{ // LoRa
|
||||
tSymbol = RegionCommonComputeSymbolTimeLoRa( DataratesUS915_HYBRID[datarate], BandwidthsUS915_HYBRID[datarate] );
|
||||
}
|
||||
|
||||
radioWakeUpTime = Radio.GetRadioWakeUpTime( );
|
||||
RegionCommonComputeRxWindowParameters( tSymbol, minRxSymbols, rxError, radioWakeUpTime, &rxConfigParams->WindowTimeout, &rxConfigParams->WindowOffset );
|
||||
}
|
||||
|
||||
bool RegionUS915HybridRxConfig( RxConfigParams_t* rxConfig, int8_t* datarate )
|
||||
{
|
||||
int8_t dr = rxConfig->Datarate;
|
||||
uint8_t maxPayload = 0;
|
||||
int8_t phyDr = 0;
|
||||
uint32_t frequency = rxConfig->Frequency;
|
||||
|
||||
if( Radio.GetStatus( ) != RF_IDLE )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if( rxConfig->Window == 0 )
|
||||
{
|
||||
// Apply window 1 frequency
|
||||
frequency = US915_HYBRID_FIRST_RX1_CHANNEL + ( rxConfig->Channel % 8 ) * US915_HYBRID_STEPWIDTH_RX1_CHANNEL;
|
||||
}
|
||||
|
||||
// Read the physical datarate from the datarates table
|
||||
phyDr = DataratesUS915_HYBRID[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 = MaxPayloadOfDatarateRepeaterUS915_HYBRID[dr];
|
||||
}
|
||||
else
|
||||
{
|
||||
maxPayload = MaxPayloadOfDatarateUS915_HYBRID[dr];
|
||||
}
|
||||
Radio.SetMaxPayloadLength( MODEM_LORA, maxPayload + LORA_MAC_FRMPAYLOAD_OVERHEAD );
|
||||
DBG_PRINTF("RX on freq %d Hz at DR %d\n\r", frequency, dr);
|
||||
|
||||
*datarate = (uint8_t) dr;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool RegionUS915HybridTxConfig( TxConfigParams_t* txConfig, int8_t* txPower, TimerTime_t* txTimeOnAir )
|
||||
{
|
||||
int8_t phyDr = DataratesUS915_HYBRID[txConfig->Datarate];
|
||||
int8_t txPowerLimited = LimitTxPower( txConfig->TxPower, Bands[Channels[txConfig->Channel].Band].TxMaxPower, txConfig->Datarate, ChannelsMask );
|
||||
uint32_t bandwidth = GetBandwidth( txConfig->Datarate );
|
||||
int8_t phyTxPower = 0;
|
||||
|
||||
// Calculate physical TX power
|
||||
phyTxPower = RegionCommonComputeTxPower( txPowerLimited, US915_HYBRID_DEFAULT_MAX_ERP, 0 );
|
||||
|
||||
Radio.SetChannel( Channels[txConfig->Channel].Frequency );
|
||||
|
||||
Radio.SetMaxPayloadLength( MODEM_LORA, txConfig->PktLen );
|
||||
Radio.SetTxConfig( MODEM_LORA, phyTxPower, 0, bandwidth, phyDr, 1, 8, false, true, 0, 0, false, 3e3 );
|
||||
DBG_PRINTF("TX on freq %d Hz at DR %d\n\r", Channels[txConfig->Channel].Frequency, txConfig->Datarate);
|
||||
|
||||
*txTimeOnAir = Radio.TimeOnAir( MODEM_LORA, txConfig->PktLen );
|
||||
*txPower = txPowerLimited;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
uint8_t RegionUS915HybridLinkAdrReq( LinkAdrReqParams_t* linkAdrReq, int8_t* drOut, int8_t* txPowOut, uint8_t* nbRepOut, uint8_t* nbBytesParsed )
|
||||
{
|
||||
uint8_t status = 0x07;
|
||||
LinkAdrParams_t linkAdrParams;
|
||||
uint8_t nextIndex = 0;
|
||||
uint8_t bytesProcessed = 0;
|
||||
uint16_t channelsMask[6] = { 0, 0, 0, 0, 0, 0 };
|
||||
|
||||
// Initialize local copy of channels mask
|
||||
RegionCommonChanMaskCopy( channelsMask, ChannelsMask, 6 );
|
||||
|
||||
while( bytesProcessed < linkAdrReq->PayloadSize )
|
||||
{
|
||||
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;
|
||||
// Apply chMask to channels 64 to 71
|
||||
channelsMask[4] = linkAdrParams.ChMask;
|
||||
}
|
||||
else if( linkAdrParams.ChMaskCtrl == 7 )
|
||||
{
|
||||
// Disable all 125 kHz channels
|
||||
channelsMask[0] = 0x0000;
|
||||
channelsMask[1] = 0x0000;
|
||||
channelsMask[2] = 0x0000;
|
||||
channelsMask[3] = 0x0000;
|
||||
// Apply chMask to channels 64 to 71
|
||||
channelsMask[4] = linkAdrParams.ChMask;
|
||||
}
|
||||
else if( linkAdrParams.ChMaskCtrl == 5 )
|
||||
{
|
||||
// RFU
|
||||
status &= 0xFE; // Channel mask KO
|
||||
}
|
||||
else
|
||||
{
|
||||
channelsMask[linkAdrParams.ChMaskCtrl] = linkAdrParams.ChMask;
|
||||
}
|
||||
}
|
||||
|
||||
// FCC 15.247 paragraph F mandates to hop on at least 2 125 kHz channels
|
||||
if( ( linkAdrParams.Datarate < DR_4 ) && ( RegionCommonCountChannels( channelsMask, 0, 4 ) < 2 ) )
|
||||
{
|
||||
status &= 0xFE; // Channel mask KO
|
||||
}
|
||||
|
||||
if( ValidateChannelsMask( channelsMask ) == false )
|
||||
{
|
||||
status &= 0xFE; // Channel mask KO
|
||||
}
|
||||
|
||||
// Verify datarate
|
||||
if( RegionCommonChanVerifyDr( US915_HYBRID_MAX_NB_CHANNELS, channelsMask, linkAdrParams.Datarate, US915_HYBRID_TX_MIN_DATARATE, US915_HYBRID_TX_MAX_DATARATE, Channels ) == false )
|
||||
{
|
||||
status &= 0xFD; // Datarate KO
|
||||
}
|
||||
|
||||
// Verify tx power
|
||||
if( RegionCommonValueInRange( linkAdrParams.TxPower, US915_HYBRID_MAX_TX_POWER, US915_HYBRID_MIN_TX_POWER ) == 0 )
|
||||
{
|
||||
// Verify if the maximum TX power is exceeded
|
||||
if( US915_HYBRID_MAX_TX_POWER > linkAdrParams.TxPower )
|
||||
{ // Apply maximum TX power. Accept TX power.
|
||||
linkAdrParams.TxPower = US915_HYBRID_MAX_TX_POWER;
|
||||
}
|
||||
else
|
||||
{
|
||||
status &= 0xFB; // TxPower KO
|
||||
}
|
||||
}
|
||||
|
||||
// Update channelsMask if everything is correct
|
||||
if( status == 0x07 )
|
||||
{
|
||||
if( linkAdrParams.NbRep == 0 )
|
||||
{ // Value of 0 is not allowed, revert to default.
|
||||
linkAdrParams.NbRep = 1;
|
||||
}
|
||||
|
||||
// Copy Mask
|
||||
RegionCommonChanMaskCopy( ChannelsMask, channelsMask, 6 );
|
||||
|
||||
ChannelsMaskRemaining[0] &= ChannelsMask[0];
|
||||
ChannelsMaskRemaining[1] &= ChannelsMask[1];
|
||||
ChannelsMaskRemaining[2] &= ChannelsMask[2];
|
||||
ChannelsMaskRemaining[3] &= ChannelsMask[3];
|
||||
ChannelsMaskRemaining[4] = ChannelsMask[4];
|
||||
ChannelsMaskRemaining[5] = ChannelsMask[5];
|
||||
}
|
||||
|
||||
// Update status variables
|
||||
*drOut = linkAdrParams.Datarate;
|
||||
*txPowOut = linkAdrParams.TxPower;
|
||||
*nbRepOut = linkAdrParams.NbRep;
|
||||
*nbBytesParsed = bytesProcessed;
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
uint8_t RegionUS915HybridRxParamSetupReq( RxParamSetupReqParams_t* rxParamSetupReq )
|
||||
{
|
||||
uint8_t status = 0x07;
|
||||
uint32_t freq = rxParamSetupReq->Frequency;
|
||||
|
||||
// Verify radio frequency
|
||||
if( ( Radio.CheckRfFrequency( freq ) == false ) ||
|
||||
( freq < US915_HYBRID_FIRST_RX1_CHANNEL ) ||
|
||||
( freq > US915_HYBRID_LAST_RX1_CHANNEL ) ||
|
||||
( ( ( freq - ( uint32_t ) US915_HYBRID_FIRST_RX1_CHANNEL ) % ( uint32_t ) US915_HYBRID_STEPWIDTH_RX1_CHANNEL ) != 0 ) )
|
||||
{
|
||||
status &= 0xFE; // Channel frequency KO
|
||||
}
|
||||
|
||||
// Verify datarate
|
||||
if( RegionCommonValueInRange( rxParamSetupReq->Datarate, US915_HYBRID_RX_MIN_DATARATE, US915_HYBRID_RX_MAX_DATARATE ) == false )
|
||||
{
|
||||
status &= 0xFD; // Datarate KO
|
||||
}
|
||||
if( ( RegionCommonValueInRange( rxParamSetupReq->Datarate, DR_5, DR_7 ) == true ) ||
|
||||
( rxParamSetupReq->Datarate > DR_13 ) )
|
||||
{
|
||||
status &= 0xFD; // Datarate KO
|
||||
}
|
||||
|
||||
// Verify datarate offset
|
||||
if( RegionCommonValueInRange( rxParamSetupReq->DrOffset, US915_HYBRID_MIN_RX1_DR_OFFSET, US915_HYBRID_MAX_RX1_DR_OFFSET ) == false )
|
||||
{
|
||||
status &= 0xFB; // Rx1DrOffset range KO
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
uint8_t RegionUS915HybridNewChannelReq( NewChannelReqParams_t* newChannelReq )
|
||||
{
|
||||
// Datarate and frequency KO
|
||||
return 0;
|
||||
}
|
||||
|
||||
int8_t RegionUS915HybridTxParamSetupReq( TxParamSetupReqParams_t* txParamSetupReq )
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
uint8_t RegionUS915HybridDlChannelReq( DlChannelReqParams_t* dlChannelReq )
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
int8_t RegionUS915HybridAlternateDr( AlternateDrParams_t* alternateDr )
|
||||
{
|
||||
int8_t datarate = 0;
|
||||
|
||||
// Re-enable 500 kHz default channels
|
||||
ReenableChannels( ChannelsMask[4], ChannelsMask );
|
||||
|
||||
if( ( alternateDr->NbTrials & 0x01 ) == 0x01 )
|
||||
{
|
||||
datarate = DR_4;
|
||||
}
|
||||
else
|
||||
{
|
||||
datarate = DR_0;
|
||||
}
|
||||
return datarate;
|
||||
}
|
||||
|
||||
void RegionUS915HybridCalcBackOff( CalcBackOffParams_t* calcBackOff )
|
||||
{
|
||||
uint8_t channel = calcBackOff->Channel;
|
||||
uint16_t joinDutyCycle = 0;
|
||||
|
||||
if( calcBackOff->Joined == false )
|
||||
{
|
||||
// Get the join duty cycle
|
||||
joinDutyCycle = RegionCommonGetJoinDc( calcBackOff->ElapsedTime );
|
||||
// Apply band time-off.
|
||||
Bands[Channels[channel].Band].TimeOff = calcBackOff->TxTimeOnAir * joinDutyCycle - calcBackOff->TxTimeOnAir;
|
||||
}
|
||||
else
|
||||
{
|
||||
Bands[Channels[channel].Band].TimeOff = 0;
|
||||
}
|
||||
}
|
||||
|
||||
bool RegionUS915HybridNextChannel( NextChanParams_t* nextChanParams, uint8_t* channel, TimerTime_t* time, TimerTime_t* aggregatedTimeOff )
|
||||
{
|
||||
uint8_t nbEnabledChannels = 0;
|
||||
uint8_t delayTx = 0;
|
||||
uint8_t enabledChannels[US915_HYBRID_MAX_NB_CHANNELS] = { 0 };
|
||||
TimerTime_t nextTxDelay = 0;
|
||||
|
||||
// Count 125kHz channels
|
||||
if( RegionCommonCountChannels( ChannelsMaskRemaining, 0, 4 ) == 0 )
|
||||
{ // Reactivate default channels
|
||||
RegionCommonChanMaskCopy( ChannelsMaskRemaining, ChannelsMask, 4 );
|
||||
}
|
||||
// Check other channels
|
||||
if( nextChanParams->Datarate >= DR_4 )
|
||||
{
|
||||
if( ( ChannelsMaskRemaining[4] & 0x00FF ) == 0 )
|
||||
{
|
||||
ChannelsMaskRemaining[4] = ChannelsMask[4];
|
||||
}
|
||||
}
|
||||
|
||||
if( nextChanParams->AggrTimeOff <= TimerGetElapsedTime( nextChanParams->LastAggrTx ) )
|
||||
{
|
||||
// Reset Aggregated time off
|
||||
*aggregatedTimeOff = 0;
|
||||
|
||||
// Update bands Time OFF
|
||||
nextTxDelay = RegionCommonUpdateBandTimeOff( nextChanParams->Joined, nextChanParams->DutyCycleEnabled, Bands, US915_HYBRID_MAX_NB_BANDS );
|
||||
|
||||
// Search how many channels are enabled
|
||||
nbEnabledChannels = CountNbOfEnabledChannels( nextChanParams->Datarate,
|
||||
ChannelsMaskRemaining, Channels,
|
||||
Bands, enabledChannels, &delayTx );
|
||||
}
|
||||
else
|
||||
{
|
||||
delayTx++;
|
||||
nextTxDelay = nextChanParams->AggrTimeOff - TimerGetElapsedTime( nextChanParams->LastAggrTx );
|
||||
}
|
||||
|
||||
if( nbEnabledChannels > 0 )
|
||||
{
|
||||
// We found a valid channel
|
||||
*channel = enabledChannels[randr( 0, nbEnabledChannels - 1 )];
|
||||
// Disable the channel in the mask
|
||||
RegionCommonChanDisable( ChannelsMaskRemaining, *channel, US915_HYBRID_MAX_NB_CHANNELS - 8 );
|
||||
|
||||
*time = 0;
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
if( delayTx > 0 )
|
||||
{
|
||||
// Delay transmission due to AggregatedTimeOff or to a band time off
|
||||
*time = nextTxDelay;
|
||||
return true;
|
||||
}
|
||||
// Datarate not supported by any channel
|
||||
*time = 0;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
LoRaMacStatus_t RegionUS915HybridChannelAdd( ChannelAddParams_t* channelAdd )
|
||||
{
|
||||
return LORAMAC_STATUS_PARAMETER_INVALID;
|
||||
}
|
||||
|
||||
bool RegionUS915HybridChannelsRemove( ChannelRemoveParams_t* channelRemove )
|
||||
{
|
||||
return LORAMAC_STATUS_PARAMETER_INVALID;
|
||||
}
|
||||
|
||||
void RegionUS915HybridSetContinuousWave( ContinuousWaveParams_t* continuousWave )
|
||||
{
|
||||
int8_t txPowerLimited = LimitTxPower( continuousWave->TxPower, Bands[Channels[continuousWave->Channel].Band].TxMaxPower, continuousWave->Datarate, ChannelsMask );
|
||||
int8_t phyTxPower = 0;
|
||||
uint32_t frequency = Channels[continuousWave->Channel].Frequency;
|
||||
|
||||
// Calculate physical TX power
|
||||
phyTxPower = RegionCommonComputeTxPower( txPowerLimited, US915_HYBRID_DEFAULT_MAX_ERP, 0 );
|
||||
|
||||
Radio.SetTxContinuousWave( frequency, phyTxPower, continuousWave->Timeout );
|
||||
}
|
||||
|
||||
uint8_t RegionUS915HybridApplyDrOffset( uint8_t downlinkDwellTime, int8_t dr, int8_t drOffset )
|
||||
{
|
||||
int8_t datarate = DatarateOffsetsUS915_HYBRID[dr][drOffset];
|
||||
|
||||
if( datarate < 0 )
|
||||
{
|
||||
datarate = DR_0;
|
||||
}
|
||||
return datarate;
|
||||
}
|
||||
|
|
@ -0,0 +1,452 @@
|
|||
/*
|
||||
* Copyright (C) 2015-2017 Alibaba Group Holding Limited
|
||||
*/
|
||||
|
||||
/*!
|
||||
* \file RegionUS915Hybrid-Hybrid.h
|
||||
*
|
||||
* \brief Region definition for US915
|
||||
*
|
||||
* \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 REGIONUS915HYB Region US915 in hybrid mode
|
||||
* This is a hybrid implementation for US915, supporting 16 uplink channels only.
|
||||
* \{
|
||||
*/
|
||||
#ifndef __REGION_US915_HYBRID_H__
|
||||
#define __REGION_US915_HYBRID_H__
|
||||
|
||||
/*!
|
||||
* LoRaMac maximum number of channels
|
||||
*/
|
||||
#define US915_HYBRID_MAX_NB_CHANNELS 72
|
||||
|
||||
/*!
|
||||
* Minimal datarate that can be used by the node
|
||||
*/
|
||||
#define US915_HYBRID_TX_MIN_DATARATE DR_0
|
||||
|
||||
/*!
|
||||
* Maximal datarate that can be used by the node
|
||||
*/
|
||||
#define US915_HYBRID_TX_MAX_DATARATE DR_4
|
||||
|
||||
/*!
|
||||
* Minimal datarate that can be used by the node
|
||||
*/
|
||||
#define US915_HYBRID_RX_MIN_DATARATE DR_8
|
||||
|
||||
/*!
|
||||
* Maximal datarate that can be used by the node
|
||||
*/
|
||||
#define US915_HYBRID_RX_MAX_DATARATE DR_13
|
||||
|
||||
/*!
|
||||
* Default datarate used by the node
|
||||
*/
|
||||
#define US915_HYBRID_DEFAULT_DATARATE DR_0
|
||||
|
||||
/*!
|
||||
* Minimal Rx1 receive datarate offset
|
||||
*/
|
||||
#define US915_HYBRID_MIN_RX1_DR_OFFSET 0
|
||||
|
||||
/*!
|
||||
* Maximal Rx1 receive datarate offset
|
||||
*/
|
||||
#define US915_HYBRID_MAX_RX1_DR_OFFSET 3
|
||||
|
||||
/*!
|
||||
* Default Rx1 receive datarate offset
|
||||
*/
|
||||
#define US915_HYBRID_DEFAULT_RX1_DR_OFFSET 0
|
||||
|
||||
/*!
|
||||
* Minimal Tx output power that can be used by the node
|
||||
*/
|
||||
#define US915_HYBRID_MIN_TX_POWER TX_POWER_10
|
||||
|
||||
/*!
|
||||
* Maximal Tx output power that can be used by the node
|
||||
*/
|
||||
#define US915_HYBRID_MAX_TX_POWER TX_POWER_0
|
||||
|
||||
/*!
|
||||
* Default Tx output power used by the node
|
||||
*/
|
||||
#define US915_HYBRID_DEFAULT_TX_POWER TX_POWER_0
|
||||
|
||||
/*!
|
||||
* Default Max ERP
|
||||
*/
|
||||
#define US915_HYBRID_DEFAULT_MAX_ERP 30.0f
|
||||
|
||||
/*!
|
||||
* ADR Ack limit
|
||||
*/
|
||||
#define US915_HYBRID_ADR_ACK_LIMIT 64
|
||||
|
||||
/*!
|
||||
* ADR Ack delay
|
||||
*/
|
||||
#define US915_HYBRID_ADR_ACK_DELAY 32
|
||||
|
||||
/*!
|
||||
* Enabled or disabled the duty cycle
|
||||
*/
|
||||
#define US915_HYBRID_DUTY_CYCLE_ENABLED 0
|
||||
|
||||
/*!
|
||||
* Maximum RX window duration
|
||||
*/
|
||||
#define US915_HYBRID_MAX_RX_WINDOW 3000
|
||||
|
||||
/*!
|
||||
* Receive delay 1
|
||||
*/
|
||||
#define US915_HYBRID_RECEIVE_DELAY1 1000
|
||||
|
||||
/*!
|
||||
* Receive delay 2
|
||||
*/
|
||||
#define US915_HYBRID_RECEIVE_DELAY2 2000
|
||||
|
||||
/*!
|
||||
* Join accept delay 1
|
||||
*/
|
||||
#define US915_HYBRID_JOIN_ACCEPT_DELAY1 5000
|
||||
|
||||
/*!
|
||||
* Join accept delay 2
|
||||
*/
|
||||
#define US915_HYBRID_JOIN_ACCEPT_DELAY2 6000
|
||||
|
||||
/*!
|
||||
* Maximum frame counter gap
|
||||
*/
|
||||
#define US915_HYBRID_MAX_FCNT_GAP 16384
|
||||
|
||||
/*!
|
||||
* Ack timeout
|
||||
*/
|
||||
#define US915_HYBRID_ACKTIMEOUT 2000
|
||||
|
||||
/*!
|
||||
* Random ack timeout limits
|
||||
*/
|
||||
#define US915_HYBRID_ACK_TIMEOUT_RND 1000
|
||||
|
||||
/*!
|
||||
* Second reception window channel frequency definition.
|
||||
*/
|
||||
#define US915_HYBRID_RX_WND_2_FREQ 923300000
|
||||
|
||||
/*!
|
||||
* Second reception window channel datarate definition.
|
||||
*/
|
||||
#define US915_HYBRID_RX_WND_2_DR DR_8
|
||||
|
||||
/*!
|
||||
* LoRaMac maximum number of bands
|
||||
*/
|
||||
#define US915_HYBRID_MAX_NB_BANDS 1
|
||||
|
||||
/*!
|
||||
* Band 0 definition
|
||||
* { DutyCycle, TxMaxPower, LastTxDoneTime, TimeOff }
|
||||
*/
|
||||
#define US915_HYBRID_BAND0 { 1, US915_HYBRID_MAX_TX_POWER, 0, 0 } // 100.0 %
|
||||
|
||||
/*!
|
||||
* Defines the first channel for RX window 1 for US band
|
||||
*/
|
||||
#define US915_HYBRID_FIRST_RX1_CHANNEL ( (uint32_t) 923300000 )
|
||||
|
||||
/*!
|
||||
* Defines the last channel for RX window 1 for US band
|
||||
*/
|
||||
#define US915_HYBRID_LAST_RX1_CHANNEL ( (uint32_t) 927500000 )
|
||||
|
||||
/*!
|
||||
* Defines the step width of the channels for RX window 1
|
||||
*/
|
||||
#define US915_HYBRID_STEPWIDTH_RX1_CHANNEL ( (uint32_t) 600000 )
|
||||
|
||||
/*!
|
||||
* Data rates table definition
|
||||
*/
|
||||
static const uint8_t DataratesUS915_HYBRID[] = { 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_HYBRID[] = { 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_HYBRID[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_HYBRID[] = { 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_HYBRID[] = { 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 RegionUS915HybridGetPhyParam( GetPhyParams_t* getPhy );
|
||||
|
||||
/*!
|
||||
* \brief Updates the last TX done parameters of the current channel.
|
||||
*
|
||||
* \param [IN] txDone Pointer to the function parameters.
|
||||
*/
|
||||
void RegionUS915HybridSetBandTxDone( SetBandTxDoneParams_t* txDone );
|
||||
|
||||
/*!
|
||||
* \brief Initializes the channels masks and the channels.
|
||||
*
|
||||
* \param [IN] type Sets the initialization type.
|
||||
*/
|
||||
void RegionUS915HybridInitDefaults( InitType_t type );
|
||||
|
||||
/*!
|
||||
* \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 RegionUS915HybridVerify( 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 RegionUS915HybridApplyCFList( 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 RegionUS915HybridChanMaskSet( ChanMaskSetParams_t* chanMaskSet );
|
||||
|
||||
/*!
|
||||
* \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 RegionUS915HybridAdrNext( AdrNextParams_t* adrNext, int8_t* drOut, int8_t* txPowOut, uint32_t* adrAckCounter );
|
||||
|
||||
/*!
|
||||
* 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 RegionUS915HybridComputeRxWindowParameters( 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 RegionUS915HybridRxConfig( 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 RegionUS915HybridTxConfig( 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 RegionUS915HybridLinkAdrReq( 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 RegionUS915HybridRxParamSetupReq( 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 RegionUS915HybridNewChannelReq( 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 RegionUS915HybridTxParamSetupReq( 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 RegionUS915HybridDlChannelReq( DlChannelReqParams_t* dlChannelReq );
|
||||
|
||||
/*!
|
||||
* \brief Alternates the datarate of the channel for the join request.
|
||||
*
|
||||
* \param [IN] alternateDr Pointer to the function parameters.
|
||||
*
|
||||
* \retval Datarate to apply.
|
||||
*/
|
||||
int8_t RegionUS915HybridAlternateDr( AlternateDrParams_t* alternateDr );
|
||||
|
||||
/*!
|
||||
* \brief Calculates the back-off time.
|
||||
*
|
||||
* \param [IN] calcBackOff Pointer to the function parameters.
|
||||
*/
|
||||
void RegionUS915HybridCalcBackOff( 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]
|
||||
*/
|
||||
bool RegionUS915HybridNextChannel( 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 RegionUS915HybridChannelAdd( 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 RegionUS915HybridChannelsRemove( ChannelRemoveParams_t* channelRemove );
|
||||
|
||||
/*!
|
||||
* \brief Sets the radio into continuous wave mode.
|
||||
*
|
||||
* \param [IN] continuousWave Pointer to the function parameters.
|
||||
*/
|
||||
void RegionUS915HybridSetContinuousWave( 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 RegionUS915HybridApplyDrOffset( uint8_t downlinkDwellTime, int8_t dr, int8_t drOffset );
|
||||
|
||||
/*! \} defgroup REGIONUS915HYB */
|
||||
|
||||
#endif // __REGION_US915_HYBRID_H__
|
||||
|
|
@ -0,0 +1,879 @@
|
|||
/*
|
||||
* Copyright (C) 2015-2017 Alibaba Group Holding Limited
|
||||
*/
|
||||
|
||||
/*
|
||||
/ _____) _ | |
|
||||
( (____ _____ ____ _| |_ _____ ____| |__
|
||||
\____ \| ___ | (_ _) ___ |/ ___) _ \
|
||||
_____) ) ____| | | || |_| ____( (___| | | |
|
||||
(______/|_____)_|_|_| \__)_____)\____)_| |_|
|
||||
(C)2013 Semtech
|
||||
___ _____ _ ___ _ _____ ___ ___ ___ ___
|
||||
/ __|_ _/_\ / __| |/ / __/ _ \| _ \/ __| __|
|
||||
\__ \ | |/ _ \ (__| ' <| _| (_) | / (__| _|
|
||||
|___/ |_/_/ \_\___|_|\_\_| \___/|_|_\\___|___|
|
||||
embedded.connectivity.solutions===============
|
||||
|
||||
Description: LoRa MAC region US915 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 <stdbool.h>
|
||||
#include <string.h>
|
||||
#include <stdint.h>
|
||||
#include <math.h>
|
||||
|
||||
#include "radio.h"
|
||||
//#include "timer.h"
|
||||
#include "timeServer.h"
|
||||
#include "LoRaMac.h"
|
||||
|
||||
#include "utilities.h"
|
||||
|
||||
#include "Region.h"
|
||||
#include "RegionCommon.h"
|
||||
#include "RegionUS915.h"
|
||||
#include "debug.h"
|
||||
|
||||
// Definitions
|
||||
#define CHANNELS_MASK_SIZE 6
|
||||
|
||||
// Global attributes
|
||||
/*!
|
||||
* LoRaMAC channels
|
||||
*/
|
||||
static ChannelParams_t Channels[US915_MAX_NB_CHANNELS];
|
||||
|
||||
/*!
|
||||
* LoRaMac bands
|
||||
*/
|
||||
static Band_t Bands[US915_MAX_NB_BANDS] =
|
||||
{
|
||||
US915_BAND0
|
||||
};
|
||||
|
||||
/*!
|
||||
* LoRaMac channels mask
|
||||
*/
|
||||
static uint16_t ChannelsMask[CHANNELS_MASK_SIZE];
|
||||
|
||||
/*!
|
||||
* LoRaMac channels remaining
|
||||
*/
|
||||
static uint16_t ChannelsMaskRemaining[CHANNELS_MASK_SIZE];
|
||||
|
||||
/*!
|
||||
* LoRaMac channels default mask
|
||||
*/
|
||||
static uint16_t ChannelsDefaultMask[CHANNELS_MASK_SIZE];
|
||||
|
||||
// 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( BandwidthsUS915[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 );
|
||||
|
||||
if( datarate == DR_4 )
|
||||
{// Limit tx power to max 26dBm
|
||||
txPowerResult = MAX( txPower, TX_POWER_2 );
|
||||
}
|
||||
else
|
||||
{
|
||||
if( RegionCommonCountChannels( channelsMask, 0, 4 ) < 50 )
|
||||
{// Limit tx power to max 21dBm
|
||||
txPowerResult = MAX( txPower, TX_POWER_5 );
|
||||
}
|
||||
}
|
||||
return txPowerResult;
|
||||
}
|
||||
|
||||
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 < US915_MAX_NB_CHANNELS; i += 16, k++ )
|
||||
{
|
||||
for( uint8_t j = 0; j < 16; j++ )
|
||||
{
|
||||
if( ( channelsMask[k] & ( 1 << j ) ) != 0 )
|
||||
{
|
||||
if( channels[i + j].Frequency == 0 )
|
||||
{ // Check if the channel is enabled
|
||||
continue;
|
||||
}
|
||||
if( RegionCommonValueInRange( datarate, channels[i + j].DrRange.Fields.Min,
|
||||
channels[i + j].DrRange.Fields.Max ) == false )
|
||||
{ // Check if the current channel selection supports the given datarate
|
||||
continue;
|
||||
}
|
||||
if( bands[channels[i + j].Band].TimeOff > 0 )
|
||||
{ // Check if the band is available for transmission
|
||||
delayTransmission++;
|
||||
continue;
|
||||
}
|
||||
enabledChannels[nbEnabledChannels++] = i + j;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
*delayTx = delayTransmission;
|
||||
return nbEnabledChannels;
|
||||
}
|
||||
|
||||
PhyParam_t RegionUS915GetPhyParam( GetPhyParams_t* getPhy )
|
||||
{
|
||||
PhyParam_t phyParam = { 0 };
|
||||
|
||||
switch( getPhy->Attribute )
|
||||
{
|
||||
case PHY_MIN_RX_DR:
|
||||
{
|
||||
phyParam.Value = US915_RX_MIN_DATARATE;
|
||||
break;
|
||||
}
|
||||
case PHY_MIN_TX_DR:
|
||||
{
|
||||
phyParam.Value = US915_TX_MIN_DATARATE;
|
||||
break;
|
||||
}
|
||||
case PHY_DEF_TX_DR:
|
||||
{
|
||||
phyParam.Value = US915_DEFAULT_DATARATE;
|
||||
break;
|
||||
}
|
||||
case PHY_NEXT_LOWER_TX_DR:
|
||||
{
|
||||
phyParam.Value = GetNextLowerTxDr( getPhy->Datarate, US915_TX_MIN_DATARATE );
|
||||
break;
|
||||
}
|
||||
case PHY_DEF_TX_POWER:
|
||||
{
|
||||
phyParam.Value = US915_DEFAULT_TX_POWER;
|
||||
break;
|
||||
}
|
||||
case PHY_MAX_PAYLOAD:
|
||||
{
|
||||
phyParam.Value = MaxPayloadOfDatarateUS915[getPhy->Datarate];
|
||||
break;
|
||||
}
|
||||
case PHY_MAX_PAYLOAD_REPEATER:
|
||||
{
|
||||
phyParam.Value = MaxPayloadOfDatarateRepeaterUS915[getPhy->Datarate];
|
||||
break;
|
||||
}
|
||||
case PHY_DUTY_CYCLE:
|
||||
{
|
||||
phyParam.Value = US915_DUTY_CYCLE_ENABLED;
|
||||
break;
|
||||
}
|
||||
case PHY_MAX_RX_WINDOW:
|
||||
{
|
||||
phyParam.Value = US915_MAX_RX_WINDOW;
|
||||
break;
|
||||
}
|
||||
case PHY_RECEIVE_DELAY1:
|
||||
{
|
||||
phyParam.Value = US915_RECEIVE_DELAY1;
|
||||
break;
|
||||
}
|
||||
case PHY_RECEIVE_DELAY2:
|
||||
{
|
||||
phyParam.Value = US915_RECEIVE_DELAY2;
|
||||
break;
|
||||
}
|
||||
case PHY_JOIN_ACCEPT_DELAY1:
|
||||
{
|
||||
phyParam.Value = US915_JOIN_ACCEPT_DELAY1;
|
||||
break;
|
||||
}
|
||||
case PHY_JOIN_ACCEPT_DELAY2:
|
||||
{
|
||||
phyParam.Value = US915_JOIN_ACCEPT_DELAY2;
|
||||
break;
|
||||
}
|
||||
case PHY_MAX_FCNT_GAP:
|
||||
{
|
||||
phyParam.Value = US915_MAX_FCNT_GAP;
|
||||
break;
|
||||
}
|
||||
case PHY_ACK_TIMEOUT:
|
||||
{
|
||||
phyParam.Value = ( US915_ACKTIMEOUT + randr( -US915_ACK_TIMEOUT_RND, US915_ACK_TIMEOUT_RND ) );
|
||||
break;
|
||||
}
|
||||
case PHY_DEF_DR1_OFFSET:
|
||||
{
|
||||
phyParam.Value = US915_DEFAULT_RX1_DR_OFFSET;
|
||||
break;
|
||||
}
|
||||
case PHY_DEF_RX2_FREQUENCY:
|
||||
{
|
||||
phyParam.Value = US915_RX_WND_2_FREQ;
|
||||
break;
|
||||
}
|
||||
case PHY_DEF_RX2_DR:
|
||||
{
|
||||
phyParam.Value = US915_RX_WND_2_DR;
|
||||
break;
|
||||
}
|
||||
case PHY_CHANNELS_MASK:
|
||||
{
|
||||
phyParam.ChannelsMask = ChannelsMask;
|
||||
break;
|
||||
}
|
||||
case PHY_CHANNELS_DEFAULT_MASK:
|
||||
{
|
||||
phyParam.ChannelsMask = ChannelsDefaultMask;
|
||||
break;
|
||||
}
|
||||
case PHY_MAX_NB_CHANNELS:
|
||||
{
|
||||
phyParam.Value = US915_MAX_NB_CHANNELS;
|
||||
break;
|
||||
}
|
||||
case PHY_CHANNELS:
|
||||
{
|
||||
phyParam.Channels = Channels;
|
||||
break;
|
||||
}
|
||||
case PHY_DEF_UPLINK_DWELL_TIME:
|
||||
case PHY_DEF_DOWNLINK_DWELL_TIME:
|
||||
{
|
||||
phyParam.Value = 0;
|
||||
break;
|
||||
}
|
||||
case PHY_DEF_MAX_EIRP:
|
||||
case PHY_DEF_ANTENNA_GAIN:
|
||||
{
|
||||
phyParam.fValue = 0;
|
||||
break;
|
||||
}
|
||||
case PHY_NB_JOIN_TRIALS:
|
||||
case PHY_DEF_NB_JOIN_TRIALS:
|
||||
{
|
||||
phyParam.Value = 2;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return phyParam;
|
||||
}
|
||||
|
||||
void RegionUS915SetBandTxDone( SetBandTxDoneParams_t* txDone )
|
||||
{
|
||||
RegionCommonSetBandTxDone( txDone->Joined, &Bands[Channels[txDone->Channel].Band], txDone->LastTxDoneTime );
|
||||
}
|
||||
|
||||
void RegionUS915InitDefaults( InitType_t type )
|
||||
{
|
||||
switch( type )
|
||||
{
|
||||
case INIT_TYPE_INIT:
|
||||
{
|
||||
// Channels
|
||||
// 125 kHz channels
|
||||
for( uint8_t i = 0; i < US915_MAX_NB_CHANNELS - 8; i++ )
|
||||
{
|
||||
Channels[i].Frequency = 902300000 + i * 200000;
|
||||
Channels[i].DrRange.Value = ( DR_3 << 4 ) | DR_0;
|
||||
Channels[i].Band = 0;
|
||||
}
|
||||
// 500 kHz channels
|
||||
for( uint8_t i = US915_MAX_NB_CHANNELS - 8; i < US915_MAX_NB_CHANNELS; i++ )
|
||||
{
|
||||
Channels[i].Frequency = 903000000 + ( i - ( US915_MAX_NB_CHANNELS - 8 ) ) * 1600000;
|
||||
Channels[i].DrRange.Value = ( DR_4 << 4 ) | DR_4;
|
||||
Channels[i].Band = 0;
|
||||
}
|
||||
|
||||
// ChannelsMask
|
||||
ChannelsDefaultMask[0] = 0xFFFF;
|
||||
ChannelsDefaultMask[1] = 0xFFFF;
|
||||
ChannelsDefaultMask[2] = 0xFFFF;
|
||||
ChannelsDefaultMask[3] = 0xFFFF;
|
||||
ChannelsDefaultMask[4] = 0x00FF;
|
||||
ChannelsDefaultMask[5] = 0x0000;
|
||||
|
||||
// Copy channels default mask
|
||||
RegionCommonChanMaskCopy( ChannelsMask, ChannelsDefaultMask, 6 );
|
||||
|
||||
// Copy into channels mask remaining
|
||||
RegionCommonChanMaskCopy( ChannelsMaskRemaining, ChannelsMask, 6 );
|
||||
break;
|
||||
}
|
||||
case INIT_TYPE_RESTORE:
|
||||
{
|
||||
// Copy channels default mask
|
||||
RegionCommonChanMaskCopy( ChannelsMask, ChannelsDefaultMask, 6 );
|
||||
|
||||
for( uint8_t i = 0; i < 6; i++ )
|
||||
{ // Copy-And the channels mask
|
||||
ChannelsMaskRemaining[i] &= ChannelsMask[i];
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool RegionUS915Verify( VerifyParams_t* verify, PhyAttribute_t phyAttribute )
|
||||
{
|
||||
switch( phyAttribute )
|
||||
{
|
||||
case PHY_TX_DR:
|
||||
{
|
||||
return RegionCommonValueInRange( verify->DatarateParams.Datarate, US915_TX_MIN_DATARATE, US915_TX_MAX_DATARATE );
|
||||
}
|
||||
case PHY_DEF_TX_DR:
|
||||
{
|
||||
return RegionCommonValueInRange( verify->DatarateParams.Datarate, DR_0, DR_5 );
|
||||
}
|
||||
case PHY_RX_DR:
|
||||
{
|
||||
return RegionCommonValueInRange( verify->DatarateParams.Datarate, US915_RX_MIN_DATARATE, US915_RX_MAX_DATARATE );
|
||||
}
|
||||
case PHY_DEF_TX_POWER:
|
||||
case PHY_TX_POWER:
|
||||
{
|
||||
// Remark: switched min and max!
|
||||
return RegionCommonValueInRange( verify->TxPower, US915_MAX_TX_POWER, US915_MIN_TX_POWER );
|
||||
}
|
||||
case PHY_DUTY_CYCLE:
|
||||
{
|
||||
return US915_DUTY_CYCLE_ENABLED;
|
||||
}
|
||||
case PHY_NB_JOIN_TRIALS:
|
||||
{
|
||||
if( verify->NbJoinTrials < 2 )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void RegionUS915ApplyCFList( ApplyCFListParams_t* applyCFList )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
bool RegionUS915ChanMaskSet( ChanMaskSetParams_t* chanMaskSet )
|
||||
{
|
||||
uint8_t nbChannels = RegionCommonCountChannels( chanMaskSet->ChannelsMaskIn, 0, 4 );
|
||||
|
||||
// Check the number of active channels
|
||||
if( ( nbChannels < 2 ) &&
|
||||
( nbChannels > 0 ) )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
switch( chanMaskSet->ChannelsMaskType )
|
||||
{
|
||||
case CHANNELS_MASK:
|
||||
{
|
||||
RegionCommonChanMaskCopy( ChannelsMask, chanMaskSet->ChannelsMaskIn, 6 );
|
||||
|
||||
for( uint8_t i = 0; i < 6; i++ )
|
||||
{ // Copy-And the channels mask
|
||||
ChannelsMaskRemaining[i] &= ChannelsMask[i];
|
||||
}
|
||||
break;
|
||||
}
|
||||
case CHANNELS_DEFAULT_MASK:
|
||||
{
|
||||
RegionCommonChanMaskCopy( ChannelsDefaultMask, chanMaskSet->ChannelsMaskIn, 6 );
|
||||
break;
|
||||
}
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool RegionUS915AdrNext( AdrNextParams_t* adrNext, int8_t* drOut, int8_t* txPowOut, uint32_t* adrAckCounter )
|
||||
{
|
||||
bool adrAckReq = false;
|
||||
int8_t datarate = adrNext->Datarate;
|
||||
int8_t txPower = adrNext->TxPower;
|
||||
GetPhyParams_t getPhy;
|
||||
PhyParam_t phyParam;
|
||||
|
||||
// Report back the adr ack counter
|
||||
*adrAckCounter = adrNext->AdrAckCounter;
|
||||
|
||||
if( adrNext->AdrEnabled == true )
|
||||
{
|
||||
if( datarate == US915_TX_MIN_DATARATE )
|
||||
{
|
||||
*adrAckCounter = 0;
|
||||
adrAckReq = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
if( adrNext->AdrAckCounter >= US915_ADR_ACK_LIMIT )
|
||||
{
|
||||
adrAckReq = true;
|
||||
txPower = US915_MAX_TX_POWER;
|
||||
}
|
||||
else
|
||||
{
|
||||
adrAckReq = false;
|
||||
}
|
||||
if( adrNext->AdrAckCounter >= ( US915_ADR_ACK_LIMIT + US915_ADR_ACK_DELAY ) )
|
||||
{
|
||||
if( ( adrNext->AdrAckCounter % US915_ADR_ACK_DELAY ) == 1 )
|
||||
{
|
||||
// Decrease the datarate
|
||||
getPhy.Attribute = PHY_NEXT_LOWER_TX_DR;
|
||||
getPhy.Datarate = datarate;
|
||||
getPhy.UplinkDwellTime = adrNext->UplinkDwellTime;
|
||||
phyParam = RegionUS915GetPhyParam( &getPhy );
|
||||
datarate = phyParam.Value;
|
||||
|
||||
if( datarate == US915_TX_MIN_DATARATE )
|
||||
{
|
||||
// We must set adrAckReq to false as soon as we reach the lowest datarate
|
||||
adrAckReq = false;
|
||||
if( adrNext->UpdateChanMask == true )
|
||||
{
|
||||
// Re-enable default channels
|
||||
ChannelsMask[0] = 0xFFFF;
|
||||
ChannelsMask[1] = 0xFFFF;
|
||||
ChannelsMask[2] = 0xFFFF;
|
||||
ChannelsMask[3] = 0xFFFF;
|
||||
ChannelsMask[4] = 0x00FF;
|
||||
ChannelsMask[5] = 0x0000;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
*drOut = datarate;
|
||||
*txPowOut = txPower;
|
||||
return adrAckReq;
|
||||
}
|
||||
|
||||
void RegionUS915ComputeRxWindowParameters( int8_t datarate, uint8_t minRxSymbols, uint32_t rxError, RxConfigParams_t *rxConfigParams )
|
||||
{
|
||||
double tSymbol = 0.0;
|
||||
uint32_t radioWakeUpTime;
|
||||
|
||||
rxConfigParams->Datarate = datarate;
|
||||
rxConfigParams->Bandwidth = GetBandwidth( datarate );
|
||||
|
||||
if( datarate == DR_7 )
|
||||
{ // FSK
|
||||
tSymbol = RegionCommonComputeSymbolTimeFsk( DataratesUS915[datarate] );
|
||||
}
|
||||
else
|
||||
{ // LoRa
|
||||
tSymbol = RegionCommonComputeSymbolTimeLoRa( DataratesUS915[datarate], BandwidthsUS915[datarate] );
|
||||
}
|
||||
|
||||
radioWakeUpTime = Radio.GetRadioWakeUpTime( );
|
||||
RegionCommonComputeRxWindowParameters( tSymbol, minRxSymbols, rxError, radioWakeUpTime, &rxConfigParams->WindowTimeout, &rxConfigParams->WindowOffset );
|
||||
}
|
||||
|
||||
bool RegionUS915RxConfig( RxConfigParams_t* rxConfig, int8_t* datarate )
|
||||
{
|
||||
int8_t dr = rxConfig->Datarate;
|
||||
uint8_t maxPayload = 0;
|
||||
int8_t phyDr = 0;
|
||||
uint32_t frequency = rxConfig->Frequency;
|
||||
|
||||
if( Radio.GetStatus( ) != RF_IDLE )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if( rxConfig->Window == 0 )
|
||||
{
|
||||
// Apply window 1 frequency
|
||||
frequency = US915_FIRST_RX1_CHANNEL + ( rxConfig->Channel % 8 ) * US915_STEPWIDTH_RX1_CHANNEL;
|
||||
}
|
||||
|
||||
// Read the physical datarate from the datarates table
|
||||
phyDr = DataratesUS915[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 = MaxPayloadOfDatarateRepeaterUS915[dr];
|
||||
}
|
||||
else
|
||||
{
|
||||
maxPayload = MaxPayloadOfDatarateUS915[dr];
|
||||
}
|
||||
Radio.SetMaxPayloadLength( MODEM_LORA, maxPayload + LORA_MAC_FRMPAYLOAD_OVERHEAD );
|
||||
DBG_PRINTF("RX on freq %d Hz at DR %d\n\r", frequency, dr);
|
||||
|
||||
*datarate = (uint8_t) dr;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool RegionUS915TxConfig( TxConfigParams_t* txConfig, int8_t* txPower, TimerTime_t* txTimeOnAir )
|
||||
{
|
||||
int8_t phyDr = DataratesUS915[txConfig->Datarate];
|
||||
int8_t txPowerLimited = LimitTxPower( txConfig->TxPower, Bands[Channels[txConfig->Channel].Band].TxMaxPower, txConfig->Datarate, ChannelsMask );
|
||||
uint32_t bandwidth = GetBandwidth( txConfig->Datarate );
|
||||
int8_t phyTxPower = 0;
|
||||
|
||||
// Calculate physical TX power
|
||||
phyTxPower = RegionCommonComputeTxPower( txPowerLimited, US915_DEFAULT_MAX_ERP, 0 );
|
||||
|
||||
Radio.SetChannel( Channels[txConfig->Channel].Frequency );
|
||||
|
||||
Radio.SetMaxPayloadLength( MODEM_LORA, txConfig->PktLen );
|
||||
Radio.SetTxConfig( MODEM_LORA, phyTxPower, 0, bandwidth, phyDr, 1, 8, false, true, 0, 0, false, 3e3 );
|
||||
DBG_PRINTF("TX on freq %d Hz at DR %d\n\r", Channels[txConfig->Channel].Frequency, txConfig->Datarate);
|
||||
|
||||
*txTimeOnAir = Radio.TimeOnAir( MODEM_LORA, txConfig->PktLen );
|
||||
*txPower = txPowerLimited;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
uint8_t RegionUS915LinkAdrReq( LinkAdrReqParams_t* linkAdrReq, int8_t* drOut, int8_t* txPowOut, uint8_t* nbRepOut, uint8_t* nbBytesParsed )
|
||||
{
|
||||
uint8_t status = 0x07;
|
||||
LinkAdrParams_t linkAdrParams;
|
||||
uint8_t nextIndex = 0;
|
||||
uint8_t bytesProcessed = 0;
|
||||
uint16_t channelsMask[6] = { 0, 0, 0, 0, 0, 0 };
|
||||
|
||||
// Initialize local copy of channels mask
|
||||
RegionCommonChanMaskCopy( channelsMask, ChannelsMask, 6 );
|
||||
|
||||
while( bytesProcessed < linkAdrReq->PayloadSize )
|
||||
{
|
||||
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;
|
||||
// Apply chMask to channels 64 to 71
|
||||
channelsMask[4] = linkAdrParams.ChMask;
|
||||
}
|
||||
else if( linkAdrParams.ChMaskCtrl == 7 )
|
||||
{
|
||||
// Disable all 125 kHz channels
|
||||
channelsMask[0] = 0x0000;
|
||||
channelsMask[1] = 0x0000;
|
||||
channelsMask[2] = 0x0000;
|
||||
channelsMask[3] = 0x0000;
|
||||
// Apply chMask to channels 64 to 71
|
||||
channelsMask[4] = linkAdrParams.ChMask;
|
||||
}
|
||||
else if( linkAdrParams.ChMaskCtrl == 5 )
|
||||
{
|
||||
// RFU
|
||||
status &= 0xFE; // Channel mask KO
|
||||
}
|
||||
else
|
||||
{
|
||||
channelsMask[linkAdrParams.ChMaskCtrl] = linkAdrParams.ChMask;
|
||||
}
|
||||
}
|
||||
|
||||
// FCC 15.247 paragraph F mandates to hop on at least 2 125 kHz channels
|
||||
if( ( linkAdrParams.Datarate < DR_4 ) && ( RegionCommonCountChannels( channelsMask, 0, 4 ) < 2 ) )
|
||||
{
|
||||
status &= 0xFE; // Channel mask KO
|
||||
}
|
||||
|
||||
// Verify datarate
|
||||
if( RegionCommonChanVerifyDr( US915_MAX_NB_CHANNELS, channelsMask, linkAdrParams.Datarate, US915_TX_MIN_DATARATE, US915_TX_MAX_DATARATE, Channels ) == false )
|
||||
{
|
||||
status &= 0xFD; // Datarate KO
|
||||
}
|
||||
|
||||
// Verify tx power
|
||||
if( RegionCommonValueInRange( linkAdrParams.TxPower, US915_MAX_TX_POWER, US915_MIN_TX_POWER ) == 0 )
|
||||
{
|
||||
// Verify if the maximum TX power is exceeded
|
||||
if( US915_MAX_TX_POWER > linkAdrParams.TxPower )
|
||||
{ // Apply maximum TX power. Accept TX power.
|
||||
linkAdrParams.TxPower = US915_MAX_TX_POWER;
|
||||
}
|
||||
else
|
||||
{
|
||||
status &= 0xFB; // TxPower KO
|
||||
}
|
||||
}
|
||||
|
||||
// Update channelsMask if everything is correct
|
||||
if( status == 0x07 )
|
||||
{
|
||||
if( linkAdrParams.NbRep == 0 )
|
||||
{ // Value of 0 is not allowed, revert to default.
|
||||
linkAdrParams.NbRep = 1;
|
||||
}
|
||||
|
||||
// Copy Mask
|
||||
RegionCommonChanMaskCopy( ChannelsMask, channelsMask, 6 );
|
||||
|
||||
ChannelsMaskRemaining[0] &= ChannelsMask[0];
|
||||
ChannelsMaskRemaining[1] &= ChannelsMask[1];
|
||||
ChannelsMaskRemaining[2] &= ChannelsMask[2];
|
||||
ChannelsMaskRemaining[3] &= ChannelsMask[3];
|
||||
ChannelsMaskRemaining[4] = ChannelsMask[4];
|
||||
ChannelsMaskRemaining[5] = ChannelsMask[5];
|
||||
}
|
||||
|
||||
// Update status variables
|
||||
*drOut = linkAdrParams.Datarate;
|
||||
*txPowOut = linkAdrParams.TxPower;
|
||||
*nbRepOut = linkAdrParams.NbRep;
|
||||
*nbBytesParsed = bytesProcessed;
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
uint8_t RegionUS915RxParamSetupReq( RxParamSetupReqParams_t* rxParamSetupReq )
|
||||
{
|
||||
uint8_t status = 0x07;
|
||||
uint32_t freq = rxParamSetupReq->Frequency;
|
||||
|
||||
// Verify radio frequency
|
||||
if( ( Radio.CheckRfFrequency( freq ) == false ) ||
|
||||
( freq < US915_FIRST_RX1_CHANNEL ) ||
|
||||
( freq > US915_LAST_RX1_CHANNEL ) ||
|
||||
( ( ( freq - ( uint32_t ) US915_FIRST_RX1_CHANNEL ) % ( uint32_t ) US915_STEPWIDTH_RX1_CHANNEL ) != 0 ) )
|
||||
{
|
||||
status &= 0xFE; // Channel frequency KO
|
||||
}
|
||||
|
||||
// Verify datarate
|
||||
if( RegionCommonValueInRange( rxParamSetupReq->Datarate, US915_RX_MIN_DATARATE, US915_RX_MAX_DATARATE ) == false )
|
||||
{
|
||||
status &= 0xFD; // Datarate KO
|
||||
}
|
||||
if( ( RegionCommonValueInRange( rxParamSetupReq->Datarate, DR_5, DR_7 ) == true ) ||
|
||||
( rxParamSetupReq->Datarate > DR_13 ) )
|
||||
{
|
||||
status &= 0xFD; // Datarate KO
|
||||
}
|
||||
|
||||
// Verify datarate offset
|
||||
if( RegionCommonValueInRange( rxParamSetupReq->DrOffset, US915_MIN_RX1_DR_OFFSET, US915_MAX_RX1_DR_OFFSET ) == false )
|
||||
{
|
||||
status &= 0xFB; // Rx1DrOffset range KO
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
uint8_t RegionUS915NewChannelReq( NewChannelReqParams_t* newChannelReq )
|
||||
{
|
||||
// Datarate and frequency KO
|
||||
return 0;
|
||||
}
|
||||
|
||||
int8_t RegionUS915TxParamSetupReq( TxParamSetupReqParams_t* txParamSetupReq )
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
uint8_t RegionUS915DlChannelReq( DlChannelReqParams_t* dlChannelReq )
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
int8_t RegionUS915AlternateDr( AlternateDrParams_t* alternateDr )
|
||||
{
|
||||
int8_t datarate = 0;
|
||||
|
||||
// Re-enable 500 kHz default channels
|
||||
ChannelsMask[4] = 0x00FF;
|
||||
|
||||
if( ( alternateDr->NbTrials & 0x01 ) == 0x01 )
|
||||
{
|
||||
datarate = DR_4;
|
||||
}
|
||||
else
|
||||
{
|
||||
datarate = DR_0;
|
||||
}
|
||||
return datarate;
|
||||
}
|
||||
|
||||
void RegionUS915CalcBackOff( CalcBackOffParams_t* calcBackOff )
|
||||
{
|
||||
uint8_t channel = calcBackOff->Channel;
|
||||
uint16_t joinDutyCycle = 0;
|
||||
|
||||
if( calcBackOff->Joined == false )
|
||||
{
|
||||
// Get the join duty cycle
|
||||
joinDutyCycle = RegionCommonGetJoinDc( calcBackOff->ElapsedTime );
|
||||
// Apply band time-off.
|
||||
Bands[Channels[channel].Band].TimeOff = calcBackOff->TxTimeOnAir * joinDutyCycle - calcBackOff->TxTimeOnAir;
|
||||
}
|
||||
else
|
||||
{
|
||||
Bands[Channels[channel].Band].TimeOff = 0;
|
||||
}
|
||||
}
|
||||
|
||||
bool RegionUS915NextChannel( NextChanParams_t* nextChanParams, uint8_t* channel, TimerTime_t* time, TimerTime_t* aggregatedTimeOff )
|
||||
{
|
||||
uint8_t nbEnabledChannels = 0;
|
||||
uint8_t delayTx = 0;
|
||||
uint8_t enabledChannels[US915_MAX_NB_CHANNELS] = { 0 };
|
||||
TimerTime_t nextTxDelay = 0;
|
||||
|
||||
// Count 125kHz channels
|
||||
if( RegionCommonCountChannels( ChannelsMaskRemaining, 0, 4 ) == 0 )
|
||||
{ // Reactivate default channels
|
||||
RegionCommonChanMaskCopy( ChannelsMaskRemaining, ChannelsMask, 4 );
|
||||
}
|
||||
// Check other channels
|
||||
if( nextChanParams->Datarate >= DR_4 )
|
||||
{
|
||||
if( ( ChannelsMaskRemaining[4] & 0x00FF ) == 0 )
|
||||
{
|
||||
ChannelsMaskRemaining[4] = ChannelsMask[4];
|
||||
}
|
||||
}
|
||||
|
||||
if( nextChanParams->AggrTimeOff <= TimerGetElapsedTime( nextChanParams->LastAggrTx ) )
|
||||
{
|
||||
// Reset Aggregated time off
|
||||
*aggregatedTimeOff = 0;
|
||||
|
||||
// Update bands Time OFF
|
||||
nextTxDelay = RegionCommonUpdateBandTimeOff( nextChanParams->Joined, nextChanParams->DutyCycleEnabled, Bands, US915_MAX_NB_BANDS );
|
||||
|
||||
// Search how many channels are enabled
|
||||
nbEnabledChannels = CountNbOfEnabledChannels( nextChanParams->Datarate,
|
||||
ChannelsMaskRemaining, Channels,
|
||||
Bands, enabledChannels, &delayTx );
|
||||
}
|
||||
else
|
||||
{
|
||||
delayTx++;
|
||||
nextTxDelay = nextChanParams->AggrTimeOff - TimerGetElapsedTime( nextChanParams->LastAggrTx );
|
||||
}
|
||||
|
||||
if( nbEnabledChannels > 0 )
|
||||
{
|
||||
// We found a valid channel
|
||||
*channel = enabledChannels[randr( 0, nbEnabledChannels - 1 )];
|
||||
// Disable the channel in the mask
|
||||
RegionCommonChanDisable( ChannelsMaskRemaining, *channel, US915_MAX_NB_CHANNELS - 8 );
|
||||
|
||||
*time = 0;
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
if( delayTx > 0 )
|
||||
{
|
||||
// Delay transmission due to AggregatedTimeOff or to a band time off
|
||||
*time = nextTxDelay;
|
||||
return true;
|
||||
}
|
||||
// Datarate not supported by any channel
|
||||
*time = 0;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
LoRaMacStatus_t RegionUS915ChannelAdd( ChannelAddParams_t* channelAdd )
|
||||
{
|
||||
return LORAMAC_STATUS_PARAMETER_INVALID;
|
||||
}
|
||||
|
||||
bool RegionUS915ChannelsRemove( ChannelRemoveParams_t* channelRemove )
|
||||
{
|
||||
return LORAMAC_STATUS_PARAMETER_INVALID;
|
||||
}
|
||||
|
||||
void RegionUS915SetContinuousWave( ContinuousWaveParams_t* continuousWave )
|
||||
{
|
||||
int8_t txPowerLimited = LimitTxPower( continuousWave->TxPower, Bands[Channels[continuousWave->Channel].Band].TxMaxPower, continuousWave->Datarate, ChannelsMask );
|
||||
int8_t phyTxPower = 0;
|
||||
uint32_t frequency = Channels[continuousWave->Channel].Frequency;
|
||||
|
||||
// Calculate physical TX power
|
||||
phyTxPower = RegionCommonComputeTxPower( txPowerLimited, US915_DEFAULT_MAX_ERP, 0 );
|
||||
|
||||
Radio.SetTxContinuousWave( frequency, phyTxPower, continuousWave->Timeout );
|
||||
}
|
||||
|
||||
uint8_t RegionUS915ApplyDrOffset( uint8_t downlinkDwellTime, int8_t dr, int8_t drOffset )
|
||||
{
|
||||
int8_t datarate = DatarateOffsetsUS915[dr][drOffset];
|
||||
|
||||
if( datarate < 0 )
|
||||
{
|
||||
datarate = DR_0;
|
||||
}
|
||||
return datarate;
|
||||
}
|
||||
|
|
@ -0,0 +1,452 @@
|
|||
/*
|
||||
* Copyright (C) 2015-2017 Alibaba Group Holding Limited
|
||||
*/
|
||||
|
||||
/*!
|
||||
* \file RegionUS915.h
|
||||
*
|
||||
* \brief Region definition for US915
|
||||
*
|
||||
* \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 REGIONUS915 Region US915
|
||||
* Implementation according to LoRaWAN Specification v1.0.2.
|
||||
* \{
|
||||
*/
|
||||
#ifndef __REGION_US915_H__
|
||||
#define __REGION_US915_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
|
||||
*/
|
||||
#define US915_MIN_TX_POWER TX_POWER_10
|
||||
|
||||
/*!
|
||||
* 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
|
||||
|
||||
/*!
|
||||
* LoRaMac maximum number of bands
|
||||
*/
|
||||
#define US915_MAX_NB_BANDS 1
|
||||
|
||||
/*!
|
||||
* Band 0 definition
|
||||
* { DutyCycle, TxMaxPower, LastTxDoneTime, TimeOff }
|
||||
*/
|
||||
#define US915_BAND0 { 1, US915_MAX_TX_POWER, 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( InitType_t type );
|
||||
|
||||
/*!
|
||||
* \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 );
|
||||
|
||||
/*!
|
||||
* \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 RegionUS915AdrNext( AdrNextParams_t* adrNext, int8_t* drOut, int8_t* txPowOut, uint32_t* adrAckCounter );
|
||||
|
||||
/*!
|
||||
* 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] alternateDr Pointer to the function parameters.
|
||||
*
|
||||
* \retval Datarate to apply.
|
||||
*/
|
||||
int8_t RegionUS915AlternateDr( AlternateDrParams_t* alternateDr );
|
||||
|
||||
/*!
|
||||
* \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]
|
||||
*/
|
||||
bool 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 );
|
||||
|
||||
/*! \} defgroup REGIONUS915 */
|
||||
|
||||
#endif // __REGION_US915_H__
|
||||
359
Living_SDK/kernel/protocols/lorawan/lora/radio/radio.h
Normal file
359
Living_SDK/kernel/protocols/lorawan/lora/radio/radio.h
Normal file
|
|
@ -0,0 +1,359 @@
|
|||
/*
|
||||
* Copyright (C) 2015-2017 Alibaba Group Holding Limited
|
||||
*/
|
||||
|
||||
/*
|
||||
/ _____) _ | |
|
||||
( (____ _____ ____ _| |_ _____ ____| |__
|
||||
\____ \| ___ | (_ _) ___ |/ ___) _ \
|
||||
_____) ) ____| | | || |_| ____( (___| | | |
|
||||
(______/|_____)_|_|_| \__)_____)\____)_| |_|
|
||||
(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
|
||||
*/
|
||||
#ifndef __RADIO_H__
|
||||
#define __RADIO_H__
|
||||
|
||||
/*!
|
||||
* Radio driver supported modems
|
||||
*/
|
||||
typedef enum
|
||||
{
|
||||
MODEM_FSK = 0,
|
||||
MODEM_LORA,
|
||||
}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 Raw SNR value given by the radio hardware
|
||||
* 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 radio
|
||||
*
|
||||
* \param [IN] events Structure containing the driver callback functions
|
||||
*/
|
||||
void ( *IoInit )( void );
|
||||
|
||||
/*!
|
||||
* \brief Initializes the radio
|
||||
*
|
||||
* \param [IN] events Structure containing the driver callback functions
|
||||
*/
|
||||
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 Sets the channels configuration
|
||||
*
|
||||
* \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 )( uint8_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 )( uint8_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 )( uint8_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 )( uint8_t addr, uint8_t *buffer, uint8_t size );
|
||||
/*!
|
||||
* \brief Set synchro word in radio
|
||||
*
|
||||
* \param [IN] data THe syncword
|
||||
*/
|
||||
void ( *SetSyncWord )( uint8_t data );
|
||||
|
||||
/*!
|
||||
* \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 Service to get the radio wake-up time.
|
||||
*
|
||||
* \retval Value of the radio wake-up time.
|
||||
*/
|
||||
uint32_t ( *GetRadioWakeUpTime ) ( void );
|
||||
|
||||
};
|
||||
|
||||
/*!
|
||||
* \brief Radio driver
|
||||
*
|
||||
* \remark This variable is defined and initialized in the specific radio
|
||||
* board implementation
|
||||
*/
|
||||
extern const struct Radio_s Radio;
|
||||
|
||||
#endif // __RADIO_H__
|
||||
723
Living_SDK/kernel/protocols/lorawan/lora/readme.md
Normal file
723
Living_SDK/kernel/protocols/lorawan/lora/readme.md
Normal file
|
|
@ -0,0 +1,723 @@
|
|||
/ _____) _ | |
|
||||
( (____ _____ ____ _| |_ _____ ____| |__
|
||||
\____ \| ___ | (_ _) ___ |/ ___) _ \
|
||||
_____) ) ____| | | || |_| ____( (___| | | |
|
||||
(______/|_____)_|_|_| \__)_____)\____)_| |_|
|
||||
(C)2013 Semtech
|
||||
|
||||
LoRaWAN endpoint stack implementation and example projects.
|
||||
=====================================
|
||||
|
||||
1. Introduction
|
||||
----------------
|
||||
The aim of this project is to show an example of the endpoint LoRaWAN stack implementation.
|
||||
|
||||
This LoRaWAN stack is an EU868 and US915 bands Class A and Class C endpoint implementation
|
||||
fully compatible with LoRaWAN 1.0.1 specification.
|
||||
Each LoRaWAN application example includes the LoRaWAN certification protocol implementation.
|
||||
|
||||
SX1272/76 radio drivers are also provided.
|
||||
In case only point to point links are required a Ping-Pong application is provided as example.
|
||||
|
||||
*The LoRaWAN stack API documentation can be found at: http://stackforce.github.io/LoRaMac-doc/*
|
||||
|
||||
**Note 1:**
|
||||
|
||||
*A port of this project can be found on [MBED Semtech Team page](http://developer.mbed.org/teams/Semtech/)*
|
||||
|
||||
*The example projects are:*
|
||||
|
||||
1. [LoRaWAN-demo-72](http://developer.mbed.org/teams/Semtech/code/LoRaWAN-demo-72/)
|
||||
2. [LoRaWAN-demo-76](http://developer.mbed.org/teams/Semtech/code/LoRaWAN-demo-76/)
|
||||
|
||||
|
||||
2. System schematic and definitions
|
||||
------------------------------------
|
||||
The available supported hardware platforms schematics can be found in the Doc directory.
|
||||
|
||||
3. 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.
|
||||
|
||||
4. Dependencies
|
||||
----------------
|
||||
This program depends on specific hardware platforms. Currently the supported
|
||||
platforms are:
|
||||
|
||||
- LoRaMote
|
||||
MCU : STM32L151CB - 128K FLASH, 10K RAM, Timers, SPI, I2C,
|
||||
USART,
|
||||
USB 2.0 full-speed device/host/OTG controller,
|
||||
DAC, ADC, DMA
|
||||
RADIO : SX1272
|
||||
ANTENNA : Printed circuit antenna
|
||||
BUTTONS : No
|
||||
LEDS : 3
|
||||
SENSORS : Proximity, Magnetic, 3 axis Accelerometer, Pressure,
|
||||
Temperature
|
||||
GPS : Yes, UP501 module
|
||||
EXTENSION HEADER : Yes, 20 pins
|
||||
REMARK : The MCU and Radio are on an IMST iM880A module
|
||||
|
||||
- MoteII
|
||||
MCU : STM32L051C8 - 64K FLASH, 8K RAM, Timers, SPI, I2C,
|
||||
USART,
|
||||
USB 2.0 full-speed device/host/OTG controller (Not used),
|
||||
DAC, ADC, DMA
|
||||
RADIO : SX1272
|
||||
ANTENNA : Printed circuit antenna
|
||||
BUTTONS : 3
|
||||
LEDS : 3
|
||||
SENSORS : Magnetic, 3 axis Accelerometer, Pressure,
|
||||
Temperature
|
||||
GPS : Yes, PAM7Q module
|
||||
Display : OLED
|
||||
ST-Link : Yes, MBED like
|
||||
EXTENSION HEADER : Yes, 20 pins
|
||||
REMARK : The MCU and Radio are on an IMST iM881A module
|
||||
|
||||
- NAMote72
|
||||
MCU : STM32L152RC - 256K FLASH, 32K RAM, Timers, SPI, I2C,
|
||||
USART,
|
||||
USB 2.0 full-speed device/host/OTG controller (Not used),
|
||||
DAC, ADC, DMA
|
||||
RADIO : SX1272
|
||||
ANTENNA : Printed circuit antenna
|
||||
BUTTONS : No
|
||||
LEDS : 4
|
||||
SENSORS : Magnetic, 3 axis Accelerometer, Pressure,
|
||||
Temperature
|
||||
GPS : Yes, SIM39EA module
|
||||
Display : OLED
|
||||
ST-Link : Yes, MBED like
|
||||
EXTENSION HEADER : Yes, Arduino connectors
|
||||
REMARK : None
|
||||
|
||||
- SensorNode
|
||||
MCU : STM32L151CBU6 - 128K FLASH, 16K RAM, Timers, SPI, I2C,
|
||||
USART,
|
||||
USB 2.0 full-speed device/host/OTG controller,
|
||||
DAC, ADC, DMA
|
||||
RADIO : SX1276
|
||||
ANTENNA : Printed circuit antenna
|
||||
BUTTONS : Power ON/OFF, General purpose button
|
||||
LEDS : 3
|
||||
SENSORS : Proximity, Magnetic, 3 axis Accelerometer, Pressure,
|
||||
Temperature
|
||||
GPS : Yes, SIM39EA module
|
||||
EXTENSION No
|
||||
REMARK : The MCU and Radio are on an NYMTEK Cherry-LCC module
|
||||
|
||||
- SK-iM880A ( IMST starter kit )
|
||||
MCU : STM32L151CB - 128K FLASH, 10K RAM, Timers, SPI, I2C,
|
||||
USART,
|
||||
USB 2.0 full-speed device/host/OTG controller,
|
||||
DAC, ADC, DMA
|
||||
RADIO : SX1272
|
||||
ANTENNA : Connector for external antenna
|
||||
BUTTONS : 1 Reset, 3 buttons + 2 DIP-Switch
|
||||
LEDS : 3
|
||||
SENSORS : Potentiometer
|
||||
GPS : Possible through pin header GPS module connection
|
||||
SDCARD : No
|
||||
EXTENSION HEADER : Yes, all IMST iM880A module pins
|
||||
REMARK : None
|
||||
|
||||
5. Usage
|
||||
---------
|
||||
Projects for CooCox-CoIDE and Keil Integrated Development Environments are available.
|
||||
|
||||
One project is available per application and for each hardware platform in each
|
||||
development environment. Different targets/configurations have been created in
|
||||
the different projects in order to select different options such as the usage or
|
||||
not of a bootloader and the radio frequency band to be used.
|
||||
|
||||
6. Changelog
|
||||
-------------
|
||||
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.
|
||||
|
||||
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 behaviour
|
||||
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.
|
||||
|
||||
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.
|
||||
|
||||
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.
|
||||
|
||||
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.
|
||||
936
Living_SDK/kernel/protocols/lorawan/lora/system/crypto/aes.c
Normal file
936
Living_SDK/kernel/protocols/lorawan/lora/system/crypto/aes.c
Normal 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 0
|
||||
# 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
|
||||
160
Living_SDK/kernel/protocols/lorawan/lora/system/crypto/aes.h
Normal file
160
Living_SDK/kernel/protocols/lorawan/lora/system/crypto/aes.h
Normal file
|
|
@ -0,0 +1,160 @@
|
|||
/*
|
||||
---------------------------------------------------------------------------
|
||||
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
|
||||
|
||||
#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
|
||||
153
Living_SDK/kernel/protocols/lorawan/lora/system/crypto/cmac.c
Normal file
153
Living_SDK/kernel/protocols/lorawan/lora/system/crypto/cmac.c
Normal 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);
|
||||
|
||||
}
|
||||
|
||||
|
|
@ -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 {
|
||||
uint32_t M_n;
|
||||
uint8_t X[16];
|
||||
uint8_t M_last[16];
|
||||
aes_context rijndael;
|
||||
} 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_ */
|
||||
|
||||
77
Living_SDK/kernel/protocols/lorawan/lora/system/delay.c
Normal file
77
Living_SDK/kernel/protocols/lorawan/lora/system/delay.c
Normal file
|
|
@ -0,0 +1,77 @@
|
|||
/*
|
||||
/ _____) _ | |
|
||||
( (____ _____ ____ _| |_ _____ ____| |__
|
||||
\____ \| ___ | (_ _) ___ |/ ___) _ \
|
||||
_____) ) ____| | | || |_| ____( (___| | | |
|
||||
(______/|_____)_|_|_| \__)_____)\____)_| |_|
|
||||
(C)2013 Semtech
|
||||
|
||||
Description: Delay functions implementation
|
||||
|
||||
License: Revised BSD License, see LICENSE.TXT file include in the project
|
||||
|
||||
Maintainer: Miguel Luis and Gregory Cristian
|
||||
*/
|
||||
/******************************************************************************
|
||||
* @file delay.c
|
||||
* @author MCD Application Team
|
||||
* @version V1.1.1
|
||||
* @date 01-June-2017
|
||||
* @brief Delay function
|
||||
******************************************************************************
|
||||
* @attention
|
||||
*
|
||||
* <h2><center>© Copyright (c) 2017 STMicroelectronics International N.V.
|
||||
* All rights reserved.</center></h2>
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted, provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistribution of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* 2. 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.
|
||||
* 3. Neither the name of STMicroelectronics nor the names of other
|
||||
* contributors to this software may be used to endorse or promote products
|
||||
* derived from this software without specific written permission.
|
||||
* 4. This software, including modifications and/or derivative works of this
|
||||
* software, must execute solely and exclusively on microcontroller or
|
||||
* microprocessor devices manufactured by or for STMicroelectronics.
|
||||
* 5. Redistribution and use of this software other than as permitted under
|
||||
* this license is void and will automatically terminate your rights under
|
||||
* this license.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY STMICROELECTRONICS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS, IMPLIED OR STATUTORY WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
|
||||
* PARTICULAR PURPOSE AND NON-INFRINGEMENT OF THIRD PARTY INTELLECTUAL PROPERTY
|
||||
* RIGHTS ARE DISCLAIMED TO THE FULLEST EXTENT PERMITTED BY LAW. IN NO EVENT
|
||||
* SHALL STMICROELECTRONICS OR CONTRIBUTORS 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.
|
||||
*
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
/* Includes ------------------------------------------------------------------*/
|
||||
#include "hw.h"
|
||||
#include "timeServer.h"
|
||||
#include "lorawan_port.h"
|
||||
|
||||
void DelayMs( uint32_t ms )
|
||||
{
|
||||
aos_lrwan_time_itf.delay_ms(ms);
|
||||
}
|
||||
|
||||
void Delay( float s )
|
||||
{
|
||||
DelayMs( (uint32_t) (s * 1000.0f) );
|
||||
}
|
||||
|
||||
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
|
||||
|
||||
33
Living_SDK/kernel/protocols/lorawan/lora/system/delay.h
Normal file
33
Living_SDK/kernel/protocols/lorawan/lora/system/delay.h
Normal file
|
|
@ -0,0 +1,33 @@
|
|||
/*
|
||||
* Copyright (C) 2015-2017 Alibaba Group Holding Limited
|
||||
*/
|
||||
|
||||
/*
|
||||
/ _____) _ | |
|
||||
( (____ _____ ____ _| |_ _____ ____| |__
|
||||
\____ \| ___ | (_ _) ___ |/ ___) _ \
|
||||
_____) ) ____| | | || |_| ____( (___| | | |
|
||||
(______/|_____)_|_|_| \__)_____)\____)_| |_|
|
||||
(C)2013 Semtech
|
||||
|
||||
Description: Delay functions implementation
|
||||
|
||||
License: Revised BSD License, see LICENSE.TXT file include in the project
|
||||
|
||||
Maintainer: Miguel Luis and Gregory Cristian
|
||||
*/
|
||||
#ifndef __DELAY_H__
|
||||
#define __DELAY_H__
|
||||
|
||||
/*!
|
||||
* Blocking delay of "s" seconds
|
||||
*/
|
||||
void Delay( float s );
|
||||
|
||||
/*!
|
||||
* Blocking delay of "ms" milliseconds
|
||||
*/
|
||||
void DelayMs( uint32_t ms );
|
||||
|
||||
#endif // __DELAY_H__
|
||||
|
||||
130
Living_SDK/kernel/protocols/lorawan/lora/system/low_power.c
Normal file
130
Living_SDK/kernel/protocols/lorawan/lora/system/low_power.c
Normal file
|
|
@ -0,0 +1,130 @@
|
|||
/*******************************************************************************
|
||||
* @file low_power.c
|
||||
* @author MCD Application Team
|
||||
* @version V1.1.1
|
||||
* @date 01-June-2017
|
||||
* @brief driver for low power
|
||||
******************************************************************************
|
||||
* @attention
|
||||
*
|
||||
* <h2><center>© Copyright (c) 2017 STMicroelectronics International N.V.
|
||||
* All rights reserved.</center></h2>
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted, provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistribution of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* 2. 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.
|
||||
* 3. Neither the name of STMicroelectronics nor the names of other
|
||||
* contributors to this software may be used to endorse or promote products
|
||||
* derived from this software without specific written permission.
|
||||
* 4. This software, including modifications and/or derivative works of this
|
||||
* software, must execute solely and exclusively on microcontroller or
|
||||
* microprocessor devices manufactured by or for STMicroelectronics.
|
||||
* 5. Redistribution and use of this software other than as permitted under
|
||||
* this license is void and will automatically terminate your rights under
|
||||
* this license.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY STMICROELECTRONICS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS, IMPLIED OR STATUTORY WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
|
||||
* PARTICULAR PURPOSE AND NON-INFRINGEMENT OF THIRD PARTY INTELLECTUAL PROPERTY
|
||||
* RIGHTS ARE DISCLAIMED TO THE FULLEST EXTENT PERMITTED BY LAW. IN NO EVENT
|
||||
* SHALL STMICROELECTRONICS OR CONTRIBUTORS 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.
|
||||
*
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
/* Includes ------------------------------------------------------------------*/
|
||||
#include "hw.h"
|
||||
#include "low_power.h"
|
||||
#include "lorawan_port.h"
|
||||
|
||||
/* Private typedef -----------------------------------------------------------*/
|
||||
/* Private define ------------------------------------------------------------*/
|
||||
/* Private macro -------------------------------------------------------------*/
|
||||
/* Private variables ---------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* \brief Flag to indicate if MCU can go to low power mode
|
||||
* When 0, MCU is authorized to go in low power mode
|
||||
*/
|
||||
static uint32_t LowPower_State = 0;
|
||||
|
||||
/* Private function prototypes -----------------------------------------------*/
|
||||
|
||||
|
||||
|
||||
/* Exported functions ---------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* \brief API to set flag allowing power mode
|
||||
*
|
||||
* \param [IN] enum e_LOW_POWER_State_Id_t
|
||||
*/
|
||||
void LowPower_Disable( e_LOW_POWER_State_Id_t state )
|
||||
{
|
||||
CPSR_ALLOC();
|
||||
RHINO_CPU_INTRPT_DISABLE();
|
||||
LowPower_State |= state;
|
||||
RHINO_CPU_INTRPT_ENABLE();
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief API to reset flag allowing power mode
|
||||
*
|
||||
* \param [IN] enum e_LOW_POWER_State_Id_t
|
||||
*/
|
||||
void LowPower_Enable( e_LOW_POWER_State_Id_t state )
|
||||
{
|
||||
CPSR_ALLOC();
|
||||
RHINO_CPU_INTRPT_DISABLE();
|
||||
LowPower_State &= ~state;
|
||||
RHINO_CPU_INTRPT_ENABLE();
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief API to get flag allowing power mode
|
||||
* \note When flag is 0, low power mode is allowed
|
||||
* \param [IN] state
|
||||
* \retval flag state
|
||||
*/
|
||||
uint32_t LowPower_GetState( void )
|
||||
{
|
||||
return LowPower_State;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Handle Low Power
|
||||
* @param None
|
||||
* @retval None
|
||||
*/
|
||||
|
||||
void LowPower_Handler( void )
|
||||
{
|
||||
CPSR_ALLOC();
|
||||
RHINO_CPU_INTRPT_DISABLE();
|
||||
|
||||
if (LowPower_State == 0) {
|
||||
aos_lrwan_chg_mode.enter_stop_mode();
|
||||
/* mcu dependent. to be implemented by user*/
|
||||
aos_lrwan_chg_mode.exit_stop_mode();
|
||||
aos_lrwan_time_itf.set_uc_wakeup_time();
|
||||
} else {
|
||||
aos_lrwan_chg_mode.enter_sleep_mode();
|
||||
}
|
||||
|
||||
RHINO_CPU_INTRPT_ENABLE();
|
||||
}
|
||||
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
|
||||
|
||||
|
||||
98
Living_SDK/kernel/protocols/lorawan/lora/system/low_power.h
Normal file
98
Living_SDK/kernel/protocols/lorawan/lora/system/low_power.h
Normal file
|
|
@ -0,0 +1,98 @@
|
|||
/******************************************************************************
|
||||
* @file low_power.h
|
||||
* @author MCD Application Team
|
||||
* @version V1.1.1
|
||||
* @date 01-June-2017
|
||||
* @brief Header for driver low_power.c module
|
||||
******************************************************************************
|
||||
* @attention
|
||||
*
|
||||
* <h2><center>© Copyright (c) 2017 STMicroelectronics International N.V.
|
||||
* All rights reserved.</center></h2>
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted, provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistribution of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* 2. 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.
|
||||
* 3. Neither the name of STMicroelectronics nor the names of other
|
||||
* contributors to this software may be used to endorse or promote products
|
||||
* derived from this software without specific written permission.
|
||||
* 4. This software, including modifications and/or derivative works of this
|
||||
* software, must execute solely and exclusively on microcontroller or
|
||||
* microprocessor devices manufactured by or for STMicroelectronics.
|
||||
* 5. Redistribution and use of this software other than as permitted under
|
||||
* this license is void and will automatically terminate your rights under
|
||||
* this license.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY STMICROELECTRONICS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS, IMPLIED OR STATUTORY WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
|
||||
* PARTICULAR PURPOSE AND NON-INFRINGEMENT OF THIRD PARTY INTELLECTUAL PROPERTY
|
||||
* RIGHTS ARE DISCLAIMED TO THE FULLEST EXTENT PERMITTED BY LAW. IN NO EVENT
|
||||
* SHALL STMICROELECTRONICS OR CONTRIBUTORS 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.
|
||||
*
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
/* Define to prevent recursive inclusion -------------------------------------*/
|
||||
#ifndef __LOW_POWER_H__
|
||||
#define __LOW_POWER_H__
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* Includes ------------------------------------------------------------------*/
|
||||
/* Exported types ------------------------------------------------------------*/
|
||||
/* Exported constants --------------------------------------------------------*/
|
||||
/* External variables --------------------------------------------------------*/
|
||||
/* Exported macros -----------------------------------------------------------*/
|
||||
/* Exported functions ------------------------------------------------------- */
|
||||
|
||||
/*!
|
||||
* @brief API to set flag allowing power mode
|
||||
*
|
||||
* @param [IN] enum e_LOW_POWER_State_Id_t
|
||||
*/
|
||||
void LowPower_Disable( e_LOW_POWER_State_Id_t state );
|
||||
|
||||
/*!
|
||||
* @brief API to reset flag allowing power mode
|
||||
*
|
||||
* @param [IN] enum e_LOW_POWER_State_Id_t
|
||||
*/
|
||||
|
||||
void LowPower_Enable( e_LOW_POWER_State_Id_t state );
|
||||
|
||||
/*!
|
||||
* @brief API to get flag allowing power mode
|
||||
* @note When flag is 0, low power mode is allowed
|
||||
* @param [IN] non
|
||||
* @retval flag state
|
||||
*/
|
||||
uint32_t LowPower_GetState( void );
|
||||
|
||||
/*!
|
||||
* @brief Manages the entry into ARM cortex deep-sleep mode
|
||||
* @param none
|
||||
* @retval none
|
||||
*/
|
||||
void LowPower_Handler( void );
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __LOW_POWER_H__ */
|
||||
|
||||
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
|
||||
10
Living_SDK/kernel/protocols/lorawan/lora/system/precision.h
Normal file
10
Living_SDK/kernel/protocols/lorawan/lora/system/precision.h
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
/*
|
||||
* Copyright (C) 2015-2017 Alibaba Group Holding Limited
|
||||
*/
|
||||
|
||||
#ifndef LORAWAN_SYSTEM_PRECISION_H
|
||||
#define LORAWAN_SYSTEM_PRECISION_H
|
||||
|
||||
#define DECIMAL float
|
||||
|
||||
#endif // LORAWAN_SYSTEM_PRECISION_H
|
||||
378
Living_SDK/kernel/protocols/lorawan/lora/system/timeServer.c
Normal file
378
Living_SDK/kernel/protocols/lorawan/lora/system/timeServer.c
Normal file
|
|
@ -0,0 +1,378 @@
|
|||
/*
|
||||
/ _____) _ | |
|
||||
( (____ _____ ____ _| |_ _____ ____| |__
|
||||
\____ \| ___ | (_ _) ___ |/ ___) _ \
|
||||
_____) ) ____| | | || |_| ____( (___| | | |
|
||||
(______/|_____)_|_|_| \__)_____)\____)_| |_|
|
||||
(C)2013 Semtech
|
||||
|
||||
Description: Generic lora driver implementation
|
||||
|
||||
License: Revised BSD License, see LICENSE.TXT file include in the project
|
||||
|
||||
Maintainer: Miguel Luis, Gregory Cristian and Wael Guibene
|
||||
*/
|
||||
/******************************************************************************
|
||||
* @file timeserver.c
|
||||
* @author MCD Application Team
|
||||
* @version V1.1.1
|
||||
* @date 01-June-2017
|
||||
* @brief Time server infrastructure
|
||||
******************************************************************************
|
||||
* @attention
|
||||
*
|
||||
* <h2><center>© Copyright (c) 2017 STMicroelectronics International N.V.
|
||||
* All rights reserved.</center></h2>
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted, provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistribution of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* 2. 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.
|
||||
* 3. Neither the name of STMicroelectronics nor the names of other
|
||||
* contributors to this software may be used to endorse or promote products
|
||||
* derived from this software without specific written permission.
|
||||
* 4. This software, including modifications and/or derivative works of this
|
||||
* software, must execute solely and exclusively on microcontroller or
|
||||
* microprocessor devices manufactured by or for STMicroelectronics.
|
||||
* 5. Redistribution and use of this software other than as permitted under
|
||||
* this license is void and will automatically terminate your rights under
|
||||
* this license.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY STMICROELECTRONICS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS, IMPLIED OR STATUTORY WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
|
||||
* PARTICULAR PURPOSE AND NON-INFRINGEMENT OF THIRD PARTY INTELLECTUAL PROPERTY
|
||||
* RIGHTS ARE DISCLAIMED TO THE FULLEST EXTENT PERMITTED BY LAW. IN NO EVENT
|
||||
* SHALL STMICROELECTRONICS OR CONTRIBUTORS 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.
|
||||
*
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
/* Includes ------------------------------------------------------------------*/
|
||||
#include <time.h>
|
||||
#include "hw.h"
|
||||
#include "timeServer.h"
|
||||
#include "lorawan_port.h"
|
||||
|
||||
/*!
|
||||
* safely execute call back
|
||||
*/
|
||||
#define exec_cb( _callback_ ) \
|
||||
do \
|
||||
{ \
|
||||
if( _callback_ == NULL ) \
|
||||
{ \
|
||||
while(1); \
|
||||
} \
|
||||
else \
|
||||
{ \
|
||||
_callback_( ); \
|
||||
} \
|
||||
} while(0);
|
||||
|
||||
|
||||
|
||||
/*!
|
||||
* Timers list head pointer
|
||||
*/
|
||||
static TimerEvent_t *TimerListHead = NULL;
|
||||
|
||||
/*!
|
||||
* \brief Adds or replace the head timer of the list.
|
||||
*
|
||||
* \remark The list is automatically sorted. The list head always contains the
|
||||
* next timer to expire.
|
||||
*
|
||||
* \param [IN] obj Timer object to be become the new head
|
||||
* \param [IN] remainingTime Remaining time of the previous head to be replaced
|
||||
*/
|
||||
static void TimerInsertNewHeadTimer( TimerEvent_t *obj );
|
||||
|
||||
/*!
|
||||
* \brief Adds a timer to the list.
|
||||
*
|
||||
* \remark The list is automatically sorted. The list head always contains the
|
||||
* next timer to expire.
|
||||
*
|
||||
* \param [IN] obj Timer object to be added to the list
|
||||
* \param [IN] remainingTime Remaining time of the running head after which the object may be added
|
||||
*/
|
||||
static void TimerInsertTimer( TimerEvent_t *obj );
|
||||
|
||||
/*!
|
||||
* \brief Sets a timeout with the duration "timestamp"
|
||||
*
|
||||
* \param [IN] timestamp Delay duration
|
||||
*/
|
||||
static void TimerSetTimeout( TimerEvent_t *obj );
|
||||
|
||||
/*!
|
||||
* \brief Check if the Object to be added is not already in the list
|
||||
*
|
||||
* \param [IN] timestamp Delay duration
|
||||
* \retval true (the object is already in the list) or false
|
||||
*/
|
||||
static bool TimerExists( TimerEvent_t *obj );
|
||||
|
||||
|
||||
|
||||
void TimerInit( TimerEvent_t *obj, void ( *callback )( void ) )
|
||||
{
|
||||
obj->Timestamp = 0;
|
||||
obj->ReloadValue = 0;
|
||||
obj->IsRunning = false;
|
||||
obj->Callback = callback;
|
||||
obj->Next = NULL;
|
||||
}
|
||||
|
||||
void TimerStart( TimerEvent_t *obj )
|
||||
{
|
||||
uint32_t elapsedTime = 0;
|
||||
CPSR_ALLOC();
|
||||
RHINO_CPU_INTRPT_DISABLE();
|
||||
|
||||
if( ( obj == NULL ) || ( TimerExists( obj ) == true ) )
|
||||
{
|
||||
RHINO_CPU_INTRPT_ENABLE();
|
||||
return;
|
||||
}
|
||||
|
||||
obj->Timestamp = obj->ReloadValue;
|
||||
obj->IsRunning = false;
|
||||
|
||||
if( TimerListHead == NULL )
|
||||
{
|
||||
aos_lrwan_time_itf.set_timer_context();
|
||||
TimerInsertNewHeadTimer( obj ); // insert a timeout at now+obj->Timestamp
|
||||
}
|
||||
else
|
||||
{
|
||||
elapsedTime = aos_lrwan_time_itf.get_timer_elapsed_time();
|
||||
obj->Timestamp += elapsedTime;
|
||||
|
||||
if( obj->Timestamp < TimerListHead->Timestamp )
|
||||
{
|
||||
TimerInsertNewHeadTimer( obj);
|
||||
}
|
||||
else
|
||||
{
|
||||
TimerInsertTimer( obj);
|
||||
}
|
||||
}
|
||||
RHINO_CPU_INTRPT_ENABLE();
|
||||
}
|
||||
|
||||
static void TimerInsertTimer( TimerEvent_t *obj)
|
||||
{
|
||||
TimerEvent_t* cur = TimerListHead;
|
||||
TimerEvent_t* next = TimerListHead->Next;
|
||||
|
||||
while (cur->Next != NULL )
|
||||
{
|
||||
if( obj->Timestamp > next->Timestamp )
|
||||
{
|
||||
cur = next;
|
||||
next = next->Next;
|
||||
}
|
||||
else
|
||||
{
|
||||
cur->Next = obj;
|
||||
obj->Next = next;
|
||||
return;
|
||||
|
||||
}
|
||||
}
|
||||
cur->Next = obj;
|
||||
obj->Next = NULL;
|
||||
}
|
||||
|
||||
static void TimerInsertNewHeadTimer( TimerEvent_t *obj )
|
||||
{
|
||||
TimerEvent_t* cur = TimerListHead;
|
||||
|
||||
if( cur != NULL )
|
||||
{
|
||||
cur->IsRunning = false;
|
||||
}
|
||||
|
||||
obj->Next = cur;
|
||||
TimerListHead = obj;
|
||||
TimerSetTimeout( TimerListHead );
|
||||
}
|
||||
|
||||
void TimerIrqHandler( void )
|
||||
{
|
||||
TimerEvent_t* cur;
|
||||
TimerEvent_t* next;
|
||||
|
||||
uint32_t old = aos_lrwan_time_itf.get_timer_context();
|
||||
uint32_t now = aos_lrwan_time_itf.set_timer_context();
|
||||
uint32_t DeltaContext = now - old; //intentionnal wrap around
|
||||
|
||||
/* update timeStamp based upon new Time Reference*/
|
||||
/* beacuse delta context should never exceed 2^32*/
|
||||
if ( TimerListHead != NULL )
|
||||
{
|
||||
for (cur=TimerListHead; cur->Next != NULL; cur= cur->Next)
|
||||
{
|
||||
next =cur->Next;
|
||||
if (next->Timestamp > DeltaContext)
|
||||
{
|
||||
next->Timestamp -= DeltaContext;
|
||||
}
|
||||
else
|
||||
{
|
||||
next->Timestamp = 0 ;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* execute imediately the alarm callback */
|
||||
if ( TimerListHead != NULL )
|
||||
{
|
||||
cur = TimerListHead;
|
||||
TimerListHead = TimerListHead->Next;
|
||||
exec_cb( cur->Callback );
|
||||
}
|
||||
|
||||
|
||||
// remove all the expired object from the list
|
||||
while( ( TimerListHead != NULL ) && ( TimerListHead->Timestamp < aos_lrwan_time_itf.get_timer_elapsed_time( ) ))
|
||||
{
|
||||
cur = TimerListHead;
|
||||
TimerListHead = TimerListHead->Next;
|
||||
exec_cb( cur->Callback );
|
||||
}
|
||||
|
||||
/* start the next TimerListHead if it exists AND NOT running */
|
||||
if(( TimerListHead != NULL ) && (TimerListHead->IsRunning == false))
|
||||
{
|
||||
TimerSetTimeout( TimerListHead );
|
||||
}
|
||||
}
|
||||
|
||||
void TimerStop( TimerEvent_t *obj )
|
||||
{
|
||||
CPSR_ALLOC();
|
||||
RHINO_CPU_INTRPT_DISABLE();
|
||||
|
||||
TimerEvent_t* prev = TimerListHead;
|
||||
TimerEvent_t* cur = TimerListHead;
|
||||
|
||||
// List is empty or the Obj to stop does not exist
|
||||
if( ( TimerListHead == NULL ) || ( obj == NULL ) )
|
||||
{
|
||||
RHINO_CPU_INTRPT_ENABLE();
|
||||
return;
|
||||
}
|
||||
|
||||
if( TimerListHead == obj ) // Stop the Head
|
||||
{
|
||||
if( TimerListHead->IsRunning == true ) // The head is already running
|
||||
{
|
||||
if( TimerListHead->Next != NULL )
|
||||
{
|
||||
TimerListHead->IsRunning = false;
|
||||
TimerListHead = TimerListHead->Next;
|
||||
TimerSetTimeout( TimerListHead );
|
||||
}
|
||||
else
|
||||
{
|
||||
aos_lrwan_time_itf.stop_alarm( );
|
||||
TimerListHead = NULL;
|
||||
}
|
||||
}
|
||||
else // Stop the head before it is started
|
||||
{
|
||||
if( TimerListHead->Next != NULL )
|
||||
{
|
||||
TimerListHead = TimerListHead->Next;
|
||||
}
|
||||
else
|
||||
{
|
||||
TimerListHead = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
else // Stop an object within the list
|
||||
{
|
||||
while( cur != NULL )
|
||||
{
|
||||
if( cur == obj )
|
||||
{
|
||||
if( cur->Next != NULL )
|
||||
{
|
||||
cur = cur->Next;
|
||||
prev->Next = cur;
|
||||
}
|
||||
else
|
||||
{
|
||||
cur = NULL;
|
||||
prev->Next = cur;
|
||||
}
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
prev = cur;
|
||||
cur = cur->Next;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
RHINO_CPU_INTRPT_ENABLE();
|
||||
}
|
||||
|
||||
static bool TimerExists( TimerEvent_t *obj )
|
||||
{
|
||||
TimerEvent_t* cur = TimerListHead;
|
||||
|
||||
while( cur != NULL )
|
||||
{
|
||||
if( cur == obj )
|
||||
{
|
||||
return true;
|
||||
}
|
||||
cur = cur->Next;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void TimerReset( TimerEvent_t *obj )
|
||||
{
|
||||
TimerStop( obj );
|
||||
TimerStart( obj );
|
||||
}
|
||||
|
||||
void TimerSetValue( TimerEvent_t *obj, uint32_t value )
|
||||
{
|
||||
TimerStop( obj );
|
||||
|
||||
aos_lrwan_time_itf.set_timer_val(obj, value);
|
||||
}
|
||||
|
||||
TimerTime_t TimerGetCurrentTime( void )
|
||||
{
|
||||
return aos_lrwan_time_itf.get_current_time();
|
||||
}
|
||||
|
||||
TimerTime_t TimerGetElapsedTime( TimerTime_t past )
|
||||
{
|
||||
return aos_lrwan_time_itf.compute_elapsed_time(past);
|
||||
}
|
||||
|
||||
static void TimerSetTimeout( TimerEvent_t *obj )
|
||||
{
|
||||
aos_lrwan_time_itf.set_timeout(obj);
|
||||
}
|
||||
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
|
||||
164
Living_SDK/kernel/protocols/lorawan/lora/system/timeServer.h
Normal file
164
Living_SDK/kernel/protocols/lorawan/lora/system/timeServer.h
Normal file
|
|
@ -0,0 +1,164 @@
|
|||
/*
|
||||
/ _____) _ | |
|
||||
( (____ _____ ____ _| |_ _____ ____| |__
|
||||
\____ \| ___ | (_ _) ___ |/ ___) _ \
|
||||
_____) ) ____| | | || |_| ____( (___| | | |
|
||||
(______/|_____)_|_|_| \__)_____)\____)_| |_|
|
||||
(C)2013 Semtech
|
||||
|
||||
Description: Timer objects and scheduling management
|
||||
|
||||
License: Revised BSD License, see LICENSE.TXT file include in the project
|
||||
|
||||
Maintainer: Miguel Luis and Gregory Cristian
|
||||
*/
|
||||
/******************************************************************************
|
||||
* @file timeServer.h
|
||||
* @author MCD Application Team
|
||||
* @version V1.1.1
|
||||
* @date 01-June-2017
|
||||
* @brief is the timer server driver
|
||||
******************************************************************************
|
||||
* @attention
|
||||
*
|
||||
* <h2><center>© Copyright (c) 2017 STMicroelectronics International N.V.
|
||||
* All rights reserved.</center></h2>
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted, provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistribution of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* 2. 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.
|
||||
* 3. Neither the name of STMicroelectronics nor the names of other
|
||||
* contributors to this software may be used to endorse or promote products
|
||||
* derived from this software without specific written permission.
|
||||
* 4. This software, including modifications and/or derivative works of this
|
||||
* software, must execute solely and exclusively on microcontroller or
|
||||
* microprocessor devices manufactured by or for STMicroelectronics.
|
||||
* 5. Redistribution and use of this software other than as permitted under
|
||||
* this license is void and will automatically terminate your rights under
|
||||
* this license.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY STMICROELECTRONICS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS, IMPLIED OR STATUTORY WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
|
||||
* PARTICULAR PURPOSE AND NON-INFRINGEMENT OF THIRD PARTY INTELLECTUAL PROPERTY
|
||||
* RIGHTS ARE DISCLAIMED TO THE FULLEST EXTENT PERMITTED BY LAW. IN NO EVENT
|
||||
* SHALL STMICROELECTRONICS OR CONTRIBUTORS 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.
|
||||
*
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
/* Define to prevent recursive inclusion -------------------------------------*/
|
||||
#ifndef __TIMESERVER_H__
|
||||
#define __TIMESERVER_H__
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* Includes ------------------------------------------------------------------*/
|
||||
|
||||
#include "utilities.h"
|
||||
|
||||
/* Exported types ------------------------------------------------------------*/
|
||||
|
||||
/*!
|
||||
* \brief Timer object description
|
||||
*/
|
||||
typedef struct TimerEvent_s
|
||||
{
|
||||
uint32_t Timestamp; //! Expiring timer value in ticks from TimerContext
|
||||
uint32_t ReloadValue; //! Reload Value when Timer is restarted
|
||||
bool IsRunning; //! Is the timer currently running
|
||||
void ( *Callback )( void ); //! Timer IRQ callback function
|
||||
struct TimerEvent_s *Next; //! Pointer to the next Timer object.
|
||||
} TimerEvent_t;
|
||||
|
||||
|
||||
/* Exported constants --------------------------------------------------------*/
|
||||
/* External variables --------------------------------------------------------*/
|
||||
/* Exported macros -----------------------------------------------------------*/
|
||||
/* Exported functions ------------------------------------------------------- */
|
||||
|
||||
/*!
|
||||
* \brief Initializes the timer object
|
||||
*
|
||||
* \remark TimerSetValue function must be called before starting the timer.
|
||||
* this function initializes timestamp and reload value at 0.
|
||||
*
|
||||
* \param [IN] obj Structure containing the timer object parameters
|
||||
* \param [IN] callback Function callback called at the end of the timeout
|
||||
*/
|
||||
void TimerInit( TimerEvent_t *obj, void ( *callback )( void ) );
|
||||
|
||||
/*!
|
||||
* \brief Timer IRQ event handler
|
||||
*
|
||||
* \note Head Timer Object is automaitcally removed from the List
|
||||
*
|
||||
* \note e.g. it is snot needded to stop it
|
||||
*/
|
||||
void TimerIrqHandler( void );
|
||||
|
||||
/*!
|
||||
* \brief Starts and adds the timer object to the list of timer events
|
||||
*
|
||||
* \param [IN] obj Structure containing the timer object parameters
|
||||
*/
|
||||
void TimerStart( TimerEvent_t *obj );
|
||||
|
||||
/*!
|
||||
* \brief Stops and removes the timer object from the list of timer events
|
||||
*
|
||||
* \param [IN] obj Structure containing the timer object parameters
|
||||
*/
|
||||
void TimerStop( TimerEvent_t *obj );
|
||||
|
||||
/*!
|
||||
* \brief Resets the timer object
|
||||
*
|
||||
* \param [IN] obj Structure containing the timer object parameters
|
||||
*/
|
||||
void TimerReset( TimerEvent_t *obj );
|
||||
|
||||
/*!
|
||||
* \brief Set timer new timeout value
|
||||
*
|
||||
* \param [IN] obj Structure containing the timer object parameters
|
||||
* \param [IN] value New timer timeout value
|
||||
*/
|
||||
void TimerSetValue( TimerEvent_t *obj, uint32_t value );
|
||||
|
||||
|
||||
/*!
|
||||
* \brief Read the current time
|
||||
*
|
||||
* \retval returns current time in ms
|
||||
*/
|
||||
TimerTime_t TimerGetCurrentTime( void );
|
||||
|
||||
/*!
|
||||
* \brief Return the Time elapsed since a fix moment in Time
|
||||
*
|
||||
* \param [IN] savedTime fix moment in Time
|
||||
* \retval time returns elapsed time in ms
|
||||
*/
|
||||
TimerTime_t TimerGetElapsedTime( TimerTime_t savedTime );
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __TIMESERVER_H__*/
|
||||
|
||||
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
|
||||
86
Living_SDK/kernel/protocols/lorawan/lora/system/timer.h
Normal file
86
Living_SDK/kernel/protocols/lorawan/lora/system/timer.h
Normal file
|
|
@ -0,0 +1,86 @@
|
|||
/*
|
||||
/ _____) _ | |
|
||||
( (____ _____ ____ _| |_ _____ ____| |__
|
||||
\____ \| ___ | (_ _) ___ |/ ___) _ \
|
||||
_____) ) ____| | | || |_| ____( (___| | | |
|
||||
(______/|_____)_|_|_| \__)_____)\____)_| |_|
|
||||
(C)2013 Semtech
|
||||
|
||||
Description: Timer objects and scheduling management
|
||||
|
||||
License: Revised BSD License, see LICENSE.TXT file include in the project
|
||||
|
||||
Maintainer: Miguel Luis and Gregory Cristian
|
||||
*/
|
||||
/******************************************************************************
|
||||
* @file timer.h
|
||||
* @author MCD Application Team
|
||||
* @version V1.1.1
|
||||
* @date 01-June-2017
|
||||
* @brief wrapper to timer server
|
||||
******************************************************************************
|
||||
* @attention
|
||||
*
|
||||
* <h2><center>© Copyright (c) 2017 STMicroelectronics International N.V.
|
||||
* All rights reserved.</center></h2>
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted, provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistribution of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* 2. 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.
|
||||
* 3. Neither the name of STMicroelectronics nor the names of other
|
||||
* contributors to this software may be used to endorse or promote products
|
||||
* derived from this software without specific written permission.
|
||||
* 4. This software, including modifications and/or derivative works of this
|
||||
* software, must execute solely and exclusively on microcontroller or
|
||||
* microprocessor devices manufactured by or for STMicroelectronics.
|
||||
* 5. Redistribution and use of this software other than as permitted under
|
||||
* this license is void and will automatically terminate your rights under
|
||||
* this license.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY STMICROELECTRONICS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS, IMPLIED OR STATUTORY WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
|
||||
* PARTICULAR PURPOSE AND NON-INFRINGEMENT OF THIRD PARTY INTELLECTUAL PROPERTY
|
||||
* RIGHTS ARE DISCLAIMED TO THE FULLEST EXTENT PERMITTED BY LAW. IN NO EVENT
|
||||
* SHALL STMICROELECTRONICS OR CONTRIBUTORS 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.
|
||||
*
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
/* Define to prevent recursive inclusion -------------------------------------*/
|
||||
#ifndef __TIMER_H__
|
||||
#define __TIMER_H__
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* Includes ------------------------------------------------------------------*/
|
||||
|
||||
#include "timeServer.h"
|
||||
|
||||
/* Exported types ------------------------------------------------------------*/
|
||||
|
||||
/*!
|
||||
* \brief Timer object description
|
||||
*/
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __TIMER_H__*/
|
||||
|
||||
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
|
||||
91
Living_SDK/kernel/protocols/lorawan/lora/system/utilities.c
Normal file
91
Living_SDK/kernel/protocols/lorawan/lora/system/utilities.c
Normal file
|
|
@ -0,0 +1,91 @@
|
|||
/*
|
||||
* Copyright (C) 2015-2017 Alibaba Group Holding Limited
|
||||
*/
|
||||
|
||||
/*
|
||||
/ _____) _ | |
|
||||
( (____ _____ ____ _| |_ _____ ____| |__
|
||||
\____ \| ___ | (_ _) ___ |/ ___) _ \
|
||||
_____) ) ____| | | || |_| ____( (___| | | |
|
||||
(______/|_____)_|_|_| \__)_____)\____)_| |_|
|
||||
(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
|
||||
*/
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#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 '?';
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
149
Living_SDK/kernel/protocols/lorawan/lora/system/utilities.h
Normal file
149
Living_SDK/kernel/protocols/lorawan/lora/system/utilities.h
Normal file
|
|
@ -0,0 +1,149 @@
|
|||
/*
|
||||
/ _____) _ | |
|
||||
( (____ _____ ____ _| |_ _____ ____| |__
|
||||
\____ \| ___ | (_ _) ___ |/ ___) _ \
|
||||
_____) ) ____| | | || |_| ____( (___| | | |
|
||||
(______/|_____)_|_|_| \__)_____)\____)_| |_|
|
||||
(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
|
||||
*/
|
||||
/******************************************************************************
|
||||
* @file utilities.h
|
||||
* @author MCD Application Team
|
||||
* @version V1.1.1
|
||||
* @date 01-June-2017
|
||||
* @brief Header for driver utilities.c module
|
||||
******************************************************************************
|
||||
* @attention
|
||||
*
|
||||
* <h2><center>© Copyright (c) 2017 STMicroelectronics International N.V.
|
||||
* All rights reserved.</center></h2>
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted, provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistribution of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* 2. 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.
|
||||
* 3. Neither the name of STMicroelectronics nor the names of other
|
||||
* contributors to this software may be used to endorse or promote products
|
||||
* derived from this software without specific written permission.
|
||||
* 4. This software, including modifications and/or derivative works of this
|
||||
* software, must execute solely and exclusively on microcontroller or
|
||||
* microprocessor devices manufactured by or for STMicroelectronics.
|
||||
* 5. Redistribution and use of this software other than as permitted under
|
||||
* this license is void and will automatically terminate your rights under
|
||||
* this license.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY STMICROELECTRONICS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS, IMPLIED OR STATUTORY WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
|
||||
* PARTICULAR PURPOSE AND NON-INFRINGEMENT OF THIRD PARTY INTELLECTUAL PROPERTY
|
||||
* RIGHTS ARE DISCLAIMED TO THE FULLEST EXTENT PERMITTED BY LAW. IN NO EVENT
|
||||
* SHALL STMICROELECTRONICS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
|
||||
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
|
||||
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
******************************************************************************
|
||||
*/
|
||||
#ifndef __UTILITIES_H__
|
||||
#define __UTILITIES_H__
|
||||
|
||||
/* prepocessor directive to align buffer*/
|
||||
#define ALIGN(n) __attribute__((aligned(n)))
|
||||
|
||||
typedef uint32_t TimerTime_t;
|
||||
|
||||
/*!
|
||||
* \brief Returns the minimum value between a and b
|
||||
*
|
||||
* \param [IN] a 1st value
|
||||
* \param [IN] b 2nd value
|
||||
* \retval minValue Minimum value
|
||||
*/
|
||||
#define MIN( a, b ) ( ( ( a ) < ( b ) ) ? ( a ) : ( b ) )
|
||||
|
||||
/*!
|
||||
* \brief Returns the maximum value between a and b
|
||||
*
|
||||
* \param [IN] a 1st value
|
||||
* \param [IN] b 2nd value
|
||||
* \retval maxValue Maximum value
|
||||
*/
|
||||
#define MAX( a, b ) ( ( ( a ) > ( b ) ) ? ( a ) : ( b ) )
|
||||
|
||||
/*!
|
||||
* \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
|
||||
*/
|
||||
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 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
|
||||
*/
|
||||
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
|
||||
*/
|
||||
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
|
||||
*/
|
||||
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__
|
||||
49
Living_SDK/kernel/protocols/lorawan/lorawan.mk
Normal file
49
Living_SDK/kernel/protocols/lorawan/lorawan.mk
Normal file
|
|
@ -0,0 +1,49 @@
|
|||
NAME := lorawan
|
||||
|
||||
$(NAME)_SOURCES := lora/system/crypto/aes.c \
|
||||
lora/system/crypto/cmac.c \
|
||||
lora/system/timeServer.c \
|
||||
lora/system/low_power.c \
|
||||
lora/system/utilities.c \
|
||||
lora/system/delay.c \
|
||||
lora/mac/region/Region.c \
|
||||
lora/mac/region/RegionCommon.c \
|
||||
lora/mac/LoRaMac.c \
|
||||
lora/mac/LoRaMacCrypto.c
|
||||
|
||||
GLOBAL_INCLUDES += . \
|
||||
lora/system/crypto \
|
||||
lora/radio \
|
||||
lora/mac \
|
||||
lora/mac/region \
|
||||
lora/system
|
||||
|
||||
linkwan?=0
|
||||
ifeq ($(linkwan), 1)
|
||||
GLOBAL_DEFINES += CONFIG_LINKWAN
|
||||
GLOBAL_DEFINES += CONFIG_DEBUG_LINKWAN
|
||||
GLOBAL_DEFINES += CONFIG_AOS_DISABLE_TICK
|
||||
GLOBAL_DEFINES += REGION_CN470A
|
||||
$(NAME)_SOURCES += linkwan/region/RegionCN470A.c
|
||||
$(NAME)_SOURCES += linkwan/linkwan.c
|
||||
|
||||
GLOBAL_INCLUDES += linkwan/include
|
||||
GLOBAL_INCLUDES += linkwan/region
|
||||
|
||||
linkwanat ?= 0
|
||||
ifeq ($(linkwanat), 1)
|
||||
GLOBAL_DEFINES += CONFIG_LINKWAN_AT
|
||||
$(NAME)_SOURCES += linkwan/linkwan_at.c
|
||||
endif
|
||||
else
|
||||
$(NAME)_SOURCES += lora/mac/region/RegionAS923.c \
|
||||
lora/mac/region/RegionAU915.c \
|
||||
lora/mac/region/RegionCN470.c \
|
||||
lora/mac/region/RegionCN779.c \
|
||||
lora/mac/region/RegionEU433.c \
|
||||
lora/mac/region/RegionEU868.c \
|
||||
lora/mac/region/RegionIN865.c \
|
||||
lora/mac/region/RegionKR920.c \
|
||||
lora/mac/region/RegionUS915.c \
|
||||
lora/mac/region/RegionUS915-Hybrid.c
|
||||
endif
|
||||
Loading…
Add table
Add a link
Reference in a new issue