segunda-feira, 8 de julho de 2024

LSM110A - LoRaWAN - Compilando APP (comandos AT) - bare metal - WISOL - EVERYNET

  


Baseado no canais de uplink, downlink, dwell, etc

LA915 · Everynet Network Server Máscara de canais (Join, Uplink, Downlink)

Foram alterados os arquivos RegionCommon.h, RegionAU915.h e RegionAU915.c para serem compatíveis com EVERYNET.

Em RegionCommon.h

/*!
 * Receive delay of 1 second.
 */
#define REGION_COMMON_DEFAULT_RECEIVE_DELAY1            5000

/*!
 * Receive delay of 2 seconds.
 */
#define REGION_COMMON_DEFAULT_RECEIVE_DELAY2            ( REGION_COMMON_DEFAULT_RECEIVE_DELAY1 + 1000 )

/*!
 * Join accept delay of 5 seconds.
 */
#define REGION_COMMON_DEFAULT_JOIN_ACCEPT_DELAY1        5000

/*!
 * Join accept delay of 6 seconds.
 */
#define REGION_COMMON_DEFAULT_JOIN_ACCEPT_DELAY2        ( REGION_COMMON_DEFAULT_JOIN_ACCEPT_DELAY1 + 1000 )

/*!

* \file RegionAU915.h

*

* \brief Region definition for AU915

*

* \copyright Revised BSD License, see section \ref LICENSE.

*

* \code

* ______ _

* / _____) _ | |

* ( (____ _____ ____ _| |_ _____ ____| |__

* \____ \| ___ | (_ _) ___ |/ ___) _ \

* _____) ) ____| | | || |_| ____( (___| | | |

* (______/|_____)_|_|_| \__)_____)\____)_| |_|

* (C)2013-2017 Semtech

*

* ___ _____ _ ___ _ _____ ___ ___ ___ ___

* / __|_ _/_\ / __| |/ / __/ _ \| _ \/ __| __|

* \__ \ | |/ _ \ (__| ' <| _| (_) | / (__| _|

* |___/ |_/_/ \_\___|_|\_\_| \___/|_|_\\___|___|

* embedded.connectivity.solutions===============

*

* \endcode

*

* \author Miguel Luis ( Semtech )

*

* \author Gregory Cristian ( Semtech )

*

* \author Daniel Jaeckle ( STACKFORCE )

*

* \author Johannes Bruder ( STACKFORCE )

*

* \defgroup REGIONAU915 Region AU915

* Implementation according to LoRaWAN Specification v1.0.2.

* \{

*/

#ifndef __REGION_AU915_H__

#define __REGION_AU915_H__


#include "region/Region.h"



#define AU915_PING_SLOT_CHANNEL_FREQ 923300000


/*!

* LoRaMac maximum number of channels

*/

#define AU915_MAX_NB_CHANNELS 72


/*!

* Minimal datarate that can be used by the node

*/

#define AU915_TX_MIN_DATARATE DR_0


/*!

* Maximal datarate that can be used by the node

*/

#define AU915_TX_MAX_DATARATE DR_5


/*!

* 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


/*!

* The minimum datarate which is used when the

* dwell time is limited.

*/

#define AU915_DWELL_LIMIT_DATARATE DR_2


/*!

* Minimal Rx1 receive datarate offset

*/

#define AU915_MIN_RX1_DR_OFFSET 0


/*!

* Maximal Rx1 receive datarate offset

*/

#define AU915_MAX_RX1_DR_OFFSET 3


/*!

* 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_5


/*!

* Default uplink dwell time configuration

*/

#define AU915_DEFAULT_UPLINK_DWELL_TIME 0


/*!

* Default downlink dwell time configuration

*/

#define AU915_DEFAULT_DOWNLINK_DWELL_TIME 0


/*!

* Default Max EIRP

*/

#define AU915_DEFAULT_MAX_EIRP 30.0f


/*!

* Default antenna gain

*/

#define AU915_DEFAULT_ANTENNA_GAIN 0.0f


/*!

* 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 1000


/*!

* Receive delay 1

*/

#define AU915_RECEIVE_DELAY1 5000


/*!

* Receive delay 2

*/

#define AU915_RECEIVE_DELAY2 6000


/*!

* Join accept delay 1

*/

#define AU915_JOIN_ACCEPT_DELAY1 5000


/*!

* Join accept delay 2

*/

#define AU915_JOIN_ACCEPT_DELAY2 6000


/*!

* Maximum frame counter gap

*/

#define AU915_MAX_FCNT_GAP 16384


/*!

* Ack timeout

*/

#define AU915_ACKTIMEOUT 2000


/*!

* Random ack timeout limits

*/

#define AU915_ACK_TIMEOUT_RND 1000


/*!

* Second reception window channel frequency definition.

*/

#define AU915_RX_WND_2_FREQ 923300000


/*!

* Second reception window channel datarate definition.

*/

#define AU915_RX_WND_2_DR DR_8


/*

* CLASS B

*/

/*!

* Beacon frequency

*/

#define AU915_BEACON_CHANNEL_FREQ 923300000


/*!

* Beacon frequency channel stepwidth

*/

#define AU915_BEACON_CHANNEL_STEPWIDTH 600000


/*!

* Number of possible beacon channels

*/

#define AU915_BEACON_NB_CHANNELS 8


/*!

* Payload size of a beacon frame

*/

#define AU915_BEACON_SIZE 19


/*!

* Size of RFU 1 field

*/

#define AU915_RFU1_SIZE 3


/*!

* Size of RFU 2 field

*/

#define AU915_RFU2_SIZE 1


/*!

* Datarate of the beacon channel

*/

#define AU915_BEACON_CHANNEL_DR DR_10


/*!

* Bandwith of the beacon channel

*/

#define AU915_BEACON_CHANNEL_BW 2


/*!

* Ping slot channel datarate

*/

#define AU915_PING_SLOT_CHANNEL_DR DR_10


/*!

* LoRaMac maximum number of bands

*/

#define AU915_MAX_NB_BANDS 1


/*!

* Band 0 definition

* { DutyCycle, TxMaxPower, LastJoinTxDoneTime, LastTxDoneTime, TimeOff }

*/

#define AU915_BAND0 { 1, AU915_MAX_TX_POWER, 0, 0, 0 } // 100.0 %


/*!

* Defines the first channel for RX window 1 for US band

*/

#define AU915_FIRST_RX1_CHANNEL ( (uint32_t) 923300000 )


/*!

* Defines the last channel for RX window 1 for US band

*/

#define AU915_LAST_RX1_CHANNEL ( (uint32_t) 927500000 )


/*!

* Defines the step width of the channels for RX window 1

*/

#define AU915_STEPWIDTH_RX1_CHANNEL ( (uint32_t) 600000 )


/*!

* Data rates table definition

*/

static const uint8_t DataratesAU915[] = { 12, 11, 10, 9, 8, 7, 8, 0, 12, 11, 10, 9, 8, 7, 0, 0 };


/*!

* Bandwidths table definition in Hz

*/

static const uint32_t BandwidthsAU915[] = { 125000, 125000, 125000, 125000, 125000, 125000, 500000, 0, 500000, 500000, 500000, 500000, 500000, 500000, 0, 0 };


/*!

* Up/Down link data rates offset definition

*/

static const int8_t DatarateOffsetsAU915[7][6] =

{

{ DR_8 , DR_8 , DR_8 , DR_8 , DR_8 , DR_8 }, // DR_0

{ DR_9 , DR_8 , DR_8 , DR_8 , DR_8 , DR_8 }, // DR_1

{ DR_10, DR_9 , DR_8 , DR_8 , DR_8 , DR_8 }, // DR_2

{ DR_11, DR_10, DR_9 , DR_8 , DR_8 , DR_8 }, // DR_3

{ DR_12, DR_11, DR_10, DR_9 , DR_8 , DR_8 }, // DR_4

{ DR_13, DR_12, DR_11, DR_10, DR_9 , DR_8 }, // DR_5

{ DR_13, DR_13, DR_12, DR_11, DR_10, DR_9 }, // DR_6

};


/*!

* Maximum payload with respect to the datarate index. Cannot operate with repeater.

* The table is valid for the dwell time configuration of 0 for uplinks.

*/

static const uint8_t MaxPayloadOfDatarateDwell0AU915[] = { 51, 51, 51, 115, 242, 242, 242, 0, 53, 129, 242, 242, 242, 242, 0, 0 };


/*!

* Maximum payload with respect to the datarate index. Can operate with repeater.

* The table is valid for the dwell time configuration of 0 for uplinks. The table provides

* repeater support.

*/

static const uint8_t MaxPayloadOfDatarateRepeaterDwell0AU915[] = { 51, 51, 51, 115, 222, 222, 222, 0, 33, 109, 222, 222, 222, 222, 0, 0 };


/*!

* Maximum payload with respect to the datarate index. Cannot operate with repeater.

* The table is valid for the dwell time configuration of 1 for uplinks.

*/

static const uint8_t MaxPayloadOfDatarateDwell1AU915[] = { 0, 0, 11, 53, 125, 242, 242, 0, 53, 129, 129, 242, 242, 242, 242 };


/*!

* Maximum payload with respect to the datarate index. Can operate with repeater.

* The table is valid for the dwell time configuration of 1 for uplinks. The table provides

* repeater support.

*/

static const uint8_t MaxPayloadOfDatarateRepeaterDwell1AU915[] = { 0, 0, 11, 53, 125, 242, 242, 0, 33, 119, 129, 242, 242, 242, 242 };


/*!

* \brief The function gets a value of a specific phy attribute.

*

* \param [IN] getPhy Pointer to the function parameters.

*

* \retval Returns a structure containing the PHY parameter.

*/

PhyParam_t RegionAU915GetPhyParam( GetPhyParams_t* getPhy );


/*!

* \brief Updates the last TX done parameters of the current channel.

*

* \param [IN] txDone Pointer to the function parameters.

*/

void RegionAU915SetBandTxDone( SetBandTxDoneParams_t* txDone );


/*!

* \brief Initializes the channels masks and the channels.

*

* \param [IN] type Sets the initialization type.

*/

void RegionAU915InitDefaults( InitDefaultsParams_t* params );


/*!

* \brief Returns a pointer to the internal context and its size.

*

* \param [OUT] params Pointer to the function parameters.

*

* \retval Points to a structure where the module store its non-volatile context.

*/

void* RegionAU915GetNvmCtx( GetPhyParams_t* params );


/*!

* \brief Verifies a parameter.

*

* \param [IN] verify Pointer to the function parameters.

*

* \param [IN] type Sets the initialization type.

*

* \retval Returns true, if the parameter is valid.

*/

bool RegionAU915Verify( VerifyParams_t* verify, PhyAttribute_t phyAttribute );


/*!

* \brief The function parses the input buffer and sets up the channels of the

* CF list.

*

* \param [IN] applyCFList Pointer to the function parameters.

*/

void RegionAU915ApplyCFList( ApplyCFListParams_t* applyCFList );


/*!

* \brief Sets a channels mask.

*

* \param [IN] chanMaskSet Pointer to the function parameters.

*

* \retval Returns true, if the channels mask could be set.

*/

bool RegionAU915ChanMaskSet( ChanMaskSetParams_t* chanMaskSet );


/*!

* Computes the Rx window timeout and offset.

*

* \param [IN] datarate Rx window datarate index to be used

*

* \param [IN] minRxSymbols Minimum required number of symbols to detect an Rx frame.

*

* \param [IN] rxError System maximum timing error of the receiver. In milliseconds

* The receiver will turn on in a [-rxError : +rxError] ms

* interval around RxOffset

*

* \param [OUT]rxConfigParams Returns updated WindowTimeout and WindowOffset fields.

*/

void RegionAU915ComputeRxWindowParameters( int8_t datarate, uint8_t minRxSymbols, uint32_t rxError, RxConfigParams_t *rxConfigParams );


/*!

* \brief Configuration of the RX windows.

*

* \param [IN] rxConfig Pointer to the function parameters.

*

* \param [OUT] datarate The datarate index which was set.

*

* \retval Returns true, if the configuration was applied successfully.

*/

bool RegionAU915RxConfig( RxConfigParams_t* rxConfig, int8_t* datarate );


/*!

* \brief TX configuration.

*

* \param [IN] txConfig Pointer to the function parameters.

*

* \param [OUT] txPower The tx power index which was set.

*

* \param [OUT] txTimeOnAir The time-on-air of the frame.

*

* \retval Returns true, if the configuration was applied successfully.

*/

bool RegionAU915TxConfig( TxConfigParams_t* txConfig, int8_t* txPower, TimerTime_t* txTimeOnAir );


/*!

* \brief The function processes a Link ADR Request.

*

* \param [IN] linkAdrReq Pointer to the function parameters.

*

* \retval Returns the status of the operation, according to the LoRaMAC specification.

*/

uint8_t RegionAU915LinkAdrReq( LinkAdrReqParams_t* linkAdrReq, int8_t* drOut, int8_t* txPowOut, uint8_t* nbRepOut, uint8_t* nbBytesParsed );


/*!

* \brief The function processes a RX Parameter Setup Request.

*

* \param [IN] rxParamSetupReq Pointer to the function parameters.

*

* \retval Returns the status of the operation, according to the LoRaMAC specification.

*/

uint8_t RegionAU915RxParamSetupReq( RxParamSetupReqParams_t* rxParamSetupReq );


/*!

* \brief The function processes a Channel Request.

*

* \param [IN] newChannelReq Pointer to the function parameters.

*

* \retval Returns the status of the operation, according to the LoRaMAC specification.

*/

uint8_t RegionAU915NewChannelReq( NewChannelReqParams_t* newChannelReq );


/*!

* \brief The function processes a TX ParamSetup Request.

*

* \param [IN] txParamSetupReq Pointer to the function parameters.

*

* \retval Returns the status of the operation, according to the LoRaMAC specification.

* Returns -1, if the functionality is not implemented. In this case, the end node

* shall not process the command.

*/

int8_t RegionAU915TxParamSetupReq( TxParamSetupReqParams_t* txParamSetupReq );


/*!

* \brief The function processes a DlChannel Request.

*

* \param [IN] dlChannelReq Pointer to the function parameters.

*

* \retval Returns the status of the operation, according to the LoRaMAC specification.

*/

uint8_t RegionAU915DlChannelReq( DlChannelReqParams_t* dlChannelReq );


/*!

* \brief Alternates the datarate of the channel for the join request.

*

* \param [IN] currentDr Current datarate.

*

* \retval Datarate to apply.

*/

int8_t RegionAU915AlternateDr( int8_t currentDr, AlternateDrType_t type );


/*!

* \brief Calculates the back-off time.

*

* \param [IN] calcBackOff Pointer to the function parameters.

*/


//void RegionAU915CalcBackOff( CalcBackOffParams_t* calcBackOff );


/*!

* \brief Searches and set the next random available channel

*

* \param [OUT] channel Next channel to use for TX.

*

* \param [OUT] time Time to wait for the next transmission according to the duty

* cycle.

*

* \param [OUT] aggregatedTimeOff Updates the aggregated time off.

*

* \retval Function status [1: OK, 0: Unable to find a channel on the current datarate]

*/

LoRaMacStatus_t RegionAU915NextChannel( NextChanParams_t* nextChanParams, uint8_t* channel, TimerTime_t* time, TimerTime_t* aggregatedTimeOff );


/*!

* \brief Adds a channel.

*

* \param [IN] channelAdd Pointer to the function parameters.

*

* \retval Status of the operation.

*/

LoRaMacStatus_t RegionAU915ChannelAdd( ChannelAddParams_t* channelAdd );


/*!

* \brief Removes a channel.

*

* \param [IN] channelRemove Pointer to the function parameters.

*

* \retval Returns true, if the channel was removed successfully.

*/

bool RegionAU915ChannelsRemove( ChannelRemoveParams_t* channelRemove );


/*!

* \brief Sets the radio into continuous wave mode.

*

* \param [IN] continuousWave Pointer to the function parameters.

*/

//////void RegionAU915SetContinuousWave( ContinuousWaveParams_t* continuousWave );


/*!

* \brief Computes new datarate according to the given offset

*

* \param [IN] downlinkDwellTime Downlink dwell time configuration. 0: No limit, 1: 400ms

*

* \param [IN] dr Current datarate

*

* \param [IN] drOffset Offset to be applied

*

* \retval newDr Computed datarate.

*/

uint8_t RegionAU915ApplyDrOffset( uint8_t downlinkDwellTime, int8_t dr, int8_t drOffset );


/*!

* \brief Sets the radio into beacon reception mode

*

* \param [IN] rxBeaconSetup Pointer to the function parameters

*/

void RegionAU915RxBeaconSetup( RxBeaconSetup_t* rxBeaconSetup, uint8_t* outDr );


/*! \} defgroup REGIONAU915 */


#endif // __REGION_AU915_H__




/*!

* \file RegionAU915.c

*

* \brief Region implementation for AU915

*

* \copyright Revised BSD License, see section \ref LICENSE.

*

* \code

* ______ _

* / _____) _ | |

* ( (____ _____ ____ _| |_ _____ ____| |__

* \____ \| ___ | (_ _) ___ |/ ___) _ \

* _____) ) ____| | | || |_| ____( (___| | | |

* (______/|_____)_|_|_| \__)_____)\____)_| |_|

* (C)2013-2017 Semtech

*

* ___ _____ _ ___ _ _____ ___ ___ ___ ___

* / __|_ _/_\ / __| |/ / __/ _ \| _ \/ __| __|

* \__ \ | |/ _ \ (__| ' <| _| (_) | / (__| _|

* |___/ |_/_/ \_\___|_|\_\_| \___/|_|_\\___|___|

* embedded.connectivity.solutions===============

*

* \endcode

*

* \author Miguel Luis ( Semtech )

*

* \author Gregory Cristian ( Semtech )

*

* \author Daniel Jaeckle ( STACKFORCE )

*/

/**

******************************************************************************

*

* Portions COPYRIGHT 2020 STMicroelectronics

*

* @file RegionAU915.c

* @author MCD Application Team

* @brief Region implementation for AU915

******************************************************************************

*/

#include "radio.h"

#include "RegionAU915.h"

#include "RegionBaseUS.h"


// Definitions

#define CHANNELS_MASK_SIZE 6


// A mask to select only valid 500KHz channels

#define CHANNELS_MASK_500KHZ_MASK 0x00FF


/* The HYBRID_DEFAULT_MASKx define the enabled channels in Hybrid mode*/

/* Note: they can be redefined in lorawan_conf.h*/

#ifndef HYBRID_DEFAULT_MASK0 /*enabled channels from channel 15 down to channel 0*/

#define HYBRID_DEFAULT_MASK0 0x00FF /*channel 7 down to channel 0 enabled*/

#endif

#ifndef HYBRID_DEFAULT_MASK1 /*enabled channels from channel 31 down to channel 16*/

#define HYBRID_DEFAULT_MASK1 0x0000

#endif

#ifndef HYBRID_DEFAULT_MASK2 /*enabled channels from channel 47 down to channel 32*/

#define HYBRID_DEFAULT_MASK2 0x0000

#endif

#ifndef HYBRID_DEFAULT_MASK3 /*enabled channels from channel 63 down to channel 48*/

#define HYBRID_DEFAULT_MASK3 0x0000

#endif

#ifndef HYBRID_DEFAULT_MASK4 /*enabled channels from channel 71 down to channel 64*/

#define HYBRID_DEFAULT_MASK4 0x0000

#endif


#if defined( REGION_AU915 )

/*

* Non-volatile module context.

*/

static RegionNvmDataGroup1_t* RegionNvmGroup1;

static RegionNvmDataGroup2_t* RegionNvmGroup2;

#if (defined( REGION_VERSION ) && ( REGION_VERSION == 0x02010001 ))

static Band_t* RegionBands;

#endif /* REGION_VERSION */


static bool VerifyRfFreq( uint32_t freq )

{

// Check radio driver support

if( Radio.CheckRfFrequency( freq ) == false )

{

return false;

}


// Rx frequencies

if( ( freq < AU915_FIRST_RX1_CHANNEL ) ||

( freq > AU915_LAST_RX1_CHANNEL ) ||

( ( ( freq - ( uint32_t ) AU915_FIRST_RX1_CHANNEL ) % ( uint32_t ) AU915_STEPWIDTH_RX1_CHANNEL ) != 0 ) )

{

return false;

}


// Tx frequencies for 125kHz

// Also includes the range for 500kHz channels

if( ( freq < 915200000 ) || ( freq > 927800000 ) )

{

return false;

}

return true;

}


static TimerTime_t GetTimeOnAir( int8_t datarate, uint16_t pktLen )

{

int8_t phyDr = DataratesAU915[datarate];

uint32_t bandwidth = RegionCommonGetBandwidth( datarate, BandwidthsAU915 );


return Radio.TimeOnAir( MODEM_LORA, bandwidth, phyDr, 1, 8, false, pktLen, true );

}

#endif /* REGION_AU915 */


PhyParam_t RegionAU915GetPhyParam( GetPhyParams_t* getPhy )

{

PhyParam_t phyParam = { 0 };


#if defined( REGION_AU915 )

switch( getPhy->Attribute )

{

case PHY_MIN_RX_DR:

{

if( getPhy->DownlinkDwellTime == 0)

{

phyParam.Value = AU915_RX_MIN_DATARATE;

}

else

{

phyParam.Value = AU915_DWELL_LIMIT_DATARATE;

}

break;

}

case PHY_MIN_TX_DR:

{

if( getPhy->UplinkDwellTime == 0)

{

phyParam.Value = AU915_TX_MIN_DATARATE;

}

else

{

phyParam.Value = AU915_DWELL_LIMIT_DATARATE;

}

break;

}

case PHY_DEF_TX_DR:

{

phyParam.Value = AU915_DEFAULT_DATARATE;

break;

}

case PHY_NEXT_LOWER_TX_DR:

{

RegionCommonGetNextLowerTxDrParams_t nextLowerTxDrParams =

{

.CurrentDr = getPhy->Datarate,

.MaxDr = ( int8_t )AU915_TX_MAX_DATARATE,

.MinDr = ( int8_t )( ( getPhy->UplinkDwellTime == 0 ) ? AU915_TX_MIN_DATARATE : AU915_DWELL_LIMIT_DATARATE ),

.NbChannels = AU915_MAX_NB_CHANNELS,

.ChannelsMask = RegionNvmGroup2->ChannelsMask,

.Channels = RegionNvmGroup2->Channels,

};

phyParam.Value = RegionCommonGetNextLowerTxDr( &nextLowerTxDrParams );

break;

}

case PHY_MAX_TX_POWER:

{

phyParam.Value = AU915_MAX_TX_POWER;

break;

}

case PHY_DEF_TX_POWER:

{

phyParam.Value = AU915_DEFAULT_TX_POWER;

break;

}

case PHY_DEF_ADR_ACK_LIMIT:

{

phyParam.Value = REGION_COMMON_DEFAULT_ADR_ACK_LIMIT;

break;

}

case PHY_DEF_ADR_ACK_DELAY:

{

phyParam.Value = REGION_COMMON_DEFAULT_ADR_ACK_DELAY;

break;

}

case PHY_MAX_PAYLOAD:

{

if( getPhy->UplinkDwellTime == 0 )

{

phyParam.Value = MaxPayloadOfDatarateDwell0AU915[getPhy->Datarate];

}

else

{

phyParam.Value = MaxPayloadOfDatarateDwell1AU915[getPhy->Datarate];

}

break;

}

/* ST_WORKAROUND_BEGIN: Keep repeater feature */

case PHY_MAX_PAYLOAD_REPEATER:

{

if( getPhy->UplinkDwellTime == 0)

{

phyParam.Value = MaxPayloadOfDatarateRepeaterDwell0AU915[getPhy->Datarate];

}

else

{

phyParam.Value = MaxPayloadOfDatarateRepeaterDwell1AU915[getPhy->Datarate];

}

break;

}

/* ST_WORKAROUND_END */

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 = REGION_COMMON_DEFAULT_RECEIVE_DELAY1;

break;

}

case PHY_RECEIVE_DELAY2:

{

phyParam.Value = REGION_COMMON_DEFAULT_RECEIVE_DELAY2;

break;

}

case PHY_JOIN_ACCEPT_DELAY1:

{

phyParam.Value = REGION_COMMON_DEFAULT_JOIN_ACCEPT_DELAY1;

break;

}

case PHY_JOIN_ACCEPT_DELAY2:

{

phyParam.Value = REGION_COMMON_DEFAULT_JOIN_ACCEPT_DELAY2;

break;

}

#if (defined( REGION_VERSION ) && ( REGION_VERSION == 0x01010003 ))

case PHY_MAX_FCNT_GAP:

{

phyParam.Value = REGION_COMMON_DEFAULT_MAX_FCNT_GAP;

break;

}

case PHY_ACK_TIMEOUT:

{

phyParam.Value = ( REGION_COMMON_DEFAULT_ACK_TIMEOUT + randr( -REGION_COMMON_DEFAULT_ACK_TIMEOUT_RND, REGION_COMMON_DEFAULT_ACK_TIMEOUT_RND ) );

break;

}

#elif (defined( REGION_VERSION ) && ( REGION_VERSION == 0x02010001 ))

case PHY_RETRANSMIT_TIMEOUT:

{

phyParam.Value = ( REGION_COMMON_DEFAULT_RETRANSMIT_TIMEOUT + randr( -REGION_COMMON_DEFAULT_RETRANSMIT_TIMEOUT_RND, REGION_COMMON_DEFAULT_RETRANSMIT_TIMEOUT_RND ) );

break;

}

#endif /* REGION_VERSION */

case PHY_DEF_DR1_OFFSET:

{

phyParam.Value = REGION_COMMON_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 = RegionNvmGroup2->ChannelsMask;

break;

}

case PHY_CHANNELS_DEFAULT_MASK:

{

phyParam.ChannelsMask = RegionNvmGroup2->ChannelsDefaultMask;

break;

}

case PHY_MAX_NB_CHANNELS:

{

phyParam.Value = AU915_MAX_NB_CHANNELS;

break;

}

case PHY_CHANNELS:

{

phyParam.Channels = RegionNvmGroup2->Channels;

break;

}

case PHY_DEF_UPLINK_DWELL_TIME:

{

phyParam.Value = AU915_DEFAULT_UPLINK_DWELL_TIME;

break;

}

case PHY_DEF_DOWNLINK_DWELL_TIME:

{

phyParam.Value = REGION_COMMON_DEFAULT_DOWNLINK_DWELL_TIME;

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_BEACON_CHANNEL_FREQ:

{

phyParam.Value = RegionBaseUSCalcDownlinkFrequency( getPhy->Channel,

AU915_BEACON_CHANNEL_FREQ,

AU915_BEACON_CHANNEL_STEPWIDTH );

break;

}

case PHY_BEACON_FORMAT:

{

phyParam.BeaconFormat.BeaconSize = AU915_BEACON_SIZE;

phyParam.BeaconFormat.Rfu1Size = AU915_RFU1_SIZE;

phyParam.BeaconFormat.Rfu2Size = AU915_RFU2_SIZE;

break;

}

case PHY_BEACON_CHANNEL_DR:

{

phyParam.Value = AU915_BEACON_CHANNEL_DR;

break;

}

case PHY_BEACON_NB_CHANNELS:

{

phyParam.Value = AU915_BEACON_NB_CHANNELS;

break;

}

case PHY_PING_SLOT_CHANNEL_FREQ:

{

phyParam.Value = RegionBaseUSCalcDownlinkFrequency( getPhy->Channel,

AU915_PING_SLOT_CHANNEL_FREQ,

AU915_BEACON_CHANNEL_STEPWIDTH );

break;

}

case PHY_PING_SLOT_CHANNEL_DR:

{

phyParam.Value = AU915_PING_SLOT_CHANNEL_DR;

break;

}

case PHY_PING_SLOT_NB_CHANNELS:

{

phyParam.Value = AU915_BEACON_NB_CHANNELS;

break;

}

case PHY_SF_FROM_DR:

{

phyParam.Value = DataratesAU915[getPhy->Datarate];

break;

}

case PHY_BW_FROM_DR:

{

phyParam.Value = RegionCommonGetBandwidth( getPhy->Datarate, BandwidthsAU915 );

break;

}

default:

{

break;

}

}


#endif /* REGION_AU915 */

return phyParam;

}


void RegionAU915SetBandTxDone( SetBandTxDoneParams_t* txDone )

{

#if defined( REGION_AU915 )

#if (defined( REGION_VERSION ) && ( REGION_VERSION == 0x01010003 ))

RegionCommonSetBandTxDone( &RegionNvmGroup1->Bands[RegionNvmGroup2->Channels[txDone->Channel].Band],

txDone->LastTxAirTime, txDone->Joined, txDone->ElapsedTimeSinceStartUp );

#elif (defined( REGION_VERSION ) && ( REGION_VERSION == 0x02010001 ))

RegionCommonSetBandTxDone( &RegionBands[RegionNvmGroup2->Channels[txDone->Channel].Band],

txDone->LastTxAirTime, txDone->Joined, txDone->ElapsedTimeSinceStartUp );

#endif /* REGION_VERSION */

#endif /* REGION_AU915 */

}


void RegionAU915InitDefaults( InitDefaultsParams_t* params )

{

#if defined( REGION_AU915 )

Band_t bands[AU915_MAX_NB_BANDS] =

{

AU915_BAND0

};


switch( params->Type )

{

case INIT_TYPE_DEFAULTS:

{

if( ( params->NvmGroup1 == NULL ) || ( params->NvmGroup2 == NULL ) )

{

return;

}


RegionNvmGroup1 = (RegionNvmDataGroup1_t*) params->NvmGroup1;

RegionNvmGroup2 = (RegionNvmDataGroup2_t*) params->NvmGroup2;

#if (defined( REGION_VERSION ) && ( REGION_VERSION == 0x02010001 ))

RegionBands = (Band_t*) params->Bands;

#endif /* REGION_VERSION */


// Initialize 8 bit channel groups index

RegionNvmGroup1->JoinChannelGroupsCurrentIndex = 0;


// Initialize the join trials counter

RegionNvmGroup1->JoinTrialsCounter = 0;


// Default bands

#if (defined( REGION_VERSION ) && ( REGION_VERSION == 0x01010003 ))

memcpy1( ( uint8_t* )RegionNvmGroup1->Bands, ( uint8_t* )bands, sizeof( Band_t ) * AU915_MAX_NB_BANDS );

#elif (defined( REGION_VERSION ) && ( REGION_VERSION == 0x02010001 ))

memcpy1( ( uint8_t* )RegionBands, ( uint8_t* )bands, sizeof( Band_t ) * AU915_MAX_NB_BANDS );

#endif /* REGION_VERSION */


// Channels

for( uint8_t i = 0; i < AU915_MAX_NB_CHANNELS - 8; i++ )

{

// 125 kHz channels

RegionNvmGroup2->Channels[i].Frequency = 915200000 + i * 200000;

RegionNvmGroup2->Channels[i].DrRange.Value = ( DR_5 << 4 ) | DR_0;

RegionNvmGroup2->Channels[i].Band = 0;

}

for( uint8_t i = AU915_MAX_NB_CHANNELS - 8; i < AU915_MAX_NB_CHANNELS; i++ )

{

// 500 kHz channels

RegionNvmGroup2->Channels[i].Frequency = 915900000 + ( i - ( AU915_MAX_NB_CHANNELS - 8 ) ) * 1600000;

RegionNvmGroup2->Channels[i].DrRange.Value = ( DR_6 << 4 ) | DR_6;

RegionNvmGroup2->Channels[i].Band = 0;

}


// Initialize channels default mask

/* ST_WORKAROUND_BEGIN: Hybrid mode */

#if ( HYBRID_ENABLED == 1 )

RegionNvmGroup2->ChannelsDefaultMask[0] = HYBRID_DEFAULT_MASK0;

RegionNvmGroup2->ChannelsDefaultMask[1] = HYBRID_DEFAULT_MASK1;

RegionNvmGroup2->ChannelsDefaultMask[2] = HYBRID_DEFAULT_MASK2;

RegionNvmGroup2->ChannelsDefaultMask[3] = HYBRID_DEFAULT_MASK3;

RegionNvmGroup2->ChannelsDefaultMask[4] = HYBRID_DEFAULT_MASK4;

RegionNvmGroup2->ChannelsDefaultMask[5] = 0x0000;

#else

RegionNvmGroup2->ChannelsDefaultMask[0] = 0x00FF;

RegionNvmGroup2->ChannelsDefaultMask[1] = 0x0000;

RegionNvmGroup2->ChannelsDefaultMask[2] = 0x0000;

RegionNvmGroup2->ChannelsDefaultMask[3] = 0x0000;

RegionNvmGroup2->ChannelsDefaultMask[4] = 0x0000;

RegionNvmGroup2->ChannelsDefaultMask[5] = 0x0000;

#endif /* HYBRID_ENABLED == 1 */

/* ST_WORKAROUND_END */


// Copy channels default mask

RegionCommonChanMaskCopy( RegionNvmGroup2->ChannelsMask, RegionNvmGroup2->ChannelsDefaultMask, CHANNELS_MASK_SIZE );


// Copy into channels mask remaining

RegionCommonChanMaskCopy( RegionNvmGroup1->ChannelsMaskRemaining, RegionNvmGroup2->ChannelsMask, CHANNELS_MASK_SIZE );

break;

}

case INIT_TYPE_RESET_TO_DEFAULT_CHANNELS:

{

// Intentional fallthrough

}

case INIT_TYPE_ACTIVATE_DEFAULT_CHANNELS:

{

// Copy channels default mask

RegionCommonChanMaskCopy( RegionNvmGroup2->ChannelsMask, RegionNvmGroup2->ChannelsDefaultMask, CHANNELS_MASK_SIZE );


for( uint8_t i = 0; i < CHANNELS_MASK_SIZE; i++ )

{ // Copy-And the channels mask

RegionNvmGroup1->ChannelsMaskRemaining[i] &= RegionNvmGroup2->ChannelsMask[i];

}

break;

}

default:

{

break;

}

}

#endif /* REGION_AU915 */

}


bool RegionAU915Verify( VerifyParams_t* verify, PhyAttribute_t phyAttribute )

{

#if defined( REGION_AU915 )

switch( phyAttribute )

{

case PHY_FREQUENCY:

{

return VerifyRfFreq( verify->Frequency );

}

case PHY_TX_DR:

case PHY_DEF_TX_DR:

{

if( verify->DatarateParams.UplinkDwellTime == 0 )

{

return RegionCommonValueInRange( verify->DatarateParams.Datarate, AU915_TX_MIN_DATARATE, AU915_TX_MAX_DATARATE );

}

else

{

return RegionCommonValueInRange( verify->DatarateParams.Datarate, AU915_DWELL_LIMIT_DATARATE, AU915_TX_MAX_DATARATE );

}

}

case PHY_RX_DR:

{

if( verify->DatarateParams.UplinkDwellTime == 0 )

{

return RegionCommonValueInRange( verify->DatarateParams.Datarate, AU915_RX_MIN_DATARATE, AU915_RX_MAX_DATARATE );

}

else

{

return RegionCommonValueInRange( verify->DatarateParams.Datarate, AU915_DWELL_LIMIT_DATARATE, AU915_RX_MAX_DATARATE );

}

}

case PHY_DEF_TX_POWER:

case PHY_TX_POWER:

{

// Remark: switched min and max!

return RegionCommonValueInRange( verify->TxPower, AU915_MAX_TX_POWER, AU915_MIN_TX_POWER );

}

case PHY_DUTY_CYCLE:

{

return AU915_DUTY_CYCLE_ENABLED;

}

default:

return false;

}

#else

return false;

#endif /* REGION_AU915 */

}


void RegionAU915ApplyCFList( ApplyCFListParams_t* applyCFList )

{

#if defined( REGION_AU915 )

// Size of the optional CF list must be 16 byte

if( applyCFList->Size != 16 )

{

return;

}


// Last byte CFListType must be 0x01 to indicate the CFList contains a series of ChMask fields

if( applyCFList->Payload[15] != 0x01 )

{

return;

}


// ChMask0 - ChMask4 must be set (every ChMask has 16 bit)

for( uint8_t chMaskItr = 0, cntPayload = 0; chMaskItr <= 4; chMaskItr++, cntPayload+=2 )

{

RegionNvmGroup2->ChannelsMask[chMaskItr] = (uint16_t) (0x00FF & applyCFList->Payload[cntPayload]);

RegionNvmGroup2->ChannelsMask[chMaskItr] |= (uint16_t) (applyCFList->Payload[cntPayload+1] << 8);

if( chMaskItr == 4 )

{

RegionNvmGroup2->ChannelsMask[chMaskItr] = RegionNvmGroup2->ChannelsMask[chMaskItr] & CHANNELS_MASK_500KHZ_MASK;

}

// Set the channel mask to the remaining

RegionNvmGroup1->ChannelsMaskRemaining[chMaskItr] &= RegionNvmGroup2->ChannelsMask[chMaskItr];

}

#endif /* REGION_AU915 */

}


bool RegionAU915ChanMaskSet( ChanMaskSetParams_t* chanMaskSet )

{

#if defined( REGION_AU915 )

switch( chanMaskSet->ChannelsMaskType )

{

case CHANNELS_MASK:

{

RegionCommonChanMaskCopy( RegionNvmGroup2->ChannelsMask, chanMaskSet->ChannelsMaskIn, CHANNELS_MASK_SIZE );


RegionNvmGroup2->ChannelsDefaultMask[4] = RegionNvmGroup2->ChannelsDefaultMask[4] & CHANNELS_MASK_500KHZ_MASK;

RegionNvmGroup2->ChannelsDefaultMask[5] = 0x0000;


for( uint8_t i = 0; i < 6; i++ )

{ // Copy-And the channels mask

RegionNvmGroup1->ChannelsMaskRemaining[i] &= RegionNvmGroup2->ChannelsMask[i];

}

break;

}

case CHANNELS_DEFAULT_MASK:

{

RegionCommonChanMaskCopy( RegionNvmGroup2->ChannelsDefaultMask, chanMaskSet->ChannelsMaskIn, CHANNELS_MASK_SIZE );

break;

}

default:

return false;

}

return true;

#else

return false;

#endif /* REGION_AU915 */

}


void RegionAU915ComputeRxWindowParameters( int8_t datarate, uint8_t minRxSymbols, uint32_t rxError, RxConfigParams_t *rxConfigParams )

{

#if defined( REGION_AU915 )

uint32_t tSymbolInUs = 0;


// Get the datarate, perform a boundary check

rxConfigParams->Datarate = MIN( datarate, AU915_RX_MAX_DATARATE );

rxConfigParams->Bandwidth = RegionCommonGetBandwidth( rxConfigParams->Datarate, BandwidthsAU915 );


tSymbolInUs = RegionCommonComputeSymbolTimeLoRa( DataratesAU915[rxConfigParams->Datarate], BandwidthsAU915[rxConfigParams->Datarate] );


RegionCommonComputeRxWindowParameters( tSymbolInUs, minRxSymbols, rxError, Radio.GetWakeupTime( ), &rxConfigParams->WindowTimeout, &rxConfigParams->WindowOffset );

#endif /* REGION_AU915 */

}


bool RegionAU915RxConfig( RxConfigParams_t* rxConfig, int8_t* datarate )

{

#if defined( REGION_AU915 )

int8_t dr = rxConfig->Datarate;

uint8_t maxPayload = 0;

int8_t phyDr = 0;

uint32_t frequency = rxConfig->Frequency;


if( Radio.GetStatus( ) != RF_IDLE )

{

return false;

}


if( rxConfig->RxSlot == RX_SLOT_WIN_1 )

{

// Apply window 1 frequency

frequency = AU915_FIRST_RX1_CHANNEL + ( rxConfig->Channel % 8 ) * AU915_STEPWIDTH_RX1_CHANNEL;

}


// Read the physical datarate from the datarates table

phyDr = DataratesAU915[dr];


Radio.SetChannel( frequency );


// Radio configuration

Radio.SetRxConfig( MODEM_LORA, rxConfig->Bandwidth, phyDr, 1, 0, 8, rxConfig->WindowTimeout, false, 0, false, 0, 0, true, rxConfig->RxContinuous );


/* ST_WORKAROUND_BEGIN: Keep repeater feature */

if( rxConfig->RepeaterSupport == true )

{

maxPayload = MaxPayloadOfDatarateRepeaterDwell0AU915[dr];

}

else

{

maxPayload = MaxPayloadOfDatarateDwell0AU915[dr];

}

Radio.SetMaxPayloadLength( MODEM_LORA, maxPayload + LORAMAC_FRAME_PAYLOAD_OVERHEAD_SIZE );

/* ST_WORKAROUND_END */


/* ST_WORKAROUND_BEGIN: Print Rx config */

RegionCommonRxConfigPrint(rxConfig->RxSlot, frequency, dr);

/* ST_WORKAROUND_END */


*datarate = (uint8_t) dr;

return true;

#else

return false;

#endif /* REGION_AU915 */

}


bool RegionAU915TxConfig( TxConfigParams_t* txConfig, int8_t* txPower, TimerTime_t* txTimeOnAir )

{

#if defined( REGION_AU915 )

int8_t phyDr = DataratesAU915[txConfig->Datarate];

#if (defined( REGION_VERSION ) && ( REGION_VERSION == 0x01010003 ))

int8_t txPowerLimited = RegionCommonLimitTxPower( txConfig->TxPower, RegionNvmGroup1->Bands[RegionNvmGroup2->Channels[txConfig->Channel].Band].TxMaxPower );

#elif (defined( REGION_VERSION ) && ( REGION_VERSION == 0x02010001 ))

int8_t txPowerLimited = RegionCommonLimitTxPower( txConfig->TxPower, RegionBands[RegionNvmGroup2->Channels[txConfig->Channel].Band].TxMaxPower );

#endif /* REGION_VERSION */

uint32_t bandwidth = RegionCommonGetBandwidth( txConfig->Datarate, BandwidthsAU915 );

int8_t phyTxPower = 0;


// Calculate physical TX power

phyTxPower = RegionCommonComputeTxPower( txPowerLimited, txConfig->MaxEirp, txConfig->AntennaGain );


// Setup the radio frequency

Radio.SetChannel( RegionNvmGroup2->Channels[txConfig->Channel].Frequency );


Radio.SetTxConfig( MODEM_LORA, phyTxPower, 0, bandwidth, phyDr, 1, 8, false, true, 0, 0, false, 4000 );

/* ST_WORKAROUND_BEGIN: Print Tx config */

RegionCommonTxConfigPrint(RegionNvmGroup2->Channels[txConfig->Channel].Frequency, txConfig->Datarate);

/* ST_WORKAROUND_END */


// Setup maximum payload length of the radio driver

Radio.SetMaxPayloadLength( MODEM_LORA, txConfig->PktLen );


// Update time-on-air

*txTimeOnAir = GetTimeOnAir( txConfig->Datarate, txConfig->PktLen );


*txPower = txPowerLimited;

return true;

#else

return false;

#endif /* REGION_AU915 */

}


uint8_t RegionAU915LinkAdrReq( LinkAdrReqParams_t* linkAdrReq, int8_t* drOut, int8_t* txPowOut, uint8_t* nbRepOut, uint8_t* nbBytesParsed )

{

uint8_t status = 0x07;

#if defined( REGION_AU915 )

RegionCommonLinkAdrParams_t linkAdrParams = { 0 };

uint8_t nextIndex = 0;

uint8_t bytesProcessed = 0;

uint16_t channelsMask[6] = { 0, 0, 0, 0, 0, 0 };

GetPhyParams_t getPhy;

PhyParam_t phyParam;

RegionCommonLinkAdrReqVerifyParams_t linkAdrVerifyParams;


// Initialize local copy of channels mask

RegionCommonChanMaskCopy( channelsMask, RegionNvmGroup2->ChannelsMask, 6 );


while( bytesProcessed < linkAdrReq->PayloadSize )

{

nextIndex = RegionCommonParseLinkAdrReq( &( linkAdrReq->Payload[bytesProcessed] ), &linkAdrParams );


if( nextIndex == 0 )

break; // break loop, since no more request has been found


// Update bytes processed

bytesProcessed += nextIndex;


// Revert status, as we only check the last ADR request for the channel mask KO

status = 0x07;


if( linkAdrParams.ChMaskCtrl == 6 )

{

// Enable all 125 kHz channels

channelsMask[0] = 0xFFFF;

channelsMask[1] = 0xFFFF;

channelsMask[2] = 0xFFFF;

channelsMask[3] = 0xFFFF;

// Apply chMask to channels 64 to 71

channelsMask[4] = linkAdrParams.ChMask & CHANNELS_MASK_500KHZ_MASK;

}

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 & CHANNELS_MASK_500KHZ_MASK;

}

else if( linkAdrParams.ChMaskCtrl == 5 )

{

// Start value for comparison

uint8_t bitMask = 1;


// cntChannelMask for channelsMask[0] until channelsMask[3]

uint8_t cntChannelMask = 0;


// i will be 1, 2, 3, ..., 7

for( uint8_t i = 0; i <= 7; i++ )

{

// 8 MSBs of ChMask are RFU

// Checking if the ChMask is set, then true

if( ( ( linkAdrParams.ChMask & 0x00FF ) & ( bitMask << i ) ) != 0 )

{

if( ( i % 2 ) == 0 )

{

// Enable a bank of 8 125kHz channels, 8 LSBs

channelsMask[cntChannelMask] |= 0x00FF;

// Enable the corresponding 500kHz channel

channelsMask[4] |= ( bitMask << i );

}

else

{

// Enable a bank of 8 125kHz channels, 8 MSBs

channelsMask[cntChannelMask] |= 0xFF00;

// Enable the corresponding 500kHz channel

channelsMask[4] |= ( bitMask << i );

// cntChannelMask increment for uneven i

cntChannelMask++;

}

}

// ChMask is not set

else

{

if( ( i % 2 ) == 0 )

{

// Disable a bank of 8 125kHz channels, 8 LSBs

channelsMask[cntChannelMask] &= 0xFF00;

// Disable the corresponding 500kHz channel

channelsMask[4] &= ~( bitMask << i );

}

else

{

// Enable a bank of 8 125kHz channels, 8 MSBs

channelsMask[cntChannelMask] &= 0x00FF;

// Disable the corresponding 500kHz channel

channelsMask[4] &= ~( bitMask << i );

// cntChannelMask increment for uneven i

cntChannelMask++;

}

}

}

}

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 ) && ( RegionCommonCountChannels( 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 = RegionAU915GetPhyParam( &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 = RegionNvmGroup2->Channels;

linkAdrVerifyParams.MinTxPower = AU915_MIN_TX_POWER;

linkAdrVerifyParams.MaxTxPower = AU915_MAX_TX_POWER;

linkAdrVerifyParams.Version = linkAdrReq->Version;


// Verify the parameters and update, if necessary

status = RegionCommonLinkAdrReqVerifyParams( &linkAdrVerifyParams, &linkAdrParams.Datarate, &linkAdrParams.TxPower, &linkAdrParams.NbRep );


// Update channelsMask if everything is correct

if( status == 0x07 )

{

// Copy Mask

RegionCommonChanMaskCopy( RegionNvmGroup2->ChannelsMask, channelsMask, 6 );


RegionNvmGroup1->ChannelsMaskRemaining[0] &= RegionNvmGroup2->ChannelsMask[0];

RegionNvmGroup1->ChannelsMaskRemaining[1] &= RegionNvmGroup2->ChannelsMask[1];

RegionNvmGroup1->ChannelsMaskRemaining[2] &= RegionNvmGroup2->ChannelsMask[2];

RegionNvmGroup1->ChannelsMaskRemaining[3] &= RegionNvmGroup2->ChannelsMask[3];

RegionNvmGroup1->ChannelsMaskRemaining[4] = RegionNvmGroup2->ChannelsMask[4];

RegionNvmGroup1->ChannelsMaskRemaining[5] = RegionNvmGroup2->ChannelsMask[5];

}


// Update status variables

*drOut = linkAdrParams.Datarate;

*txPowOut = linkAdrParams.TxPower;

*nbRepOut = linkAdrParams.NbRep;

*nbBytesParsed = bytesProcessed;


#endif /* REGION_AU915 */

return status;

}


uint8_t RegionAU915RxParamSetupReq( RxParamSetupReqParams_t* rxParamSetupReq )

{

uint8_t status = 0x07;

#if defined( REGION_AU915 )


// Verify radio frequency

if( VerifyRfFreq( rxParamSetupReq->Frequency ) == false )

{

status &= 0xFE; // Channel frequency KO

}


// Verify datarate

if( RegionCommonValueInRange( rxParamSetupReq->Datarate, AU915_RX_MIN_DATARATE, AU915_RX_MAX_DATARATE ) == false )

{

status &= 0xFD; // Datarate KO

}

if( ( rxParamSetupReq->Datarate == DR_7 ) ||

( rxParamSetupReq->Datarate > DR_13 ) )

{

status &= 0xFD; // Datarate KO

}


// Verify datarate offset

if( RegionCommonValueInRange( rxParamSetupReq->DrOffset, AU915_MIN_RX1_DR_OFFSET, AU915_MAX_RX1_DR_OFFSET ) == false )

{

status &= 0xFB; // Rx1DrOffset range KO

}


#endif /* REGION_AU915 */

return status;

}



uint8_t RegionAU915NewChannelReq( NewChannelReqParams_t* newChannelReq )

{

// Do not accept the request

return -1;

}


int8_t RegionAU915TxParamSetupReq( TxParamSetupReqParams_t* txParamSetupReq )

{

// Accept the request

return 0;

}


uint8_t RegionAU915DlChannelReq( DlChannelReqParams_t* dlChannelReq )

{

// Do not accept the request

return -1;

}


int8_t RegionAU915AlternateDr( int8_t currentDr, AlternateDrType_t type )

{

#if defined( REGION_AU915 )

// Alternates the data rate according to the channel sequence:

// Eight times a 125kHz DR_2 and then one 500kHz DR_6 channel

if( type == ALTERNATE_DR )

{

RegionNvmGroup1->JoinTrialsCounter++;

}

else

{

RegionNvmGroup1->JoinTrialsCounter--;

}


if( RegionNvmGroup1->JoinTrialsCounter % 9 == 0 )

{

// Use DR_6 every 9th times.

currentDr = DR_6;

}

else

{

currentDr = DR_2;

}

return currentDr;

#else

return -1;

#endif /* REGION_AU915 */

}


LoRaMacStatus_t RegionAU915NextChannel( NextChanParams_t* nextChanParams, uint8_t* channel, TimerTime_t* time, TimerTime_t* aggregatedTimeOff )

{

#if defined( REGION_AU915 )

uint8_t nbEnabledChannels = 0;

uint8_t nbRestrictedChannels = 0;

uint8_t enabledChannels[AU915_MAX_NB_CHANNELS] = { 0 };

RegionCommonIdentifyChannelsParam_t identifyChannelsParam;

RegionCommonCountNbOfEnabledChannelsParams_t countChannelsParams;

LoRaMacStatus_t status = LORAMAC_STATUS_NO_CHANNEL_FOUND;


// Count 125kHz channels

if( RegionCommonCountChannels( RegionNvmGroup1->ChannelsMaskRemaining, 0, 4 ) == 0 )

{ // Reactivate default channels

RegionCommonChanMaskCopy( RegionNvmGroup1->ChannelsMaskRemaining, RegionNvmGroup2->ChannelsMask, 4 );


RegionNvmGroup1->JoinChannelGroupsCurrentIndex = 0;

}

// Check other channels

if( nextChanParams->Datarate >= DR_6 )

{

if( ( RegionNvmGroup1->ChannelsMaskRemaining[4] & CHANNELS_MASK_500KHZ_MASK ) == 0 )

{

RegionNvmGroup1->ChannelsMaskRemaining[4] = RegionNvmGroup2->ChannelsMask[4];

}

}


// Search how many channels are enabled

countChannelsParams.Joined = nextChanParams->Joined;

countChannelsParams.Datarate = nextChanParams->Datarate;

countChannelsParams.ChannelsMask = RegionNvmGroup1->ChannelsMaskRemaining;

countChannelsParams.Channels = RegionNvmGroup2->Channels;

#if (defined( REGION_VERSION ) && ( REGION_VERSION == 0x01010003 ))

countChannelsParams.Bands = RegionNvmGroup1->Bands;

#elif (defined( REGION_VERSION ) && ( REGION_VERSION == 0x02010001 ))

countChannelsParams.Bands = RegionBands;

#endif /* REGION_VERSION */

countChannelsParams.MaxNbChannels = AU915_MAX_NB_CHANNELS;

countChannelsParams.JoinChannels = NULL;


identifyChannelsParam.AggrTimeOff = nextChanParams->AggrTimeOff;

identifyChannelsParam.LastAggrTx = nextChanParams->LastAggrTx;

identifyChannelsParam.DutyCycleEnabled = nextChanParams->DutyCycleEnabled;

identifyChannelsParam.MaxBands = AU915_MAX_NB_BANDS;


identifyChannelsParam.ElapsedTimeSinceStartUp = nextChanParams->ElapsedTimeSinceStartUp;

identifyChannelsParam.LastTxIsJoinRequest = nextChanParams->LastTxIsJoinRequest;

identifyChannelsParam.ExpectedTimeOnAir = GetTimeOnAir( nextChanParams->Datarate, nextChanParams->PktLen );


identifyChannelsParam.CountNbOfEnabledChannelsParam = &countChannelsParams;


status = RegionCommonIdentifyChannels( &identifyChannelsParam, aggregatedTimeOff, enabledChannels,

&nbEnabledChannels, &nbRestrictedChannels, time );


if( status == LORAMAC_STATUS_OK )

{

if( nextChanParams->Joined == true )

{

// Choose randomly on of the remaining channels

*channel = enabledChannels[randr( 0, nbEnabledChannels - 1 )];

}

else

{

// For rapid network acquisition in mixed gateway channel plan environments, the device

// follow a random channel selection sequence. It probes alternating one out of a

// group of eight 125 kHz channels followed by probing one 500 kHz channel each pass.

// Each time a 125 kHz channel will be selected from another group.


// 125kHz Channels (0 - 63) DR2

if( nextChanParams->Datarate == DR_2 )

{

if( RegionBaseUSComputeNext125kHzJoinChannel( ( uint16_t* ) RegionNvmGroup1->ChannelsMaskRemaining,

&RegionNvmGroup1->JoinChannelGroupsCurrentIndex, channel ) == LORAMAC_STATUS_PARAMETER_INVALID )

{

return LORAMAC_STATUS_PARAMETER_INVALID;

}

}

// 500kHz Channels (64 - 71) DR6

else

{

// Choose the next available channel

uint8_t i = 0;

while( ( ( RegionNvmGroup1->ChannelsMaskRemaining[4] & CHANNELS_MASK_500KHZ_MASK ) & ( 1 << i ) ) == 0 )

{

i++;

}

*channel = 64 + i;

}

}


// Disable the channel in the mask

RegionCommonChanDisable( RegionNvmGroup1->ChannelsMaskRemaining, *channel, AU915_MAX_NB_CHANNELS );

}

return status;

#else

return LORAMAC_STATUS_NO_CHANNEL_FOUND;

#endif /* REGION_AU915 */

}


LoRaMacStatus_t RegionAU915ChannelAdd( ChannelAddParams_t* channelAdd )

{

return LORAMAC_STATUS_PARAMETER_INVALID;

}


bool RegionAU915ChannelsRemove( ChannelRemoveParams_t* channelRemove )

{

return LORAMAC_STATUS_PARAMETER_INVALID;

}


#if (defined( REGION_VERSION ) && ( REGION_VERSION == 0x01010003 ))

void RegionAU915SetContinuousWave( ContinuousWaveParams_t* continuousWave )

{

#if defined( REGION_AU915 )

int8_t txPowerLimited = RegionCommonLimitTxPower( continuousWave->TxPower, RegionNvmGroup1->Bands[RegionNvmGroup2->Channels[continuousWave->Channel].Band].TxMaxPower );

int8_t phyTxPower = 0;

uint32_t frequency = RegionNvmGroup2->Channels[continuousWave->Channel].Frequency;


// Calculate physical TX power

phyTxPower = RegionCommonComputeTxPower( txPowerLimited, continuousWave->MaxEirp, continuousWave->AntennaGain );


Radio.SetTxContinuousWave( frequency, phyTxPower, continuousWave->Timeout );

#endif /* REGION_AU915 */

}

#endif /* REGION_VERSION */


uint8_t RegionAU915ApplyDrOffset( uint8_t downlinkDwellTime, int8_t dr, int8_t drOffset )

{

#if defined( REGION_AU915 )

int8_t datarate = DatarateOffsetsAU915[dr][drOffset];


if( datarate < 0 )

{

if( downlinkDwellTime == 0 )

{

datarate = AU915_TX_MIN_DATARATE;

}

else

{

datarate = AU915_DWELL_LIMIT_DATARATE;

}

}

return datarate;

#else

return 0;

#endif /* REGION_AU915 */

}


void RegionAU915RxBeaconSetup( RxBeaconSetup_t* rxBeaconSetup, uint8_t* outDr )

{

#if defined( REGION_AU915 )

RegionCommonRxBeaconSetupParams_t regionCommonRxBeaconSetup;


regionCommonRxBeaconSetup.Datarates = DataratesAU915;

regionCommonRxBeaconSetup.Frequency = rxBeaconSetup->Frequency;

regionCommonRxBeaconSetup.BeaconSize = AU915_BEACON_SIZE;

regionCommonRxBeaconSetup.BeaconDatarate = AU915_BEACON_CHANNEL_DR;

regionCommonRxBeaconSetup.BeaconChannelBW = AU915_BEACON_CHANNEL_BW;

regionCommonRxBeaconSetup.RxTime = rxBeaconSetup->RxTime;

regionCommonRxBeaconSetup.SymbolTimeout = rxBeaconSetup->SymbolTimeout;


RegionCommonRxBeaconSetup( &regionCommonRxBeaconSetup );


// Store downlink datarate

*outDr = AU915_BEACON_CHANNEL_DR;

#endif /* REGION_AU915 */

}


Entre em contato para testes.

A VERSÃO DO LORAMAC VERSION  É 1.0.4

Também alterado

// LoRaWAN/App/lora_app.h
/* LoraWAN application configuration (Mw is configured by lorawan_conf.h) */
/* Available: LORAMAC_REGION_AS923, LORAMAC_REGION_AU915, LORAMAC_REGION_EU868, LORAMAC_REGION_KR920, LORAMAC_REGION_IN865, LORAMAC_REGION_US915, LORAMAC_REGION_RU864 */
#define ACTIVE_REGION LORAMAC_REGION_AU915 //<=====================


Este documento é um guia básico (resumo) sobre instalação do SDK da WISOL para a módulo LoRa/SigFox LSM110A LoRa/Sigfox da Seongji e geração da APP como comandos AT, bem como os primeiros acessos à rede LoRaWAN e envio de pacotes com os comandos AT. Também é mostrado como configurar para trabalhar em uma faixa de frequências e região.


LSM110A Starter KIT
Módulo

O LSM110A é um módulo de última geração que integra o STMicroelectronics STM32WL. É muito menos consumo atual para o dispositivo IoT para estender a vida útil da bateria. E, também suporta ambas as tecnologias – Sigfox e LoRa – com o próprio módulo LSM110A.

Você pode trocar Sigfox ou LoRa com ele para que você também possa reduzir o custo. É altamente otimizado para solução de IoT (Alto Consumo de Energia, Baixo Custo)

A LSM110A completou a certificação verificada Sigfox Rc2, certificação Rc4 e certificação LoRaWAN versão 1.0.4 classe A, C.

Conteúdo do SDK



Baixando o SDK

No caso, foi realizado via Prompt de Comando, com o GIT já instalado no Windows, mas você pode baixar em ZIP do repositório e descompactar.


C:\>git clone https://github.com/Support-SJI/LSM110A.git




Compilação do Firmware 

Para gerar o firmware para o LSM1x0A, será necessário que você instale o STM32CubeIDE em sua máquina.


SDK Build

Ferramentas de desenvolvimento de software ST STM32CubeIDE
Após executar o STM32CubeIDE 

Escolhe seu WorkSpace preferido


Uma tela com Documentação do STM32Cube aparecerá, mas você pode fechá-la.


  • Import o SDK no menu File
  • Selecione "Projects from Folders or Archive" e então Click em Next

  •     Selecione o Folder do Projeto
C:\LSM1x0A_SDK_LoRaWAN104\Projects\NUCLEO-WL55JC\Applications\LoRaWAN_SigFox\LSM1x0A\STM32CubeIDE


  •     Click em Finish


  •     Após o projeto ser importado, ele é criado e mostrado no Project Explorer (Tab) no canto superior esquerdo



Compilando o SDK

Altere para Release o projeto


Execute Build All no menu Project




    Após fazer o Build All,um HEX é criado no folder Released



BootLoader (Importante)

A partir da versão de atualização de 2 de junho de 2022, o IAP (Bootloader) foi aplicado.

Em primeiro lugar, você precisa baixar IAP (Bootloader). 

Consulte o arquivo ReadMe.md de Utilities/1_SJITools/1_FW_Merge_Tool para gerar e baixar FW, incluindo IAP para FW gerado pelo Building do SDK.



Copie o arquivo LSM1x0A_SDK_LoRaWAN_Sigfox.hex gerado pelo STM32 CUBE IDE na pasta

C:\LSM1x0A_SDK_LoRaWAN104\Projects\NUCLEO-WL55JC\Applications\LoRaWAN_SigFox\LSM1x0A\STM32CubeIDE\Release


para a pasta

C:\LSM1x0A_SDK_LoRaWAN104\Utilities\1_SJITools\1_FW_Merge_Tool

    
    Estes são os arquivos prontos para o Merge


    Execute o seguinte comando BAT

FW_Merge_SDK.bat


    Um novo HEX será gerado

    LSM1x0A_V100_SDK_FW.hex


   
    Fazendo o UPLOAD do Firmware HEX Gerado

    Será necessário que você instale em sua máquina o STM32 CUBE Programmer
    
    Conectando S-TLINK V2 no LSM110A Starter KIT, via SWD
    

    Conecte o ST-LINK V2 na USB e execute o STM32 CUBE Programmer



    Enquanto segurando o botão Reset do LSM110A Starter KIT, pressione Connect no STM32 CUBE Programmer e libere o botão de Reset.
    

    
    Carregue agora o arquivo BOOTLOADER clicando em Open File

   C:\LSM1x0A_SDK_LoRaWAN104\Utilities\1_SJITools\1_FW_Merge_Tool\LSM_IAP_V100_220516.hex

Address: 0x08000000

Depois carregue

LSM1x0A_V100_SDK_FW.hex

    
    Click então em Start Programming



    Testando o Bootloader com o APP com comandos AT

    Conecte o LSM110A Starter KIT na USB do computador e abra um emulador de terminal na COMM que foi criada (9600,N,8,1) e veja o que deve aparecer.
    

     Aplicativo para testes com comandos AT para LoRaWAN

Fazendo o primeiro Join e publicando um HELLO! 

  • Primeiro selecione LoRaWAN (default após RESET)
  • Pegue o DevEUI de seu módulo LSM1x0A



ATENÇÃO: PARA UTILIZAR SERVIÇOS DA EVERYNET, CONTATE E PEÇA OS BROKERS.

A American Tower é uma multi nacional presente em mais de 16 países, com de 160.000 sites no mundo onde ela aluga espaço para as operadoras colocarem suas torres celulares e rádios. No Brasil ela possui mais de 19.000 sites, tendo uma ampla presença geográfica. Ela decidiu de forma pioneira no Brasil lançar uma rede LoRaWAN junto com a EveryNet, de forma a permitir o avanço do IoT.

O cliente que tem um produto que siga o padrão LoRaWAN pode contratar o serviço de dados da American Tower / EveyNet de forma a se preocupar somente com seus devices e aplicação, sem ter que se focar na infra-estrutura e gateways.





OTAA

• Vantagem: a rede gera e envia as chaves de criptografia; isto torna mais seguro. Devido ao maior nível de segurança, o OTAA é o método mais utilizado em IoT / LoRaWAN. 

• AppEUI: Este é um identificador de aplicativo exclusivo usado para agrupar objetos. este
endereço, 64 bits, é usado para classificar os dispositivos periféricos por aplicação. Essa configuração pode seja ajustado. 

• DevEUI: Este identificador, configurado de fábrica, torna cada objeto único. Em princípio, esta
configuração não pode ser ajustada. 

• AppKey: esta é uma chave secreta compartilhada entre o dispositivo periférico e a rede. É usado para determinar as chaves da sessão. Essa configuração pode ser ajustada.

Concentre-se na OTAA 

O Servido de Rede é o componente de software encarregado de estabelecer uma conexão com os objetos e gerenciando o núcleo da rede. Durante a conexão OTAA, e supondo que o dispositivo esteja autorizado a conectar-se a rede, a rede troca chaves de criptografia específicas da sessão com o núcleo da rede. O Servidor de Rede então aloca informações específicas para a sessão e as envia para o aparelho periférico:

DevAddr: Endereço lógico (equivalente a um endereço IP) que será usado para todos comunicação subseqüente.

 NetSKey (chave de sessão de rede): chave de criptografia entre o objeto e o operador usado para transmissões e para validar a integridade das mensagens. 

•   AppSKey (chave de sessão do aplicativo): chave de criptografia entre o objeto e operador (através da aplicação) utilizado para as transmissões e para validar a integridade das mensagens

1.1 Entrando na EveryNet

Passo 1: Cadastre-se uma conta de usuário no servidor EveryNet, em https://ns.atc.everynet.io




1.2 Adicionar um dispositivo EndDevice LoRaWan




Esta seção mostra como adicionar um dispositivo EndDevice LoRaWAN à rede LoRaWAN e ver os dados pelo web site da EveryNet. Usamos o LSM110A como um dispositivo de referência - a configuração para outros dispositivos LoRaWAN será semelhante.

Passo 1​: Criar uma definição de dispositivos no EveryNet

Três códigos são necessários para definir o dispositivo no EveryNet: 

Device EUI - código de identificação único para um dispositivo em particular. 
Application EUI - código de identificação para um aplicativo definido no Everynet. 
Application key - Chave exclusiva para proteger as comunicações com um dispositivo em particular.

Para o servidor EveryNet, você pode usar os códigos estabelecidos por você ou criados pelo servidor.

Pressione o sinal de + para abrir a tela abaixo e adicionar device!





Mude para Activation para OTAA e Encryption para NS

LA915-928


Dicas

Device EUI –  deixe o sistema gerar
Application EUI – deixe o sistema gerar
Application key – deixe o sistema gerar

Nota-se que há uma APP EUI já criado por EveryNet, mas esta não é a definida no dispositivo. Para adicionar o APP EUI do dispositivo LSM110A, utilize comandos AT.

Introduzir os códigos ApplicationEUI ApplicationKey obtidos do site da EveryNet e SET para cada um.




Passo 2: Ligar dispositivo LSM110A e vai juntar-se automaticamente a rede EveryNet. 


Depois de ingressar com sucesso, ele vai começar a fazer upload de mensagens para a EveryNet. Selecione a guia Dados e você vai ver os dados que aparecem no painel.

Note que isso pode levar algum tempo para que os dados do dispositivo para aparecer no visor EveryNet.

Dados são mostrados no final da página

Configuração no Servidor final.

Não esquecer de especificar "LoRaWAN protocol version" que você está utilizando em seu EndDevice (LoRaWAN protocol version)



  • Configure agora o módulo LSM1x0A
Region Band (AU915)
Get EUI
Set CLASS A
Adaptive DataRate (ON)
App Key
App EUI
NetWork Key

TESTES

JOIN EM OTAA
JOINED
SEND BINARY DATA


DOWNLINK


Testes em um segundo KIT

AT+BAND=?

1:AU915

OK

AT+NWKID=?

0

OK

AT+DEUI=?

00:80:E1:15:05:1F:XX:XX

OK

AT+CLASS=A

OK

AT+VL=3

OK

AT+ADR=1

OK

AT+APPEUI=?

00:00:00:00:00:00:00:00

OK

AT+SEND=1:1:BBBBBBBBBB

3786s169:TX on freq 918200000 Hz at DR 2

AT_NO_NETWORK_JOINED

3786s688:MAC txDone
3791s525:RX_1 on freq 927500000 Hz at DR 10
3791s804:MAC rxDone

+EVT:JOINED

>> MCRootKey:   7A:68:49:FB:63:29:BC:63:14:71:1A:7F:59:1D:4B:FF
>> MCKEKey:     B6:54:0A:C5:86:0B:84:E8:9A:7B:20:D1:60:B2:A9:13
>> NwkSKey:     29:C2:BE:0C:6B:35:A8:1B:4F:BF:26:CF:B0:4B:7E:3B

>> AppSKey:     DE:C5:93:EF:60:6F:EE:0C:E2:B4:A0:40:C5:20:5C:02

+EVT:RX_1, PORT 0, DR 10, RSSI -38, SNR 9

Mais testes, com credenciais...

ATZ
AT+BAND=1
AT+CLASS=A
AT+VL=3
AT+ADR=1
AT+APPEUI=00:00:00:00:00:00:00:00
AT+APPKEY=09:ED:14:80:B2:AF:1D:2C:44:B4:29:A6:A6:DF:87:7B
AT+NWKKEY=09:ED:14:80:B2:AF:1D:2C:44:B4:29:A6:A6:DF:87:7B
AT+JOIN=1
AT+SEND=1:1:BBBBBBBBBB

Comandos

AT+BAND=1 <===
AT+CLASS=A <====
AT+VL=3 
AT+ADR=1 
AT+APPEUI=00:00:00:00:00:00:00:00 <===
AT+APPKEY=09:ED:14:80:B2:AF:1D:2C:44:B4:29:A6:A6:DF:87:7B <===
AT+NWKKEY=09:ED:14:80:B2:AF:1D:2C:44:B4:29:A6:A6:DF:87:7B <==
AT+JOIN=1 <===
AT+SEND=1:1:BBBBBBBBBB <====

Dúvidas

Favor ler documentos em

Kit de avaliação para módulo LoRa e Sigfox Wisol Seong JI SJI LSM110A

Operação em rede pública e privada LoRaWAN  e também ponto a ponto (P2P)

Opera também em Sigfox

Alterne entre LoRa e Sigfox por comando AT, não precisa trocar o Firmware!

Permite embarcar sua aplicação


Módulo LoRa e Sigfox Wisol Seong JI SJI LSM110A

Módulo LoRa e Sigfox compacto

Escolha entre operação LoRa e Sigfox por comando "on the fly", sem precisar trocar firmware !

LoRa: para operação redes públicas e privadas LoRaWAN bem como ponto a ponto (P2P)
Sigfox: zonas RCZ2 e RCZ4 (inclui Brasil)

Caracteristicas:

- Permite embarcar a aplicação
- Dimensão: 14x15x2,8mm
- Frequência: RCZ2 Tx 902,2MHz  Rx 905,2MHz
- Potência de saida: configurável até +22dBm
- Sensibilidade:  -129dBm@LoRa(BW=500KHz, SF=12)
                  -124dBm@Sigfox(0.6Kbps)
- Tensão de operação: 1,8 - 3,6Vdc
- Interface UART 9600 8N1
- Baixo consumo
- Na operação P2P não necessita de gateway LoRaWAN

Aplicações:
- Medição individualizada de água, energia, gás
- Automação comercial, industrial residencial;
- Rede de sensores;
- Sistemas de alarme e segurança;
- Estações meteorológicas;
- Automação agrícola.
 

NÃO TESTADO - OPENCPU (API MODE) - NÃO TESTADO

Caso queira utilizar como OpenCPU e embarcar sua aplicação:
  • utilize o SDK do STM32 
  • veja como é estruturado a troca de mensagens em (Message Sequence Chart) numa conexão com LoraWAN

Lembrando que não há nenhum exemplo no momento por parte da Smartcore ou Wisol quando utilizado como OPENCPU. Requer conhecimento em programação C baseado no STM32.


Mas estes vídeos mostram como utilizar o STM32WL com SDK da STM



Gerando HEX


Referências


  • DevNonce is too small error in the device events: If the device is using LoRaWAN MAC version 1.1 or 1.0.4, this error occurs when DevNonce is not being incremented, so the Join Server ignores Join Requests with the same or lower DevNonce value comparing to the previous one. Contact your device’s manufacturer to find out the correct LoRaWAN MAC and PHY versions, and configure the device in The Things Stack accordingly

Sobre a SMARTCORE

A SmartCore fornece módulos para comunicação wireless, biometria, conectividade, rastreamento e automação.
Nosso portfólio inclui modem 2G/3G/4G/NB-IoT/Cat.M, satelital, módulos WiFi, Bluetooth, GNSS / GPS, Sigfox, LoRa, leitor de cartão, leitor QR code, mecanismo de impressão, mini-board PC, antena, pigtail, LCD, bateria, repetidor GPS e sensores.

Mais detalhes em www.smartcore.com.br

Nenhum comentário:

Postar um comentário