2018-10-02 23:08:38 +02:00
/*
* Copyright ( c ) 2014 - 2016 IBM Corporation .
2021-07-25 14:39:11 +02:00
* Copyright ( c ) 2017 , 2019 - 2021 MCCI Corporation .
2018-10-02 23:08:38 +02:00
* All rights reserved .
*
* Redistribution and use in source and binary forms , with or without
* modification , are permitted provided that the following conditions are met :
* * Redistributions of source code must retain the above copyright
* notice , this list of conditions and the following disclaimer .
* * Redistributions in binary form must reproduce the above copyright
* notice , this list of conditions and the following disclaimer in the
* documentation and / or other materials provided with the distribution .
* * Neither the name of the < organization > nor the
* names of its contributors may be used to endorse or promote products
* derived from this software without specific prior written permission .
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS " AS IS " AND
* ANY EXPRESS OR IMPLIED WARRANTIES , INCLUDING , BUT NOT LIMITED TO , THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED . IN NO EVENT SHALL < COPYRIGHT HOLDER > BE LIABLE FOR ANY
* DIRECT , INDIRECT , INCIDENTAL , SPECIAL , EXEMPLARY , OR CONSEQUENTIAL DAMAGES
* ( INCLUDING , BUT NOT LIMITED TO , PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES ;
* LOSS OF USE , DATA , OR PROFITS ; OR BUSINESS INTERRUPTION ) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY , WHETHER IN CONTRACT , STRICT LIABILITY , OR TORT
* ( INCLUDING NEGLIGENCE OR OTHERWISE ) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE , EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE .
*/
# define LMIC_DR_LEGACY 0
# include "lmic_bandplan.h"
# if defined(CFG_us915)
// ================================================================================
//
// BEG: US915 related stuff
//
CONST_TABLE ( u1_t , _DR2RPS_CRC ) [ ] = {
ILLEGAL_RPS , // [-1]
MAKERPS ( SF10 , BW125 , CR_4_5 , 0 , 0 ) , // [0]
MAKERPS ( SF9 , BW125 , CR_4_5 , 0 , 0 ) , // [1]
MAKERPS ( SF8 , BW125 , CR_4_5 , 0 , 0 ) , // [2]
MAKERPS ( SF7 , BW125 , CR_4_5 , 0 , 0 ) , // [3]
MAKERPS ( SF8 , BW500 , CR_4_5 , 0 , 0 ) , // [4]
ILLEGAL_RPS , // [5]
ILLEGAL_RPS , // [6]
ILLEGAL_RPS , // [7]
MAKERPS ( SF12 , BW500 , CR_4_5 , 0 , 0 ) , // [8]
MAKERPS ( SF11 , BW500 , CR_4_5 , 0 , 0 ) , // [9]
MAKERPS ( SF10 , BW500 , CR_4_5 , 0 , 0 ) , // [10]
MAKERPS ( SF9 , BW500 , CR_4_5 , 0 , 0 ) , // [11]
MAKERPS ( SF8 , BW500 , CR_4_5 , 0 , 0 ) , // [12]
MAKERPS ( SF7 , BW500 , CR_4_5 , 0 , 0 ) , // [13]
ILLEGAL_RPS // [14]
} ;
2021-07-25 14:39:11 +02:00
bit_t
LMICus915_validDR ( dr_t dr ) {
// use subtract here to avoid overflow
if ( dr > = LENOF_TABLE ( _DR2RPS_CRC ) - 2 )
return 0 ;
return TABLE_GET_U1 ( _DR2RPS_CRC , dr + 1 ) ! = ILLEGAL_RPS ;
}
2019-10-02 21:37:48 +02:00
static CONST_TABLE ( u1_t , maxFrameLens ) [ ] = {
19 + 5 , 61 + 5 , 133 + 5 , 250 + 5 , 250 + 5 , 0 , 0 , 0 ,
61 + 5 , 133 + 5 , 250 + 5 , 250 + 5 , 250 + 5 , 250 + 5
} ;
2018-10-02 23:08:38 +02:00
uint8_t LMICus915_maxFrameLen ( uint8_t dr ) {
if ( dr < LENOF_TABLE ( maxFrameLens ) )
return TABLE_GET_U1 ( maxFrameLens , dr ) ;
else
2019-10-02 21:37:48 +02:00
return 0 ;
}
int8_t LMICus915_pow2dbm ( uint8_t mcmd_ladr_p1 ) {
if ( ( mcmd_ladr_p1 & MCMD_LinkADRReq_POW_MASK ) >
( ( LMIC_LORAWAN_SPEC_VERSION < LMIC_LORAWAN_SPEC_VERSION_1_0_3 )
? US915_LinkAdrReq_POW_MAX_1_0_2
: US915_LinkAdrReq_POW_MAX_1_0_3 ) )
return - 128 ;
else
return ( ( s1_t ) ( US915_TX_MAX_DBM - ( ( ( mcmd_ladr_p1 ) & MCMD_LinkADRReq_POW_MASK ) < < 1 ) ) ) ;
2018-10-02 23:08:38 +02:00
}
static CONST_TABLE ( ostime_t , DR2HSYM_osticks ) [ ] = {
us2osticksRound ( 128 < < 5 ) , // DR_SF10 DR_SF12CR
us2osticksRound ( 128 < < 4 ) , // DR_SF9 DR_SF11CR
us2osticksRound ( 128 < < 3 ) , // DR_SF8 DR_SF10CR
us2osticksRound ( 128 < < 2 ) , // DR_SF7 DR_SF9CR
us2osticksRound ( 128 < < 1 ) , // DR_SF8C DR_SF8CR
us2osticksRound ( 128 < < 0 ) // ------ DR_SF7CR
} ;
ostime_t LMICus915_dr2hsym ( uint8_t dr ) {
return TABLE_GET_OSTIME ( DR2HSYM_osticks , ( dr ) & 7 ) ; // map DR_SFnCR -> 0-6
}
u4_t LMICus915_convFreq ( xref2cu1_t ptr ) {
u4_t freq = ( os_rlsbf4 ( ptr - 1 ) > > 8 ) * 100 ;
if ( freq < US915_FREQ_MIN | | freq > US915_FREQ_MAX )
freq = 0 ;
return freq ;
}
2021-07-25 14:39:11 +02:00
///
/// \brief query number of default channels.
///
/// For US, we have no programmable channels; all channels
/// are fixed. Return the total channel count.
///
u1_t LMIC_queryNumDefaultChannels ( ) {
return 64 + 8 ;
}
///
/// \brief LMIC_setupChannel for US915
///
/// \note there are no progammable channels for US915, so this API
/// always returns FALSE.
///
2018-10-02 23:08:38 +02:00
bit_t LMIC_setupChannel ( u1_t chidx , u4_t freq , u2_t drmap , s1_t band ) {
2021-07-25 14:39:11 +02:00
LMIC_API_PARAMETER ( chidx ) ;
LMIC_API_PARAMETER ( freq ) ;
LMIC_API_PARAMETER ( drmap ) ;
2018-10-21 23:28:25 +02:00
LMIC_API_PARAMETER ( band ) ;
2021-07-25 14:39:11 +02:00
return 0 ; // channels 0..71 are hardwired
2018-10-02 23:08:38 +02:00
}
2019-10-02 21:37:48 +02:00
bit_t LMIC_disableChannel ( u1_t channel ) {
bit_t result = 0 ;
2021-07-25 14:39:11 +02:00
if ( channel < 72 ) {
2018-10-02 23:08:38 +02:00
if ( ENABLED_CHANNEL ( channel ) ) {
2019-10-02 21:37:48 +02:00
result = 1 ;
2018-10-02 23:08:38 +02:00
if ( IS_CHANNEL_125khz ( channel ) )
LMIC . activeChannels125khz - - ;
else if ( IS_CHANNEL_500khz ( channel ) )
LMIC . activeChannels500khz - - ;
}
LMIC . channelMap [ channel > > 4 ] & = ~ ( 1 < < ( channel & 0xF ) ) ;
}
2019-10-02 21:37:48 +02:00
return result ;
2018-10-02 23:08:38 +02:00
}
2019-10-02 21:37:48 +02:00
bit_t LMIC_enableChannel ( u1_t channel ) {
bit_t result = 0 ;
2021-07-25 14:39:11 +02:00
if ( channel < 72 ) {
2018-10-02 23:08:38 +02:00
if ( ! ENABLED_CHANNEL ( channel ) ) {
2019-10-02 21:37:48 +02:00
result = 1 ;
2018-10-02 23:08:38 +02:00
if ( IS_CHANNEL_125khz ( channel ) )
LMIC . activeChannels125khz + + ;
else if ( IS_CHANNEL_500khz ( channel ) )
LMIC . activeChannels500khz + + ;
}
LMIC . channelMap [ channel > > 4 ] | = ( 1 < < ( channel & 0xF ) ) ;
}
2019-10-02 21:37:48 +02:00
return result ;
2018-10-02 23:08:38 +02:00
}
2019-10-02 21:37:48 +02:00
bit_t LMIC_enableSubBand ( u1_t band ) {
2018-10-02 23:08:38 +02:00
ASSERT ( band < 8 ) ;
u1_t start = band * 8 ;
u1_t end = start + 8 ;
2019-10-02 21:37:48 +02:00
bit_t result = 0 ;
2018-10-02 23:08:38 +02:00
// enable all eight 125 kHz channels in this subband
for ( int channel = start ; channel < end ; + + channel )
2019-10-02 21:37:48 +02:00
result | = LMIC_enableChannel ( channel ) ;
2018-10-02 23:08:38 +02:00
// there's a single 500 kHz channel associated with
// each group of 8 125 kHz channels. Enable it, too.
2019-10-02 21:37:48 +02:00
result | = LMIC_enableChannel ( 64 + band ) ;
return result ;
2018-10-02 23:08:38 +02:00
}
2019-10-02 21:37:48 +02:00
bit_t LMIC_disableSubBand ( u1_t band ) {
2018-10-02 23:08:38 +02:00
ASSERT ( band < 8 ) ;
u1_t start = band * 8 ;
u1_t end = start + 8 ;
2019-10-02 21:37:48 +02:00
bit_t result = 0 ;
2018-10-02 23:08:38 +02:00
// disable all eight 125 kHz channels in this subband
for ( int channel = start ; channel < end ; + + channel )
2019-10-02 21:37:48 +02:00
result | = LMIC_disableChannel ( channel ) ;
2018-10-02 23:08:38 +02:00
// there's a single 500 kHz channel associated with
// each group of 8 125 kHz channels. Disable it, too.
2019-10-02 21:37:48 +02:00
result | = LMIC_disableChannel ( 64 + band ) ;
return result ;
2018-10-02 23:08:38 +02:00
}
2019-10-02 21:37:48 +02:00
bit_t LMIC_selectSubBand ( u1_t band ) {
bit_t result = 0 ;
2018-10-02 23:08:38 +02:00
ASSERT ( band < 8 ) ;
for ( int b = 0 ; b < 8 ; + + b ) {
if ( band = = b )
2019-10-02 21:37:48 +02:00
result | = LMIC_enableSubBand ( b ) ;
2018-10-02 23:08:38 +02:00
else
2019-10-02 21:37:48 +02:00
result | = LMIC_disableSubBand ( b ) ;
2018-10-02 23:08:38 +02:00
}
2019-10-02 21:37:48 +02:00
return result ;
2018-10-02 23:08:38 +02:00
}
void LMICus915_updateTx ( ostime_t txbeg ) {
u1_t chnl = LMIC . txChnl ;
if ( chnl < 64 ) {
LMIC . freq = US915_125kHz_UPFBASE + chnl * US915_125kHz_UPFSTEP ;
if ( LMIC . activeChannels125khz > = 50 )
LMIC . txpow = 30 ;
else
LMIC . txpow = 21 ;
} else {
// at 500kHz bandwidth, we're allowed more power.
LMIC . txpow = 26 ;
2021-07-25 14:39:11 +02:00
LMIC . freq = US915_500kHz_UPFBASE + ( chnl - 64 ) * US915_500kHz_UPFSTEP ;
2018-10-02 23:08:38 +02:00
}
// Update global duty cycle stats
if ( LMIC . globalDutyRate ! = 0 ) {
ostime_t airtime = calcAirTime ( LMIC . rps , LMIC . dataLen ) ;
LMIC . globalDutyAvail = txbeg + ( airtime < < LMIC . globalDutyRate ) ;
}
}
# if !defined(DISABLE_BEACONS)
void LMICus915_setBcnRxParams ( void ) {
LMIC . dataLen = 0 ;
LMIC . freq = US915_500kHz_DNFBASE + LMIC . bcnChnl * US915_500kHz_DNFSTEP ;
LMIC . rps = setIh ( setNocrc ( dndr2rps ( ( dr_t ) DR_BCN ) , 1 ) , LEN_BCN ) ;
}
# endif // !DISABLE_BEACONS
2019-10-02 21:37:48 +02:00
// set the Rx1 dndr, rps.
2018-10-02 23:08:38 +02:00
void LMICus915_setRx1Params ( void ) {
2019-10-02 21:37:48 +02:00
u1_t const txdr = LMIC . dndr ;
u1_t candidateDr ;
2018-10-02 23:08:38 +02:00
LMIC . freq = US915_500kHz_DNFBASE + ( LMIC . txChnl & 0x7 ) * US915_500kHz_DNFSTEP ;
2019-10-02 21:37:48 +02:00
if ( /* TX datarate */ txdr < LORAWAN_DR4 )
candidateDr = txdr + 10 - LMIC . rx1DrOffset ;
else
candidateDr = LORAWAN_DR13 - LMIC . rx1DrOffset ;
if ( candidateDr < LORAWAN_DR8 )
candidateDr = LORAWAN_DR8 ;
else if ( candidateDr > LORAWAN_DR13 )
candidateDr = LORAWAN_DR13 ;
LMIC . dndr = candidateDr ;
2018-10-02 23:08:38 +02:00
LMIC . rps = dndr2rps ( LMIC . dndr ) ;
}
2019-10-02 21:37:48 +02:00
void LMICus915_initJoinLoop ( void ) {
LMICuslike_initJoinLoop ( ) ;
// initialize the adrTxPower.
LMIC . adrTxPow = 20 ; // dBm
}
2018-10-02 23:08:38 +02:00
//
// END: US915 related stuff
//
// ================================================================================
# endif