Update LoRaMac-node to Version 4.4.4,fix Security breach found by Tencent Blade Team please refer to security advisory - CVE-2020-11068

fix Security breach found by Tencent Blade Team please refer to security advisory - CVE-2020-11068
This commit is contained in:
supowang
2020-05-29 11:59:05 +08:00
parent 5d9895cecc
commit f9bd2588a2
137 changed files with 10401 additions and 4328 deletions

File diff suppressed because it is too large Load Diff

View File

@@ -36,6 +36,15 @@
* layer and the supported features.
* \{
*
* \example classA/B-L072Z-LRWAN1/main.c
* LoRaWAN class A application example for the B-L072Z-LRWAN1.
*
* \example classB/B-L072Z-LRWAN1/main.c
* LoRaWAN class B application example for the B-L072Z-LRWAN1.
*
* \example classC/B-L072Z-LRWAN1/main.c
* LoRaWAN class C application example for the B-L072Z-LRWAN1.
*
* \example classA/NAMote72/main.c
* LoRaWAN class A application example for the NAMote72.
*
@@ -63,10 +72,60 @@
* \example classC/NucleoL152/main.c
* LoRaWAN class C application example for the NucleoL152.
*
* \example classA/NucleoL476/main.c
* LoRaWAN class A application example for the NucleoL476.
*
* \example classB/NucleoL476/main.c
* LoRaWAN class B application example for the NucleoL476.
*
* \example classC/NucleoL476/main.c
* LoRaWAN class C application example for the NucleoL476.
*
* \example classA/SAMR34/main.c
* LoRaWAN class A application example for the SAMR34.
*
* \example classB/SAMR34/main.c
* LoRaWAN class B application example for the SAMR34.
*
* \example classC/SAMR34/main.c
* LoRaWAN class C application example for the SAMR34.
*
* \example classA/SKiM880B/main.c
* LoRaWAN class A application example for the SKiM880B.
*
* \example classB/SKiM880B/main.c
* LoRaWAN class B application example for the SKiM880B.
*
* \example classC/SKiM880B/main.c
* LoRaWAN class C application example for the SKiM880B.
*
* \example classA/SKiM881AXL/main.c
* LoRaWAN class A application example for the SKiM881AXL.
*
* \example classB/SKiM881AXL/main.c
* LoRaWAN class B application example for the SKiM881AXL.
*
* \example classC/SKiM881AXL/main.c
* LoRaWAN class C application example for the SKiM881AXL.
*
* \example classA/SKiM980A/main.c
* LoRaWAN class A application example for the SKiM980A.
*
* \example classB/SKiM980A/main.c
* LoRaWAN class B application example for the SKiM980A.
*
* \example classC/SKiM980A/main.c
* LoRaWAN class C application example for the SKiM980A.
*
*/
#ifndef __LORAMAC_H__
#define __LORAMAC_H__
#ifdef __cplusplus
extern "C"
{
#endif
#include <stdint.h>
#include <stdbool.h>
#include "utilities.h"
@@ -90,24 +149,11 @@
*/
#define DOWN_LINK 1
/*!
* Sets the length of the LoRaMAC footer field.
* Mainly indicates the MIC field length
*/
#define LORAMAC_MFR_LEN 4
/*!
* LoRaMac MLME-Confirm queue length
*/
#define LORA_MAC_MLME_CONFIRM_QUEUE_LEN 5
/*!
* FRMPayload overhead to be used when setting the Radio.SetMaxPayloadLength
* in RxWindowSetup function.
* Maximum PHYPayload = MaxPayloadOfDatarate/MaxPayloadOfDatarateRepeater + LORA_MAC_FRMPAYLOAD_OVERHEAD
*/
#define LORA_MAC_FRMPAYLOAD_OVERHEAD 13 // MHDR(1) + FHDR(7) + Port(1) + MIC(4)
/*!
* Maximum number of multicast context
*/
@@ -116,34 +162,7 @@
/*!
* Start value for multicast keys enumeration
*/
#define LORAMAC_CRYPTO_MULITCAST_KEYS 127
/*!
* LoRaWAN devices classes definition
*
* LoRaWAN Specification V1.0.2, chapter 2.1
*/
typedef enum eDeviceClass
{
/*!
* LoRaWAN device class A
*
* LoRaWAN Specification V1.0.2, chapter 3
*/
CLASS_A = 0x00,
/*!
* LoRaWAN device class B
*
* LoRaWAN Specification V1.0.2, chapter 8
*/
CLASS_B = 0x01,
/*!
* LoRaWAN device class C
*
* LoRaWAN Specification V1.0.2, chapter 17
*/
CLASS_C = 0x02,
}DeviceClass_t;
#define LORAMAC_CRYPTO_MULTICAST_KEYS 127
/*!
* End-Device activation type
@@ -164,7 +183,6 @@ typedef enum eActivationType
ACTIVATION_TYPE_OTAA = 2,
}ActivationType_t;
/*!
* LoRaMAC channels parameters definition
*/
@@ -222,9 +240,9 @@ typedef struct sChannelParams
}ChannelParams_t;
/*!
* LoRaMAC receive window 2 channel parameters
* LoRaMAC receive window channel parameters
*/
typedef struct sRx2ChannelParams
typedef struct sRxChannelParams
{
/*!
* Frequency in Hz
@@ -238,7 +256,7 @@ typedef struct sRx2ChannelParams
* The allowed ranges are region specific. Please refer to \ref DR_0 to \ref DR_15 for details.
*/
uint8_t Datarate;
}Rx2ChannelParams_t;
}RxChannelParams_t;
/*!
* LoRaMAC receive window enumeration
@@ -257,14 +275,22 @@ typedef enum eLoRaMacRxSlot
* LoRaMAC receive window 2 for class c - continuous listening
*/
RX_SLOT_WIN_CLASS_C,
/*!
* LoRaMAC class c multicast downlink
*/
RX_SLOT_WIN_CLASS_C_MULTICAST,
/*!
* LoRaMAC class b ping slot window
*/
RX_SLOT_WIN_PING_SLOT,
RX_SLOT_WIN_CLASS_B_PING_SLOT,
/*!
* LoRaMAC class b multicast slot window
*/
RX_SLOT_WIN_MULTICAST_SLOT,
RX_SLOT_WIN_CLASS_B_MULTICAST_SLOT,
/*!
* LoRaMAC no active receive window
*/
RX_SLOT_NONE,
}LoRaMacRxSlot_t;
/*!
@@ -328,14 +354,6 @@ typedef struct sLoRaMacCtxs
* \brief Size of MLME Confirm queue module context
*/
size_t ConfirmQueueNvmCtxSize;
/*!
* \brief Pointer to FCnt handler module context
*/
void* FCntHandlerNvmCtx;
/*!
* \brief Size of FCnt handler module context
*/
size_t FCntHandlerNvmCtxSize;
}LoRaMacCtxs_t;
/*!
@@ -393,7 +411,11 @@ typedef struct sLoRaMacParams
/*!
* LoRaMAC 2nd reception window settings
*/
Rx2ChannelParams_t Rx2Channel;
RxChannelParams_t Rx2Channel;
/*!
* LoRaMAC continuous reception window settings
*/
RxChannelParams_t RxCChannel;
/*!
* Uplink dwell time configuration. 0: No limit, 1: 400ms
*/
@@ -410,44 +432,8 @@ typedef struct sLoRaMacParams
* Antenna gain of the node
*/
float AntennaGain;
/*!
* Indicates if the node supports repeaters
*/
bool RepeaterSupport;
}LoRaMacParams_t;
/*!
* Multicast channel
*/
typedef struct sMulticastChannel
{
/*
* Address identifier
*/
AddressIdentifier_t AddrID;
/*!
* Address
*/
uint32_t Address;
/*!
* True if the entry is active
*/
bool IsEnabled;
/*!
* Reception frequency of the ping slot windows
*/
uint32_t Frequency;
/*!
* Datarate of the ping slot
*/
int8_t Datarate;
/*!
* This parameter is necessary for class b operation. It defines the
* periodicity of the multicast downlink slots
*/
uint16_t Periodicity;
}MulticastChannel_t;
/*!
* LoRaMAC data structure for a PingSlotInfoReq \ref MLME_PING_SLOT_INFO
*
@@ -487,7 +473,7 @@ typedef struct sBeaconInfo
* Timestamp in seconds since 00:00:00, Sunday 6th of January 1980
* (start of the GPS epoch) modulo 2^32
*/
uint32_t Time;
SysTime_t Time;
/*!
* Frequency
*/
@@ -616,23 +602,27 @@ typedef union eLoRaMacFlags_t
/*!
* MCPS-Req pending
*/
uint8_t McpsReq : 1;
uint8_t McpsReq : 1;
/*!
* MCPS-Ind pending
*/
uint8_t McpsInd : 1;
uint8_t McpsInd : 1;
/*!
* MLME-Req pending
*/
uint8_t MlmeReq : 1;
uint8_t MlmeReq : 1;
/*!
* MLME-Ind pending
*/
uint8_t MlmeInd : 1;
uint8_t MlmeInd : 1;
/*!
* MLME-Ind to schedule an uplink pending
*/
uint8_t MlmeSchedUplinkInd : 1;
/*!
* MAC cycle done
*/
uint8_t MacDone : 1;
uint8_t MacDone : 1;
}Bits;
}LoRaMacFlags_t;
@@ -679,6 +669,19 @@ typedef enum eMcps
MCPS_PROPRIETARY,
}Mcps_t;
/*!
* Structure which defines return parameters for requests.
*/
typedef struct sRequestReturnParam
{
/*!
* This value reports the time in milliseconds which
* an application must wait before its possible to send
* the next uplink.
*/
TimerTime_t DutyCycleWaitTime;
}RequestReturnParam_t;
/*!
* LoRaMAC MCPS-Request for an unconfirmed frame
*/
@@ -799,6 +802,11 @@ typedef struct sMcpsReq
*/
McpsReqProprietary_t Proprietary;
}Req;
/*!
* MCPS-Request return parameters
*/
RequestReturnParam_t ReqReturn;
}McpsReq_t;
/*!
@@ -909,6 +917,10 @@ typedef struct sMcpsIndication
* The device address of the frame
*/
uint32_t DevAddress;
/*!
* Set if a DeviceTimeAns MAC command was received.
*/
bool DeviceTimeAnsReceived;
}McpsIndication_t;
/*!
@@ -937,6 +949,10 @@ typedef struct sMcpsIndication
*/
typedef enum eMlme
{
/*!
* An unknown MLME service
*/
MLME_UNKNOWN,
/*!
* Initiates the Over-the-Air activation
*
@@ -1033,18 +1049,6 @@ typedef enum eMlme
*/
typedef struct sMlmeReqJoin
{
/*!
* Globally unique end-device identifier
*
* LoRaWAN Specification V1.1.0, chapter 6.1.1.2
*/
uint8_t* DevEui;
/*!
* Join Sever identifier
*
* LoRaWAN Specification V1.1.0, chapter 6.1.1.1
*/
uint8_t* JoinEui;
/*!
* Datarate used for join request.
*/
@@ -1105,7 +1109,7 @@ typedef struct sMlmeReqDeriveMcSessionKeyPair
/*!
* Address identifier to select the multicast group
*/
AddressIdentifier_t AddrID;
AddressIdentifier_t GroupID;
}MlmeReqDeriveMcSessionKeyPair_t;
/*!
@@ -1144,6 +1148,11 @@ typedef struct sMlmeReq
*/
MlmeReqDeriveMcSessionKeyPair_t DeriveMcSessionKeyPair;
}Req;
/*!
* MLME-Request return parameters
*/
RequestReturnParam_t ReqReturn;
}MlmeReq_t;
/*!
@@ -1216,6 +1225,9 @@ typedef struct sMlmeIndication
* ----------------------------------------------| :-: | :-:
* \ref MIB_DEVICE_CLASS | YES | YES
* \ref MIB_NETWORK_ACTIVATION | YES | YES
* \ref MIB_DEV_EUI | YES | YES
* \ref MIB_JOIN_EUI | YES | YES
* \ref MIB_SE_PIN | YES | YES
* \ref MIB_ADR | YES | YES
* \ref MIB_NET_ID | YES | YES
* \ref MIB_DEV_ADDR | YES | YES
@@ -1241,9 +1253,11 @@ typedef struct sMlmeIndication
* \ref MIB_MC_APP_S_KEY_3 | NO | YES
* \ref MIB_MC_NWK_S_KEY_3 | NO | YES
* \ref MIB_PUBLIC_NETWORK | YES | YES
* \ref MIB_REPEATER_SUPPORT | YES | YES
* \ref MIB_CHANNELS | YES | NO
* \ref MIB_RX2_CHANNEL | YES | YES
* \ref MIB_RX2_DFAULT_CHANNEL | YES | YES
* \ref MIB_RXC_CHANNEL | YES | YES
* \ref MIB_RXC_DFAULT_CHANNEL | YES | YES
* \ref MIB_CHANNELS_MASK | YES | YES
* \ref MIB_CHANNELS_DEFAULT_MASK | YES | YES
* \ref MIB_CHANNELS_NB_TRANS | YES | YES
@@ -1273,7 +1287,8 @@ typedef struct sMlmeIndication
* \ref MIB_ANTENNA_GAIN | YES | YES
* \ref MIB_DEFAULT_ANTENNA_GAIN | YES | YES
* \ref MIB_NVM_CTXS | YES | YES
* \ref MIB_ABP_LORAWAN_VERSION | YES | YES
* \ref MIB_ABP_LORAWAN_VERSION | NO | YES
* \ref MIB_LORAWAN_VERSION | YES | NO
*
* The following table provides links to the function implementations of the
* related MIB primitives:
@@ -1297,6 +1312,22 @@ typedef enum eMib
* LoRaWAN Specification V1.0.2
*/
MIB_NETWORK_ACTIVATION,
/*!
* LoRaWAN device EUI
*
* LoRaWAN Specification V1.0.2
*/
MIB_DEV_EUI,
/*!
* LoRaWAN join EUI
*
* LoRaWAN Specification V1.0.2
*/
MIB_JOIN_EUI,
/*!
* Secure-element pin
*/
MIB_SE_PIN,
/*!
* Adaptive data rate
*
@@ -1451,14 +1482,6 @@ typedef enum eMib
* [true: public network, false: private network]
*/
MIB_PUBLIC_NETWORK,
/*!
* Support the operation with repeaters
*
* LoRaWAN Regional Parameters V1.0.2rB
*
* [true: repeater support enabled, false: repeater support disabled]
*/
MIB_REPEATER_SUPPORT,
/*!
* Communication channels. A get request will return a
* pointer which references the first entry of the channel list. The
@@ -1479,6 +1502,18 @@ typedef enum eMib
* LoRaWAN Specification V1.0.2, chapter 3.3.2
*/
MIB_RX2_DEFAULT_CHANNEL,
/*!
* Set receive window C channel
*
* LoRaWAN Specification V1.0.2, chapter 3.3.1
*/
MIB_RXC_CHANNEL,
/*!
* Set receive window C channel
*
* LoRaWAN Specification V1.0.2, chapter 3.3.2
*/
MIB_RXC_DEFAULT_CHANNEL,
/*!
* LoRaWAN channels mask
*
@@ -1575,7 +1610,7 @@ typedef enum eMib
* The antenna gain is used to calculate the TX power of the node.
* The formula is:
* radioTxPower = ( int8_t )floor( maxEirp - antennaGain )
*
*
* \remark The antenna gain value is referenced to the isotropic antenna.
* The value is in dBi.
* MIB_ANTENNA_GAIN[dBi] = measuredAntennaGain[dBd] + 2.15
@@ -1586,7 +1621,7 @@ typedef enum eMib
* The antenna gain is used to calculate the TX power of the node.
* The formula is:
* radioTxPower = ( int8_t )floor( maxEirp - antennaGain )
*
*
* \remark The antenna gain value is referenced to the isotropic antenna.
* The value is in dBi.
* MIB_DEFAULT_ANTENNA_GAIN[dBi] = measuredAntennaGain[dBd] + 2.15
@@ -1600,6 +1635,10 @@ typedef enum eMib
* LoRaWAN MAC layer operating version when activated by ABP.
*/
MIB_ABP_LORAWAN_VERSION,
/*!
* LoRaWAN MAC and regional parameter version.
*/
MIB_LORAWAN_VERSION,
/*!
* Beacon interval in ms
*/
@@ -1677,6 +1716,24 @@ typedef union uMibParam
* Related MIB type: \ref MIB_NETWORK_ACTIVATION
*/
ActivationType_t NetworkActivation;
/*!
* LoRaWAN device EUI
*
* Related MIB type: \ref MIB_DEV_EUI
*/
uint8_t* DevEui;
/*!
* LoRaWAN Join server EUI
*
* Related MIB type: \ref MIB_JOIN_EUI
*/
uint8_t* JoinEui;
/*!
* Secure-element pin
*
* Related MIB type: \ref MIB_SE_PIN
*/
uint8_t* SePin;
/*!
* Activation state of ADR
*
@@ -1827,12 +1884,6 @@ typedef union uMibParam
* Related MIB type: \ref MIB_PUBLIC_NETWORK
*/
bool EnablePublicNetwork;
/*!
* Enable or disable repeater support
*
* Related MIB type: \ref MIB_REPEATER_SUPPORT
*/
bool EnableRepeaterSupport;
/*!
* LoRaWAN Channel
*
@@ -1844,13 +1895,25 @@ typedef union uMibParam
*
* Related MIB type: \ref MIB_RX2_CHANNEL
*/
Rx2ChannelParams_t Rx2Channel;
RxChannelParams_t Rx2Channel;
/*!
* Channel for the receive window 2
*
* Related MIB type: \ref MIB_RX2_DEFAULT_CHANNEL
*/
Rx2ChannelParams_t Rx2DefaultChannel;
RxChannelParams_t Rx2DefaultChannel;
/*!
* Channel for the receive window C
*
* Related MIB type: \ref MIB_RXC_CHANNEL
*/
RxChannelParams_t RxCChannel;
/*!
* Channel for the receive window C
*
* Related MIB type: \ref MIB_RXC_DEFAULT_CHANNEL
*/
RxChannelParams_t RxCDefaultChannel;
/*!
* Channel mask
*
@@ -1928,7 +1991,7 @@ typedef union uMibParam
*
* Related MIB type: \ref MIB_MULTICAST_CHANNEL
*/
MulticastChannel_t MulticastChannel;
McChannelParams_t MulticastChannel;
/*!
* System overall timing error in milliseconds.
*
@@ -1965,6 +2028,16 @@ typedef union uMibParam
* Related MIB type: \ref MIB_ABP_LORAWAN_VERSION
*/
Version_t AbpLrWanVersion;
/*
* LoRaWAN MAC regional parameter version.
*
* Related MIB type: \ref MIB_LORAWAN_VERSION
*/
struct sLrWanVersion
{
Version_t LoRaWan;
Version_t LoRaWanRegion;
}LrWanVersion;
/*!
* Beacon interval in ms
*
@@ -2131,7 +2204,17 @@ typedef enum eLoRaMacStatus
*/
LORAMAC_STATUS_SKIPPED_APP_DATA,
/*!
* ToDo
* An MCPS or MLME request can return this status. In this case,
* the MAC cannot send the frame, as the duty cycle limits all
* available bands. When a request returns this value, the
* variable "DutyCycleWaitTime" in "ReqReturn" of the input
* parameters contains the remaining time to wait. If the
* value is constant and does not change, the expected time
* on air for this frame is exceeding the maximum permitted
* time according to the duty cycle time period, defined
* in Region.h, DUTY_CYCLE_TIME_PERIOD. By default this time
* is 1 hour, and a band with 1% duty cycle is then allowed
* to use an air time of 36 seconds.
*/
LORAMAC_STATUS_DUTYCYCLE_RESTRICTED,
/*!
@@ -2175,7 +2258,11 @@ typedef enum eLoRaMacStatus
*/
LORAMAC_STATUS_CONFIRM_QUEUE_ERROR,
/*!
* Undefined error occured
* The multicast group doesn't exist
*/
LORAMAC_STATUS_MC_GROUP_UNDEFINED,
/*!
* Undefined error occurred
*/
LORAMAC_STATUS_ERROR
}LoRaMacStatus_t;
@@ -2260,10 +2347,6 @@ typedef enum LoRaMacNvmCtxModule_e
* Context for the confirm queue
*/
LORAMAC_NVMCTXMODULE_CONFIRM_QUEUE,
/*!
* Context for the frame count handler
*/
LORAMAC_NVMCTXMODULE_FCNT_HANDLER
}LoRaMacNvmCtxModule_t;
@@ -2328,7 +2411,7 @@ typedef struct sLoRaMacCallback
/*!
*\brief Will be called each time a Radio IRQ is handled by the MAC
* layer.
*
*
*\warning Runs in a IRQ context. Should only change variables state.
*/
void ( *MacProcessNotify )( void );
@@ -2382,6 +2465,13 @@ LoRaMacStatus_t LoRaMacStart( void );
*/
LoRaMacStatus_t LoRaMacStop( void );
/*!
* \brief Returns a value indicating if the MAC layer is busy or not.
*
* \retval isBusy Mac layer is busy.
*/
bool LoRaMacIsBusy( void );
/*!
* Processes the LoRaMac events.
*
@@ -2449,18 +2539,60 @@ LoRaMacStatus_t LoRaMacChannelAdd( uint8_t id, ChannelParams_t params );
LoRaMacStatus_t LoRaMacChannelRemove( uint8_t id );
/*!
* \brief LoRaMAC multicast channel setting service
* \brief LoRaMAC multicast channel setup service
*
* \details Sets a multicast channel.
* \details Sets up a multicast channel.
*
* \param [IN] channel - Multicast channel to set.
*
* \retval LoRaMacStatus_t Status of the operation. Possible returns are:
* \ref LORAMAC_STATUS_OK,
* \ref LORAMAC_STATUS_BUSY,
* \ref LORAMAC_STATUS_PARAMETER_INVALID.
* \ref LORAMAC_STATUS_PARAMETER_INVALID,
* \ref LORAMAC_STATUS_MC_GROUP_UNDEFINED.
*/
LoRaMacStatus_t LoRaMacMulticastChannelSet( MulticastChannel_t channel );
LoRaMacStatus_t LoRaMacMcChannelSetup( McChannelParams_t *channel );
/*!
* \brief LoRaMAC multicast channel removal service
*
* \details Removes/Disables a multicast channel.
*
* \param [IN] groupID - Multicast channel ID to be removed/disabled
*
* \retval LoRaMacStatus_t Status of the operation. Possible returns are:
* \ref LORAMAC_STATUS_OK,
* \ref LORAMAC_STATUS_BUSY,
* \ref LORAMAC_STATUS_MC_GROUP_UNDEFINED.
*/
LoRaMacStatus_t LoRaMacMcChannelDelete( AddressIdentifier_t groupID );
/*!
* \brief LoRaMAC multicast channel get groupId from MC address.
*
* \param [IN] mcAddress - Multicast address to be checked
*
* \retval groupID Multicast channel ID associated to the address.
* Returns 0xFF if the address isn't found.
*/
uint8_t LoRaMacMcChannelGetGroupId( uint32_t mcAddress );
/*!
* \brief LoRaMAC multicast channel Rx parameters setup service
*
* \details Sets up a multicast channel reception parameters.
*
* \param [IN] groupID - Multicast channel ID
* \param [IN] rxParams - Reception parameters
* \param [OUT] status - Status mask [UNDEF_ID | FREQ_ERR | DR_ERR | GROUP_ID]
*
* \retval LoRaMacStatus_t Status of the operation. Possible returns are:
* \ref LORAMAC_STATUS_OK,
* \ref LORAMAC_STATUS_BUSY,
* \ref LORAMAC_STATUS_PARAMETER_INVALID,
* \ref LORAMAC_STATUS_MC_GROUP_UNDEFINED.
*/
LoRaMacStatus_t LoRaMacMcChannelSetupRxParams( AddressIdentifier_t groupID, McRxParams_t *rxParams, uint8_t *status );
/*!
* \brief LoRaMAC MIB-Get
@@ -2526,32 +2658,15 @@ LoRaMacStatus_t LoRaMacMibSetRequestConfirm( MibRequestConfirm_t* mibSet );
*
* \details The Mac layer management entity handles management services. The
* following code-snippet shows how to use the API to perform a
* network join request.
* network join request. Please note that for a join request, the
* DevEUI and the JoinEUI must be set previously via the MIB. Please
* also refer to the sample implementations.
*
* \code
* static uint8_t DevEui[] =
* {
* 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
* };
* static uint8_t JoinEui[] =
* {
* 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
* };
* static uint8_t NwkKey[] =
* {
* 0x2B, 0x7E, 0x15, 0x16, 0x28, 0xAE, 0xD2, 0xA6,
* 0xAB, 0xF7, 0x15, 0x88, 0x09, 0xCF, 0x4F, 0x3C
* };
* static uint8_t AppKey[] =
* {
* 0x2B, 0x7E, 0x15, 0x16, 0x28, 0xAE, 0xD2, 0xA6,
* 0xAB, 0xF7, 0x15, 0x88, 0x09, 0xCF, 0x4F, 0x3C
* };
*
* MlmeReq_t mlmeReq;
* mlmeReq.Type = MLME_JOIN;
* mlmeReq.Req.Join.DevEui = DevEui;
* mlmeReq.Req.Join.JoinEui = JoinEui;
* mlmeReq.Req.Join.Datarate = LORAWAN_DEFAULT_DATARATE;
*
* if( LoRaMacMlmeRequest( &mlmeReq ) == LORAMAC_STATUS_OK )
* {
@@ -2605,6 +2720,18 @@ LoRaMacStatus_t LoRaMacMlmeRequest( MlmeReq_t* mlmeRequest );
*/
LoRaMacStatus_t LoRaMacMcpsRequest( McpsReq_t* mcpsRequest );
/*!
* \brief LoRaMAC deinitialization
*
* \details This function stops the timers, re-initializes MAC & regional parameters to default
* and sets radio into sleep state.
*
* \retval LoRaMacStatus_t Status of the operation. Possible returns are:
* \ref LORAMAC_STATUS_OK,
* \ref LORAMAC_STATUS_BUSY
*/
LoRaMacStatus_t LoRaMacDeInitialization( void );
/*!
* Automatically add the Region.h file at the end of LoRaMac.h file.
* This is required because Region.h uses definitions from LoRaMac.h
@@ -2613,4 +2740,8 @@ LoRaMacStatus_t LoRaMacMcpsRequest( McpsReq_t* mcpsRequest );
/*! \} defgroup LORAMAC */
#ifdef __cplusplus
}
#endif
#endif // __LORAMAC_H__

View File

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

View File

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

File diff suppressed because it is too large Load Diff

View File

@@ -37,6 +37,11 @@
#ifndef __LORAMACCLASSB_H__
#define __LORAMACCLASSB_H__
#ifdef __cplusplus
extern "C"
{
#endif
#include "systime.h"
#include "LoRaMacTypes.h"
@@ -121,42 +126,15 @@ typedef enum ePingSlotState
*/
typedef struct sPingSlotContext
{
struct sPingSlotCtrl
{
/*!
* Set when the server assigned a ping slot to the node
*/
uint8_t Assigned : 1;
/*!
* Set when a custom frequency is used
*/
uint8_t CustomFreq : 1;
}Ctrl;
/*!
* Ping slot length time in ms
*/
uint32_t PingSlotWindow;
/*!
* Number of ping slots
*/
uint8_t PingNb;
/*!
* Period of the ping slots
*/
uint16_t PingPeriod;
/*!
* Ping offset
*/
uint16_t PingOffset;
/*!
* Reception frequency of the ping slot windows
*/
uint32_t Frequency;
/*!
* Datarate of the ping slot
*/
int8_t Datarate;
/*!
* Current symbol timeout. The node enlarges this variable in case of beacon
* loss.
@@ -184,10 +162,6 @@ typedef struct sBeaconContext
* Set if the node has acquired the beacon
*/
uint8_t BeaconAcquired : 1;
/*!
* Set if the node has a custom frequency for beaconing and ping slots
*/
uint8_t CustomFreq : 1;
/*!
* Set if a beacon delay was set for the beacon acquisition
*/
@@ -205,10 +179,7 @@ typedef struct sBeaconContext
*/
uint8_t ResumeBeaconing : 1;
}Ctrl;
/*!
* Beacon reception frequency
*/
uint32_t Frequency;
/*!
* Current temperature
*/
@@ -216,15 +187,15 @@ typedef struct sBeaconContext
/*!
* Beacon time received with the beacon frame
*/
TimerTime_t BeaconTime;
SysTime_t BeaconTime;
/*!
* Time when the last beacon was received
*/
TimerTime_t LastBeaconRx;
SysTime_t LastBeaconRx;
/*!
* Time when the next beacon will be received
*/
TimerTime_t NextBeaconRx;
SysTime_t NextBeaconRx;
/*!
* This is the time where the RX window will be opened.
* Its base is NextBeaconRx with temperature compensations
@@ -265,7 +236,7 @@ typedef struct sLoRaMacClassBCallback
/*!
*\brief Will be called each time a Radio IRQ is handled by the MAC
* layer.
*
*
*\warning Runs in a IRQ context. Should only change variables state.
*/
void ( *MacProcessNotify )( void );
@@ -314,7 +285,7 @@ typedef struct sLoRaMacClassBParams
* Signature of callback function to be called by this module when the
* non-volatile needs to be saved.
*/
typedef void ( *EventNvmCtxChanged )( void );
typedef void ( *LoRaMacClassBNvmEvent )( void );
/*!
* \brief Initialize LoRaWAN Class B
@@ -323,7 +294,7 @@ typedef void ( *EventNvmCtxChanged )( void );
* \param [IN] callbacks Contains the callback which the Class B implementation needs
* \param [IN] callback function which will be called when the non-volatile context needs to be saved.
*/
void LoRaMacClassBInit( LoRaMacClassBParams_t *classBParams, LoRaMacClassBCallback_t *callbacks, EventNvmCtxChanged classBNvmCtxChanged );
void LoRaMacClassBInit( LoRaMacClassBParams_t *classBParams, LoRaMacClassBCallback_t *callbacks, LoRaMacClassBNvmEvent classBNvmCtxChanged );
/*!
* Restores the internal non-volatile context from passed pointer.
@@ -561,4 +532,8 @@ void LoRaMacClassBSetMulticastPeriodicity( MulticastCtx_t* multicastChannel );
void LoRaMacClassBProcess( void );
#ifdef __cplusplus
}
#endif
#endif // __LORAMACCLASSB_H__

View File

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

View File

@@ -17,27 +17,23 @@ License: Revised BSD License, see LICENSE.TXT file include in the project
Maintainer: Miguel Luis ( Semtech ), Daniel Jaeckle ( STACKFORCE ), Johannes Bruder ( STACKFORCE )
*/
#include <stddef.h>
#include "utilities.h"
#include "LoRaMacCommands.h"
#include "LoRaMacConfirmQueue.h"
/*
/*!
* Number of MAC Command slots
*/
#define NUM_OF_MAC_COMMANDS 15
/*
/*!
* Size of the CID field of MAC commands
*/
#define CID_FIELD_SIZE 1
#define CID_FIELD_SIZE 1
/*
* List of all stick MAC command answers which will be deleted after a receiving downlink
*/
const uint8_t CIDsStickyAnsCmds[] = { MOTE_MAC_DL_CHANNEL_ANS, MOTE_MAC_RX_PARAM_SETUP_ANS, MOTE_MAC_RX_TIMING_SETUP_ANS };
/*
/*!
* Mac Commands list structure
*/
typedef struct sMacCommandsList
@@ -52,7 +48,7 @@ typedef struct sMacCommandsList
MacCommand_t* Last;
} MacCommandsList_t;
/*
/*!
* LoRaMac Commands Context structure
*/
typedef struct sLoRaMacCommandsCtx
@@ -71,27 +67,27 @@ typedef struct sLoRaMacCommandsCtx
size_t SerializedCmdsSize;
} LoRaMacCommandsCtx_t;
/*
/*!
* Callback function to notify the upper layer about context change
*/
static EventNvmCtxChanged CommandsNvmCtxChanged;
static LoRaMacCommandsNvmEvent CommandsNvmCtxChanged;
/*
/*!
* Non-volatile module context.
*/
static LoRaMacCommandsCtx_t NvmCtx;
/* Memory management functions */
/*
/*!
* \brief Determines if a MAC command slot is free
*
* \param[IN] slot - Slot to check
* \retval - Status of the operation
*/
bool isSlotFree( const MacCommand_t* slot )
static bool IsSlotFree( const MacCommand_t* slot )
{
uint8_t* mem = (uint8_t*) slot;
uint8_t* mem = ( uint8_t* )slot;
for( uint16_t size = 0; size < sizeof( MacCommand_t ); size++ )
{
@@ -103,114 +99,112 @@ bool isSlotFree( const MacCommand_t* slot )
return true;
}
/*
/*!
* \brief Allocates a new MAC command memory slot
*
* \retval - Pointer to slot
*/
MacCommand_t* mallocNewMacCommandSlot( )
static MacCommand_t* MallocNewMacCommandSlot( void )
{
uint8_t itr = 0;
while( isSlotFree( ( const MacCommand_t* ) &NvmCtx.MacCommandSlots[itr]) == false )
while( IsSlotFree( ( const MacCommand_t* )&NvmCtx.MacCommandSlots[itr] ) == false )
{
itr++;
if( itr == NUM_OF_MAC_COMMANDS )
{
return 0;
return NULL;
}
}
return &NvmCtx.MacCommandSlots[itr];
}
/*
/*!
* \brief Free memory slot
*
* \param[IN] slot - Slot to free
*
* \retval - Status of the operation
*/
bool freeMacCommandSlot( MacCommand_t* slot )
static bool FreeMacCommandSlot( MacCommand_t* slot )
{
if( slot == 0 )
if( slot == NULL )
{
return false;
}
memset1( (uint8_t*) slot, 0x00, sizeof( MacCommand_t ));
memset1( ( uint8_t* )slot, 0x00, sizeof( MacCommand_t ) );
return true;
}
/* Linked list functions */
/*
/*!
* \brief Initialize list
*
* \param[IN] list - List that shall be initialized
* \retval - Status of the operation
*/
static bool linkedListInit( MacCommandsList_t* list )
static bool LinkedListInit( MacCommandsList_t* list )
{
if( list == 0 )
if( list == NULL )
{
return false;
}
list->First = 0;
list->Last = 0;
list->First = NULL;
list->Last = NULL;
return true;
}
/*
/*!
* \brief Add an element to the list
*
* \param[IN] list - List where the element shall be added.
* \param[IN] element - Element to add
* \retval - Status of the operation
*/
static bool linkedListAdd( MacCommandsList_t* list, MacCommand_t* element )
static bool LinkedListAdd( MacCommandsList_t* list, MacCommand_t* element )
{
if( ( list == 0 ) && ( element == 0 ) )
if( ( list == NULL ) || ( element == NULL ) )
{
return false;
}
/* Check if this is the first entry to enter the list. */
if( list->First == 0 )
// Check if this is the first entry to enter the list.
if( list->First == NULL )
{
list->First = element;
}
/* Check if the last entry exists and update its next point. */
// Check if the last entry exists and update its next point.
if( list->Last )
{
list->Last->Next = element;
}
/* Update the next point of this entry. */
element->Next = 0;
// Update the next point of this entry.
element->Next = NULL;
/* Update the last entry of the list. */
// Update the last entry of the list.
list->Last = element;
return true;
}
/*
/*!
* \brief Return the previous element in the list.
*
* \param[IN] list - List
* \param[IN] element - Element where the previous element shall be searched
* \retval - Status of the operation
*/
static MacCommand_t* linkedListGetPrevious( MacCommandsList_t* list, MacCommand_t* element )
static MacCommand_t* LinkedListGetPrevious( MacCommandsList_t* list, MacCommand_t* element )
{
if( ( list == 0 ) && ( element == 0 ) )
if( ( list == NULL ) || ( element == NULL ) )
{
return NULL;
}
@@ -220,14 +214,11 @@ static MacCommand_t* linkedListGetPrevious( MacCommandsList_t* list, MacCommand_
// Start at the head of the list
curElement = list->First;
/*
* When current element is the first of the list, there's no previous element so we can return NULL immediately.
*/
if( element != curElement)
// When current element is the first of the list, there's no previous element so we can return NULL immediately.
if( element != curElement )
{
// Loop through all elements until the end is reached or the next of current is the current element.
while(curElement && (curElement->Next != element))
while( ( curElement != NULL ) && ( curElement->Next != element ) )
{
curElement = curElement->Next;
}
@@ -240,21 +231,21 @@ static MacCommand_t* linkedListGetPrevious( MacCommandsList_t* list, MacCommand_
return curElement;
}
/*
/*!
* \brief Remove an element from the list
*
* \param[IN] list - List where the element shall be removed from.
* \param[IN] element - Element to remove
* \retval - Status of the operation
*/
static bool linkedListRemove( MacCommandsList_t* list, MacCommand_t* element )
static bool LinkedListRemove( MacCommandsList_t* list, MacCommand_t* element )
{
if( ( list == 0 ) && ( element == 0 ) )
if( ( list == NULL ) || ( element == NULL ) )
{
return false;
}
MacCommand_t* PrevElement = linkedListGetPrevious( list, element );
MacCommand_t* PrevElement = LinkedListGetPrevious( list, element );
if( list->First == element )
{
@@ -266,12 +257,12 @@ static bool linkedListRemove( MacCommandsList_t* list, MacCommand_t* element )
list->Last = PrevElement;
}
if( PrevElement )
if( PrevElement != NULL )
{
PrevElement->Next = element->Next;
}
element->Next = 0;
element->Next = NULL;
return true;
}
@@ -290,6 +281,7 @@ static bool IsSticky( uint8_t cid )
case MOTE_MAC_DL_CHANNEL_ANS:
case MOTE_MAC_RX_PARAM_SETUP_ANS:
case MOTE_MAC_RX_TIMING_SETUP_ANS:
case MOTE_MAC_TX_PARAM_SETUP_ANS:
return true;
default:
return false;
@@ -307,13 +299,12 @@ static void NvmCtxCallback( void )
}
}
LoRaMacCommandStatus_t LoRaMacCommandsInit( EventNvmCtxChanged commandsNvmCtxChanged )
LoRaMacCommandStatus_t LoRaMacCommandsInit( LoRaMacCommandsNvmEvent commandsNvmCtxChanged )
{
// Initialize with default
memset1( (uint8_t*)&NvmCtx, 0, sizeof( NvmCtx ) );
memset1( ( uint8_t* )&NvmCtx, 0, sizeof( NvmCtx ) );
linkedListInit( &NvmCtx.MacCommandList );
LinkedListInit( &NvmCtx.MacCommandList );
// Assign callback
CommandsNvmCtxChanged = commandsNvmCtxChanged;
@@ -326,7 +317,7 @@ LoRaMacCommandStatus_t LoRaMacCommandsRestoreNvmCtx( void* commandsNvmCtx )
// Restore module context
if( commandsNvmCtx != NULL )
{
memcpy1( ( uint8_t* ) &NvmCtx, ( uint8_t* ) commandsNvmCtx, sizeof( NvmCtx ) );
memcpy1( ( uint8_t* )&NvmCtx, ( uint8_t* )commandsNvmCtx, sizeof( NvmCtx ) );
return LORAMAC_COMMANDS_SUCCESS;
}
else
@@ -341,24 +332,24 @@ void* LoRaMacCommandsGetNvmCtx( size_t* commandsNvmCtxSize )
return &NvmCtx;
}
LoRaMacCommandStatus_t LoRaMacCommandsAddCmd( uint8_t cid, uint8_t* payload, size_t payloadSize )
LoRaMacCommandStatus_t LoRaMacCommandsAddCmd( uint8_t cid, uint8_t* payload, size_t payloadSize )
{
if( payload == 0 )
if( payload == NULL )
{
return LORAMAC_COMMANDS_ERROR_NPE;
}
MacCommand_t* newCmd;
// Allocate a memory slot
newCmd = mallocNewMacCommandSlot( );
newCmd = MallocNewMacCommandSlot( );
if( newCmd == 0 )
if( newCmd == NULL )
{
return LORAMAC_COMMANDS_ERROR_MEMORY;
}
// Add it to the list of Mac commands
if( linkedListAdd( &NvmCtx.MacCommandList, newCmd ) == false )
if( LinkedListAdd( &NvmCtx.MacCommandList, newCmd ) == false )
{
return LORAMAC_COMMANDS_ERROR;
}
@@ -366,7 +357,7 @@ LoRaMacCommandStatus_t LoRaMacCommandsAddCmd( uint8_t cid, uint8_t* payload, si
// Set Values
newCmd->CID = cid;
newCmd->PayloadSize = payloadSize;
memcpy1( ( uint8_t* ) newCmd->Payload, payload, payloadSize );
memcpy1( ( uint8_t* )newCmd->Payload, payload, payloadSize );
newCmd->IsSticky = IsSticky( cid );
NvmCtx.SerializedCmdsSize += ( CID_FIELD_SIZE + payloadSize );
@@ -384,7 +375,7 @@ LoRaMacCommandStatus_t LoRaMacCommandsRemoveCmd( MacCommand_t* macCmd )
}
// Remove the Mac command element from MacCommandList
if( linkedListRemove( &NvmCtx.MacCommandList, macCmd ) == false )
if( LinkedListRemove( &NvmCtx.MacCommandList, macCmd ) == false )
{
return LORAMAC_COMMANDS_ERROR_CMD_NOT_FOUND;
}
@@ -392,7 +383,7 @@ LoRaMacCommandStatus_t LoRaMacCommandsRemoveCmd( MacCommand_t* macCmd )
NvmCtx.SerializedCmdsSize -= ( CID_FIELD_SIZE + macCmd->PayloadSize );
// Free the MacCommand Slot
if( freeMacCommandSlot( macCmd ) == false )
if( FreeMacCommandSlot( macCmd ) == false )
{
return LORAMAC_COMMANDS_ERROR;
}
@@ -410,19 +401,19 @@ LoRaMacCommandStatus_t LoRaMacCommandsGetCmd( uint8_t cid, MacCommand_t** macCmd
curElement = NvmCtx.MacCommandList.First;
// Loop through all elements until we find the element with the given CID
while(curElement && ( curElement->CID != cid ) )
while( ( curElement != NULL ) && ( curElement->CID != cid ) )
{
curElement = curElement->Next;
}
// Update the pointer anyway
*macCmd = curElement;
// Handle error in case if we reached the end without finding it.
if( curElement == NULL )
{
return LORAMAC_COMMANDS_ERROR_CMD_NOT_FOUND;
}
*macCmd = curElement;
return LORAMAC_COMMANDS_SUCCESS;
}
@@ -435,7 +426,7 @@ LoRaMacCommandStatus_t LoRaMacCommandsRemoveNoneStickyCmds( void )
curElement = NvmCtx.MacCommandList.First;
// Loop through all elements
while( curElement )
while( curElement != NULL )
{
if( curElement->IsSticky == false )
{
@@ -466,16 +457,9 @@ LoRaMacCommandStatus_t LoRaMacCommandsRemoveStickyAnsCmds( void )
while( curElement != NULL )
{
nexElement = curElement->Next;
if( curElement->IsSticky == true )
if( IsSticky( curElement->CID ) == true )
{
for( uint8_t i = 0; i < sizeof( CIDsStickyAnsCmds ); i++)
{
if( curElement->CID == CIDsStickyAnsCmds[i] )
{
LoRaMacCommandsRemoveCmd( curElement );
break;
}
}
LoRaMacCommandsRemoveCmd( curElement );
}
curElement = nexElement;
}
@@ -493,28 +477,28 @@ LoRaMacCommandStatus_t LoRaMacCommandsGetSizeSerializedCmds( size_t* size )
}
*size = NvmCtx.SerializedCmdsSize;
return LORAMAC_COMMANDS_SUCCESS;
}
LoRaMacCommandStatus_t LoRaMacCommandsSerializeCmds( size_t availableSize, size_t* effectiveSize, uint8_t* buffer )
LoRaMacCommandStatus_t LoRaMacCommandsSerializeCmds( size_t availableSize, size_t* effectiveSize, uint8_t* buffer )
{
MacCommand_t* curElement = NvmCtx.MacCommandList.First;
MacCommand_t* nextElement;
uint8_t itr = 0;
if( ( buffer == NULL ) || ( effectiveSize == NULL ) )
{
return LORAMAC_COMMANDS_ERROR_NPE;
}
MacCommand_t* curElement;
curElement = NvmCtx.MacCommandList.First;
uint8_t itr = 0;
// Loop through all elements
while( curElement )
// Loop through all elements which fits into the buffer
while( curElement != NULL )
{
// If the next MAC command still fits into the buffer, add it.
if( ( availableSize - itr ) >= ( CID_FIELD_SIZE + curElement->PayloadSize ) )
{
buffer[itr++] = curElement->CID;
memcpy1( &buffer[itr], curElement->Payload, curElement->PayloadSize );
itr = itr + curElement->PayloadSize;
itr += curElement->PayloadSize;
}
else
{
@@ -523,6 +507,18 @@ LoRaMacCommandStatus_t LoRaMacCommandsSerializeCmds( size_t availableSize, size_
curElement = curElement->Next;
}
// Remove all commands which do not fit into the buffer
while( curElement != NULL )
{
// Store the next element before removing the current one
nextElement = curElement->Next;
LoRaMacCommandsRemoveCmd( curElement );
curElement = nextElement;
}
// Fetch the effective size of the mac commands
LoRaMacCommandsGetSizeSerializedCmds( effectiveSize );
return LORAMAC_COMMANDS_SUCCESS;
}
@@ -538,7 +534,7 @@ LoRaMacCommandStatus_t LoRaMacCommandsStickyCmdsPending( bool* cmdsPending )
*cmdsPending = false;
// Loop through all elements
while( curElement )
while( curElement != NULL )
{
if( curElement->IsSticky == true )
{
@@ -551,3 +547,103 @@ LoRaMacCommandStatus_t LoRaMacCommandsStickyCmdsPending( bool* cmdsPending )
return LORAMAC_COMMANDS_SUCCESS;
}
uint8_t LoRaMacCommandsGetCmdSize( uint8_t cid )
{
uint8_t cidSize = 0;
// Decode Frame MAC commands
switch( cid )
{
case SRV_MAC_LINK_CHECK_ANS:
{
// cid + Margin + GwCnt
cidSize = 3;
break;
}
case SRV_MAC_LINK_ADR_REQ:
{
// cid + DataRate_TXPower + ChMask (2) + Redundancy
cidSize = 5;
break;
}
case SRV_MAC_DUTY_CYCLE_REQ:
{
// cid + DutyCyclePL
cidSize = 2;
break;
}
case SRV_MAC_RX_PARAM_SETUP_REQ:
{
// cid + DLsettings + Frequency (3)
cidSize = 5;
break;
}
case SRV_MAC_DEV_STATUS_REQ:
{
// cid
cidSize = 1;
break;
}
case SRV_MAC_NEW_CHANNEL_REQ:
{
// cid + ChIndex + Frequency (3) + DrRange
cidSize = 6;
break;
}
case SRV_MAC_RX_TIMING_SETUP_REQ:
{
// cid + Settings
cidSize = 2;
break;
}
case SRV_MAC_TX_PARAM_SETUP_REQ:
{
// cid + EIRP_DwellTime
cidSize = 2;
break;
}
case SRV_MAC_DL_CHANNEL_REQ:
{
// cid + ChIndex + Frequency (3)
cidSize = 5;
break;
}
case SRV_MAC_DEVICE_TIME_ANS:
{
// cid + Seconds (4) + Fractional seconds (1)
cidSize = 6;
break;
}
case SRV_MAC_PING_SLOT_INFO_ANS:
{
// cid
cidSize = 1;
break;
}
case SRV_MAC_PING_SLOT_CHANNEL_REQ:
{
// cid + Frequency (3) + DR
cidSize = 5;
break;
}
case SRV_MAC_BEACON_TIMING_ANS:
{
// cid + TimingDelay (2) + Channel
cidSize = 4;
break;
}
case SRV_MAC_BEACON_FREQ_REQ:
{
// cid + Frequency (3)
cidSize = 4;
break;
}
default:
{
// Unknown command. ABORT MAC commands processing
break;
}
}
return cidSize;
}

View File

@@ -35,6 +35,11 @@
#ifndef __LORAMAC_COMMANDS_H__
#define __LORAMAC_COMMANDS_H__
#ifdef __cplusplus
extern "C"
{
#endif
#include <stdint.h>
#include <stddef.h>
#include "LoRaMacTypes.h"
@@ -109,7 +114,7 @@ typedef enum eLoRaMacCommandsStatus
* Signature of callback function to be called by this module when the
* non-volatile needs to be saved.
*/
typedef void ( *EventNvmCtxChanged )( void );
typedef void ( *LoRaMacCommandsNvmEvent )( void );
/*!
* \brief Initialization of LoRaMac MAC commands module
@@ -119,7 +124,7 @@ typedef void ( *EventNvmCtxChanged )( void );
*
* \retval - Status of the operation
*/
LoRaMacCommandStatus_t LoRaMacCommandsInit( EventNvmCtxChanged commandsNvmCtxChanged );
LoRaMacCommandStatus_t LoRaMacCommandsInit( LoRaMacCommandsNvmEvent commandsNvmCtxChanged );
/*!
* Restores the internal non-volatile context from passed pointer.
@@ -212,7 +217,20 @@ LoRaMacCommandStatus_t LoRaMacCommandsSerializeCmds( size_t availableSize, size_
*/
LoRaMacCommandStatus_t LoRaMacCommandsStickyCmdsPending( bool* cmdsPending );
/*!
* \brief Get the MAC command size with corresponding CID.
*
* \param[IN] cid - MAC command identifier
*
* \retval Size of the command.
*/
uint8_t LoRaMacCommandsGetCmdSize( uint8_t cid );
/*! \} addtogroup LORAMAC */
#ifdef __cplusplus
}
#endif
#endif // __LORAMAC_COMMANDS_H__

View File

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

View File

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

File diff suppressed because it is too large Load Diff

View File

@@ -37,6 +37,11 @@
#ifndef __LORAMAC_CRYPTO_H__
#define __LORAMAC_CRYPTO_H__
#ifdef __cplusplus
extern "C"
{
#endif
#include <stdlib.h>
#include <stdint.h>
#include <stdbool.h>
@@ -44,6 +49,26 @@
#include "LoRaMacTypes.h"
#include "LoRaMacMessageTypes.h"
/*!
* Indicates if LoRaWAN 1.1.x crypto scheme is enabled
*/
#define USE_LRWAN_1_1_X_CRYPTO 0
/*!
* Indicates if a random devnonce must be used or not
*/
#define USE_RANDOM_DEV_NONCE 1
/*!
* Indicates if JoinNonce is counter based and requires to be checked
*/
#define USE_JOIN_NONCE_COUNTER_CHECK 0
/*!
* Initial value of the frame counters
*/
#define FCNT_DOWN_INITAL_VALUE 0xFFFFFFFF
/*!
* LoRaMac Cryto Status
*/
@@ -70,9 +95,21 @@ typedef enum eLoRaMacCryptoStatus
*/
LORAMAC_CRYPTO_FAIL_RJCOUNT0_OVERFLOW,
/*!
* FCntUp/Down check failed
* FCNT_ID is not supported
*/
LORAMAC_CRYPTO_FAIL_FCNT,
LORAMAC_CRYPTO_FAIL_FCNT_ID,
/*!
* FCntUp/Down check failed (new FCnt is smaller than previous one)
*/
LORAMAC_CRYPTO_FAIL_FCNT_SMALLER,
/*!
* FCntUp/Down check failed (duplicated)
*/
LORAMAC_CRYPTO_FAIL_FCNT_DUPLICATED,
/*!
* MAX_GAP_FCNT check failed
*/
LORAMAC_CRYPTO_FAIL_MAX_GAP_FCNT,
/*!
* Not allowed parameter value
*/
@@ -125,7 +162,7 @@ typedef enum eLoRaMacCryptoStatus
* crypto module context.
*
*/
typedef void ( *EventNvmCtxChanged )( void );
typedef void ( *LoRaMacCryptoNvmEvent )( void );
/*!
* Initialization of LoRaMac Crypto module
@@ -135,11 +172,11 @@ typedef void ( *EventNvmCtxChanged )( void );
* non-volatile context have to be stored.
* \retval - Status of the operation
*/
LoRaMacCryptoStatus_t LoRaMacCryptoInit( EventNvmCtxChanged cryptoNvmCtxChanged );
LoRaMacCryptoStatus_t LoRaMacCryptoInit( LoRaMacCryptoNvmEvent cryptoNvmCtxChanged );
/*!
* Sets the LoRaWAN specification version to be used.
*
*
* \warning This function should be used for ABP only. In case of OTA the version will be set automatically.
*
* \param[IN] version - LoRaWAN specification version to be used.
@@ -164,6 +201,34 @@ LoRaMacCryptoStatus_t LoRaMacCryptoRestoreNvmCtx( void* cryptoNvmCtx );
*/
void* LoRaMacCryptoGetNvmCtx( size_t* cryptoNvmCtxSize );
/*!
* Returns updated fCntID downlink counter value.
*
* \param[IN] fCntID - Frame counter identifier
* \param[IN] maxFcntGap - Maximum allowed frame counter difference (only necessary for L2 LW1.0.x)
* \param[IN] frameFcnt - Received frame counter (used to update current counter value)
* \param[OUT] currentDown - Current downlink counter value
* \retval - Status of the operation
*/
LoRaMacCryptoStatus_t LoRaMacCryptoGetFCntDown( FCntIdentifier_t fCntID, uint16_t maxFCntGap, uint32_t frameFcnt, uint32_t* currentDown );
/*!
* Returns updated fCntUp uplink counter value.
*
* \param[IN] currentUp - Uplink counter value
* \retval - Status of the operation
*/
LoRaMacCryptoStatus_t LoRaMacCryptoGetFCntUp( uint32_t* currentUp );
/*!
* Provides multicast context.
*
* \param[IN] multicastList - Pointer to the multicast context list
*
* \retval - Status of the operation
*/
LoRaMacCryptoStatus_t LoRaMacCryptoSetMulticastReference( MulticastCtx_t* multicastList );
/*!
* Sets a key
*
@@ -235,16 +300,28 @@ LoRaMacCryptoStatus_t LoRaMacCryptoSecureMessage( uint32_t fCntUp, uint8_t txDr,
LoRaMacCryptoStatus_t LoRaMacCryptoUnsecureMessage( AddressIdentifier_t addrID, uint32_t address, FCntIdentifier_t fCntID, uint32_t fCntDown, LoRaMacMessageData_t* macMsg );
/*!
* Derives the McKEKey from the AppKey or NwkKey.
* Derives the McRootKey from the AppKey.
*
* McKEKey = aes128_encrypt(NwkKey or AppKey , nonce | DevEUI | pad16)
* 1.0.x
* McRootKey = aes128_encrypt(AppKey, 0x00 | pad16)
*
* \param[IN] keyID - Key identifier of the root key to use to perform the derivation ( NwkKey or AppKey )
* \param[IN] nonce - Nonce value ( nonce <= 15)
* \param[IN] devEUI - DevEUI Value
* 1.1.x
* McRootKey = aes128_encrypt(AppKey, 0x20 | pad16)
*
* \param[IN] keyID - Key identifier of the root key to use to perform the derivation ( AppKey )
* \retval - Status of the operation
*/
LoRaMacCryptoStatus_t LoRaMacCryptoDeriveMcKEKey( KeyIdentifier_t keyID, uint16_t nonce, uint8_t* devEUI );
LoRaMacCryptoStatus_t LoRaMacCryptoDeriveMcRootKey( KeyIdentifier_t keyID );
/*!
* Derives the McKEKey from the McRootKey.
*
* McKEKey = aes128_encrypt(McRootKey , 0x00 | pad16)
*
* \param[IN] keyID - Key identifier of the root key to use to perform the derivation ( McRootKey )
* \retval - Status of the operation
*/
LoRaMacCryptoStatus_t LoRaMacCryptoDeriveMcKEKey( KeyIdentifier_t keyID );
/*!
* Derives a Multicast group key pair ( McAppSKey, McNwkSKey ) from McKey
@@ -260,4 +337,8 @@ LoRaMacCryptoStatus_t LoRaMacCryptoDeriveMcSessionKeyPair( AddressIdentifier_t a
/*! \} addtogroup LORAMAC */
#ifdef __cplusplus
}
#endif
#endif // __LORAMAC_CRYPTO_H__

View File

@@ -1,319 +0,0 @@
/*
/ _____) _ | |
( (____ _____ ____ _| |_ _____ ____| |__
\____ \| ___ | (_ _) ___ |/ ___) _ \
_____) ) ____| | | || |_| ____( (___| | | |
(______/|_____)_|_|_| \__)_____)\____)_| |_|
(C)2013 Semtech
___ _____ _ ___ _ _____ ___ ___ ___ ___
/ __|_ _/_\ / __| |/ / __/ _ \| _ \/ __| __|
\__ \ | |/ _ \ (__| ' <| _| (_) | / (__| _|
|___/ |_/_/ \_\___|_|\_\_| \___/|_|_\\___|___|
embedded.connectivity.solutions===============
Description: LoRa MAC layer frame counter handling implementation
License: Revised BSD License, see LICENSE.TXT file include in the project
Maintainer: Miguel Luis ( Semtech ), Daniel Jaeckle ( STACKFORCE ), Johannes Bruder ( STACKFORCE )
*/
#include <string.h>
#include "utilities.h"
#include "LoRaMacFCntHandler.h"
/*
* Initial value of the frame counters
*/
#define FCNT_DOWN_INITAL_VALUE 0xFFFFFFFF
/*!
* LoRaWAN Frame counter list.
*/
typedef struct sFCntList
{
/*
* Uplink frame counter which is incremented with each uplink.
*/
uint32_t FCntUp;
/*
* Network downlink frame counter which is incremented with each downlink on FPort 0
* or when the FPort field is missing.
*/
uint32_t NFCntDown;
/*
* Application downlink frame counter which is incremented with each downlink
* on a port different than 0.
*/
uint32_t AFCntDown;
/*
* In case if the device is connected to a LoRaWAN 1.0 Server,
* this counter is used for every kind of downlink frame.
*/
uint32_t FCntDown;
/*!
* Multicast downlink counter for index 0
*/
uint32_t McFCntDown0;
/*!
* Multicast downlink counter for index 1
*/
uint32_t McFCntDown1;
/*!
* Multicast downlink counter for index 2
*/
uint32_t McFCntDown2;
/*!
* Multicast downlink counter for index 3
*/
uint32_t McFCntDown3;
}FCntList_t;
/*
* LoRaMac Commands Context structure
*/
typedef struct sLoRaMacFCntHandlerNvmCtx
{
/*
* Frame counter list
*/
FCntList_t FCntList;
} LoRaMacFCntHandlerNvmCtx_t;
/*
* Non-volatile module context.
*/
static LoRaMacFCntHandlerNvmCtx_t FCntHandlerNvmCtx;
/*
* Callback function to notify the upper layer about context change
*/
static EventNvmCtxChanged FCntHandlerNvmCtxChanged;
/*
* \brief Wrapper function for the NvmCtx
*/
static void NvmCtxChanged( void )
{
if( FCntHandlerNvmCtxChanged != NULL )
{
FCntHandlerNvmCtxChanged( );
}
}
LoRaMacFCntHandlerStatus_t LoRaMacFCntHandlerInit( EventNvmCtxChanged fCntHandlerNvmCtxChanged )
{
// Initialize with default
LoRaMacResetFCnts( );
// Assign callback
FCntHandlerNvmCtxChanged = fCntHandlerNvmCtxChanged;
return LORAMAC_FCNT_HANDLER_SUCCESS;
}
LoRaMacFCntHandlerStatus_t LoRaMacFCntHandlerRestoreNvmCtx( void* fCntHandlerNvmCtx )
{
// Restore module context
if( fCntHandlerNvmCtx != NULL )
{
memcpy1( ( uint8_t* ) &FCntHandlerNvmCtx, ( uint8_t* ) fCntHandlerNvmCtx, sizeof( FCntHandlerNvmCtx ) );
return LORAMAC_FCNT_HANDLER_SUCCESS;
}
else
{
return LORAMAC_FCNT_HANDLER_ERROR_NPE;
}
}
void* LoRaMacFCntHandlerGetNvmCtx( size_t* fCntHandlerNvmCtxSize )
{
*fCntHandlerNvmCtxSize = sizeof( FCntHandlerNvmCtx );
return &FCntHandlerNvmCtx;
}
LoRaMacFCntHandlerStatus_t LoRaMacGetFCntDown( AddressIdentifier_t addrID, FType_t fType, LoRaMacMessageData_t* macMsg, Version_t lrWanVersion,
uint16_t maxFCntGap, FCntIdentifier_t* fCntID, uint32_t* currentDown )
{
uint32_t previousDown = 0;
int32_t fCntDiff = 0;
if( ( macMsg == NULL ) || ( fCntID == NULL ) ||
( currentDown == NULL ) )
{
return LORAMAC_FCNT_HANDLER_ERROR_NPE;
}
// Determine the frame counter identifier and choose counter from FCntList
switch( addrID )
{
case UNICAST_DEV_ADDR:
if( lrWanVersion.Fields.Minor == 1 )
{
if( ( fType == FRAME_TYPE_A ) || ( fType == FRAME_TYPE_D ) )
{
*fCntID = A_FCNT_DOWN;
previousDown = FCntHandlerNvmCtx.FCntList.AFCntDown;
}
else
{
*fCntID = N_FCNT_DOWN;
previousDown = FCntHandlerNvmCtx.FCntList.NFCntDown;
}
}
else
{ // For LoRaWAN 1.0.X
*fCntID = FCNT_DOWN;
previousDown = FCntHandlerNvmCtx.FCntList.FCntDown;
}
break;
case MULTICAST_0_ADDR:
*fCntID = MC_FCNT_DOWN_0;
previousDown = FCntHandlerNvmCtx.FCntList.McFCntDown0;
break;
case MULTICAST_1_ADDR:
*fCntID = MC_FCNT_DOWN_1;
previousDown = FCntHandlerNvmCtx.FCntList.McFCntDown1;
break;
case MULTICAST_2_ADDR:
*fCntID = MC_FCNT_DOWN_2;
previousDown = FCntHandlerNvmCtx.FCntList.McFCntDown3;
break;
case MULTICAST_3_ADDR:
*fCntID = MC_FCNT_DOWN_3;
previousDown = FCntHandlerNvmCtx.FCntList.McFCntDown3;
break;
default:
return LORAMAC_FCNT_HANDLER_ERROR;
}
// For LoRaWAN 1.0.X only, allow downlink frames of 0
if( previousDown == FCNT_DOWN_INITAL_VALUE )
{
*currentDown = macMsg->FHDR.FCnt;
}
else
{
// Add difference, consider roll-over
fCntDiff = ( int32_t )macMsg->FHDR.FCnt - ( int32_t )( previousDown & 0x0000FFFF );
if( fCntDiff > 0 )
{ // Positive difference
*currentDown = previousDown + fCntDiff;
}
else if( fCntDiff == 0 )
{ // Duplicate FCnt value, keep the current value.
*currentDown = previousDown;
return LORAMAC_FCNT_HANDLER_CHECK_FAIL;
}
else
{ // Negative difference, assume a roll-over of one uint16_t
*currentDown = ( previousDown & 0xFFFF0000 ) + 0x10000 + macMsg->FHDR.FCnt;
}
}
// For LoRaWAN 1.0.X only, check maxFCntGap
if( lrWanVersion.Fields.Minor == 0 )
{
if( ( ( int32_t )*currentDown - ( int32_t )previousDown ) >= maxFCntGap )
{
return LORAMAC_FCNT_HANDLER_MAX_GAP_FAIL;
}
}
return LORAMAC_FCNT_HANDLER_SUCCESS;
}
LoRaMacFCntHandlerStatus_t LoRaMacSetFCntDown( FCntIdentifier_t fCntID, uint32_t currentDown )
{
switch( fCntID )
{
case FCNT_UP:
return LORAMAC_FCNT_HANDLER_ERROR_INVALID_FCNT_ID;
case N_FCNT_DOWN:
FCntHandlerNvmCtx.FCntList.NFCntDown = currentDown;
break;
case A_FCNT_DOWN:
FCntHandlerNvmCtx.FCntList.AFCntDown = currentDown;
break;
case FCNT_DOWN:
FCntHandlerNvmCtx.FCntList.FCntDown = currentDown;
break;
case MC_FCNT_DOWN_0:
FCntHandlerNvmCtx.FCntList.McFCntDown0 = currentDown;
break;
case MC_FCNT_DOWN_1:
FCntHandlerNvmCtx.FCntList.McFCntDown1 = currentDown;
break;
case MC_FCNT_DOWN_2:
FCntHandlerNvmCtx.FCntList.McFCntDown2 = currentDown;
break;
case MC_FCNT_DOWN_3:
FCntHandlerNvmCtx.FCntList.McFCntDown3 = currentDown;
break;
default:
return LORAMAC_FCNT_HANDLER_ERROR;
}
NvmCtxChanged( );
return LORAMAC_FCNT_HANDLER_SUCCESS;
}
LoRaMacFCntHandlerStatus_t LoRaMacGetFCntUp( uint32_t* currentUp )
{
if( currentUp == NULL )
{
return LORAMAC_FCNT_HANDLER_ERROR_NPE;
}
*currentUp = FCntHandlerNvmCtx.FCntList.FCntUp + 1;
return LORAMAC_FCNT_HANDLER_SUCCESS;
}
LoRaMacFCntHandlerStatus_t LoRaMacSetFCntUp( uint32_t currentUp )
{
FCntHandlerNvmCtx.FCntList.FCntUp = currentUp;
NvmCtxChanged( );
return LORAMAC_FCNT_HANDLER_SUCCESS;
}
LoRaMacFCntHandlerStatus_t LoRaMacResetFCnts( void )
{
FCntHandlerNvmCtx.FCntList.FCntUp = 0;
FCntHandlerNvmCtx.FCntList.NFCntDown = FCNT_DOWN_INITAL_VALUE;
FCntHandlerNvmCtx.FCntList.AFCntDown = FCNT_DOWN_INITAL_VALUE;
FCntHandlerNvmCtx.FCntList.FCntDown = FCNT_DOWN_INITAL_VALUE;
FCntHandlerNvmCtx.FCntList.McFCntDown0 = FCNT_DOWN_INITAL_VALUE;
FCntHandlerNvmCtx.FCntList.McFCntDown1 = FCNT_DOWN_INITAL_VALUE;
FCntHandlerNvmCtx.FCntList.McFCntDown2 = FCNT_DOWN_INITAL_VALUE;
FCntHandlerNvmCtx.FCntList.McFCntDown3 = FCNT_DOWN_INITAL_VALUE;
NvmCtxChanged( );
return LORAMAC_FCNT_HANDLER_SUCCESS;
}
LoRaMacFCntHandlerStatus_t LoRaMacFCntHandlerSetMulticastReference( MulticastCtx_t* multicastList )
{
if( multicastList == NULL )
{
return LORAMAC_FCNT_HANDLER_ERROR_NPE;
}
multicastList[0].DownLinkCounter = &FCntHandlerNvmCtx.FCntList.McFCntDown0;
multicastList[1].DownLinkCounter = &FCntHandlerNvmCtx.FCntList.McFCntDown1;
multicastList[2].DownLinkCounter = &FCntHandlerNvmCtx.FCntList.McFCntDown2;
multicastList[3].DownLinkCounter = &FCntHandlerNvmCtx.FCntList.McFCntDown3;
return LORAMAC_FCNT_HANDLER_SUCCESS;
}

View File

@@ -1,170 +0,0 @@
/*!
* \file LoRaMacFCntHandler.h
*
* \brief LoRa MAC layer frame counter handling
*
* \copyright Revised BSD License, see section \ref LICENSE.
*
* \code
* ______ _
* / _____) _ | |
* ( (____ _____ ____ _| |_ _____ ____| |__
* \____ \| ___ | (_ _) ___ |/ ___) _ \
* _____) ) ____| | | || |_| ____( (___| | | |
* (______/|_____)_|_|_| \__)_____)\____)_| |_|
* (C)2013 Semtech
*
* ___ _____ _ ___ _ _____ ___ ___ ___ ___
* / __|_ _/_\ / __| |/ / __/ _ \| _ \/ __| __|
* \__ \ | |/ _ \ (__| ' <| _| (_) | / (__| _|
* |___/ |_/_/ \_\___|_|\_\_| \___/|_|_\\___|___|
* embedded.connectivity.solutions===============
*
* \endcode
*
* \author Miguel Luis ( Semtech )
*
* \author Daniel Jaeckle ( STACKFORCE )
*
* \author Johannes Bruder ( STACKFORCE )
*
* addtogroup LORAMAC
* \{
*
*/
#ifndef __LORAMAC_FCNT_HANDLER_H__
#define __LORAMAC_FCNT_HANDLER_H__
#include <stdint.h>
#include "LoRaMacTypes.h"
#include "LoRaMacMessageTypes.h"
/*!
* LoRaMac FCnt Handler Status
*/
typedef enum eLoRaMacFCntHandlerStatus
{
/*!
* No error occurred
*/
LORAMAC_FCNT_HANDLER_SUCCESS = 0,
/*!
* FCntUp/Down check failed
*/
LORAMAC_FCNT_HANDLER_CHECK_FAIL,
/*!
* The status idicates that the node has lost MAX_FCNT_GAP or more frames
*/
LORAMAC_FCNT_HANDLER_MAX_GAP_FAIL,
/*!
* Invalid frame counter identifier exception
*/
LORAMAC_FCNT_HANDLER_ERROR_INVALID_FCNT_ID,
/*!
* Null pointer exception
*/
LORAMAC_FCNT_HANDLER_ERROR_NPE,
/*!
* Undefined Error occurred
*/
LORAMAC_FCNT_HANDLER_ERROR,
}LoRaMacFCntHandlerStatus_t;
/*!
* Signature of callback function to be called by this module when the
* non-volatile needs to be saved.
*/
typedef void ( *EventNvmCtxChanged )( void );
/*!
* \brief Initialization of LoRaMac FCnt Handler module
*
* \param[IN] fCntHandlerNvmCtxChanged - Callback function which will be called when the
* non-volatile context needs to be saved.
*
* \retval - Status of the operation
*/
LoRaMacFCntHandlerStatus_t LoRaMacFCntHandlerInit( EventNvmCtxChanged fCntHandlerNvmCtxChanged );
/*!
* Restores the internal non-volatile context from passed pointer.
*
* \param[IN] fCntHandlerNvmCtx - Pointer to non-volatile FCnt handler module context to be restored.
*
* \retval - Status of the operation
*/
LoRaMacFCntHandlerStatus_t LoRaMacFCntHandlerRestoreNvmCtx( void* fCntHandlerNvmCtx );
/*!
* Returns a pointer to the internal non-volatile context.
*
* \param[IN] fCntHandlerNvmCtxSize - Size of the module non-volatile context
*
* \retval - Points to a structure where the module store its non-volatile context
*/
void* LoRaMacFCntHandlerGetNvmCtx( size_t* fCntHandlerNvmCtxSize );
/*!
* Computes next 32 bit downlink counter value and determines the frame counter ID.
*
* \param[IN] addrID - Address identifier
* \param[IN] fType - Frame type
* \param[IN] macMsg - Data message object, holding the current 16 bit transmitted frame counter
* \param[IN] lrWanVersion - LoRaWAN version
* \param[IN] maxFCntGap - Maximum allowed frame counter difference (only for 1.0.X necessary)
* \param[OUT] fCntID - Frame counter identifier
* \param[OUT] currentDown - Current downlink counter value
*
* \retval - Status of the operation
*/
LoRaMacFCntHandlerStatus_t LoRaMacGetFCntDown( AddressIdentifier_t addrID, FType_t fType, LoRaMacMessageData_t* macMsg, Version_t lrWanVersion,
uint16_t maxFCntGap, FCntIdentifier_t* fCntID, uint32_t* currentDown );
/*!
* Sets the downlink counter value according to the counter ID.
*
* \param[IN] fCntID - Frame counter identifier
* \param[IN] currentDown - Current downlink counter value
*
* \retval - Status of the operation
*/
LoRaMacFCntHandlerStatus_t LoRaMacSetFCntDown( FCntIdentifier_t fCntID, uint32_t currentDown );
/*!
* Computes next uplink counter value.
*
* \param[OUT] currentUp - Current uplink counter value
*
* \retval - Status of the operation
*/
LoRaMacFCntHandlerStatus_t LoRaMacGetFCntUp( uint32_t* currentUp );
/*!
* Sets the uplink counter value according to the counter ID.
*
* \param[IN] currentUp - Current uplink counter value
*
* \retval - Status of the operation
*/
LoRaMacFCntHandlerStatus_t LoRaMacSetFCntUp( uint32_t currentUp );
/*!
* Resets the value of FCntUp, NFCntDown, AFCntDown and FCntDown to zero
*
* \retval - Status of the operation
*/
LoRaMacFCntHandlerStatus_t LoRaMacResetFCnts( void );
/*!
* Sets the reference to the multicast downlink counter
*
* \param[IN] multicastList Pointer to the multicast list
*
* \retval - Status of the operation
*/
LoRaMacFCntHandlerStatus_t LoRaMacFCntHandlerSetMulticastReference( MulticastCtx_t* multicastList );
/*! \} addtogroup LORAMAC */
#endif // __LORAMAC_FCNT_HANDLER_H__

View File

@@ -37,23 +37,160 @@
#ifndef __LORAMAC_HEADER_TYPES_H__
#define __LORAMAC_HEADER_TYPES_H__
#ifdef __cplusplus
extern "C"
{
#endif
#include <stdint.h>
/*! Frame header (FHDR) maximum field size */
#define LORAMAC_FHDR_MAX_FIELD_SIZE 22
/*! MAC header field size */
#define LORAMAC_MHDR_FIELD_SIZE 1
/*! ReJoinType field size */
#define LORAMAC_JOIN_TYPE_FIELD_SIZE 1
/*! Join EUI field size */
#define LORAMAC_JOIN_EUI_FIELD_SIZE 8
/*! Device EUI field size */
#define LORAMAC_DEV_EUI_FIELD_SIZE 8
/*! End-device nonce field size */
#define LORAMAC_DEV_NONCE_FIELD_SIZE 2
/*! Join-server nonce field size */
#define LORAMAC_JOIN_NONCE_FIELD_SIZE 3
/*! RJcount0 field size */
#define LORAMAC_RJCOUNT_0_FIELD_SIZE 2
/*! RJcount1 field size */
#define LORAMAC_RJCOUNT_1_FIELD_SIZE 2
/*! Network ID field size */
#define LORAMAC_NET_ID_FIELD_SIZE 3
/*! Device address field size */
#define LORAMAC_DEV_ADDR_FIELD_SIZE 4
/*! DLSettings field size */
#define LORAMAC_DL_SETTINGS_FIELD_SIZE 1
/*! RxDelay field size */
#define LORAMAC_RX_DELAY_FIELD_SIZE 1
/*! CFList field size */
#define LORAMAC_CF_LIST_FIELD_SIZE 16
/*! FHDR Device address field size */
#define LORAMAC_FHDR_DEV_ADD_FIELD_SIZE 4
#define LORAMAC_FHDR_DEV_ADDR_FIELD_SIZE LORAMAC_DEV_ADDR_FIELD_SIZE
/*! FHDR Frame control field size */
#define LORAMAC_FHDR_F_CTRL_FIELD_SIZE 1
#define LORAMAC_FHDR_F_CTRL_FIELD_SIZE 1
/*! FHDR Frame control field size */
#define LORAMAC_FHDR_F_CNT_FIELD_SIZE 2
#define LORAMAC_FHDR_F_CNT_FIELD_SIZE 2
/*! FOpts maximum field size */
#define LORAMAC_FHDR_F_OPTS_MAX_FIELD_SIZE 15
#define LORAMAC_FHDR_F_OPTS_MAX_FIELD_SIZE 15
/*! Port field size */
#define LORAMAC_F_PORT_FIELD_SIZE 1
/*! Port field size */
#define LORAMAC_MAC_PAYLOAD_FIELD_MAX_SIZE 242
/*! MIC field size */
#define LORAMAC_MIC_FIELD_SIZE 4
/*!
* JoinRequest frame size
*
* MHDR(1) + JoinEUI(8) + DevEUI(8) + DevNonce(2) + MIC(4)
*/
#define LORAMAC_JOIN_REQ_MSG_SIZE ( LORAMAC_MHDR_FIELD_SIZE + LORAMAC_JOIN_EUI_FIELD_SIZE + \
LORAMAC_DEV_EUI_FIELD_SIZE + LORAMAC_DEV_NONCE_FIELD_SIZE + \
LORAMAC_MIC_FIELD_SIZE )
/*!
* ReJoinRequest type 1 frame size
*
* MHDR(1) + ReJoinType(1) + JoinEUI(8) + DevEUI(8) + RJcount1(2) + MIC(4)
*/
#define LORAMAC_RE_JOIN_1_MSG_SIZE ( LORAMAC_MHDR_FIELD_SIZE + LORAMAC_JOIN_TYPE_FIELD_SIZE + \
LORAMAC_JOIN_EUI_FIELD_SIZE + LORAMAC_DEV_EUI_FIELD_SIZE + \
LORAMAC_RJCOUNT_1_FIELD_SIZE + \
LORAMAC_MIC_FIELD_SIZE )
/*!
* ReJoinRequest type 0 or 2 frame size
*
* MHDR(1) + ReJoinType(1) + NetID(3) + DevEUI(8) + RJcount0(2) + MIC(4)
*/
#define LORAMAC_RE_JOIN_0_2_MSG_SIZE ( LORAMAC_MHDR_FIELD_SIZE + LORAMAC_JOIN_TYPE_FIELD_SIZE + \
LORAMAC_NET_ID_FIELD_SIZE + LORAMAC_DEV_EUI_FIELD_SIZE + \
LORAMAC_RJCOUNT_0_FIELD_SIZE + \
LORAMAC_MIC_FIELD_SIZE )
/*!
* JoinAccept frame minimum size
*
* MHDR(1) + AppNonce(3) + NetID(3) + DevAddr(4) + DLSettings(1) + RxDelay(1) + MIC(4)
*/
#define LORAMAC_JOIN_ACCEPT_FRAME_MIN_SIZE ( LORAMAC_MHDR_FIELD_SIZE + LORAMAC_JOIN_NONCE_FIELD_SIZE + \
LORAMAC_NET_ID_FIELD_SIZE + LORAMAC_DEV_ADDR_FIELD_SIZE + \
LORAMAC_DL_SETTINGS_FIELD_SIZE + LORAMAC_RX_DELAY_FIELD_SIZE + \
LORAMAC_MIC_FIELD_SIZE )
/*!
* JoinAccept frame maximum size
*
* MHDR(1) + AppNonce(3) + NetID(3) + DevAddr(4) + DLSettings(1) + RxDelay(1) + CFList(16) + MIC(4)
*/
#define LORAMAC_JOIN_ACCEPT_FRAME_MAX_SIZE ( LORAMAC_MHDR_FIELD_SIZE + LORAMAC_JOIN_NONCE_FIELD_SIZE + \
LORAMAC_NET_ID_FIELD_SIZE + LORAMAC_DEV_ADDR_FIELD_SIZE + \
LORAMAC_DL_SETTINGS_FIELD_SIZE + LORAMAC_RX_DELAY_FIELD_SIZE + \
LORAMAC_CF_LIST_FIELD_SIZE + LORAMAC_MIC_FIELD_SIZE )
/*!
* MIC computation offset
* \remark required for 1.1.x support
*/
#define JOIN_ACCEPT_MIC_COMPUTATION_OFFSET \
( LORAMAC_MHDR_FIELD_SIZE + LORAMAC_JOIN_TYPE_FIELD_SIZE + LORAMAC_JOIN_EUI_FIELD_SIZE + \
LORAMAC_DEV_NONCE_FIELD_SIZE )
/*!
* FRMPayload overhead to be used when setting the Radio.SetMaxPayloadLength
*
* Overhead to be used when setting the Radio.SetMaxPayloadLength in RxWindowSetup function.
*
* MHDR(1) + FHDR(7) + Port(1) + MIC(4)
*
* Maximum PHYPayload = MaxPayloadOfDatarate + LORAMAC_FRAME_PAYLOAD_OVERHEAD_SIZE
*/
#define LORAMAC_FRAME_PAYLOAD_OVERHEAD_SIZE ( LORAMAC_MHDR_FIELD_SIZE + ( LORAMAC_FHDR_DEV_ADDR_FIELD_SIZE + \
LORAMAC_FHDR_F_CTRL_FIELD_SIZE + LORAMAC_FHDR_F_CNT_FIELD_SIZE ) + \
LORAMAC_F_PORT_FIELD_SIZE + LORAMAC_MIC_FIELD_SIZE )
/*!
* FRMPayload minimum size
*
* MHDR(1) + FHDR(7) + MIC(4)
*/
#define LORAMAC_FRAME_PAYLOAD_MIN_SIZE ( LORAMAC_MHDR_FIELD_SIZE + ( LORAMAC_FHDR_DEV_ADDR_FIELD_SIZE + \
LORAMAC_FHDR_F_CTRL_FIELD_SIZE + LORAMAC_FHDR_F_CNT_FIELD_SIZE ) + \
LORAMAC_MIC_FIELD_SIZE )
/*!
* FRMPayload maximum possible size
*
* MHDR(1) + FHDR(7) + Port(1) + MACPayload(242) + MIC(4)
*/
#define LORAMAC_FRAME_PAYLOAD_MAX_SIZE ( LORAMAC_MHDR_FIELD_SIZE + ( LORAMAC_FHDR_DEV_ADDR_FIELD_SIZE + \
LORAMAC_FHDR_F_CTRL_FIELD_SIZE + LORAMAC_FHDR_F_CNT_FIELD_SIZE ) + \
LORAMAC_F_PORT_FIELD_SIZE + LORAMAC_MAC_PAYLOAD_FIELD_MAX_SIZE + \
LORAMAC_MIC_FIELD_SIZE )
/*!
* LoRaMAC field definition of DLSettings
@@ -183,4 +320,8 @@ typedef struct sLoRaMacFrameHeader
/*! \} addtogroup LORAMAC */
#ifdef __cplusplus
}
#endif
#endif // __LORAMAC_HEADER_TYPES_H__

View File

@@ -37,43 +37,14 @@
#ifndef __LORAMAC_MESSAGE_TYPES_H__
#define __LORAMAC_MESSAGE_TYPES_H__
#ifdef __cplusplus
extern "C"
{
#endif
#include <stdint.h>
#include "LoRaMacHeaderTypes.h"
/*! MAC header field size */
#define LORAMAC_MHDR_FIELD_SIZE 1
/*! Join EUI field size */
#define LORAMAC_JOIN_EUI_FIELD_SIZE 8
/*! Device EUI field size */
#define LORAMAC_DEV_EUI_FIELD_SIZE 8
/*! Join-server nonce field size */
#define LORAMAC_JOIN_NONCE_FIELD_SIZE 3
/*! Network ID field size */
#define LORAMAC_NET_ID_FIELD_SIZE 3
/*! Port field size */
#define LORAMAC_F_PORT_FIELD_SIZE 1
/*! CFList field size */
#define LORAMAC_C_FLIST_FIELD_SIZE 16
/*! MIC field size */
#define LORAMAC_MIC_FIELD_SIZE 4
/*! Join-request message size */
#define LORAMAC_JOIN_REQ_MSG_SIZE 23
/*! ReJoin-request type 1 message size */
#define LORAMAC_RE_JOIN_1_MSG_SIZE 24
/*! ReJoin-request type 0 or 2 message size */
#define LORAMAC_RE_JOIN_0_2_MSG_SIZE 19
/*!
* LoRaMac type for Join-request message
*/
@@ -324,4 +295,8 @@ typedef struct sLoRaMacMessage
/*! \} addtogroup LORAMAC */
#ifdef __cplusplus
}
#endif
#endif // __LORAMAC_MESSAGE_TYPES_H__

View File

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

View File

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

View File

@@ -107,7 +107,7 @@ LoRaMacSerializerStatus_t LoRaMacSerializerReJoinType0or2( LoRaMacMessageReJoinT
macMsg->Buffer[bufItr++] = macMsg->ReJoinType;
memcpyr( &macMsg->Buffer[bufItr], macMsg->NetID, LORAMAC_NET_ID_FIELD_SIZE );
memcpy1( &macMsg->Buffer[bufItr], macMsg->NetID, LORAMAC_NET_ID_FIELD_SIZE );
bufItr += LORAMAC_NET_ID_FIELD_SIZE;
memcpyr( &macMsg->Buffer[bufItr], macMsg->DevEUI, LORAMAC_DEV_EUI_FIELD_SIZE );
@@ -130,23 +130,23 @@ LoRaMacSerializerStatus_t LoRaMacSerializerData( LoRaMacMessageData_t* macMsg )
// Check macMsg->BufSize
uint16_t computedBufSize = LORAMAC_MHDR_FIELD_SIZE
+ LORAMAC_FHDR_DEV_ADD_FIELD_SIZE
+ LORAMAC_FHDR_DEV_ADDR_FIELD_SIZE
+ LORAMAC_FHDR_F_CTRL_FIELD_SIZE
+ LORAMAC_FHDR_F_CNT_FIELD_SIZE;
if( macMsg->FRMPayloadSize == 0 )
computedBufSize += macMsg->FHDR.FCtrl.Bits.FOptsLen;
if( macMsg->FRMPayloadSize > 0 )
{
if( macMsg->BufSize < computedBufSize )
{
return LORAMAC_SERIALIZER_ERROR_BUF_SIZE;
}
computedBufSize += LORAMAC_F_PORT_FIELD_SIZE;
}
else
{ //If FRMPayload >0, FPort field is present.
if( macMsg->BufSize < computedBufSize + macMsg->FHDR.FCtrl.Bits.FOptsLen + macMsg->FRMPayloadSize + LORAMAC_F_PORT_FIELD_SIZE )
{
return LORAMAC_SERIALIZER_ERROR_BUF_SIZE;
}
computedBufSize += macMsg->FRMPayloadSize;
computedBufSize += LORAMAC_MIC_FIELD_SIZE;
if( macMsg->BufSize < computedBufSize )
{
return LORAMAC_SERIALIZER_ERROR_BUF_SIZE;
}
macMsg->Buffer[bufItr++] = macMsg->MHDR.Value;

View File

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

View File

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

View File

@@ -35,6 +35,11 @@
#ifndef __LORAMAC_TYPES_H__
#define __LORAMAC_TYPES_H__
#ifdef __cplusplus
extern "C"
{
#endif
#include <stdint.h>
#include <stdbool.h>
#include "timer.h"
@@ -47,7 +52,34 @@
/*!
* Start value for multicast keys enumeration
*/
#define LORAMAC_CRYPTO_MULITCAST_KEYS 127
#define LORAMAC_CRYPTO_MULTICAST_KEYS 127
/*!
* LoRaWAN devices classes definition
*
* LoRaWAN Specification V1.0.2, chapter 2.1
*/
typedef enum DeviceClass_e
{
/*!
* LoRaWAN device class A
*
* LoRaWAN Specification V1.0.2, chapter 3
*/
CLASS_A = 0x00,
/*!
* LoRaWAN device class B
*
* LoRaWAN Specification V1.0.2, chapter 8
*/
CLASS_B = 0x01,
/*!
* LoRaWAN device class C
*
* LoRaWAN Specification V1.0.2, chapter 17
*/
CLASS_C = 0x02,
}DeviceClass_t;
/*!
* LoRaWAN Frame type enumeration to differ between the possible data up/down frame configurations.
@@ -162,10 +194,14 @@ typedef enum eKeyIdentifier
* Application session key
*/
APP_S_KEY,
/*!
* Multicast root key
*/
MC_ROOT_KEY,
/*!
* Multicast key encryption key
*/
MC_KE_KEY = LORAMAC_CRYPTO_MULITCAST_KEYS,
MC_KE_KEY = LORAMAC_CRYPTO_MULTICAST_KEYS,
/*!
* Multicast root key index 0
*/
@@ -251,40 +287,121 @@ typedef enum eAddressIdentifier
UNICAST_DEV_ADDR = 4,
}AddressIdentifier_t;
/*!
* Multicast context
/*
* Multicast Rx window parameters
*/
typedef struct sMulticastCtx
typedef union uMcRxParams
{
struct
{
/*!
* Reception frequency of the ping slot windows
*/
uint32_t Frequency;
/*!
* Datarate of the ping slot
*/
int8_t Datarate;
/*!
* This parameter is necessary for class B operation. It defines the
* periodicity of the multicast downlink slots
*/
uint16_t Periodicity;
}ClassB;
struct
{
/*!
* Reception frequency of the ping slot windows
*/
uint32_t Frequency;
/*!
* Datarate of the ping slot
*/
int8_t Datarate;
}ClassC;
}McRxParams_t;
/*!
* Multicast channel
*/
typedef struct sMcChannelParams
{
/*!
* Indicate if the multicast channel is being setup remotely or locally.
* Indicates which set of keys are to be used. \ref uMcKeys
*/
bool IsRemotelySetup;
/*!
* Multicats channel LoRaWAN class B or C
*/
DeviceClass_t Class;
/*!
* True if the entry is active
*/
bool IsEnabled;
/*
* Address identifier
*/
AddressIdentifier_t AddrID;
AddressIdentifier_t GroupID;
/*!
* Address
*/
uint32_t Address;
/*!
* Multicast keys
*/
union uMcKeys
{
/*!
* Encrypted multicast key - Used when IsRemotelySetup equals `true`.
* MC_KEY is decrypted and then the session keys ar derived.
*/
uint8_t *McKeyE;
/*!
* Multicast Session keys - Used when IsRemotelySetup equals `false`
*/
struct
{
/*!
* Multicast application session key
*/
uint8_t *McAppSKey;
/*!
* Multicast network session key
*/
uint8_t *McNwkSKey;
}Session;
}McKeys;
/*!
* Minimum multicast frame counter value
*/
uint32_t FCountMin;
/*!
* Maximum multicast frame counter value
*/
uint32_t FCountMax;
/*!
* Multicast reception parameters
*/
McRxParams_t RxParams;
}McChannelParams_t;
/*!
* Multicast context
*/
typedef struct sMulticastCtx
{
/*!
* Multicast channel parameters
*/
McChannelParams_t ChannelParams;
/*!
* Downlink counter
*/
uint32_t* DownLinkCounter;
/*!
* True if the entry is active
/*
* Following parameters are only used for ClassB multicast channels
*/
bool IsEnabled;
/*!
* Reception frequency of the ping slot windows
*/
uint32_t Frequency;
/*!
* Datarate of the ping slot
*/
int8_t Datarate;
/*!
* This parameter is necessary for class b operation. It defines the
* periodicity of the multicast downlink slots
*/
uint16_t Periodicity;
/*!
* Number of multicast slots. The variable can be
* calculated as follows:
@@ -475,17 +592,24 @@ typedef struct sBand
*/
int8_t TxMaxPower;
/*!
* Time stamp of the last JoinReq Tx frame.
* The last time the band has been
* synchronized with the current time
*/
TimerTime_t LastJoinTxDoneTime;
TimerTime_t LastBandUpdateTime;
/*!
* Time stamp of the last Tx frame
* Current time credits which are available. This
* is a value in ms
*/
TimerTime_t LastTxDoneTime;
TimerTime_t TimeCredits;
/*!
* Holds the time where the device is off
* Maximum time credits which are available. This
* is a value in ms
*/
TimerTime_t TimeOff;
TimerTime_t MaxTimeCredits;
/*!
* Set to true when the band is ready for use.
*/
bool ReadyForTransmission;
}Band_t;
/*!
@@ -548,5 +672,9 @@ typedef enum eLoRaMacBatteryLevel
BAT_LEVEL_NO_MEASURE = 0xFF,
}LoRaMacBatteryLevel_t;
#ifdef __cplusplus
}
#endif
#endif // __LORAMAC_TYPES_H__

View File

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

View File

@@ -52,17 +52,32 @@
#ifndef __REGION_H__
#define __REGION_H__
#ifdef __cplusplus
extern "C"
{
#endif
#include <stdint.h>
#include <stdbool.h>
#include "utilities.h"
#include "LoRaMac.h"
#include "timer.h"
#include "RegionCommon.h"
/*!
* Macro to compute bit of a channel index.
*/
#define LC( channelIndex ) ( uint16_t )( 1 << ( channelIndex - 1 ) )
#ifndef REGION_VERSION
/*!
* Regional parameters version definition.
*/
#define REGION_VERSION 0x00010003
#endif
/*!
* Region | SF
* ------------ | :-----:
@@ -476,7 +491,7 @@
* EU868 | -
* IN865 | Max EIRP - 18
* KR920 | -
* US915 | Max ERP - 16
* US915 | Max ERP - 18
* RU864 | -
*/
#define TX_POWER_9 9
@@ -492,28 +507,72 @@
* EU868 | -
* IN865 | Max EIRP - 20
* KR920 | -
* US915 | Max ERP - 10
* US915 | Max ERP - 20
* RU864 | -
*/
#define TX_POWER_10 10
/*!
* RFU
* Region | dBM
* ------------ | :-----:
* AS923 | -
* AU915 | Max EIRP - 22
* CN470 | -
* CN779 | -
* EU433 | -
* EU868 | -
* IN865 | -
* KR920 | -
* US915 | Max ERP - 22
* RU864 | -
*/
#define TX_POWER_11 11
/*!
* RFU
* Region | dBM
* ------------ | :-----:
* AS923 | -
* AU915 | Max EIRP - 24
* CN470 | -
* CN779 | -
* EU433 | -
* EU868 | -
* IN865 | -
* KR920 | -
* US915 | Max ERP - 24
* RU864 | -
*/
#define TX_POWER_12 12
/*!
* RFU
* Region | dBM
* ------------ | :-----:
* AS923 | -
* AU915 | Max EIRP - 26
* CN470 | -
* CN779 | -
* EU433 | -
* EU868 | -
* IN865 | -
* KR920 | -
* US915 | Max ERP - 26
* RU864 | -
*/
#define TX_POWER_13 13
/*!
* RFU
* Region | dBM
* ------------ | :-----:
* AS923 | -
* AU915 | Max EIRP - 28
* CN470 | -
* CN779 | -
* EU433 | -
* EU868 | -
* IN865 | -
* KR920 | -
* US915 | Max ERP - 28
* RU864 | -
*/
#define TX_POWER_14 14
@@ -529,6 +588,11 @@
*/
typedef enum ePhyAttribute
{
/*!
* Frequency. It is available
* to perform a verification with RegionVerify().
*/
PHY_FREQUENCY,
/*!
* Minimum RX datarate.
*/
@@ -585,10 +649,6 @@ typedef enum ePhyAttribute
* Maximum payload possible.
*/
PHY_MAX_PAYLOAD,
/*!
* Maximum payload possible when repeater support is enabled.
*/
PHY_MAX_PAYLOAD_REPEATER,
/*!
* Duty cycle.
*/
@@ -743,10 +803,26 @@ typedef enum ePhyAttribute
* The number of channels for the beacon reception.
*/
PHY_BEACON_NB_CHANNELS,
/*!
* Ping slot channel frequency.
*/
PHY_PING_SLOT_CHANNEL_FREQ,
/*!
* The datarate of a ping slot channel.
*/
PHY_PING_SLOT_CHANNEL_DR
PHY_PING_SLOT_CHANNEL_DR,
/*
* The number of channels for the ping slot reception.
*/
PHY_PING_SLOT_NB_CHANNELS,
/*!
* The equivalent spreading factor value from datarate
*/
PHY_SF_FROM_DR,
/*!
* The equivalent bandwith index from datarate
*/
PHY_BW_FROM_DR,
}PhyAttribute_t;
/*!
@@ -754,6 +830,10 @@ typedef enum ePhyAttribute
*/
typedef enum eInitType
{
/*!
* Initializes the band definitions.
*/
INIT_TYPE_BANDS,
/*!
* Initializes the region specific data to defaults, according to the
* LoRaWAN specification.
@@ -825,6 +905,10 @@ typedef union uPhyParam
* Beacon format
*/
BeaconFormat_t BeaconFormat;
/*!
* Duty Cycle Period
*/
TimerTime_t DutyCycleTimePeriod;
}PhyParam_t;
/*!
@@ -839,23 +923,29 @@ typedef struct sGetPhyParams
/*!
* Datarate.
* The parameter is needed for the following queries:
* PHY_MAX_PAYLOAD, PHY_MAX_PAYLOAD_REPEATER, PHY_NEXT_LOWER_TX_DR.
* PHY_MAX_PAYLOAD, PHY_NEXT_LOWER_TX_DR, PHY_SF_FROM_DR, PHY_BW_FROM_DR.
*/
int8_t Datarate;
/*!
* Uplink dwell time. This parameter must be set to query:
* PHY_MAX_PAYLOAD, PHY_MAX_PAYLOAD_REPEATER, PHY_MIN_TX_DR.
* PHY_MAX_PAYLOAD, PHY_MIN_TX_DR.
* The parameter is needed for the following queries:
* PHY_MIN_TX_DR, PHY_MAX_PAYLOAD, PHY_MAX_PAYLOAD_REPEATER, PHY_NEXT_LOWER_TX_DR.
* PHY_MIN_TX_DR, PHY_MAX_PAYLOAD, PHY_NEXT_LOWER_TX_DR.
*/
uint8_t UplinkDwellTime;
/*!
* Downlink dwell time. This parameter must be set to query:
* PHY_MAX_PAYLOAD, PHY_MAX_PAYLOAD_REPEATER, PHY_MIN_RX_DR.
* PHY_MAX_PAYLOAD, PHY_MIN_RX_DR.
* The parameter is needed for the following queries:
* PHY_MIN_RX_DR, PHY_MAX_PAYLOAD, PHY_MAX_PAYLOAD_REPEATER.
* PHY_MIN_RX_DR, PHY_MAX_PAYLOAD.
*/
uint8_t DownlinkDwellTime;
/*!
* Specification of the downlink channel. Used in Class B only.
* The parameter is needed for the following queries:
* PHY_BEACON_CHANNEL_FREQ, PHY_PING_SLOT_CHANNEL_FREQ
*/
uint8_t Channel;
}GetPhyParams_t;
/*!
@@ -875,6 +965,14 @@ typedef struct sSetBandTxDoneParams
* Last TX done time.
*/
TimerTime_t LastTxDoneTime;
/*!
* Time-on-air of the last transmission.
*/
TimerTime_t LastTxAirTime;
/*!
* Elapsed time since initialization.
*/
SysTime_t ElapsedTimeSinceStartUp;
}SetBandTxDoneParams_t;
/*!
@@ -909,6 +1007,10 @@ typedef struct sGetNvmCtxParams
*/
typedef union uVerifyParams
{
/*!
* Channel frequency to verify
*/
uint32_t Frequency;
/*!
* TX power to verify.
*/
@@ -1004,10 +1106,6 @@ typedef struct sRxConfigParams
* Downlink dwell time.
*/
uint8_t DownlinkDwellTime;
/*!
* Set to true, if a repeater is supported.
*/
bool RepeaterSupport;
/*!
* Set to true, if RX should be continuous.
*/
@@ -1171,37 +1269,6 @@ typedef enum eAlternateDrType
ALTERNATE_DR_RESTORE
}AlternateDrType_t;
/*!
* Parameter structure for the function RegionCalcBackOff.
*/
typedef struct sCalcBackOffParams
{
/*!
* Set to true, if the node has already joined a network, otherwise false.
*/
bool Joined;
/*!
* Joined Set to true, if the last uplink was a join request
*/
bool LastTxIsJoinRequest;
/*!
* Set to true, if the duty cycle is enabled, otherwise false.
*/
bool DutyCycleEnabled;
/*!
* Current channel index.
*/
uint8_t Channel;
/*!
* Elapsed time since the start of the node.
*/
SysTime_t ElapsedTime;
/*!
* Time-on-air of the last transmission.
*/
TimerTime_t TxTimeOnAir;
}CalcBackOffParams_t;
/*!
* Parameter structure for the function RegionNextChannel.
*/
@@ -1227,6 +1294,18 @@ typedef struct sNextChanParams
* Set to true, if the duty cycle is enabled, otherwise false.
*/
bool DutyCycleEnabled;
/*!
* Elapsed time since the start of the node.
*/
SysTime_t ElapsedTimeSinceStartUp;
/*!
* Joined Set to true, if the last uplink was a join request
*/
bool LastTxIsJoinRequest;
/*!
* Payload length of the next frame
*/
uint16_t PktLen;
}NextChanParams_t;
/*!
@@ -1552,15 +1631,6 @@ uint8_t RegionDlChannelReq( LoRaMacRegion_t region, DlChannelReqParams_t* dlChan
*/
int8_t RegionAlternateDr( LoRaMacRegion_t region, int8_t currentDr, AlternateDrType_t type );
/*!
* \brief Calculates the back-off time.
*
* \param [IN] region LoRaWAN region.
*
* \param [IN] calcBackOff Pointer to the function parameters.
*/
void RegionCalcBackOff( LoRaMacRegion_t region, CalcBackOffParams_t* calcBackOff );
/*!
* \brief Searches and set the next random available channel
*
@@ -1630,6 +1700,17 @@ uint8_t RegionApplyDrOffset( LoRaMacRegion_t region, uint8_t downlinkDwellTime,
*/
void RegionRxBeaconSetup( LoRaMacRegion_t region, RxBeaconSetup_t* rxBeaconSetup, uint8_t* outDr );
/*!
* \brief Gets the version of the regional parameters implementation.
*
* \retval Version of the regional parameters.
*/
Version_t RegionGetVersion( void );
/*! \} defgroup REGION */
#ifdef __cplusplus
}
#endif
#endif // __REGION_H__

View File

@@ -119,45 +119,21 @@ static bool VerifyRfFreq( uint32_t freq )
return true;
}
static uint8_t CountNbOfEnabledChannels( bool joined, uint8_t datarate, uint16_t* channelsMask, ChannelParams_t* channels, Band_t* bands, uint8_t* enabledChannels, uint8_t* delayTx )
static TimerTime_t GetTimeOnAir( int8_t datarate, uint16_t pktLen )
{
uint8_t nbEnabledChannels = 0;
uint8_t delayTransmission = 0;
int8_t phyDr = DataratesAS923[datarate];
uint32_t bandwidth = GetBandwidth( datarate );
TimerTime_t timeOnAir = 0;
for( uint8_t i = 0, k = 0; i < AS923_MAX_NB_CHANNELS; i += 16, k++ )
{
for( uint8_t j = 0; j < 16; j++ )
{
if( ( channelsMask[k] & ( 1 << j ) ) != 0 )
{
if( channels[i + j].Frequency == 0 )
{ // Check if the channel is enabled
continue;
}
if( joined == false )
{
if( ( AS923_JOIN_CHANNELS & ( 1 << j ) ) == 0 )
{
continue;
}
}
if( RegionCommonValueInRange( datarate, channels[i + j].DrRange.Fields.Min,
channels[i + j].DrRange.Fields.Max ) == false )
{ // Check if the current channel selection supports the given datarate
continue;
}
if( bands[channels[i + j].Band].TimeOff > 0 )
{ // Check if the band is available for transmission
delayTransmission++;
continue;
}
enabledChannels[nbEnabledChannels++] = i + j;
}
}
if( datarate == DR_7 )
{ // High Speed FSK channel
timeOnAir = Radio.TimeOnAir( MODEM_FSK, bandwidth, phyDr * 1000, 0, 5, false, pktLen, true );
}
*delayTx = delayTransmission;
return nbEnabledChannels;
else
{
timeOnAir = Radio.TimeOnAir( MODEM_LORA, bandwidth, phyDr, 1, 8, false, pktLen, true );
}
return timeOnAir;
}
PhyParam_t RegionAS923GetPhyParam( GetPhyParams_t* getPhy )
@@ -239,18 +215,6 @@ PhyParam_t RegionAS923GetPhyParam( GetPhyParams_t* getPhy )
}
break;
}
case PHY_MAX_PAYLOAD_REPEATER:
{
if( getPhy->UplinkDwellTime == 0 )
{
phyParam.Value = MaxPayloadOfDatarateRepeaterDwell0AS923[getPhy->Datarate];
}
else
{
phyParam.Value = MaxPayloadOfDatarateDwell1UpAS923[getPhy->Datarate];
}
break;
}
case PHY_DUTY_CYCLE:
{
phyParam.Value = AS923_DUTY_CYCLE_ENABLED;
@@ -363,11 +327,26 @@ PhyParam_t RegionAS923GetPhyParam( GetPhyParams_t* getPhy )
phyParam.Value = AS923_BEACON_CHANNEL_DR;
break;
}
case PHY_PING_SLOT_CHANNEL_FREQ:
{
phyParam.Value = AS923_PING_SLOT_CHANNEL_FREQ;
break;
}
case PHY_PING_SLOT_CHANNEL_DR:
{
phyParam.Value = AS923_PING_SLOT_CHANNEL_DR;
break;
}
case PHY_SF_FROM_DR:
{
phyParam.Value = DataratesAS923[getPhy->Datarate];
break;
}
case PHY_BW_FROM_DR:
{
phyParam.Value = GetBandwidth( getPhy->Datarate );
break;
}
default:
{
break;
@@ -379,7 +358,8 @@ PhyParam_t RegionAS923GetPhyParam( GetPhyParams_t* getPhy )
void RegionAS923SetBandTxDone( SetBandTxDoneParams_t* txDone )
{
RegionCommonSetBandTxDone( txDone->Joined, &NvmCtx.Bands[NvmCtx.Channels[txDone->Channel].Band], txDone->LastTxDoneTime );
RegionCommonSetBandTxDone( &NvmCtx.Bands[NvmCtx.Channels[txDone->Channel].Band],
txDone->LastTxAirTime, txDone->Joined, txDone->ElapsedTimeSinceStartUp );
}
void RegionAS923InitDefaults( InitDefaultsParams_t* params )
@@ -391,10 +371,14 @@ void RegionAS923InitDefaults( InitDefaultsParams_t* params )
switch( params->Type )
{
case INIT_TYPE_INIT:
case INIT_TYPE_BANDS:
{
// Initialize bands
memcpy1( ( uint8_t* )NvmCtx.Bands, ( uint8_t* )bands, sizeof( Band_t ) * AS923_MAX_NB_BANDS );
break;
}
case INIT_TYPE_INIT:
{
// Channels
NvmCtx.Channels[0] = ( ChannelParams_t ) AS923_LC1;
@@ -402,6 +386,7 @@ void RegionAS923InitDefaults( InitDefaultsParams_t* params )
// Initialize the channels default mask
NvmCtx.ChannelsDefaultMask[0] = LC( 1 ) + LC( 2 );
// Update the channels mask
RegionCommonChanMaskCopy( NvmCtx.ChannelsMask, NvmCtx.ChannelsDefaultMask, 1 );
break;
@@ -418,6 +403,10 @@ void RegionAS923InitDefaults( InitDefaultsParams_t* params )
{
// Restore channels default mask
NvmCtx.ChannelsMask[0] |= NvmCtx.ChannelsDefaultMask[0];
// Channels
NvmCtx.Channels[0] = ( ChannelParams_t ) AS923_LC1;
NvmCtx.Channels[1] = ( ChannelParams_t ) AS923_LC2;
break;
}
default:
@@ -437,6 +426,10 @@ bool RegionAS923Verify( VerifyParams_t* verify, PhyAttribute_t phyAttribute )
{
switch( phyAttribute )
{
case PHY_FREQUENCY:
{
return VerifyRfFreq( verify->Frequency );
}
case PHY_TX_DR:
{
if( verify->DatarateParams.UplinkDwellTime == 0 )
@@ -581,7 +574,6 @@ bool RegionAS923RxConfig( RxConfigParams_t* rxConfig, int8_t* datarate )
{
RadioModems_t modem;
int8_t dr = rxConfig->Datarate;
uint8_t maxPayload = 0;
int8_t phyDr = 0;
uint32_t frequency = rxConfig->Frequency;
@@ -618,17 +610,7 @@ bool RegionAS923RxConfig( RxConfigParams_t* rxConfig, int8_t* datarate )
Radio.SetRxConfig( modem, rxConfig->Bandwidth, phyDr, 1, 0, 8, rxConfig->WindowTimeout, false, 0, false, 0, 0, true, rxConfig->RxContinuous );
}
// Check for repeater support
if( rxConfig->RepeaterSupport == true )
{
maxPayload = MaxPayloadOfDatarateRepeaterDwell0AS923[dr];
}
else
{
maxPayload = MaxPayloadOfDatarateDwell0AS923[dr];
}
Radio.SetMaxPayloadLength( modem, maxPayload + LORA_MAC_FRMPAYLOAD_OVERHEAD );
Radio.SetMaxPayloadLength( modem, MaxPayloadOfDatarateDwell0AS923[dr] + LORAMAC_FRAME_PAYLOAD_OVERHEAD_SIZE );
*datarate = (uint8_t) dr;
return true;
@@ -651,18 +633,19 @@ bool RegionAS923TxConfig( TxConfigParams_t* txConfig, int8_t* txPower, TimerTime
if( txConfig->Datarate == DR_7 )
{ // High Speed FSK channel
modem = MODEM_FSK;
Radio.SetTxConfig( modem, phyTxPower, 25000, bandwidth, phyDr * 1000, 0, 5, false, true, 0, 0, false, 3000 );
Radio.SetTxConfig( modem, phyTxPower, 25000, bandwidth, phyDr * 1000, 0, 5, false, true, 0, 0, false, 4000 );
}
else
{
modem = MODEM_LORA;
Radio.SetTxConfig( modem, phyTxPower, 0, bandwidth, phyDr, 1, 8, false, true, 0, 0, false, 3000 );
Radio.SetTxConfig( modem, phyTxPower, 0, bandwidth, phyDr, 1, 8, false, true, 0, 0, false, 4000 );
}
// Update time-on-air
*txTimeOnAir = GetTimeOnAir( txConfig->Datarate, txConfig->PktLen );
// Setup maximum payload lenght of the radio driver
Radio.SetMaxPayloadLength( modem, txConfig->PktLen );
// Get the time-on-air of the next tx frame
*txTimeOnAir = Radio.TimeOnAir( modem, txConfig->PktLen );
*txPower = txPowerLimited;
return true;
@@ -888,55 +871,45 @@ int8_t RegionAS923AlternateDr( int8_t currentDr, AlternateDrType_t type )
return AS923_DWELL_LIMIT_DATARATE;
}
void RegionAS923CalcBackOff( CalcBackOffParams_t* calcBackOff )
{
RegionCommonCalcBackOffParams_t calcBackOffParams;
calcBackOffParams.Channels = NvmCtx.Channels;
calcBackOffParams.Bands = NvmCtx.Bands;
calcBackOffParams.LastTxIsJoinRequest = calcBackOff->LastTxIsJoinRequest;
calcBackOffParams.Joined = calcBackOff->Joined;
calcBackOffParams.DutyCycleEnabled = calcBackOff->DutyCycleEnabled;
calcBackOffParams.Channel = calcBackOff->Channel;
calcBackOffParams.ElapsedTime = calcBackOff->ElapsedTime;
calcBackOffParams.TxTimeOnAir = calcBackOff->TxTimeOnAir;
RegionCommonCalcBackOff( &calcBackOffParams );
}
LoRaMacStatus_t RegionAS923NextChannel( NextChanParams_t* nextChanParams, uint8_t* channel, TimerTime_t* time, TimerTime_t* aggregatedTimeOff )
{
uint8_t channelNext = 0;
uint8_t nbEnabledChannels = 0;
uint8_t delayTx = 0;
uint8_t nbRestrictedChannels = 0;
uint8_t enabledChannels[AS923_MAX_NB_CHANNELS] = { 0 };
TimerTime_t nextTxDelay = 0;
RegionCommonIdentifyChannelsParam_t identifyChannelsParam;
RegionCommonCountNbOfEnabledChannelsParams_t countChannelsParams;
LoRaMacStatus_t status = LORAMAC_STATUS_NO_CHANNEL_FOUND;
if( RegionCommonCountChannels( NvmCtx.ChannelsMask, 0, 1 ) == 0 )
{ // Reactivate default channels
NvmCtx.ChannelsMask[0] |= LC( 1 ) + LC( 2 );
}
if( nextChanParams->AggrTimeOff <= TimerGetElapsedTime( nextChanParams->LastAggrTx ) )
{
// Reset Aggregated time off
*aggregatedTimeOff = 0;
// Search how many channels are enabled
countChannelsParams.Joined = nextChanParams->Joined;
countChannelsParams.Datarate = nextChanParams->Datarate;
countChannelsParams.ChannelsMask = NvmCtx.ChannelsMask;
countChannelsParams.Channels = NvmCtx.Channels;
countChannelsParams.Bands = NvmCtx.Bands;
countChannelsParams.MaxNbChannels = AS923_MAX_NB_CHANNELS;
countChannelsParams.JoinChannels = AS923_JOIN_CHANNELS;
// Update bands Time OFF
nextTxDelay = RegionCommonUpdateBandTimeOff( nextChanParams->Joined, nextChanParams->DutyCycleEnabled, NvmCtx.Bands, AS923_MAX_NB_BANDS );
identifyChannelsParam.AggrTimeOff = nextChanParams->AggrTimeOff;
identifyChannelsParam.LastAggrTx = nextChanParams->LastAggrTx;
identifyChannelsParam.DutyCycleEnabled = nextChanParams->DutyCycleEnabled;
identifyChannelsParam.MaxBands = AS923_MAX_NB_BANDS;
// Search how many channels are enabled
nbEnabledChannels = CountNbOfEnabledChannels( nextChanParams->Joined, nextChanParams->Datarate,
NvmCtx.ChannelsMask, NvmCtx.Channels,
NvmCtx.Bands, enabledChannels, &delayTx );
}
else
{
delayTx++;
nextTxDelay = nextChanParams->AggrTimeOff - TimerGetElapsedTime( nextChanParams->LastAggrTx );
}
identifyChannelsParam.ElapsedTimeSinceStartUp = nextChanParams->ElapsedTimeSinceStartUp;
identifyChannelsParam.LastTxIsJoinRequest = nextChanParams->LastTxIsJoinRequest;
identifyChannelsParam.ExpectedTimeOnAir = GetTimeOnAir( nextChanParams->Datarate, nextChanParams->PktLen );
if( nbEnabledChannels > 0 )
identifyChannelsParam.CountNbOfEnabledChannelsParam = &countChannelsParams;
status = RegionCommonIdentifyChannels( &identifyChannelsParam, aggregatedTimeOff, enabledChannels,
&nbEnabledChannels, &nbRestrictedChannels, time );
if( status == LORAMAC_STATUS_OK )
{
for( uint8_t i = 0, j = randr( 0, nbEnabledChannels - 1 ); i < AS923_MAX_NB_CHANNELS; i++ )
{
@@ -949,25 +922,19 @@ LoRaMacStatus_t RegionAS923NextChannel( NextChanParams_t* nextChanParams, uint8_
{
// Free channel found
*channel = channelNext;
*time = 0;
return LORAMAC_STATUS_OK;
}
}
return LORAMAC_STATUS_NO_FREE_CHANNEL_FOUND;
// Even if one or more channels are available according to the channel plan, no free channel
// was found during the LBT procedure.
status = LORAMAC_STATUS_NO_FREE_CHANNEL_FOUND;
}
else
else if( status == LORAMAC_STATUS_NO_CHANNEL_FOUND )
{
if( delayTx > 0 )
{
// Delay transmission due to AggregatedTimeOff or to a band time off
*time = nextTxDelay;
return LORAMAC_STATUS_DUTYCYCLE_RESTRICTED;
}
// Datarate not supported by any channel, restore defaults
NvmCtx.ChannelsMask[0] |= LC( 1 ) + LC( 2 );
*time = 0;
return LORAMAC_STATUS_NO_CHANNEL_FOUND;
}
return status;
}
LoRaMacStatus_t RegionAS923ChannelAdd( ChannelAddParams_t* channelAdd )

View File

@@ -37,6 +37,11 @@
#ifndef __REGION_AS923_H__
#define __REGION_AS923_H__
#ifdef __cplusplus
extern "C"
{
#endif
#include "region/Region.h"
/*!
@@ -212,6 +217,11 @@
*/
#define AS923_BEACON_CHANNEL_FREQ 923400000
/*!
* Ping slot channel frequency
*/
#define AS923_PING_SLOT_CHANNEL_FREQ 923400000
/*!
* Payload size of a beacon frame
*/
@@ -249,9 +259,9 @@
/*!
* Band 0 definition
* { DutyCycle, TxMaxPower, LastJoinTxDoneTime, LastTxDoneTime, TimeOff }
* Band = { DutyCycle, TxMaxPower, LastBandUpdateTime, TimeCredits, MaxTimeCredits, ReadyForTransmission }
*/
#define AS923_BAND0 { 100, AS923_MAX_TX_POWER, 0, 0, 0 } // 1.0 %
#define AS923_BAND0 { 100, AS923_MAX_TX_POWER, 0, 0, 0, 0 } // 1.0 %
/*!
* LoRaMac default channel 1
@@ -291,27 +301,20 @@ static const uint8_t DataratesAS923[] = { 12, 11, 10, 9, 8, 7, 7, 50 };
static const uint32_t BandwidthsAS923[] = { 125000, 125000, 125000, 125000, 125000, 125000, 250000, 0 };
/*!
* Maximum payload with respect to the datarate index. Cannot operate with repeater.
* Maximum payload with respect to the datarate index.
* The table is valid for the dwell time configuration of 0 for uplinks and downlinks.
*/
static const uint8_t MaxPayloadOfDatarateDwell0AS923[] = { 51, 51, 51, 115, 242, 242, 242, 242 };
/*!
* Maximum payload with respect to the datarate index. Can operate with repeater.
* The table is valid for the dwell time configuration of 0 for uplinks and downlinks. The table provides
* repeater support.
*/
static const uint8_t MaxPayloadOfDatarateRepeaterDwell0AS923[] = { 51, 51, 51, 115, 222, 222, 222, 222 };
/*!
* Maximum payload with respect to the datarate index. Can operate with and without repeater.
* The table proides repeater support. The table is only valid for uplinks.
* Maximum payload with respect to the datarate index.
* The table is only valid for uplinks.
*/
static const uint8_t MaxPayloadOfDatarateDwell1UpAS923[] = { 0, 0, 11, 53, 125, 242, 242, 242 };
/*!
* Maximum payload with respect to the datarate index. Can operate with and without repeater.
* The table proides repeater support. The table is only valid for downlinks.
* Maximum payload with respect to the datarate index.
* The table is only valid for downlinks.
*/
static const uint8_t MaxPayloadOfDatarateDwell1DownAS923[] = { 0, 0, 11, 53, 126, 242, 242, 242 };
@@ -475,13 +478,6 @@ uint8_t RegionAS923DlChannelReq( DlChannelReqParams_t* dlChannelReq );
*/
int8_t RegionAS923AlternateDr( int8_t currentDr, AlternateDrType_t type );
/*!
* \brief Calculates the back-off time.
*
* \param [IN] calcBackOff Pointer to the function parameters.
*/
void RegionAS923CalcBackOff( CalcBackOffParams_t* calcBackOff );
/*!
* \brief Searches and set the next random available channel
*
@@ -543,4 +539,8 @@ uint8_t RegionAS923ApplyDrOffset( uint8_t downlinkDwellTime, int8_t dr, int8_t d
/*! \} defgroup REGIONAS923 */
#ifdef __cplusplus
}
#endif
#endif // __REGION_AS923_H__

View File

@@ -140,38 +140,12 @@ static bool VerifyRfFreq( uint32_t freq )
return true;
}
static uint8_t CountNbOfEnabledChannels( uint8_t datarate, uint16_t* channelsMask, ChannelParams_t* channels, Band_t* bands, uint8_t* enabledChannels, uint8_t* delayTx )
static TimerTime_t GetTimeOnAir( int8_t datarate, uint16_t pktLen )
{
uint8_t nbEnabledChannels = 0;
uint8_t delayTransmission = 0;
int8_t phyDr = DataratesAU915[datarate];
uint32_t bandwidth = GetBandwidth( datarate );
for( uint8_t i = 0, k = 0; i < AU915_MAX_NB_CHANNELS; i += 16, k++ )
{
for( uint8_t j = 0; j < 16; j++ )
{
if( ( channelsMask[k] & ( 1 << j ) ) != 0 )
{
if( channels[i + j].Frequency == 0 )
{ // Check if the channel is enabled
continue;
}
if( RegionCommonValueInRange( datarate, channels[i + j].DrRange.Fields.Min,
channels[i + j].DrRange.Fields.Max ) == false )
{ // Check if the current channel selection supports the given datarate
continue;
}
if( bands[channels[i + j].Band].TimeOff > 0 )
{ // Check if the band is available for transmission
delayTransmission++;
continue;
}
enabledChannels[nbEnabledChannels++] = i + j;
}
}
}
*delayTx = delayTransmission;
return nbEnabledChannels;
return Radio.TimeOnAir( MODEM_LORA, bandwidth, phyDr, 1, 8, false, pktLen, true );
}
PhyParam_t RegionAU915GetPhyParam( GetPhyParams_t* getPhy )
@@ -253,18 +227,6 @@ PhyParam_t RegionAU915GetPhyParam( GetPhyParams_t* getPhy )
}
break;
}
case PHY_MAX_PAYLOAD_REPEATER:
{
if( getPhy->UplinkDwellTime == 0)
{
phyParam.Value = MaxPayloadOfDatarateRepeaterDwell0AU915[getPhy->Datarate];
}
else
{
phyParam.Value = MaxPayloadOfDatarateRepeaterDwell1AU915[getPhy->Datarate];
}
break;
}
case PHY_DUTY_CYCLE:
{
phyParam.Value = AU915_DUTY_CYCLE_ENABLED;
@@ -360,6 +322,11 @@ PhyParam_t RegionAU915GetPhyParam( GetPhyParams_t* getPhy )
phyParam.fValue = AU915_DEFAULT_ANTENNA_GAIN;
break;
}
case PHY_BEACON_CHANNEL_FREQ:
{
phyParam.Value = AU915_BEACON_CHANNEL_FREQ + ( getPhy->Channel * AU915_BEACON_CHANNEL_STEPWIDTH );
break;
}
case PHY_BEACON_FORMAT:
{
phyParam.BeaconFormat.BeaconSize = AU915_BEACON_SIZE;
@@ -382,11 +349,26 @@ PhyParam_t RegionAU915GetPhyParam( GetPhyParams_t* getPhy )
phyParam.Value = AU915_BEACON_NB_CHANNELS;
break;
}
case PHY_PING_SLOT_CHANNEL_FREQ:
{
phyParam.Value = AU915_PING_SLOT_CHANNEL_FREQ + ( getPhy->Channel * AU915_BEACON_CHANNEL_STEPWIDTH );
break;
}
case PHY_PING_SLOT_CHANNEL_DR:
{
phyParam.Value = AU915_PING_SLOT_CHANNEL_DR;
break;
}
case PHY_SF_FROM_DR:
{
phyParam.Value = DataratesAU915[getPhy->Datarate];
break;
}
case PHY_BW_FROM_DR:
{
phyParam.Value = GetBandwidth( getPhy->Datarate );
break;
}
default:
{
break;
@@ -398,7 +380,8 @@ PhyParam_t RegionAU915GetPhyParam( GetPhyParams_t* getPhy )
void RegionAU915SetBandTxDone( SetBandTxDoneParams_t* txDone )
{
RegionCommonSetBandTxDone( txDone->Joined, &NvmCtx.Bands[NvmCtx.Channels[txDone->Channel].Band], txDone->LastTxDoneTime );
RegionCommonSetBandTxDone( &NvmCtx.Bands[NvmCtx.Channels[txDone->Channel].Band],
txDone->LastTxAirTime, txDone->Joined, txDone->ElapsedTimeSinceStartUp );
}
void RegionAU915InitDefaults( InitDefaultsParams_t* params )
@@ -410,11 +393,28 @@ void RegionAU915InitDefaults( InitDefaultsParams_t* params )
switch( params->Type )
{
case INIT_TYPE_INIT:
case INIT_TYPE_BANDS:
{
// Initialize bands
memcpy1( ( uint8_t* )NvmCtx.Bands, ( uint8_t* )bands, sizeof( Band_t ) * AU915_MAX_NB_BANDS );
// Initialize channels default mask
NvmCtx.ChannelsDefaultMask[0] = 0xFFFF;
NvmCtx.ChannelsDefaultMask[1] = 0xFFFF;
NvmCtx.ChannelsDefaultMask[2] = 0xFFFF;
NvmCtx.ChannelsDefaultMask[3] = 0xFFFF;
NvmCtx.ChannelsDefaultMask[4] = 0x00FF;
NvmCtx.ChannelsDefaultMask[5] = 0x0000;
// Copy channels default mask
RegionCommonChanMaskCopy( NvmCtx.ChannelsMask, NvmCtx.ChannelsDefaultMask, 6 );
// Copy into channels mask remaining
RegionCommonChanMaskCopy( NvmCtx.ChannelsMaskRemaining, NvmCtx.ChannelsMask, 6 );
break;
}
case INIT_TYPE_INIT:
{
// Channels
// 125 kHz channels
for( uint8_t i = 0; i < AU915_MAX_NB_CHANNELS - 8; i++ )
@@ -430,20 +430,6 @@ void RegionAU915InitDefaults( InitDefaultsParams_t* params )
NvmCtx.Channels[i].DrRange.Value = ( DR_6 << 4 ) | DR_6;
NvmCtx.Channels[i].Band = 0;
}
// Initialize channels default mask
NvmCtx.ChannelsDefaultMask[0] = 0xFFFF;
NvmCtx.ChannelsDefaultMask[1] = 0xFFFF;
NvmCtx.ChannelsDefaultMask[2] = 0xFFFF;
NvmCtx.ChannelsDefaultMask[3] = 0xFFFF;
NvmCtx.ChannelsDefaultMask[4] = 0x00FF;
NvmCtx.ChannelsDefaultMask[5] = 0x0000;
// Copy channels default mask
RegionCommonChanMaskCopy( NvmCtx.ChannelsMask, NvmCtx.ChannelsDefaultMask, 6 );
// Copy into channels mask remaining
RegionCommonChanMaskCopy( NvmCtx.ChannelsMaskRemaining, NvmCtx.ChannelsMask, 6 );
break;
}
case INIT_TYPE_RESTORE_CTX:
@@ -482,6 +468,10 @@ bool RegionAU915Verify( VerifyParams_t* verify, PhyAttribute_t phyAttribute )
{
switch( phyAttribute )
{
case PHY_FREQUENCY:
{
return VerifyRfFreq( verify->Frequency );
}
case PHY_TX_DR:
case PHY_DEF_TX_DR:
{
@@ -592,7 +582,6 @@ void RegionAU915ComputeRxWindowParameters( int8_t datarate, uint8_t minRxSymbols
bool RegionAU915RxConfig( RxConfigParams_t* rxConfig, int8_t* datarate )
{
int8_t dr = rxConfig->Datarate;
uint8_t maxPayload = 0;
int8_t phyDr = 0;
uint32_t frequency = rxConfig->Frequency;
@@ -615,15 +604,7 @@ bool RegionAU915RxConfig( RxConfigParams_t* rxConfig, int8_t* datarate )
// Radio configuration
Radio.SetRxConfig( MODEM_LORA, rxConfig->Bandwidth, phyDr, 1, 0, 8, rxConfig->WindowTimeout, false, 0, false, 0, 0, true, rxConfig->RxContinuous );
if( rxConfig->RepeaterSupport == true )
{
maxPayload = MaxPayloadOfDatarateRepeaterDwell0AU915[dr];
}
else
{
maxPayload = MaxPayloadOfDatarateDwell0AU915[dr];
}
Radio.SetMaxPayloadLength( MODEM_LORA, maxPayload + LORA_MAC_FRMPAYLOAD_OVERHEAD );
Radio.SetMaxPayloadLength( MODEM_LORA, MaxPayloadOfDatarateDwell0AU915[dr] + LORAMAC_FRAME_PAYLOAD_OVERHEAD_SIZE );
*datarate = (uint8_t) dr;
return true;
@@ -642,14 +623,14 @@ bool RegionAU915TxConfig( TxConfigParams_t* txConfig, int8_t* txPower, TimerTime
// Setup the radio frequency
Radio.SetChannel( NvmCtx.Channels[txConfig->Channel].Frequency );
Radio.SetTxConfig( MODEM_LORA, phyTxPower, 0, bandwidth, phyDr, 1, 8, false, true, 0, 0, false, 3000 );
Radio.SetTxConfig( MODEM_LORA, phyTxPower, 0, bandwidth, phyDr, 1, 8, false, true, 0, 0, false, 4000 );
// Setup maximum payload lenght of the radio driver
Radio.SetMaxPayloadLength( MODEM_LORA, txConfig->PktLen );
// Update time-on-air
*txTimeOnAir = GetTimeOnAir( txConfig->Datarate, txConfig->PktLen );
*txTimeOnAir = Radio.TimeOnAir( MODEM_LORA, txConfig->PktLen );
*txPower = txPowerLimited;
return true;
}
@@ -880,28 +861,14 @@ int8_t RegionAU915AlternateDr( int8_t currentDr, AlternateDrType_t type )
return currentDr;
}
void RegionAU915CalcBackOff( CalcBackOffParams_t* calcBackOff )
{
RegionCommonCalcBackOffParams_t calcBackOffParams;
calcBackOffParams.Channels = NvmCtx.Channels;
calcBackOffParams.Bands = NvmCtx.Bands;
calcBackOffParams.LastTxIsJoinRequest = calcBackOff->LastTxIsJoinRequest;
calcBackOffParams.Joined = calcBackOff->Joined;
calcBackOffParams.DutyCycleEnabled = calcBackOff->DutyCycleEnabled;
calcBackOffParams.Channel = calcBackOff->Channel;
calcBackOffParams.ElapsedTime = calcBackOff->ElapsedTime;
calcBackOffParams.TxTimeOnAir = calcBackOff->TxTimeOnAir;
RegionCommonCalcBackOff( &calcBackOffParams );
}
LoRaMacStatus_t RegionAU915NextChannel( NextChanParams_t* nextChanParams, uint8_t* channel, TimerTime_t* time, TimerTime_t* aggregatedTimeOff )
{
uint8_t nbEnabledChannels = 0;
uint8_t delayTx = 0;
uint8_t nbRestrictedChannels = 0;
uint8_t enabledChannels[AU915_MAX_NB_CHANNELS] = { 0 };
TimerTime_t nextTxDelay = 0;
RegionCommonIdentifyChannelsParam_t identifyChannelsParam;
RegionCommonCountNbOfEnabledChannelsParams_t countChannelsParams;
LoRaMacStatus_t status = LORAMAC_STATUS_NO_CHANNEL_FOUND;
// Count 125kHz channels
if( RegionCommonCountChannels( NvmCtx.ChannelsMaskRemaining, 0, 4 ) == 0 )
@@ -917,47 +884,37 @@ LoRaMacStatus_t RegionAU915NextChannel( NextChanParams_t* nextChanParams, uint8_
}
}
if( nextChanParams->AggrTimeOff <= TimerGetElapsedTime( nextChanParams->LastAggrTx ) )
{
// Reset Aggregated time off
*aggregatedTimeOff = 0;
// Search how many channels are enabled
countChannelsParams.Joined = nextChanParams->Joined;
countChannelsParams.Datarate = nextChanParams->Datarate;
countChannelsParams.ChannelsMask = NvmCtx.ChannelsMaskRemaining;
countChannelsParams.Channels = NvmCtx.Channels;
countChannelsParams.Bands = NvmCtx.Bands;
countChannelsParams.MaxNbChannels = AU915_MAX_NB_CHANNELS;
countChannelsParams.JoinChannels = 0;
// Update bands Time OFF
nextTxDelay = RegionCommonUpdateBandTimeOff( nextChanParams->Joined, nextChanParams->DutyCycleEnabled, NvmCtx.Bands, AU915_MAX_NB_BANDS );
identifyChannelsParam.AggrTimeOff = nextChanParams->AggrTimeOff;
identifyChannelsParam.LastAggrTx = nextChanParams->LastAggrTx;
identifyChannelsParam.DutyCycleEnabled = nextChanParams->DutyCycleEnabled;
identifyChannelsParam.MaxBands = AU915_MAX_NB_BANDS;
// Search how many channels are enabled
nbEnabledChannels = CountNbOfEnabledChannels( nextChanParams->Datarate,
NvmCtx.ChannelsMaskRemaining, NvmCtx.Channels,
NvmCtx.Bands, enabledChannels, &delayTx );
}
else
{
delayTx++;
nextTxDelay = nextChanParams->AggrTimeOff - TimerGetElapsedTime( nextChanParams->LastAggrTx );
}
identifyChannelsParam.ElapsedTimeSinceStartUp = nextChanParams->ElapsedTimeSinceStartUp;
identifyChannelsParam.LastTxIsJoinRequest = nextChanParams->LastTxIsJoinRequest;
identifyChannelsParam.ExpectedTimeOnAir = GetTimeOnAir( nextChanParams->Datarate, nextChanParams->PktLen );
if( nbEnabledChannels > 0 )
identifyChannelsParam.CountNbOfEnabledChannelsParam = &countChannelsParams;
status = RegionCommonIdentifyChannels( &identifyChannelsParam, aggregatedTimeOff, enabledChannels,
&nbEnabledChannels, &nbRestrictedChannels, time );
if( status == LORAMAC_STATUS_OK )
{
// We found a valid channel
*channel = enabledChannels[randr( 0, nbEnabledChannels - 1 )];
// Disable the channel in the mask
RegionCommonChanDisable( NvmCtx.ChannelsMaskRemaining, *channel, AU915_MAX_NB_CHANNELS - 8 );
*time = 0;
return LORAMAC_STATUS_OK;
}
else
{
if( delayTx > 0 )
{
// Delay transmission due to AggregatedTimeOff or to a band time off
*time = nextTxDelay;
return LORAMAC_STATUS_DUTYCYCLE_RESTRICTED;
}
// Datarate not supported by any channel
*time = 0;
return LORAMAC_STATUS_NO_CHANNEL_FOUND;
}
return status;
}
LoRaMacStatus_t RegionAU915ChannelAdd( ChannelAddParams_t* channelAdd )

View File

@@ -37,6 +37,11 @@
#ifndef __REGION_AU915_H__
#define __REGION_AU915_H__
#ifdef __cplusplus
extern "C"
{
#endif
#include "region/Region.h"
/*!
@@ -93,7 +98,7 @@
/*!
* Minimal Tx output power that can be used by the node
*/
#define AU915_MIN_TX_POWER TX_POWER_10
#define AU915_MIN_TX_POWER TX_POWER_14
/*!
* Maximal Tx output power that can be used by the node
@@ -203,6 +208,11 @@
*/
#define AU915_BEACON_CHANNEL_STEPWIDTH 600000
/*!
* Ping slot channel frequency
*/
#define AU915_PING_SLOT_CHANNEL_FREQ 923300000
/*!
* Number of possible beacon channels
*/
@@ -226,7 +236,7 @@
/*!
* Datarate of the beacon channel
*/
#define AU915_BEACON_CHANNEL_DR DR_10
#define AU915_BEACON_CHANNEL_DR DR_8
/*!
* Bandwith of the beacon channel
@@ -236,7 +246,7 @@
/*!
* Ping slot channel datarate
*/
#define AU915_PING_SLOT_CHANNEL_DR DR_10
#define AU915_PING_SLOT_CHANNEL_DR DR_8
/*!
* LoRaMac maximum number of bands
@@ -245,9 +255,9 @@
/*!
* Band 0 definition
* { DutyCycle, TxMaxPower, LastJoinTxDoneTime, LastTxDoneTime, TimeOff }
* Band = { DutyCycle, TxMaxPower, LastBandUpdateTime, TimeCredits, MaxTimeCredits, ReadyForTransmission }
*/
#define AU915_BAND0 { 1, AU915_MAX_TX_POWER, 0, 0, 0 } // 100.0 %
#define AU915_BAND0 { 1, AU915_MAX_TX_POWER, 0, 0, 0, 0 } // 100.0 %
/*!
* Defines the first channel for RX window 1 for US band
@@ -289,30 +299,16 @@ static const int8_t DatarateOffsetsAU915[7][6] =
};
/*!
* Maximum payload with respect to the datarate index. Cannot operate with repeater.
* Maximum payload with respect to the datarate index.
* The table is valid for the dwell time configuration of 0 for uplinks.
*/
static const uint8_t MaxPayloadOfDatarateDwell0AU915[] = { 51, 51, 51, 115, 242, 242, 242, 242, 0, 53, 129, 242, 242, 242, 242 };
static const uint8_t MaxPayloadOfDatarateDwell0AU915[] = { 51, 51, 51, 115, 242, 242, 242, 0, 53, 129, 242, 242, 242, 242 };
/*!
* Maximum payload with respect to the datarate index. Can operate with repeater.
* The table is valid for the dwell time configuration of 0 for uplinks. The table provides
* repeater support.
*/
static const uint8_t MaxPayloadOfDatarateRepeaterDwell0AU915[] = { 51, 51, 51, 115, 222, 222, 222, 0, 33, 109, 222, 222, 222, 222 };
/*!
* Maximum payload with respect to the datarate index. Cannot operate with repeater.
* Maximum payload with respect to the datarate index.
* The table is valid for the dwell time configuration of 1 for uplinks.
*/
static const uint8_t MaxPayloadOfDatarateDwell1AU915[] = { 0, 0, 11, 53, 125, 242, 242, 0, 53, 129, 129, 242, 242, 242, 242 };
/*!
* Maximum payload with respect to the datarate index. Can operate with repeater.
* The table is valid for the dwell time configuration of 1 for uplinks. The table provides
* repeater support.
*/
static const uint8_t MaxPayloadOfDatarateRepeaterDwell1AU915[] = { 0, 0, 11, 53, 125, 242, 242, 0, 33, 119, 129, 242, 242, 242, 242 };
static const uint8_t MaxPayloadOfDatarateDwell1AU915[] = { 0, 0, 11, 53, 125, 242, 242, 0, 53, 129, 242, 242, 242, 242 };
/*!
* \brief The function gets a value of a specific phy attribute.
@@ -469,13 +465,6 @@ uint8_t RegionAU915DlChannelReq( DlChannelReqParams_t* dlChannelReq );
*/
int8_t RegionAU915AlternateDr( int8_t currentDr, AlternateDrType_t type );
/*!
* \brief Calculates the back-off time.
*
* \param [IN] calcBackOff Pointer to the function parameters.
*/
void RegionAU915CalcBackOff( CalcBackOffParams_t* calcBackOff );
/*!
* \brief Searches and set the next random available channel
*
@@ -537,4 +526,8 @@ uint8_t RegionAU915ApplyDrOffset( uint8_t downlinkDwellTime, int8_t dr, int8_t d
/*! \} defgroup REGIONAU915 */
#ifdef __cplusplus
}
#endif
#endif // __REGION_AU915_H__

View File

@@ -128,38 +128,12 @@ static bool VerifyRfFreq( uint32_t freq )
return true;
}
static uint8_t CountNbOfEnabledChannels( uint8_t datarate, uint16_t* channelsMask, ChannelParams_t* channels, Band_t* bands, uint8_t* enabledChannels, uint8_t* delayTx )
static TimerTime_t GetTimeOnAir( int8_t datarate, uint16_t pktLen )
{
uint8_t nbEnabledChannels = 0;
uint8_t delayTransmission = 0;
int8_t phyDr = DataratesCN470[datarate];
uint32_t bandwidth = GetBandwidth( datarate );
for( uint8_t i = 0, k = 0; i < CN470_MAX_NB_CHANNELS; i += 16, k++ )
{
for( uint8_t j = 0; j < 16; j++ )
{
if( ( channelsMask[k] & ( 1 << j ) ) != 0 )
{
if( channels[i + j].Frequency == 0 )
{ // Check if the channel is enabled
continue;
}
if( RegionCommonValueInRange( datarate, channels[i + j].DrRange.Fields.Min,
channels[i + j].DrRange.Fields.Max ) == false )
{ // Check if the current channel selection supports the given datarate
continue;
}
if( bands[channels[i + j].Band].TimeOff > 0 )
{ // Check if the band is available for transmission
delayTransmission++;
continue;
}
enabledChannels[nbEnabledChannels++] = i + j;
}
}
}
*delayTx = delayTransmission;
return nbEnabledChannels;
return Radio.TimeOnAir( MODEM_LORA, bandwidth, phyDr, 1, 8, false, pktLen, true );
}
PhyParam_t RegionCN470GetPhyParam( GetPhyParams_t* getPhy )
@@ -213,11 +187,6 @@ PhyParam_t RegionCN470GetPhyParam( GetPhyParams_t* getPhy )
phyParam.Value = MaxPayloadOfDatarateCN470[getPhy->Datarate];
break;
}
case PHY_MAX_PAYLOAD_REPEATER:
{
phyParam.Value = MaxPayloadOfDatarateRepeaterCN470[getPhy->Datarate];
break;
}
case PHY_DUTY_CYCLE:
{
phyParam.Value = CN470_DUTY_CYCLE_ENABLED;
@@ -309,6 +278,11 @@ PhyParam_t RegionCN470GetPhyParam( GetPhyParams_t* getPhy )
phyParam.fValue = CN470_DEFAULT_ANTENNA_GAIN;
break;
}
case PHY_BEACON_CHANNEL_FREQ:
{
phyParam.Value = CN470_BEACON_CHANNEL_FREQ;
break;
}
case PHY_BEACON_FORMAT:
{
phyParam.BeaconFormat.BeaconSize = CN470_BEACON_SIZE;
@@ -331,11 +305,26 @@ PhyParam_t RegionCN470GetPhyParam( GetPhyParams_t* getPhy )
phyParam.Value = CN470_BEACON_NB_CHANNELS;
break;
}
case PHY_PING_SLOT_CHANNEL_FREQ:
{
phyParam.Value = CN470_PING_SLOT_CHANNEL_FREQ;
break;
}
case PHY_PING_SLOT_CHANNEL_DR:
{
phyParam.Value = CN470_PING_SLOT_CHANNEL_DR;
break;
}
case PHY_SF_FROM_DR:
{
phyParam.Value = DataratesCN470[getPhy->Datarate];
break;
}
case PHY_BW_FROM_DR:
{
phyParam.Value = GetBandwidth( getPhy->Datarate );
break;
}
default:
{
break;
@@ -347,7 +336,8 @@ PhyParam_t RegionCN470GetPhyParam( GetPhyParams_t* getPhy )
void RegionCN470SetBandTxDone( SetBandTxDoneParams_t* txDone )
{
RegionCommonSetBandTxDone( txDone->Joined, &NvmCtx.Bands[NvmCtx.Channels[txDone->Channel].Band], txDone->LastTxDoneTime );
RegionCommonSetBandTxDone( &NvmCtx.Bands[NvmCtx.Channels[txDone->Channel].Band],
txDone->LastTxAirTime, txDone->Joined, txDone->ElapsedTimeSinceStartUp );
}
void RegionCN470InitDefaults( InitDefaultsParams_t* params )
@@ -359,11 +349,14 @@ void RegionCN470InitDefaults( InitDefaultsParams_t* params )
switch( params->Type )
{
case INIT_TYPE_INIT:
case INIT_TYPE_BANDS:
{
// Initialize bands
memcpy1( ( uint8_t* )NvmCtx.Bands, ( uint8_t* )bands, sizeof( Band_t ) * CN470_MAX_NB_BANDS );
break;
}
case INIT_TYPE_INIT:
{
// Channels
// 125 kHz channels
for( uint8_t i = 0; i < CN470_MAX_NB_CHANNELS; i++ )
@@ -374,21 +367,13 @@ void RegionCN470InitDefaults( InitDefaultsParams_t* params )
}
// Initialize the channels default mask
#if 0
NvmCtx.ChannelsDefaultMask[0] = 0xFFFF;
NvmCtx.ChannelsDefaultMask[1] = 0xFFFF;
NvmCtx.ChannelsDefaultMask[2] = 0xFFFF;
NvmCtx.ChannelsDefaultMask[3] = 0xFFFF;
NvmCtx.ChannelsDefaultMask[4] = 0xFFFF;
NvmCtx.ChannelsDefaultMask[5] = 0xFFFF;
#else
NvmCtx.ChannelsDefaultMask[0] = 0x00FF;
NvmCtx.ChannelsDefaultMask[1] = 0x0000;
NvmCtx.ChannelsDefaultMask[2] = 0x0000;
NvmCtx.ChannelsDefaultMask[3] = 0x0000;
NvmCtx.ChannelsDefaultMask[4] = 0x0000;
NvmCtx.ChannelsDefaultMask[5] = 0x0000;
#endif
// Update the channels mask
RegionCommonChanMaskCopy( NvmCtx.ChannelsMask, NvmCtx.ChannelsDefaultMask, 6 );
break;
@@ -424,6 +409,10 @@ bool RegionCN470Verify( VerifyParams_t* verify, PhyAttribute_t phyAttribute )
{
switch( phyAttribute )
{
case PHY_FREQUENCY:
{
return VerifyRfFreq( verify->Frequency );
}
case PHY_TX_DR:
case PHY_DEF_TX_DR:
{
@@ -506,7 +495,6 @@ void RegionCN470ComputeRxWindowParameters( int8_t datarate, uint8_t minRxSymbols
bool RegionCN470RxConfig( RxConfigParams_t* rxConfig, int8_t* datarate )
{
int8_t dr = rxConfig->Datarate;
uint8_t maxPayload = 0;
int8_t phyDr = 0;
uint32_t frequency = rxConfig->Frequency;
@@ -529,15 +517,7 @@ bool RegionCN470RxConfig( RxConfigParams_t* rxConfig, int8_t* datarate )
// Radio configuration
Radio.SetRxConfig( MODEM_LORA, rxConfig->Bandwidth, phyDr, 1, 0, 8, rxConfig->WindowTimeout, false, 0, false, 0, 0, true, rxConfig->RxContinuous );
if( rxConfig->RepeaterSupport == true )
{
maxPayload = MaxPayloadOfDatarateRepeaterCN470[dr];
}
else
{
maxPayload = MaxPayloadOfDatarateCN470[dr];
}
Radio.SetMaxPayloadLength( MODEM_LORA, maxPayload + LORA_MAC_FRMPAYLOAD_OVERHEAD );
Radio.SetMaxPayloadLength( MODEM_LORA, MaxPayloadOfDatarateCN470[dr] + LORAMAC_FRAME_PAYLOAD_OVERHEAD_SIZE );
*datarate = (uint8_t) dr;
return true;
@@ -555,11 +535,11 @@ bool RegionCN470TxConfig( TxConfigParams_t* txConfig, int8_t* txPower, TimerTime
// Setup the radio frequency
Radio.SetChannel( NvmCtx.Channels[txConfig->Channel].Frequency );
Radio.SetTxConfig( MODEM_LORA, phyTxPower, 0, 0, phyDr, 1, 8, false, true, 0, 0, false, 3000 );
Radio.SetTxConfig( MODEM_LORA, phyTxPower, 0, 0, phyDr, 1, 8, false, true, 0, 0, false, 4000 );
// Setup maximum payload lenght of the radio driver
Radio.SetMaxPayloadLength( MODEM_LORA, txConfig->PktLen );
// Get the time-on-air of the next tx frame
*txTimeOnAir = Radio.TimeOnAir( MODEM_LORA, txConfig->PktLen );
// Update time-on-air
*txTimeOnAir = GetTimeOnAir( txConfig->Datarate, txConfig->PktLen );
*txPower = txPowerLimited;
return true;
@@ -708,28 +688,14 @@ int8_t RegionCN470AlternateDr( int8_t currentDr, AlternateDrType_t type )
return currentDr;
}
void RegionCN470CalcBackOff( CalcBackOffParams_t* calcBackOff )
{
RegionCommonCalcBackOffParams_t calcBackOffParams;
calcBackOffParams.Channels = NvmCtx.Channels;
calcBackOffParams.Bands = NvmCtx.Bands;
calcBackOffParams.LastTxIsJoinRequest = calcBackOff->LastTxIsJoinRequest;
calcBackOffParams.Joined = calcBackOff->Joined;
calcBackOffParams.DutyCycleEnabled = calcBackOff->DutyCycleEnabled;
calcBackOffParams.Channel = calcBackOff->Channel;
calcBackOffParams.ElapsedTime = calcBackOff->ElapsedTime;
calcBackOffParams.TxTimeOnAir = calcBackOff->TxTimeOnAir;
RegionCommonCalcBackOff( &calcBackOffParams );
}
LoRaMacStatus_t RegionCN470NextChannel( NextChanParams_t* nextChanParams, uint8_t* channel, TimerTime_t* time, TimerTime_t* aggregatedTimeOff )
{
uint8_t nbEnabledChannels = 0;
uint8_t delayTx = 0;
uint8_t nbRestrictedChannels = 0;
uint8_t enabledChannels[CN470_MAX_NB_CHANNELS] = { 0 };
TimerTime_t nextTxDelay = 0;
RegionCommonIdentifyChannelsParam_t identifyChannelsParam;
RegionCommonCountNbOfEnabledChannelsParams_t countChannelsParams;
LoRaMacStatus_t status = LORAMAC_STATUS_NO_CHANNEL_FOUND;
// Count 125kHz channels
if( RegionCommonCountChannels( NvmCtx.ChannelsMask, 0, 6 ) == 0 )
@@ -742,45 +708,35 @@ LoRaMacStatus_t RegionCN470NextChannel( NextChanParams_t* nextChanParams, uint8_
NvmCtx.ChannelsMask[5] = 0xFFFF;
}
if( nextChanParams->AggrTimeOff <= TimerGetElapsedTime( nextChanParams->LastAggrTx ) )
{
// Reset Aggregated time off
*aggregatedTimeOff = 0;
// Search how many channels are enabled
countChannelsParams.Joined = nextChanParams->Joined;
countChannelsParams.Datarate = nextChanParams->Datarate;
countChannelsParams.ChannelsMask = NvmCtx.ChannelsMask;
countChannelsParams.Channels = NvmCtx.Channels;
countChannelsParams.Bands = NvmCtx.Bands;
countChannelsParams.MaxNbChannels = CN470_MAX_NB_CHANNELS;
countChannelsParams.JoinChannels = 0;
// Update bands Time OFF
nextTxDelay = RegionCommonUpdateBandTimeOff( nextChanParams->Joined, nextChanParams->DutyCycleEnabled, NvmCtx.Bands, CN470_MAX_NB_BANDS );
identifyChannelsParam.AggrTimeOff = nextChanParams->AggrTimeOff;
identifyChannelsParam.LastAggrTx = nextChanParams->LastAggrTx;
identifyChannelsParam.DutyCycleEnabled = nextChanParams->DutyCycleEnabled;
identifyChannelsParam.MaxBands = CN470_MAX_NB_BANDS;
// Search how many channels are enabled
nbEnabledChannels = CountNbOfEnabledChannels( nextChanParams->Datarate,
NvmCtx.ChannelsMask, NvmCtx.Channels,
NvmCtx.Bands, enabledChannels, &delayTx );
}
else
{
delayTx++;
nextTxDelay = nextChanParams->AggrTimeOff - TimerGetElapsedTime( nextChanParams->LastAggrTx );
}
identifyChannelsParam.ElapsedTimeSinceStartUp = nextChanParams->ElapsedTimeSinceStartUp;
identifyChannelsParam.LastTxIsJoinRequest = nextChanParams->LastTxIsJoinRequest;
identifyChannelsParam.ExpectedTimeOnAir = GetTimeOnAir( nextChanParams->Datarate, nextChanParams->PktLen );
if( nbEnabledChannels > 0 )
identifyChannelsParam.CountNbOfEnabledChannelsParam = &countChannelsParams;
status = RegionCommonIdentifyChannels( &identifyChannelsParam, aggregatedTimeOff, enabledChannels,
&nbEnabledChannels, &nbRestrictedChannels, time );
if( status == LORAMAC_STATUS_OK )
{
// We found a valid channel
*channel = enabledChannels[randr( 0, nbEnabledChannels - 1 )];
*time = 0;
return LORAMAC_STATUS_OK;
}
else
{
if( delayTx > 0 )
{
// Delay transmission due to AggregatedTimeOff or to a band time off
*time = nextTxDelay;
return LORAMAC_STATUS_DUTYCYCLE_RESTRICTED;
}
// Datarate not supported by any channel
*time = 0;
return LORAMAC_STATUS_NO_CHANNEL_FOUND;
}
return status;
}
LoRaMacStatus_t RegionCN470ChannelAdd( ChannelAddParams_t* channelAdd )

View File

@@ -37,6 +37,11 @@
#ifndef __REGION_CN470_H__
#define __REGION_CN470_H__
#ifdef __cplusplus
extern "C"
{
#endif
#include "region/Region.h"
/*!
@@ -187,6 +192,11 @@
*/
#define CN470_BEACON_CHANNEL_STEPWIDTH 200000
/*!
* Ping slot channel frequency
*/
#define CN470_PING_SLOT_CHANNEL_FREQ 508300000
/*!
* Number of possible beacon channels
*/
@@ -229,9 +239,9 @@
/*!
* Band 0 definition
* { DutyCycle, TxMaxPower, LastJoinTxDoneTime, LastTxDoneTime, TimeOff }
* Band = { DutyCycle, TxMaxPower, LastBandUpdateTime, TimeCredits, MaxTimeCredits, ReadyForTransmission }
*/
#define CN470_BAND0 { 1, CN470_MAX_TX_POWER, 0, 0, 0 } // 100.0 %
#define CN470_BAND0 { 1, CN470_MAX_TX_POWER, 0, 0, 0, 0 } // 100.0 %
/*!
* Defines the first channel for RX window 1 for CN470 band
@@ -259,14 +269,9 @@ static const uint8_t DataratesCN470[] = { 12, 11, 10, 9, 8, 7 };
static const uint32_t BandwidthsCN470[] = { 125000, 125000, 125000, 125000, 125000, 125000 };
/*!
* Maximum payload with respect to the datarate index. Cannot operate with repeater.
* Maximum payload with respect to the datarate index.
*/
static const uint8_t MaxPayloadOfDatarateCN470[] = { 51, 51, 51, 115, 222, 222 };
/*!
* Maximum payload with respect to the datarate index. Can operate with repeater.
*/
static const uint8_t MaxPayloadOfDatarateRepeaterCN470[] = { 51, 51, 51, 115, 222, 222 };
static const uint8_t MaxPayloadOfDatarateCN470[] = { 51, 51, 51, 115, 242, 242 };
/*!
* \brief The function gets a value of a specific phy attribute.
@@ -423,13 +428,6 @@ uint8_t RegionCN470DlChannelReq( DlChannelReqParams_t* dlChannelReq );
*/
int8_t RegionCN470AlternateDr( int8_t currentDr, AlternateDrType_t type );
/*!
* \brief Calculates the back-off time.
*
* \param [IN] calcBackOff Pointer to the function parameters.
*/
void RegionCN470CalcBackOff( CalcBackOffParams_t* calcBackOff );
/*!
* \brief Searches and set the next random available channel
*
@@ -491,4 +489,8 @@ uint8_t RegionCN470ApplyDrOffset( uint8_t downlinkDwellTime, int8_t dr, int8_t d
/*! \} defgroup REGIONCN470 */
#ifdef __cplusplus
}
#endif
#endif // __REGION_CN470_H__

View File

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

View File

@@ -37,6 +37,11 @@
#ifndef __REGION_CN779_H__
#define __REGION_CN779_H__
#ifdef __cplusplus
extern "C"
{
#endif
#include "region/Region.h"
/*!
@@ -199,6 +204,11 @@
*/
#define CN779_BEACON_CHANNEL_FREQ 785000000
/*!
* Ping slot channel frequency
*/
#define CN779_PING_SLOT_CHANNEL_FREQ 785000000
/*!
* Payload size of a beacon frame
*/
@@ -236,9 +246,9 @@
/*!
* Band 0 definition
* { DutyCycle, TxMaxPower, LastJoinTxDoneTime, LastTxDoneTime, TimeOff }
* Band = { DutyCycle, TxMaxPower, LastBandUpdateTime, TimeCredits, MaxTimeCredits, ReadyForTransmission }
*/
#define CN779_BAND0 { 100, CN779_MAX_TX_POWER, 0, 0, 0 } // 1.0 %
#define CN779_BAND0 { 100, CN779_MAX_TX_POWER, 0, 0, 0, 0 } // 1.0 %
/*!
* LoRaMac default channel 1
@@ -273,15 +283,10 @@ static const uint8_t DataratesCN779[] = { 12, 11, 10, 9, 8, 7, 7, 50 };
static const uint32_t BandwidthsCN779[] = { 125000, 125000, 125000, 125000, 125000, 125000, 250000, 0 };
/*!
* Maximum payload with respect to the datarate index. Cannot operate with repeater.
* Maximum payload with respect to the datarate index.
*/
static const uint8_t MaxPayloadOfDatarateCN779[] = { 51, 51, 51, 115, 242, 242, 242, 242 };
/*!
* Maximum payload with respect to the datarate index. Can operate with repeater.
*/
static const uint8_t MaxPayloadOfDatarateRepeaterCN779[] = { 51, 51, 51, 115, 222, 222, 222, 222 };
/*!
* \brief The function gets a value of a specific phy attribute.
*
@@ -437,13 +442,6 @@ uint8_t RegionCN779DlChannelReq( DlChannelReqParams_t* dlChannelReq );
*/
int8_t RegionCN779AlternateDr( int8_t currentDr, AlternateDrType_t type );
/*!
* \brief Calculates the back-off time.
*
* \param [IN] calcBackOff Pointer to the function parameters.
*/
void RegionCN779CalcBackOff( CalcBackOffParams_t* calcBackOff );
/*!
* \brief Searches and set the next random available channel
*
@@ -505,4 +503,8 @@ uint8_t RegionCN779ApplyDrOffset( uint8_t downlinkDwellTime, int8_t dr, int8_t d
/*! \} defgroup REGIONCN779 */
#ifdef __cplusplus
}
#endif
#endif // __REGION_CN779_H__

View File

@@ -33,9 +33,108 @@
#include "utilities.h"
#include "RegionCommon.h"
#define BACKOFF_DC_1_HOUR 100
#define BACKOFF_DC_10_HOURS 1000
#define BACKOFF_DC_24_HOURS 10000
#define BACKOFF_DC_1_HOUR 100
#define BACKOFF_DC_10_HOURS 1000
#define BACKOFF_DC_24_HOURS 10000
#define BACKOFF_DC_TIMER_PERIOD_FACTOR 100
#ifndef DUTY_CYCLE_TIME_PERIOD
/*!
* Default duty cycle time period is 1 hour = 3600000 ms
*/
#define DUTY_CYCLE_TIME_PERIOD 3600000
#endif
static uint16_t GetDutyCycle( Band_t* band, bool joined, SysTime_t elapsedTimeSinceStartup )
{
uint16_t joinDutyCycle = RegionCommonGetJoinDc( elapsedTimeSinceStartup );
uint16_t dutyCycle = band->DCycle;
if( joined == false )
{
// Get the join duty cycle which depends on the runtime
joinDutyCycle = RegionCommonGetJoinDc( elapsedTimeSinceStartup );
// Take the most restrictive duty cycle
dutyCycle = MAX( dutyCycle, joinDutyCycle );
}
// Prevent value of 0
if( dutyCycle == 0 )
{
dutyCycle = 1;
}
return dutyCycle;
}
static uint16_t SetMaxTimeCredits( Band_t* band, bool joined, SysTime_t elapsedTimeSinceStartup )
{
uint16_t dutyCycle = band->DCycle;
uint8_t timePeriodFactor = 1;
// Get the band duty cycle. If not joined, the function either returns the join duty cycle
// or the band duty cycle, whichever is more restrictive.
dutyCycle = GetDutyCycle( band, joined, elapsedTimeSinceStartup );
if( joined == false )
{
// Apply a factor to increase the maximum time period of observation
timePeriodFactor = dutyCycle / BACKOFF_DC_TIMER_PERIOD_FACTOR;
}
// Setup the maximum allowed credits
band->MaxTimeCredits = DUTY_CYCLE_TIME_PERIOD * timePeriodFactor;
// In case if it is the first time, update also the current
// time credits
if( band->LastBandUpdateTime == 0 )
{
band->TimeCredits = band->MaxTimeCredits;
}
return dutyCycle;
}
static uint16_t UpdateTimeCredits( Band_t* band, bool joined, bool dutyCycleEnabled,
bool lastTxIsJoinRequest, SysTime_t elapsedTimeSinceStartup,
TimerTime_t currentTime )
{
uint16_t dutyCycle = SetMaxTimeCredits( band, joined, elapsedTimeSinceStartup );
if( joined == false )
{
if( ( dutyCycleEnabled == false ) &&
( lastTxIsJoinRequest == false ) )
{
// This is the case when the duty cycle is off and the last uplink frame was not a join.
// This could happen in case of a rejoin, e.g. in compliance test mode.
// In this special case we have to set the time off to 0, since the join duty cycle shall only
// be applied after the first join request.
band->TimeCredits = band->MaxTimeCredits;
}
}
else
{
if( dutyCycleEnabled == false )
{
band->TimeCredits = band->MaxTimeCredits;
}
}
// Get the difference between now and the last update
band->TimeCredits += TimerGetElapsedTime( band->LastBandUpdateTime );
// Limit band credits to maximum
if( band->TimeCredits > band->MaxTimeCredits )
{
band->TimeCredits = band->MaxTimeCredits;
}
// Synchronize update time
band->LastBandUpdateTime = currentTime;
return dutyCycle;
}
static uint8_t CountChannels( uint16_t mask, uint8_t nbBits )
{
@@ -147,62 +246,87 @@ void RegionCommonChanMaskCopy( uint16_t* channelsMaskDest, uint16_t* channelsMas
}
}
void RegionCommonSetBandTxDone( bool joined, Band_t* band, TimerTime_t lastTxDone )
void RegionCommonSetBandTxDone( Band_t* band, TimerTime_t lastTxAirTime, bool joined, SysTime_t elapsedTimeSinceStartup )
{
if( joined == true )
// Get the band duty cycle. If not joined, the function either returns the join duty cycle
// or the band duty cycle, whichever is more restrictive.
uint16_t dutyCycle = GetDutyCycle( band, joined, elapsedTimeSinceStartup );
// Reduce with transmission time
if( band->TimeCredits > ( lastTxAirTime * dutyCycle ) )
{
band->LastTxDoneTime = lastTxDone;
// Reduce time credits by the time of air
band->TimeCredits -= ( lastTxAirTime * dutyCycle );
}
else
{
band->LastTxDoneTime = lastTxDone;
band->LastJoinTxDoneTime = lastTxDone;
band->TimeCredits = 0;
}
}
TimerTime_t RegionCommonUpdateBandTimeOff( bool joined, bool dutyCycle, Band_t* bands, uint8_t nbBands )
TimerTime_t RegionCommonUpdateBandTimeOff( bool joined, Band_t* bands,
uint8_t nbBands, bool dutyCycleEnabled,
bool lastTxIsJoinRequest, SysTime_t elapsedTimeSinceStartup,
TimerTime_t expectedTimeOnAir )
{
TimerTime_t nextTxDelay = ( TimerTime_t )( -1 );
TimerTime_t minTimeToWait = TIMERTIME_T_MAX;
TimerTime_t currentTime = TimerGetCurrentTime( );
TimerTime_t creditCosts = 0;
uint16_t dutyCycle = 1;
uint8_t validBands = 0;
// Update bands Time OFF
for( uint8_t i = 0; i < nbBands; i++ )
{
if( joined == false )
{
TimerTime_t txDoneTime = MAX( TimerGetElapsedTime( bands[i].LastJoinTxDoneTime ),
( dutyCycle == true ) ? TimerGetElapsedTime( bands[i].LastTxDoneTime ) : 0 );
// Synchronization of bands and credits
dutyCycle = UpdateTimeCredits( &bands[i], joined, dutyCycleEnabled,
lastTxIsJoinRequest, elapsedTimeSinceStartup,
currentTime );
if( bands[i].TimeOff <= txDoneTime )
{
bands[i].TimeOff = 0;
}
if( bands[i].TimeOff != 0 )
{
nextTxDelay = MIN( bands[i].TimeOff - txDoneTime, nextTxDelay );
}
// Calculate the credit costs for the next transmission
// with the duty cycle and the expected time on air
creditCosts = expectedTimeOnAir * dutyCycle;
// Check if the band is ready for transmission. Its ready,
// when the duty cycle is off, or the TimeCredits of the band
// is higher than the credit costs for the transmission.
if( ( bands[i].TimeCredits > creditCosts ) ||
( dutyCycleEnabled == false ) )
{
bands[i].ReadyForTransmission = true;
// This band is a potential candidate for an
// upcoming transmission, so increase the counter.
validBands++;
}
else
{
if( dutyCycle == true )
// In this case, the band has not enough credits
// for the next transmission.
bands[i].ReadyForTransmission = false;
if( bands[i].MaxTimeCredits > creditCosts )
{
if( bands[i].TimeOff <= TimerGetElapsedTime( bands[i].LastTxDoneTime ) )
{
bands[i].TimeOff = 0;
}
if( bands[i].TimeOff != 0 )
{
nextTxDelay = MIN( bands[i].TimeOff - TimerGetElapsedTime( bands[i].LastTxDoneTime ),
nextTxDelay );
}
}
else
{
nextTxDelay = 0;
bands[i].TimeOff = 0;
// The band can only be taken into account, if the maximum credits
// of the band are higher than the credit costs.
// We calculate the minTimeToWait among the bands which are not
// ready for transmission and which are potentially available
// for a transmission in the future.
minTimeToWait = MIN( minTimeToWait, ( creditCosts - bands[i].TimeCredits ) );
// This band is a potential candidate for an
// upcoming transmission (even if its time credits are not enough
// at the moment), so increase the counter.
validBands++;
}
}
}
return nextTxDelay;
if( validBands == 0 )
{
// There is no valid band available to handle a transmission
// in the given DUTY_CYCLE_TIME_PERIOD.
return TIMERTIME_T_MAX;
}
return minTimeToWait;
}
uint8_t RegionCommonParseLinkAdrReq( uint8_t* payload, RegionCommonLinkAdrParams_t* linkAdrParams )
@@ -311,50 +435,6 @@ int8_t RegionCommonComputeTxPower( int8_t txPowerIndex, float maxEirp, float ant
return phyTxPower;
}
void RegionCommonCalcBackOff( RegionCommonCalcBackOffParams_t* calcBackOffParams )
{
uint8_t bandIdx = calcBackOffParams->Channels[calcBackOffParams->Channel].Band;
uint16_t dutyCycle = calcBackOffParams->Bands[bandIdx].DCycle;
uint16_t joinDutyCycle = 0;
// Reset time-off to initial value.
calcBackOffParams->Bands[bandIdx].TimeOff = 0;
if( calcBackOffParams->Joined == false )
{
// Get the join duty cycle
joinDutyCycle = RegionCommonGetJoinDc( calcBackOffParams->ElapsedTime );
// Apply the most restricting duty cycle
dutyCycle = MAX( dutyCycle, joinDutyCycle );
// Reset the timeoff if the last frame was not a join request and when the duty cycle is not enabled
if( ( calcBackOffParams->DutyCycleEnabled == false ) && ( calcBackOffParams->LastTxIsJoinRequest == false ) )
{
// This is the case when the duty cycle is off and the last uplink frame was not a join.
// This could happen in case of a rejoin, e.g. in compliance test mode.
// In this special case we have to set the time off to 0, since the join duty cycle shall only
// be applied after the first join request.
calcBackOffParams->Bands[bandIdx].TimeOff = 0;
}
else
{
// Apply band time-off.
calcBackOffParams->Bands[bandIdx].TimeOff = calcBackOffParams->TxTimeOnAir * dutyCycle - calcBackOffParams->TxTimeOnAir;
}
}
else
{
if( calcBackOffParams->DutyCycleEnabled == true )
{
calcBackOffParams->Bands[bandIdx].TimeOff = calcBackOffParams->TxTimeOnAir * dutyCycle - calcBackOffParams->TxTimeOnAir;
}
else
{
calcBackOffParams->Bands[bandIdx].TimeOff = 0;
}
}
}
void RegionCommonRxBeaconSetup( RegionCommonRxBeaconSetupParams_t* rxBeaconSetupParams )
{
bool rxContinuous = true;
@@ -382,3 +462,90 @@ void RegionCommonRxBeaconSetup( RegionCommonRxBeaconSetupParams_t* rxBeaconSetup
Radio.Rx( rxBeaconSetupParams->RxTime );
}
void RegionCommonCountNbOfEnabledChannels( RegionCommonCountNbOfEnabledChannelsParams_t* countNbOfEnabledChannelsParams,
uint8_t* enabledChannels, uint8_t* nbEnabledChannels, uint8_t* nbRestrictedChannels )
{
uint8_t nbChannelCount = 0;
uint8_t nbRestrictedChannelsCount = 0;
for( uint8_t i = 0, k = 0; i < countNbOfEnabledChannelsParams->MaxNbChannels; i += 16, k++ )
{
for( uint8_t j = 0; j < 16; j++ )
{
if( ( countNbOfEnabledChannelsParams->ChannelsMask[k] & ( 1 << j ) ) != 0 )
{
if( countNbOfEnabledChannelsParams->Channels[i + j].Frequency == 0 )
{ // Check if the channel is enabled
continue;
}
if( ( countNbOfEnabledChannelsParams->Joined == false ) &&
( countNbOfEnabledChannelsParams->JoinChannels > 0 ) )
{
if( ( countNbOfEnabledChannelsParams->JoinChannels & ( 1 << j ) ) == 0 )
{
continue;
}
}
if( RegionCommonValueInRange( countNbOfEnabledChannelsParams->Datarate,
countNbOfEnabledChannelsParams->Channels[i + j].DrRange.Fields.Min,
countNbOfEnabledChannelsParams->Channels[i + j].DrRange.Fields.Max ) == false )
{ // Check if the current channel selection supports the given datarate
continue;
}
if( countNbOfEnabledChannelsParams->Bands[countNbOfEnabledChannelsParams->Channels[i + j].Band].ReadyForTransmission == false )
{ // Check if the band is available for transmission
nbRestrictedChannelsCount++;
continue;
}
enabledChannels[nbChannelCount++] = i + j;
}
}
}
*nbEnabledChannels = nbChannelCount;
*nbRestrictedChannels = nbRestrictedChannelsCount;
}
LoRaMacStatus_t RegionCommonIdentifyChannels( RegionCommonIdentifyChannelsParam_t* identifyChannelsParam,
TimerTime_t* aggregatedTimeOff, uint8_t* enabledChannels,
uint8_t* nbEnabledChannels, uint8_t* nbRestrictedChannels,
TimerTime_t* nextTxDelay )
{
TimerTime_t elapsed = TimerGetElapsedTime( identifyChannelsParam->LastAggrTx );
*nextTxDelay = identifyChannelsParam->AggrTimeOff - elapsed;
*nbRestrictedChannels = 1;
*nbEnabledChannels = 0;
if( ( identifyChannelsParam->LastAggrTx == 0 ) ||
( identifyChannelsParam->AggrTimeOff <= elapsed ) )
{
// Reset Aggregated time off
*aggregatedTimeOff = 0;
// Update bands Time OFF
*nextTxDelay = RegionCommonUpdateBandTimeOff( identifyChannelsParam->CountNbOfEnabledChannelsParam->Joined,
identifyChannelsParam->CountNbOfEnabledChannelsParam->Bands,
identifyChannelsParam->MaxBands,
identifyChannelsParam->DutyCycleEnabled,
identifyChannelsParam->LastTxIsJoinRequest,
identifyChannelsParam->ElapsedTimeSinceStartUp,
identifyChannelsParam->ExpectedTimeOnAir );
RegionCommonCountNbOfEnabledChannels( identifyChannelsParam->CountNbOfEnabledChannelsParam, enabledChannels,
nbEnabledChannels, nbRestrictedChannels );
}
if( *nbEnabledChannels > 0 )
{
*nextTxDelay = 0;
return LORAMAC_STATUS_OK;
}
else if( *nbRestrictedChannels > 0 )
{
return LORAMAC_STATUS_DUTYCYCLE_RESTRICTED;
}
else
{
return LORAMAC_STATUS_NO_CHANNEL_FOUND;
}
}

View File

@@ -37,9 +37,23 @@
#ifndef __REGIONCOMMON_H__
#define __REGIONCOMMON_H__
#ifdef __cplusplus
extern "C"
{
#endif
#include "LoRaMacTypes.h"
#include "LoRaMacHeaderTypes.h"
#include "region/Region.h"
/*!
* Default ping slots periodicity
*
* Periodicity is equal to 2^REGION_COMMON_DEFAULT_PING_SLOT_PERIODICITY seconds.
* Example: 2^7 = 128 seconds. The end-device will open an Rx slot every 128 seconds.
*/
#define REGION_COMMON_DEFAULT_PING_SLOT_PERIODICITY 7
typedef struct sRegionCommonLinkAdrParams
{
/*!
@@ -132,42 +146,6 @@ typedef struct sRegionCommonLinkAdrReqVerifyParams
int8_t MaxTxPower;
}RegionCommonLinkAdrReqVerifyParams_t;
typedef struct sRegionCommonCalcBackOffParams
{
/*!
* A pointer to region specific channels.
*/
ChannelParams_t* Channels;
/*!
* A pointer to region specific bands.
*/
Band_t* Bands;
/*!
* Set to true, if the last uplink was a join request.
*/
bool LastTxIsJoinRequest;
/*!
* Set to true, if the node is joined.
*/
bool Joined;
/*!
* Set to true, if the duty cycle is enabled.
*/
bool DutyCycleEnabled;
/*!
* The current channel.
*/
uint8_t Channel;
/*!
* The elapsed time since initialization.
*/
SysTime_t ElapsedTime;
/*!
* The time on air of the last Tx frame.
*/
TimerTime_t TxTimeOnAir;
}RegionCommonCalcBackOffParams_t;
typedef struct sRegionCommonRxBeaconSetupParams
{
/*!
@@ -200,6 +178,90 @@ typedef struct sRegionCommonRxBeaconSetupParams
uint16_t SymbolTimeout;
}RegionCommonRxBeaconSetupParams_t;
typedef struct sRegionCommonCountNbOfEnabledChannelsParams
{
/*!
* Set to true, if the device is joined.
*/
bool Joined;
/*!
* The datarate to count the available channels.
*/
uint8_t Datarate;
/*!
* A pointer to the channels mask to verify.
*/
uint16_t* ChannelsMask;
/*!
* A pointer to the channels.
*/
ChannelParams_t* Channels;
/*!
* A pointer to the bands.
*/
Band_t* Bands;
/*!
* The number of available channels.
*/
uint16_t MaxNbChannels;
/*!
* A bitmask containing the join channels.
*/
uint16_t JoinChannels;
}RegionCommonCountNbOfEnabledChannelsParams_t;
typedef struct sRegionCommonIdentifyChannelsParam
{
/*!
* Aggregated time-off time.
*/
TimerTime_t AggrTimeOff;
/*!
* Time of the last aggregated TX.
*/
TimerTime_t LastAggrTx;
/*!
* Set to true, if the duty cycle is enabled, otherwise false.
*/
bool DutyCycleEnabled;
/*!
* Maximum number of bands.
*/
uint8_t MaxBands;
/*!
* Elapsed time since the start of the node.
*/
SysTime_t ElapsedTimeSinceStartUp;
/*!
* Joined Set to true, if the last uplink was a join request
*/
bool LastTxIsJoinRequest;
/*!
* Expected time-on-air
*/
TimerTime_t ExpectedTimeOnAir;
/*!
* Pointer to a structure of RegionCommonCountNbOfEnabledChannelsParams_t.
*/
RegionCommonCountNbOfEnabledChannelsParams_t* CountNbOfEnabledChannelsParam;
}RegionCommonIdentifyChannelsParam_t;
typedef struct sRegionCommonSetDutyCycleParams
{
/*!
* Duty cycle period.
*/
TimerTime_t DutyCycleTimePeriod;
/*!
* Number of bands available.
*/
uint8_t MaxBands;
/*!
* A pointer to the bands.
*/
Band_t* Bands;
}RegionCommonSetDutyCycleParams_t;
/*!
* \brief Calculates the join duty cycle.
* This is a generic function and valid for all regions.
@@ -289,13 +351,15 @@ void RegionCommonChanMaskCopy( uint16_t* channelsMaskDest, uint16_t* channelsMas
* \brief Sets the last tx done property.
* This is a generic function and valid for all regions.
*
* \param [IN] joined Set to true, if the node has joined the network
*
* \param [IN] band The band to be updated.
*
* \param [IN] lastTxDone The time of the last TX done.
* \param [IN] lastTxAirTime The time on air of the last TX frame.
*
* \param [IN] joined Set to true if the device has joined.
*
* \param [IN] elapsedTimeSinceStartup Elapsed time since initialization.
*/
void RegionCommonSetBandTxDone( bool joined, Band_t* band, TimerTime_t lastTxDone );
void RegionCommonSetBandTxDone( Band_t* band, TimerTime_t lastTxAirTime, bool joined, SysTime_t elapsedTimeSinceStartup );
/*!
* \brief Updates the time-offs of the bands.
@@ -303,15 +367,24 @@ void RegionCommonSetBandTxDone( bool joined, Band_t* band, TimerTime_t lastTxDon
*
* \param [IN] joined Set to true, if the node has joined the network
*
* \param [IN] dutyCycle Set to true, if the duty cycle is enabled.
*
* \param [IN] bands A pointer to the bands.
*
* \param [IN] nbBands The number of bands available.
*
* \param [IN] dutyCycleEnabled Set to true, if the duty cycle is enabled.
*
* \param [IN] lastTxIsJoinRequest Set to true, if the last TX is a join request.
*
* \param [IN] elapsedTimeSinceStartup Elapsed time since start up.
*
* \param [IN] expectedTimeOnAir Expected time on air for the next transmission.
*
* \retval Returns the time which must be waited to perform the next uplink.
*/
TimerTime_t RegionCommonUpdateBandTimeOff( bool joined, bool dutyCycle, Band_t* bands, uint8_t nbBands );
TimerTime_t RegionCommonUpdateBandTimeOff( bool joined, Band_t* bands,
uint8_t nbBands, bool dutyCycleEnabled,
bool lastTxIsJoinRequest, SysTime_t elapsedTimeSinceStartup,
TimerTime_t expectedTimeOnAir );
/*!
* \brief Parses the parameter of an LinkAdrRequest.
@@ -385,7 +458,7 @@ void RegionCommonComputeRxWindowParameters( double tSymbol, uint8_t minRxSymbols
/*!
* \brief Computes the txPower, based on the max EIRP and the antenna gain.
*
*
* \remark US915 region uses a conducted power as input value for maxEirp.
* Thus, the antennaGain parameter must be set to 0.
*
@@ -400,13 +473,6 @@ void RegionCommonComputeRxWindowParameters( double tSymbol, uint8_t minRxSymbols
*/
int8_t RegionCommonComputeTxPower( int8_t txPowerIndex, float maxEirp, float antennaGain );
/*!
* \brief Calculates the duty cycle for the current band.
*
* \param [IN] calcBackOffParams A pointer to the input parameters.
*/
void RegionCommonCalcBackOff( RegionCommonCalcBackOffParams_t* calcBackOffParams );
/*!
* \brief Sets up the radio into RX beacon mode.
*
@@ -414,6 +480,52 @@ void RegionCommonCalcBackOff( RegionCommonCalcBackOffParams_t* calcBackOffParams
*/
void RegionCommonRxBeaconSetup( RegionCommonRxBeaconSetupParams_t* rxBeaconSetupParams );
/*!
* \brief Counts the number of enabled channels.
*
* \param [IN] countNbOfEnabledChannelsParams A pointer to the input parameters.
*
* \param [OUT] enabledChannels A pointer to an array of size XX_MAX_NB_CHANNELS. The function
* stores the available channels into this array.
*
* \param [OUT] nbEnabledChannels The number of available channels found.
*
* \param [OUT] nbRestrictedChannels It contains the number of channel
* which are available, but restricted due to duty cycle.
*/
void RegionCommonCountNbOfEnabledChannels( RegionCommonCountNbOfEnabledChannelsParams_t* countNbOfEnabledChannelsParams,
uint8_t* enabledChannels, uint8_t* nbEnabledChannels, uint8_t* nbRestrictedChannels );
/*!
* \brief Identifies all channels which are available currently.
*
* \param [IN] identifyChannelsParam A pointer to the input parameters.
*
* \param [OUT] aggregatedTimeOff The new value of the aggregatedTimeOff. The function
* may resets it to 0.
*
* \param [OUT] enabledChannels A pointer to an array of size XX_MAX_NB_CHANNELS. The function
* stores the available channels into this array.
*
* \param [OUT] nbEnabledChannels The number of available channels found.
*
* \param [OUT] nbRestrictedChannels It contains the number of channel
* which are available, but restricted due to duty cycle.
*
* \param [OUT] nextTxDelay Holds the time which has to be waited for the next possible
* uplink transmission.
*
*\retval Status of the operation.
*/
LoRaMacStatus_t RegionCommonIdentifyChannels( RegionCommonIdentifyChannelsParam_t* identifyChannelsParam,
TimerTime_t* aggregatedTimeOff, uint8_t* enabledChannels,
uint8_t* nbEnabledChannels, uint8_t* nbRestrictedChannels,
TimerTime_t* nextTxDelay );
/*! \} defgroup REGIONCOMMON */
#ifdef __cplusplus
}
#endif
#endif // __REGIONCOMMON_H__

View File

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

View File

@@ -37,6 +37,11 @@
#ifndef __REGION_EU433_H__
#define __REGION_EU433_H__
#ifdef __cplusplus
extern "C"
{
#endif
#include "region/Region.h"
/*!
@@ -204,6 +209,11 @@
*/
#define EU433_BEACON_CHANNEL_FREQ 434665000
/*!
* Ping slot channel frequency
*/
#define EU433_PING_SLOT_CHANNEL_FREQ 434665000
/*!
* Payload size of a beacon frame
*/
@@ -236,9 +246,9 @@
/*!
* Band 0 definition
* { DutyCycle, TxMaxPower, LastJoinTxDoneTime, LastTxDoneTime, TimeOff }
* Band = { DutyCycle, TxMaxPower, LastBandUpdateTime, TimeCredits, MaxTimeCredits, ReadyForTransmission }
*/
#define EU433_BAND0 { 100, EU433_MAX_TX_POWER, 0, 0, 0 } // 1.0 %
#define EU433_BAND0 { 100, EU433_MAX_TX_POWER, 0, 0, 0, 0 } // 1.0 %
/*!
* LoRaMac default channel 1
@@ -274,15 +284,10 @@ static const uint8_t DataratesEU433[] = { 12, 11, 10, 9, 8, 7, 7, 50 };
static const uint32_t BandwidthsEU433[] = { 125000, 125000, 125000, 125000, 125000, 125000, 250000, 0 };
/*!
* Maximum payload with respect to the datarate index. Cannot operate with repeater.
* Maximum payload with respect to the datarate index.
*/
static const uint8_t MaxPayloadOfDatarateEU433[] = { 51, 51, 51, 115, 242, 242, 242, 242 };
/*!
* Maximum payload with respect to the datarate index. Can operate with repeater.
*/
static const uint8_t MaxPayloadOfDatarateRepeaterEU433[] = { 51, 51, 51, 115, 222, 222, 222, 222 };
/*!
* \brief The function gets a value of a specific phy attribute.
*
@@ -438,13 +443,6 @@ uint8_t RegionEU433DlChannelReq( DlChannelReqParams_t* dlChannelReq );
*/
int8_t RegionEU433AlternateDr( int8_t currentDr, AlternateDrType_t type );
/*!
* \brief Calculates the back-off time.
*
* \param [IN] calcBackOff Pointer to the function parameters.
*/
void RegionEU433CalcBackOff( CalcBackOffParams_t* calcBackOff );
/*!
* \brief Searches and set the next random available channel
*
@@ -502,8 +500,12 @@ uint8_t RegionEU433ApplyDrOffset( uint8_t downlinkDwellTime, int8_t dr, int8_t d
*
* \param [IN] rxBeaconSetup Pointer to the function parameters
*/
void RegionEU433RxBeaconSetup( RxBeaconSetup_t* rxBeaconSetup, uint8_t* outDr );
void RegionEU433RxBeaconSetup( RxBeaconSetup_t* rxBeaconSetup, uint8_t* outDr );
/*! \} defgroup REGIONEU433 */
#ifdef __cplusplus
}
#endif
#endif // __REGION_EU433_H__

View File

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

View File

@@ -37,6 +37,11 @@
#ifndef __REGION_EU868_H__
#define __REGION_EU868_H__
#ifdef __cplusplus
extern "C"
{
#endif
#include "region/Region.h"
/*!
@@ -196,6 +201,11 @@
*/
#define EU868_BEACON_CHANNEL_FREQ 869525000
/*!
* Ping slot channel frequency
*/
#define EU868_PING_SLOT_CHANNEL_FREQ 869525000
/*!
* Payload size of a beacon frame
*/
@@ -229,37 +239,44 @@
/*!
* Maximum number of bands
*/
#define EU868_MAX_NB_BANDS 5
#define EU868_MAX_NB_BANDS 6
/*!
* Band 0 definition
* { DutyCycle, TxMaxPower, LastJoinTxDoneTime, LastTxDoneTime, TimeOff }
* Band = { DutyCycle, TxMaxPower, LastBandUpdateTime, TimeCredits, MaxTimeCredits, ReadyForTransmission }
*/
#define EU868_BAND0 { 100 , EU868_MAX_TX_POWER, 0, 0, 0 } // 1.0 %
#define EU868_BAND0 { 100 , EU868_MAX_TX_POWER, 0, 0, 0, 0 } // 1.0 %
/*!
* Band 1 definition
* { DutyCycle, TxMaxPower, LastJoinTxDoneTime, LastTxDoneTime, TimeOff }
* Band = { DutyCycle, TxMaxPower, LastBandUpdateTime, TimeCredits, MaxTimeCredits, ReadyForTransmission }
*/
#define EU868_BAND1 { 100 , EU868_MAX_TX_POWER, 0, 0, 0 } // 1.0 %
#define EU868_BAND1 { 100 , EU868_MAX_TX_POWER, 0, 0, 0, 0 } // 1.0 %
/*!
* Band 2 definition
* Band = { DutyCycle, TxMaxPower, LastJoinTxDoneTime, LastTxDoneTime, TimeOff }
* Band = { DutyCycle, TxMaxPower, LastBandUpdateTime, TimeCredits, MaxTimeCredits, ReadyForTransmission }
*/
#define EU868_BAND2 { 1000, EU868_MAX_TX_POWER, 0, 0, 0 } // 0.1 %
#define EU868_BAND2 { 1000, EU868_MAX_TX_POWER, 0, 0, 0, 0 } // 0.1 %
/*!
* Band 3 definition
* Band = { DutyCycle, TxMaxPower, LastJoinTxDoneTime, LastTxDoneTime, TimeOff }
* Band = { DutyCycle, TxMaxPower, LastBandUpdateTime, TimeCredits, MaxTimeCredits, ReadyForTransmission }
*/
#define EU868_BAND3 { 10 , EU868_MAX_TX_POWER, 0, 0, 0 } // 10.0 %
#define EU868_BAND3 { 10 , EU868_MAX_TX_POWER, 0, 0, 0, 0 } // 10.0 %
/*!
* Band 4 definition
* Band = { DutyCycle, TxMaxPower, LastJoinTxDoneTime, LastTxDoneTime, TimeOff }
* Band = { DutyCycle, TxMaxPower, LastBandUpdateTime, TimeCredits, MaxTimeCredits, ReadyForTransmission }
*/
#define EU868_BAND4 { 100 , EU868_MAX_TX_POWER, 0, 0, 0 } // 1.0 %
#define EU868_BAND4 { 100 , EU868_MAX_TX_POWER, 0, 0, 0, 0 } // 1.0 %
/*!
* Band 5 definition
* Band = { DutyCycle, TxMaxPower, LastJoinTxDoneTime, LastTxDoneTime, TimeOff,
* DutyCycleTimePeriod, MaxAllowedTimeOnAir, AggregatedTimeOnAir, StartTimeOfPeriod }
*/
#define EU868_BAND5 { 1000, EU868_MAX_TX_POWER, 0, 0, 0, 0 } // 0.1 %
/*!
* LoRaMac default channel 1
@@ -295,15 +312,10 @@ static const uint8_t DataratesEU868[] = { 12, 11, 10, 9, 8, 7, 7, 50 };
static const uint32_t BandwidthsEU868[] = { 125000, 125000, 125000, 125000, 125000, 125000, 250000, 0 };
/*!
* Maximum payload with respect to the datarate index. Cannot operate with repeater.
* Maximum payload with respect to the datarate index.
*/
static const uint8_t MaxPayloadOfDatarateEU868[] = { 51, 51, 51, 115, 242, 242, 242, 242 };
/*!
* Maximum payload with respect to the datarate index. Can operate with repeater.
*/
static const uint8_t MaxPayloadOfDatarateRepeaterEU868[] = { 51, 51, 51, 115, 222, 222, 222, 222 };
/*!
* \brief The function gets a value of a specific phy attribute.
*
@@ -459,13 +471,6 @@ uint8_t RegionEU868DlChannelReq( DlChannelReqParams_t* dlChannelReq );
*/
int8_t RegionEU868AlternateDr( int8_t currentDr, AlternateDrType_t type );
/*!
* \brief Calculates the back-off time.
*
* \param [IN] calcBackOff Pointer to the function parameters.
*/
void RegionEU868CalcBackOff( CalcBackOffParams_t* calcBackOff );
/*!
* \brief Searches and set the next random available channel
*
@@ -527,4 +532,8 @@ void RegionEU868RxBeaconSetup( RxBeaconSetup_t* rxBeaconSetup, uint8_t* outDr );
/*! \} defgroup REGIONEU868 */
#ifdef __cplusplus
}
#endif
#endif // __REGION_EU868_H__

View File

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

View File

@@ -37,6 +37,11 @@
#ifndef __REGION_IN865_H__
#define __REGION_IN865_H__
#ifdef __cplusplus
extern "C"
{
#endif
#include "region/Region.h"
/*!
@@ -132,7 +137,7 @@
/*!
* Enabled or disabled the duty cycle
*/
#define IN865_DUTY_CYCLE_ENABLED 1
#define IN865_DUTY_CYCLE_ENABLED 0
/*!
* Maximum RX window duration
@@ -196,6 +201,11 @@
*/
#define IN865_BEACON_CHANNEL_FREQ 866550000
/*!
* Ping slot channel frequency
*/
#define IN865_PING_SLOT_CHANNEL_FREQ 866550000
/*!
* Payload size of a beacon frame
*/
@@ -233,9 +243,9 @@
/*!
* Band 0 definition
* { DutyCycle, TxMaxPower, LastJoinTxDoneTime, LastTxDoneTime, TimeOff }
* Band = { DutyCycle, TxMaxPower, LastBandUpdateTime, TimeCredits, MaxTimeCredits, ReadyForTransmission }
*/
#define IN865_BAND0 { 1 , IN865_MAX_TX_POWER, 0, 0, 0 } // 100.0 %
#define IN865_BAND0 { 1 , IN865_MAX_TX_POWER, 0, 0, 0, 0 } // 100.0 %
/*!
* LoRaMac default channel 1
@@ -271,15 +281,10 @@ static const uint8_t DataratesIN865[] = { 12, 11, 10, 9, 8, 7, 7, 50 };
static const uint32_t BandwidthsIN865[] = { 125000, 125000, 125000, 125000, 125000, 125000, 250000, 0 };
/*!
* Maximum payload with respect to the datarate index. Cannot operate with repeater.
* Maximum payload with respect to the datarate index.
*/
static const uint8_t MaxPayloadOfDatarateIN865[] = { 51, 51, 51, 115, 242, 242, 242, 242 };
/*!
* Maximum payload with respect to the datarate index. Can operate with repeater.
*/
static const uint8_t MaxPayloadOfDatarateRepeaterIN865[] = { 51, 51, 51, 115, 222, 222, 222, 222 };
/*!
* Effective datarate offsets for receive window 1.
*/
@@ -440,13 +445,6 @@ uint8_t RegionIN865DlChannelReq( DlChannelReqParams_t* dlChannelReq );
*/
int8_t RegionIN865AlternateDr( int8_t currentDr, AlternateDrType_t type );
/*!
* \brief Calculates the back-off time.
*
* \param [IN] calcBackOff Pointer to the function parameters.
*/
void RegionIN865CalcBackOff( CalcBackOffParams_t* calcBackOff );
/*!
* \brief Searches and set the next random available channel
*
@@ -508,4 +506,8 @@ uint8_t RegionIN865ApplyDrOffset( uint8_t downlinkDwellTime, int8_t dr, int8_t d
/*! \} defgroup REGIONIN865 */
#ifdef __cplusplus
}
#endif
#endif // __REGION_IN865_H__

View File

@@ -138,45 +138,12 @@ static bool VerifyRfFreq( uint32_t freq )
return false;
}
static uint8_t CountNbOfEnabledChannels( bool joined, uint8_t datarate, uint16_t* channelsMask, ChannelParams_t* channels, Band_t* bands, uint8_t* enabledChannels, uint8_t* delayTx )
static TimerTime_t GetTimeOnAir( int8_t datarate, uint16_t pktLen )
{
uint8_t nbEnabledChannels = 0;
uint8_t delayTransmission = 0;
int8_t phyDr = DataratesKR920[datarate];
uint32_t bandwidth = GetBandwidth( datarate );
for( uint8_t i = 0, k = 0; i < KR920_MAX_NB_CHANNELS; i += 16, k++ )
{
for( uint8_t j = 0; j < 16; j++ )
{
if( ( channelsMask[k] & ( 1 << j ) ) != 0 )
{
if( channels[i + j].Frequency == 0 )
{ // Check if the channel is enabled
continue;
}
if( joined == false )
{
if( ( KR920_JOIN_CHANNELS & ( 1 << j ) ) == 0 )
{
continue;
}
}
if( RegionCommonValueInRange( datarate, channels[i + j].DrRange.Fields.Min,
channels[i + j].DrRange.Fields.Max ) == false )
{ // Check if the current channel selection supports the given datarate
continue;
}
if( bands[channels[i + j].Band].TimeOff > 0 )
{ // Check if the band is available for transmission
delayTransmission++;
continue;
}
enabledChannels[nbEnabledChannels++] = i + j;
}
}
}
*delayTx = delayTransmission;
return nbEnabledChannels;
return Radio.TimeOnAir( MODEM_LORA, bandwidth, phyDr, 1, 8, false, pktLen, true );
}
PhyParam_t RegionKR920GetPhyParam( GetPhyParams_t* getPhy )
@@ -230,11 +197,6 @@ PhyParam_t RegionKR920GetPhyParam( GetPhyParams_t* getPhy )
phyParam.Value = MaxPayloadOfDatarateKR920[getPhy->Datarate];
break;
}
case PHY_MAX_PAYLOAD_REPEATER:
{
phyParam.Value = MaxPayloadOfDatarateRepeaterKR920[getPhy->Datarate];
break;
}
case PHY_DUTY_CYCLE:
{
phyParam.Value = KR920_DUTY_CYCLE_ENABLED;
@@ -347,11 +309,26 @@ PhyParam_t RegionKR920GetPhyParam( GetPhyParams_t* getPhy )
phyParam.Value = KR920_BEACON_CHANNEL_DR;
break;
}
case PHY_PING_SLOT_CHANNEL_FREQ:
{
phyParam.Value = KR920_PING_SLOT_CHANNEL_FREQ;
break;
}
case PHY_PING_SLOT_CHANNEL_DR:
{
phyParam.Value = KR920_PING_SLOT_CHANNEL_DR;
break;
}
case PHY_SF_FROM_DR:
{
phyParam.Value = DataratesKR920[getPhy->Datarate];
break;
}
case PHY_BW_FROM_DR:
{
phyParam.Value = GetBandwidth( getPhy->Datarate );
break;
}
default:
{
break;
@@ -363,7 +340,8 @@ PhyParam_t RegionKR920GetPhyParam( GetPhyParams_t* getPhy )
void RegionKR920SetBandTxDone( SetBandTxDoneParams_t* txDone )
{
RegionCommonSetBandTxDone( txDone->Joined, &NvmCtx.Bands[NvmCtx.Channels[txDone->Channel].Band], txDone->LastTxDoneTime );
RegionCommonSetBandTxDone( &NvmCtx.Bands[NvmCtx.Channels[txDone->Channel].Band],
txDone->LastTxAirTime, txDone->Joined, txDone->ElapsedTimeSinceStartUp );
}
void RegionKR920InitDefaults( InitDefaultsParams_t* params )
@@ -375,10 +353,14 @@ void RegionKR920InitDefaults( InitDefaultsParams_t* params )
switch( params->Type )
{
case INIT_TYPE_INIT:
case INIT_TYPE_BANDS:
{
// Initialize bands
memcpy1( ( uint8_t* )NvmCtx.Bands, ( uint8_t* )bands, sizeof( Band_t ) * KR920_MAX_NB_BANDS );
break;
}
case INIT_TYPE_INIT:
{
// Channels
NvmCtx.Channels[0] = ( ChannelParams_t ) KR920_LC1;
@@ -387,6 +369,7 @@ void RegionKR920InitDefaults( InitDefaultsParams_t* params )
// Initialize the channels default mask
NvmCtx.ChannelsDefaultMask[0] = LC( 1 ) + LC( 2 ) + LC( 3 );
// Update the channels mask
RegionCommonChanMaskCopy( NvmCtx.ChannelsMask, NvmCtx.ChannelsDefaultMask, 1 );
break;
@@ -403,6 +386,11 @@ void RegionKR920InitDefaults( InitDefaultsParams_t* params )
{
// Restore channels default mask
NvmCtx.ChannelsMask[0] |= NvmCtx.ChannelsDefaultMask[0];
// Channels
NvmCtx.Channels[0] = ( ChannelParams_t ) KR920_LC1;
NvmCtx.Channels[1] = ( ChannelParams_t ) KR920_LC2;
NvmCtx.Channels[2] = ( ChannelParams_t ) KR920_LC3;
break;
}
default:
@@ -422,6 +410,10 @@ bool RegionKR920Verify( VerifyParams_t* verify, PhyAttribute_t phyAttribute )
{
switch( phyAttribute )
{
case PHY_FREQUENCY:
{
return VerifyRfFreq( verify->Frequency );
}
case PHY_TX_DR:
{
return RegionCommonValueInRange( verify->DatarateParams.Datarate, KR920_TX_MIN_DATARATE, KR920_TX_MAX_DATARATE );
@@ -544,7 +536,6 @@ void RegionKR920ComputeRxWindowParameters( int8_t datarate, uint8_t minRxSymbols
bool RegionKR920RxConfig( RxConfigParams_t* rxConfig, int8_t* datarate )
{
int8_t dr = rxConfig->Datarate;
uint8_t maxPayload = 0;
int8_t phyDr = 0;
uint32_t frequency = rxConfig->Frequency;
@@ -571,8 +562,7 @@ bool RegionKR920RxConfig( RxConfigParams_t* rxConfig, int8_t* datarate )
// Radio configuration
Radio.SetRxConfig( MODEM_LORA, rxConfig->Bandwidth, phyDr, 1, 0, 8, rxConfig->WindowTimeout, false, 0, false, 0, 0, true, rxConfig->RxContinuous );
maxPayload = MaxPayloadOfDatarateKR920[dr];
Radio.SetMaxPayloadLength( MODEM_LORA, maxPayload + LORA_MAC_FRMPAYLOAD_OVERHEAD );
Radio.SetMaxPayloadLength( MODEM_LORA, MaxPayloadOfDatarateKR920[dr] + LORAMAC_FRAME_PAYLOAD_OVERHEAD_SIZE );
*datarate = (uint8_t) dr;
return true;
@@ -596,12 +586,12 @@ bool RegionKR920TxConfig( TxConfigParams_t* txConfig, int8_t* txPower, TimerTime
// Setup the radio frequency
Radio.SetChannel( NvmCtx.Channels[txConfig->Channel].Frequency );
Radio.SetTxConfig( MODEM_LORA, phyTxPower, 0, bandwidth, phyDr, 1, 8, false, true, 0, 0, false, 3000 );
Radio.SetTxConfig( MODEM_LORA, phyTxPower, 0, bandwidth, phyDr, 1, 8, false, true, 0, 0, false, 4000 );
// Setup maximum payload lenght of the radio driver
Radio.SetMaxPayloadLength( MODEM_LORA, txConfig->PktLen );
// Get the time-on-air of the next tx frame
*txTimeOnAir = Radio.TimeOnAir( MODEM_LORA, txConfig->PktLen );
// Update time-on-air
*txTimeOnAir = GetTimeOnAir( txConfig->Datarate, txConfig->PktLen );
*txPower = txPowerLimited;
return true;
@@ -825,55 +815,45 @@ int8_t RegionKR920AlternateDr( int8_t currentDr, AlternateDrType_t type )
return currentDr;
}
void RegionKR920CalcBackOff( CalcBackOffParams_t* calcBackOff )
{
RegionCommonCalcBackOffParams_t calcBackOffParams;
calcBackOffParams.Channels = NvmCtx.Channels;
calcBackOffParams.Bands = NvmCtx.Bands;
calcBackOffParams.LastTxIsJoinRequest = calcBackOff->LastTxIsJoinRequest;
calcBackOffParams.Joined = calcBackOff->Joined;
calcBackOffParams.DutyCycleEnabled = calcBackOff->DutyCycleEnabled;
calcBackOffParams.Channel = calcBackOff->Channel;
calcBackOffParams.ElapsedTime = calcBackOff->ElapsedTime;
calcBackOffParams.TxTimeOnAir = calcBackOff->TxTimeOnAir;
RegionCommonCalcBackOff( &calcBackOffParams );
}
LoRaMacStatus_t RegionKR920NextChannel( NextChanParams_t* nextChanParams, uint8_t* channel, TimerTime_t* time, TimerTime_t* aggregatedTimeOff )
{
uint8_t channelNext = 0;
uint8_t nbEnabledChannels = 0;
uint8_t delayTx = 0;
uint8_t nbRestrictedChannels = 0;
uint8_t enabledChannels[KR920_MAX_NB_CHANNELS] = { 0 };
TimerTime_t nextTxDelay = 0;
RegionCommonIdentifyChannelsParam_t identifyChannelsParam;
RegionCommonCountNbOfEnabledChannelsParams_t countChannelsParams;
LoRaMacStatus_t status = LORAMAC_STATUS_NO_CHANNEL_FOUND;
if( RegionCommonCountChannels( NvmCtx.ChannelsMask, 0, 1 ) == 0 )
{ // Reactivate default channels
NvmCtx.ChannelsMask[0] |= LC( 1 ) + LC( 2 ) + LC( 3 );
}
if( nextChanParams->AggrTimeOff <= TimerGetElapsedTime( nextChanParams->LastAggrTx ) )
{
// Reset Aggregated time off
*aggregatedTimeOff = 0;
// Search how many channels are enabled
countChannelsParams.Joined = nextChanParams->Joined;
countChannelsParams.Datarate = nextChanParams->Datarate;
countChannelsParams.ChannelsMask = NvmCtx.ChannelsMask;
countChannelsParams.Channels = NvmCtx.Channels;
countChannelsParams.Bands = NvmCtx.Bands;
countChannelsParams.MaxNbChannels = KR920_MAX_NB_CHANNELS;
countChannelsParams.JoinChannels = KR920_JOIN_CHANNELS;
// Update bands Time OFF
nextTxDelay = RegionCommonUpdateBandTimeOff( nextChanParams->Joined, nextChanParams->DutyCycleEnabled, NvmCtx.Bands, KR920_MAX_NB_BANDS );
identifyChannelsParam.AggrTimeOff = nextChanParams->AggrTimeOff;
identifyChannelsParam.LastAggrTx = nextChanParams->LastAggrTx;
identifyChannelsParam.DutyCycleEnabled = nextChanParams->DutyCycleEnabled;
identifyChannelsParam.MaxBands = KR920_MAX_NB_BANDS;
// Search how many channels are enabled
nbEnabledChannels = CountNbOfEnabledChannels( nextChanParams->Joined, nextChanParams->Datarate,
NvmCtx.ChannelsMask, NvmCtx.Channels,
NvmCtx.Bands, enabledChannels, &delayTx );
}
else
{
delayTx++;
nextTxDelay = nextChanParams->AggrTimeOff - TimerGetElapsedTime( nextChanParams->LastAggrTx );
}
identifyChannelsParam.ElapsedTimeSinceStartUp = nextChanParams->ElapsedTimeSinceStartUp;
identifyChannelsParam.LastTxIsJoinRequest = nextChanParams->LastTxIsJoinRequest;
identifyChannelsParam.ExpectedTimeOnAir = GetTimeOnAir( nextChanParams->Datarate, nextChanParams->PktLen );
if( nbEnabledChannels > 0 )
identifyChannelsParam.CountNbOfEnabledChannelsParam = &countChannelsParams;
status = RegionCommonIdentifyChannels( &identifyChannelsParam, aggregatedTimeOff, enabledChannels,
&nbEnabledChannels, &nbRestrictedChannels, time );
if( status == LORAMAC_STATUS_OK )
{
for( uint8_t i = 0, j = randr( 0, nbEnabledChannels - 1 ); i < KR920_MAX_NB_CHANNELS; i++ )
{
@@ -886,25 +866,19 @@ LoRaMacStatus_t RegionKR920NextChannel( NextChanParams_t* nextChanParams, uint8_
{
// Free channel found
*channel = channelNext;
*time = 0;
return LORAMAC_STATUS_OK;
}
}
return LORAMAC_STATUS_NO_FREE_CHANNEL_FOUND;
// Even if one or more channels are available according to the channel plan, no free channel
// was found during the LBT procedure.
status = LORAMAC_STATUS_NO_FREE_CHANNEL_FOUND;
}
else
else if( status == LORAMAC_STATUS_NO_CHANNEL_FOUND )
{
if( delayTx > 0 )
{
// Delay transmission due to AggregatedTimeOff or to a band time off
*time = nextTxDelay;
return LORAMAC_STATUS_DUTYCYCLE_RESTRICTED;
}
// Datarate not supported by any channel, restore defaults
NvmCtx.ChannelsMask[0] |= LC( 1 ) + LC( 2 ) + LC( 3 );
*time = 0;
return LORAMAC_STATUS_NO_CHANNEL_FOUND;
}
return status;
}
LoRaMacStatus_t RegionKR920ChannelAdd( ChannelAddParams_t* channelAdd )

View File

@@ -37,6 +37,11 @@
#ifndef __REGION_KR920_H__
#define __REGION_KR920_H__
#ifdef __cplusplus
extern "C"
{
#endif
#include "region/Region.h"
/*!
@@ -201,6 +206,11 @@
*/
#define KR920_BEACON_CHANNEL_FREQ 923100000
/*!
* Ping slot channel frequency
*/
#define KR920_PING_SLOT_CHANNEL_FREQ 923100000
/*!
* Payload size of a beacon frame
*/
@@ -238,9 +248,9 @@
/*!
* Band 0 definition
* { DutyCycle, TxMaxPower, LastJoinTxDoneTime, LastTxDoneTime, TimeOff }
* Band = { DutyCycle, TxMaxPower, LastBandUpdateTime, TimeCredits, MaxTimeCredits, ReadyForTransmission }
*/
#define KR920_BAND0 { 1 , KR920_MAX_TX_POWER, 0, 0, 0 } // 100.0 %
#define KR920_BAND0 { 1 , KR920_MAX_TX_POWER, 0, 0, 0, 0 } // 100.0 %
/*!
* LoRaMac default channel 1
@@ -286,15 +296,10 @@ static const uint8_t DataratesKR920[] = { 12, 11, 10, 9, 8, 7 };
static const uint32_t BandwidthsKR920[] = { 125000, 125000, 125000, 125000, 125000, 125000 };
/*!
* Maximum payload with respect to the datarate index. Can operate with and without a repeater.
* Maximum payload with respect to the datarate index.
*/
static const uint8_t MaxPayloadOfDatarateKR920[] = { 51, 51, 51, 115, 242, 242 };
/*!
* Maximum payload with respect to the datarate index. Can operate with repeater.
*/
static const uint8_t MaxPayloadOfDatarateRepeaterKR920[] = { 51, 51, 51, 115, 222, 222 };
/*!
* \brief The function gets a value of a specific phy attribute.
*
@@ -450,13 +455,6 @@ uint8_t RegionKR920DlChannelReq( DlChannelReqParams_t* dlChannelReq );
*/
int8_t RegionKR920AlternateDr( int8_t currentDr, AlternateDrType_t type );
/*!
* \brief Calculates the back-off time.
*
* \param [IN] calcBackOff Pointer to the function parameters.
*/
void RegionKR920CalcBackOff( CalcBackOffParams_t* calcBackOff );
/*!
* \brief Searches and set the next random available channel
*
@@ -518,4 +516,8 @@ uint8_t RegionKR920ApplyDrOffset( uint8_t downlinkDwellTime, int8_t dr, int8_t d
/*! \} defgroup REGIONKR920 */
#ifdef __cplusplus
}
#endif
#endif // __REGION_KR920_H__

View File

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

View File

@@ -35,6 +35,11 @@
#ifndef __REGION_RU864_H__
#define __REGION_RU864_H__
#ifdef __cplusplus
extern "C"
{
#endif
#include "LoRaMac.h"
/*!
@@ -194,6 +199,11 @@
*/
#define RU864_BEACON_CHANNEL_FREQ 869100000
/*!
* Ping slot channel frequency
*/
#define RU864_PING_SLOT_CHANNEL_FREQ 868900000
/*!
* Payload size of a beacon frame
*/
@@ -219,6 +229,11 @@
*/
#define RU864_BEACON_CHANNEL_BW 0
/*!
* Datarate of the ping slot channel
*/
#define RU864_PING_SLOT_CHANNEL_DR DR_3
/*!
* Maximum number of bands
*/
@@ -226,9 +241,9 @@
/*!
* Band 0 definition
* { DutyCycle, TxMaxPower, LastJoinTxDoneTime, LastTxDoneTime, TimeOff }
* Band = { DutyCycle, TxMaxPower, LastBandUpdateTime, TimeCredits, MaxTimeCredits, ReadyForTransmission }
*/
#define RU864_BAND0 { 100 , RU864_MAX_TX_POWER, 0, 0, 0 } // 1.0 %
#define RU864_BAND0 { 100 , RU864_MAX_TX_POWER, 0, 0, 0, 0 } // 1.0 %
/*!
* LoRaMac default channel 1
@@ -259,15 +274,10 @@ static const uint8_t DataratesRU864[] = { 12, 11, 10, 9, 8, 7, 7, 50 };
static const uint32_t BandwidthsRU864[] = { 125000, 125000, 125000, 125000, 125000, 125000, 250000, 0 };
/*!
* Maximum payload with respect to the datarate index. Cannot operate with repeater.
* Maximum payload with respect to the datarate index.
*/
static const uint8_t MaxPayloadOfDatarateRU864[] = { 51, 51, 51, 115, 242, 242, 242, 242 };
/*!
* Maximum payload with respect to the datarate index. Can operate with repeater.
*/
static const uint8_t MaxPayloadOfDatarateRepeaterRU864[] = { 51, 51, 51, 115, 222, 222, 222, 222 };
/*!
* \brief The function gets a value of a specific phy attribute.
*
@@ -423,13 +433,6 @@ uint8_t RegionRU864DlChannelReq( DlChannelReqParams_t* dlChannelReq );
*/
int8_t RegionRU864AlternateDr( int8_t currentDr, AlternateDrType_t type );
/*!
* \brief Calculates the back-off time.
*
* \param [IN] calcBackOff Pointer to the function parameters.
*/
void RegionRU864CalcBackOff( CalcBackOffParams_t* calcBackOff );
/*!
* \brief Searches and set the next random available channel
*
@@ -491,4 +494,8 @@ void RegionRU864RxBeaconSetup( RxBeaconSetup_t* rxBeaconSetup, uint8_t* outDr );
/*! \} defgroup REGIONRU864 */
#ifdef __cplusplus
}
#endif
#endif // __REGION_RU864_H__

View File

@@ -254,38 +254,12 @@ static bool VerifyRfFreq( uint32_t freq )
return true;
}
static uint8_t CountNbOfEnabledChannels( uint8_t datarate, uint16_t* channelsMask, ChannelParams_t* channels, Band_t* bands, uint8_t* enabledChannels, uint8_t* delayTx )
static TimerTime_t GetTimeOnAir( int8_t datarate, uint16_t pktLen )
{
uint8_t nbEnabledChannels = 0;
uint8_t delayTransmission = 0;
int8_t phyDr = DataratesUS915[datarate];
uint32_t bandwidth = GetBandwidth( datarate );
for( uint8_t i = 0, k = 0; i < US915_MAX_NB_CHANNELS; i += 16, k++ )
{
for( uint8_t j = 0; j < 16; j++ )
{
if( ( channelsMask[k] & ( 1 << j ) ) != 0 )
{
if( channels[i + j].Frequency == 0 )
{ // Check if the channel is enabled
continue;
}
if( RegionCommonValueInRange( datarate, channels[i + j].DrRange.Fields.Min,
channels[i + j].DrRange.Fields.Max ) == false )
{ // Check if the current channel selection supports the given datarate
continue;
}
if( bands[channels[i + j].Band].TimeOff > 0 )
{ // Check if the band is available for transmission
delayTransmission++;
continue;
}
enabledChannels[nbEnabledChannels++] = i + j;
}
}
}
*delayTx = delayTransmission;
return nbEnabledChannels;
return Radio.TimeOnAir( MODEM_LORA, bandwidth, phyDr, 1, 8, false, pktLen, true );
}
PhyParam_t RegionUS915GetPhyParam( GetPhyParams_t* getPhy )
@@ -339,11 +313,6 @@ PhyParam_t RegionUS915GetPhyParam( GetPhyParams_t* getPhy )
phyParam.Value = MaxPayloadOfDatarateUS915[getPhy->Datarate];
break;
}
case PHY_MAX_PAYLOAD_REPEATER:
{
phyParam.Value = MaxPayloadOfDatarateRepeaterUS915[getPhy->Datarate];
break;
}
case PHY_DUTY_CYCLE:
{
phyParam.Value = US915_DUTY_CYCLE_ENABLED;
@@ -427,7 +396,7 @@ PhyParam_t RegionUS915GetPhyParam( GetPhyParams_t* getPhy )
}
case PHY_DEF_MAX_EIRP:
{
phyParam.fValue = US915_DEFAULT_MAX_ERP + 2.15;
phyParam.fValue = US915_DEFAULT_MAX_ERP + 2.15f;
break;
}
case PHY_DEF_ANTENNA_GAIN:
@@ -437,7 +406,7 @@ PhyParam_t RegionUS915GetPhyParam( GetPhyParams_t* getPhy )
}
case PHY_BEACON_CHANNEL_FREQ:
{
phyParam.Value = US915_BEACON_CHANNEL_FREQ;
phyParam.Value = US915_BEACON_CHANNEL_FREQ + ( getPhy->Channel * US915_BEACON_CHANNEL_STEPWIDTH );
break;
}
case PHY_BEACON_FORMAT:
@@ -462,11 +431,26 @@ PhyParam_t RegionUS915GetPhyParam( GetPhyParams_t* getPhy )
phyParam.Value = US915_BEACON_NB_CHANNELS;
break;
}
case PHY_PING_SLOT_CHANNEL_FREQ:
{
phyParam.Value = US915_PING_SLOT_CHANNEL_FREQ + ( getPhy->Channel * US915_BEACON_CHANNEL_STEPWIDTH );
break;
}
case PHY_PING_SLOT_CHANNEL_DR:
{
phyParam.Value = US915_PING_SLOT_CHANNEL_DR;
break;
}
case PHY_SF_FROM_DR:
{
phyParam.Value = DataratesUS915[getPhy->Datarate];
break;
}
case PHY_BW_FROM_DR:
{
phyParam.Value = GetBandwidth( getPhy->Datarate );
break;
}
default:
{
break;
@@ -478,7 +462,8 @@ PhyParam_t RegionUS915GetPhyParam( GetPhyParams_t* getPhy )
void RegionUS915SetBandTxDone( SetBandTxDoneParams_t* txDone )
{
RegionCommonSetBandTxDone( txDone->Joined, &NvmCtx.Bands[NvmCtx.Channels[txDone->Channel].Band], txDone->LastTxDoneTime );
RegionCommonSetBandTxDone( &NvmCtx.Bands[NvmCtx.Channels[txDone->Channel].Band],
txDone->LastTxAirTime, txDone->Joined, txDone->ElapsedTimeSinceStartUp );
}
void RegionUS915InitDefaults( InitDefaultsParams_t* params )
@@ -490,7 +475,7 @@ void RegionUS915InitDefaults( InitDefaultsParams_t* params )
switch( params->Type )
{
case INIT_TYPE_INIT:
case INIT_TYPE_BANDS:
{
// Initialize bands
memcpy1( ( uint8_t* )NvmCtx.Bands, ( uint8_t* )bands, sizeof( Band_t ) * US915_MAX_NB_BANDS );
@@ -501,6 +486,23 @@ void RegionUS915InitDefaults( InitDefaultsParams_t* params )
// Initialize the join trials counter
NvmCtx.JoinTrialsCounter = 0;
// ChannelsMask
NvmCtx.ChannelsDefaultMask[0] = 0xFFFF;
NvmCtx.ChannelsDefaultMask[1] = 0xFFFF;
NvmCtx.ChannelsDefaultMask[2] = 0xFFFF;
NvmCtx.ChannelsDefaultMask[3] = 0xFFFF;
NvmCtx.ChannelsDefaultMask[4] = 0x00FF;
NvmCtx.ChannelsDefaultMask[5] = 0x0000;
// Copy channels default mask
RegionCommonChanMaskCopy( NvmCtx.ChannelsMask, NvmCtx.ChannelsDefaultMask, 6 );
// Copy into channels mask remaining
RegionCommonChanMaskCopy( NvmCtx.ChannelsMaskRemaining, NvmCtx.ChannelsMask, 6 );
break;
}
case INIT_TYPE_INIT:
{
// Channels
// 125 kHz channels
for( uint8_t i = 0; i < US915_MAX_NB_CHANNELS - 8; i++ )
@@ -516,20 +518,6 @@ void RegionUS915InitDefaults( InitDefaultsParams_t* params )
NvmCtx.Channels[i].DrRange.Value = ( DR_4 << 4 ) | DR_4;
NvmCtx.Channels[i].Band = 0;
}
// ChannelsMask
NvmCtx.ChannelsDefaultMask[0] = 0xFFFF;
NvmCtx.ChannelsDefaultMask[1] = 0xFFFF;
NvmCtx.ChannelsDefaultMask[2] = 0xFFFF;
NvmCtx.ChannelsDefaultMask[3] = 0xFFFF;
NvmCtx.ChannelsDefaultMask[4] = 0x00FF;
NvmCtx.ChannelsDefaultMask[5] = 0x0000;
// Copy channels default mask
RegionCommonChanMaskCopy( NvmCtx.ChannelsMask, NvmCtx.ChannelsDefaultMask, 6 );
// Copy into channels mask remaining
RegionCommonChanMaskCopy( NvmCtx.ChannelsMaskRemaining, NvmCtx.ChannelsMask, 6 );
break;
}
case INIT_TYPE_RESTORE_CTX:
@@ -568,6 +556,10 @@ bool RegionUS915Verify( VerifyParams_t* verify, PhyAttribute_t phyAttribute )
{
switch( phyAttribute )
{
case PHY_FREQUENCY:
{
return VerifyRfFreq( verify->Frequency );
}
case PHY_TX_DR:
{
return RegionCommonValueInRange( verify->DatarateParams.Datarate, US915_TX_MIN_DATARATE, US915_TX_MAX_DATARATE );
@@ -676,7 +668,6 @@ void RegionUS915ComputeRxWindowParameters( int8_t datarate, uint8_t minRxSymbols
bool RegionUS915RxConfig( RxConfigParams_t* rxConfig, int8_t* datarate )
{
int8_t dr = rxConfig->Datarate;
uint8_t maxPayload = 0;
int8_t phyDr = 0;
uint32_t frequency = rxConfig->Frequency;
@@ -699,15 +690,7 @@ bool RegionUS915RxConfig( RxConfigParams_t* rxConfig, int8_t* datarate )
// Radio configuration
Radio.SetRxConfig( MODEM_LORA, rxConfig->Bandwidth, phyDr, 1, 0, 8, rxConfig->WindowTimeout, false, 0, false, 0, 0, true, rxConfig->RxContinuous );
if( rxConfig->RepeaterSupport == true )
{
maxPayload = MaxPayloadOfDatarateRepeaterUS915[dr];
}
else
{
maxPayload = MaxPayloadOfDatarateUS915[dr];
}
Radio.SetMaxPayloadLength( MODEM_LORA, maxPayload + LORA_MAC_FRMPAYLOAD_OVERHEAD );
Radio.SetMaxPayloadLength( MODEM_LORA, MaxPayloadOfDatarateUS915[dr] + LORAMAC_FRAME_PAYLOAD_OVERHEAD_SIZE );
*datarate = (uint8_t) dr;
return true;
@@ -726,14 +709,15 @@ bool RegionUS915TxConfig( TxConfigParams_t* txConfig, int8_t* txPower, TimerTime
// Setup the radio frequency
Radio.SetChannel( NvmCtx.Channels[txConfig->Channel].Frequency );
Radio.SetTxConfig( MODEM_LORA, phyTxPower, 0, bandwidth, phyDr, 1, 8, false, true, 0, 0, false, 3000 );
Radio.SetTxConfig( MODEM_LORA, phyTxPower, 0, bandwidth, phyDr, 1, 8, false, true, 0, 0, false, 4000 );
// Setup maximum payload lenght of the radio driver
Radio.SetMaxPayloadLength( MODEM_LORA, txConfig->PktLen );
// Get the time-on-air of the next tx frame
*txTimeOnAir = Radio.TimeOnAir( MODEM_LORA, txConfig->PktLen );
*txPower = txPowerLimited;
// Update time-on-air
*txTimeOnAir = GetTimeOnAir( txConfig->Datarate, txConfig->PktLen );
*txPower = txPowerLimited;
return true;
}
@@ -969,29 +953,15 @@ int8_t RegionUS915AlternateDr( int8_t currentDr, AlternateDrType_t type )
return currentDr;
}
void RegionUS915CalcBackOff( CalcBackOffParams_t* calcBackOff )
{
RegionCommonCalcBackOffParams_t calcBackOffParams;
calcBackOffParams.Channels = NvmCtx.Channels;
calcBackOffParams.Bands = NvmCtx.Bands;
calcBackOffParams.LastTxIsJoinRequest = calcBackOff->LastTxIsJoinRequest;
calcBackOffParams.Joined = calcBackOff->Joined;
calcBackOffParams.DutyCycleEnabled = calcBackOff->DutyCycleEnabled;
calcBackOffParams.Channel = calcBackOff->Channel;
calcBackOffParams.ElapsedTime = calcBackOff->ElapsedTime;
calcBackOffParams.TxTimeOnAir = calcBackOff->TxTimeOnAir;
RegionCommonCalcBackOff( &calcBackOffParams );
}
LoRaMacStatus_t RegionUS915NextChannel( NextChanParams_t* nextChanParams, uint8_t* channel, TimerTime_t* time, TimerTime_t* aggregatedTimeOff )
{
uint8_t nbEnabledChannels = 0;
uint8_t delayTx = 0;
uint8_t nbRestrictedChannels = 0;
uint8_t enabledChannels[US915_MAX_NB_CHANNELS] = { 0 };
TimerTime_t nextTxDelay = 0;
uint8_t newChannelIndex;
uint8_t newChannelIndex = 0;
RegionCommonIdentifyChannelsParam_t identifyChannelsParam;
RegionCommonCountNbOfEnabledChannelsParams_t countChannelsParams;
LoRaMacStatus_t status = LORAMAC_STATUS_NO_CHANNEL_FOUND;
// Count 125kHz channels
if( RegionCommonCountChannels( NvmCtx.ChannelsMaskRemaining, 0, 4 ) == 0 )
@@ -1009,26 +979,30 @@ LoRaMacStatus_t RegionUS915NextChannel( NextChanParams_t* nextChanParams, uint8_
}
}
if( nextChanParams->AggrTimeOff <= TimerGetElapsedTime( nextChanParams->LastAggrTx ) )
{
// Reset Aggregated time off
*aggregatedTimeOff = 0;
// Search how many channels are enabled
countChannelsParams.Joined = nextChanParams->Joined;
countChannelsParams.Datarate = nextChanParams->Datarate;
countChannelsParams.ChannelsMask = NvmCtx.ChannelsMaskRemaining;
countChannelsParams.Channels = NvmCtx.Channels;
countChannelsParams.Bands = NvmCtx.Bands;
countChannelsParams.MaxNbChannels = US915_MAX_NB_CHANNELS;
countChannelsParams.JoinChannels = 0;
// Update bands Time OFF
nextTxDelay = RegionCommonUpdateBandTimeOff( nextChanParams->Joined, nextChanParams->DutyCycleEnabled, NvmCtx.Bands, US915_MAX_NB_BANDS );
identifyChannelsParam.AggrTimeOff = nextChanParams->AggrTimeOff;
identifyChannelsParam.LastAggrTx = nextChanParams->LastAggrTx;
identifyChannelsParam.DutyCycleEnabled = nextChanParams->DutyCycleEnabled;
identifyChannelsParam.MaxBands = US915_MAX_NB_BANDS;
// Search how many channels are enabled
nbEnabledChannels = CountNbOfEnabledChannels( nextChanParams->Datarate,
NvmCtx.ChannelsMaskRemaining, NvmCtx.Channels,
NvmCtx.Bands, enabledChannels, &delayTx );
}
else
{
delayTx++;
nextTxDelay = nextChanParams->AggrTimeOff - TimerGetElapsedTime( nextChanParams->LastAggrTx );
}
identifyChannelsParam.CountNbOfEnabledChannelsParam = &countChannelsParams;
if( nbEnabledChannels > 0 )
identifyChannelsParam.ElapsedTimeSinceStartUp = nextChanParams->ElapsedTimeSinceStartUp;
identifyChannelsParam.LastTxIsJoinRequest = nextChanParams->LastTxIsJoinRequest;
identifyChannelsParam.ExpectedTimeOnAir = GetTimeOnAir( nextChanParams->Datarate, nextChanParams->PktLen );
status = RegionCommonIdentifyChannels( &identifyChannelsParam, aggregatedTimeOff, enabledChannels,
&nbEnabledChannels, &nbRestrictedChannels, time );
if( status == LORAMAC_STATUS_OK )
{
if( nextChanParams->Joined == true )
{
@@ -1066,22 +1040,8 @@ LoRaMacStatus_t RegionUS915NextChannel( NextChanParams_t* nextChanParams, uint8_
// Disable the channel in the mask
RegionCommonChanDisable( NvmCtx.ChannelsMaskRemaining, *channel, US915_MAX_NB_CHANNELS );
*time = 0;
return LORAMAC_STATUS_OK;
}
else
{
if( delayTx > 0 )
{
// Delay transmission due to AggregatedTimeOff or to a band time off
*time = nextTxDelay;
return LORAMAC_STATUS_DUTYCYCLE_RESTRICTED;
}
// Datarate not supported by any channel
*time = 0;
return LORAMAC_STATUS_NO_CHANNEL_FOUND;
}
return status;
}
LoRaMacStatus_t RegionUS915ChannelAdd( ChannelAddParams_t* channelAdd )

View File

@@ -37,6 +37,11 @@
#ifndef __REGION_US915_H__
#define __REGION_US915_H__
#ifdef __cplusplus
extern "C"
{
#endif
#include "region/Region.h"
/*!
@@ -87,7 +92,7 @@
/*!
* Minimal Tx output power that can be used by the node
*/
#define US915_MIN_TX_POWER TX_POWER_10
#define US915_MIN_TX_POWER TX_POWER_14
/*!
* Maximal Tx output power that can be used by the node
@@ -182,6 +187,11 @@
*/
#define US915_BEACON_CHANNEL_STEPWIDTH 600000
/*!
* Ping slot channel frequency
*/
#define US915_PING_SLOT_CHANNEL_FREQ 923300000
/*!
* Number of possible beacon channels
*/
@@ -224,9 +234,9 @@
/*!
* Band 0 definition
* { DutyCycle, TxMaxPower, LastJoinTxDoneTime, LastTxDoneTime, TimeOff }
* Band = { DutyCycle, TxMaxPower, LastBandUpdateTime, TimeCredits, MaxTimeCredits, ReadyForTransmission }
*/
#define US915_BAND0 { 1, US915_MAX_TX_POWER, 0, 0, 0 } // 100.0 %
#define US915_BAND0 { 1, US915_MAX_TX_POWER, 0, 0, 0, 0 } // 100.0 %
/*!
* Defines the first channel for RX window 1 for US band
@@ -266,15 +276,10 @@ static const int8_t DatarateOffsetsUS915[5][4] =
};
/*!
* Maximum payload with respect to the datarate index. Cannot operate with repeater.
* Maximum payload with respect to the datarate index.
*/
static const uint8_t MaxPayloadOfDatarateUS915[] = { 11, 53, 125, 242, 242, 0, 0, 0, 53, 129, 242, 242, 242, 242, 0, 0 };
/*!
* Maximum payload with respect to the datarate index. Can operate with repeater.
*/
static const uint8_t MaxPayloadOfDatarateRepeaterUS915[] = { 11, 53, 125, 242, 242, 0, 0, 0, 33, 109, 222, 222, 222, 222, 0, 0 };
/*!
* \brief The function gets a value of a specific phy attribute.
*
@@ -432,13 +437,6 @@ uint8_t RegionUS915DlChannelReq( DlChannelReqParams_t* dlChannelReq );
*/
int8_t RegionUS915AlternateDr( int8_t currentDr, AlternateDrType_t type );
/*!
* \brief Calculates the back-off time.
*
* \param [IN] calcBackOff Pointer to the function parameters.
*/
void RegionUS915CalcBackOff( CalcBackOffParams_t* calcBackOff );
/*!
* \brief Searches and set the next random available channel
*
@@ -496,8 +494,12 @@ uint8_t RegionUS915ApplyDrOffset( uint8_t downlinkDwellTime, int8_t dr, int8_t d
*
* \param [IN] rxBeaconSetup Pointer to the function parameters
*/
void RegionUS915RxBeaconSetup( RxBeaconSetup_t* rxBeaconSetup, uint8_t* outDr );
void RegionUS915RxBeaconSetup( RxBeaconSetup_t* rxBeaconSetup, uint8_t* outDr );
/*! \} defgroup REGIONUS915 */
#ifdef __cplusplus
}
#endif
#endif // __REGION_US915_H__

View File

@@ -30,13 +30,37 @@
*
* \author Johannes Bruder ( STACKFORCE )
*
* \defgroup SECUREELEMENT Secure Element API Definition
*
* \{
*
*/
#ifndef __SECURE_ELEMENT_H__
#define __SECURE_ELEMENT_H__
#ifdef __cplusplus
extern "C"
{
#endif
#include <stdint.h>
#include "LoRaMacCrypto.h"
/*!
* Secure-element keys size in bytes
*/
#define SE_KEY_SIZE 16
/*!
* Secure-element EUI size in bytes
*/
#define SE_EUI_SIZE 8
/*!
* Secure-element pin size in bytes
*/
#define SE_PIN_SIZE 4
/*!
* Return values.
*/
@@ -70,6 +94,10 @@ typedef enum eSecureElementStatus
* Undefined Error occurred
*/
SECURE_ELEMENT_ERROR,
/*!
* Failed to encrypt
*/
SECURE_ELEMENT_FAIL_ENCRYPT,
}SecureElementStatus_t;
/*!
@@ -77,7 +105,7 @@ typedef enum eSecureElementStatus
* non volatile context have to be stored.
*
*/
typedef void ( *EventNvmCtxChanged )( void );
typedef void ( *SecureElementNvmEvent )( void );
/*!
* Initialization of Secure Element driver
@@ -86,7 +114,7 @@ typedef void ( *EventNvmCtxChanged )( void );
* non-volatile context have to be stored.
* \retval - Status of the operation
*/
SecureElementStatus_t SecureElementInit( EventNvmCtxChanged seNvmCtxChanged );
SecureElementStatus_t SecureElementInit( SecureElementNvmEvent seNvmCtxChanged );
/*!
* Restores the internal nvm context from passed pointer.
@@ -114,15 +142,16 @@ void* SecureElementGetNvmCtx( size_t* seNvmCtxSize );
SecureElementStatus_t SecureElementSetKey( KeyIdentifier_t keyID, uint8_t* key );
/*!
* Computes a CMAC
* Computes a CMAC of a message using provided initial Bx block
*
* \param[IN] micBxBuffer - Buffer containing the initial Bx block
* \param[IN] buffer - Data buffer
* \param[IN] size - Data buffer size
* \param[IN] keyID - Key identifier to determine the AES key to be used
* \param[OUT] cmac - Computed cmac
* \retval - Status of the operation
*/
SecureElementStatus_t SecureElementComputeAesCmac( uint8_t* buffer, uint16_t size, KeyIdentifier_t keyID, uint32_t* cmac );
SecureElementStatus_t SecureElementComputeAesCmac( uint8_t* micBxBuffer, uint8_t* buffer, uint16_t size, KeyIdentifier_t keyID, uint32_t* cmac );
/*!
* Verifies a CMAC (computes and compare with expected cmac)
@@ -157,6 +186,22 @@ SecureElementStatus_t SecureElementAesEncrypt( uint8_t* buffer, uint16_t size, K
*/
SecureElementStatus_t SecureElementDeriveAndStoreKey( Version_t version, uint8_t* input, KeyIdentifier_t rootKeyID, KeyIdentifier_t targetKeyID );
/*!
* Process JoinAccept message.
*
* \param[IN] encJoinAccept - Received encrypted JoinAccept message
* \param[IN] encJoinAcceptSize - Received encrypted JoinAccept message Size
* \param[OUT] decJoinAccept - Decrypted and validated JoinAccept message
* \param[OUT] versionMinor - Detected LoRaWAN specification version minor field.
* - 0 -> LoRaWAN 1.0.x
* - 1 -> LoRaWAN 1.1.x
* \retval - Status of the operation
*/
SecureElementStatus_t SecureElementProcessJoinAccept( JoinReqIdentifier_t joinReqType, uint8_t* joinEui,
uint16_t devNonce, uint8_t* encJoinAccept,
uint8_t encJoinAcceptSize, uint8_t* decJoinAccept,
uint8_t* versionMinor );
/*!
* Generates a random number
*
@@ -165,4 +210,55 @@ SecureElementStatus_t SecureElementDeriveAndStoreKey( Version_t version, uint8_t
*/
SecureElementStatus_t SecureElementRandomNumber( uint32_t* randomNum );
/*!
* Sets the DevEUI
*
* \param[IN] devEui - Pointer to the 8-byte devEUI
* \retval - Status of the operation
*/
SecureElementStatus_t SecureElementSetDevEui( uint8_t* devEui );
/*!
* Gets the DevEUI
*
* \retval - Pointer to the 8-byte devEUI
*/
uint8_t* SecureElementGetDevEui( void );
/*!
* Sets the JoinEUI
*
* \param[IN] joinEui - Pointer to the 8-byte joinEui
* \retval - Status of the operation
*/
SecureElementStatus_t SecureElementSetJoinEui( uint8_t* joinEui );
/*!
* Gets the DevEUI
*
* \retval - Pointer to the 8-byte joinEui
*/
uint8_t* SecureElementGetJoinEui( void );
/*!
* Sets the pin
*
* \param[IN] pin - Pointer to the 4-byte pin
* \retval - Status of the operation
*/
SecureElementStatus_t SecureElementSetPin( uint8_t* pin );
/*!
* Gets the Pin
*
* \retval - Pointer to the 4-byte pin
*/
uint8_t* SecureElementGetPin( void );
/*! \} defgroup SECUREELEMENT */
#ifdef __cplusplus
}
#endif
#endif // __SECURE_ELEMENT_H__