/*!
 * \file      RegionCustomAType.h
 *
 * \brief     Region definition for CustomAType
 *
 * \copyright Revised BSD License, see section \ref LICENSE.
 *
 * \code
 *                ______                              _
 *               / _____)             _              | |
 *              ( (____  _____ ____ _| |_ _____  ____| |__
 *               \____ \| ___ |    (_   _) ___ |/ ___)  _ \
 *               _____) ) ____| | | || |_| ____( (___| | | |
 *              (______/|_____)_|_|_| \__)_____)\____)_| |_|
 *              (C)2013 Semtech
 *
 *               ___ _____ _   ___ _  _____ ___  ___  ___ ___
 *              / __|_   _/_\ / __| |/ / __/ _ \| _ \/ __| __|
 *              \__ \ | |/ _ \ (__| ' <| _| (_) |   / (__| _|
 *              |___/ |_/_/ \_\___|_|\_\_| \___/|_|_\\___|___|
 *              embedded.connectivity.solutions===============
 *
 * \endcode
 *
 * \author    Miguel Luis ( Semtech )
 *
 * \author    Gregory Cristian ( Semtech )
 *
 * \author    Daniel Jaeckle ( STACKFORCE )
 *
 * \author    Ray Tsou ( ASE )
 *
 * \defgroup  REGIONCustomAType Region CustomAType
 *            Implementation according to LoRaWAN Specification v1.0.2.
 * \{
 */
#ifndef __REGION_CustomAType_H__
#define __REGION_CustomAType_H__
#include "LoRaMac.h"
#include "Region.h"
#include "RegionCommon.h"
#include "qm_common.h"
//#include <LoRaMac.h>

/*!
 * LoRaMac maximum number of channels
 */
#define CustomAType_MAX_NB_CHANNELS_def                   16

/*!
 * Minimal datarate that can be used by the node
 */
#define CustomAType_TX_MIN_DATARATE                       DR_0

/*!
 * Maximal datarate that can be used by the node
 */
#define CustomAType_TX_MAX_DATARATE                       DR_7

/*!
 * Minimal datarate that can be used by the node
 */
#define CustomAType_RX_MIN_DATARATE                       DR_0

/*!
 * Maximal datarate that can be used by the node
 */
#define CustomAType_RX_MAX_DATARATE                       DR_7

/*!
 * Default datarate used by the node
 */
#define CustomAType_DEFAULT_DATARATE                      DR_0

/*!
 * Minimal Rx1 receive datarate offset
 */
#define CustomAType_MIN_RX1_DR_OFFSET                     0

/*!
 * Maximal Rx1 receive datarate offset
 */
#define CustomAType_MAX_RX1_DR_OFFSET_def                 5

/*!
 * Default Rx1 receive datarate offset
 */
#define CustomAType_DEFAULT_RX1_DR_OFFSET                 0

/*!
 * ADR Ack limit
 */
#define CustomAType_ADR_ACK_LIMIT                         64

/*!
 * ADR Ack delay
 */
#define CustomAType_ADR_ACK_DELAY                         32

/*!
 * Enabled or disabled the duty cycle
 */
#define CustomAType_DUTY_CYCLE_ENABLED                    1

/*!
 * Maximum RX window duration
 */
#define CustomAType_MAX_RX_WINDOW                         3000

/*!
 * Receive delay 1
 */
#define CustomAType_RECEIVE_DELAY1                        1000

/*!
 * Receive delay 2
 */
#define CustomAType_RECEIVE_DELAY2                        2000

/*!
 * Join accept delay 1
 */
#define CustomAType_JOIN_ACCEPT_DELAY1                    5000

/*!
 * Join accept delay 2
 */
#define CustomAType_JOIN_ACCEPT_DELAY2                    6000

/*!
 * Maximum frame counter gap
 */
#define CustomAType_MAX_FCNT_GAP                          16384

/*!
 * Ack timeout
 */
#define CustomAType_ACKTIMEOUT                            2000

/*!
 * Random ack timeout limits
 */
#define CustomAType_ACK_TIMEOUT_RND                       1000

#if ( CustomAType_DEFAULT_DATARATE > DR_5 )
#error "A default DR higher than DR_5 may lead to connectivity loss."
#endif

/*!
 * Second reception window channel frequency definition.
 */
#define CustomAType_RX_WND_2_FREQ_def                         869525000

/*!
 * Second reception window channel datarate definition.
 */
#define CustomAType_RX_WND_2_DR_def                           DR_0

/*!
 * Maximum number of bands
 */
#define CustomAType_MAX_NB_BANDS                          5

/*!
 * Band 0 definition
 * { DutyCycle, TxMaxPower, LastTxDoneTime, TimeOff }
 */
#define CustomAType_BAND0                           { 100, TX_POWER_0, 0,  0 } //  1.0 %
#define IN865_BAND0                                 { 1  , TX_POWER_0, 0,  0 } //  100.0 %
#define EU868_BAND0                                 { 100, TX_POWER_1, 0,  0 } //  1.0 %

/*!
 * Band 1 definition
 * { DutyCycle, TxMaxPower, LastTxDoneTime, TimeOff }
 */
#define EU868_BAND1                                 { 100 , TX_POWER_1, 0,  0 } //  1.0 %

/*!
 * Band 2 definition
 * Band = { DutyCycle, TxMaxPower, LastTxDoneTime, TimeOff }
 */
#define EU868_BAND2                                 { 1000, TX_POWER_1, 0,  0 } //  0.1 %

/*!
 * Band 2 definition
 * Band = { DutyCycle, TxMaxPower, LastTxDoneTime, TimeOff }
 */
#define EU868_BAND3                                 { 10  , TX_POWER_1, 0,  0 } // 10.0 %

/*!
 * Band 2 definition
 * Band = { DutyCycle, TxMaxPower, LastTxDoneTime, TimeOff }
 */
#define EU868_BAND4                                 { 100 , TX_POWER_1, 0,  0 } //  1.0 %

/*!
 * LoRaMac default channel 1
 * Channel = { Frequency [Hz], RX1 Frequency [Hz], { ( ( DrMax << 4 ) | DrMin ) }, Band }
 */
#define CustomAType_LC1                             { 868100000, 0, { ( ( DR_6 << 4 ) | DR_0 ) }, 1 }
#define EU868_LC1                                   { 868100000, 0, { ( ( DR_5 << 4 ) | DR_0 ) }, 1 }
#define CN779_LC1                                   { 779500000, 0, { ( ( DR_5 << 4 ) | DR_0 ) }, 0 }
#define EU433_LC1                                   { 433175000, 0, { ( ( DR_5 << 4 ) | DR_0 ) }, 0 }
#define IN865_LC1                                   { 865062500, 0, { ( ( DR_5 << 4 ) | DR_0 ) }, 1 }

/*!
 * LoRaMac default channel 2
 * Channel = { Frequency [Hz], RX1 Frequency [Hz], { ( ( DrMax << 4 ) | DrMin ) }, Band }
 */
#define CustomAType_LC2                             { 868300000, 0, { ( ( DR_6 << 4 ) | DR_0 ) }, 1 }
#define EU868_LC2                                   { 868300000, 0, { ( ( DR_5 << 4 ) | DR_0 ) }, 1 }
#define CN779_LC2                                   { 779700000, 0, { ( ( DR_5 << 4 ) | DR_0 ) }, 0 }
#define EU433_LC2                                   { 433375000, 0, { ( ( DR_5 << 4 ) | DR_0 ) }, 0 }
#define IN865_LC2                                   { 865402500, 0, { ( ( DR_5 << 4 ) | DR_0 ) }, 1 }


/*!
 * LoRaMac default channel 3
 * Channel = { Frequency [Hz], RX1 Frequency [Hz], { ( ( DrMax << 4 ) | DrMin ) }, Band }
 */
#define CustomAType_LC3                             { 868500000, 0, { ( ( DR_6 << 4 ) | DR_0 ) }, 1 }
#define EU868_LC3                                   { 868500000, 0, { ( ( DR_5 << 4 ) | DR_0 ) }, 1 }
#define CN779_LC3                                   { 779900000, 0, { ( ( DR_5 << 4 ) | DR_0 ) }, 0 }
#define EU433_LC3                                   { 433575000, 0, { ( ( DR_5 << 4 ) | DR_0 ) }, 0 }
#define IN865_LC3                                   { 865985000, 0, { ( ( DR_5 << 4 ) | DR_0 ) }, 1 }


/*!
 * LoRaMac channels which are allowed for the join procedure
 */
#define CustomAType_JOIN_CHANNELS                         ( uint16_t )( LC( 1 ) | LC( 2 ) | LC( 3 ) )

/*!
 * Data rates table definition
 */
static const uint8_t DataratesCustomAType[]  = { 12, 11, 10,  9,  8,  7,  7, 50 };

/*!
 * Maximum payload with respect to the datarate index. Cannot operate with repeater.
 */
static const uint8_t MaxPayloadOfDatarateCustomAType[] = { 51, 51, 51, 115, 242, 242, 242, 242 };

/*!
 * Maximum payload with respect to the datarate index. Can operate with repeater.
 */
static const uint8_t MaxPayloadOfDatarateRepeaterCustomAType[] = { 51, 51, 51, 115, 222, 222, 222, 222 };

/*!
 * Tx output powers table definition
 */

//static const int8_t TxPowersCustomAType[] = { 20, 14, 11,  8,  5,  2 };
static const int8_t TxPowersCustomAType[] = { 16, 14, 12, 10, 8, 6, 4, 2 };
static const int8_t TxPowersEU433_CN779[] = { 10, 7, 4,  1,  -2,  -5 };
//static const int8_t TxPowersIN865[] = { 20, 18, 16, 14, 12, 10, 8, 6, 4, 2, 0 };
static const int8_t TxPowersIN865[] = { 30, 28, 26, 24, 22, 20, 18, 16, 14, 12, 10 };

/*!
 * Effective datarate offsets for receive window 1.
 */
static const int8_t EffectiveRx1DrOffsetIN865[] = { 0, 1, 2, 3, 4, 5, -1, -2 };



/*!
 * \brief The function gets a value of a specific phy attribute.
 *
 * \param [IN] getPhy Pointer to the function parameters.
 */
void RegionCustomATypeGetPhyParam( GetPhyParams_t* getPhy );

/*!
 * \brief Updates the last TX done parameters of the current channel.
 *
 * \param [IN] txDone Pointer to the function parameters.
 */
void RegionCustomATypeSetBandTxDone( SetBandTxDoneParams_t* txDone );

/*!
 * \brief Initializes the channels masks and the channels.
 *
 * \param [IN] type Sets the initialization type.
 */
void RegionCustomATypeInitDefaults( InitType_t type );

/*!
 * \brief Verifies a parameter.
 *
 * \param [IN] verify Pointer to the function parameters.
 *
 * \param [IN] type Sets the initialization type.
 *
 * \retval Returns true, if the parameter is valid.
 */
bool RegionCustomATypeVerify( 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 RegionCustomATypeApplyCFList( 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 RegionCustomATypeChanMaskSet( ChanMaskSetParams_t* chanMaskSet );

/*!
 * \brief Calculates the next datarate to set, when ADR is on or off.
 *
 * \param [IN] adrNext Pointer to the function parameters.
 *
 * \param [OUT] drOut The calculated datarate for the next TX.
 *
 * \param [OUT] txPowOut The TX power for the next TX.
 *
 * \param [OUT] adrAckCounter The calculated ADR acknowledgement counter.
 *
 * \retval Returns true, if an ADR request should be performed.
 */
bool RegionCustomATypeAdrNext( AdrNextParams_t* adrNext, int8_t* drOut, int8_t* txPowOut, uint32_t* adrAckCounter );

/*!
 * \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 RegionCustomATypeRxConfig( 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 RegionCustomATypeTxConfig( TxConfigParams_t* txConfig, int8_t* txPower, uint32_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 RegionCustomATypeLinkAdrReq( 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 RegionCustomATypeRxParamSetupReq( 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 RegionCustomATypeNewChannelReq( 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 RegionCustomATypeTxParamSetupReq( 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 RegionCustomATypeDlChannelReq( DlChannelReqParams_t* dlChannelReq );

/*
 * \brief Alternates the datarate of the channel for the join request.
 *
 * \param [IN] alternateDr Pointer to the function parameters.
 *
 * \retval Datarate to apply.
 */
int8_t RegionCustomATypeAlternateDr( AlternateDrParams_t* alternateDr );

/*!
 * \brief Calculates the back-off time.
 *
 * \param [IN] calcBackOff Pointer to the function parameters.
 */
void RegionCustomATypeCalcBackOff( 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.
 *
 * \retval Function status [1: OK, 0: Unable to find a channel on the current datarate]
 */
bool RegionCustomATypeNextChannel( NextChanParams_t* nextChanParams, uint8_t* channel, uint32_t* time );

/*!
 * \brief Adds a channel.
 *
 * \param [IN] channelAdd Pointer to the function parameters.
 *
 * \retval Status of the operation.
 */
LoRaMacStatus_t RegionCustomATypeChannelAdd( 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 RegionCustomATypeChannelsRemove( ChannelRemoveParams_t* channelRemove  );

/*!
 * \brief Sets the radio into continuous wave mode.
 *
 * \param [IN] continuousWave Pointer to the function parameters.
 */
void RegionCustomATypeSetContinuousWave( ContinuousWaveParams_t* continuousWave );

void RegionCustomATypeSetPreambleLength( uint8_t CustomPreambleLength );

void RegionCustomATypeSetCustomMaxChannel( uint8_t CustomMaxChannel );

void RegionCustomATypeSetNBOfChannels( uint8_t NumbChannels);

void RegionCustomATypeSetRX2WindowFreq( uint32_t Frequency );

void RegionCustomASetRegion( LoRaMacRegion_t region);

void RegionCustomATypeTXPowerParams(uint8_t MinTxPower, uint8_t MaxTxPower, uint8_t DefaultTxPower );

void RegionCustomATypeClearTimeOff( bool dutyCycle);

/*! \} defgroup REGIONCustomAType */

#endif // __REGION_CustomAType_H__
