mirror of https://github.com/ARMmbed/mbed-os.git
Adding PHY layer for LoRaWAN
LoRaPHY is the abstract class for the LoRa PHY layer which governs the LoRaRadio and provides some common functionality to all regional implementations. We support 10 regions and every region comes loaded with default parameters. These parameters can be changed by the Mac layer or explicitely by the stack controller layer using APIs provided. This layer in essence detaches Mac completely from PHY and provides more modular approach to the entire system. Apart from class structure, the internal functionality is directly deduced from semtech reference implementation that's why most of the internal data structures are used on 'as is' basis. In addition to that, the PHY layer provides APIs to control the LoRaRadio layer, i.e., the lora radio driver, ensuring that the radio is accessed from a single entry point. A seperate data structure file is added which is common to PHY layers only.pull/6087/head
parent
c9804bd167
commit
c861c321be
|
@ -0,0 +1,437 @@
|
|||
/**
|
||||
/ _____) _ | |
|
||||
( (____ _____ ____ _| |_ _____ ____| |__
|
||||
\____ \| ___ | (_ _) ___ |/ ___) _ \
|
||||
_____) ) ____| | | || |_| ____( (___| | | |
|
||||
(______/|_____)_|_|_| \__)_____)\____)_| |_|
|
||||
(C)2013 Semtech
|
||||
___ _____ _ ___ _ _____ ___ ___ ___ ___
|
||||
/ __|_ _/_\ / __| |/ / __/ _ \| _ \/ __| __|
|
||||
\__ \ | |/ _ \ (__| ' <| _| (_) | / (__| _|
|
||||
|___/ |_/_/ \_\___|_|\_\_| \___/|_|_\\___|___|
|
||||
embedded.connectivity.solutions===============
|
||||
|
||||
License: Revised BSD License, see LICENSE.TXT file include in the project
|
||||
|
||||
Maintainer: Miguel Luis ( Semtech ), Gregory Cristian ( Semtech ) and Daniel Jaeckle ( STACKFORCE )
|
||||
|
||||
|
||||
Copyright (c) 2017, Arm Limited and affiliates.
|
||||
|
||||
SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <stdint.h>
|
||||
#include <math.h>
|
||||
#include "lorawan/lorastack/phy/LoRaPHY.h"
|
||||
#include "lorawan/system/LoRaWANTimer.h"
|
||||
|
||||
#define BACKOFF_DC_1_HOUR 100
|
||||
#define BACKOFF_DC_10_HOURS 1000
|
||||
#define BACKOFF_DC_24_HOURS 10000
|
||||
|
||||
static uint8_t CountChannels( uint16_t mask, uint8_t nbBits )
|
||||
{
|
||||
uint8_t nbActiveBits = 0;
|
||||
|
||||
for( uint8_t j = 0; j < nbBits; j++ )
|
||||
{
|
||||
if( ( mask & ( 1 << j ) ) == ( 1 << j ) )
|
||||
{
|
||||
nbActiveBits++;
|
||||
}
|
||||
}
|
||||
return nbActiveBits;
|
||||
}
|
||||
|
||||
LoRaPHY::LoRaPHY()
|
||||
{
|
||||
}
|
||||
|
||||
LoRaPHY::~LoRaPHY()
|
||||
{
|
||||
_radio = NULL;
|
||||
}
|
||||
|
||||
void LoRaPHY::set_radio_instance(LoRaRadio& radio)
|
||||
{
|
||||
_radio = &radio;
|
||||
}
|
||||
|
||||
void LoRaPHY::put_radio_to_sleep() {
|
||||
_radio->lock();
|
||||
_radio->sleep();
|
||||
_radio->unlock();
|
||||
}
|
||||
|
||||
void LoRaPHY::put_radio_to_standby() {
|
||||
_radio->lock();
|
||||
_radio->standby();
|
||||
_radio->unlock();
|
||||
}
|
||||
|
||||
void LoRaPHY::setup_tx_cont_wave_mode(uint16_t timeout, uint32_t frequency,
|
||||
uint8_t power)
|
||||
{
|
||||
_radio->lock();
|
||||
_radio->set_tx_continuous_wave(frequency, power, timeout);
|
||||
_radio->unlock();
|
||||
}
|
||||
|
||||
void LoRaPHY::setup_public_network_mode(bool set)
|
||||
{
|
||||
_radio->lock();
|
||||
_radio->set_public_network(set);
|
||||
_radio->unlock();
|
||||
}
|
||||
|
||||
void LoRaPHY::setup_rx_window(bool rx_continuous, uint32_t max_rx_window)
|
||||
{
|
||||
_radio->lock();
|
||||
|
||||
if (!rx_continuous) {
|
||||
_radio->receive(max_rx_window);
|
||||
_radio->unlock();
|
||||
return;
|
||||
}
|
||||
|
||||
_radio->receive(0); // Continuous mode
|
||||
|
||||
_radio->unlock();
|
||||
}
|
||||
|
||||
// For DevNonce for example
|
||||
uint32_t LoRaPHY::get_radio_rng()
|
||||
{
|
||||
uint32_t rand;
|
||||
|
||||
_radio->lock();
|
||||
rand =_radio->random();
|
||||
_radio->unlock();
|
||||
|
||||
return rand;
|
||||
}
|
||||
|
||||
void LoRaPHY::handle_send(uint8_t *buf, uint8_t size)
|
||||
{
|
||||
_radio->lock();
|
||||
_radio->send(buf, size);
|
||||
_radio->unlock();
|
||||
}
|
||||
|
||||
int32_t LoRaPHY::get_random(int32_t min, int32_t max)
|
||||
{
|
||||
return (int32_t) rand() % (max - min + 1) + min;
|
||||
}
|
||||
|
||||
uint16_t LoRaPHY::get_join_DC( TimerTime_t elapsedTime )
|
||||
{
|
||||
uint16_t dutyCycle = 0;
|
||||
|
||||
if( elapsedTime < 3600000 )
|
||||
{
|
||||
dutyCycle = BACKOFF_DC_1_HOUR;
|
||||
}
|
||||
else if( elapsedTime < ( 3600000 + 36000000 ) )
|
||||
{
|
||||
dutyCycle = BACKOFF_DC_10_HOURS;
|
||||
}
|
||||
else
|
||||
{
|
||||
dutyCycle = BACKOFF_DC_24_HOURS;
|
||||
}
|
||||
return dutyCycle;
|
||||
}
|
||||
|
||||
bool LoRaPHY::verify_channel_DR( uint8_t nbChannels, uint16_t* channelsMask, int8_t dr, int8_t minDr, int8_t maxDr, ChannelParams_t* channels )
|
||||
{
|
||||
if( val_in_range( dr, minDr, maxDr ) == 0 )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
for( uint8_t i = 0, k = 0; i < nbChannels; i += 16, k++ )
|
||||
{
|
||||
for( uint8_t j = 0; j < 16; j++ )
|
||||
{
|
||||
if( ( ( channelsMask[k] & ( 1 << j ) ) != 0 ) )
|
||||
{// Check datarate validity for enabled channels
|
||||
if( val_in_range( dr, ( channels[i + j].DrRange.Fields.Min & 0x0F ),
|
||||
( channels[i + j].DrRange.Fields.Max & 0x0F ) ) == 1 )
|
||||
{
|
||||
// At least 1 channel has been found we can return OK.
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
uint8_t LoRaPHY::val_in_range( int8_t value, int8_t min, int8_t max )
|
||||
{
|
||||
if( ( value >= min ) && ( value <= max ) )
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool LoRaPHY::disable_channel( uint16_t* channelsMask, uint8_t id, uint8_t maxChannels )
|
||||
{
|
||||
uint8_t index = id / 16;
|
||||
|
||||
if( ( index > ( maxChannels / 16 ) ) || ( id >= maxChannels ) )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// Deactivate channel
|
||||
channelsMask[index] &= ~( 1 << ( id % 16 ) );
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
uint8_t LoRaPHY::num_active_channels( uint16_t* channelsMask, uint8_t startIdx, uint8_t stopIdx )
|
||||
{
|
||||
uint8_t nbChannels = 0;
|
||||
|
||||
if( channelsMask == NULL )
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
for( uint8_t i = startIdx; i < stopIdx; i++ )
|
||||
{
|
||||
nbChannels += CountChannels( channelsMask[i], 16 );
|
||||
}
|
||||
|
||||
return nbChannels;
|
||||
}
|
||||
|
||||
void LoRaPHY::copy_channel_mask( uint16_t* channelsMaskDest, uint16_t* channelsMaskSrc, uint8_t len )
|
||||
{
|
||||
if( ( channelsMaskDest != NULL ) && ( channelsMaskSrc != NULL ) )
|
||||
{
|
||||
for( uint8_t i = 0; i < len; i++ )
|
||||
{
|
||||
channelsMaskDest[i] = channelsMaskSrc[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void LoRaPHY::set_last_tx_done( bool joined, Band_t* band, TimerTime_t lastTxDone )
|
||||
{
|
||||
if( joined == true )
|
||||
{
|
||||
band->LastTxDoneTime = lastTxDone;
|
||||
}
|
||||
else
|
||||
{
|
||||
band->LastTxDoneTime = lastTxDone;
|
||||
band->LastJoinTxDoneTime = lastTxDone;
|
||||
}
|
||||
}
|
||||
|
||||
TimerTime_t LoRaPHY::update_band_timeoff( bool joined, bool dutyCycle, Band_t* bands, uint8_t nbBands )
|
||||
{
|
||||
TimerTime_t nextTxDelay = ( TimerTime_t )( -1 );
|
||||
|
||||
// Update bands Time OFF
|
||||
for( uint8_t i = 0; i < nbBands; i++ )
|
||||
{
|
||||
if( joined == false )
|
||||
{
|
||||
uint32_t txDoneTime = MAX( TimerGetElapsedTime( bands[i].LastJoinTxDoneTime ),
|
||||
( dutyCycle == true ) ? TimerGetElapsedTime( bands[i].LastTxDoneTime ) : 0 );
|
||||
|
||||
if( bands[i].TimeOff <= txDoneTime )
|
||||
{
|
||||
bands[i].TimeOff = 0;
|
||||
}
|
||||
if( bands[i].TimeOff != 0 )
|
||||
{
|
||||
nextTxDelay = MIN( bands[i].TimeOff - txDoneTime, nextTxDelay );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if( dutyCycle == true )
|
||||
{
|
||||
if( bands[i].TimeOff <= TimerGetElapsedTime( bands[i].LastTxDoneTime ) )
|
||||
{
|
||||
bands[i].TimeOff = 0;
|
||||
}
|
||||
if( bands[i].TimeOff != 0 )
|
||||
{
|
||||
nextTxDelay = MIN( bands[i].TimeOff - TimerGetElapsedTime( bands[i].LastTxDoneTime ),
|
||||
nextTxDelay );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
nextTxDelay = 0;
|
||||
bands[i].TimeOff = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
return nextTxDelay;
|
||||
}
|
||||
|
||||
uint8_t LoRaPHY::parse_link_ADR_req( uint8_t* payload, RegionCommonLinkAdrParams_t* linkAdrParams )
|
||||
{
|
||||
uint8_t retIndex = 0;
|
||||
|
||||
if( payload[0] == SRV_MAC_LINK_ADR_REQ )
|
||||
{
|
||||
// Parse datarate and tx power
|
||||
linkAdrParams->Datarate = payload[1];
|
||||
linkAdrParams->TxPower = linkAdrParams->Datarate & 0x0F;
|
||||
linkAdrParams->Datarate = ( linkAdrParams->Datarate >> 4 ) & 0x0F;
|
||||
// Parse ChMask
|
||||
linkAdrParams->ChMask = ( uint16_t )payload[2];
|
||||
linkAdrParams->ChMask |= ( uint16_t )payload[3] << 8;
|
||||
// Parse ChMaskCtrl and nbRep
|
||||
linkAdrParams->NbRep = payload[4];
|
||||
linkAdrParams->ChMaskCtrl = ( linkAdrParams->NbRep >> 4 ) & 0x07;
|
||||
linkAdrParams->NbRep &= 0x0F;
|
||||
|
||||
// LinkAdrReq has 4 bytes length + 1 byte CMD
|
||||
retIndex = 5;
|
||||
}
|
||||
return retIndex;
|
||||
}
|
||||
|
||||
uint8_t LoRaPHY::verify_link_ADR_req( RegionCommonLinkAdrReqVerifyParams_t* verifyParams, int8_t* dr, int8_t* txPow, uint8_t* nbRep )
|
||||
{
|
||||
uint8_t status = verifyParams->Status;
|
||||
int8_t datarate = verifyParams->Datarate;
|
||||
int8_t txPower = verifyParams->TxPower;
|
||||
int8_t nbRepetitions = verifyParams->NbRep;
|
||||
|
||||
// Handle the case when ADR is off.
|
||||
if( verifyParams->AdrEnabled == false )
|
||||
{
|
||||
// When ADR is off, we are allowed to change the channels mask and the NbRep,
|
||||
// if the datarate and the TX power of the LinkAdrReq are set to 0x0F.
|
||||
if( ( verifyParams->Datarate != 0x0F ) || ( verifyParams->TxPower != 0x0F ) )
|
||||
{
|
||||
status = 0;
|
||||
nbRepetitions = verifyParams->CurrentNbRep;
|
||||
}
|
||||
// Get the current datarate and tx power
|
||||
datarate = verifyParams->CurrentDatarate;
|
||||
txPower = verifyParams->CurrentTxPower;
|
||||
}
|
||||
|
||||
if( status != 0 )
|
||||
{
|
||||
// Verify datarate. The variable phyParam. Value contains the minimum allowed datarate.
|
||||
if( verify_channel_DR( verifyParams->NbChannels, verifyParams->ChannelsMask, datarate,
|
||||
verifyParams->MinDatarate, verifyParams->MaxDatarate, verifyParams->Channels ) == false )
|
||||
{
|
||||
status &= 0xFD; // Datarate KO
|
||||
}
|
||||
|
||||
// Verify tx power
|
||||
if( val_in_range( txPower, verifyParams->MaxTxPower, verifyParams->MinTxPower ) == 0 )
|
||||
{
|
||||
// Verify if the maximum TX power is exceeded
|
||||
if( verifyParams->MaxTxPower > txPower )
|
||||
{ // Apply maximum TX power. Accept TX power.
|
||||
txPower = verifyParams->MaxTxPower;
|
||||
}
|
||||
else
|
||||
{
|
||||
status &= 0xFB; // TxPower KO
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// If the status is ok, verify the NbRep
|
||||
if( status == 0x07 )
|
||||
{
|
||||
if( nbRepetitions == 0 )
|
||||
{ // Keep the current one
|
||||
nbRepetitions = verifyParams->CurrentNbRep;
|
||||
}
|
||||
}
|
||||
|
||||
// Apply changes
|
||||
*dr = datarate;
|
||||
*txPow = txPower;
|
||||
*nbRep = nbRepetitions;
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
double LoRaPHY::compute_symb_timeout_lora( uint8_t phyDr, uint32_t bandwidth )
|
||||
{
|
||||
return ( ( double )( 1 << phyDr ) / ( double )bandwidth ) * 1000;
|
||||
}
|
||||
|
||||
double LoRaPHY::compute_symb_timeout_fsk( uint8_t phyDr )
|
||||
{
|
||||
return ( 8.0 / ( double )phyDr ); // 1 symbol equals 1 byte
|
||||
}
|
||||
|
||||
void LoRaPHY::get_rx_window_params( double tSymbol, uint8_t minRxSymbols, uint32_t rxError, uint32_t wakeUpTime, uint32_t* windowTimeout, int32_t* windowOffset )
|
||||
{
|
||||
*windowTimeout = MAX( ( uint32_t )ceil( ( ( 2 * minRxSymbols - 8 ) * tSymbol + 2 * rxError ) / tSymbol ), minRxSymbols ); // Computed number of symbols
|
||||
*windowOffset = ( int32_t )ceil( ( 4.0 * tSymbol ) - ( ( *windowTimeout * tSymbol ) / 2.0 ) - wakeUpTime );
|
||||
}
|
||||
|
||||
int8_t LoRaPHY::compute_tx_power( int8_t txPowerIndex, float maxEirp, float antennaGain )
|
||||
{
|
||||
int8_t phyTxPower = 0;
|
||||
|
||||
phyTxPower = ( int8_t )floor( ( maxEirp - ( txPowerIndex * 2U ) ) - antennaGain );
|
||||
|
||||
return phyTxPower;
|
||||
}
|
||||
|
||||
void LoRaPHY::get_DC_backoff( 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 = get_join_DC( 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;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,677 @@
|
|||
/**
|
||||
* @file LoRaPHY.h
|
||||
*
|
||||
* @brief An abstract class providing radio object to children and
|
||||
* provide base for implementing LoRa PHY layer
|
||||
*
|
||||
* \code
|
||||
* ______ _
|
||||
* / _____) _ | |
|
||||
* ( (____ _____ ____ _| |_ _____ ____| |__
|
||||
* \____ \| ___ | (_ _) ___ |/ ___) _ \
|
||||
* _____) ) ____| | | || |_| ____( (___| | | |
|
||||
* (______/|_____)_|_|_| \__)_____)\____)_| |_|
|
||||
* (C)2013 Semtech
|
||||
* ___ _____ _ ___ _ _____ ___ ___ ___ ___
|
||||
* / __|_ _/_\ / __| |/ / __/ _ \| _ \/ __| __|
|
||||
* \__ \ | |/ _ \ (__| ' <| _| (_) | / (__| _|
|
||||
* |___/ |_/_/ \_\___|_|\_\_| \___/|_|_\\___|___|
|
||||
* embedded.connectivity.solutions===============
|
||||
*
|
||||
* \endcode
|
||||
*
|
||||
* Description: LoRa PHY layer
|
||||
*
|
||||
* License: Revised BSD License, see LICENSE.TXT file include in the project
|
||||
*
|
||||
* Maintainer: Miguel Luis ( Semtech ), Gregory Cristian ( Semtech ) and Daniel Jaeckle ( STACKFORCE )
|
||||
*
|
||||
* Copyright (c) 2017, Arm Limited and affiliates.
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef MBED_OS_LORAPHY_BASE_
|
||||
#define MBED_OS_LORAPHY_BASE_
|
||||
|
||||
#include "lorawan/system/LoRaWANTimer.h"
|
||||
#include "lorawan/lorastack/phy/lora_phy_ds.h"
|
||||
#include "netsocket/LoRaRadio.h"
|
||||
|
||||
class LoRaPHY {
|
||||
|
||||
public:
|
||||
LoRaPHY();
|
||||
virtual ~LoRaPHY();
|
||||
|
||||
void set_radio_instance(LoRaRadio& radio);
|
||||
|
||||
void put_radio_to_sleep(void);
|
||||
|
||||
void put_radio_to_standby(void);
|
||||
|
||||
void setup_rx_window(bool is_rx_continuous, uint32_t max_rx_window);
|
||||
|
||||
void setup_tx_cont_wave_mode(uint16_t timeout, uint32_t frequency,
|
||||
uint8_t power);
|
||||
|
||||
void handle_send(uint8_t *buf, uint8_t size);
|
||||
|
||||
void setup_public_network_mode(bool set);
|
||||
|
||||
uint32_t get_radio_rng();
|
||||
|
||||
/*!
|
||||
* \brief The function gets a value of a specific PHY attribute.
|
||||
*
|
||||
* \param [in] getPhy A pointer to the function parameters.
|
||||
*
|
||||
* \retval A structure containing the PHY parameter.
|
||||
*/
|
||||
virtual PhyParam_t get_phy_params(GetPhyParams_t* getPhy ) = 0;
|
||||
|
||||
/*!
|
||||
* \brief Updates the last TX done parameters of the current channel.
|
||||
*
|
||||
* \param [in] txDone A pointer to the function parameters.
|
||||
*/
|
||||
virtual void set_band_tx_done(SetBandTxDoneParams_t* txDone ) = 0;
|
||||
|
||||
/*!
|
||||
* \brief Initializes the channels masks and the channels.
|
||||
*
|
||||
* \param [in] type Sets the initialization type.
|
||||
*/
|
||||
virtual void load_defaults(InitType_t type ) = 0;
|
||||
|
||||
/*!
|
||||
* \brief Verifies a parameter.
|
||||
*
|
||||
* \param [in] verify A pointer to the function parameters.
|
||||
*
|
||||
* \param [in] phyAttribute The attribute for which the verification is needed.
|
||||
*
|
||||
* \retval True, if the parameter is valid.
|
||||
*/
|
||||
virtual bool verify(VerifyParams_t* verify, PhyAttribute_t phyAttribute ) = 0;
|
||||
|
||||
/*!
|
||||
* \brief The function parses the input buffer and sets up the channels of the CF list.
|
||||
*
|
||||
* \param [in] applyCFList A pointer to the function parameters.
|
||||
*/
|
||||
virtual void apply_cf_list(ApplyCFListParams_t* applyCFList ) = 0;
|
||||
|
||||
/*!
|
||||
* \brief Sets a channels mask.
|
||||
*
|
||||
* \param [in] chanMaskSet A pointer to the function parameters.
|
||||
*
|
||||
* \retval True, if the channels mask could be set.
|
||||
*/
|
||||
virtual bool set_channel_mask(ChanMaskSetParams_t* chanMaskSet ) = 0;
|
||||
|
||||
/*!
|
||||
* \brief Calculates the next datarate to set, when ADR is on or off.
|
||||
*
|
||||
* \param [in] adrNext A pointer to the function parameters.
|
||||
*
|
||||
* \param [out] drOut The calculated datarate for the next TX.
|
||||
*
|
||||
* \param [out] txPowOut The TX power for the next TX.
|
||||
*
|
||||
* \param [out] adrAckCounter The calculated ADR acknowledgement counter.
|
||||
*
|
||||
* \retval True, if an ADR request should be performed.
|
||||
*/
|
||||
virtual bool get_next_ADR(AdrNextParams_t* adrNext, int8_t* drOut,
|
||||
int8_t* txPowOut, uint32_t* adrAckCounter ) = 0;
|
||||
|
||||
/*!
|
||||
* \brief Configuration of the RX windows.
|
||||
*
|
||||
* \param [in] rxConfig A pointer to the function parameters.
|
||||
*
|
||||
* \param [out] datarate The datarate index set.
|
||||
*
|
||||
* \retval True, if the configuration was applied successfully.
|
||||
*/
|
||||
virtual bool rx_config(RxConfigParams_t* rxConfig, int8_t* datarate ) = 0;
|
||||
|
||||
/*
|
||||
* RX window precise timing
|
||||
*
|
||||
* For more details please consult the following document, chapter 3.1.2.
|
||||
* http://www.semtech.com/images/datasheet/SX1272_settings_for_LoRaWAN_v2.0.pdf
|
||||
* or
|
||||
* http://www.semtech.com/images/datasheet/SX1276_settings_for_LoRaWAN_v2.0.pdf
|
||||
*
|
||||
* Downlink start: T = Tx + 1s (+/- 20 us)
|
||||
* |
|
||||
* TRxEarly | TRxLate
|
||||
* | | |
|
||||
* | | +---+---+---+---+---+---+---+---+
|
||||
* | | | Latest Rx window |
|
||||
* | | +---+---+---+---+---+---+---+---+
|
||||
* | | |
|
||||
* +---+---+---+---+---+---+---+---+
|
||||
* | Earliest Rx window |
|
||||
* +---+---+---+---+---+---+---+---+
|
||||
* |
|
||||
* +---+---+---+---+---+---+---+---+
|
||||
*Downlink preamble 8 symbols | | | | | | | | |
|
||||
* +---+---+---+---+---+---+---+---+
|
||||
*
|
||||
* Worst case Rx window timings
|
||||
*
|
||||
* TRxLate = DEFAULT_MIN_RX_SYMBOLS * tSymbol - RADIO_WAKEUP_TIME
|
||||
* TRxEarly = 8 - DEFAULT_MIN_RX_SYMBOLS * tSymbol - RxWindowTimeout - RADIO_WAKEUP_TIME
|
||||
*
|
||||
* TRxLate - TRxEarly = 2 * DEFAULT_SYSTEM_MAX_RX_ERROR
|
||||
*
|
||||
* RxOffset = ( TRxLate + TRxEarly ) / 2
|
||||
*
|
||||
* RxWindowTimeout = ( 2 * DEFAULT_MIN_RX_SYMBOLS - 8 ) * tSymbol + 2 * DEFAULT_SYSTEM_MAX_RX_ERROR
|
||||
* RxOffset = 4 * tSymbol - RxWindowTimeout / 2 - RADIO_WAKE_UP_TIME
|
||||
*
|
||||
* The minimum value of RxWindowTimeout must be 5 symbols which implies that the system always tolerates at least an error of 1.5 * tSymbol.
|
||||
*/
|
||||
/*!
|
||||
* Computes the RX window timeout and offset.
|
||||
*
|
||||
* \param [in] datarate The RX window datarate index to be used.
|
||||
*
|
||||
* \param [in] minRxSymbols The minimum number of symbols required to detect an RX frame.
|
||||
*
|
||||
* \param [in] rxError The maximum timing error of the receiver in milliseconds.
|
||||
* The receiver will turn on in a [-rxError : +rxError] ms
|
||||
* interval around RxOffset.
|
||||
*
|
||||
* \param [out] rxConfigParams Returns the updated WindowTimeout and WindowOffset fields.
|
||||
*
|
||||
*/
|
||||
virtual void compute_rx_win_params(int8_t datarate,
|
||||
uint8_t minRxSymbols,
|
||||
uint32_t rxError,
|
||||
RxConfigParams_t *rxConfigParams) = 0;
|
||||
/*!
|
||||
* \brief TX configuration.
|
||||
*
|
||||
* \param [in] txConfig A pointer to the function parameters.
|
||||
*
|
||||
* \param [out] txPower The TX power index set.
|
||||
*
|
||||
* \param [out] txTimeOnAir The time-on-air of the frame.
|
||||
*
|
||||
* \retval True, if the configuration was applied successfully.
|
||||
*/
|
||||
virtual bool tx_config(TxConfigParams_t* txConfig, int8_t* txPower,
|
||||
TimerTime_t* txTimeOnAir ) = 0;
|
||||
|
||||
/*!
|
||||
* \brief The function processes a Link ADR Request.
|
||||
*
|
||||
* \param [in] linkAdrReq A pointer to the function parameters.
|
||||
*
|
||||
* \param [out] drOut The datarate applied.
|
||||
*
|
||||
* \param [out] txPowOut The TX power applied.
|
||||
*
|
||||
* \param [out] nbRepOut The number of repetitions to apply.
|
||||
*
|
||||
* \param [out] nbBytesParsed The number of bytes parsed.
|
||||
*
|
||||
* \retval The status of the operation, according to the LoRaMAC specification.
|
||||
*/
|
||||
virtual uint8_t link_ADR_request(LinkAdrReqParams_t* linkAdrReq,
|
||||
int8_t* drOut, int8_t* txPowOut,
|
||||
uint8_t* nbRepOut,
|
||||
uint8_t* nbBytesParsed ) = 0;
|
||||
|
||||
/*!
|
||||
* \brief The function processes a RX Parameter Setup Request.
|
||||
*
|
||||
* \param [in] rxParamSetupReq A pointer to the function parameters.
|
||||
*
|
||||
* \retval The status of the operation, according to the LoRaMAC specification.
|
||||
*/
|
||||
virtual uint8_t setup_rx_params(RxParamSetupReqParams_t* rxParamSetupReq ) = 0;
|
||||
|
||||
/*!
|
||||
* \brief The function processes a New Channel Request.
|
||||
*
|
||||
* \param [in] newChannelReq A pointer to the function parameters.
|
||||
*
|
||||
* \retval The status of the operation, according to the LoRaMAC specification.
|
||||
*/
|
||||
virtual uint8_t request_new_channel(NewChannelReqParams_t* newChannelReq ) = 0;
|
||||
|
||||
/*!
|
||||
* \brief The function processes a TX ParamSetup Request.
|
||||
*
|
||||
* \param [in] txParamSetupReq A pointer to the function parameters.
|
||||
*
|
||||
* \retval The status of the operation, according to the LoRaMAC specification.
|
||||
* Returns -1, if the functionality is not implemented. In this case, the end node
|
||||
* shall ignore the command.
|
||||
*/
|
||||
virtual int8_t setup_tx_params(TxParamSetupReqParams_t* txParamSetupReq ) = 0;
|
||||
|
||||
/*!
|
||||
* \brief The function processes a DlChannel Request.
|
||||
*
|
||||
* \param [in] dlChannelReq A pointer to the function parameters.
|
||||
*
|
||||
* \retval The status of the operation, according to the LoRaMAC specification.
|
||||
*/
|
||||
virtual uint8_t dl_channel_request(DlChannelReqParams_t* dlChannelReq ) = 0;
|
||||
|
||||
/*!
|
||||
* \brief Alternates the datarate of the channel for the join request.
|
||||
*
|
||||
* \param [in] alternateDr A pointer to the function parameters.
|
||||
*
|
||||
* \retval The datarate to apply.
|
||||
*/
|
||||
virtual int8_t get_alternate_DR(AlternateDrParams_t* alternateDr ) = 0;
|
||||
|
||||
/*!
|
||||
* \brief Calculates the back-off time.
|
||||
*
|
||||
* \param [in] calcBackOff A pointer to the function parameters.
|
||||
*/
|
||||
virtual void calculate_backoff(CalcBackOffParams_t* calcBackOff ) = 0;
|
||||
|
||||
/*!
|
||||
* \brief Searches and sets the next random available channel.
|
||||
*
|
||||
* \param [in] nextChanParams Parameters for the next channel.
|
||||
*
|
||||
* \param [out] channel The next channel to use for TX.
|
||||
*
|
||||
* \param [out] time The time to wait for the next transmission according to the duty cycle.
|
||||
*
|
||||
* \param [out] aggregatedTimeOff Updates the aggregated time off.
|
||||
*
|
||||
* \retval Function status [1: OK, 0: Unable to find a channel on the current datarate].
|
||||
*/
|
||||
virtual bool set_next_channel(NextChanParams_t* nextChanParams,
|
||||
uint8_t* channel, TimerTime_t* time,
|
||||
TimerTime_t* aggregatedTimeOff ) = 0;
|
||||
|
||||
/*!
|
||||
* \brief Adds a channel.
|
||||
*
|
||||
* \param [in] channelAdd A pointer to the function parameters.
|
||||
*
|
||||
* \retval The status of the operation.
|
||||
*/
|
||||
virtual LoRaMacStatus_t add_channel(ChannelAddParams_t* channelAdd ) = 0;
|
||||
|
||||
/*!
|
||||
* \brief Removes a channel.
|
||||
*
|
||||
* \param [in] channelRemove A pointer to the function parameters.
|
||||
*
|
||||
* \retval True, if the channel was removed successfully.
|
||||
*/
|
||||
virtual bool remove_channel(ChannelRemoveParams_t* channelRemove ) = 0;
|
||||
|
||||
/*!
|
||||
* \brief Sets the radio into continuous wave mode.
|
||||
*
|
||||
* \param [in] continuousWave A pointer to the function parameters.
|
||||
*/
|
||||
virtual void set_tx_cont_mode(ContinuousWaveParams_t* continuousWave ) = 0;
|
||||
|
||||
/*!
|
||||
* \brief Computes new datarate according to the given offset
|
||||
*
|
||||
* \param [in] downlinkDwellTime The downlink dwell time configuration. 0: No limit, 1: 400ms
|
||||
*
|
||||
* \param [in] dr The current datarate.
|
||||
*
|
||||
* \param [in] drOffset The offset to be applied.
|
||||
*
|
||||
* \retval newDr The computed datarate.
|
||||
*/
|
||||
virtual uint8_t apply_DR_offset(uint8_t downlinkDwellTime, int8_t dr, int8_t drOffset ) = 0;
|
||||
|
||||
protected:
|
||||
LoRaRadio *_radio;
|
||||
|
||||
typedef struct sRegionCommonLinkAdrParams
|
||||
{
|
||||
/*!
|
||||
* The number of repetitions.
|
||||
*/
|
||||
uint8_t NbRep;
|
||||
/*!
|
||||
* Datarate.
|
||||
*/
|
||||
int8_t Datarate;
|
||||
/*!
|
||||
* TX power.
|
||||
*/
|
||||
int8_t TxPower;
|
||||
/*!
|
||||
* Channels mask control field.
|
||||
*/
|
||||
uint8_t ChMaskCtrl;
|
||||
/*!
|
||||
* Channels mask field.
|
||||
*/
|
||||
uint16_t ChMask;
|
||||
}RegionCommonLinkAdrParams_t;
|
||||
|
||||
typedef struct sRegionCommonLinkAdrReqVerifyParams
|
||||
{
|
||||
/*!
|
||||
* The current status of the AdrLinkRequest.
|
||||
*/
|
||||
uint8_t Status;
|
||||
/*!
|
||||
* Set to true, if ADR is enabled.
|
||||
*/
|
||||
bool AdrEnabled;
|
||||
/*!
|
||||
* The datarate the AdrLinkRequest wants to set.
|
||||
*/
|
||||
int8_t Datarate;
|
||||
/*!
|
||||
* The TX power the AdrLinkRequest wants to set.
|
||||
*/
|
||||
int8_t TxPower;
|
||||
/*!
|
||||
* The number of repetitions the AdrLinkRequest wants to set.
|
||||
*/
|
||||
uint8_t NbRep;
|
||||
/*!
|
||||
* The current datarate the node is using.
|
||||
*/
|
||||
int8_t CurrentDatarate;
|
||||
/*!
|
||||
* The current TX power the node is using.
|
||||
*/
|
||||
int8_t CurrentTxPower;
|
||||
/*!
|
||||
* The current number of repetitions the node is using.
|
||||
*/
|
||||
int8_t CurrentNbRep;
|
||||
/*!
|
||||
* The number of channels.
|
||||
*/
|
||||
uint8_t NbChannels;
|
||||
/*!
|
||||
* A pointer to the first element of the channels mask.
|
||||
*/
|
||||
uint16_t* ChannelsMask;
|
||||
/*!
|
||||
* The minimum possible datarate.
|
||||
*/
|
||||
int8_t MinDatarate;
|
||||
/*!
|
||||
* The maximum possible datarate.
|
||||
*/
|
||||
int8_t MaxDatarate;
|
||||
/*!
|
||||
* A pointer to the channels.
|
||||
*/
|
||||
ChannelParams_t* Channels;
|
||||
/*!
|
||||
* The minimum possible TX power.
|
||||
*/
|
||||
int8_t MinTxPower;
|
||||
/*!
|
||||
* The maximum possible TX power.
|
||||
*/
|
||||
int8_t MaxTxPower;
|
||||
}RegionCommonLinkAdrReqVerifyParams_t;
|
||||
|
||||
typedef struct sRegionCommonCalcBackOffParams
|
||||
{
|
||||
/*!
|
||||
* A pointer to region specific channels.
|
||||
*/
|
||||
ChannelParams_t* Channels;
|
||||
/*!
|
||||
* A pointer to region specific bands.
|
||||
*/
|
||||
Band_t* Bands;
|
||||
/*!
|
||||
* Set to true, if the last uplink was a join request.
|
||||
*/
|
||||
bool LastTxIsJoinRequest;
|
||||
/*!
|
||||
* Set to true, if the node is joined.
|
||||
*/
|
||||
bool Joined;
|
||||
/*!
|
||||
* Set to true, if the duty cycle is enabled.
|
||||
*/
|
||||
bool DutyCycleEnabled;
|
||||
/*!
|
||||
* The current channel.
|
||||
*/
|
||||
uint8_t Channel;
|
||||
/*!
|
||||
* The elapsed time since initialization.
|
||||
*/
|
||||
TimerTime_t ElapsedTime;
|
||||
/*!
|
||||
* The time on air of the last TX frame.
|
||||
*/
|
||||
TimerTime_t TxTimeOnAir;
|
||||
}RegionCommonCalcBackOffParams_t;
|
||||
|
||||
/*!
|
||||
* \brief Calculates the join duty cycle.
|
||||
* This is a generic function and valid for all regions.
|
||||
*
|
||||
* \param [in] elapsedTime The time elapsed since starting the device.
|
||||
*
|
||||
* \retval Duty cycle restriction.
|
||||
*/
|
||||
uint16_t get_join_DC( TimerTime_t elapsedTime );
|
||||
|
||||
/*!
|
||||
* \brief Verifies, if a value is in a given range.
|
||||
* This is a generic function and valid for all regions.
|
||||
*
|
||||
* \param [in] value The value to verify, if it is in range.
|
||||
*
|
||||
* \param [in] min The minimum possible value.
|
||||
*
|
||||
* \param [in] max The maximum possible value.
|
||||
*
|
||||
* \retval 1 if the value is in range, otherwise 0.
|
||||
*/
|
||||
uint8_t val_in_range( int8_t value, int8_t min, int8_t max );
|
||||
|
||||
/*!
|
||||
* \brief Verifies, if a datarate is available on an active channel.
|
||||
* This is a generic function and valid for all regions.
|
||||
*
|
||||
* \param [in] nbChannels The number of channels.
|
||||
*
|
||||
* \param [in] channelsMask The channels mask of the region.
|
||||
*
|
||||
* \param [in] dr The datarate to verify.
|
||||
*
|
||||
* \param [in] minDr The minimum datarate.
|
||||
*
|
||||
* \param [in] maxDr The maximum datarate.
|
||||
*
|
||||
* \param [in] channels The channels of the region.
|
||||
*
|
||||
* \retval True if the datarate is supported, false if not.
|
||||
*/
|
||||
bool verify_channel_DR( uint8_t nbChannels, uint16_t* channelsMask, int8_t dr,
|
||||
int8_t minDr, int8_t maxDr, ChannelParams_t* channels );
|
||||
|
||||
/*!
|
||||
* \brief Disables a channel in a given channels mask.
|
||||
* This is a generic function and valid for all regions.
|
||||
*
|
||||
* \param [in] channelsMask The channels mask of the region.
|
||||
*
|
||||
* \param [in] id The ID of the channels mask to disable.
|
||||
*
|
||||
* \param [in] maxChannels The maximum number of channels.
|
||||
*
|
||||
* \retval True if the channel could be disabled, false if not.
|
||||
*/
|
||||
bool disable_channel( uint16_t* channelsMask, uint8_t id, uint8_t maxChannels );
|
||||
|
||||
/*!
|
||||
* \brief Counts the number of active channels in a given channels mask.
|
||||
* This is a generic function and valid for all regions.
|
||||
*
|
||||
* \param [in] channelsMask The channels mask of the region.
|
||||
*
|
||||
* \param [in] startIdx The start index.
|
||||
*
|
||||
* \param [in] stopIdx The stop index (the channels of this index will not be counted).
|
||||
*
|
||||
* \retval The number of active channels.
|
||||
*/
|
||||
uint8_t num_active_channels( uint16_t* channelsMask, uint8_t startIdx, uint8_t stopIdx );
|
||||
|
||||
/*!
|
||||
* \brief Copy a channels mask.
|
||||
* This is a generic function and valid for all regions.
|
||||
*
|
||||
* \param [in] channelsMaskDest The destination channels mask.
|
||||
*
|
||||
* \param [in] channelsMaskSrc The source channels mask.
|
||||
*
|
||||
* \param [in] len The index length to copy.
|
||||
*/
|
||||
void copy_channel_mask( uint16_t* channelsMaskDest, uint16_t* channelsMaskSrc, uint8_t len );
|
||||
|
||||
/*!
|
||||
* \brief Sets the last TX done property.
|
||||
* This is a generic function and valid for all regions.
|
||||
*
|
||||
* \param [in] joined Set to true, if the node has joined the network
|
||||
*
|
||||
* \param [in] band The band to be updated.
|
||||
*
|
||||
* \param [in] lastTxDone The time of the last TX done.
|
||||
*/
|
||||
void set_last_tx_done( bool joined, Band_t* band, TimerTime_t lastTxDone );
|
||||
|
||||
/*!
|
||||
* \brief Updates the time-offs of the bands.
|
||||
* This is a generic function and valid for all regions.
|
||||
*
|
||||
* \param [in] joined Set to true, if the node has joined the network
|
||||
*
|
||||
* \param [in] dutyCycle Set to true, if the duty cycle is enabled.
|
||||
*
|
||||
* \param [in] bands A pointer to the bands.
|
||||
*
|
||||
* \param [in] nbBands The number of bands available.
|
||||
*
|
||||
* \retval The time which must be waited to perform the next uplink.
|
||||
*/
|
||||
TimerTime_t update_band_timeoff( bool joined, bool dutyCycle, Band_t* bands, uint8_t nbBands );
|
||||
|
||||
/*!
|
||||
* \brief Parses the parameter of an LinkAdrRequest.
|
||||
* This is a generic function and valid for all regions.
|
||||
*
|
||||
* \param [in] payload A pointer to the payload containing the MAC commands. The payload
|
||||
* must contain the CMD identifier, followed by the parameters.
|
||||
*
|
||||
* \param [out] parseLinkAdr The function fills the structure with the ADR parameters.
|
||||
*
|
||||
* \retval The length of the ADR request, if a request was found. Otherwise, the
|
||||
* function returns 0.
|
||||
*/
|
||||
uint8_t parse_link_ADR_req( uint8_t* payload, RegionCommonLinkAdrParams_t* parseLinkAdr );
|
||||
|
||||
/*!
|
||||
* \brief Verifies and updates the datarate, the TX power and the number of repetitions
|
||||
* of a LinkAdrRequest. This also depends on the ADR configuration.
|
||||
*
|
||||
* \param [in] verifyParams A pointer to a structure containing the input parameters.
|
||||
*
|
||||
* \param [out] dr The updated datarate.
|
||||
*
|
||||
* \param [out] txPow The updated TX power.
|
||||
*
|
||||
* \param [out] nbRep The updated number of repetitions.
|
||||
*
|
||||
* \retval The status according to the LinkAdrRequest definition.
|
||||
*/
|
||||
uint8_t verify_link_ADR_req( RegionCommonLinkAdrReqVerifyParams_t* verifyParams, int8_t* dr, int8_t* txPow, uint8_t* nbRep );
|
||||
|
||||
/*!
|
||||
* \brief Computes the symbol time for LoRa modulation.
|
||||
*
|
||||
* \param [in] phyDr The physical datarate to use.
|
||||
*
|
||||
* \param [in] bandwidth The bandwidth to use.
|
||||
*
|
||||
* \retval The symbol time.
|
||||
*/
|
||||
double compute_symb_timeout_lora( uint8_t phyDr, uint32_t bandwidth );
|
||||
|
||||
/*!
|
||||
* \brief Computes the symbol time for FSK modulation.
|
||||
*
|
||||
* \param [in] phyDr The physical datarate to use.
|
||||
*
|
||||
* \retval The symbol time.
|
||||
*/
|
||||
double compute_symb_timeout_fsk( uint8_t phyDr );
|
||||
|
||||
/*!
|
||||
* \brief Computes the RX window timeout and the RX window offset.
|
||||
*
|
||||
* \param [in] tSymbol The symbol timeout.
|
||||
*
|
||||
* \param [in] minRxSymbols The minimum required number of symbols to detect an RX frame.
|
||||
*
|
||||
* \param [in] rxError The system maximum timing error of the receiver in milliseconds
|
||||
* The receiver will turn on in a [-rxError : +rxError] ms interval around RxOffset.
|
||||
*
|
||||
* \param [in] wakeUpTime The wakeup time of the system.
|
||||
*
|
||||
* \param [out] windowTimeout The RX window timeout.
|
||||
*
|
||||
* \param [out] windowOffset The RX window time offset to be applied to the RX delay.
|
||||
*/
|
||||
void get_rx_window_params( double tSymbol, uint8_t minRxSymbols, uint32_t rxError, uint32_t wakeUpTime, uint32_t* windowTimeout, int32_t* windowOffset );
|
||||
|
||||
/*!
|
||||
* \brief Computes the txPower, based on the max EIRP and the antenna gain.
|
||||
*
|
||||
* \param [in] txPowerIndex The TX power index.
|
||||
*
|
||||
* \param [in] maxEirp The maximum EIRP.
|
||||
*
|
||||
* \param [in] antennaGain The antenna gain.
|
||||
*
|
||||
* \retval The physical TX power.
|
||||
*/
|
||||
int8_t compute_tx_power( int8_t txPowerIndex, float maxEirp, float antennaGain );
|
||||
|
||||
/*!
|
||||
* \brief Provides a random number in the range provided.
|
||||
*
|
||||
* \param [in] min lower boundary
|
||||
* \param [in] max upper boundary
|
||||
*/
|
||||
int32_t get_random(int32_t min, int32_t max);
|
||||
|
||||
/*!
|
||||
* \brief Calculates the duty cycle for the current band.
|
||||
*
|
||||
* \param [in] calcBackOffParams A pointer to the input parameters.
|
||||
*/
|
||||
void get_DC_backoff( RegionCommonCalcBackOffParams_t* calcBackOffParams );
|
||||
};
|
||||
|
||||
#endif /* MBED_OS_LORAPHY_BASE_ */
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,363 @@
|
|||
/**
|
||||
* @file LoRaPHYAS923.h
|
||||
*
|
||||
* @brief Implements LoRaPHY for Asia-Pacific 923 MHz band
|
||||
*
|
||||
* \code
|
||||
* ______ _
|
||||
* / _____) _ | |
|
||||
* ( (____ _____ ____ _| |_ _____ ____| |__
|
||||
* \____ \| ___ | (_ _) ___ |/ ___) _ \
|
||||
* _____) ) ____| | | || |_| ____( (___| | | |
|
||||
* (______/|_____)_|_|_| \__)_____)\____)_| |_|
|
||||
* (C)2013 Semtech
|
||||
* ___ _____ _ ___ _ _____ ___ ___ ___ ___
|
||||
* / __|_ _/_\ / __| |/ / __/ _ \| _ \/ __| __|
|
||||
* \__ \ | |/ _ \ (__| ' <| _| (_) | / (__| _|
|
||||
* |___/ |_/_/ \_\___|_|\_\_| \___/|_|_\\___|___|
|
||||
* embedded.connectivity.solutions===============
|
||||
*
|
||||
* \endcode
|
||||
*
|
||||
*
|
||||
* License: Revised BSD License, see LICENSE.TXT file include in the project
|
||||
*
|
||||
* Maintainer: Miguel Luis ( Semtech ), Gregory Cristian ( Semtech ) and Daniel Jaeckle ( STACKFORCE )
|
||||
*
|
||||
* Copyright (c) 2017, Arm Limited and affiliates.
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef MBED_OS_LORAPHY_AS923_H_
|
||||
#define MBED_OS_LORAPHY_AS923_H_
|
||||
|
||||
#include "LoRaPHY.h"
|
||||
#include "netsocket/LoRaRadio.h"
|
||||
|
||||
/*!
|
||||
* LoRaMac maximum number of channels
|
||||
*/
|
||||
#define AS923_MAX_NB_CHANNELS 16
|
||||
|
||||
/*!
|
||||
* Maximum number of bands
|
||||
*/
|
||||
#define AS923_MAX_NB_BANDS 1
|
||||
|
||||
#define AS923_CHANNELS_MASK_SIZE 1
|
||||
|
||||
|
||||
class LoRaPHYAS923 : public LoRaPHY {
|
||||
|
||||
public:
|
||||
|
||||
LoRaPHYAS923();
|
||||
virtual ~LoRaPHYAS923();
|
||||
|
||||
/*!
|
||||
* \brief The function gets a value of a specific PHY attribute.
|
||||
*
|
||||
* \param [in] getPhy A pointer to the function parameters.
|
||||
*
|
||||
* \retval A structure containing the PHY parameter.
|
||||
*/
|
||||
virtual PhyParam_t get_phy_params(GetPhyParams_t* getPhy );
|
||||
|
||||
/*!
|
||||
* \brief Updates the last TX done parameters of the current channel.
|
||||
*
|
||||
* \param [in] txDone A pointer to the function parameters.
|
||||
*/
|
||||
virtual void set_band_tx_done(SetBandTxDoneParams_t* txDone );
|
||||
|
||||
/*!
|
||||
* \brief Initializes the channels masks and the channels.
|
||||
*
|
||||
* \param [in] type Sets the initialization type.
|
||||
*/
|
||||
virtual void load_defaults(InitType_t type );
|
||||
|
||||
/*!
|
||||
* \brief Verifies a parameter.
|
||||
*
|
||||
* \param [in] verify A pointer to the function parameters.
|
||||
*
|
||||
* \param [in] phyAttribute The attribute to be verified.
|
||||
*
|
||||
* \retval True, if the parameter is valid.
|
||||
*/
|
||||
virtual bool verify(VerifyParams_t* verify, PhyAttribute_t phyAttribute );
|
||||
|
||||
/*!
|
||||
* \brief The function parses the input buffer and sets up the channels of the
|
||||
* CF list.
|
||||
*
|
||||
* \param [in] applyCFList A pointer to the function parameters.
|
||||
*/
|
||||
virtual void apply_cf_list(ApplyCFListParams_t* applyCFList );
|
||||
|
||||
/*!
|
||||
* \brief Sets a channels mask.
|
||||
*
|
||||
* \param [in] chanMaskSet A pointer to the function parameters.
|
||||
*
|
||||
* \retval True, if the channels mask could be set.
|
||||
*/
|
||||
virtual bool set_channel_mask(ChanMaskSetParams_t* chanMaskSet );
|
||||
|
||||
/*!
|
||||
* \brief Calculates the next datarate to set, when ADR is on or off.
|
||||
*
|
||||
* \param [in] adrNext A pointer to the function parameters.
|
||||
*
|
||||
* \param [out] drOut The calculated datarate for the next TX.
|
||||
*
|
||||
* \param [out] txPowOut The TX power for the next TX.
|
||||
*
|
||||
* \param [out] adrAckCounter The calculated ADR acknowledgement counter.
|
||||
*
|
||||
* \retval True, if an ADR request should be performed.
|
||||
*/
|
||||
virtual bool get_next_ADR(AdrNextParams_t* adrNext, int8_t* drOut,
|
||||
int8_t* txPowOut, uint32_t* adrAckCounter );
|
||||
|
||||
/*!
|
||||
* \brief Configuration of the RX windows.
|
||||
*
|
||||
* \param [in] rxConfig A pointer to the function parameters.
|
||||
*
|
||||
* \param [out] datarate The datarate index set.
|
||||
*
|
||||
* \retval True, if the configuration was applied successfully.
|
||||
*/
|
||||
virtual bool rx_config(RxConfigParams_t* rxConfig, int8_t* datarate );
|
||||
|
||||
/*
|
||||
* RX window precise timing.
|
||||
*
|
||||
* For more details please consult the following document, chapter 3.1.2.
|
||||
* http://www.semtech.com/images/datasheet/SX1272_settings_for_LoRaWAN_v2.0.pdf
|
||||
* or
|
||||
* http://www.semtech.com/images/datasheet/SX1276_settings_for_LoRaWAN_v2.0.pdf
|
||||
*
|
||||
* Downlink start: T = Tx + 1s (+/- 20 us)
|
||||
* |
|
||||
* TRxEarly | TRxLate
|
||||
* | | |
|
||||
* | | +---+---+---+---+---+---+---+---+
|
||||
* | | | Latest Rx window |
|
||||
* | | +---+---+---+---+---+---+---+---+
|
||||
* | | |
|
||||
* +---+---+---+---+---+---+---+---+
|
||||
* | Earliest Rx window |
|
||||
* +---+---+---+---+---+---+---+---+
|
||||
* |
|
||||
* +---+---+---+---+---+---+---+---+
|
||||
*Downlink preamble 8 symbols | | | | | | | | |
|
||||
* +---+---+---+---+---+---+---+---+
|
||||
*
|
||||
* Worst case Rx window timings
|
||||
*
|
||||
* TRxLate = DEFAULT_MIN_RX_SYMBOLS * tSymbol - RADIO_WAKEUP_TIME
|
||||
* TRxEarly = 8 - DEFAULT_MIN_RX_SYMBOLS * tSymbol - RxWindowTimeout - RADIO_WAKEUP_TIME
|
||||
*
|
||||
* TRxLate - TRxEarly = 2 * DEFAULT_SYSTEM_MAX_RX_ERROR
|
||||
*
|
||||
* RxOffset = ( TRxLate + TRxEarly ) / 2
|
||||
*
|
||||
* RxWindowTimeout = ( 2 * DEFAULT_MIN_RX_SYMBOLS - 8 ) * tSymbol + 2 * DEFAULT_SYSTEM_MAX_RX_ERROR
|
||||
* RxOffset = 4 * tSymbol - RxWindowTimeout / 2 - RADIO_WAKE_UP_TIME
|
||||
*
|
||||
* The minimum value of RxWindowTimeout must be 5 symbols which implies that the system always tolerates at least an error of 1.5 * tSymbol
|
||||
*/
|
||||
/*!
|
||||
* Computes the RX window timeout and offset.
|
||||
*
|
||||
* \param [in] datarate The RX window datarate index to be used.
|
||||
*
|
||||
* \param [in] minRxSymbols The minimum required number of symbols to detect an RX frame.
|
||||
*
|
||||
* \param [in] rxError The system maximum timing error of the receiver in milliseconds.
|
||||
* The receiver will turn on in a [-rxError : +rxError] ms
|
||||
* interval around RxOffset.
|
||||
*
|
||||
* \param [out] rxConfigParams The updated WindowTimeout and WindowOffset fields.
|
||||
*/
|
||||
virtual void compute_rx_win_params(int8_t datarate,
|
||||
uint8_t minRxSymbols,
|
||||
uint32_t rxError,
|
||||
RxConfigParams_t *rxConfigParams);
|
||||
|
||||
/*!
|
||||
* \brief TX configuration.
|
||||
*
|
||||
* \param [in] txConfig A pointer to the function parameters.
|
||||
*
|
||||
* \param [out] txPower The TX power index set.
|
||||
*
|
||||
* \param [out] txTimeOnAir The time-on-air of the frame.
|
||||
*
|
||||
* \retval True, if the configuration was applied successfully.
|
||||
*/
|
||||
virtual bool tx_config(TxConfigParams_t* txConfig, int8_t* txPower,
|
||||
TimerTime_t* txTimeOnAir );
|
||||
|
||||
/*!
|
||||
* \brief The function processes a Link ADR Request.
|
||||
*
|
||||
* \param [in] linkAdrReq A pointer to the function parameters.
|
||||
*
|
||||
* \param [out] drOut The datarate applied.
|
||||
*
|
||||
* \param [out] txPowOut The TX power applied.
|
||||
*
|
||||
* \param [out] nbRepOut The number of repetitions to apply.
|
||||
*
|
||||
* \param [out] nbBytesParsed The number of bytes parsed.
|
||||
*
|
||||
* \retval The status of the operation, according to the LoRaMAC specification.
|
||||
*/
|
||||
virtual uint8_t link_ADR_request(LinkAdrReqParams_t* linkAdrReq,
|
||||
int8_t* drOut, int8_t* txPowOut,
|
||||
uint8_t* nbRepOut,
|
||||
uint8_t* nbBytesParsed );
|
||||
|
||||
/*!
|
||||
* \brief The function processes a RX parameter setup request.
|
||||
*
|
||||
* \param [in] rxParamSetupReq A pointer to the function parameters.
|
||||
*
|
||||
* \retval The status of the operation, according to the LoRaMAC specification.
|
||||
*/
|
||||
virtual uint8_t setup_rx_params(RxParamSetupReqParams_t* rxParamSetupReq );
|
||||
|
||||
/*!
|
||||
* \brief The function processes a new channel request.
|
||||
*
|
||||
* \param [in] newChannelReq A pointer to the function parameters.
|
||||
*
|
||||
* \retval The status of the operation, according to the LoRaMAC specification.
|
||||
*/
|
||||
virtual uint8_t request_new_channel(NewChannelReqParams_t* newChannelReq );
|
||||
|
||||
/*!
|
||||
* \brief The function processes a TX ParamSetup request.
|
||||
*
|
||||
* \param [in] txParamSetupReq A pointer to the function parameters.
|
||||
*
|
||||
* \retval The status of the operation, according to the LoRaMAC specification.
|
||||
* Returns -1, if the functionality is not implemented. In this case, the end node
|
||||
* shall ignore the command.
|
||||
*/
|
||||
virtual int8_t setup_tx_params(TxParamSetupReqParams_t* txParamSetupReq );
|
||||
|
||||
/*!
|
||||
* \brief The function processes a DlChannel request.
|
||||
*
|
||||
* \param [in] dlChannelReq A pointer to the function parameters.
|
||||
*
|
||||
* \retval The status of the operation, according to the LoRaMAC specification.
|
||||
*/
|
||||
virtual uint8_t dl_channel_request(DlChannelReqParams_t* dlChannelReq );
|
||||
|
||||
/*!
|
||||
* \brief Alternates the datarate of the channel for the join request.
|
||||
*
|
||||
* \param [in] alternateDr A pointer to the function parameters.
|
||||
*
|
||||
* \retval The datarate to apply.
|
||||
*/
|
||||
virtual int8_t get_alternate_DR(AlternateDrParams_t* alternateDr );
|
||||
|
||||
/*!
|
||||
* \brief Calculates the back-off time.
|
||||
*
|
||||
* \param [in] calcBackOff A pointer to the function parameters.
|
||||
*/
|
||||
virtual void calculate_backoff(CalcBackOffParams_t* calcBackOff );
|
||||
|
||||
/*!
|
||||
* \brief Searches and sets the next random available channel.
|
||||
*
|
||||
* \param [in] nextChanParams The parameters for the next channel
|
||||
*
|
||||
* \param [out] channel The next channel to use for TX.
|
||||
*
|
||||
* \param [out] time The time to wait for the next transmission according to the duty cycle.
|
||||
*
|
||||
* \param [out] aggregatedTimeOff Updates the aggregated time off.
|
||||
*
|
||||
* \retval Function status [1: OK, 0: Unable to find a channel on the current datarate].
|
||||
*/
|
||||
virtual bool set_next_channel(NextChanParams_t* nextChanParams,
|
||||
uint8_t* channel, TimerTime_t* time,
|
||||
TimerTime_t* aggregatedTimeOff );
|
||||
|
||||
/*!
|
||||
* \brief Adds a channel.
|
||||
*
|
||||
* \param [in] channelAdd A pointer to the function parameters.
|
||||
*
|
||||
* \retval The status of the operation.
|
||||
*/
|
||||
virtual LoRaMacStatus_t add_channel(ChannelAddParams_t* channelAdd );
|
||||
|
||||
/*!
|
||||
* \brief Removes a channel.
|
||||
*
|
||||
* \param [in] channelRemove A pointer to the function parameters.
|
||||
*
|
||||
* \retval True, if the channel was removed successfully.
|
||||
*/
|
||||
virtual bool remove_channel(ChannelRemoveParams_t* channelRemove );
|
||||
|
||||
/*!
|
||||
* \brief Sets the radio into continuous wave mode.
|
||||
*
|
||||
* \param [in] continuousWave A pointer to the function parameters.
|
||||
*/
|
||||
virtual void set_tx_cont_mode(ContinuousWaveParams_t* continuousWave );
|
||||
|
||||
/*!
|
||||
* \brief Computes a new datarate according to the given offset.
|
||||
*
|
||||
* \param [in] downlinkDwellTime The downlink dwell time configuration. 0: No limit, 1: 400ms
|
||||
*
|
||||
* \param [in] dr The current datarate.
|
||||
*
|
||||
* \param [in] drOffset The offset to be applied.
|
||||
*
|
||||
* \retval newDr The computed datarate.
|
||||
*/
|
||||
virtual uint8_t apply_DR_offset(uint8_t downlinkDwellTime, int8_t dr, int8_t drOffset );
|
||||
|
||||
private:
|
||||
uint8_t CountNbOfEnabledChannels(bool joined, uint8_t datarate,
|
||||
uint16_t* channelsMask,
|
||||
ChannelParams_t* channels, Band_t* bands,
|
||||
uint8_t* enabledChannels, uint8_t* delayTx);
|
||||
|
||||
// Global attributes
|
||||
/*!
|
||||
* LoRaMAC channels
|
||||
*/
|
||||
ChannelParams_t Channels[AS923_MAX_NB_CHANNELS];
|
||||
|
||||
/*!
|
||||
* LoRaMac bands
|
||||
*/
|
||||
Band_t Bands[AS923_MAX_NB_BANDS];
|
||||
|
||||
/*!
|
||||
* LoRaMac channels mask
|
||||
*/
|
||||
uint16_t ChannelsMask[AS923_CHANNELS_MASK_SIZE];
|
||||
|
||||
/*!
|
||||
* LoRaMac channels default mask
|
||||
*/
|
||||
uint16_t ChannelsDefaultMask[AS923_CHANNELS_MASK_SIZE];
|
||||
};
|
||||
|
||||
#endif /* MBED_OS_LORAPHY_AS923_H_ */
|
|
@ -0,0 +1,984 @@
|
|||
/**
|
||||
* @file LoRaPHYAU915.cpp
|
||||
*
|
||||
* @brief Implements LoRaPHY for Australian 915 MHz band
|
||||
*
|
||||
* \code
|
||||
* ______ _
|
||||
* / _____) _ | |
|
||||
* ( (____ _____ ____ _| |_ _____ ____| |__
|
||||
* \____ \| ___ | (_ _) ___ |/ ___) _ \
|
||||
* _____) ) ____| | | || |_| ____( (___| | | |
|
||||
* (______/|_____)_|_|_| \__)_____)\____)_| |_|
|
||||
* (C)2013 Semtech
|
||||
* ___ _____ _ ___ _ _____ ___ ___ ___ ___
|
||||
* / __|_ _/_\ / __| |/ / __/ _ \| _ \/ __| __|
|
||||
* \__ \ | |/ _ \ (__| ' <| _| (_) | / (__| _|
|
||||
* |___/ |_/_/ \_\___|_|\_\_| \___/|_|_\\___|___|
|
||||
* embedded.connectivity.solutions===============
|
||||
*
|
||||
* \endcode
|
||||
*
|
||||
*
|
||||
* License: Revised BSD License, see LICENSE.TXT file include in the project
|
||||
*
|
||||
* Maintainer: Miguel Luis ( Semtech ), Gregory Cristian ( Semtech ) and Daniel Jaeckle ( STACKFORCE )
|
||||
*
|
||||
* Copyright (c) 2017, Arm Limited and affiliates.
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*
|
||||
*/
|
||||
|
||||
#include "LoRaPHYAU915.h"
|
||||
#include "lora_phy_ds.h"
|
||||
#include "LoRaRadio.h"
|
||||
|
||||
/*!
|
||||
* Minimal datarate that can be used by the node
|
||||
*/
|
||||
#define AU915_TX_MIN_DATARATE DR_0
|
||||
|
||||
/*!
|
||||
* Maximal datarate that can be used by the node
|
||||
*/
|
||||
#define AU915_TX_MAX_DATARATE DR_6
|
||||
|
||||
/*!
|
||||
* Minimal datarate that can be used by the node
|
||||
*/
|
||||
#define AU915_RX_MIN_DATARATE DR_8
|
||||
|
||||
/*!
|
||||
* Maximal datarate that can be used by the node
|
||||
*/
|
||||
#define AU915_RX_MAX_DATARATE DR_13
|
||||
|
||||
/*!
|
||||
* Default datarate used by the node
|
||||
*/
|
||||
#define AU915_DEFAULT_DATARATE DR_0
|
||||
|
||||
/*!
|
||||
* Minimal Rx1 receive datarate offset
|
||||
*/
|
||||
#define AU915_MIN_RX1_DR_OFFSET 0
|
||||
|
||||
/*!
|
||||
* Maximal Rx1 receive datarate offset
|
||||
*/
|
||||
#define AU915_MAX_RX1_DR_OFFSET 6
|
||||
|
||||
/*!
|
||||
* Default Rx1 receive datarate offset
|
||||
*/
|
||||
#define AU915_DEFAULT_RX1_DR_OFFSET 0
|
||||
|
||||
/*!
|
||||
* Minimal Tx output power that can be used by the node
|
||||
*/
|
||||
#define AU915_MIN_TX_POWER TX_POWER_10
|
||||
|
||||
/*!
|
||||
* Maximal Tx output power that can be used by the node
|
||||
*/
|
||||
#define AU915_MAX_TX_POWER TX_POWER_0
|
||||
|
||||
/*!
|
||||
* Default Tx output power used by the node
|
||||
*/
|
||||
#define AU915_DEFAULT_TX_POWER TX_POWER_0
|
||||
|
||||
/*!
|
||||
* Default Max EIRP
|
||||
*/
|
||||
#define AU915_DEFAULT_MAX_EIRP 30.0f
|
||||
|
||||
/*!
|
||||
* Default antenna gain
|
||||
*/
|
||||
#define AU915_DEFAULT_ANTENNA_GAIN 2.15f
|
||||
|
||||
/*!
|
||||
* ADR Ack limit
|
||||
*/
|
||||
#define AU915_ADR_ACK_LIMIT 64
|
||||
|
||||
/*!
|
||||
* ADR Ack delay
|
||||
*/
|
||||
#define AU915_ADR_ACK_DELAY 32
|
||||
|
||||
/*!
|
||||
* Enabled or disabled the duty cycle
|
||||
*/
|
||||
#define AU915_DUTY_CYCLE_ENABLED 0
|
||||
|
||||
/*!
|
||||
* Maximum RX window duration
|
||||
*/
|
||||
#define AU915_MAX_RX_WINDOW 3000
|
||||
|
||||
/*!
|
||||
* Receive delay 1
|
||||
*/
|
||||
#define AU915_RECEIVE_DELAY1 1000
|
||||
|
||||
/*!
|
||||
* Receive delay 2
|
||||
*/
|
||||
#define AU915_RECEIVE_DELAY2 2000
|
||||
|
||||
/*!
|
||||
* Join accept delay 1
|
||||
*/
|
||||
#define AU915_JOIN_ACCEPT_DELAY1 5000
|
||||
|
||||
/*!
|
||||
* Join accept delay 2
|
||||
*/
|
||||
#define AU915_JOIN_ACCEPT_DELAY2 6000
|
||||
|
||||
/*!
|
||||
* Maximum frame counter gap
|
||||
*/
|
||||
#define AU915_MAX_FCNT_GAP 16384
|
||||
|
||||
/*!
|
||||
* Ack timeout
|
||||
*/
|
||||
#define AU915_ACKTIMEOUT 2000
|
||||
|
||||
/*!
|
||||
* Random ack timeout limits
|
||||
*/
|
||||
#define AU915_ACK_TIMEOUT_RND 1000
|
||||
|
||||
/*!
|
||||
* Second reception window channel frequency definition.
|
||||
*/
|
||||
#define AU915_RX_WND_2_FREQ 923300000
|
||||
|
||||
/*!
|
||||
* Second reception window channel datarate definition.
|
||||
*/
|
||||
#define AU915_RX_WND_2_DR DR_8
|
||||
|
||||
|
||||
/*!
|
||||
* Band 0 definition
|
||||
* { DutyCycle, TxMaxPower, LastTxDoneTime, TimeOff }
|
||||
*/
|
||||
#define AU915_BAND0 { 1, AU915_MAX_TX_POWER, 0, 0 } // 100.0 %
|
||||
|
||||
/*!
|
||||
* Defines the first channel for RX window 1 for US band
|
||||
*/
|
||||
#define AU915_FIRST_RX1_CHANNEL ( (uint32_t) 923300000 )
|
||||
|
||||
/*!
|
||||
* Defines the last channel for RX window 1 for US band
|
||||
*/
|
||||
#define AU915_LAST_RX1_CHANNEL ( (uint32_t) 927500000 )
|
||||
|
||||
/*!
|
||||
* Defines the step width of the channels for RX window 1
|
||||
*/
|
||||
#define AU915_STEPWIDTH_RX1_CHANNEL ( (uint32_t) 600000 )
|
||||
|
||||
/*!
|
||||
* Data rates table definition
|
||||
*/
|
||||
static const uint8_t DataratesAU915[] = { 12, 11, 10, 9, 8, 7, 8, 0, 12, 11, 10,
|
||||
9, 8, 7, 0, 0 };
|
||||
|
||||
/*!
|
||||
* Bandwidths table definition in Hz
|
||||
*/
|
||||
static const uint32_t BandwidthsAU915[] = { 125000, 125000, 125000, 125000,
|
||||
125000, 125000, 500000, 0, 500000, 500000, 500000, 500000, 500000, 500000,
|
||||
0, 0 };
|
||||
|
||||
/*!
|
||||
* Up/Down link data rates offset definition
|
||||
*/
|
||||
static const int8_t DatarateOffsetsAU915[7][6] = { { DR_8, DR_8, DR_8, DR_8,
|
||||
DR_8, DR_8 }, // DR_0
|
||||
{ DR_9, DR_8, DR_8, DR_8, DR_8, DR_8 }, // DR_1
|
||||
{ DR_10, DR_9, DR_8, DR_8, DR_8, DR_8 }, // DR_2
|
||||
{ DR_11, DR_10, DR_9, DR_8, DR_8, DR_8 }, // DR_3
|
||||
{ DR_12, DR_11, DR_10, DR_9, DR_8, DR_8 }, // DR_4
|
||||
{ DR_13, DR_12, DR_11, DR_10, DR_9, DR_8 }, // DR_5
|
||||
{ DR_13, DR_13, DR_12, DR_11, DR_10, DR_9 }, // DR_6
|
||||
};
|
||||
|
||||
/*!
|
||||
* Maximum payload with respect to the datarate index. Cannot operate with repeater.
|
||||
*/
|
||||
static const uint8_t MaxPayloadOfDatarateAU915[] = { 51, 51, 51, 115, 242, 242,
|
||||
242, 0, 53, 129, 242, 242, 242, 242, 0, 0 };
|
||||
|
||||
/*!
|
||||
* Maximum payload with respect to the datarate index. Can operate with repeater.
|
||||
*/
|
||||
static const uint8_t MaxPayloadOfDatarateRepeaterAU915[] = { 51, 51, 51, 115,
|
||||
222, 222, 222, 0, 33, 109, 222, 222, 222, 222, 0, 0 };
|
||||
|
||||
|
||||
// Static functions
|
||||
static int8_t GetNextLowerTxDr(int8_t dr, int8_t minDr)
|
||||
{
|
||||
uint8_t nextLowerDr = 0;
|
||||
|
||||
if (dr == minDr) {
|
||||
nextLowerDr = minDr;
|
||||
} else {
|
||||
nextLowerDr = dr - 1;
|
||||
}
|
||||
return nextLowerDr;
|
||||
}
|
||||
|
||||
static uint32_t GetBandwidth(uint32_t drIndex)
|
||||
{
|
||||
switch (BandwidthsAU915[drIndex]) {
|
||||
default:
|
||||
case 125000:
|
||||
return 0;
|
||||
case 250000:
|
||||
return 1;
|
||||
case 500000:
|
||||
return 2;
|
||||
}
|
||||
}
|
||||
|
||||
static int8_t LimitTxPower(int8_t txPower, int8_t maxBandTxPower,
|
||||
int8_t datarate, uint16_t* channelsMask)
|
||||
{
|
||||
int8_t txPowerResult = txPower;
|
||||
|
||||
// Limit tx power to the band max
|
||||
txPowerResult = MAX(txPower, maxBandTxPower);
|
||||
|
||||
return txPowerResult;
|
||||
}
|
||||
|
||||
uint8_t LoRaPHYAU915::CountNbOfEnabledChannels(uint8_t datarate,
|
||||
uint16_t* channelsMask,
|
||||
ChannelParams_t* channels,
|
||||
Band_t* bands, uint8_t* enabledChannels,
|
||||
uint8_t* delayTx)
|
||||
{
|
||||
uint8_t nbEnabledChannels = 0;
|
||||
uint8_t delayTransmission = 0;
|
||||
|
||||
for (uint8_t i = 0, k = 0; i < AU915_MAX_NB_CHANNELS; i += 16, k++) {
|
||||
for (uint8_t j = 0; j < 16; j++) {
|
||||
if ((channelsMask[k] & (1 << j)) != 0) {
|
||||
if (channels[i + j].Frequency == 0) { // Check if the channel is enabled
|
||||
continue;
|
||||
}
|
||||
if (val_in_range(datarate, channels[i + j].DrRange.Fields.Min,
|
||||
channels[i + j].DrRange.Fields.Max) == 0) { // 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;
|
||||
}
|
||||
|
||||
LoRaPHYAU915::LoRaPHYAU915()
|
||||
{
|
||||
const Band_t band0 = AU915_BAND0;
|
||||
Bands[0] = band0;
|
||||
}
|
||||
|
||||
LoRaPHYAU915::~LoRaPHYAU915()
|
||||
{
|
||||
}
|
||||
|
||||
PhyParam_t LoRaPHYAU915::get_phy_params(GetPhyParams_t* getPhy)
|
||||
{
|
||||
PhyParam_t phyParam = { 0 };
|
||||
|
||||
switch (getPhy->Attribute) {
|
||||
case PHY_MIN_RX_DR: {
|
||||
phyParam.Value = AU915_RX_MIN_DATARATE;
|
||||
break;
|
||||
}
|
||||
case PHY_MIN_TX_DR: {
|
||||
phyParam.Value = AU915_TX_MIN_DATARATE;
|
||||
break;
|
||||
}
|
||||
case PHY_DEF_TX_DR: {
|
||||
phyParam.Value = AU915_DEFAULT_DATARATE;
|
||||
break;
|
||||
}
|
||||
case PHY_NEXT_LOWER_TX_DR: {
|
||||
phyParam.Value = GetNextLowerTxDr(getPhy->Datarate,
|
||||
AU915_TX_MIN_DATARATE);
|
||||
break;
|
||||
}
|
||||
case PHY_DEF_TX_POWER: {
|
||||
phyParam.Value = AU915_DEFAULT_TX_POWER;
|
||||
break;
|
||||
}
|
||||
case PHY_MAX_PAYLOAD: {
|
||||
phyParam.Value = MaxPayloadOfDatarateAU915[getPhy->Datarate];
|
||||
break;
|
||||
}
|
||||
case PHY_MAX_PAYLOAD_REPEATER: {
|
||||
phyParam.Value =
|
||||
MaxPayloadOfDatarateRepeaterAU915[getPhy->Datarate];
|
||||
break;
|
||||
}
|
||||
case PHY_DUTY_CYCLE: {
|
||||
phyParam.Value = AU915_DUTY_CYCLE_ENABLED;
|
||||
break;
|
||||
}
|
||||
case PHY_MAX_RX_WINDOW: {
|
||||
phyParam.Value = AU915_MAX_RX_WINDOW;
|
||||
break;
|
||||
}
|
||||
case PHY_RECEIVE_DELAY1: {
|
||||
phyParam.Value = AU915_RECEIVE_DELAY1;
|
||||
break;
|
||||
}
|
||||
case PHY_RECEIVE_DELAY2: {
|
||||
phyParam.Value = AU915_RECEIVE_DELAY2;
|
||||
break;
|
||||
}
|
||||
case PHY_JOIN_ACCEPT_DELAY1: {
|
||||
phyParam.Value = AU915_JOIN_ACCEPT_DELAY1;
|
||||
break;
|
||||
}
|
||||
case PHY_JOIN_ACCEPT_DELAY2: {
|
||||
phyParam.Value = AU915_JOIN_ACCEPT_DELAY2;
|
||||
break;
|
||||
}
|
||||
case PHY_MAX_FCNT_GAP: {
|
||||
phyParam.Value = AU915_MAX_FCNT_GAP;
|
||||
break;
|
||||
}
|
||||
case PHY_ACK_TIMEOUT: {
|
||||
phyParam.Value =
|
||||
( AU915_ACKTIMEOUT
|
||||
+ get_random(-AU915_ACK_TIMEOUT_RND,
|
||||
AU915_ACK_TIMEOUT_RND));
|
||||
break;
|
||||
}
|
||||
case PHY_DEF_DR1_OFFSET: {
|
||||
phyParam.Value = AU915_DEFAULT_RX1_DR_OFFSET;
|
||||
break;
|
||||
}
|
||||
case PHY_DEF_RX2_FREQUENCY: {
|
||||
phyParam.Value = AU915_RX_WND_2_FREQ;
|
||||
break;
|
||||
}
|
||||
case PHY_DEF_RX2_DR: {
|
||||
phyParam.Value = AU915_RX_WND_2_DR;
|
||||
break;
|
||||
}
|
||||
case PHY_CHANNELS_MASK: {
|
||||
phyParam.ChannelsMask = ChannelsMask;
|
||||
break;
|
||||
}
|
||||
case PHY_CHANNELS_DEFAULT_MASK: {
|
||||
phyParam.ChannelsMask = ChannelsDefaultMask;
|
||||
break;
|
||||
}
|
||||
case PHY_MAX_NB_CHANNELS: {
|
||||
phyParam.Value = AU915_MAX_NB_CHANNELS;
|
||||
break;
|
||||
}
|
||||
case PHY_CHANNELS: {
|
||||
phyParam.Channels = Channels;
|
||||
break;
|
||||
}
|
||||
case PHY_DEF_UPLINK_DWELL_TIME:
|
||||
case PHY_DEF_DOWNLINK_DWELL_TIME: {
|
||||
phyParam.Value = 0;
|
||||
break;
|
||||
}
|
||||
case PHY_DEF_MAX_EIRP: {
|
||||
phyParam.fValue = AU915_DEFAULT_MAX_EIRP;
|
||||
break;
|
||||
}
|
||||
case PHY_DEF_ANTENNA_GAIN: {
|
||||
phyParam.fValue = AU915_DEFAULT_ANTENNA_GAIN;
|
||||
break;
|
||||
}
|
||||
case PHY_NB_JOIN_TRIALS:
|
||||
case PHY_DEF_NB_JOIN_TRIALS: {
|
||||
phyParam.Value = 2;
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return phyParam;
|
||||
}
|
||||
|
||||
void LoRaPHYAU915::set_band_tx_done(SetBandTxDoneParams_t* txDone)
|
||||
{
|
||||
set_last_tx_done(txDone->Joined, &Bands[Channels[txDone->Channel].Band],
|
||||
txDone->LastTxDoneTime);
|
||||
}
|
||||
|
||||
void LoRaPHYAU915::load_defaults(InitType_t type)
|
||||
{
|
||||
switch (type) {
|
||||
case INIT_TYPE_INIT: {
|
||||
// Channels
|
||||
// 125 kHz channels
|
||||
for (uint8_t i = 0; i < AU915_MAX_NB_CHANNELS - 8; i++) {
|
||||
Channels[i].Frequency = 915200000 + i * 200000;
|
||||
Channels[i].DrRange.Value = ( DR_5 << 4) | DR_0;
|
||||
Channels[i].Band = 0;
|
||||
}
|
||||
// 500 kHz channels
|
||||
for (uint8_t i = AU915_MAX_NB_CHANNELS - 8;
|
||||
i < AU915_MAX_NB_CHANNELS; i++) {
|
||||
Channels[i].Frequency = 915900000
|
||||
+ (i - ( AU915_MAX_NB_CHANNELS - 8)) * 1600000;
|
||||
Channels[i].DrRange.Value = ( DR_6 << 4) | DR_6;
|
||||
Channels[i].Band = 0;
|
||||
}
|
||||
|
||||
// Initialize channels default mask
|
||||
ChannelsDefaultMask[0] = 0xFFFF;
|
||||
ChannelsDefaultMask[1] = 0xFFFF;
|
||||
ChannelsDefaultMask[2] = 0xFFFF;
|
||||
ChannelsDefaultMask[3] = 0xFFFF;
|
||||
ChannelsDefaultMask[4] = 0x00FF;
|
||||
ChannelsDefaultMask[5] = 0x0000;
|
||||
|
||||
// Copy channels default mask
|
||||
copy_channel_mask(ChannelsMask, ChannelsDefaultMask, 6);
|
||||
|
||||
// Copy into channels mask remaining
|
||||
copy_channel_mask(ChannelsMaskRemaining, ChannelsMask, 6);
|
||||
break;
|
||||
}
|
||||
case INIT_TYPE_RESTORE: {
|
||||
// Copy channels default mask
|
||||
copy_channel_mask(ChannelsMask, ChannelsDefaultMask, 6);
|
||||
|
||||
for (uint8_t i = 0; i < 6; i++) { // Copy-And the channels mask
|
||||
ChannelsMaskRemaining[i] &= ChannelsMask[i];
|
||||
}
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool LoRaPHYAU915::verify(VerifyParams_t* verify, PhyAttribute_t phyAttribute)
|
||||
{
|
||||
switch (phyAttribute) {
|
||||
case PHY_TX_DR:
|
||||
case PHY_DEF_TX_DR: {
|
||||
return val_in_range(verify->DatarateParams.Datarate,
|
||||
AU915_TX_MIN_DATARATE, AU915_TX_MAX_DATARATE);
|
||||
}
|
||||
case PHY_RX_DR: {
|
||||
return val_in_range(verify->DatarateParams.Datarate,
|
||||
AU915_RX_MIN_DATARATE, AU915_RX_MAX_DATARATE);
|
||||
}
|
||||
case PHY_DEF_TX_POWER:
|
||||
case PHY_TX_POWER: {
|
||||
// Remark: switched min and max!
|
||||
return val_in_range(verify->TxPower, AU915_MAX_TX_POWER,
|
||||
AU915_MIN_TX_POWER);
|
||||
}
|
||||
case PHY_DUTY_CYCLE: {
|
||||
return AU915_DUTY_CYCLE_ENABLED;
|
||||
}
|
||||
case PHY_NB_JOIN_TRIALS: {
|
||||
if (verify->NbJoinTrials < 2) {
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void LoRaPHYAU915::apply_cf_list(ApplyCFListParams_t* applyCFList)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
bool LoRaPHYAU915::set_channel_mask(ChanMaskSetParams_t* chanMaskSet)
|
||||
{
|
||||
uint8_t nbChannels = num_active_channels(chanMaskSet->ChannelsMaskIn, 0, 4);
|
||||
|
||||
// Check the number of active channels
|
||||
// According to ACMA regulation, we require at least 20 125KHz channels, if
|
||||
// the node shall utilize 125KHz channels.
|
||||
if ((nbChannels < 20) && (nbChannels > 0)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
switch (chanMaskSet->ChannelsMaskType) {
|
||||
case CHANNELS_MASK: {
|
||||
copy_channel_mask(ChannelsMask, chanMaskSet->ChannelsMaskIn, 6);
|
||||
|
||||
for (uint8_t i = 0; i < 6; i++) { // Copy-And the channels mask
|
||||
ChannelsMaskRemaining[i] &= ChannelsMask[i];
|
||||
}
|
||||
break;
|
||||
}
|
||||
case CHANNELS_DEFAULT_MASK: {
|
||||
copy_channel_mask(ChannelsDefaultMask, chanMaskSet->ChannelsMaskIn,
|
||||
6);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool LoRaPHYAU915::get_next_ADR(AdrNextParams_t* adrNext, int8_t* drOut,
|
||||
int8_t* txPowOut, uint32_t* adrAckCounter)
|
||||
{
|
||||
bool adrAckReq = false;
|
||||
int8_t datarate = adrNext->Datarate;
|
||||
int8_t txPower = adrNext->TxPower;
|
||||
GetPhyParams_t getPhy;
|
||||
PhyParam_t phyParam;
|
||||
|
||||
// Report back the adr ack counter
|
||||
*adrAckCounter = adrNext->AdrAckCounter;
|
||||
|
||||
if (adrNext->AdrEnabled == true) {
|
||||
if (datarate == AU915_TX_MIN_DATARATE) {
|
||||
*adrAckCounter = 0;
|
||||
adrAckReq = false;
|
||||
} else {
|
||||
if (adrNext->AdrAckCounter >= AU915_ADR_ACK_LIMIT) {
|
||||
adrAckReq = true;
|
||||
txPower = AU915_MAX_TX_POWER;
|
||||
} else {
|
||||
adrAckReq = false;
|
||||
}
|
||||
if (adrNext->AdrAckCounter
|
||||
>= ( AU915_ADR_ACK_LIMIT + AU915_ADR_ACK_DELAY)) {
|
||||
if ((adrNext->AdrAckCounter % AU915_ADR_ACK_DELAY) == 1) {
|
||||
// Decrease the datarate
|
||||
getPhy.Attribute = PHY_NEXT_LOWER_TX_DR;
|
||||
getPhy.Datarate = datarate;
|
||||
getPhy.UplinkDwellTime = adrNext->UplinkDwellTime;
|
||||
phyParam = get_phy_params(&getPhy);
|
||||
datarate = phyParam.Value;
|
||||
|
||||
if (datarate == AU915_TX_MIN_DATARATE) {
|
||||
// We must set adrAckReq to false as soon as we reach the lowest datarate
|
||||
adrAckReq = false;
|
||||
if (adrNext->UpdateChanMask == true) {
|
||||
// Re-enable default channels
|
||||
ChannelsMask[0] = 0xFFFF;
|
||||
ChannelsMask[1] = 0xFFFF;
|
||||
ChannelsMask[2] = 0xFFFF;
|
||||
ChannelsMask[3] = 0xFFFF;
|
||||
ChannelsMask[4] = 0x00FF;
|
||||
ChannelsMask[5] = 0x0000;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
*drOut = datarate;
|
||||
*txPowOut = txPower;
|
||||
return adrAckReq;
|
||||
}
|
||||
|
||||
void LoRaPHYAU915::compute_rx_win_params(int8_t datarate, uint8_t minRxSymbols,
|
||||
uint32_t rxError,
|
||||
RxConfigParams_t *rxConfigParams)
|
||||
{
|
||||
double tSymbol = 0.0;
|
||||
|
||||
// Get the datarate, perform a boundary check
|
||||
rxConfigParams->Datarate = MIN(datarate, AU915_RX_MAX_DATARATE);
|
||||
rxConfigParams->Bandwidth = GetBandwidth(rxConfigParams->Datarate);
|
||||
|
||||
tSymbol = compute_symb_timeout_lora(
|
||||
DataratesAU915[rxConfigParams->Datarate],
|
||||
BandwidthsAU915[rxConfigParams->Datarate]);
|
||||
|
||||
get_rx_window_params(tSymbol, minRxSymbols, rxError, RADIO_WAKEUP_TIME,
|
||||
&rxConfigParams->WindowTimeout,
|
||||
&rxConfigParams->WindowOffset);
|
||||
}
|
||||
|
||||
bool LoRaPHYAU915::rx_config(RxConfigParams_t* rxConfig, int8_t* datarate)
|
||||
{
|
||||
int8_t dr = rxConfig->Datarate;
|
||||
uint8_t maxPayload = 0;
|
||||
int8_t phyDr = 0;
|
||||
uint32_t frequency = rxConfig->Frequency;
|
||||
|
||||
if (_radio->get_status() != RF_IDLE) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (rxConfig->Window == 0) {
|
||||
// Apply window 1 frequency
|
||||
frequency = AU915_FIRST_RX1_CHANNEL
|
||||
+ (rxConfig->Channel % 8) * AU915_STEPWIDTH_RX1_CHANNEL;
|
||||
}
|
||||
|
||||
// Read the physical datarate from the datarates table
|
||||
phyDr = DataratesAU915[dr];
|
||||
|
||||
_radio->set_channel(frequency);
|
||||
|
||||
// Radio configuration
|
||||
_radio->set_rx_config(MODEM_LORA, rxConfig->Bandwidth, phyDr, 1, 0, 8,
|
||||
rxConfig->WindowTimeout, false, 0, false, 0, 0, true,
|
||||
rxConfig->RxContinuous);
|
||||
|
||||
if (rxConfig->RepeaterSupport == true) {
|
||||
maxPayload = MaxPayloadOfDatarateRepeaterAU915[dr];
|
||||
} else {
|
||||
maxPayload = MaxPayloadOfDatarateAU915[dr];
|
||||
}
|
||||
_radio->set_max_payload_length(MODEM_LORA,
|
||||
maxPayload + LORA_MAC_FRMPAYLOAD_OVERHEAD);
|
||||
|
||||
*datarate = (uint8_t) dr;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool LoRaPHYAU915::tx_config(TxConfigParams_t* txConfig, int8_t* txPower,
|
||||
TimerTime_t* txTimeOnAir)
|
||||
{
|
||||
int8_t phyDr = DataratesAU915[txConfig->Datarate];
|
||||
int8_t txPowerLimited = LimitTxPower(
|
||||
txConfig->TxPower,
|
||||
Bands[Channels[txConfig->Channel].Band].TxMaxPower,
|
||||
txConfig->Datarate, ChannelsMask);
|
||||
uint32_t bandwidth = GetBandwidth(txConfig->Datarate);
|
||||
int8_t phyTxPower = 0;
|
||||
|
||||
// Calculate physical TX power
|
||||
phyTxPower = compute_tx_power(txPowerLimited, txConfig->MaxEirp,
|
||||
txConfig->AntennaGain);
|
||||
|
||||
// Setup the radio frequency
|
||||
_radio->set_channel(Channels[txConfig->Channel].Frequency);
|
||||
|
||||
_radio->set_tx_config(MODEM_LORA, phyTxPower, 0, bandwidth, phyDr, 1, 8,
|
||||
false, true, 0, 0, false, 3000);
|
||||
|
||||
// Setup maximum payload lenght of the radio driver
|
||||
_radio->set_max_payload_length(MODEM_LORA, txConfig->PktLen);
|
||||
|
||||
*txTimeOnAir = _radio->time_on_air(MODEM_LORA, txConfig->PktLen);
|
||||
*txPower = txPowerLimited;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
uint8_t LoRaPHYAU915::link_ADR_request(LinkAdrReqParams_t* linkAdrReq,
|
||||
int8_t* drOut, int8_t* txPowOut,
|
||||
uint8_t* nbRepOut,
|
||||
uint8_t* nbBytesParsed)
|
||||
{
|
||||
uint8_t status = 0x07;
|
||||
RegionCommonLinkAdrParams_t linkAdrParams;
|
||||
uint8_t nextIndex = 0;
|
||||
uint8_t bytesProcessed = 0;
|
||||
uint16_t channelsMask[6] = { 0, 0, 0, 0, 0, 0 };
|
||||
GetPhyParams_t getPhy;
|
||||
PhyParam_t phyParam;
|
||||
RegionCommonLinkAdrReqVerifyParams_t linkAdrVerifyParams;
|
||||
|
||||
// Initialize local copy of channels mask
|
||||
copy_channel_mask(channelsMask, ChannelsMask, 6);
|
||||
|
||||
while (bytesProcessed < linkAdrReq->PayloadSize) {
|
||||
nextIndex = parse_link_ADR_req(&(linkAdrReq->Payload[bytesProcessed]),
|
||||
&linkAdrParams);
|
||||
|
||||
if (nextIndex == 0)
|
||||
break; // break loop, since no more request has been found
|
||||
|
||||
// Update bytes processed
|
||||
bytesProcessed += nextIndex;
|
||||
|
||||
// Revert status, as we only check the last ADR request for the channel mask KO
|
||||
status = 0x07;
|
||||
|
||||
if (linkAdrParams.ChMaskCtrl == 6) {
|
||||
// Enable all 125 kHz channels
|
||||
channelsMask[0] = 0xFFFF;
|
||||
channelsMask[1] = 0xFFFF;
|
||||
channelsMask[2] = 0xFFFF;
|
||||
channelsMask[3] = 0xFFFF;
|
||||
// Apply chMask to channels 64 to 71
|
||||
channelsMask[4] = linkAdrParams.ChMask;
|
||||
} else if (linkAdrParams.ChMaskCtrl == 7) {
|
||||
// Disable all 125 kHz channels
|
||||
channelsMask[0] = 0x0000;
|
||||
channelsMask[1] = 0x0000;
|
||||
channelsMask[2] = 0x0000;
|
||||
channelsMask[3] = 0x0000;
|
||||
// Apply chMask to channels 64 to 71
|
||||
channelsMask[4] = linkAdrParams.ChMask;
|
||||
} else if (linkAdrParams.ChMaskCtrl == 5) {
|
||||
// RFU
|
||||
status &= 0xFE; // Channel mask KO
|
||||
} else {
|
||||
channelsMask[linkAdrParams.ChMaskCtrl] = linkAdrParams.ChMask;
|
||||
}
|
||||
}
|
||||
|
||||
// FCC 15.247 paragraph F mandates to hop on at least 2 125 kHz channels
|
||||
if ((linkAdrParams.Datarate < DR_6)
|
||||
&& (num_active_channels(channelsMask, 0, 4) < 2)) {
|
||||
status &= 0xFE; // Channel mask KO
|
||||
}
|
||||
|
||||
// Get the minimum possible datarate
|
||||
getPhy.Attribute = PHY_MIN_TX_DR;
|
||||
getPhy.UplinkDwellTime = linkAdrReq->UplinkDwellTime;
|
||||
phyParam = get_phy_params(&getPhy);
|
||||
|
||||
linkAdrVerifyParams.Status = status;
|
||||
linkAdrVerifyParams.AdrEnabled = linkAdrReq->AdrEnabled;
|
||||
linkAdrVerifyParams.Datarate = linkAdrParams.Datarate;
|
||||
linkAdrVerifyParams.TxPower = linkAdrParams.TxPower;
|
||||
linkAdrVerifyParams.NbRep = linkAdrParams.NbRep;
|
||||
linkAdrVerifyParams.CurrentDatarate = linkAdrReq->CurrentDatarate;
|
||||
linkAdrVerifyParams.CurrentTxPower = linkAdrReq->CurrentTxPower;
|
||||
linkAdrVerifyParams.CurrentNbRep = linkAdrReq->CurrentNbRep;
|
||||
linkAdrVerifyParams.NbChannels = AU915_MAX_NB_CHANNELS;
|
||||
linkAdrVerifyParams.ChannelsMask = channelsMask;
|
||||
linkAdrVerifyParams.MinDatarate = (int8_t) phyParam.Value;
|
||||
linkAdrVerifyParams.MaxDatarate = AU915_TX_MAX_DATARATE;
|
||||
linkAdrVerifyParams.Channels = Channels;
|
||||
linkAdrVerifyParams.MinTxPower = AU915_MIN_TX_POWER;
|
||||
linkAdrVerifyParams.MaxTxPower = AU915_MAX_TX_POWER;
|
||||
|
||||
// Verify the parameters and update, if necessary
|
||||
status = verify_link_ADR_req(&linkAdrVerifyParams, &linkAdrParams.Datarate,
|
||||
&linkAdrParams.TxPower, &linkAdrParams.NbRep);
|
||||
|
||||
// Update channelsMask if everything is correct
|
||||
if (status == 0x07) {
|
||||
// Copy Mask
|
||||
copy_channel_mask(ChannelsMask, channelsMask, 6);
|
||||
|
||||
ChannelsMaskRemaining[0] &= ChannelsMask[0];
|
||||
ChannelsMaskRemaining[1] &= ChannelsMask[1];
|
||||
ChannelsMaskRemaining[2] &= ChannelsMask[2];
|
||||
ChannelsMaskRemaining[3] &= ChannelsMask[3];
|
||||
ChannelsMaskRemaining[4] = ChannelsMask[4];
|
||||
ChannelsMaskRemaining[5] = ChannelsMask[5];
|
||||
}
|
||||
|
||||
// Update status variables
|
||||
*drOut = linkAdrParams.Datarate;
|
||||
*txPowOut = linkAdrParams.TxPower;
|
||||
*nbRepOut = linkAdrParams.NbRep;
|
||||
*nbBytesParsed = bytesProcessed;
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
uint8_t LoRaPHYAU915::setup_rx_params(RxParamSetupReqParams_t* rxParamSetupReq)
|
||||
{
|
||||
uint8_t status = 0x07;
|
||||
uint32_t freq = rxParamSetupReq->Frequency;
|
||||
|
||||
// Verify radio frequency
|
||||
if ((_radio->check_rf_frequency(freq) == false)
|
||||
|| (freq < AU915_FIRST_RX1_CHANNEL)
|
||||
|| (freq > AU915_LAST_RX1_CHANNEL)
|
||||
|| (((freq - (uint32_t) AU915_FIRST_RX1_CHANNEL)
|
||||
% (uint32_t) AU915_STEPWIDTH_RX1_CHANNEL) != 0)) {
|
||||
status &= 0xFE; // Channel frequency KO
|
||||
}
|
||||
|
||||
// Verify datarate
|
||||
if (val_in_range(rxParamSetupReq->Datarate, AU915_RX_MIN_DATARATE,
|
||||
AU915_RX_MAX_DATARATE) == 0) {
|
||||
status &= 0xFD; // Datarate KO
|
||||
}
|
||||
if ((rxParamSetupReq->Datarate == DR_7)
|
||||
|| (rxParamSetupReq->Datarate > DR_13)) {
|
||||
status &= 0xFD; // Datarate KO
|
||||
}
|
||||
|
||||
// Verify datarate offset
|
||||
if (val_in_range(rxParamSetupReq->DrOffset, AU915_MIN_RX1_DR_OFFSET,
|
||||
AU915_MAX_RX1_DR_OFFSET) == 0) {
|
||||
status &= 0xFB; // Rx1DrOffset range KO
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
uint8_t LoRaPHYAU915::request_new_channel(NewChannelReqParams_t* newChannelReq)
|
||||
{
|
||||
// Datarate and frequency KO
|
||||
return 0;
|
||||
}
|
||||
|
||||
int8_t LoRaPHYAU915::setup_tx_params(TxParamSetupReqParams_t* txParamSetupReq)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
uint8_t LoRaPHYAU915::dl_channel_request(DlChannelReqParams_t* dlChannelReq)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
int8_t LoRaPHYAU915::get_alternate_DR(AlternateDrParams_t* alternateDr)
|
||||
{
|
||||
int8_t datarate = 0;
|
||||
|
||||
// Re-enable 500 kHz default channels
|
||||
ChannelsMask[4] = 0x00FF;
|
||||
|
||||
if ((alternateDr->NbTrials & 0x01) == 0x01) {
|
||||
datarate = DR_6;
|
||||
} else {
|
||||
datarate = DR_0;
|
||||
}
|
||||
return datarate;
|
||||
}
|
||||
|
||||
void LoRaPHYAU915::calculate_backoff(CalcBackOffParams_t* calcBackOff)
|
||||
{
|
||||
RegionCommonCalcBackOffParams_t calcBackOffParams;
|
||||
|
||||
calcBackOffParams.Channels = Channels;
|
||||
calcBackOffParams.Bands = 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;
|
||||
|
||||
get_DC_backoff(&calcBackOffParams);
|
||||
}
|
||||
|
||||
bool LoRaPHYAU915::set_next_channel(NextChanParams_t* nextChanParams,
|
||||
uint8_t* channel, TimerTime_t* time,
|
||||
TimerTime_t* aggregatedTimeOff)
|
||||
{
|
||||
uint8_t nbEnabledChannels = 0;
|
||||
uint8_t delayTx = 0;
|
||||
uint8_t enabledChannels[AU915_MAX_NB_CHANNELS] = { 0 };
|
||||
TimerTime_t nextTxDelay = 0;
|
||||
|
||||
// Count 125kHz channels
|
||||
if (num_active_channels(ChannelsMaskRemaining, 0, 4) == 0) { // Reactivate default channels
|
||||
copy_channel_mask(ChannelsMaskRemaining, ChannelsMask, 4);
|
||||
}
|
||||
// Check other channels
|
||||
if (nextChanParams->Datarate >= DR_6) {
|
||||
if ((ChannelsMaskRemaining[4] & 0x00FF) == 0) {
|
||||
ChannelsMaskRemaining[4] = ChannelsMask[4];
|
||||
}
|
||||
}
|
||||
|
||||
if (nextChanParams->AggrTimeOff
|
||||
<= TimerGetElapsedTime(nextChanParams->LastAggrTx)) {
|
||||
// Reset Aggregated time off
|
||||
*aggregatedTimeOff = 0;
|
||||
|
||||
// Update bands Time OFF
|
||||
nextTxDelay = update_band_timeoff(nextChanParams->Joined,
|
||||
nextChanParams->DutyCycleEnabled,
|
||||
Bands, AU915_MAX_NB_BANDS);
|
||||
|
||||
// Search how many channels are enabled
|
||||
nbEnabledChannels = CountNbOfEnabledChannels(nextChanParams->Datarate,
|
||||
ChannelsMaskRemaining,
|
||||
Channels, Bands,
|
||||
enabledChannels, &delayTx);
|
||||
} else {
|
||||
delayTx++;
|
||||
nextTxDelay = nextChanParams->AggrTimeOff
|
||||
- TimerGetElapsedTime(nextChanParams->LastAggrTx);
|
||||
}
|
||||
|
||||
if (nbEnabledChannels > 0) {
|
||||
// We found a valid channel
|
||||
*channel = enabledChannels[get_random(0, nbEnabledChannels - 1)];
|
||||
// Disable the channel in the mask
|
||||
disable_channel(ChannelsMaskRemaining, *channel,
|
||||
AU915_MAX_NB_CHANNELS - 8);
|
||||
|
||||
*time = 0;
|
||||
return true;
|
||||
} else {
|
||||
if (delayTx > 0) {
|
||||
// Delay transmission due to AggregatedTimeOff or to a band time off
|
||||
*time = nextTxDelay;
|
||||
return true;
|
||||
}
|
||||
// Datarate not supported by any channel
|
||||
*time = 0;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
LoRaMacStatus_t LoRaPHYAU915::add_channel(ChannelAddParams_t* channelAdd)
|
||||
{
|
||||
return LORAMAC_STATUS_PARAMETER_INVALID;
|
||||
}
|
||||
|
||||
bool LoRaPHYAU915::remove_channel(ChannelRemoveParams_t* channelRemove)
|
||||
{
|
||||
return LORAMAC_STATUS_PARAMETER_INVALID;
|
||||
}
|
||||
|
||||
void LoRaPHYAU915::set_tx_cont_mode(ContinuousWaveParams_t* continuousWave)
|
||||
{
|
||||
int8_t txPowerLimited = LimitTxPower(
|
||||
continuousWave->TxPower,
|
||||
Bands[Channels[continuousWave->Channel].Band].TxMaxPower,
|
||||
continuousWave->Datarate, ChannelsMask);
|
||||
int8_t phyTxPower = 0;
|
||||
uint32_t frequency = Channels[continuousWave->Channel].Frequency;
|
||||
|
||||
// Calculate physical TX power
|
||||
phyTxPower = compute_tx_power(txPowerLimited, continuousWave->MaxEirp,
|
||||
continuousWave->AntennaGain);
|
||||
|
||||
_radio->set_tx_continuous_wave(frequency, phyTxPower,
|
||||
continuousWave->Timeout);
|
||||
}
|
||||
|
||||
uint8_t LoRaPHYAU915::apply_DR_offset(uint8_t downlinkDwellTime, int8_t dr,
|
||||
int8_t drOffset)
|
||||
{
|
||||
int8_t datarate = DatarateOffsetsAU915[dr][drOffset];
|
||||
|
||||
if (datarate < 0) {
|
||||
datarate = DR_0;
|
||||
}
|
||||
return datarate;
|
||||
}
|
|
@ -0,0 +1,373 @@
|
|||
/**
|
||||
* @file LoRaPHYAU915.h
|
||||
*
|
||||
* @brief Implements LoRaPHY for Australian 915 MHz band
|
||||
*
|
||||
* \code
|
||||
* ______ _
|
||||
* / _____) _ | |
|
||||
* ( (____ _____ ____ _| |_ _____ ____| |__
|
||||
* \____ \| ___ | (_ _) ___ |/ ___) _ \
|
||||
* _____) ) ____| | | || |_| ____( (___| | | |
|
||||
* (______/|_____)_|_|_| \__)_____)\____)_| |_|
|
||||
* (C)2013 Semtech
|
||||
* ___ _____ _ ___ _ _____ ___ ___ ___ ___
|
||||
* / __|_ _/_\ / __| |/ / __/ _ \| _ \/ __| __|
|
||||
* \__ \ | |/ _ \ (__| ' <| _| (_) | / (__| _|
|
||||
* |___/ |_/_/ \_\___|_|\_\_| \___/|_|_\\___|___|
|
||||
* embedded.connectivity.solutions===============
|
||||
*
|
||||
* \endcode
|
||||
*
|
||||
*
|
||||
* License: Revised BSD License, see LICENSE.TXT file include in the project
|
||||
*
|
||||
* Maintainer: Miguel Luis ( Semtech ), Gregory Cristian ( Semtech ) and Daniel Jaeckle ( STACKFORCE )
|
||||
*
|
||||
* Copyright (c) 2017, Arm Limited and affiliates.
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef MBED_OS_LORAPHY_AU915_H_
|
||||
|
||||
#define MBED_OS_LORAPHY_AU915_H_
|
||||
|
||||
#include "LoRaPHY.h"
|
||||
#include "netsocket/LoRaRadio.h"
|
||||
|
||||
// Definitions
|
||||
/*!
|
||||
* LoRaMac maximum number of channels
|
||||
*/
|
||||
#define AU915_MAX_NB_CHANNELS 72
|
||||
|
||||
/*!
|
||||
* LoRaMac maximum number of bands
|
||||
*/
|
||||
#define AU915_MAX_NB_BANDS 1
|
||||
|
||||
#define AU915_CHANNELS_MASK_SIZE 6
|
||||
|
||||
|
||||
class LoRaPHYAU915 : public LoRaPHY{
|
||||
|
||||
public:
|
||||
|
||||
LoRaPHYAU915();
|
||||
virtual ~LoRaPHYAU915();
|
||||
|
||||
/*!
|
||||
* \brief The function gets a value of a specific PHY attribute.
|
||||
*
|
||||
* \param [in] getPhy A pointer to the function parameters.
|
||||
*
|
||||
* \retval A structure containing the PHY parameter.
|
||||
*/
|
||||
virtual PhyParam_t get_phy_params(GetPhyParams_t* getPhy );
|
||||
|
||||
/*!
|
||||
* \brief Updates the last TX done parameters of the current channel.
|
||||
*
|
||||
* \param [in] txDone A pointer to the function parameters.
|
||||
*/
|
||||
virtual void set_band_tx_done(SetBandTxDoneParams_t* txDone );
|
||||
|
||||
/*!
|
||||
* \brief Initializes the channels masks and the channels.
|
||||
*
|
||||
* \param [in] type Sets the initialization type.
|
||||
*/
|
||||
virtual void load_defaults(InitType_t type );
|
||||
|
||||
/*!
|
||||
* \brief Verifies a parameter.
|
||||
*
|
||||
* \param [in] verify A pointer to the function parameters.
|
||||
*
|
||||
* \param [in] phyAttribute The attribute to be verified.
|
||||
*
|
||||
* \retval True, if the parameter is valid.
|
||||
*/
|
||||
virtual bool verify(VerifyParams_t* verify, PhyAttribute_t phyAttribute );
|
||||
|
||||
/*!
|
||||
* \brief The function parses the input buffer and sets up the channels of the
|
||||
* CF list.
|
||||
*
|
||||
* \param [in] applyCFList A pointer to the function parameters.
|
||||
*/
|
||||
virtual void apply_cf_list(ApplyCFListParams_t* applyCFList );
|
||||
|
||||
/*!
|
||||
* \brief Sets a channels mask.
|
||||
*
|
||||
* \param [in] chanMaskSet A pointer to the function parameters.
|
||||
*
|
||||
* \retval True, if the channels mask could be set.
|
||||
*/
|
||||
virtual bool set_channel_mask(ChanMaskSetParams_t* chanMaskSet );
|
||||
|
||||
/*!
|
||||
* \brief Calculates the next datarate to set, when ADR is on or off.
|
||||
*
|
||||
* \param [in] adrNext A pointer to the function parameters.
|
||||
*
|
||||
* \param [out] drOut The calculated datarate for the next TX.
|
||||
*
|
||||
* \param [out] txPowOut The TX power for the next TX.
|
||||
*
|
||||
* \param [out] adrAckCounter The calculated ADR acknowledgement counter.
|
||||
*
|
||||
* \retval True, if an ADR request should be performed.
|
||||
*/
|
||||
virtual bool get_next_ADR(AdrNextParams_t* adrNext, int8_t* drOut,
|
||||
int8_t* txPowOut, uint32_t* adrAckCounter );
|
||||
|
||||
/*!
|
||||
* \brief Configuration of the RX windows.
|
||||
*
|
||||
* \param [in] rxConfig A pointer to the function parameters.
|
||||
*
|
||||
* \param [out] datarate The datarate index set.
|
||||
*
|
||||
* \retval True, if the configuration was applied successfully.
|
||||
*/
|
||||
virtual bool rx_config(RxConfigParams_t* rxConfig, int8_t* datarate );
|
||||
|
||||
/*
|
||||
* RX window precise timing
|
||||
*
|
||||
* For more details please consult the following document, chapter 3.1.2.
|
||||
* http://www.semtech.com/images/datasheet/SX1272_settings_for_LoRaWAN_v2.0.pdf
|
||||
* or
|
||||
* http://www.semtech.com/images/datasheet/SX1276_settings_for_LoRaWAN_v2.0.pdf
|
||||
*
|
||||
* Downlink start: T = Tx + 1s (+/- 20 us)
|
||||
* |
|
||||
* TRxEarly | TRxLate
|
||||
* | | |
|
||||
* | | +---+---+---+---+---+---+---+---+
|
||||
* | | | Latest Rx window |
|
||||
* | | +---+---+---+---+---+---+---+---+
|
||||
* | | |
|
||||
* +---+---+---+---+---+---+---+---+
|
||||
* | Earliest Rx window |
|
||||
* +---+---+---+---+---+---+---+---+
|
||||
* |
|
||||
* +---+---+---+---+---+---+---+---+
|
||||
*Downlink preamble 8 symbols | | | | | | | | |
|
||||
* +---+---+---+---+---+---+---+---+
|
||||
*
|
||||
* Worst case Rx window timings
|
||||
*
|
||||
* TRxLate = DEFAULT_MIN_RX_SYMBOLS * tSymbol - RADIO_WAKEUP_TIME
|
||||
* TRxEarly = 8 - DEFAULT_MIN_RX_SYMBOLS * tSymbol - RxWindowTimeout - RADIO_WAKEUP_TIME
|
||||
*
|
||||
* TRxLate - TRxEarly = 2 * DEFAULT_SYSTEM_MAX_RX_ERROR
|
||||
*
|
||||
* RxOffset = ( TRxLate + TRxEarly ) / 2
|
||||
*
|
||||
* RxWindowTimeout = ( 2 * DEFAULT_MIN_RX_SYMBOLS - 8 ) * tSymbol + 2 * DEFAULT_SYSTEM_MAX_RX_ERROR
|
||||
* RxOffset = 4 * tSymbol - RxWindowTimeout / 2 - RADIO_WAKE_UP_TIME
|
||||
*
|
||||
* The minimum value of RxWindowTimeout must be 5 symbols which implies that the system always tolerates at least an error of 1.5 * tSymbol
|
||||
*/
|
||||
/*!
|
||||
* Computes the Rx window timeout and offset.
|
||||
*
|
||||
* \param [in] datarate The RX window datarate index to be used.
|
||||
*
|
||||
* \param [in] minRxSymbols The minimum number of symbols required to detect an RX frame.
|
||||
*
|
||||
* \param [in] rxError The system maximum timing error of the receiver in milliseconds.
|
||||
* The receiver will turn on in a [-rxError : +rxError] ms
|
||||
* interval around RxOffset.
|
||||
*
|
||||
* \param [out] rxConfigParams The updated WindowTimeout and WindowOffset fields.
|
||||
*/
|
||||
virtual void compute_rx_win_params(int8_t datarate,
|
||||
uint8_t minRxSymbols,
|
||||
uint32_t rxError,
|
||||
RxConfigParams_t *rxConfigParams);
|
||||
|
||||
/*!
|
||||
* \brief TX configuration.
|
||||
*
|
||||
* \param [in] txConfig A pointer to the function parameters.
|
||||
*
|
||||
* \param [out] txPower The TX power index set.
|
||||
*
|
||||
* \param [out] txTimeOnAir The time-on-air of the frame.
|
||||
*
|
||||
* \retval True, if the configuration was applied successfully.
|
||||
*/
|
||||
virtual bool tx_config(TxConfigParams_t* txConfig, int8_t* txPower,
|
||||
TimerTime_t* txTimeOnAir );
|
||||
|
||||
/*!
|
||||
* \brief The function processes a Link ADR Request.
|
||||
*
|
||||
* \param [in] linkAdrReq A pointer to the function parameters.
|
||||
*
|
||||
* \param [out] drOut The datarate applied.
|
||||
*
|
||||
* \param [out] txPowOut The TX power applied.
|
||||
*
|
||||
* \param [out] nbRepOut The number of repetitions to apply.
|
||||
*
|
||||
* \param [out] nbBytesParsed The number bytes parsed.
|
||||
*
|
||||
* \retval The status of the operation, according to the LoRaMAC specification.
|
||||
*/
|
||||
virtual uint8_t link_ADR_request(LinkAdrReqParams_t* linkAdrReq,
|
||||
int8_t* drOut, int8_t* txPowOut,
|
||||
uint8_t* nbRepOut,
|
||||
uint8_t* nbBytesParsed );
|
||||
|
||||
/*!
|
||||
* \brief The function processes a RX parameter setup request.
|
||||
*
|
||||
* \param [in] rxParamSetupReq A pointer to the function parameters.
|
||||
*
|
||||
* \retval The status of the operation, according to the LoRaMAC specification.
|
||||
*/
|
||||
virtual uint8_t setup_rx_params(RxParamSetupReqParams_t* rxParamSetupReq );
|
||||
|
||||
/*!
|
||||
* \brief The function processes a new channel request.
|
||||
*
|
||||
* \param [in] newChannelReq A pointer to the function parameters.
|
||||
*
|
||||
* \retval The status of the operation, according to the LoRaMAC specification.
|
||||
*/
|
||||
virtual uint8_t request_new_channel(NewChannelReqParams_t* newChannelReq );
|
||||
|
||||
/*!
|
||||
* \brief The function processes a TX ParamSetup request.
|
||||
*
|
||||
* \param [in] txParamSetupReq A pointer to the function parameters.
|
||||
*
|
||||
* \retval The status of the operation, according to the LoRaMAC specification.
|
||||
* Returns -1, if the functionality is not implemented. In this case, the end node
|
||||
* shall ignore the command.
|
||||
*/
|
||||
virtual int8_t setup_tx_params(TxParamSetupReqParams_t* txParamSetupReq );
|
||||
|
||||
/*!
|
||||
* \brief The function processes a DlChannel request.
|
||||
*
|
||||
* \param [in] dlChannelReq A pointer to the function parameters.
|
||||
*
|
||||
* \retval The status of the operation, according to the LoRaMAC specification.
|
||||
*/
|
||||
virtual uint8_t dl_channel_request(DlChannelReqParams_t* dlChannelReq );
|
||||
|
||||
/*!
|
||||
* \brief Alternates the datarate of the channel for the join request.
|
||||
*
|
||||
* \param [in] alternateDr A pointer to the function parameters.
|
||||
*
|
||||
* \retval The datarate to apply.
|
||||
*/
|
||||
virtual int8_t get_alternate_DR(AlternateDrParams_t* alternateDr );
|
||||
|
||||
/*!
|
||||
* \brief Calculates the back-off time.
|
||||
*
|
||||
* \param [in] calcBackOff A pointer to the function parameters.
|
||||
*/
|
||||
virtual void calculate_backoff(CalcBackOffParams_t* calcBackOff );
|
||||
|
||||
/*!
|
||||
* \brief Searches and sets the next random available channel.
|
||||
*
|
||||
* \param [in] nextChanParams The parameters for the next channel.
|
||||
*
|
||||
* \param [out] channel The next channel to use for TX.
|
||||
*
|
||||
* \param [out] time The time to wait for the next transmission according to the duty
|
||||
* cycle.
|
||||
*
|
||||
* \param [out] aggregatedTimeOff Updates the aggregated time off.
|
||||
*
|
||||
* \retval The function status [1: OK, 0: Unable to find a channel on the current datarate].
|
||||
*/
|
||||
virtual bool set_next_channel(NextChanParams_t* nextChanParams,
|
||||
uint8_t* channel, TimerTime_t* time,
|
||||
TimerTime_t* aggregatedTimeOff );
|
||||
|
||||
/*!
|
||||
* \brief Adds a channel.
|
||||
*
|
||||
* \param [in] channelAdd A pointer to the function parameters.
|
||||
*
|
||||
* \retval The status of the operation.
|
||||
*/
|
||||
virtual LoRaMacStatus_t add_channel(ChannelAddParams_t* channelAdd );
|
||||
|
||||
/*!
|
||||
* \brief Removes a channel.
|
||||
*
|
||||
* \param [in] channelRemove A pointer to the function parameters.
|
||||
*
|
||||
* \retval True, if the channel was removed successfully.
|
||||
*/
|
||||
virtual bool remove_channel(ChannelRemoveParams_t* channelRemove );
|
||||
|
||||
/*!
|
||||
* \brief Sets the radio into continuous wave mode.
|
||||
*
|
||||
* \param [in] continuousWave A pointer to the function parameters.
|
||||
*/
|
||||
virtual void set_tx_cont_mode(ContinuousWaveParams_t* continuousWave );
|
||||
|
||||
/*!
|
||||
* \brief Computes a new datarate according to the given offset.
|
||||
*
|
||||
* \param [in] downlinkDwellTime The downlink dwell time configuration. 0: No limit, 1: 400ms
|
||||
*
|
||||
* \param [in] dr The current datarate.
|
||||
*
|
||||
* \param [in] drOffset The offset to be applied.
|
||||
*
|
||||
* \retval newDr The computed datarate.
|
||||
*/
|
||||
virtual uint8_t apply_DR_offset(uint8_t downlinkDwellTime, int8_t dr, int8_t drOffset );
|
||||
|
||||
private:
|
||||
uint8_t CountNbOfEnabledChannels(uint8_t datarate,
|
||||
uint16_t* channelsMask,
|
||||
ChannelParams_t* channels,
|
||||
Band_t* bands, uint8_t* enabledChannels,
|
||||
uint8_t* delayTx);
|
||||
|
||||
|
||||
// Global attributes
|
||||
/*!
|
||||
* LoRaMAC channels
|
||||
*/
|
||||
ChannelParams_t Channels[AU915_MAX_NB_CHANNELS];
|
||||
|
||||
/*!
|
||||
* LoRaMac bands
|
||||
*/
|
||||
Band_t Bands[AU915_MAX_NB_BANDS];
|
||||
|
||||
/*!
|
||||
* LoRaMac channels mask
|
||||
*/
|
||||
uint16_t ChannelsMask[AU915_CHANNELS_MASK_SIZE];
|
||||
|
||||
/*!
|
||||
* LoRaMac channels remaining
|
||||
*/
|
||||
uint16_t ChannelsMaskRemaining[AU915_CHANNELS_MASK_SIZE];
|
||||
|
||||
/*!
|
||||
* LoRaMac channels default mask
|
||||
*/
|
||||
uint16_t ChannelsDefaultMask[AU915_CHANNELS_MASK_SIZE];
|
||||
};
|
||||
|
||||
#endif /* MBED_OS_LORAPHY_AU915_H_ */
|
|
@ -0,0 +1,979 @@
|
|||
/**
|
||||
* @file LoRaPHYCN470.cpp
|
||||
*
|
||||
* @brief Implements LoRaPHY for Chinese 470 MHz band
|
||||
*
|
||||
* \code
|
||||
* ______ _
|
||||
* / _____) _ | |
|
||||
* ( (____ _____ ____ _| |_ _____ ____| |__
|
||||
* \____ \| ___ | (_ _) ___ |/ ___) _ \
|
||||
* _____) ) ____| | | || |_| ____( (___| | | |
|
||||
* (______/|_____)_|_|_| \__)_____)\____)_| |_|
|
||||
* (C)2013 Semtech
|
||||
* ___ _____ _ ___ _ _____ ___ ___ ___ ___
|
||||
* / __|_ _/_\ / __| |/ / __/ _ \| _ \/ __| __|
|
||||
* \__ \ | |/ _ \ (__| ' <| _| (_) | / (__| _|
|
||||
* |___/ |_/_/ \_\___|_|\_\_| \___/|_|_\\___|___|
|
||||
* embedded.connectivity.solutions===============
|
||||
*
|
||||
* \endcode
|
||||
*
|
||||
*
|
||||
* License: Revised BSD License, see LICENSE.TXT file include in the project
|
||||
*
|
||||
* Maintainer: Miguel Luis ( Semtech ), Gregory Cristian ( Semtech ) and Daniel Jaeckle ( STACKFORCE )
|
||||
*
|
||||
* Copyright (c) 2017, Arm Limited and affiliates.
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*
|
||||
*/
|
||||
|
||||
#include "LoRaPHYCN470.h"
|
||||
|
||||
#include "lora_phy_ds.h"
|
||||
#include "LoRaRadio.h"
|
||||
|
||||
/*!
|
||||
* Minimal datarate that can be used by the node
|
||||
*/
|
||||
#define CN470_TX_MIN_DATARATE DR_0
|
||||
|
||||
/*!
|
||||
* Maximal datarate that can be used by the node
|
||||
*/
|
||||
#define CN470_TX_MAX_DATARATE DR_5
|
||||
|
||||
/*!
|
||||
* Minimal datarate that can be used by the node
|
||||
*/
|
||||
#define CN470_RX_MIN_DATARATE DR_0
|
||||
|
||||
/*!
|
||||
* Maximal datarate that can be used by the node
|
||||
*/
|
||||
#define CN470_RX_MAX_DATARATE DR_5
|
||||
|
||||
/*!
|
||||
* Default datarate used by the node
|
||||
*/
|
||||
#define CN470_DEFAULT_DATARATE DR_0
|
||||
|
||||
/*!
|
||||
* Minimal Rx1 receive datarate offset
|
||||
*/
|
||||
#define CN470_MIN_RX1_DR_OFFSET 0
|
||||
|
||||
/*!
|
||||
* Maximal Rx1 receive datarate offset
|
||||
*/
|
||||
#define CN470_MAX_RX1_DR_OFFSET 3
|
||||
|
||||
/*!
|
||||
* Default Rx1 receive datarate offset
|
||||
*/
|
||||
#define CN470_DEFAULT_RX1_DR_OFFSET 0
|
||||
|
||||
/*!
|
||||
* Minimal Tx output power that can be used by the node
|
||||
*/
|
||||
#define CN470_MIN_TX_POWER TX_POWER_7
|
||||
|
||||
/*!
|
||||
* Maximal Tx output power that can be used by the node
|
||||
*/
|
||||
#define CN470_MAX_TX_POWER TX_POWER_0
|
||||
|
||||
/*!
|
||||
* Default Tx output power used by the node
|
||||
*/
|
||||
#define CN470_DEFAULT_TX_POWER TX_POWER_0
|
||||
|
||||
/*!
|
||||
* Default Max EIRP
|
||||
*/
|
||||
#define CN470_DEFAULT_MAX_EIRP 19.15f
|
||||
|
||||
/*!
|
||||
* Default antenna gain
|
||||
*/
|
||||
#define CN470_DEFAULT_ANTENNA_GAIN 2.15f
|
||||
|
||||
/*!
|
||||
* ADR Ack limit
|
||||
*/
|
||||
#define CN470_ADR_ACK_LIMIT 64
|
||||
|
||||
/*!
|
||||
* ADR Ack delay
|
||||
*/
|
||||
#define CN470_ADR_ACK_DELAY 32
|
||||
|
||||
/*!
|
||||
* Enabled or disabled the duty cycle
|
||||
*/
|
||||
#define CN470_DUTY_CYCLE_ENABLED 0
|
||||
|
||||
/*!
|
||||
* Maximum RX window duration
|
||||
*/
|
||||
#define CN470_MAX_RX_WINDOW 3000
|
||||
|
||||
/*!
|
||||
* Receive delay 1
|
||||
*/
|
||||
#define CN470_RECEIVE_DELAY1 1000
|
||||
|
||||
/*!
|
||||
* Receive delay 2
|
||||
*/
|
||||
#define CN470_RECEIVE_DELAY2 2000
|
||||
|
||||
/*!
|
||||
* Join accept delay 1
|
||||
*/
|
||||
#define CN470_JOIN_ACCEPT_DELAY1 5000
|
||||
|
||||
/*!
|
||||
* Join accept delay 2
|
||||
*/
|
||||
#define CN470_JOIN_ACCEPT_DELAY2 6000
|
||||
|
||||
/*!
|
||||
* Maximum frame counter gap
|
||||
*/
|
||||
#define CN470_MAX_FCNT_GAP 16384
|
||||
|
||||
/*!
|
||||
* Ack timeout
|
||||
*/
|
||||
#define CN470_ACKTIMEOUT 2000
|
||||
|
||||
/*!
|
||||
* Random ack timeout limits
|
||||
*/
|
||||
#define CN470_ACK_TIMEOUT_RND 1000
|
||||
|
||||
/*!
|
||||
* Second reception window channel frequency definition.
|
||||
*/
|
||||
#define CN470_RX_WND_2_FREQ 505300000
|
||||
|
||||
/*!
|
||||
* Second reception window channel datarate definition.
|
||||
*/
|
||||
#define CN470_RX_WND_2_DR DR_0
|
||||
|
||||
/*!
|
||||
* Band 0 definition
|
||||
* { DutyCycle, TxMaxPower, LastTxDoneTime, TimeOff }
|
||||
*/
|
||||
#define CN470_BAND0 { 1, CN470_MAX_TX_POWER, 0, 0 } // 100.0 %
|
||||
|
||||
/*!
|
||||
* Defines the first channel for RX window 1 for CN470 band
|
||||
*/
|
||||
#define CN470_FIRST_RX1_CHANNEL ( (uint32_t) 500300000 )
|
||||
|
||||
/*!
|
||||
* Defines the last channel for RX window 1 for CN470 band
|
||||
*/
|
||||
#define CN470_LAST_RX1_CHANNEL ( (uint32_t) 509700000 )
|
||||
|
||||
/*!
|
||||
* Defines the step width of the channels for RX window 1
|
||||
*/
|
||||
#define CN470_STEPWIDTH_RX1_CHANNEL ( (uint32_t) 200000 )
|
||||
|
||||
/*!
|
||||
* Data rates table definition
|
||||
*/
|
||||
static const uint8_t DataratesCN470[] = { 12, 11, 10, 9, 8, 7 };
|
||||
|
||||
/*!
|
||||
* Bandwidths table definition in Hz
|
||||
*/
|
||||
static const uint32_t BandwidthsCN470[] = { 125000, 125000, 125000, 125000, 125000, 125000 };
|
||||
|
||||
/*!
|
||||
* Maximum payload with respect to the datarate index. Cannot operate with repeater.
|
||||
*/
|
||||
static const uint8_t MaxPayloadOfDatarateCN470[] = { 51, 51, 51, 115, 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 functions
|
||||
static int8_t GetNextLowerTxDr( int8_t dr, int8_t minDr )
|
||||
{
|
||||
uint8_t nextLowerDr = 0;
|
||||
|
||||
if( dr == minDr )
|
||||
{
|
||||
nextLowerDr = minDr;
|
||||
}
|
||||
else
|
||||
{
|
||||
nextLowerDr = dr - 1;
|
||||
}
|
||||
return nextLowerDr;
|
||||
}
|
||||
|
||||
static uint32_t GetBandwidth( uint32_t drIndex )
|
||||
{
|
||||
switch( BandwidthsCN470[drIndex] )
|
||||
{
|
||||
default:
|
||||
case 125000:
|
||||
return 0;
|
||||
case 250000:
|
||||
return 1;
|
||||
case 500000:
|
||||
return 2;
|
||||
}
|
||||
}
|
||||
|
||||
static int8_t LimitTxPower( int8_t txPower, int8_t maxBandTxPower, int8_t datarate, uint16_t* channelsMask )
|
||||
{
|
||||
int8_t txPowerResult = txPower;
|
||||
|
||||
// Limit tx power to the band max
|
||||
txPowerResult = MAX( txPower, maxBandTxPower );
|
||||
|
||||
return txPowerResult;
|
||||
}
|
||||
|
||||
uint8_t LoRaPHYCN470::CountNbOfEnabledChannels( uint8_t datarate, uint16_t* channelsMask, ChannelParams_t* channels, Band_t* bands, uint8_t* enabledChannels, uint8_t* delayTx )
|
||||
{
|
||||
uint8_t nbEnabledChannels = 0;
|
||||
uint8_t delayTransmission = 0;
|
||||
|
||||
for( uint8_t i = 0, k = 0; i < CN470_MAX_NB_CHANNELS; i += 16, k++ )
|
||||
{
|
||||
for( uint8_t j = 0; j < 16; j++ )
|
||||
{
|
||||
if( ( channelsMask[k] & ( 1 << j ) ) != 0 )
|
||||
{
|
||||
if( channels[i + j].Frequency == 0 )
|
||||
{ // Check if the channel is enabled
|
||||
continue;
|
||||
}
|
||||
if( val_in_range( datarate, channels[i + j].DrRange.Fields.Min,
|
||||
channels[i + j].DrRange.Fields.Max ) == 0 )
|
||||
{ // 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;
|
||||
}
|
||||
|
||||
LoRaPHYCN470::LoRaPHYCN470()
|
||||
{
|
||||
const Band_t band0 = CN470_BAND0;
|
||||
Bands[0] = band0;
|
||||
}
|
||||
|
||||
LoRaPHYCN470::~LoRaPHYCN470()
|
||||
{
|
||||
}
|
||||
|
||||
PhyParam_t LoRaPHYCN470::get_phy_params(GetPhyParams_t* getPhy)
|
||||
{
|
||||
PhyParam_t phyParam = { 0 };
|
||||
|
||||
switch( getPhy->Attribute )
|
||||
{
|
||||
case PHY_MIN_RX_DR:
|
||||
{
|
||||
phyParam.Value = CN470_RX_MIN_DATARATE;
|
||||
break;
|
||||
}
|
||||
case PHY_MIN_TX_DR:
|
||||
{
|
||||
phyParam.Value = CN470_TX_MIN_DATARATE;
|
||||
break;
|
||||
}
|
||||
case PHY_DEF_TX_DR:
|
||||
{
|
||||
phyParam.Value = CN470_DEFAULT_DATARATE;
|
||||
break;
|
||||
}
|
||||
case PHY_NEXT_LOWER_TX_DR:
|
||||
{
|
||||
phyParam.Value = GetNextLowerTxDr( getPhy->Datarate, CN470_TX_MIN_DATARATE );
|
||||
break;
|
||||
}
|
||||
case PHY_DEF_TX_POWER:
|
||||
{
|
||||
phyParam.Value = CN470_DEFAULT_TX_POWER;
|
||||
break;
|
||||
}
|
||||
case PHY_MAX_PAYLOAD:
|
||||
{
|
||||
phyParam.Value = MaxPayloadOfDatarateCN470[getPhy->Datarate];
|
||||
break;
|
||||
}
|
||||
case PHY_MAX_PAYLOAD_REPEATER:
|
||||
{
|
||||
phyParam.Value = MaxPayloadOfDatarateRepeaterCN470[getPhy->Datarate];
|
||||
break;
|
||||
}
|
||||
case PHY_DUTY_CYCLE:
|
||||
{
|
||||
phyParam.Value = CN470_DUTY_CYCLE_ENABLED;
|
||||
break;
|
||||
}
|
||||
case PHY_MAX_RX_WINDOW:
|
||||
{
|
||||
phyParam.Value = CN470_MAX_RX_WINDOW;
|
||||
break;
|
||||
}
|
||||
case PHY_RECEIVE_DELAY1:
|
||||
{
|
||||
phyParam.Value = CN470_RECEIVE_DELAY1;
|
||||
break;
|
||||
}
|
||||
case PHY_RECEIVE_DELAY2:
|
||||
{
|
||||
phyParam.Value = CN470_RECEIVE_DELAY2;
|
||||
break;
|
||||
}
|
||||
case PHY_JOIN_ACCEPT_DELAY1:
|
||||
{
|
||||
phyParam.Value = CN470_JOIN_ACCEPT_DELAY1;
|
||||
break;
|
||||
}
|
||||
case PHY_JOIN_ACCEPT_DELAY2:
|
||||
{
|
||||
phyParam.Value = CN470_JOIN_ACCEPT_DELAY2;
|
||||
break;
|
||||
}
|
||||
case PHY_MAX_FCNT_GAP:
|
||||
{
|
||||
phyParam.Value = CN470_MAX_FCNT_GAP;
|
||||
break;
|
||||
}
|
||||
case PHY_ACK_TIMEOUT:
|
||||
{
|
||||
phyParam.Value = ( CN470_ACKTIMEOUT + get_random( -CN470_ACK_TIMEOUT_RND, CN470_ACK_TIMEOUT_RND ) );
|
||||
break;
|
||||
}
|
||||
case PHY_DEF_DR1_OFFSET:
|
||||
{
|
||||
phyParam.Value = CN470_DEFAULT_RX1_DR_OFFSET;
|
||||
break;
|
||||
}
|
||||
case PHY_DEF_RX2_FREQUENCY:
|
||||
{
|
||||
phyParam.Value = CN470_RX_WND_2_FREQ;
|
||||
break;
|
||||
}
|
||||
case PHY_DEF_RX2_DR:
|
||||
{
|
||||
phyParam.Value = CN470_RX_WND_2_DR;
|
||||
break;
|
||||
}
|
||||
case PHY_CHANNELS_MASK:
|
||||
{
|
||||
phyParam.ChannelsMask = ChannelsMask;
|
||||
break;
|
||||
}
|
||||
case PHY_CHANNELS_DEFAULT_MASK:
|
||||
{
|
||||
phyParam.ChannelsMask = ChannelsDefaultMask;
|
||||
break;
|
||||
}
|
||||
case PHY_MAX_NB_CHANNELS:
|
||||
{
|
||||
phyParam.Value = CN470_MAX_NB_CHANNELS;
|
||||
break;
|
||||
}
|
||||
case PHY_CHANNELS:
|
||||
{
|
||||
phyParam.Channels = Channels;
|
||||
break;
|
||||
}
|
||||
case PHY_DEF_UPLINK_DWELL_TIME:
|
||||
case PHY_DEF_DOWNLINK_DWELL_TIME:
|
||||
{
|
||||
phyParam.Value = 0;
|
||||
break;
|
||||
}
|
||||
case PHY_DEF_MAX_EIRP:
|
||||
{
|
||||
phyParam.fValue = CN470_DEFAULT_MAX_EIRP;
|
||||
break;
|
||||
}
|
||||
case PHY_DEF_ANTENNA_GAIN:
|
||||
{
|
||||
phyParam.fValue = CN470_DEFAULT_ANTENNA_GAIN;
|
||||
break;
|
||||
}
|
||||
case PHY_NB_JOIN_TRIALS:
|
||||
case PHY_DEF_NB_JOIN_TRIALS:
|
||||
{
|
||||
phyParam.Value = 48;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return phyParam;
|
||||
}
|
||||
|
||||
void LoRaPHYCN470::set_band_tx_done(SetBandTxDoneParams_t* txDone)
|
||||
{
|
||||
set_last_tx_done( txDone->Joined, &Bands[Channels[txDone->Channel].Band], txDone->LastTxDoneTime );
|
||||
}
|
||||
|
||||
void LoRaPHYCN470::load_defaults(InitType_t type)
|
||||
{
|
||||
switch( type )
|
||||
{
|
||||
case INIT_TYPE_INIT:
|
||||
{
|
||||
// Channels
|
||||
// 125 kHz channels
|
||||
for( uint8_t i = 0; i < CN470_MAX_NB_CHANNELS; i++ )
|
||||
{
|
||||
Channels[i].Frequency = 470300000 + i * 200000;
|
||||
Channels[i].DrRange.Value = ( DR_5 << 4 ) | DR_0;
|
||||
Channels[i].Band = 0;
|
||||
}
|
||||
|
||||
// Initialize the channels default mask
|
||||
ChannelsDefaultMask[0] = 0xFFFF;
|
||||
ChannelsDefaultMask[1] = 0xFFFF;
|
||||
ChannelsDefaultMask[2] = 0xFFFF;
|
||||
ChannelsDefaultMask[3] = 0xFFFF;
|
||||
ChannelsDefaultMask[4] = 0xFFFF;
|
||||
ChannelsDefaultMask[5] = 0xFFFF;
|
||||
|
||||
// Update the channels mask
|
||||
copy_channel_mask( ChannelsMask, ChannelsDefaultMask, 6 );
|
||||
break;
|
||||
}
|
||||
case INIT_TYPE_RESTORE:
|
||||
{
|
||||
// Restore channels default mask
|
||||
copy_channel_mask( ChannelsMask, ChannelsDefaultMask, 6 );
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool LoRaPHYCN470::verify( VerifyParams_t* verify, PhyAttribute_t phyAttribute )
|
||||
{
|
||||
switch( phyAttribute )
|
||||
{
|
||||
case PHY_TX_DR:
|
||||
case PHY_DEF_TX_DR:
|
||||
{
|
||||
return val_in_range( verify->DatarateParams.Datarate, CN470_TX_MIN_DATARATE, CN470_TX_MAX_DATARATE );
|
||||
}
|
||||
case PHY_RX_DR:
|
||||
{
|
||||
return val_in_range( verify->DatarateParams.Datarate, CN470_RX_MIN_DATARATE, CN470_RX_MAX_DATARATE );
|
||||
}
|
||||
case PHY_DEF_TX_POWER:
|
||||
case PHY_TX_POWER:
|
||||
{
|
||||
// Remark: switched min and max!
|
||||
return val_in_range( verify->TxPower, CN470_MAX_TX_POWER, CN470_MIN_TX_POWER );
|
||||
}
|
||||
case PHY_DUTY_CYCLE:
|
||||
{
|
||||
return CN470_DUTY_CYCLE_ENABLED;
|
||||
}
|
||||
case PHY_NB_JOIN_TRIALS:
|
||||
{
|
||||
if( verify->NbJoinTrials < 48 )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void LoRaPHYCN470::apply_cf_list(ApplyCFListParams_t* applyCFList)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
bool LoRaPHYCN470::set_channel_mask( ChanMaskSetParams_t* chanMaskSet )
|
||||
{
|
||||
switch( chanMaskSet->ChannelsMaskType )
|
||||
{
|
||||
case CHANNELS_MASK:
|
||||
{
|
||||
copy_channel_mask( ChannelsMask, chanMaskSet->ChannelsMaskIn, 6 );
|
||||
break;
|
||||
}
|
||||
case CHANNELS_DEFAULT_MASK:
|
||||
{
|
||||
copy_channel_mask( ChannelsDefaultMask, chanMaskSet->ChannelsMaskIn, 6 );
|
||||
break;
|
||||
}
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool LoRaPHYCN470::get_next_ADR(AdrNextParams_t* adrNext, int8_t* drOut,
|
||||
int8_t* txPowOut, uint32_t* adrAckCounter)
|
||||
{
|
||||
bool adrAckReq = false;
|
||||
int8_t datarate = adrNext->Datarate;
|
||||
int8_t txPower = adrNext->TxPower;
|
||||
GetPhyParams_t getPhy;
|
||||
PhyParam_t phyParam;
|
||||
|
||||
// Report back the adr ack counter
|
||||
*adrAckCounter = adrNext->AdrAckCounter;
|
||||
|
||||
if( adrNext->AdrEnabled == true )
|
||||
{
|
||||
if( datarate == CN470_TX_MIN_DATARATE )
|
||||
{
|
||||
*adrAckCounter = 0;
|
||||
adrAckReq = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
if( adrNext->AdrAckCounter >= CN470_ADR_ACK_LIMIT )
|
||||
{
|
||||
adrAckReq = true;
|
||||
txPower = CN470_MAX_TX_POWER;
|
||||
}
|
||||
else
|
||||
{
|
||||
adrAckReq = false;
|
||||
}
|
||||
if( adrNext->AdrAckCounter >= ( CN470_ADR_ACK_LIMIT + CN470_ADR_ACK_DELAY ) )
|
||||
{
|
||||
if( ( adrNext->AdrAckCounter % CN470_ADR_ACK_DELAY ) == 1 )
|
||||
{
|
||||
// Decrease the datarate
|
||||
getPhy.Attribute = PHY_NEXT_LOWER_TX_DR;
|
||||
getPhy.Datarate = datarate;
|
||||
getPhy.UplinkDwellTime = adrNext->UplinkDwellTime;
|
||||
phyParam = get_phy_params(&getPhy);
|
||||
datarate = phyParam.Value;
|
||||
|
||||
if( datarate == CN470_TX_MIN_DATARATE )
|
||||
{
|
||||
// We must set adrAckReq to false as soon as we reach the lowest datarate
|
||||
adrAckReq = false;
|
||||
if( adrNext->UpdateChanMask == true )
|
||||
{
|
||||
// Re-enable default channels
|
||||
ChannelsMask[0] = 0xFFFF;
|
||||
ChannelsMask[1] = 0xFFFF;
|
||||
ChannelsMask[2] = 0xFFFF;
|
||||
ChannelsMask[3] = 0xFFFF;
|
||||
ChannelsMask[4] = 0xFFFF;
|
||||
ChannelsMask[5] = 0xFFFF;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
*drOut = datarate;
|
||||
*txPowOut = txPower;
|
||||
return adrAckReq;
|
||||
}
|
||||
|
||||
void LoRaPHYCN470::compute_rx_win_params(int8_t datarate, uint8_t minRxSymbols,
|
||||
uint32_t rxError,
|
||||
RxConfigParams_t *rxConfigParams)
|
||||
{
|
||||
double tSymbol = 0.0;
|
||||
|
||||
// Get the datarate, perform a boundary check
|
||||
rxConfigParams->Datarate = MIN( datarate, CN470_RX_MAX_DATARATE );
|
||||
rxConfigParams->Bandwidth = GetBandwidth( rxConfigParams->Datarate );
|
||||
|
||||
tSymbol = compute_symb_timeout_lora( DataratesCN470[rxConfigParams->Datarate], BandwidthsCN470[rxConfigParams->Datarate] );
|
||||
|
||||
get_rx_window_params( tSymbol, minRxSymbols, rxError, RADIO_WAKEUP_TIME, &rxConfigParams->WindowTimeout, &rxConfigParams->WindowOffset );
|
||||
}
|
||||
|
||||
bool LoRaPHYCN470::rx_config(RxConfigParams_t* rxConfig, int8_t* datarate)
|
||||
{
|
||||
int8_t dr = rxConfig->Datarate;
|
||||
uint8_t maxPayload = 0;
|
||||
int8_t phyDr = 0;
|
||||
uint32_t frequency = rxConfig->Frequency;
|
||||
|
||||
if(_radio->get_status() != RF_IDLE )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if( rxConfig->Window == 0 )
|
||||
{
|
||||
// Apply window 1 frequency
|
||||
frequency = CN470_FIRST_RX1_CHANNEL + ( rxConfig->Channel % 48 ) * CN470_STEPWIDTH_RX1_CHANNEL;
|
||||
}
|
||||
|
||||
// Read the physical datarate from the datarates table
|
||||
phyDr = DataratesCN470[dr];
|
||||
|
||||
_radio->set_channel(frequency);
|
||||
|
||||
// Radio configuration
|
||||
_radio->set_rx_config(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->set_max_payload_length(MODEM_LORA, maxPayload + LORA_MAC_FRMPAYLOAD_OVERHEAD);
|
||||
|
||||
*datarate = (uint8_t) dr;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool LoRaPHYCN470::tx_config(TxConfigParams_t* txConfig, int8_t* txPower,
|
||||
TimerTime_t* txTimeOnAir)
|
||||
{
|
||||
int8_t phyDr = DataratesCN470[txConfig->Datarate];
|
||||
int8_t txPowerLimited = LimitTxPower( txConfig->TxPower, Bands[Channels[txConfig->Channel].Band].TxMaxPower, txConfig->Datarate, ChannelsMask );
|
||||
int8_t phyTxPower = 0;
|
||||
|
||||
// Calculate physical TX power
|
||||
phyTxPower = compute_tx_power( txPowerLimited, txConfig->MaxEirp, txConfig->AntennaGain );
|
||||
|
||||
// Setup the radio frequency
|
||||
_radio->set_channel(Channels[txConfig->Channel].Frequency);
|
||||
|
||||
_radio->set_tx_config(MODEM_LORA, phyTxPower, 0, 0, phyDr, 1, 8, false, true,
|
||||
0, 0, false, 3000);
|
||||
// Setup maximum payload lenght of the radio driver
|
||||
_radio->set_max_payload_length(MODEM_LORA, txConfig->PktLen);
|
||||
// Get the time-on-air of the next tx frame
|
||||
*txTimeOnAir = _radio->time_on_air(MODEM_LORA, txConfig->PktLen);
|
||||
*txPower = txPowerLimited;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
uint8_t LoRaPHYCN470::link_ADR_request(LinkAdrReqParams_t* linkAdrReq,
|
||||
int8_t* drOut, int8_t* txPowOut,
|
||||
uint8_t* nbRepOut, uint8_t* nbBytesParsed)
|
||||
{
|
||||
uint8_t status = 0x07;
|
||||
RegionCommonLinkAdrParams_t linkAdrParams;
|
||||
uint8_t nextIndex = 0;
|
||||
uint8_t bytesProcessed = 0;
|
||||
uint16_t channelsMask[6] = { 0, 0, 0, 0, 0, 0 };
|
||||
GetPhyParams_t getPhy;
|
||||
PhyParam_t phyParam;
|
||||
RegionCommonLinkAdrReqVerifyParams_t linkAdrVerifyParams;
|
||||
|
||||
// Initialize local copy of channels mask
|
||||
copy_channel_mask( channelsMask, ChannelsMask, 6 );
|
||||
|
||||
while( bytesProcessed < linkAdrReq->PayloadSize )
|
||||
{
|
||||
// Get ADR request parameters
|
||||
nextIndex = parse_link_ADR_req( &( linkAdrReq->Payload[bytesProcessed] ), &linkAdrParams );
|
||||
|
||||
if( nextIndex == 0 )
|
||||
break; // break loop, since no more request has been found
|
||||
|
||||
// Update bytes processed
|
||||
bytesProcessed += nextIndex;
|
||||
|
||||
// Revert status, as we only check the last ADR request for the channel mask KO
|
||||
status = 0x07;
|
||||
|
||||
if( linkAdrParams.ChMaskCtrl == 6 )
|
||||
{
|
||||
// Enable all 125 kHz channels
|
||||
channelsMask[0] = 0xFFFF;
|
||||
channelsMask[1] = 0xFFFF;
|
||||
channelsMask[2] = 0xFFFF;
|
||||
channelsMask[3] = 0xFFFF;
|
||||
channelsMask[4] = 0xFFFF;
|
||||
channelsMask[5] = 0xFFFF;
|
||||
}
|
||||
else if( linkAdrParams.ChMaskCtrl == 7 )
|
||||
{
|
||||
status &= 0xFE; // Channel mask KO
|
||||
}
|
||||
else
|
||||
{
|
||||
for( uint8_t i = 0; i < 16; i++ )
|
||||
{
|
||||
if( ( ( linkAdrParams.ChMask & ( 1 << i ) ) != 0 ) &&
|
||||
( Channels[linkAdrParams.ChMaskCtrl * 16 + i].Frequency == 0 ) )
|
||||
{// Trying to enable an undefined channel
|
||||
status &= 0xFE; // Channel mask KO
|
||||
}
|
||||
}
|
||||
channelsMask[linkAdrParams.ChMaskCtrl] = linkAdrParams.ChMask;
|
||||
}
|
||||
}
|
||||
|
||||
// Get the minimum possible datarate
|
||||
getPhy.Attribute = PHY_MIN_TX_DR;
|
||||
getPhy.UplinkDwellTime = linkAdrReq->UplinkDwellTime;
|
||||
phyParam = get_phy_params(&getPhy);
|
||||
|
||||
linkAdrVerifyParams.Status = status;
|
||||
linkAdrVerifyParams.AdrEnabled = linkAdrReq->AdrEnabled;
|
||||
linkAdrVerifyParams.Datarate = linkAdrParams.Datarate;
|
||||
linkAdrVerifyParams.TxPower = linkAdrParams.TxPower;
|
||||
linkAdrVerifyParams.NbRep = linkAdrParams.NbRep;
|
||||
linkAdrVerifyParams.CurrentDatarate = linkAdrReq->CurrentDatarate;
|
||||
linkAdrVerifyParams.CurrentTxPower = linkAdrReq->CurrentTxPower;
|
||||
linkAdrVerifyParams.CurrentNbRep = linkAdrReq->CurrentNbRep;
|
||||
linkAdrVerifyParams.NbChannels = CN470_MAX_NB_CHANNELS;
|
||||
linkAdrVerifyParams.ChannelsMask = channelsMask;
|
||||
linkAdrVerifyParams.MinDatarate = ( int8_t )phyParam.Value;
|
||||
linkAdrVerifyParams.MaxDatarate = CN470_TX_MAX_DATARATE;
|
||||
linkAdrVerifyParams.Channels = Channels;
|
||||
linkAdrVerifyParams.MinTxPower = CN470_MIN_TX_POWER;
|
||||
linkAdrVerifyParams.MaxTxPower = CN470_MAX_TX_POWER;
|
||||
|
||||
// Verify the parameters and update, if necessary
|
||||
status = verify_link_ADR_req( &linkAdrVerifyParams, &linkAdrParams.Datarate, &linkAdrParams.TxPower, &linkAdrParams.NbRep );
|
||||
|
||||
// Update channelsMask if everything is correct
|
||||
if( status == 0x07 )
|
||||
{
|
||||
// Copy Mask
|
||||
copy_channel_mask( ChannelsMask, channelsMask, 6 );
|
||||
}
|
||||
|
||||
// Update status variables
|
||||
*drOut = linkAdrParams.Datarate;
|
||||
*txPowOut = linkAdrParams.TxPower;
|
||||
*nbRepOut = linkAdrParams.NbRep;
|
||||
*nbBytesParsed = bytesProcessed;
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
uint8_t LoRaPHYCN470::setup_rx_params( RxParamSetupReqParams_t* rxParamSetupReq)
|
||||
{
|
||||
uint8_t status = 0x07;
|
||||
uint32_t freq = rxParamSetupReq->Frequency;
|
||||
|
||||
// Verify radio frequency
|
||||
if( (_radio->check_rf_frequency(freq) == false ) ||
|
||||
( freq < CN470_FIRST_RX1_CHANNEL ) ||
|
||||
( freq > CN470_LAST_RX1_CHANNEL ) ||
|
||||
( ( ( freq - ( uint32_t ) CN470_FIRST_RX1_CHANNEL ) % ( uint32_t ) CN470_STEPWIDTH_RX1_CHANNEL ) != 0 ) )
|
||||
{
|
||||
status &= 0xFE; // Channel frequency KO
|
||||
}
|
||||
|
||||
// Verify datarate
|
||||
if( val_in_range( rxParamSetupReq->Datarate, CN470_RX_MIN_DATARATE, CN470_RX_MAX_DATARATE ) == 0 )
|
||||
{
|
||||
status &= 0xFD; // Datarate KO
|
||||
}
|
||||
|
||||
// Verify datarate offset
|
||||
if( val_in_range( rxParamSetupReq->DrOffset, CN470_MIN_RX1_DR_OFFSET, CN470_MAX_RX1_DR_OFFSET ) == 0 )
|
||||
{
|
||||
status &= 0xFB; // Rx1DrOffset range KO
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
uint8_t LoRaPHYCN470::request_new_channel(NewChannelReqParams_t* newChannelReq)
|
||||
{
|
||||
// Datarate and frequency KO
|
||||
return 0;
|
||||
}
|
||||
|
||||
int8_t LoRaPHYCN470::setup_tx_params(TxParamSetupReqParams_t* txParamSetupReq)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
uint8_t LoRaPHYCN470::dl_channel_request(DlChannelReqParams_t* dlChannelReq)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
int8_t LoRaPHYCN470::get_alternate_DR(AlternateDrParams_t* alternateDr)
|
||||
{
|
||||
int8_t datarate = 0;
|
||||
|
||||
if( ( alternateDr->NbTrials % 48 ) == 0 )
|
||||
{
|
||||
datarate = DR_0;
|
||||
}
|
||||
else if( ( alternateDr->NbTrials % 32 ) == 0 )
|
||||
{
|
||||
datarate = DR_1;
|
||||
}
|
||||
else if( ( alternateDr->NbTrials % 24 ) == 0 )
|
||||
{
|
||||
datarate = DR_2;
|
||||
}
|
||||
else if( ( alternateDr->NbTrials % 16 ) == 0 )
|
||||
{
|
||||
datarate = DR_3;
|
||||
}
|
||||
else if( ( alternateDr->NbTrials % 8 ) == 0 )
|
||||
{
|
||||
datarate = DR_4;
|
||||
}
|
||||
else
|
||||
{
|
||||
datarate = DR_5;
|
||||
}
|
||||
return datarate;
|
||||
}
|
||||
|
||||
void LoRaPHYCN470::calculate_backoff(CalcBackOffParams_t* calcBackOff)
|
||||
{
|
||||
RegionCommonCalcBackOffParams_t calcBackOffParams;
|
||||
|
||||
calcBackOffParams.Channels = Channels;
|
||||
calcBackOffParams.Bands = 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;
|
||||
|
||||
get_DC_backoff( &calcBackOffParams );
|
||||
}
|
||||
|
||||
bool LoRaPHYCN470::set_next_channel(NextChanParams_t* nextChanParams,
|
||||
uint8_t* channel, TimerTime_t* time,
|
||||
TimerTime_t* aggregatedTimeOff)
|
||||
{
|
||||
uint8_t nbEnabledChannels = 0;
|
||||
uint8_t delayTx = 0;
|
||||
uint8_t enabledChannels[CN470_MAX_NB_CHANNELS] = { 0 };
|
||||
TimerTime_t nextTxDelay = 0;
|
||||
|
||||
// Count 125kHz channels
|
||||
if( num_active_channels( ChannelsMask, 0, 6 ) == 0 )
|
||||
{ // Reactivate default channels
|
||||
ChannelsMask[0] = 0xFFFF;
|
||||
ChannelsMask[1] = 0xFFFF;
|
||||
ChannelsMask[2] = 0xFFFF;
|
||||
ChannelsMask[3] = 0xFFFF;
|
||||
ChannelsMask[4] = 0xFFFF;
|
||||
ChannelsMask[5] = 0xFFFF;
|
||||
}
|
||||
|
||||
if( nextChanParams->AggrTimeOff <= TimerGetElapsedTime( nextChanParams->LastAggrTx ) )
|
||||
{
|
||||
// Reset Aggregated time off
|
||||
*aggregatedTimeOff = 0;
|
||||
|
||||
// Update bands Time OFF
|
||||
nextTxDelay = update_band_timeoff( nextChanParams->Joined, nextChanParams->DutyCycleEnabled, Bands, CN470_MAX_NB_BANDS );
|
||||
|
||||
// Search how many channels are enabled
|
||||
nbEnabledChannels = CountNbOfEnabledChannels( nextChanParams->Datarate,
|
||||
ChannelsMask, Channels,
|
||||
Bands, enabledChannels, &delayTx );
|
||||
}
|
||||
else
|
||||
{
|
||||
delayTx++;
|
||||
nextTxDelay = nextChanParams->AggrTimeOff - TimerGetElapsedTime( nextChanParams->LastAggrTx );
|
||||
}
|
||||
|
||||
if( nbEnabledChannels > 0 )
|
||||
{
|
||||
// We found a valid channel
|
||||
*channel = enabledChannels[get_random( 0, nbEnabledChannels - 1 )];
|
||||
|
||||
*time = 0;
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
if( delayTx > 0 )
|
||||
{
|
||||
// Delay transmission due to AggregatedTimeOff or to a band time off
|
||||
*time = nextTxDelay;
|
||||
return true;
|
||||
}
|
||||
// Datarate not supported by any channel
|
||||
*time = 0;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
LoRaMacStatus_t LoRaPHYCN470::add_channel(ChannelAddParams_t* channelAdd)
|
||||
{
|
||||
return LORAMAC_STATUS_PARAMETER_INVALID;
|
||||
}
|
||||
|
||||
bool LoRaPHYCN470::remove_channel(ChannelRemoveParams_t* channelRemove)
|
||||
{
|
||||
return LORAMAC_STATUS_PARAMETER_INVALID;
|
||||
}
|
||||
|
||||
void LoRaPHYCN470::set_tx_cont_mode(ContinuousWaveParams_t* continuousWave)
|
||||
{
|
||||
int8_t txPowerLimited = LimitTxPower( continuousWave->TxPower, Bands[Channels[continuousWave->Channel].Band].TxMaxPower, continuousWave->Datarate, ChannelsMask );
|
||||
int8_t phyTxPower = 0;
|
||||
uint32_t frequency = Channels[continuousWave->Channel].Frequency;
|
||||
|
||||
// Calculate physical TX power
|
||||
phyTxPower = compute_tx_power( txPowerLimited, continuousWave->MaxEirp, continuousWave->AntennaGain );
|
||||
|
||||
_radio->set_tx_continuous_wave(frequency, phyTxPower, continuousWave->Timeout);
|
||||
}
|
||||
|
||||
uint8_t LoRaPHYCN470::apply_DR_offset(uint8_t downlinkDwellTime, int8_t dr,
|
||||
int8_t drOffset)
|
||||
{
|
||||
int8_t datarate = dr - drOffset;
|
||||
|
||||
if( datarate < 0 )
|
||||
{
|
||||
datarate = DR_0;
|
||||
}
|
||||
return datarate;
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,365 @@
|
|||
/**
|
||||
* @file LoRaPHYCN470.h
|
||||
*
|
||||
* @brief Implements LoRaPHY for Chinese 470 MHz band
|
||||
*
|
||||
* \code
|
||||
* ______ _
|
||||
* / _____) _ | |
|
||||
* ( (____ _____ ____ _| |_ _____ ____| |__
|
||||
* \____ \| ___ | (_ _) ___ |/ ___) _ \
|
||||
* _____) ) ____| | | || |_| ____( (___| | | |
|
||||
* (______/|_____)_|_|_| \__)_____)\____)_| |_|
|
||||
* (C)2013 Semtech
|
||||
* ___ _____ _ ___ _ _____ ___ ___ ___ ___
|
||||
* / __|_ _/_\ / __| |/ / __/ _ \| _ \/ __| __|
|
||||
* \__ \ | |/ _ \ (__| ' <| _| (_) | / (__| _|
|
||||
* |___/ |_/_/ \_\___|_|\_\_| \___/|_|_\\___|___|
|
||||
* embedded.connectivity.solutions===============
|
||||
*
|
||||
* \endcode
|
||||
*
|
||||
*
|
||||
* License: Revised BSD License, see LICENSE.TXT file include in the project
|
||||
*
|
||||
* Maintainer: Miguel Luis ( Semtech ), Gregory Cristian ( Semtech ) and Daniel Jaeckle ( STACKFORCE )
|
||||
*
|
||||
* Copyright (c) 2017, Arm Limited and affiliates.
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef MBED_OS_LORAPHY_CN470_H_
|
||||
#define MBED_OS_LORAPHY_CN470_H_
|
||||
|
||||
#include "LoRaPHY.h"
|
||||
#include "netsocket/LoRaRadio.h"
|
||||
|
||||
// Definitions
|
||||
/*!
|
||||
* LoRaMac maximum number of channels
|
||||
*/
|
||||
#define CN470_MAX_NB_CHANNELS 96
|
||||
|
||||
/*!
|
||||
* LoRaMac maximum number of bands
|
||||
*/
|
||||
#define CN470_MAX_NB_BANDS 1
|
||||
|
||||
|
||||
#define CN470_CHANNELS_MASK_SIZE 6
|
||||
|
||||
|
||||
class LoRaPHYCN470 : public LoRaPHY {
|
||||
|
||||
public:
|
||||
|
||||
LoRaPHYCN470();
|
||||
virtual ~LoRaPHYCN470();
|
||||
|
||||
/*!
|
||||
* \brief The function gets a value of a specific PHY attribute.
|
||||
*
|
||||
* \param [in] getPhy A pointer to the function parameters.
|
||||
*
|
||||
* \retval A structure containing the PHY parameter.
|
||||
*/
|
||||
virtual PhyParam_t get_phy_params(GetPhyParams_t* getPhy );
|
||||
|
||||
/*!
|
||||
* \brief Updates the last TX done parameters of the current channel.
|
||||
*
|
||||
* \param [in] txDone A pointer to the function parameters.
|
||||
*/
|
||||
virtual void set_band_tx_done(SetBandTxDoneParams_t* txDone );
|
||||
|
||||
/*!
|
||||
* \brief Initializes the channels masks and the channels.
|
||||
*
|
||||
* \param [in] type Sets the initialization type.
|
||||
*/
|
||||
virtual void load_defaults(InitType_t type );
|
||||
|
||||
/*!
|
||||
* \brief Verifies a parameter.
|
||||
*
|
||||
* \param [in] verify A pointer to the function parameters.
|
||||
*
|
||||
* \param [in] phyAttribute The attribute to be verified.
|
||||
*
|
||||
* \retval True, if the parameter is valid.
|
||||
*/
|
||||
virtual bool verify(VerifyParams_t* verify, PhyAttribute_t phyAttribute );
|
||||
|
||||
/*!
|
||||
* \brief The function parses the input buffer and sets up the channels of the
|
||||
* CF list.
|
||||
*
|
||||
* \param [in] applyCFList A pointer to the function parameters.
|
||||
*/
|
||||
virtual void apply_cf_list(ApplyCFListParams_t* applyCFList );
|
||||
|
||||
/*!
|
||||
* \brief Sets a channels mask.
|
||||
*
|
||||
* \param [in] chanMaskSet A pointer to the function parameters.
|
||||
*
|
||||
* \retval True, if the channels mask could be set.
|
||||
*/
|
||||
virtual bool set_channel_mask(ChanMaskSetParams_t* chanMaskSet );
|
||||
|
||||
/*!
|
||||
* \brief Calculates the next datarate to set, when ADR is on or off.
|
||||
*
|
||||
* \param [in] adrNext A pointer to the function parameters.
|
||||
*
|
||||
* \param [out] drOut The calculated datarate for the next TX.
|
||||
*
|
||||
* \param [out] txPowOut The TX power for the next TX.
|
||||
*
|
||||
* \param [out] adrAckCounter The calculated ADR acknowledgement counter.
|
||||
*
|
||||
* \retval True, if an ADR request should be performed.
|
||||
*/
|
||||
virtual bool get_next_ADR(AdrNextParams_t* adrNext, int8_t* drOut,
|
||||
int8_t* txPowOut, uint32_t* adrAckCounter );
|
||||
|
||||
/*!
|
||||
* \brief Configuration of the RX windows.
|
||||
*
|
||||
* \param [in] rxConfig A pointer to the function parameters.
|
||||
*
|
||||
* \param [out] datarate The datarate index set.
|
||||
*
|
||||
* \retval True, if the configuration was applied successfully.
|
||||
*/
|
||||
virtual bool rx_config(RxConfigParams_t* rxConfig, int8_t* datarate );
|
||||
|
||||
/*
|
||||
* RX window precise timing
|
||||
*
|
||||
* For more details please consult the following document, chapter 3.1.2.
|
||||
* http://www.semtech.com/images/datasheet/SX1272_settings_for_LoRaWAN_v2.0.pdf
|
||||
* or
|
||||
* http://www.semtech.com/images/datasheet/SX1276_settings_for_LoRaWAN_v2.0.pdf
|
||||
*
|
||||
* Downlink start: T = Tx + 1s (+/- 20 us)
|
||||
* |
|
||||
* TRxEarly | TRxLate
|
||||
* | | |
|
||||
* | | +---+---+---+---+---+---+---+---+
|
||||
* | | | Latest Rx window |
|
||||
* | | +---+---+---+---+---+---+---+---+
|
||||
* | | |
|
||||
* +---+---+---+---+---+---+---+---+
|
||||
* | Earliest Rx window |
|
||||
* +---+---+---+---+---+---+---+---+
|
||||
* |
|
||||
* +---+---+---+---+---+---+---+---+
|
||||
*Downlink preamble 8 symbols | | | | | | | | |
|
||||
* +---+---+---+---+---+---+---+---+
|
||||
*
|
||||
* Worst case Rx window timings
|
||||
*
|
||||
* TRxLate = DEFAULT_MIN_RX_SYMBOLS * tSymbol - RADIO_WAKEUP_TIME
|
||||
* TRxEarly = 8 - DEFAULT_MIN_RX_SYMBOLS * tSymbol - RxWindowTimeout - RADIO_WAKEUP_TIME
|
||||
*
|
||||
* TRxLate - TRxEarly = 2 * DEFAULT_SYSTEM_MAX_RX_ERROR
|
||||
*
|
||||
* RxOffset = ( TRxLate + TRxEarly ) / 2
|
||||
*
|
||||
* RxWindowTimeout = ( 2 * DEFAULT_MIN_RX_SYMBOLS - 8 ) * tSymbol + 2 * DEFAULT_SYSTEM_MAX_RX_ERROR
|
||||
* RxOffset = 4 * tSymbol - RxWindowTimeout / 2 - RADIO_WAKE_UP_TIME
|
||||
*
|
||||
* The minimum value of RxWindowTimeout must be 5 symbols which implies that the system always tolerates at least an error of 1.5 * tSymbol
|
||||
*/
|
||||
/*!
|
||||
* Computes the RX window timeout and offset.
|
||||
*
|
||||
* \param [in] datarate The RX window datarate index to be used.
|
||||
*
|
||||
* \param [in] minRxSymbols The minimum number of symbols required to detect an RX frame.
|
||||
*
|
||||
* \param [in] rxError The system maximum timing error of the receiver in milliseconds.
|
||||
* The receiver will turn on in a [-rxError : +rxError] ms
|
||||
* interval around RxOffset.
|
||||
*
|
||||
* \param [out] rxConfigParams The updated WindowTimeout and WindowOffset fields.
|
||||
*/
|
||||
virtual void compute_rx_win_params(int8_t datarate,
|
||||
uint8_t minRxSymbols,
|
||||
uint32_t rxError,
|
||||
RxConfigParams_t *rxConfigParams);
|
||||
|
||||
/*!
|
||||
* \brief TX configuration.
|
||||
*
|
||||
* \param [in] txConfig A pointer to the function parameters.
|
||||
*
|
||||
* \param [out] txPower The TX power index set.
|
||||
*
|
||||
* \param [out] txTimeOnAir The time-on-air of the frame.
|
||||
*
|
||||
* \retval True, if the configuration was applied successfully.
|
||||
*/
|
||||
virtual bool tx_config(TxConfigParams_t* txConfig, int8_t* txPower,
|
||||
TimerTime_t* txTimeOnAir );
|
||||
|
||||
/*!
|
||||
* \brief The function processes a Link ADR request.
|
||||
*
|
||||
* \param [in] linkAdrReq A pointer to the function parameters.
|
||||
*
|
||||
* \param [out] drOut The datarate applied.
|
||||
*
|
||||
* \param [out] txPowOut The TX power applied.
|
||||
*
|
||||
* \param [out] nbRepOut The number of repetitions to apply.
|
||||
*
|
||||
* \param [out] nbBytesParsed The number of bytes parsed.
|
||||
*
|
||||
* \retval The status of the operation, according to the LoRaMAC specification.
|
||||
*/
|
||||
virtual uint8_t link_ADR_request(LinkAdrReqParams_t* linkAdrReq,
|
||||
int8_t* drOut, int8_t* txPowOut,
|
||||
uint8_t* nbRepOut,
|
||||
uint8_t* nbBytesParsed );
|
||||
|
||||
/*!
|
||||
* \brief The function processes a RX parameter setup request.
|
||||
*
|
||||
* \param [in] rxParamSetupReq A pointer to the function parameters.
|
||||
*
|
||||
* \retval The status of the operation, according to the LoRaMAC specification.
|
||||
*/
|
||||
virtual uint8_t setup_rx_params(RxParamSetupReqParams_t* rxParamSetupReq );
|
||||
|
||||
/*!
|
||||
* \brief The function processes a new channel request.
|
||||
*
|
||||
* \param [in] newChannelReq A pointer to the function parameters.
|
||||
*
|
||||
* \retval The status of the operation, according to the LoRaMAC specification.
|
||||
*/
|
||||
virtual uint8_t request_new_channel(NewChannelReqParams_t* newChannelReq );
|
||||
|
||||
/*!
|
||||
* \brief The function processes a TX ParamSetup request.
|
||||
*
|
||||
* \param [in] txParamSetupReq A pointer to the function parameters.
|
||||
*
|
||||
* \retval The status of the operation, according to the LoRaMAC specification.
|
||||
* Returns -1, if the functionality is not implemented. In this case, the end node
|
||||
* shall ignore the command.
|
||||
*/
|
||||
virtual int8_t setup_tx_params(TxParamSetupReqParams_t* txParamSetupReq );
|
||||
|
||||
/*!
|
||||
* \brief The function processes a DlChannel request.
|
||||
*
|
||||
* \param [in] dlChannelReq A pointer to the function parameters.
|
||||
*
|
||||
* \retval The status of the operation, according to the LoRaMAC specification.
|
||||
*/
|
||||
virtual uint8_t dl_channel_request(DlChannelReqParams_t* dlChannelReq );
|
||||
|
||||
/*!
|
||||
* \brief Alternates the datarate of the channel for the join request.
|
||||
*
|
||||
* \param [in] alternateDr A pointer to the function parameters.
|
||||
*
|
||||
* \retval The datarate to apply.
|
||||
*/
|
||||
virtual int8_t get_alternate_DR(AlternateDrParams_t* alternateDr );
|
||||
|
||||
/*!
|
||||
* \brief Calculates the back-off time.
|
||||
*
|
||||
* \param [in] calcBackOff A pointer to the function parameters.
|
||||
*/
|
||||
virtual void calculate_backoff(CalcBackOffParams_t* calcBackOff );
|
||||
|
||||
/*!
|
||||
* \brief Searches and sets the next random available channel.
|
||||
*
|
||||
* \param [in] nextChanParams The parameters for the next channel
|
||||
*
|
||||
* \param [out] channel The next channel to use for TX.
|
||||
*
|
||||
* \param [out] time The time to wait for the next transmission according to the duty
|
||||
* cycle.
|
||||
*
|
||||
* \param [out] aggregatedTimeOff Updates the aggregated time off.
|
||||
*
|
||||
* \retval Function status [1: OK, 0: Unable to find a channel on the current datarate].
|
||||
*/
|
||||
virtual bool set_next_channel(NextChanParams_t* nextChanParams,
|
||||
uint8_t* channel, TimerTime_t* time,
|
||||
TimerTime_t* aggregatedTimeOff );
|
||||
|
||||
/*!
|
||||
* \brief Adds a channel.
|
||||
*
|
||||
* \param [in] channelAdd A pointer to the function parameters.
|
||||
*
|
||||
* \retval The status of the operation.
|
||||
*/
|
||||
virtual LoRaMacStatus_t add_channel(ChannelAddParams_t* channelAdd );
|
||||
|
||||
/*!
|
||||
* \brief Removes a channel.
|
||||
*
|
||||
* \param [in] channelRemove A pointer to the function parameters.
|
||||
*
|
||||
* \retval True, if the channel was removed successfully.
|
||||
*/
|
||||
virtual bool remove_channel(ChannelRemoveParams_t* channelRemove );
|
||||
|
||||
/*!
|
||||
* \brief Sets the radio into continuous wave mode.
|
||||
*
|
||||
* \param [in] continuousWave A pointer to the function parameters.
|
||||
*/
|
||||
virtual void set_tx_cont_mode(ContinuousWaveParams_t* continuousWave );
|
||||
|
||||
/*!
|
||||
* \brief Computes a new datarate according to the given offset.
|
||||
*
|
||||
* \param [in] downlinkDwellTime The downlink dwell time configuration. 0: No limit, 1: 400ms
|
||||
*
|
||||
* \param [in] dr The current datarate.
|
||||
*
|
||||
* \param [in] drOffset The offset to be applied.
|
||||
*
|
||||
* \retval newDr The computed datarate.
|
||||
*/
|
||||
virtual uint8_t apply_DR_offset(uint8_t downlinkDwellTime, int8_t dr, int8_t drOffset );
|
||||
|
||||
private:
|
||||
uint8_t CountNbOfEnabledChannels( uint8_t datarate, uint16_t* channelsMask, ChannelParams_t* channels, Band_t* bands, uint8_t* enabledChannels, uint8_t* delayTx );
|
||||
bool RegionCN470ChanMaskSet( ChanMaskSetParams_t* chanMaskSet );
|
||||
|
||||
|
||||
// Global attributes
|
||||
/*!
|
||||
* LoRaMAC channels
|
||||
*/
|
||||
ChannelParams_t Channels[CN470_MAX_NB_CHANNELS];
|
||||
|
||||
/*!
|
||||
* LoRaMac bands
|
||||
*/
|
||||
Band_t Bands[CN470_MAX_NB_BANDS];
|
||||
|
||||
/*!
|
||||
* LoRaMac channels mask
|
||||
*/
|
||||
uint16_t ChannelsMask[CN470_CHANNELS_MASK_SIZE];
|
||||
|
||||
/*!
|
||||
* LoRaMac channels default mask
|
||||
*/
|
||||
uint16_t ChannelsDefaultMask[CN470_CHANNELS_MASK_SIZE];
|
||||
};
|
||||
|
||||
#endif /* MBED_OS_LORAPHY_CN470_H_ */
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,354 @@
|
|||
/**
|
||||
* @file LoRaPHYCN779.h
|
||||
*
|
||||
* @brief Implements LoRaPHY for Chinese 779 MHz band
|
||||
*
|
||||
* \code
|
||||
* ______ _
|
||||
* / _____) _ | |
|
||||
* ( (____ _____ ____ _| |_ _____ ____| |__
|
||||
* \____ \| ___ | (_ _) ___ |/ ___) _ \
|
||||
* _____) ) ____| | | || |_| ____( (___| | | |
|
||||
* (______/|_____)_|_|_| \__)_____)\____)_| |_|
|
||||
* (C)2013 Semtech
|
||||
* ___ _____ _ ___ _ _____ ___ ___ ___ ___
|
||||
* / __|_ _/_\ / __| |/ / __/ _ \| _ \/ __| __|
|
||||
* \__ \ | |/ _ \ (__| ' <| _| (_) | / (__| _|
|
||||
* |___/ |_/_/ \_\___|_|\_\_| \___/|_|_\\___|___|
|
||||
* embedded.connectivity.solutions===============
|
||||
*
|
||||
* \endcode
|
||||
*
|
||||
*
|
||||
* License: Revised BSD License, see LICENSE.TXT file include in the project
|
||||
*
|
||||
* Maintainer: Miguel Luis ( Semtech ), Gregory Cristian ( Semtech ) and Daniel Jaeckle ( STACKFORCE )
|
||||
*
|
||||
* Copyright (c) 2017, Arm Limited and affiliates.
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef MBED_OS_LORAPHY_CN779_H_
|
||||
#define MBED_OS_LORAPHY_CN779_H_
|
||||
|
||||
#include "LoRaPHY.h"
|
||||
#include "netsocket/LoRaRadio.h"
|
||||
|
||||
#define CN779_MAX_NB_CHANNELS 16
|
||||
|
||||
#define CN779_MAX_NB_BANDS 1
|
||||
|
||||
#define CN779_CHANNELS_MASK_SIZE 1
|
||||
|
||||
|
||||
class LoRaPHYCN779 : public LoRaPHY {
|
||||
|
||||
public:
|
||||
|
||||
LoRaPHYCN779();
|
||||
virtual ~LoRaPHYCN779();
|
||||
|
||||
/*!
|
||||
* \brief The function gets a value of a specific PHY attribute.
|
||||
*
|
||||
* \param [in] getPhy A pointer to the function parameters.
|
||||
*
|
||||
* \retval The structure containing the PHY parameter.
|
||||
*/
|
||||
virtual PhyParam_t get_phy_params(GetPhyParams_t* getPhy );
|
||||
|
||||
/*!
|
||||
* \brief Updates the last TX done parameters of the current channel.
|
||||
*
|
||||
* \param [in] txDone A pointer to the function parameters.
|
||||
*/
|
||||
virtual void set_band_tx_done(SetBandTxDoneParams_t* txDone );
|
||||
|
||||
/*!
|
||||
* \brief Initializes the channels masks and the channels.
|
||||
*
|
||||
* \param [in] type Sets the initialization type.
|
||||
*/
|
||||
virtual void load_defaults(InitType_t type );
|
||||
|
||||
/*!
|
||||
* \brief Verifies a parameter.
|
||||
*
|
||||
* \param [in] verify A pointer to the function parameters.
|
||||
*
|
||||
* \param [in] phyAttribute The attribute to verify.
|
||||
*
|
||||
* \retval True, if the parameter is valid.
|
||||
*/
|
||||
virtual bool verify(VerifyParams_t* verify, PhyAttribute_t phyAttribute );
|
||||
|
||||
/*!
|
||||
* \brief The function parses the input buffer and sets up the channels of the CF list.
|
||||
*
|
||||
* \param [in] applyCFList A pointer to the function parameters.
|
||||
*/
|
||||
virtual void apply_cf_list(ApplyCFListParams_t* applyCFList );
|
||||
|
||||
/*!
|
||||
* \brief Sets a channels mask.
|
||||
*
|
||||
* \param [in] chanMaskSet A pointer to the function parameters.
|
||||
*
|
||||
* \retval True, if the channels mask could be set.
|
||||
*/
|
||||
virtual bool set_channel_mask(ChanMaskSetParams_t* chanMaskSet );
|
||||
|
||||
/*!
|
||||
* \brief Calculates the next datarate to set, when ADR is on or off.
|
||||
*
|
||||
* \param [in] adrNext A pointer to the function parameters.
|
||||
*
|
||||
* \param [out] drOut The calculated datarate for the next TX.
|
||||
*
|
||||
* \param [out] txPowOut The TX power for the next TX.
|
||||
*
|
||||
* \param [out] adrAckCounter The calculated ADR acknowledgement counter.
|
||||
*
|
||||
* \retval True, if an ADR request should be performed.
|
||||
*/
|
||||
virtual bool get_next_ADR(AdrNextParams_t* adrNext, int8_t* drOut,
|
||||
int8_t* txPowOut, uint32_t* adrAckCounter );
|
||||
|
||||
/*!
|
||||
* \brief Configuration of the RX windows.
|
||||
*
|
||||
* \param [in] rxConfig A pointer to the function parameters.
|
||||
*
|
||||
* \param [out] datarate The datarate index set.
|
||||
*
|
||||
* \retval True, if the configuration was applied successfully.
|
||||
*/
|
||||
virtual bool rx_config(RxConfigParams_t* rxConfig, int8_t* datarate );
|
||||
|
||||
/*
|
||||
* RX window precise timing
|
||||
*
|
||||
* For more details please consult the following document, chapter 3.1.2.
|
||||
* http://www.semtech.com/images/datasheet/SX1272_settings_for_LoRaWAN_v2.0.pdf
|
||||
* or
|
||||
* http://www.semtech.com/images/datasheet/SX1276_settings_for_LoRaWAN_v2.0.pdf
|
||||
*
|
||||
* Downlink start: T = Tx + 1s (+/- 20 us)
|
||||
* |
|
||||
* TRxEarly | TRxLate
|
||||
* | | |
|
||||
* | | +---+---+---+---+---+---+---+---+
|
||||
* | | | Latest Rx window |
|
||||
* | | +---+---+---+---+---+---+---+---+
|
||||
* | | |
|
||||
* +---+---+---+---+---+---+---+---+
|
||||
* | Earliest Rx window |
|
||||
* +---+---+---+---+---+---+---+---+
|
||||
* |
|
||||
* +---+---+---+---+---+---+---+---+
|
||||
*Downlink preamble 8 symbols | | | | | | | | |
|
||||
* +---+---+---+---+---+---+---+---+
|
||||
*
|
||||
* Worst case Rx window timings
|
||||
*
|
||||
* TRxLate = DEFAULT_MIN_RX_SYMBOLS * tSymbol - RADIO_WAKEUP_TIME
|
||||
* TRxEarly = 8 - DEFAULT_MIN_RX_SYMBOLS * tSymbol - RxWindowTimeout - RADIO_WAKEUP_TIME
|
||||
*
|
||||
* TRxLate - TRxEarly = 2 * DEFAULT_SYSTEM_MAX_RX_ERROR
|
||||
*
|
||||
* RxOffset = ( TRxLate + TRxEarly ) / 2
|
||||
*
|
||||
* RxWindowTimeout = ( 2 * DEFAULT_MIN_RX_SYMBOLS - 8 ) * tSymbol + 2 * DEFAULT_SYSTEM_MAX_RX_ERROR
|
||||
* RxOffset = 4 * tSymbol - RxWindowTimeout / 2 - RADIO_WAKE_UP_TIME
|
||||
*
|
||||
* The minimum value of RxWindowTimeout must be 5 symbols which implies that the system always tolerates at least an error of 1.5 * tSymbol
|
||||
*/
|
||||
/*!
|
||||
* Computes the RX window timeout and offset.
|
||||
*
|
||||
* \param [in] datarate The RX window datarate index to be used.
|
||||
*
|
||||
* \param [in] minRxSymbols The minimum required number of symbols to detect an RX frame.
|
||||
*
|
||||
* \param [in] rxError The system maximum timing error of the receiver in milliseconds.
|
||||
* The receiver will turn on in a [-rxError : +rxError] ms
|
||||
* interval around RxOffset.
|
||||
*
|
||||
* \param [out] rxConfigParams Returns the updated WindowTimeout and WindowOffset fields.
|
||||
*/
|
||||
virtual void compute_rx_win_params(int8_t datarate,
|
||||
uint8_t minRxSymbols,
|
||||
uint32_t rxError,
|
||||
RxConfigParams_t *rxConfigParams);
|
||||
|
||||
/*!
|
||||
* \brief TX configuration.
|
||||
*
|
||||
* \param [in] txConfig A pointer to the function parameters.
|
||||
*
|
||||
* \param [out] txPower The TX power index set.
|
||||
*
|
||||
* \param [out] txTimeOnAir The time-on-air of the frame.
|
||||
*
|
||||
* \retval True, if the configuration was applied successfully.
|
||||
*/
|
||||
virtual bool tx_config(TxConfigParams_t* txConfig, int8_t* txPower,
|
||||
TimerTime_t* txTimeOnAir );
|
||||
|
||||
/*!
|
||||
* \brief The function processes a Link ADR request.
|
||||
*
|
||||
* \param [in] linkAdrReq A pointer to the function parameters.
|
||||
*
|
||||
* \param [out] drOut The datarate applied.
|
||||
*
|
||||
* \param [out] txPowOut The TX power applied.
|
||||
*
|
||||
* \param [out] nbRepOut The number of repetitions to apply.
|
||||
*
|
||||
* \param [out] nbBytesParsed The number of bytes parsed.
|
||||
*
|
||||
* \retval The status of the operation, according to the LoRaMAC specification.
|
||||
*/
|
||||
virtual uint8_t link_ADR_request(LinkAdrReqParams_t* linkAdrReq,
|
||||
int8_t* drOut, int8_t* txPowOut,
|
||||
uint8_t* nbRepOut,
|
||||
uint8_t* nbBytesParsed );
|
||||
|
||||
/*!
|
||||
* \brief The function processes a RX parameter setup request.
|
||||
*
|
||||
* \param [in] rxParamSetupReq A pointer to the function parameters.
|
||||
*
|
||||
* \retval The status of the operation, according to the LoRaMAC specification.
|
||||
*/
|
||||
virtual uint8_t setup_rx_params(RxParamSetupReqParams_t* rxParamSetupReq );
|
||||
|
||||
/*!
|
||||
* \brief The function processes a new channel request.
|
||||
*
|
||||
* \param [in] newChannelReq A pointer to the function parameters.
|
||||
*
|
||||
* \retval The status of the operation, according to the LoRaMAC specification.
|
||||
*/
|
||||
virtual uint8_t request_new_channel(NewChannelReqParams_t* newChannelReq );
|
||||
|
||||
/*!
|
||||
* \brief The function processes a TX ParamSetup request.
|
||||
*
|
||||
* \param [in] txParamSetupReq A pointer to the function parameters.
|
||||
*
|
||||
* \retval The status of the operation, according to the LoRaMAC specification.
|
||||
* Returns -1, if the functionality is not implemented. In this case, the end node
|
||||
* shall ignore the command.
|
||||
*/
|
||||
virtual int8_t setup_tx_params(TxParamSetupReqParams_t* txParamSetupReq );
|
||||
|
||||
/*!
|
||||
* \brief The function processes a DlChannel request.
|
||||
*
|
||||
* \param [in] dlChannelReq A pointer to the function parameters.
|
||||
*
|
||||
* \retval The status of the operation, according to the LoRaMAC specification.
|
||||
*/
|
||||
virtual uint8_t dl_channel_request(DlChannelReqParams_t* dlChannelReq );
|
||||
|
||||
/*!
|
||||
* \brief Alternates the datarate of the channel for the join request.
|
||||
*
|
||||
* \param [in] alternateDr A pointer to the function parameters.
|
||||
*
|
||||
* \retval The datarate to apply.
|
||||
*/
|
||||
virtual int8_t get_alternate_DR(AlternateDrParams_t* alternateDr );
|
||||
|
||||
/*!
|
||||
* \brief Calculates the back-off time.
|
||||
*
|
||||
* \param [in] calcBackOff A pointer to the function parameters.
|
||||
*/
|
||||
virtual void calculate_backoff(CalcBackOffParams_t* calcBackOff );
|
||||
|
||||
/*!
|
||||
* \brief Searches and sets the next random available channel.
|
||||
*
|
||||
* \param [in] nextChanParams The parameters for the next channel.
|
||||
*
|
||||
* \param [out] channel The next channel to use for TX.
|
||||
*
|
||||
* \param [out] time The time to wait for the next transmission according to the duty
|
||||
* cycle.
|
||||
*
|
||||
* \param [out] aggregatedTimeOff Updates the aggregated time off.
|
||||
*
|
||||
* \retval Function status [1: OK, 0: Unable to find a channel on the current datarate].
|
||||
*/
|
||||
virtual bool set_next_channel(NextChanParams_t* nextChanParams,
|
||||
uint8_t* channel, TimerTime_t* time,
|
||||
TimerTime_t* aggregatedTimeOff );
|
||||
|
||||
/*!
|
||||
* \brief Adds a channel.
|
||||
*
|
||||
* \param [in] channelAdd A pointer to the function parameters.
|
||||
*
|
||||
* \retval The status of the operation.
|
||||
*/
|
||||
virtual LoRaMacStatus_t add_channel(ChannelAddParams_t* channelAdd );
|
||||
|
||||
/*!
|
||||
* \brief Removes a channel.
|
||||
*
|
||||
* \param [in] channelRemove A pointer to the function parameters.
|
||||
*
|
||||
* \retval True, if the channel was removed successfully.
|
||||
*/
|
||||
virtual bool remove_channel(ChannelRemoveParams_t* channelRemove );
|
||||
|
||||
/*!
|
||||
* \brief Sets the radio into continuous wave mode.
|
||||
*
|
||||
* \param [in] continuousWave A pointer to the function parameters.
|
||||
*/
|
||||
virtual void set_tx_cont_mode(ContinuousWaveParams_t* continuousWave );
|
||||
|
||||
/*!
|
||||
* \brief Computes a new datarate according to the given offset.
|
||||
*
|
||||
* \param [in] downlinkDwellTime The downlink dwell time configuration. 0: No limit, 1: 400ms
|
||||
*
|
||||
* \param [in] dr The current datarate.
|
||||
*
|
||||
* \param [in] drOffset The offset to be applied.
|
||||
*
|
||||
* \retval newDr The computed datarate.
|
||||
*/
|
||||
virtual uint8_t apply_DR_offset(uint8_t downlinkDwellTime, int8_t dr, int8_t drOffset );
|
||||
|
||||
private:
|
||||
uint8_t CountNbOfEnabledChannels( bool joined, uint8_t datarate, uint16_t* channelsMask, ChannelParams_t* channels, Band_t* bands, uint8_t* enabledChannels, uint8_t* delayTx );
|
||||
|
||||
// Global attributes
|
||||
/*!
|
||||
* LoRaMAC channels
|
||||
*/
|
||||
ChannelParams_t Channels[CN779_MAX_NB_CHANNELS];
|
||||
|
||||
/*!
|
||||
* LoRaMac bands
|
||||
*/
|
||||
Band_t Bands[CN779_MAX_NB_BANDS];
|
||||
|
||||
/*!
|
||||
* LoRaMac channels mask
|
||||
*/
|
||||
uint16_t ChannelsMask[CN779_CHANNELS_MASK_SIZE];
|
||||
|
||||
/*!
|
||||
* LoRaMac channels default mask
|
||||
*/
|
||||
uint16_t ChannelsDefaultMask[CN779_CHANNELS_MASK_SIZE];
|
||||
};
|
||||
|
||||
#endif /* MBED_OS_LORAPHY_CN779_H_ */
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,361 @@
|
|||
/**
|
||||
* @file LoRaPHYEU433.h
|
||||
*
|
||||
* @brief Implements LoRaPHY for European 433 MHz band
|
||||
*
|
||||
* \code
|
||||
* ______ _
|
||||
* / _____) _ | |
|
||||
* ( (____ _____ ____ _| |_ _____ ____| |__
|
||||
* \____ \| ___ | (_ _) ___ |/ ___) _ \
|
||||
* _____) ) ____| | | || |_| ____( (___| | | |
|
||||
* (______/|_____)_|_|_| \__)_____)\____)_| |_|
|
||||
* (C)2013 Semtech
|
||||
* ___ _____ _ ___ _ _____ ___ ___ ___ ___
|
||||
* / __|_ _/_\ / __| |/ / __/ _ \| _ \/ __| __|
|
||||
* \__ \ | |/ _ \ (__| ' <| _| (_) | / (__| _|
|
||||
* |___/ |_/_/ \_\___|_|\_\_| \___/|_|_\\___|___|
|
||||
* embedded.connectivity.solutions===============
|
||||
*
|
||||
* \endcode
|
||||
*
|
||||
*
|
||||
* License: Revised BSD License, see LICENSE.TXT file include in the project
|
||||
*
|
||||
* Maintainer: Miguel Luis ( Semtech ), Gregory Cristian ( Semtech ) and Daniel Jaeckle ( STACKFORCE )
|
||||
*
|
||||
* Copyright (c) 2017, Arm Limited and affiliates.
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef MBED_OS_LORAPHY_EU433_H_
|
||||
#define MBED_OS_LORAPHY_EU433_H_
|
||||
|
||||
#include "LoRaPHY.h"
|
||||
#include "netsocket/LoRaRadio.h"
|
||||
|
||||
/*!
|
||||
* LoRaMac maximum number of channels
|
||||
*/
|
||||
#define EU433_MAX_NB_CHANNELS 16
|
||||
|
||||
/*!
|
||||
* LoRaMac maximum number of bands
|
||||
*/
|
||||
#define EU433_MAX_NB_BANDS 1
|
||||
|
||||
#define EU433_CHANNELS_MASK_SIZE 1
|
||||
|
||||
|
||||
class LoRaPHYEU433 : public LoRaPHY {
|
||||
|
||||
public:
|
||||
|
||||
LoRaPHYEU433();
|
||||
virtual ~LoRaPHYEU433();
|
||||
|
||||
/*!
|
||||
* \brief The function gets a value of a specific PHY attribute.
|
||||
*
|
||||
* \param [in] getPhy A pointer to the function parameters.
|
||||
*
|
||||
* \retval The structure containing the PHY parameter.
|
||||
*/
|
||||
virtual PhyParam_t get_phy_params(GetPhyParams_t* getPhy );
|
||||
|
||||
/*!
|
||||
* \brief Updates the last TX done parameters of the current channel.
|
||||
*
|
||||
* \param [in] txDone A pointer to the function parameters.
|
||||
*/
|
||||
virtual void set_band_tx_done(SetBandTxDoneParams_t* txDone );
|
||||
|
||||
/*!
|
||||
* \brief Initializes the channels masks and the channels.
|
||||
*
|
||||
* \param [in] type Sets the initialization type.
|
||||
*/
|
||||
virtual void load_defaults(InitType_t type );
|
||||
|
||||
/*!
|
||||
* \brief Verifies a parameter.
|
||||
*
|
||||
* \param [in] verify A pointer to the function parameters.
|
||||
*
|
||||
* \param [in] phyAttribute The attribute to verify.
|
||||
*
|
||||
* \retval True, if the parameter is valid.
|
||||
*/
|
||||
virtual bool verify(VerifyParams_t* verify, PhyAttribute_t phyAttribute );
|
||||
|
||||
/*!
|
||||
* \brief The function parses the input buffer and sets up the channels of the CF list.
|
||||
*
|
||||
* \param [in] applyCFList A pointer to the function parameters.
|
||||
*/
|
||||
virtual void apply_cf_list(ApplyCFListParams_t* applyCFList );
|
||||
|
||||
/*!
|
||||
* \brief Sets a channels mask.
|
||||
*
|
||||
* \param [in] chanMaskSet A pointer to the function parameters.
|
||||
*
|
||||
* \retval True, if the channels mask could be set.
|
||||
*/
|
||||
virtual bool set_channel_mask(ChanMaskSetParams_t* chanMaskSet );
|
||||
|
||||
/*!
|
||||
* \brief Calculates the next datarate to set, when ADR is on or off.
|
||||
*
|
||||
* \param [in] adrNext A pointer to the function parameters.
|
||||
*
|
||||
* \param [out] drOut The calculated datarate for the next TX.
|
||||
*
|
||||
* \param [out] txPowOut The TX power for the next TX.
|
||||
*
|
||||
* \param [out] adrAckCounter The calculated ADR acknowledgement counter.
|
||||
*
|
||||
* \retval True, if an ADR request should be performed.
|
||||
*/
|
||||
virtual bool get_next_ADR(AdrNextParams_t* adrNext, int8_t* drOut,
|
||||
int8_t* txPowOut, uint32_t* adrAckCounter );
|
||||
|
||||
/*!
|
||||
* \brief Configuration of the RX windows.
|
||||
*
|
||||
* \param [in] rxConfig A pointer to the function parameters.
|
||||
*
|
||||
* \param [out] datarate The datarate index set.
|
||||
*
|
||||
* \retval True, if the configuration was applied successfully.
|
||||
*/
|
||||
virtual bool rx_config(RxConfigParams_t* rxConfig, int8_t* datarate );
|
||||
|
||||
/*
|
||||
* RX window precise timing
|
||||
*
|
||||
* For more details please consult the following document, chapter 3.1.2.
|
||||
* http://www.semtech.com/images/datasheet/SX1272_settings_for_LoRaWAN_v2.0.pdf
|
||||
* or
|
||||
* http://www.semtech.com/images/datasheet/SX1276_settings_for_LoRaWAN_v2.0.pdf
|
||||
*
|
||||
* Downlink start: T = Tx + 1s (+/- 20 us)
|
||||
* |
|
||||
* TRxEarly | TRxLate
|
||||
* | | |
|
||||
* | | +---+---+---+---+---+---+---+---+
|
||||
* | | | Latest Rx window |
|
||||
* | | +---+---+---+---+---+---+---+---+
|
||||
* | | |
|
||||
* +---+---+---+---+---+---+---+---+
|
||||
* | Earliest Rx window |
|
||||
* +---+---+---+---+---+---+---+---+
|
||||
* |
|
||||
* +---+---+---+---+---+---+---+---+
|
||||
*Downlink preamble 8 symbols | | | | | | | | |
|
||||
* +---+---+---+---+---+---+---+---+
|
||||
*
|
||||
* Worst case Rx window timings
|
||||
*
|
||||
* TRxLate = DEFAULT_MIN_RX_SYMBOLS * tSymbol - RADIO_WAKEUP_TIME
|
||||
* TRxEarly = 8 - DEFAULT_MIN_RX_SYMBOLS * tSymbol - RxWindowTimeout - RADIO_WAKEUP_TIME
|
||||
*
|
||||
* TRxLate - TRxEarly = 2 * DEFAULT_SYSTEM_MAX_RX_ERROR
|
||||
*
|
||||
* RxOffset = ( TRxLate + TRxEarly ) / 2
|
||||
*
|
||||
* RxWindowTimeout = ( 2 * DEFAULT_MIN_RX_SYMBOLS - 8 ) * tSymbol + 2 * DEFAULT_SYSTEM_MAX_RX_ERROR
|
||||
* RxOffset = 4 * tSymbol - RxWindowTimeout / 2 - RADIO_WAKE_UP_TIME
|
||||
*
|
||||
* The minimum value of RxWindowTimeout must be 5 symbols which implies that the system always tolerates at least an error of 1.5 * tSymbol
|
||||
*/
|
||||
/*!
|
||||
* Computes the RX window timeout and offset.
|
||||
*
|
||||
* \param [in] datarate The RX window datarate index to be used.
|
||||
*
|
||||
* \param [in] minRxSymbols The minimum number of symbols required to detect an RX frame.
|
||||
*
|
||||
* \param [in] rxError The system maximum timing error of the receiver in milliseconds.
|
||||
* The receiver will turn on in a [-rxError : +rxError] ms
|
||||
* interval around RxOffset.
|
||||
*
|
||||
* \param [out] rxConfigParams Returns the updated WindowTimeout and WindowOffset fields.
|
||||
*/
|
||||
virtual void compute_rx_win_params(int8_t datarate,
|
||||
uint8_t minRxSymbols,
|
||||
uint32_t rxError,
|
||||
RxConfigParams_t *rxConfigParams);
|
||||
|
||||
/*!
|
||||
* \brief TX configuration.
|
||||
*
|
||||
* \param [in] txConfig A pointer to the function parameters.
|
||||
*
|
||||
* \param [out] txPower The TX power index set.
|
||||
*
|
||||
* \param [out] txTimeOnAir The time-on-air of the frame.
|
||||
*
|
||||
* \retval True, if the configuration was applied successfully.
|
||||
*/
|
||||
virtual bool tx_config(TxConfigParams_t* txConfig, int8_t* txPower,
|
||||
TimerTime_t* txTimeOnAir );
|
||||
|
||||
/*!
|
||||
* \brief The function processes a Link ADR request.
|
||||
*
|
||||
* \param [in] linkAdrReq A pointer to the function parameters.
|
||||
*
|
||||
* \param [out] drOut The datarate applied.
|
||||
*
|
||||
* \param [out] txPowOut The TX power applied.
|
||||
*
|
||||
* \param [out] nbRepOut The number of repetitions to apply.
|
||||
*
|
||||
* \param [out] nbBytesParsed The number of bytes parsed.
|
||||
*
|
||||
* \retval The status of the operation, according to the LoRaMAC specification.
|
||||
*/
|
||||
virtual uint8_t link_ADR_request(LinkAdrReqParams_t* linkAdrReq,
|
||||
int8_t* drOut, int8_t* txPowOut,
|
||||
uint8_t* nbRepOut,
|
||||
uint8_t* nbBytesParsed );
|
||||
|
||||
/*!
|
||||
* \brief The function processes a RX parameter setup request.
|
||||
*
|
||||
* \param [in] rxParamSetupReq A pointer to the function parameters.
|
||||
*
|
||||
* \retval The status of the operation, according to the LoRaMAC specification.
|
||||
*/
|
||||
virtual uint8_t setup_rx_params(RxParamSetupReqParams_t* rxParamSetupReq );
|
||||
|
||||
/*!
|
||||
* \brief The function processes a new channel request.
|
||||
*
|
||||
* \param [in] newChannelReq A pointer to the function parameters.
|
||||
*
|
||||
* \retval The status of the operation, according to the LoRaMAC specification.
|
||||
*/
|
||||
virtual uint8_t request_new_channel(NewChannelReqParams_t* newChannelReq );
|
||||
|
||||
/*!
|
||||
* \brief The function processes a TX ParamSetup request.
|
||||
*
|
||||
* \param [in] txParamSetupReq A pointer to the function parameters.
|
||||
*
|
||||
* \retval The status of the operation, according to the LoRaMAC specification.
|
||||
* Returns -1, if the functionality is not implemented. In this case, the end node
|
||||
* shall ignore the command.
|
||||
*/
|
||||
virtual int8_t setup_tx_params(TxParamSetupReqParams_t* txParamSetupReq );
|
||||
|
||||
/*!
|
||||
* \brief The function processes a DlChannel request.
|
||||
*
|
||||
* \param [in] dlChannelReq A pointer to the function parameters.
|
||||
*
|
||||
* \retval The status of the operation, according to the LoRaMAC specification.
|
||||
*/
|
||||
virtual uint8_t dl_channel_request(DlChannelReqParams_t* dlChannelReq );
|
||||
|
||||
/*!
|
||||
* \brief Alternates the datarate of the channel for the join request.
|
||||
*
|
||||
* \param [in] alternateDr A pointer to the function parameters.
|
||||
*
|
||||
* \retval The datarate to apply.
|
||||
*/
|
||||
virtual int8_t get_alternate_DR(AlternateDrParams_t* alternateDr );
|
||||
|
||||
/*!
|
||||
* \brief Calculates the back-off time.
|
||||
*
|
||||
* \param [in] calcBackOff A pointer to the function parameters.
|
||||
*/
|
||||
virtual void calculate_backoff(CalcBackOffParams_t* calcBackOff );
|
||||
|
||||
/*!
|
||||
* \brief Searches and sets the next random available channel.
|
||||
*
|
||||
* \param [in] nextChanParams The parameters for the next channel
|
||||
*
|
||||
* \param [out] channel The next channel to use for TX.
|
||||
*
|
||||
* \param [out] time The time to wait for the next transmission according to the duty
|
||||
* cycle.
|
||||
*
|
||||
* \param [out] aggregatedTimeOff Updates the aggregated time off.
|
||||
*
|
||||
* \retval Function status [1: OK, 0: Unable to find a channel on the current datarate].
|
||||
*/
|
||||
virtual bool set_next_channel(NextChanParams_t* nextChanParams,
|
||||
uint8_t* channel, TimerTime_t* time,
|
||||
TimerTime_t* aggregatedTimeOff );
|
||||
|
||||
/*!
|
||||
* \brief Adds a channel.
|
||||
*
|
||||
* \param [in] channelAdd A pointer to the function parameters.
|
||||
*
|
||||
* \retval The status of the operation.
|
||||
*/
|
||||
virtual LoRaMacStatus_t add_channel(ChannelAddParams_t* channelAdd );
|
||||
|
||||
/*!
|
||||
* \brief Removes a channel.
|
||||
*
|
||||
* \param [in] channelRemove A pointer to the function parameters.
|
||||
*
|
||||
* \retval True, if the channel was removed successfully.
|
||||
*/
|
||||
virtual bool remove_channel(ChannelRemoveParams_t* channelRemove );
|
||||
|
||||
/*!
|
||||
* \brief Sets the radio into continuous wave mode.
|
||||
*
|
||||
* \param [in] continuousWave A pointer to the function parameters.
|
||||
*/
|
||||
virtual void set_tx_cont_mode(ContinuousWaveParams_t* continuousWave );
|
||||
|
||||
/*!
|
||||
* \brief Computes new datarate according to the given offset.
|
||||
*
|
||||
* \param [in] downlinkDwellTime The downlink dwell time configuration. 0: No limit, 1: 400ms
|
||||
*
|
||||
* \param [in] dr The current datarate.
|
||||
*
|
||||
* \param [in] drOffset The offset to be applied.
|
||||
*
|
||||
* \retval newDr The computed datarate.
|
||||
*/
|
||||
virtual uint8_t apply_DR_offset(uint8_t downlinkDwellTime, int8_t dr, int8_t drOffset );
|
||||
|
||||
private:
|
||||
uint8_t CountNbOfEnabledChannels( bool joined, uint8_t datarate, uint16_t* channelsMask, ChannelParams_t* channels, Band_t* bands, uint8_t* enabledChannels, uint8_t* delayTx );
|
||||
|
||||
// Global attributes
|
||||
/*!
|
||||
* LoRaMAC channels
|
||||
*/
|
||||
ChannelParams_t Channels[EU433_MAX_NB_CHANNELS];
|
||||
|
||||
/*!
|
||||
* LoRaMac bands
|
||||
*/
|
||||
Band_t Bands[EU433_MAX_NB_BANDS];
|
||||
|
||||
/*!
|
||||
* LoRaMac channels mask
|
||||
*/
|
||||
uint16_t ChannelsMask[EU433_CHANNELS_MASK_SIZE];
|
||||
|
||||
/*!
|
||||
* LoRaMac channels default mask
|
||||
*/
|
||||
uint16_t ChannelsDefaultMask[EU433_CHANNELS_MASK_SIZE];
|
||||
};
|
||||
|
||||
|
||||
#endif /* MBED_OS_LORAPHY_EU433_H_ */
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,358 @@
|
|||
/**
|
||||
* @file LoRaPHYEU868.h
|
||||
*
|
||||
* @brief Implements LoRaPHY for European 868 MHz band
|
||||
*
|
||||
* \code
|
||||
* ______ _
|
||||
* / _____) _ | |
|
||||
* ( (____ _____ ____ _| |_ _____ ____| |__
|
||||
* \____ \| ___ | (_ _) ___ |/ ___) _ \
|
||||
* _____) ) ____| | | || |_| ____( (___| | | |
|
||||
* (______/|_____)_|_|_| \__)_____)\____)_| |_|
|
||||
* (C)2013 Semtech
|
||||
* ___ _____ _ ___ _ _____ ___ ___ ___ ___
|
||||
* / __|_ _/_\ / __| |/ / __/ _ \| _ \/ __| __|
|
||||
* \__ \ | |/ _ \ (__| ' <| _| (_) | / (__| _|
|
||||
* |___/ |_/_/ \_\___|_|\_\_| \___/|_|_\\___|___|
|
||||
* embedded.connectivity.solutions===============
|
||||
*
|
||||
* \endcode
|
||||
*
|
||||
*
|
||||
* License: Revised BSD License, see LICENSE.TXT file include in the project
|
||||
*
|
||||
* Maintainer: Miguel Luis ( Semtech ), Gregory Cristian ( Semtech ) and Daniel Jaeckle ( STACKFORCE )
|
||||
*
|
||||
* Copyright (c) 2017, Arm Limited and affiliates.
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef MBED_OS_LORAPHY_EU868_H_
|
||||
#define MBED_OS_LORAPHY_EU868_H_
|
||||
|
||||
#include "LoRaPHY.h"
|
||||
#include "netsocket/LoRaRadio.h"
|
||||
|
||||
/*!
|
||||
* LoRaMac maximum number of channels
|
||||
*/
|
||||
#define EU868_MAX_NB_CHANNELS 16
|
||||
|
||||
/*!
|
||||
* Maximum number of bands
|
||||
*/
|
||||
#define EU868_MAX_NB_BANDS 5
|
||||
|
||||
#define EU868_CHANNELS_MASK_SIZE 1
|
||||
|
||||
|
||||
class LoRaPHYEU868 : public LoRaPHY {
|
||||
|
||||
public:
|
||||
LoRaPHYEU868();
|
||||
virtual ~LoRaPHYEU868();
|
||||
|
||||
/*!
|
||||
* \brief The function gets a value of a specific PHY attribute.
|
||||
*
|
||||
* \param [in] getPhy A pointer to the function parameters.
|
||||
*
|
||||
* \retval The structure containing the PHY parameter.
|
||||
*/
|
||||
virtual PhyParam_t get_phy_params(GetPhyParams_t* getPhy );
|
||||
|
||||
/*!
|
||||
* \brief Updates the last TX done parameters of the current channel.
|
||||
*
|
||||
* \param [in] txDone A pointer to the function parameters.
|
||||
*/
|
||||
virtual void set_band_tx_done(SetBandTxDoneParams_t* txDone );
|
||||
|
||||
/*!
|
||||
* \brief Initializes the channels masks and the channels.
|
||||
*
|
||||
* \param [in] type Sets the initialization type.
|
||||
*/
|
||||
virtual void load_defaults(InitType_t type );
|
||||
|
||||
/*!
|
||||
* \brief Verifies a parameter.
|
||||
*
|
||||
* \param [in] verify A pointer to the function parameters.
|
||||
*
|
||||
* \param [in] phyAttribute The attribute to verify.
|
||||
*
|
||||
* \retval True, if the parameter is valid.
|
||||
*/
|
||||
virtual bool verify(VerifyParams_t* verify, PhyAttribute_t phyAttribute );
|
||||
|
||||
/*!
|
||||
* \brief The function parses the input buffer and sets up the channels of the CF list.
|
||||
*
|
||||
* \param [in] applyCFList A pointer to the function parameters.
|
||||
*/
|
||||
virtual void apply_cf_list(ApplyCFListParams_t* applyCFList );
|
||||
|
||||
/*!
|
||||
* \brief Sets a channels mask.
|
||||
*
|
||||
* \param [in] chanMaskSet A pointer to the function parameters.
|
||||
*
|
||||
* \retval True, if the channels mask could be set.
|
||||
*/
|
||||
virtual bool set_channel_mask(ChanMaskSetParams_t* chanMaskSet );
|
||||
|
||||
/*!
|
||||
* \brief Calculates the next datarate to set, when ADR is on or off.
|
||||
*
|
||||
* \param [in] adrNext A pointer to the function parameters.
|
||||
*
|
||||
* \param [out] drOut The calculated datarate for the next TX.
|
||||
*
|
||||
* \param [out] txPowOut The TX power for the next TX.
|
||||
*
|
||||
* \param [out] adrAckCounter The calculated ADR acknowledgement counter.
|
||||
*
|
||||
* \retval True, if an ADR request should be performed.
|
||||
*/
|
||||
virtual bool get_next_ADR(AdrNextParams_t* adrNext, int8_t* drOut,
|
||||
int8_t* txPowOut, uint32_t* adrAckCounter );
|
||||
|
||||
/*!
|
||||
* \brief Configuration of the RX windows.
|
||||
*
|
||||
* \param [in] rxConfig A pointer to the function parameters.
|
||||
*
|
||||
* \param [out] datarate The datarate index set.
|
||||
*
|
||||
* \retval True, if the configuration was applied successfully.
|
||||
*/
|
||||
virtual bool rx_config(RxConfigParams_t* rxConfig, int8_t* datarate );
|
||||
|
||||
/*
|
||||
* RX window precise timing
|
||||
*
|
||||
* For more details please consult the following document, chapter 3.1.2.
|
||||
* http://www.semtech.com/images/datasheet/SX1272_settings_for_LoRaWAN_v2.0.pdf
|
||||
* or
|
||||
* http://www.semtech.com/images/datasheet/SX1276_settings_for_LoRaWAN_v2.0.pdf
|
||||
*
|
||||
* Downlink start: T = Tx + 1s (+/- 20 us)
|
||||
* |
|
||||
* TRxEarly | TRxLate
|
||||
* | | |
|
||||
* | | +---+---+---+---+---+---+---+---+
|
||||
* | | | Latest Rx window |
|
||||
* | | +---+---+---+---+---+---+---+---+
|
||||
* | | |
|
||||
* +---+---+---+---+---+---+---+---+
|
||||
* | Earliest Rx window |
|
||||
* +---+---+---+---+---+---+---+---+
|
||||
* |
|
||||
* +---+---+---+---+---+---+---+---+
|
||||
*Downlink preamble 8 symbols | | | | | | | | |
|
||||
* +---+---+---+---+---+---+---+---+
|
||||
*
|
||||
* Worst case Rx window timings
|
||||
*
|
||||
* TRxLate = DEFAULT_MIN_RX_SYMBOLS * tSymbol - RADIO_WAKEUP_TIME
|
||||
* TRxEarly = 8 - DEFAULT_MIN_RX_SYMBOLS * tSymbol - RxWindowTimeout - RADIO_WAKEUP_TIME
|
||||
*
|
||||
* TRxLate - TRxEarly = 2 * DEFAULT_SYSTEM_MAX_RX_ERROR
|
||||
*
|
||||
* RxOffset = ( TRxLate + TRxEarly ) / 2
|
||||
*
|
||||
* RxWindowTimeout = ( 2 * DEFAULT_MIN_RX_SYMBOLS - 8 ) * tSymbol + 2 * DEFAULT_SYSTEM_MAX_RX_ERROR
|
||||
* RxOffset = 4 * tSymbol - RxWindowTimeout / 2 - RADIO_WAKE_UP_TIME
|
||||
*
|
||||
* The minimum value of RxWindowTimeout must be 5 symbols which implies that the system always tolerates at least an error of 1.5 * tSymbol
|
||||
*/
|
||||
/*!
|
||||
* Computes the RX window timeout and offset.
|
||||
*
|
||||
* \param [in] datarate The RX window datarate index to be used.
|
||||
*
|
||||
* \param [in] minRxSymbols The minimum number of symbols required to detect an RX frame.
|
||||
*
|
||||
* \param [in] rxError The system maximum timing error of the receiver in milliseconds.
|
||||
* The receiver will turn on in a [-rxError : +rxError] ms
|
||||
* interval around RxOffset.
|
||||
*
|
||||
* \param [out] rxConfigParams Returns the updated WindowTimeout and WindowOffset fields.
|
||||
*/
|
||||
virtual void compute_rx_win_params(int8_t datarate,
|
||||
uint8_t minRxSymbols,
|
||||
uint32_t rxError,
|
||||
RxConfigParams_t *rxConfigParams);
|
||||
|
||||
/*!
|
||||
* \brief TX configuration.
|
||||
*
|
||||
* \param [in] txConfig A pointer to the function parameters.
|
||||
*
|
||||
* \param [out] txPower The TX power index set.
|
||||
*
|
||||
* \param [out] txTimeOnAir The time-on-air of the frame.
|
||||
*
|
||||
* \retval True, if the configuration was applied successfully.
|
||||
*/
|
||||
virtual bool tx_config(TxConfigParams_t* txConfig, int8_t* txPower,
|
||||
TimerTime_t* txTimeOnAir );
|
||||
|
||||
/*!
|
||||
* \brief The function processes a Link ADR request.
|
||||
*
|
||||
* \param [in] linkAdrReq A pointer to the function parameters.
|
||||
*
|
||||
* \param [out] drOut The datarate applied.
|
||||
*
|
||||
* \param [out] txPowOut The TX power applied.
|
||||
*
|
||||
* \param [out] nbRepOut The number of repetitions to apply.
|
||||
*
|
||||
* \param [out] nbBytesParsed The number of bytes parsed.
|
||||
*
|
||||
* \retval The status of the operation, according to the LoRaMAC specification.
|
||||
*/
|
||||
virtual uint8_t link_ADR_request(LinkAdrReqParams_t* linkAdrReq,
|
||||
int8_t* drOut, int8_t* txPowOut,
|
||||
uint8_t* nbRepOut,
|
||||
uint8_t* nbBytesParsed );
|
||||
|
||||
/*!
|
||||
* \brief The function processes a RX parameter setup request.
|
||||
*
|
||||
* \param [in] rxParamSetupReq A pointer to the function parameters.
|
||||
*
|
||||
* \retval The status of the operation, according to the LoRaMAC specification.
|
||||
*/
|
||||
virtual uint8_t setup_rx_params(RxParamSetupReqParams_t* rxParamSetupReq );
|
||||
|
||||
/*!
|
||||
* \brief The function processes a new channel request.
|
||||
*
|
||||
* \param [in] newChannelReq A pointer to the function parameters.
|
||||
*
|
||||
* \retval The status of the operation, according to the LoRaMAC specification.
|
||||
*/
|
||||
virtual uint8_t request_new_channel(NewChannelReqParams_t* newChannelReq );
|
||||
|
||||
/*!
|
||||
* \brief The function processes a TX ParamSetup request.
|
||||
*
|
||||
* \param [in] txParamSetupReq A pointer to the function parameters.
|
||||
*
|
||||
* \retval The status of the operation, according to the LoRaMAC specification.
|
||||
* Returns -1, if the functionality is not implemented. In this case, the end node
|
||||
* shall ignore the command.
|
||||
*/
|
||||
virtual int8_t setup_tx_params(TxParamSetupReqParams_t* txParamSetupReq );
|
||||
|
||||
/*!
|
||||
* \brief The function processes a DlChannel request.
|
||||
*
|
||||
* \param [in] dlChannelReq A pointer to the function parameters.
|
||||
*
|
||||
* \retval The status of the operation, according to the LoRaMAC specification.
|
||||
*/
|
||||
virtual uint8_t dl_channel_request(DlChannelReqParams_t* dlChannelReq );
|
||||
|
||||
/*!
|
||||
* \brief Alternates the datarate of the channel for the join request.
|
||||
*
|
||||
* \param [in] alternateDr A pointer to the function parameters.
|
||||
*
|
||||
* \retval The datarate to apply.
|
||||
*/
|
||||
virtual int8_t get_alternate_DR(AlternateDrParams_t* alternateDr );
|
||||
|
||||
/*!
|
||||
* \brief Calculates the back-off time.
|
||||
*
|
||||
* \param [in] calcBackOff A pointer to the function parameters.
|
||||
*/
|
||||
virtual void calculate_backoff(CalcBackOffParams_t* calcBackOff );
|
||||
|
||||
/*!
|
||||
* \brief Searches and sets the next random available channel.
|
||||
*
|
||||
* \param [in] nextChanParams The parameters for the next channel.
|
||||
*
|
||||
* \param [out] channel The next channel to use for TX.
|
||||
*
|
||||
* \param [out] time The time to wait for the next transmission according to the duty cycle.
|
||||
*
|
||||
* \param [out] aggregatedTimeOff Updates the aggregated time off.
|
||||
*
|
||||
* \retval The function status [1: OK, 0: Unable to find a channel on the current datarate].
|
||||
*/
|
||||
virtual bool set_next_channel(NextChanParams_t* nextChanParams,
|
||||
uint8_t* channel, TimerTime_t* time,
|
||||
TimerTime_t* aggregatedTimeOff );
|
||||
|
||||
/*!
|
||||
* \brief Adds a channel.
|
||||
*
|
||||
* \param [in] channelAdd A pointer to the function parameters.
|
||||
*
|
||||
* \retval The status of the operation.
|
||||
*/
|
||||
virtual LoRaMacStatus_t add_channel(ChannelAddParams_t* channelAdd );
|
||||
|
||||
/*!
|
||||
* \brief Removes a channel.
|
||||
*
|
||||
* \param [in] channelRemove A pointer to the function parameters.
|
||||
*
|
||||
* \retval True, if the channel was removed successfully.
|
||||
*/
|
||||
virtual bool remove_channel(ChannelRemoveParams_t* channelRemove );
|
||||
|
||||
/*!
|
||||
* \brief Sets the radio into continuous wave mode.
|
||||
*
|
||||
* \param [in] continuousWave A pointer to the function parameters.
|
||||
*/
|
||||
virtual void set_tx_cont_mode(ContinuousWaveParams_t* continuousWave );
|
||||
|
||||
/*!
|
||||
* \brief Computes a new datarate according to the given offset.
|
||||
*
|
||||
* \param [in] downlinkDwellTime The downlink dwell time configuration. 0: No limit, 1: 400ms
|
||||
*
|
||||
* \param [in] dr The current datarate.
|
||||
*
|
||||
* \param [in] drOffset The offset to be applied.
|
||||
*
|
||||
* \retval newDr The computed datarate.
|
||||
*/
|
||||
virtual uint8_t apply_DR_offset(uint8_t downlinkDwellTime, int8_t dr, int8_t drOffset );
|
||||
|
||||
private:
|
||||
uint8_t CountNbOfEnabledChannels( bool joined, uint8_t datarate, uint16_t* channelsMask, ChannelParams_t* channels, Band_t* bands, uint8_t* enabledChannels, uint8_t* delayTx );
|
||||
|
||||
// Global attributes
|
||||
/*!
|
||||
* LoRaMAC channels
|
||||
*/
|
||||
ChannelParams_t Channels[EU868_MAX_NB_CHANNELS];
|
||||
|
||||
/*!
|
||||
* LoRaMac bands
|
||||
*/
|
||||
Band_t Bands[EU868_MAX_NB_BANDS];
|
||||
|
||||
/*!
|
||||
* LoRaMac channels mask
|
||||
*/
|
||||
uint16_t ChannelsMask[EU868_CHANNELS_MASK_SIZE];
|
||||
|
||||
/*!
|
||||
* LoRaMac channels default mask
|
||||
*/
|
||||
uint16_t ChannelsDefaultMask[EU868_CHANNELS_MASK_SIZE];
|
||||
};
|
||||
|
||||
#endif /* MBED_OS_LORAPHY_EU868_H_ */
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,361 @@
|
|||
/**
|
||||
* @file LoRaPHYIN865.h
|
||||
*
|
||||
* @brief Implements LoRaPHY for Indian 865 MHz band
|
||||
*
|
||||
* \code
|
||||
* ______ _
|
||||
* / _____) _ | |
|
||||
* ( (____ _____ ____ _| |_ _____ ____| |__
|
||||
* \____ \| ___ | (_ _) ___ |/ ___) _ \
|
||||
* _____) ) ____| | | || |_| ____( (___| | | |
|
||||
* (______/|_____)_|_|_| \__)_____)\____)_| |_|
|
||||
* (C)2013 Semtech
|
||||
* ___ _____ _ ___ _ _____ ___ ___ ___ ___
|
||||
* / __|_ _/_\ / __| |/ / __/ _ \| _ \/ __| __|
|
||||
* \__ \ | |/ _ \ (__| ' <| _| (_) | / (__| _|
|
||||
* |___/ |_/_/ \_\___|_|\_\_| \___/|_|_\\___|___|
|
||||
* embedded.connectivity.solutions===============
|
||||
*
|
||||
* \endcode
|
||||
*
|
||||
*
|
||||
* License: Revised BSD License, see LICENSE.TXT file include in the project
|
||||
*
|
||||
* Maintainer: Miguel Luis ( Semtech ), Gregory Cristian ( Semtech ) and Daniel Jaeckle ( STACKFORCE )
|
||||
*
|
||||
* Copyright (c) 2017, Arm Limited and affiliates.
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef MBED_OS_LORAPHY_IN865_H_
|
||||
#define MBED_OS_LORAPHY_IN865_H_
|
||||
|
||||
#include "LoRaPHY.h"
|
||||
#include "netsocket/LoRaRadio.h"
|
||||
|
||||
|
||||
/*!
|
||||
* LoRaMac maximum number of channels
|
||||
*/
|
||||
#define IN865_MAX_NB_CHANNELS 16
|
||||
|
||||
/*!
|
||||
* Maximum number of bands
|
||||
*/
|
||||
#define IN865_MAX_NB_BANDS 1
|
||||
|
||||
|
||||
#define IN865_CHANNELS_MASK_SIZE 1
|
||||
|
||||
|
||||
class LoRaPHYIN865 : public LoRaPHY {
|
||||
|
||||
public:
|
||||
|
||||
LoRaPHYIN865();
|
||||
virtual ~LoRaPHYIN865();
|
||||
|
||||
/*!
|
||||
* \brief The function gets a value of a specific PHY attribute.
|
||||
*
|
||||
* \param [in] getPhy A pointer to the function parameters.
|
||||
*
|
||||
* \retval The structure containing the PHY parameter.
|
||||
*/
|
||||
virtual PhyParam_t get_phy_params(GetPhyParams_t* getPhy );
|
||||
|
||||
/*!
|
||||
* \brief Updates the last TX done parameters of the current channel.
|
||||
*
|
||||
* \param [in] txDone A pointer to the function parameters.
|
||||
*/
|
||||
virtual void set_band_tx_done(SetBandTxDoneParams_t* txDone );
|
||||
|
||||
/*!
|
||||
* \brief Initializes the channels masks and the channels.
|
||||
*
|
||||
* \param [in] type Sets the initialization type.
|
||||
*/
|
||||
virtual void load_defaults(InitType_t type );
|
||||
|
||||
/*!
|
||||
* \brief Verifies a parameter.
|
||||
*
|
||||
* \param [in] verify A pointer to the function parameters.
|
||||
*
|
||||
* \param [in] phyAttribute The attribute to verify.
|
||||
*
|
||||
* \retval True, if the parameter is valid.
|
||||
*/
|
||||
virtual bool verify(VerifyParams_t* verify, PhyAttribute_t phyAttribute );
|
||||
|
||||
/*!
|
||||
* \brief The function parses the input buffer and sets up the channels of the CF list.
|
||||
*
|
||||
* \param [in] applyCFList A pointer to the function parameters.
|
||||
*/
|
||||
virtual void apply_cf_list(ApplyCFListParams_t* applyCFList );
|
||||
|
||||
/*!
|
||||
* \brief Sets a channels mask.
|
||||
*
|
||||
* \param [in] chanMaskSet A pointer to the function parameters.
|
||||
*
|
||||
* \retval True, if the channels mask could be set.
|
||||
*/
|
||||
virtual bool set_channel_mask(ChanMaskSetParams_t* chanMaskSet );
|
||||
|
||||
/*!
|
||||
* \brief Calculates the next datarate to set, when ADR is on or off.
|
||||
*
|
||||
* \param [in] adrNext A pointer to the function parameters.
|
||||
*
|
||||
* \param [out] drOut The calculated datarate for the next TX.
|
||||
*
|
||||
* \param [out] txPowOut The TX power for the next TX.
|
||||
*
|
||||
* \param [out] adrAckCounter The calculated ADR acknowledgement counter.
|
||||
*
|
||||
* \retval True, if an ADR request should be performed.
|
||||
*/
|
||||
virtual bool get_next_ADR(AdrNextParams_t* adrNext, int8_t* drOut,
|
||||
int8_t* txPowOut, uint32_t* adrAckCounter );
|
||||
|
||||
/*!
|
||||
* \brief Configuration of the RX windows.
|
||||
*
|
||||
* \param [in] rxConfig A pointer to the function parameters.
|
||||
*
|
||||
* \param [out] datarate The datarate index set.
|
||||
*
|
||||
* \retval True, if the configuration was applied successfully.
|
||||
*/
|
||||
virtual bool rx_config(RxConfigParams_t* rxConfig, int8_t* datarate );
|
||||
|
||||
/*
|
||||
* RX window precise timing
|
||||
*
|
||||
* For more details, please consult the following document, chapter 3.1.2.
|
||||
* http://www.semtech.com/images/datasheet/SX1272_settings_for_LoRaWAN_v2.0.pdf
|
||||
* or
|
||||
* http://www.semtech.com/images/datasheet/SX1276_settings_for_LoRaWAN_v2.0.pdf
|
||||
*
|
||||
* Downlink start: T = Tx + 1s (+/- 20 us)
|
||||
* |
|
||||
* TRxEarly | TRxLate
|
||||
* | | |
|
||||
* | | +---+---+---+---+---+---+---+---+
|
||||
* | | | Latest Rx window |
|
||||
* | | +---+---+---+---+---+---+---+---+
|
||||
* | | |
|
||||
* +---+---+---+---+---+---+---+---+
|
||||
* | Earliest Rx window |
|
||||
* +---+---+---+---+---+---+---+---+
|
||||
* |
|
||||
* +---+---+---+---+---+---+---+---+
|
||||
*Downlink preamble 8 symbols | | | | | | | | |
|
||||
* +---+---+---+---+---+---+---+---+
|
||||
*
|
||||
* Worst case Rx window timings
|
||||
*
|
||||
* TRxLate = DEFAULT_MIN_RX_SYMBOLS * tSymbol - RADIO_WAKEUP_TIME
|
||||
* TRxEarly = 8 - DEFAULT_MIN_RX_SYMBOLS * tSymbol - RxWindowTimeout - RADIO_WAKEUP_TIME
|
||||
*
|
||||
* TRxLate - TRxEarly = 2 * DEFAULT_SYSTEM_MAX_RX_ERROR
|
||||
*
|
||||
* RxOffset = ( TRxLate + TRxEarly ) / 2
|
||||
*
|
||||
* RxWindowTimeout = ( 2 * DEFAULT_MIN_RX_SYMBOLS - 8 ) * tSymbol + 2 * DEFAULT_SYSTEM_MAX_RX_ERROR
|
||||
* RxOffset = 4 * tSymbol - RxWindowTimeout / 2 - RADIO_WAKE_UP_TIME
|
||||
*
|
||||
* The minimum value of RxWindowTimeout must be 5 symbols which implies that the system always tolerates at least an error of 1.5 * tSymbol
|
||||
*/
|
||||
/*!
|
||||
* Computes the RX window timeout and offset.
|
||||
*
|
||||
* \param [in] datarate The RX window datarate index to be used.
|
||||
*
|
||||
* \param [in] minRxSymbols The minimum number of symbols required to detect an RX frame.
|
||||
*
|
||||
* \param [in] rxError The system maximum timing error of the receiver in milliseconds.
|
||||
* The receiver will turn on in a [-rxError : +rxError] ms
|
||||
* interval around RxOffset.
|
||||
*
|
||||
* \param [out] rxConfigParams Returns the updated WindowTimeout and WindowOffset fields.
|
||||
*/
|
||||
virtual void compute_rx_win_params(int8_t datarate,
|
||||
uint8_t minRxSymbols,
|
||||
uint32_t rxError,
|
||||
RxConfigParams_t *rxConfigParams);
|
||||
|
||||
/*!
|
||||
* \brief TX configuration.
|
||||
*
|
||||
* \param [in] txConfig A pointer to the function parameters.
|
||||
*
|
||||
* \param [out] txPower The TX power index set.
|
||||
*
|
||||
* \param [out] txTimeOnAir The time-on-air of the frame.
|
||||
*
|
||||
* \retval True, if the configuration was applied successfully.
|
||||
*/
|
||||
virtual bool tx_config(TxConfigParams_t* txConfig, int8_t* txPower,
|
||||
TimerTime_t* txTimeOnAir );
|
||||
|
||||
/*!
|
||||
* \brief The function processes a Link ADR request.
|
||||
*
|
||||
* \param [in] linkAdrReq A pointer to the function parameters.
|
||||
*
|
||||
* \param [out] drOut The datarate applied.
|
||||
*
|
||||
* \param [out] txPowOut The TX power applied.
|
||||
*
|
||||
* \param [out] nbRepOut The number of repetitions to apply.
|
||||
*
|
||||
* \param [out] nbBytesParsed The number of bytes parsed.
|
||||
*
|
||||
* \retval The status of the operation, according to the LoRaMAC specification.
|
||||
*/
|
||||
virtual uint8_t link_ADR_request(LinkAdrReqParams_t* linkAdrReq,
|
||||
int8_t* drOut, int8_t* txPowOut,
|
||||
uint8_t* nbRepOut,
|
||||
uint8_t* nbBytesParsed );
|
||||
|
||||
/*!
|
||||
* \brief The function processes a RX parameter setup request.
|
||||
*
|
||||
* \param [in] rxParamSetupReq A pointer to the function parameters.
|
||||
*
|
||||
* \retval The status of the operation, according to the LoRaMAC specification.
|
||||
*/
|
||||
virtual uint8_t setup_rx_params(RxParamSetupReqParams_t* rxParamSetupReq );
|
||||
|
||||
/*!
|
||||
* \brief The function processes a new channel request.
|
||||
*
|
||||
* \param [in] newChannelReq A pointer to the function parameters.
|
||||
*
|
||||
* \retval The status of the operation, according to the LoRaMAC specification.
|
||||
*/
|
||||
virtual uint8_t request_new_channel(NewChannelReqParams_t* newChannelReq );
|
||||
|
||||
/*!
|
||||
* \brief The function processes a TX ParamSetup request.
|
||||
*
|
||||
* \param [in] txParamSetupReq A pointer to the function parameters.
|
||||
*
|
||||
* \retval The status of the operation, according to the LoRaMAC specification.
|
||||
* Returns -1, if the functionality is not implemented. In this case, the end node
|
||||
* shall ignore the command.
|
||||
*/
|
||||
virtual int8_t setup_tx_params(TxParamSetupReqParams_t* txParamSetupReq );
|
||||
|
||||
/*!
|
||||
* \brief The function processes a DlChannel request.
|
||||
*
|
||||
* \param [in] dlChannelReq A pointer to the function parameters.
|
||||
*
|
||||
* \retval The status of the operation, according to the LoRaMAC specification.
|
||||
*/
|
||||
virtual uint8_t dl_channel_request(DlChannelReqParams_t* dlChannelReq );
|
||||
|
||||
/*!
|
||||
* \brief Alternates the datarate of the channel for the join request.
|
||||
*
|
||||
* \param [in] alternateDr A pointer to the function parameters.
|
||||
*
|
||||
* \retval The datarate to apply.
|
||||
*/
|
||||
virtual int8_t get_alternate_DR(AlternateDrParams_t* alternateDr );
|
||||
|
||||
/*!
|
||||
* \brief Calculates the back-off time.
|
||||
*
|
||||
* \param [in] calcBackOff A pointer to the function parameters.
|
||||
*/
|
||||
virtual void calculate_backoff(CalcBackOffParams_t* calcBackOff );
|
||||
|
||||
/*!
|
||||
* \brief Searches and sets the next random available channel.
|
||||
*
|
||||
* \param [in] nextChanParams The parameters for the next channel.
|
||||
*
|
||||
* \param [out] channel The next channel to use for TX.
|
||||
*
|
||||
* \param [out] time The time to wait for the next transmission according to the duty cycle.
|
||||
*
|
||||
* \param [out] aggregatedTimeOff Updates the aggregated time off.
|
||||
*
|
||||
* \retval The function status [1: OK, 0: Unable to find a channel on the current datarate].
|
||||
*/
|
||||
virtual bool set_next_channel(NextChanParams_t* nextChanParams,
|
||||
uint8_t* channel, TimerTime_t* time,
|
||||
TimerTime_t* aggregatedTimeOff );
|
||||
|
||||
/*!
|
||||
* \brief Adds a channel.
|
||||
*
|
||||
* \param [in] channelAdd A pPointer to the function parameters.
|
||||
*
|
||||
* \retval The status of the operation.
|
||||
*/
|
||||
virtual LoRaMacStatus_t add_channel(ChannelAddParams_t* channelAdd );
|
||||
|
||||
/*!
|
||||
* \brief Removes a channel.
|
||||
*
|
||||
* \param [in] channelRemove A pointer to the function parameters.
|
||||
*
|
||||
* \retval True, if the channel was removed successfully.
|
||||
*/
|
||||
virtual bool remove_channel(ChannelRemoveParams_t* channelRemove );
|
||||
|
||||
/*!
|
||||
* \brief Sets the radio into continuous wave mode.
|
||||
*
|
||||
* \param [in] continuousWave A pointer to the function parameters.
|
||||
*/
|
||||
virtual void set_tx_cont_mode(ContinuousWaveParams_t* continuousWave );
|
||||
|
||||
/*!
|
||||
* \brief Computes a new datarate according to the given offset.
|
||||
*
|
||||
* \param [in] downlinkDwellTime The downlink dwell time configuration. 0: No limit, 1: 400ms
|
||||
*
|
||||
* \param [in] dr The current datarate.
|
||||
*
|
||||
* \param [in] drOffset The offset to be applied.
|
||||
*
|
||||
* \retval newDr The computed datarate.
|
||||
*/
|
||||
virtual uint8_t apply_DR_offset(uint8_t downlinkDwellTime, int8_t dr, int8_t drOffset );
|
||||
|
||||
private:
|
||||
uint8_t CountNbOfEnabledChannels( bool joined, uint8_t datarate, uint16_t* channelsMask, ChannelParams_t* channels, Band_t* bands, uint8_t* enabledChannels, uint8_t* delayTx );
|
||||
|
||||
// Global attributes
|
||||
/*!
|
||||
* LoRaMAC channels
|
||||
*/
|
||||
ChannelParams_t Channels[IN865_MAX_NB_CHANNELS];
|
||||
|
||||
/*!
|
||||
* LoRaMac bands
|
||||
*/
|
||||
Band_t Bands[IN865_MAX_NB_BANDS];
|
||||
|
||||
/*!
|
||||
* LoRaMac channels mask
|
||||
*/
|
||||
uint16_t ChannelsMask[IN865_CHANNELS_MASK_SIZE];
|
||||
|
||||
/*!
|
||||
* LoRaMac channels default mask
|
||||
*/
|
||||
uint16_t ChannelsDefaultMask[IN865_CHANNELS_MASK_SIZE];
|
||||
};
|
||||
|
||||
#endif /* MBED_OS_LORAPHY_IN865_H_ */
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,359 @@
|
|||
/**
|
||||
* @file LoRaPHYKR920.h
|
||||
*
|
||||
* @brief Implements LoRaPHY for Korean 920 MHz band
|
||||
*
|
||||
* \code
|
||||
* ______ _
|
||||
* / _____) _ | |
|
||||
* ( (____ _____ ____ _| |_ _____ ____| |__
|
||||
* \____ \| ___ | (_ _) ___ |/ ___) _ \
|
||||
* _____) ) ____| | | || |_| ____( (___| | | |
|
||||
* (______/|_____)_|_|_| \__)_____)\____)_| |_|
|
||||
* (C)2013 Semtech
|
||||
* ___ _____ _ ___ _ _____ ___ ___ ___ ___
|
||||
* / __|_ _/_\ / __| |/ / __/ _ \| _ \/ __| __|
|
||||
* \__ \ | |/ _ \ (__| ' <| _| (_) | / (__| _|
|
||||
* |___/ |_/_/ \_\___|_|\_\_| \___/|_|_\\___|___|
|
||||
* embedded.connectivity.solutions===============
|
||||
*
|
||||
* \endcode
|
||||
*
|
||||
*
|
||||
* License: Revised BSD License, see LICENSE.TXT file include in the project
|
||||
*
|
||||
* Maintainer: Miguel Luis ( Semtech ), Gregory Cristian ( Semtech ) and Daniel Jaeckle ( STACKFORCE )
|
||||
*
|
||||
* Copyright (c) 2017, Arm Limited and affiliates.
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef MBED_OS_LORAPHY_KR920_H_
|
||||
#define MBED_OS_LORAPHY_KR920_H_
|
||||
|
||||
#include "LoRaPHY.h"
|
||||
#include "netsocket/LoRaRadio.h"
|
||||
|
||||
/*!
|
||||
* LoRaMac maximum number of channels
|
||||
*/
|
||||
#define KR920_MAX_NB_CHANNELS 16
|
||||
|
||||
/*!
|
||||
* Maximum number of bands
|
||||
*/
|
||||
#define KR920_MAX_NB_BANDS 1
|
||||
|
||||
#define KR920_CHANNELS_MASK_SIZE 1
|
||||
|
||||
|
||||
class LoRaPHYKR920 : public LoRaPHY {
|
||||
|
||||
public:
|
||||
|
||||
LoRaPHYKR920();
|
||||
virtual ~LoRaPHYKR920();
|
||||
|
||||
/*!
|
||||
* \brief The function gets a value of a specific PHY attribute.
|
||||
*
|
||||
* \param [in] getPhy A pointer to the function parameters.
|
||||
*
|
||||
* \retval The structure containing the PHY parameter.
|
||||
*/
|
||||
virtual PhyParam_t get_phy_params(GetPhyParams_t* getPhy );
|
||||
|
||||
/*!
|
||||
* \brief Updates the last TX done parameters of the current channel.
|
||||
*
|
||||
* \param [in] txDone A pointer to the function parameters.
|
||||
*/
|
||||
virtual void set_band_tx_done(SetBandTxDoneParams_t* txDone );
|
||||
|
||||
/*!
|
||||
* \brief Initializes the channels masks and the channels.
|
||||
*
|
||||
* \param [in] type Sets the initialization type.
|
||||
*/
|
||||
virtual void load_defaults(InitType_t type );
|
||||
|
||||
/*!
|
||||
* \brief Verifies a parameter.
|
||||
*
|
||||
* \param [in] verify A pointer to the function parameters.
|
||||
*
|
||||
* \param [in] phyAttribute The attribute to verify.
|
||||
*
|
||||
* \retval True, if the parameter is valid.
|
||||
*/
|
||||
virtual bool verify(VerifyParams_t* verify, PhyAttribute_t phyAttribute );
|
||||
|
||||
/*!
|
||||
* \brief The function parses the input buffer and sets up the channels of the CF list.
|
||||
*
|
||||
* \param [in] applyCFList A pointer to the function parameters.
|
||||
*/
|
||||
virtual void apply_cf_list(ApplyCFListParams_t* applyCFList );
|
||||
|
||||
/*!
|
||||
* \brief Sets a channels mask.
|
||||
*
|
||||
* \param [in] chanMaskSet A pointer to the function parameters.
|
||||
*
|
||||
* \retval True, if the channels mask could be set.
|
||||
*/
|
||||
virtual bool set_channel_mask(ChanMaskSetParams_t* chanMaskSet );
|
||||
|
||||
/*!
|
||||
* \brief Calculates the next datarate to set, when ADR is on or off.
|
||||
*
|
||||
* \param [in] adrNext A pointer to the function parameters.
|
||||
*
|
||||
* \param [out] drOut The calculated datarate for the next TX.
|
||||
*
|
||||
* \param [out] txPowOut The TX power for the next TX.
|
||||
*
|
||||
* \param [out] adrAckCounter The calculated ADR acknowledgement counter.
|
||||
*
|
||||
* \retval True, if an ADR request should be performed.
|
||||
*/
|
||||
virtual bool get_next_ADR(AdrNextParams_t* adrNext, int8_t* drOut,
|
||||
int8_t* txPowOut, uint32_t* adrAckCounter );
|
||||
|
||||
/*!
|
||||
* \brief Configuration of the RX windows.
|
||||
*
|
||||
* \param [in] rxConfig A pointer to the function parameters.
|
||||
*
|
||||
* \param [out] datarate The datarate index set.
|
||||
*
|
||||
* \retval True, if the configuration was applied successfully.
|
||||
*/
|
||||
virtual bool rx_config(RxConfigParams_t* rxConfig, int8_t* datarate );
|
||||
|
||||
/*
|
||||
* RX window precise timing
|
||||
*
|
||||
* For more details, please consult the following document, chapter 3.1.2.
|
||||
* http://www.semtech.com/images/datasheet/SX1272_settings_for_LoRaWAN_v2.0.pdf
|
||||
* or
|
||||
* http://www.semtech.com/images/datasheet/SX1276_settings_for_LoRaWAN_v2.0.pdf
|
||||
*
|
||||
* Downlink start: T = Tx + 1s (+/- 20 us)
|
||||
* |
|
||||
* TRxEarly | TRxLate
|
||||
* | | |
|
||||
* | | +---+---+---+---+---+---+---+---+
|
||||
* | | | Latest Rx window |
|
||||
* | | +---+---+---+---+---+---+---+---+
|
||||
* | | |
|
||||
* +---+---+---+---+---+---+---+---+
|
||||
* | Earliest Rx window |
|
||||
* +---+---+---+---+---+---+---+---+
|
||||
* |
|
||||
* +---+---+---+---+---+---+---+---+
|
||||
*Downlink preamble 8 symbols | | | | | | | | |
|
||||
* +---+---+---+---+---+---+---+---+
|
||||
*
|
||||
* Worst case Rx window timings
|
||||
*
|
||||
* TRxLate = DEFAULT_MIN_RX_SYMBOLS * tSymbol - RADIO_WAKEUP_TIME
|
||||
* TRxEarly = 8 - DEFAULT_MIN_RX_SYMBOLS * tSymbol - RxWindowTimeout - RADIO_WAKEUP_TIME
|
||||
*
|
||||
* TRxLate - TRxEarly = 2 * DEFAULT_SYSTEM_MAX_RX_ERROR
|
||||
*
|
||||
* RxOffset = ( TRxLate + TRxEarly ) / 2
|
||||
*
|
||||
* RxWindowTimeout = ( 2 * DEFAULT_MIN_RX_SYMBOLS - 8 ) * tSymbol + 2 * DEFAULT_SYSTEM_MAX_RX_ERROR
|
||||
* RxOffset = 4 * tSymbol - RxWindowTimeout / 2 - RADIO_WAKE_UP_TIME
|
||||
*
|
||||
* The minimum value of RxWindowTimeout must be 5 symbols which implies that the system always tolerates at least an error of 1.5 * tSymbol
|
||||
*/
|
||||
/*!
|
||||
* Computes the RX window timeout and offset.
|
||||
*
|
||||
* \param [in] datarate The RX window datarate index to be used.
|
||||
*
|
||||
* \param [in] minRxSymbols The minimum number of symbols required to detect an RX frame.
|
||||
*
|
||||
* \param [in] rxError The system maximum timing error of the receiver in milliseconds.
|
||||
* The receiver will turn on in a [-rxError : +rxError] ms
|
||||
* interval around RxOffset.
|
||||
*
|
||||
* \param [out] rxConfigParams Returns the updated WindowTimeout and WindowOffset fields.
|
||||
*/
|
||||
virtual void compute_rx_win_params(int8_t datarate,
|
||||
uint8_t minRxSymbols,
|
||||
uint32_t rxError,
|
||||
RxConfigParams_t *rxConfigParams);
|
||||
|
||||
/*!
|
||||
* \brief TX configuration.
|
||||
*
|
||||
* \param [in] txConfig A pointer to the function parameters.
|
||||
*
|
||||
* \param [out] txPower The TX power index set.
|
||||
*
|
||||
* \param [out] txTimeOnAir The time-on-air of the frame.
|
||||
*
|
||||
* \retval True, if the configuration was applied successfully.
|
||||
*/
|
||||
virtual bool tx_config(TxConfigParams_t* txConfig, int8_t* txPower,
|
||||
TimerTime_t* txTimeOnAir );
|
||||
|
||||
/*!
|
||||
* \brief The function processes a Link ADR request.
|
||||
*
|
||||
* \param [in] linkAdrReq A pointer to the function parameters.
|
||||
*
|
||||
* \param [out] drOut The datarate applied.
|
||||
*
|
||||
* \param [out] txPowOut The TX power applied.
|
||||
*
|
||||
* \param [out] nbRepOut The number of repetitions to apply.
|
||||
*
|
||||
* \param [out] nbBytesParsed The number of bytes parsed.
|
||||
*
|
||||
* \retval The status of the operation, according to the LoRaMAC specification.
|
||||
*/
|
||||
virtual uint8_t link_ADR_request(LinkAdrReqParams_t* linkAdrReq,
|
||||
int8_t* drOut, int8_t* txPowOut,
|
||||
uint8_t* nbRepOut,
|
||||
uint8_t* nbBytesParsed );
|
||||
|
||||
/*!
|
||||
* \brief The function processes a RX parameter setup request.
|
||||
*
|
||||
* \param [in] rxParamSetupReq A pointer to the function parameters.
|
||||
*
|
||||
* \retval The status of the operation, according to the LoRaMAC specification.
|
||||
*/
|
||||
virtual uint8_t setup_rx_params(RxParamSetupReqParams_t* rxParamSetupReq );
|
||||
|
||||
/*!
|
||||
* \brief The function processes a new channel request.
|
||||
*
|
||||
* \param [in] newChannelReq A pointer to the function parameters.
|
||||
*
|
||||
* \retval The status of the operation, according to the LoRaMAC specification.
|
||||
*/
|
||||
virtual uint8_t request_new_channel(NewChannelReqParams_t* newChannelReq );
|
||||
|
||||
/*!
|
||||
* \brief The function processes a TX ParamSetup request.
|
||||
*
|
||||
* \param [in] txParamSetupReq A pointer to the function parameters.
|
||||
*
|
||||
* \retval The status of the operation, according to the LoRaMAC specification.
|
||||
* Returns -1, if the functionality is not implemented. In this case, the end node
|
||||
* shall ignore the command.
|
||||
*/
|
||||
virtual int8_t setup_tx_params(TxParamSetupReqParams_t* txParamSetupReq );
|
||||
|
||||
/*!
|
||||
* \brief The function processes a DlChannel request.
|
||||
*
|
||||
* \param [in] dlChannelReq A pointer to the function parameters.
|
||||
*
|
||||
* \retval The status of the operation, according to the LoRaMAC specification.
|
||||
*/
|
||||
virtual uint8_t dl_channel_request(DlChannelReqParams_t* dlChannelReq );
|
||||
|
||||
/*!
|
||||
* \brief Alternates the datarate of the channel for the join request.
|
||||
*
|
||||
* \param [in] alternateDr A pointer to the function parameters.
|
||||
*
|
||||
* \retval The datarate to apply.
|
||||
*/
|
||||
virtual int8_t get_alternate_DR(AlternateDrParams_t* alternateDr );
|
||||
|
||||
/*!
|
||||
* \brief Calculates the back-off time.
|
||||
*
|
||||
* \param [in] calcBackOff A pointer to the function parameters.
|
||||
*/
|
||||
virtual void calculate_backoff(CalcBackOffParams_t* calcBackOff );
|
||||
|
||||
/*!
|
||||
* \brief Searches and sets the next random available channel.
|
||||
*
|
||||
* \param [in] nextChanParams The parameters for the next channel.
|
||||
*
|
||||
* \param [out] channel The next channel to use for TX.
|
||||
*
|
||||
* \param [out] time The time to wait for the next transmission according to the duty cycle.
|
||||
*
|
||||
* \param [out] aggregatedTimeOff Updates the aggregated time off.
|
||||
*
|
||||
* \retval The function status [1: OK, 0: Unable to find a channel on the current datarate].
|
||||
*/
|
||||
virtual bool set_next_channel(NextChanParams_t* nextChanParams,
|
||||
uint8_t* channel, TimerTime_t* time,
|
||||
TimerTime_t* aggregatedTimeOff );
|
||||
|
||||
/*!
|
||||
* \brief Adds a channel.
|
||||
*
|
||||
* \param [in] channelAdd A pointer to the function parameters.
|
||||
*
|
||||
* \retval The status of the operation.
|
||||
*/
|
||||
virtual LoRaMacStatus_t add_channel(ChannelAddParams_t* channelAdd );
|
||||
|
||||
/*!
|
||||
* \brief Removes a channel.
|
||||
*
|
||||
* \param [in] channelRemove A pointer to the function parameters.
|
||||
*
|
||||
* \retval True, if the channel was removed successfully.
|
||||
*/
|
||||
virtual bool remove_channel(ChannelRemoveParams_t* channelRemove );
|
||||
|
||||
/*!
|
||||
* \brief Sets the radio into continuous wave mode.
|
||||
*
|
||||
* \param [in] continuousWave A pointer to the function parameters.
|
||||
*/
|
||||
virtual void set_tx_cont_mode(ContinuousWaveParams_t* continuousWave );
|
||||
|
||||
/*!
|
||||
* \brief Computes new datarate according to the given offset.
|
||||
*
|
||||
* \param [in] downlinkDwellTime The downlink dwell time configuration. 0: No limit, 1: 400ms
|
||||
*
|
||||
* \param [in] dr The current datarate.
|
||||
*
|
||||
* \param [in] drOffset The offset to be applied.
|
||||
*
|
||||
* \retval newDr The computed datarate.
|
||||
*/
|
||||
virtual uint8_t apply_DR_offset(uint8_t downlinkDwellTime, int8_t dr, int8_t drOffset );
|
||||
|
||||
uint8_t CountNbOfEnabledChannels( bool joined, uint8_t datarate, uint16_t* channelsMask, ChannelParams_t* channels, Band_t* bands, uint8_t* enabledChannels, uint8_t* delayTx );
|
||||
|
||||
// Global attributes
|
||||
/*!
|
||||
* LoRaMAC channels
|
||||
*/
|
||||
ChannelParams_t Channels[KR920_MAX_NB_CHANNELS];
|
||||
|
||||
/*!
|
||||
* LoRaMac bands
|
||||
*/
|
||||
Band_t Bands[KR920_MAX_NB_BANDS];
|
||||
|
||||
/*!
|
||||
* LoRaMac channels mask
|
||||
*/
|
||||
uint16_t ChannelsMask[KR920_CHANNELS_MASK_SIZE];
|
||||
|
||||
/*!
|
||||
* LoRaMac channels default mask
|
||||
*/
|
||||
uint16_t ChannelsDefaultMask[KR920_CHANNELS_MASK_SIZE];
|
||||
};
|
||||
|
||||
#endif // MBED_OS_LORAPHY_KR920_H_
|
||||
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,365 @@
|
|||
/**
|
||||
* @file LoRaPHYUS915.h
|
||||
*
|
||||
* @brief Implements LoRaPHY for US 915 MHz band
|
||||
*
|
||||
* \code
|
||||
* ______ _
|
||||
* / _____) _ | |
|
||||
* ( (____ _____ ____ _| |_ _____ ____| |__
|
||||
* \____ \| ___ | (_ _) ___ |/ ___) _ \
|
||||
* _____) ) ____| | | || |_| ____( (___| | | |
|
||||
* (______/|_____)_|_|_| \__)_____)\____)_| |_|
|
||||
* (C)2013 Semtech
|
||||
* ___ _____ _ ___ _ _____ ___ ___ ___ ___
|
||||
* / __|_ _/_\ / __| |/ / __/ _ \| _ \/ __| __|
|
||||
* \__ \ | |/ _ \ (__| ' <| _| (_) | / (__| _|
|
||||
* |___/ |_/_/ \_\___|_|\_\_| \___/|_|_\\___|___|
|
||||
* embedded.connectivity.solutions===============
|
||||
*
|
||||
* \endcode
|
||||
*
|
||||
*
|
||||
* License: Revised BSD License, see LICENSE.TXT file include in the project
|
||||
*
|
||||
* Maintainer: Miguel Luis ( Semtech ), Gregory Cristian ( Semtech ) and Daniel Jaeckle ( STACKFORCE )
|
||||
*
|
||||
* Copyright (c) 2017, Arm Limited and affiliates.
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef MBED_OS_LORAPHYUS_915_H_
|
||||
#define MBED_OS_LORAPHYUS_915_H_
|
||||
|
||||
#include "LoRaPHY.h"
|
||||
#include "netsocket/LoRaRadio.h"
|
||||
|
||||
/*!
|
||||
* LoRaMac maximum number of channels
|
||||
*/
|
||||
#define US915_MAX_NB_CHANNELS 72
|
||||
|
||||
/*!
|
||||
* LoRaMac maximum number of bands
|
||||
*/
|
||||
#define US915_MAX_NB_BANDS 1
|
||||
|
||||
#define US915_CHANNELS_MASK_SIZE 6
|
||||
|
||||
|
||||
class LoRaPHYUS915 : public LoRaPHY {
|
||||
|
||||
public:
|
||||
|
||||
LoRaPHYUS915();
|
||||
virtual ~LoRaPHYUS915();
|
||||
|
||||
/*!
|
||||
* \brief The function gets a value of a specific PHY attribute.
|
||||
*
|
||||
* \param [in] getPhy A pointer to the function parameters.
|
||||
*
|
||||
* \retval The structure containing the PHY parameter.
|
||||
*/
|
||||
virtual PhyParam_t get_phy_params(GetPhyParams_t* getPhy );
|
||||
|
||||
/*!
|
||||
* \brief Updates the last TX done parameters of the current channel.
|
||||
*
|
||||
* \param [in] txDone A pointer to the function parameters.
|
||||
*/
|
||||
virtual void set_band_tx_done(SetBandTxDoneParams_t* txDone );
|
||||
|
||||
/*!
|
||||
* \brief Initializes the channels masks and the channels.
|
||||
*
|
||||
* \param [in] type Sets the initialization type.
|
||||
*/
|
||||
virtual void load_defaults(InitType_t type );
|
||||
|
||||
/*!
|
||||
* \brief Verifies a parameter.
|
||||
*
|
||||
* \param [in] verify A pointer to the function parameters.
|
||||
*
|
||||
* \param [in] phyAttribute The attribute to verify.
|
||||
*
|
||||
* \retval True, if the parameter is valid.
|
||||
*/
|
||||
virtual bool verify(VerifyParams_t* verify, PhyAttribute_t phyAttribute );
|
||||
|
||||
/*!
|
||||
* \brief The function parses the input buffer and sets up the channels of the CF list.
|
||||
*
|
||||
* \param [in] applyCFList A pointer to the function parameters.
|
||||
*/
|
||||
virtual void apply_cf_list(ApplyCFListParams_t* applyCFList );
|
||||
|
||||
/*!
|
||||
* \brief Sets a channels mask.
|
||||
*
|
||||
* \param [in] chanMaskSet A pointer to the function parameters.
|
||||
*
|
||||
* \retval True, if the channels mask could be set.
|
||||
*/
|
||||
virtual bool set_channel_mask(ChanMaskSetParams_t* chanMaskSet );
|
||||
|
||||
/*!
|
||||
* \brief Calculates the next datarate to set, when ADR is on or off.
|
||||
*
|
||||
* \param [in] adrNext A pointer to the function parameters.
|
||||
*
|
||||
* \param [out] drOut The calculated datarate for the next TX.
|
||||
*
|
||||
* \param [out] txPowOut The TX power for the next TX.
|
||||
*
|
||||
* \param [out] adrAckCounter The calculated ADR acknowledgement counter.
|
||||
*
|
||||
* \retval True, if an ADR request should be performed.
|
||||
*/
|
||||
virtual bool get_next_ADR(AdrNextParams_t* adrNext, int8_t* drOut,
|
||||
int8_t* txPowOut, uint32_t* adrAckCounter );
|
||||
|
||||
/*!
|
||||
* \brief Configuration of the RX windows.
|
||||
*
|
||||
* \param [in] rxConfig A pointer to the function parameters.
|
||||
*
|
||||
* \param [out] datarate The datarate index set.
|
||||
*
|
||||
* \retval True, if the configuration was applied successfully.
|
||||
*/
|
||||
virtual bool rx_config(RxConfigParams_t* rxConfig, int8_t* datarate );
|
||||
|
||||
/*
|
||||
* RX window precise timing
|
||||
*
|
||||
* For more details, please consult the following document, chapter 3.1.2.
|
||||
* http://www.semtech.com/images/datasheet/SX1272_settings_for_LoRaWAN_v2.0.pdf
|
||||
* or
|
||||
* http://www.semtech.com/images/datasheet/SX1276_settings_for_LoRaWAN_v2.0.pdf
|
||||
*
|
||||
* Downlink start: T = Tx + 1s (+/- 20 us)
|
||||
* |
|
||||
* TRxEarly | TRxLate
|
||||
* | | |
|
||||
* | | +---+---+---+---+---+---+---+---+
|
||||
* | | | Latest Rx window |
|
||||
* | | +---+---+---+---+---+---+---+---+
|
||||
* | | |
|
||||
* +---+---+---+---+---+---+---+---+
|
||||
* | Earliest Rx window |
|
||||
* +---+---+---+---+---+---+---+---+
|
||||
* |
|
||||
* +---+---+---+---+---+---+---+---+
|
||||
*Downlink preamble 8 symbols | | | | | | | | |
|
||||
* +---+---+---+---+---+---+---+---+
|
||||
*
|
||||
* Worst case Rx window timings
|
||||
*
|
||||
* TRxLate = DEFAULT_MIN_RX_SYMBOLS * tSymbol - RADIO_WAKEUP_TIME
|
||||
* TRxEarly = 8 - DEFAULT_MIN_RX_SYMBOLS * tSymbol - RxWindowTimeout - RADIO_WAKEUP_TIME
|
||||
*
|
||||
* TRxLate - TRxEarly = 2 * DEFAULT_SYSTEM_MAX_RX_ERROR
|
||||
*
|
||||
* RxOffset = ( TRxLate + TRxEarly ) / 2
|
||||
*
|
||||
* RxWindowTimeout = ( 2 * DEFAULT_MIN_RX_SYMBOLS - 8 ) * tSymbol + 2 * DEFAULT_SYSTEM_MAX_RX_ERROR
|
||||
* RxOffset = 4 * tSymbol - RxWindowTimeout / 2 - RADIO_WAKE_UP_TIME
|
||||
*
|
||||
* The minimum value of RxWindowTimeout must be 5 symbols which implies that the system always tolerates at least an error of 1.5 * tSymbol
|
||||
*/
|
||||
/*!
|
||||
* Computes the RX window timeout and offset.
|
||||
*
|
||||
* \param [in] datarate The RX window datarate index to be used.
|
||||
*
|
||||
* \param [in] minRxSymbols The minimum number of symbols required to detect an RX frame.
|
||||
*
|
||||
* \param [in] rxError The system maximum timing error of the receiver in milliseconds.
|
||||
* The receiver will turn on in a [-rxError : +rxError] ms
|
||||
* interval around RxOffset.
|
||||
*
|
||||
* \param [out] rxConfigParams Returns the updated WindowTimeout and WindowOffset fields.
|
||||
*/
|
||||
virtual void compute_rx_win_params(int8_t datarate,
|
||||
uint8_t minRxSymbols,
|
||||
uint32_t rxError,
|
||||
RxConfigParams_t *rxConfigParams);
|
||||
|
||||
/*!
|
||||
* \brief TX configuration.
|
||||
*
|
||||
* \param [in] txConfig A pointer to the function parameters.
|
||||
*
|
||||
* \param [out] txPower The TX power index set.
|
||||
*
|
||||
* \param [out] txTimeOnAir The time-on-air of the frame.
|
||||
*
|
||||
* \retval True, if the configuration was applied successfully.
|
||||
*/
|
||||
virtual bool tx_config(TxConfigParams_t* txConfig, int8_t* txPower,
|
||||
TimerTime_t* txTimeOnAir );
|
||||
|
||||
/*!
|
||||
* \brief The function processes a Link ADR request.
|
||||
*
|
||||
* \param [in] linkAdrReq A pointer to the function parameters.
|
||||
*
|
||||
* \param [out] drOut The datarate applied.
|
||||
*
|
||||
* \param [out] txPowOut The TX power applied.
|
||||
*
|
||||
* \param [out] nbRepOut The number of repetitions to apply.
|
||||
*
|
||||
* \param [out] nbBytesParsed The number of bytes parsed.
|
||||
*
|
||||
* \retval The status of the operation, according to the LoRaMAC specification.
|
||||
*/
|
||||
virtual uint8_t link_ADR_request(LinkAdrReqParams_t* linkAdrReq,
|
||||
int8_t* drOut, int8_t* txPowOut,
|
||||
uint8_t* nbRepOut,
|
||||
uint8_t* nbBytesParsed );
|
||||
|
||||
/*!
|
||||
* \brief The function processes a RX parameter setup request.
|
||||
*
|
||||
* \param [in] rxParamSetupReq A pointer to the function parameters.
|
||||
*
|
||||
* \retval The status of the operation, according to the LoRaMAC specification.
|
||||
*/
|
||||
virtual uint8_t setup_rx_params(RxParamSetupReqParams_t* rxParamSetupReq );
|
||||
|
||||
/*!
|
||||
* \brief The function processes a new channel request.
|
||||
*
|
||||
* \param [in] newChannelReq A pointer to the function parameters.
|
||||
*
|
||||
* \retval The status of the operation, according to the LoRaMAC specification.
|
||||
*/
|
||||
virtual uint8_t request_new_channel(NewChannelReqParams_t* newChannelReq );
|
||||
|
||||
/*!
|
||||
* \brief The function processes a TX ParamSetup request.
|
||||
*
|
||||
* \param [in] txParamSetupReq A pointer to the function parameters.
|
||||
*
|
||||
* \retval The status of the operation, according to the LoRaMAC specification.
|
||||
* Returns -1, if the functionality is not implemented. In this case, the end node
|
||||
* shall ignore the command.
|
||||
*/
|
||||
virtual int8_t setup_tx_params(TxParamSetupReqParams_t* txParamSetupReq );
|
||||
|
||||
/*!
|
||||
* \brief The function processes a DlChannel request.
|
||||
*
|
||||
* \param [in] dlChannelReq A pointer to the function parameters.
|
||||
*
|
||||
* \retval The status of the operation, according to the LoRaMAC specification.
|
||||
*/
|
||||
virtual uint8_t dl_channel_request(DlChannelReqParams_t* dlChannelReq );
|
||||
|
||||
/*!
|
||||
* \brief Alternates the datarate of the channel for the join request.
|
||||
*
|
||||
* \param [in] alternateDr A pointer to the function parameters.
|
||||
*
|
||||
* \retval The datarate to apply.
|
||||
*/
|
||||
virtual int8_t get_alternate_DR(AlternateDrParams_t* alternateDr );
|
||||
|
||||
/*!
|
||||
* \brief Calculates the back-off time.
|
||||
*
|
||||
* \param [in] calcBackOff A pointer to the function parameters.
|
||||
*/
|
||||
virtual void calculate_backoff(CalcBackOffParams_t* calcBackOff );
|
||||
|
||||
/*!
|
||||
* \brief Searches and sets the next random available channel.
|
||||
*
|
||||
* \param [in] nextChanParams The parameters for the next channel.
|
||||
*
|
||||
* \param [out] channel The next channel to use for TX.
|
||||
*
|
||||
* \param [out] time The time to wait for the next transmission according to the duty cycle.
|
||||
*
|
||||
* \param [out] aggregatedTimeOff Updates the aggregated time off.
|
||||
*
|
||||
* \retval The function status [1: OK, 0: Unable to find a channel on the current datarate].
|
||||
*/
|
||||
virtual bool set_next_channel(NextChanParams_t* nextChanParams,
|
||||
uint8_t* channel, TimerTime_t* time,
|
||||
TimerTime_t* aggregatedTimeOff );
|
||||
|
||||
/*!
|
||||
* \brief Adds a channel.
|
||||
*
|
||||
* \param [in] channelAdd A pointer to the function parameters.
|
||||
*
|
||||
* \retval The status of the operation.
|
||||
*/
|
||||
virtual LoRaMacStatus_t add_channel(ChannelAddParams_t* channelAdd );
|
||||
|
||||
/*!
|
||||
* \brief Removes a channel.
|
||||
*
|
||||
* \param [in] channelRemove A pointer to the function parameters.
|
||||
*
|
||||
* \retval True, if the channel was removed successfully.
|
||||
*/
|
||||
virtual bool remove_channel(ChannelRemoveParams_t* channelRemove );
|
||||
|
||||
/*!
|
||||
* \brief Sets the radio into continuous wave mode.
|
||||
*
|
||||
* \param [in] continuousWave A pointer to the function parameters.
|
||||
*/
|
||||
virtual void set_tx_cont_mode(ContinuousWaveParams_t* continuousWave );
|
||||
|
||||
/*!
|
||||
* \brief Computes a new datarate according to the given offset
|
||||
*
|
||||
* \param [in] downlinkDwellTime The downlink dwell time configuration. 0: No limit, 1: 400ms
|
||||
*
|
||||
* \param [in] dr The current datarate.
|
||||
*
|
||||
* \param [in] drOffset The offset to be applied.
|
||||
*
|
||||
* \retval newDr The computed datarate.
|
||||
*/
|
||||
virtual uint8_t apply_DR_offset(uint8_t downlinkDwellTime, int8_t dr, int8_t drOffset );
|
||||
|
||||
private:
|
||||
int8_t LimitTxPower( int8_t txPower, int8_t maxBandTxPower, int8_t datarate, uint16_t* channelsMask );
|
||||
uint8_t CountNbOfEnabledChannels( uint8_t datarate, uint16_t* channelsMask, ChannelParams_t* channels, Band_t* bands, uint8_t* enabledChannels, uint8_t* delayTx );
|
||||
|
||||
// Global attributes
|
||||
/*!
|
||||
* LoRaMAC channels
|
||||
*/
|
||||
ChannelParams_t Channels[US915_MAX_NB_CHANNELS];
|
||||
|
||||
/*!
|
||||
* LoRaMac bands
|
||||
*/
|
||||
Band_t Bands[US915_MAX_NB_BANDS];
|
||||
|
||||
/*!
|
||||
* LoRaMac channels mask
|
||||
*/
|
||||
uint16_t ChannelsMask[US915_CHANNELS_MASK_SIZE];
|
||||
|
||||
/*!
|
||||
* LoRaMac channels remaining
|
||||
*/
|
||||
uint16_t ChannelsMaskRemaining[US915_CHANNELS_MASK_SIZE];
|
||||
|
||||
/*!
|
||||
* LoRaMac channels default mask
|
||||
*/
|
||||
uint16_t ChannelsDefaultMask[US915_CHANNELS_MASK_SIZE];
|
||||
};
|
||||
|
||||
#endif /* MBED_OS_LORAPHY_US915_H_ */
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,366 @@
|
|||
/**
|
||||
* @file LoRaPHYUS915Hybrid.h
|
||||
*
|
||||
* @brief Implements LoRaPHY for US 915 MHz Hybrid band
|
||||
*
|
||||
* \code
|
||||
* ______ _
|
||||
* / _____) _ | |
|
||||
* ( (____ _____ ____ _| |_ _____ ____| |__
|
||||
* \____ \| ___ | (_ _) ___ |/ ___) _ \
|
||||
* _____) ) ____| | | || |_| ____( (___| | | |
|
||||
* (______/|_____)_|_|_| \__)_____)\____)_| |_|
|
||||
* (C)2013 Semtech
|
||||
* ___ _____ _ ___ _ _____ ___ ___ ___ ___
|
||||
* / __|_ _/_\ / __| |/ / __/ _ \| _ \/ __| __|
|
||||
* \__ \ | |/ _ \ (__| ' <| _| (_) | / (__| _|
|
||||
* |___/ |_/_/ \_\___|_|\_\_| \___/|_|_\\___|___|
|
||||
* embedded.connectivity.solutions===============
|
||||
*
|
||||
* \endcode
|
||||
*
|
||||
*
|
||||
* License: Revised BSD License, see LICENSE.TXT file include in the project
|
||||
*
|
||||
* Maintainer: Miguel Luis ( Semtech ), Gregory Cristian ( Semtech ) and Daniel Jaeckle ( STACKFORCE )
|
||||
*
|
||||
* Copyright (c) 2017, Arm Limited and affiliates.
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef MBED_OS_LORAPHY_US915HYBRID_H_
|
||||
#define MBED_OS_LORAPHY_US915_HYBRID_H_
|
||||
|
||||
#include "LoRaPHY.h"
|
||||
#include "netsocket/LoRaRadio.h"
|
||||
|
||||
|
||||
/*!
|
||||
* LoRaMac maximum number of channels
|
||||
*/
|
||||
#define US915_HYBRID_MAX_NB_CHANNELS 72
|
||||
|
||||
/*!
|
||||
* LoRaMac maximum number of bands
|
||||
*/
|
||||
#define US915_HYBRID_MAX_NB_BANDS 1
|
||||
|
||||
#define US915_HYBRID_CHANNELS_MASK_SIZE 6
|
||||
|
||||
|
||||
class LoRaPHYUS915Hybrid : public LoRaPHY {
|
||||
|
||||
public:
|
||||
|
||||
LoRaPHYUS915Hybrid();
|
||||
virtual ~LoRaPHYUS915Hybrid();
|
||||
|
||||
/*!
|
||||
* \brief The function gets a value of a specific PHY attribute.
|
||||
*
|
||||
* \param [in] getPhy A pointer to the function parameters.
|
||||
*
|
||||
* \retval The structure containing the PHY parameter.
|
||||
*/
|
||||
virtual PhyParam_t get_phy_params(GetPhyParams_t* getPhy );
|
||||
|
||||
/*!
|
||||
* \brief Updates the last TX done parameters of the current channel.
|
||||
*
|
||||
* \param [in] txDone A pointer to the function parameters.
|
||||
*/
|
||||
virtual void set_band_tx_done(SetBandTxDoneParams_t* txDone );
|
||||
|
||||
/*!
|
||||
* \brief Initializes the channels masks and the channels.
|
||||
*
|
||||
* \param [in] type Sets the initialization type.
|
||||
*/
|
||||
virtual void load_defaults(InitType_t type );
|
||||
|
||||
/*!
|
||||
* \brief Verifies a parameter.
|
||||
*
|
||||
* \param [in] verify A pointer to the function parameters.
|
||||
*
|
||||
* \param [in] phyAttribute The attribute to verify.
|
||||
*
|
||||
* \retval True, if the parameter is valid.
|
||||
*/
|
||||
virtual bool verify(VerifyParams_t* verify, PhyAttribute_t phyAttribute );
|
||||
|
||||
/*!
|
||||
* \brief The function parses the input buffer and sets up the channels of the CF list.
|
||||
*
|
||||
* \param [in] applyCFList A pointer to the function parameters.
|
||||
*/
|
||||
virtual void apply_cf_list(ApplyCFListParams_t* applyCFList );
|
||||
|
||||
/*!
|
||||
* \brief Sets a channels mask.
|
||||
*
|
||||
* \param [in] chanMaskSet A pointer to the function parameters.
|
||||
*
|
||||
* \retval True, if the channels mask could be set.
|
||||
*/
|
||||
virtual bool set_channel_mask(ChanMaskSetParams_t* chanMaskSet );
|
||||
|
||||
/*!
|
||||
* \brief Calculates the next datarate to set, when ADR is on or off.
|
||||
*
|
||||
* \param [in] adrNext A pointer to the function parameters.
|
||||
*
|
||||
* \param [out] drOut The calculated datarate for the next TX.
|
||||
*
|
||||
* \param [out] txPowOut The TX power for the next TX.
|
||||
*
|
||||
* \param [out] adrAckCounter The calculated ADR acknowledgement counter.
|
||||
*
|
||||
* \retval True, if an ADR request should be performed.
|
||||
*/
|
||||
virtual bool get_next_ADR(AdrNextParams_t* adrNext, int8_t* drOut,
|
||||
int8_t* txPowOut, uint32_t* adrAckCounter );
|
||||
|
||||
/*!
|
||||
* \brief Configuration of the RX windows.
|
||||
*
|
||||
* \param [in] rxConfig A pointer to the function parameters.
|
||||
*
|
||||
* \param [out] datarate The datarate index set.
|
||||
*
|
||||
* \retval True, if the configuration was applied successfully.
|
||||
*/
|
||||
virtual bool rx_config(RxConfigParams_t* rxConfig, int8_t* datarate );
|
||||
|
||||
/*
|
||||
* RX window precise timing
|
||||
*
|
||||
* For more details, please consult the following document, chapter 3.1.2.
|
||||
* http://www.semtech.com/images/datasheet/SX1272_settings_for_LoRaWAN_v2.0.pdf
|
||||
* or
|
||||
* http://www.semtech.com/images/datasheet/SX1276_settings_for_LoRaWAN_v2.0.pdf
|
||||
*
|
||||
* Downlink start: T = Tx + 1s (+/- 20 us)
|
||||
* |
|
||||
* TRxEarly | TRxLate
|
||||
* | | |
|
||||
* | | +---+---+---+---+---+---+---+---+
|
||||
* | | | Latest Rx window |
|
||||
* | | +---+---+---+---+---+---+---+---+
|
||||
* | | |
|
||||
* +---+---+---+---+---+---+---+---+
|
||||
* | Earliest Rx window |
|
||||
* +---+---+---+---+---+---+---+---+
|
||||
* |
|
||||
* +---+---+---+---+---+---+---+---+
|
||||
*Downlink preamble 8 symbols | | | | | | | | |
|
||||
* +---+---+---+---+---+---+---+---+
|
||||
*
|
||||
* Worst case Rx window timings
|
||||
*
|
||||
* TRxLate = DEFAULT_MIN_RX_SYMBOLS * tSymbol - RADIO_WAKEUP_TIME
|
||||
* TRxEarly = 8 - DEFAULT_MIN_RX_SYMBOLS * tSymbol - RxWindowTimeout - RADIO_WAKEUP_TIME
|
||||
*
|
||||
* TRxLate - TRxEarly = 2 * DEFAULT_SYSTEM_MAX_RX_ERROR
|
||||
*
|
||||
* RxOffset = ( TRxLate + TRxEarly ) / 2
|
||||
*
|
||||
* RxWindowTimeout = ( 2 * DEFAULT_MIN_RX_SYMBOLS - 8 ) * tSymbol + 2 * DEFAULT_SYSTEM_MAX_RX_ERROR
|
||||
* RxOffset = 4 * tSymbol - RxWindowTimeout / 2 - RADIO_WAKE_UP_TIME
|
||||
*
|
||||
* The minimum value of RxWindowTimeout must be 5 symbols which implies that the system always tolerates at least an error of 1.5 * tSymbol
|
||||
*/
|
||||
/*!
|
||||
* Computes the RX window timeout and offset.
|
||||
*
|
||||
* \param [in] datarate The RX window datarate index to be used.
|
||||
*
|
||||
* \param [in] minRxSymbols The minimum number of symbols required to detect an RX frame.
|
||||
*
|
||||
* \param [in] rxError The system maximum timing error of the receiver in milliseconds.
|
||||
* The receiver will turn on in a [-rxError : +rxError] ms
|
||||
* interval around RxOffset.
|
||||
*
|
||||
* \param [out] rxConfigParams Returns the updated WindowTimeout and WindowOffset fields.
|
||||
*/
|
||||
virtual void compute_rx_win_params(int8_t datarate,
|
||||
uint8_t minRxSymbols,
|
||||
uint32_t rxError,
|
||||
RxConfigParams_t *rxConfigParams);
|
||||
|
||||
/*!
|
||||
* \brief TX configuration.
|
||||
*
|
||||
* \param [in] txConfig A pointer to the function parameters.
|
||||
*
|
||||
* \param [out] txPower The TX power index set.
|
||||
*
|
||||
* \param [out] txTimeOnAir The time-on-air of the frame.
|
||||
*
|
||||
* \retval True, if the configuration was applied successfully.
|
||||
*/
|
||||
virtual bool tx_config(TxConfigParams_t* txConfig, int8_t* txPower,
|
||||
TimerTime_t* txTimeOnAir );
|
||||
|
||||
/*!
|
||||
* \brief The function processes a Link ADR request.
|
||||
*
|
||||
* \param [in] linkAdrReq A pointer to the function parameters.
|
||||
*
|
||||
* \param [out] drOut The datarate applied.
|
||||
*
|
||||
* \param [out] txPowOut The TX power applied.
|
||||
*
|
||||
* \param [out] nbRepOut The number of repetitions to apply.
|
||||
*
|
||||
* \param [out] nbBytesParsed The number of bytes parsed.
|
||||
*
|
||||
* \retval The status of the operation, according to the LoRaMAC specification.
|
||||
*/
|
||||
virtual uint8_t link_ADR_request(LinkAdrReqParams_t* linkAdrReq,
|
||||
int8_t* drOut, int8_t* txPowOut,
|
||||
uint8_t* nbRepOut,
|
||||
uint8_t* nbBytesParsed );
|
||||
|
||||
/*!
|
||||
* \brief The function processes a RX parameter setup request.
|
||||
*
|
||||
* \param [in] rxParamSetupReq A pointer to the function parameters.
|
||||
*
|
||||
* \retval The status of the operation, according to the LoRaMAC specification.
|
||||
*/
|
||||
virtual uint8_t setup_rx_params(RxParamSetupReqParams_t* rxParamSetupReq );
|
||||
|
||||
/*!
|
||||
* \brief The function processes a new channel request.
|
||||
*
|
||||
* \param [in] newChannelReq A pointer to the function parameters.
|
||||
*
|
||||
* \retval The status of the operation, according to the LoRaMAC specification.
|
||||
*/
|
||||
virtual uint8_t request_new_channel(NewChannelReqParams_t* newChannelReq );
|
||||
|
||||
/*!
|
||||
* \brief The function processes a TX ParamSetup request.
|
||||
*
|
||||
* \param [in] txParamSetupReq A pointer to the function parameters.
|
||||
*
|
||||
* \retval The status of the operation, according to the LoRaMAC specification.
|
||||
* Returns -1, if the functionality is not implemented. In this case, the end node
|
||||
* shall ignore the command.
|
||||
*/
|
||||
virtual int8_t setup_tx_params(TxParamSetupReqParams_t* txParamSetupReq );
|
||||
|
||||
/*!
|
||||
* \brief The function processes a DlChannel request.
|
||||
*
|
||||
* \param [in] dlChannelReq A pointer to the function parameters.
|
||||
*
|
||||
* \retval The status of the operation, according to the LoRaMAC specification.
|
||||
*/
|
||||
virtual uint8_t dl_channel_request(DlChannelReqParams_t* dlChannelReq );
|
||||
|
||||
/*!
|
||||
* \brief Alternates the datarate of the channel for the join request.
|
||||
*
|
||||
* \param [in] alternateDr A pointer to the function parameters.
|
||||
*
|
||||
* \retval The datarate to apply.
|
||||
*/
|
||||
virtual int8_t get_alternate_DR(AlternateDrParams_t* alternateDr );
|
||||
|
||||
/*!
|
||||
* \brief Calculates the back-off time.
|
||||
*
|
||||
* \param [in] calcBackOff A pointer to the function parameters.
|
||||
*/
|
||||
virtual void calculate_backoff(CalcBackOffParams_t* calcBackOff );
|
||||
|
||||
/*!
|
||||
* \brief Searches and sets the next random available channel.
|
||||
*
|
||||
* \param [in] nextChanParams The parameters for the next channel.
|
||||
*
|
||||
* \param [out] channel The next channel to use for TX.
|
||||
*
|
||||
* \param [out] time The time to wait for the next transmission according to the duty cycle.
|
||||
*
|
||||
* \param [out] aggregatedTimeOff Updates the aggregated time off.
|
||||
*
|
||||
* \retval The function status [1: OK, 0: Unable to find a channel on the current datarate].
|
||||
*/
|
||||
virtual bool set_next_channel(NextChanParams_t* nextChanParams,
|
||||
uint8_t* channel, TimerTime_t* time,
|
||||
TimerTime_t* aggregatedTimeOff );
|
||||
|
||||
/*!
|
||||
* \brief Adds a channel.
|
||||
*
|
||||
* \param [in] channelAdd A pointer to the function parameters.
|
||||
*
|
||||
* \retval The status of the operation.
|
||||
*/
|
||||
virtual LoRaMacStatus_t add_channel(ChannelAddParams_t* channelAdd );
|
||||
|
||||
/*!
|
||||
* \brief Removes a channel.
|
||||
*
|
||||
* \param [in] channelRemove A pointer to the function parameters.
|
||||
*
|
||||
* \retval True, if the channel was removed successfully.
|
||||
*/
|
||||
virtual bool remove_channel(ChannelRemoveParams_t* channelRemove );
|
||||
|
||||
/*!
|
||||
* \brief Sets the radio into continuous wave mode.
|
||||
*
|
||||
* \param [in] continuousWave A pointer to the function parameters.
|
||||
*/
|
||||
virtual void set_tx_cont_mode(ContinuousWaveParams_t* continuousWave );
|
||||
|
||||
/*!
|
||||
* \brief Computes a new datarate according to the given offset.
|
||||
*
|
||||
* \param [in] downlinkDwellTime The downlink dwell time configuration. 0: No limit, 1: 400ms
|
||||
*
|
||||
* \param [in] dr The current datarate.
|
||||
*
|
||||
* \param [in] drOffset The offset to be applied.
|
||||
*
|
||||
* \retval newDr The computed datarate.
|
||||
*/
|
||||
virtual uint8_t apply_DR_offset(uint8_t downlinkDwellTime, int8_t dr, int8_t drOffset );
|
||||
|
||||
private:
|
||||
int8_t LimitTxPower( int8_t txPower, int8_t maxBandTxPower, int8_t datarate, uint16_t* channelsMask );
|
||||
uint8_t CountNbOfEnabledChannels( uint8_t datarate, uint16_t* channelsMask, ChannelParams_t* channels, Band_t* bands, uint8_t* enabledChannels, uint8_t* delayTx );
|
||||
|
||||
// Global attributes
|
||||
/*!
|
||||
* LoRaMAC channels
|
||||
*/
|
||||
ChannelParams_t Channels[US915_HYBRID_MAX_NB_CHANNELS];
|
||||
|
||||
/*!
|
||||
* LoRaMac bands
|
||||
*/
|
||||
Band_t Bands[US915_HYBRID_MAX_NB_BANDS];
|
||||
|
||||
/*!
|
||||
* LoRaMac channels mask
|
||||
*/
|
||||
uint16_t ChannelsMask[US915_HYBRID_CHANNELS_MASK_SIZE];
|
||||
|
||||
/*!
|
||||
* LoRaMac channels remaining
|
||||
*/
|
||||
uint16_t ChannelsMaskRemaining[US915_HYBRID_CHANNELS_MASK_SIZE];
|
||||
|
||||
/*!
|
||||
* LoRaMac channels default mask
|
||||
*/
|
||||
uint16_t ChannelsDefaultMask[US915_HYBRID_CHANNELS_MASK_SIZE];
|
||||
};
|
||||
|
||||
#endif /* MBED_OS_LORAPHY_US915HYBRID_H_ */
|
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue