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

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

View File

@@ -23,7 +23,7 @@ cmake_minimum_required(VERSION 3.6)
#---------------------------------------------------------------------------------------
# Allow switching of radios
set(RADIO_LIST sx1272 sx1276 sx126x)
set(RADIO_LIST sx1272 sx1276 sx126x lr1110)
set(RADIO sx1272 CACHE STRING "Default radio is sx1272")
set_property(CACHE RADIO PROPERTY STRINGS ${RADIO_LIST})
set_property(CACHE RADIO PROPERTY ADVANCED)
@@ -32,17 +32,47 @@ set_property(CACHE RADIO PROPERTY ADVANCED)
# Target
#---------------------------------------------------------------------------------------
file(GLOB ${PROJECT_NAME}_SOURCES "${RADIO}/*.c")
foreach( R ${RADIO_LIST} )
if(${R} MATCHES ${RADIO} )
list(APPEND ${PROJECT_NAME}_SOURCES
${CMAKE_CURRENT_SOURCE_DIR}/${RADIO}/radio.c
)
list(APPEND ${PROJECT_NAME}_SOURCES
${CMAKE_CURRENT_SOURCE_DIR}/${RADIO}/${RADIO}_driver/src/lr1110_bootloader.c
${CMAKE_CURRENT_SOURCE_DIR}/${RADIO}/${RADIO}_driver/src/lr1110_crypto_engine.c
${CMAKE_CURRENT_SOURCE_DIR}/${RADIO}/${RADIO}_driver/src/lr1110_gnss.c
${CMAKE_CURRENT_SOURCE_DIR}/${RADIO}/${RADIO}_driver/src/lr1110_radio.c
${CMAKE_CURRENT_SOURCE_DIR}/${RADIO}/${RADIO}_driver/src/lr1110_regmem.c
${CMAKE_CURRENT_SOURCE_DIR}/${RADIO}/${RADIO}_driver/src/lr1110_system.c
${CMAKE_CURRENT_SOURCE_DIR}/${RADIO}/${RADIO}_driver/src/lr1110_wifi.c
)
else()
file(GLOB ${PROJECT_NAME}_SOURCES
${CMAKE_CURRENT_SOURCE_DIR}/${RADIO}/*.c
)
endif()
endforeach()
add_library(${PROJECT_NAME} OBJECT EXCLUDE_FROM_ALL ${${PROJECT_NAME}_SOURCES})
add_dependencies(${PROJECT_NAME} board)
foreach( R ${RADIO_LIST} )
if(${R} MATCHES lr1110 )
list(APPEND ${PROJECT_NAME}_INCLUDES
${CMAKE_CURRENT_SOURCE_DIR}/${RADIO})
list(APPEND ${PROJECT_NAME}_INCLUDES
${CMAKE_CURRENT_SOURCE_DIR}/${RADIO}/${RADIO}_driver/src)
else()
list(APPEND ${PROJECT_NAME}_INCLUDES
${CMAKE_CURRENT_SOURCE_DIR}/${RADIO}
)
endif()
endforeach()
target_include_directories(${PROJECT_NAME} PUBLIC
${CMAKE_CURRENT_SOURCE_DIR}
${CMAKE_CURRENT_SOURCE_DIR}/sx126x
${CMAKE_CURRENT_SOURCE_DIR}/sx1272
${CMAKE_CURRENT_SOURCE_DIR}/sx1276
${${PROJECT_NAME}_INCLUDES}
$<TARGET_PROPERTY:board,INTERFACE_INCLUDE_DIRECTORIES>
$<TARGET_PROPERTY:system,INTERFACE_INCLUDE_DIRECTORIES>
)

View File

@@ -0,0 +1,117 @@
/*!
* \file lr1110.h
*
* \brief LR1110 driver implementation
*
* \copyright Revised BSD License, see file LICENSE.txt
*
* \code
* ______ _
* / _____) _ | |
* ( (____ _____ ____ _| |_ _____ ____| |__
* \____ \| ___ | (_ _) ___ |/ ___) _ \
* _____) ) ____| | | || |_| ____( (___| | | |
* (______/|_____)_|_|_| \__)_____)\____)_| |_|
* (C)2019-2019 Semtech
*
* \endcode
*/
#ifndef __LR1110_H__
#define __LR1110_H__
#ifdef __cplusplus
extern "C" {
#endif
#include <stdint.h>
#include <stdbool.h>
#include <math.h>
#include "gpio.h"
#include "spi.h"
#include "radio.h"
#include "lr1110_hal.h"
#include "lr1110_radio_types.h"
/*!
* \brief The type describing the modulation parameters for every packet types
*/
typedef struct
{
lr1110_radio_packet_types_t packet_type; //!< Packet to which the modulation parameters are referring to.
struct
{
lr1110_radio_modulation_param_gfsk_t gfsk;
lr1110_radio_modulation_param_lora_t lora;
}modulation; //!< Holds the modulation parameters structure
} lr1110_modulation_params_t;
/*!
* \brief The type describing the packet parameters for every packet types
*/
typedef struct
{
lr1110_radio_packet_types_t packet_type; //!< Packet to which the packet parameters are referring to.
struct
{
lr1110_radio_packet_param_gfsk_t gfsk;
lr1110_radio_packet_param_lora_t lora;
}packet; //!< Holds the packet parameters structure
} lr1110_packet_params_t;
/*!
* \brief Radio operating modes
*/
typedef enum lr1110_hal_operating_mode_e
{
LR1110_HAL_OP_MODE_SLEEP = 0x00, //! The radio is in sleep mode
LR1110_HAL_OP_MODE_STDBY_RC, //! The radio is in standby mode with RC oscillator
LR1110_HAL_OP_MODE_STDBY_XOSC, //! The radio is in standby mode with XOSC oscillator
LR1110_HAL_OP_MODE_FS, //! The radio is in frequency synthesis mode
LR1110_HAL_OP_MODE_TX, //! The radio is in transmit mode
LR1110_HAL_OP_MODE_RX, //! The radio is in receive single mode
LR1110_HAL_OP_MODE_RX_C, //! The radio is in receive continuous mode
LR1110_HAL_OP_MODE_RX_DC, //! The radio is in receive duty cycle mode
LR1110_HAL_OP_MODE_CAD //! The radio is in channel activity detection mode
} lr1110_hal_operating_mode_t;
/*!
* Radio hardware and global parameters
*/
typedef struct lr1110_s
{
Gpio_t reset;
Gpio_t busy;
Gpio_t dio_1;
Spi_t spi;
lr1110_hal_operating_mode_t op_mode;
lr1110_modulation_params_t modulation_params;
lr1110_packet_params_t packet_params;
} lr1110_t;
/*!
* Hardware IO IRQ callback function definition
*/
typedef void ( *lr1110_dio_irq_handler )( void* context );
/*!
* Get radio operating mode
*
* \remark Must be implemented by the upper layer
*
* \param [in] context Radio implementation parameters
* \retval op_mode Radio current operating mode
*/
lr1110_hal_operating_mode_t lr1110_hal_get_operating_mode( const void* context );
/*!
* Set radio operating mode
*
* \remark Must be implemented by the upper layer
*
* \param [in] context Radio implementation parameters
* \param [in] op_mode Radio operating mode
*/
void lr1110_hal_set_operating_mode( const void* context, const lr1110_hal_operating_mode_t op_mode );
#endif // __LR1110_H__

File diff suppressed because it is too large Load Diff

View File

@@ -23,6 +23,11 @@
#ifndef __RADIO_H__
#define __RADIO_H__
#ifdef __cplusplus
extern "C"
{
#endif
#include <stdint.h>
#include <stdbool.h>
@@ -91,6 +96,16 @@ typedef struct
* \param [IN] channelDetected Channel Activity detected during the CAD
*/
void ( *CadDone ) ( bool channelActivityDetected );
/*!
* \brief Gnss Done Done callback prototype.
*/
void ( *GnssDone )( void );
/*!
* \brief Gnss Done Done callback prototype.
*/
void ( *WifiDone )( void );
}RadioEvents_t;
/*!
@@ -243,11 +258,30 @@ struct Radio_s
* \Remark Can only be called once SetRxConfig or SetTxConfig have been called
*
* \param [IN] modem Radio modem to be used [0: FSK, 1: LoRa]
* \param [IN] pktLen Packet payload length
* \param [IN] bandwidth Sets the bandwidth
* FSK : >= 2600 and <= 250000 Hz
* LoRa: [0: 125 kHz, 1: 250 kHz,
* 2: 500 kHz, 3: Reserved]
* \param [IN] datarate Sets the Datarate
* FSK : 600..300000 bits/s
* LoRa: [6: 64, 7: 128, 8: 256, 9: 512,
* 10: 1024, 11: 2048, 12: 4096 chips]
* \param [IN] coderate Sets the coding rate (LoRa only)
* FSK : N/A ( set to 0 )
* LoRa: [1: 4/5, 2: 4/6, 3: 4/7, 4: 4/8]
* \param [IN] preambleLen Sets the Preamble length
* FSK : Number of bytes
* LoRa: Length in symbols (the hardware adds 4 more symbols)
* \param [IN] fixLen Fixed length packets [0: variable, 1: fixed]
* \param [IN] payloadLen Sets payload length when fixed length is used
* \param [IN] crcOn Enables/Disables the CRC [0: OFF, 1: ON]
*
* \retval airTime Computed airTime (ms) for the given packet payload length
*/
uint32_t ( *TimeOnAir )( RadioModems_t modem, uint8_t pktLen );
uint32_t ( *TimeOnAir )( RadioModems_t modem, uint32_t bandwidth,
uint32_t datarate, uint8_t coderate,
uint16_t preambleLen, bool fixLen, uint8_t payloadLen,
bool crcOn );
/*!
* \brief Sends the buffer of size. Prepares the packet to be sent and sets
* the radio in transmission
@@ -294,14 +328,14 @@ struct Radio_s
* \param [IN]: addr Register address
* \param [IN]: data New register value
*/
void ( *Write )( uint16_t addr, uint8_t data );
void ( *Write )( uint32_t addr, uint8_t data );
/*!
* \brief Reads the radio register at the specified address
*
* \param [IN]: addr Register address
* \retval data Register value
*/
uint8_t ( *Read )( uint16_t addr );
uint8_t ( *Read )( uint32_t addr );
/*!
* \brief Writes multiple radio registers starting at address
*
@@ -309,7 +343,7 @@ struct Radio_s
* \param [IN] buffer Buffer containing the new register's values
* \param [IN] size Number of registers to be written
*/
void ( *WriteBuffer )( uint16_t addr, uint8_t *buffer, uint8_t size );
void ( *WriteBuffer )( uint32_t addr, uint8_t *buffer, uint8_t size );
/*!
* \brief Reads multiple radio registers starting at address
*
@@ -317,7 +351,7 @@ struct Radio_s
* \param [OUT] buffer Buffer where to copy the registers data
* \param [IN] size Number of registers to be read
*/
void ( *ReadBuffer )( uint16_t addr, uint8_t *buffer, uint8_t size );
void ( *ReadBuffer )( uint32_t addr, uint8_t *buffer, uint8_t size );
/*!
* \brief Sets the maximum payload length.
*
@@ -374,4 +408,8 @@ struct Radio_s
*/
extern const struct Radio_s Radio;
#ifdef __cplusplus
}
#endif
#endif // __RADIO_H__

View File

@@ -184,11 +184,30 @@ bool RadioCheckRfFrequency( uint32_t frequency );
* \Remark Can only be called once SetRxConfig or SetTxConfig have been called
*
* \param [IN] modem Radio modem to be used [0: FSK, 1: LoRa]
* \param [IN] pktLen Packet payload length
* \param [IN] bandwidth Sets the bandwidth
* FSK : >= 2600 and <= 250000 Hz
* LoRa: [0: 125 kHz, 1: 250 kHz,
* 2: 500 kHz, 3: Reserved]
* \param [IN] datarate Sets the Datarate
* FSK : 600..300000 bits/s
* LoRa: [6: 64, 7: 128, 8: 256, 9: 512,
* 10: 1024, 11: 2048, 12: 4096 chips]
* \param [IN] coderate Sets the coding rate (LoRa only)
* FSK : N/A ( set to 0 )
* LoRa: [1: 4/5, 2: 4/6, 3: 4/7, 4: 4/8]
* \param [IN] preambleLen Sets the Preamble length
* FSK : Number of bytes
* LoRa: Length in symbols (the hardware adds 4 more symbols)
* \param [IN] fixLen Fixed length packets [0: variable, 1: fixed]
* \param [IN] payloadLen Sets payload length when fixed length is used
* \param [IN] crcOn Enables/Disables the CRC [0: OFF, 1: ON]
*
* \retval airTime Computed airTime (ms) for the given packet payload length
*/
uint32_t RadioTimeOnAir( RadioModems_t modem, uint8_t pktLen );
uint32_t RadioTimeOnAir( RadioModems_t modem, uint32_t bandwidth,
uint32_t datarate, uint8_t coderate,
uint16_t preambleLen, bool fixLen, uint8_t payloadLen,
bool crcOn );
/*!
* \brief Sends the buffer of size. Prepares the packet to be sent and sets
@@ -243,7 +262,7 @@ int16_t RadioRssi( RadioModems_t modem );
* \param [IN]: addr Register address
* \param [IN]: data New register value
*/
void RadioWrite( uint16_t addr, uint8_t data );
void RadioWrite( uint32_t addr, uint8_t data );
/*!
* \brief Reads the radio register at the specified address
@@ -251,7 +270,7 @@ void RadioWrite( uint16_t addr, uint8_t data );
* \param [IN]: addr Register address
* \retval data Register value
*/
uint8_t RadioRead( uint16_t addr );
uint8_t RadioRead( uint32_t addr );
/*!
* \brief Writes multiple radio registers starting at address
@@ -260,7 +279,7 @@ uint8_t RadioRead( uint16_t addr );
* \param [IN] buffer Buffer containing the new register's values
* \param [IN] size Number of registers to be written
*/
void RadioWriteBuffer( uint16_t addr, uint8_t *buffer, uint8_t size );
void RadioWriteBuffer( uint32_t addr, uint8_t *buffer, uint8_t size );
/*!
* \brief Reads multiple radio registers starting at address
@@ -269,7 +288,7 @@ void RadioWriteBuffer( uint16_t addr, uint8_t *buffer, uint8_t size );
* \param [OUT] buffer Buffer where to copy the registers data
* \param [IN] size Number of registers to be read
*/
void RadioReadBuffer( uint16_t addr, uint8_t *buffer, uint8_t size );
void RadioReadBuffer( uint32_t addr, uint8_t *buffer, uint8_t size );
/*!
* \brief Sets the maximum payload length.
@@ -395,11 +414,6 @@ const FskBandwidth_t FskBandwidths[] =
const RadioLoRaBandwidths_t Bandwidths[] = { LORA_BW_125, LORA_BW_250, LORA_BW_500 };
// SF12 SF11 SF10 SF9 SF8 SF7
static double RadioLoRaSymbTime[3][6] = {{ 32.768, 16.384, 8.192, 4.096, 2.048, 1.024 }, // 125 KHz
{ 16.384, 8.192, 4.096, 2.048, 1.024, 0.512 }, // 250 KHz
{ 8.192, 4.096, 2.048, 1.024, 0.512, 0.256 }}; // 500 KHz
uint8_t MaxPayloadLength = 0xFF;
uint32_t TxTimeout = 0;
@@ -562,6 +576,8 @@ bool RadioIsChannelFree( RadioModems_t modem, uint32_t freq, int16_t rssiThresh,
int16_t rssi = 0;
uint32_t carrierSenseTime = 0;
RadioSleep( );
RadioSetModem( modem );
RadioSetChannel( freq );
@@ -589,7 +605,6 @@ bool RadioIsChannelFree( RadioModems_t modem, uint32_t freq, int16_t rssiThresh,
uint32_t RadioRandom( void )
{
uint8_t i;
uint32_t rnd = 0;
/*
@@ -598,17 +613,10 @@ uint32_t RadioRandom( void )
// Set LoRa modem ON
RadioSetModem( MODEM_LORA );
// Set radio in continuous reception
SX126xSetRx( 0 );
// Disable LoRa modem interrupts
SX126xSetDioIrqParams( IRQ_RADIO_NONE, IRQ_RADIO_NONE, IRQ_RADIO_NONE, IRQ_RADIO_NONE );
for( i = 0; i < 32; i++ )
{
DelayMs( 1 );
// Unfiltered RSSI value reading. Only takes the LSB value
rnd |= ( ( uint32_t )SX126xGetRssiInst( ) & 0x01 ) << i;
}
RadioSleep( );
rnd = SX126xGetRandom( );
return rnd;
}
@@ -675,7 +683,6 @@ void RadioSetRxConfig( RadioModems_t modem, uint32_t bandwidth,
case MODEM_LORA:
SX126xSetStopRxTimerOnPreambleDetect( false );
SX126xSetLoRaSymbNumTimeout( symbTimeout );
SX126x.ModulationParams.PacketType = PACKET_TYPE_LORA;
SX126x.ModulationParams.Params.LoRa.SpreadingFactor = ( RadioLoRaSpreadingFactors_t )datarate;
SX126x.ModulationParams.Params.LoRa.Bandwidth = Bandwidths[bandwidth];
@@ -716,9 +723,24 @@ void RadioSetRxConfig( RadioModems_t modem, uint32_t bandwidth,
SX126x.PacketParams.Params.LoRa.CrcMode = ( RadioLoRaCrcModes_t )crcOn;
SX126x.PacketParams.Params.LoRa.InvertIQ = ( RadioLoRaIQModes_t )iqInverted;
RadioStandby( );
RadioSetModem( ( SX126x.ModulationParams.PacketType == PACKET_TYPE_GFSK ) ? MODEM_FSK : MODEM_LORA );
SX126xSetModulationParams( &SX126x.ModulationParams );
SX126xSetPacketParams( &SX126x.PacketParams );
SX126xSetLoRaSymbNumTimeout( symbTimeout );
// WORKAROUND - Optimizing the Inverted IQ Operation, see DS_SX1261-2_V1.2 datasheet chapter 15.4
if( SX126x.PacketParams.Params.LoRa.InvertIQ == LORA_IQ_INVERTED )
{
// RegIqPolaritySetup = @address 0x0736
SX126xWriteRegister( 0x0736, SX126xReadRegister( 0x0736 ) & ~( 1 << 2 ) );
}
else
{
// RegIqPolaritySetup @address 0x0736
SX126xWriteRegister( 0x0736, SX126xReadRegister( 0x0736 ) | ( 1 << 2 ) );
}
// WORKAROUND END
// Timeout Max, Timeout handled directly in SetRx function
RxTimeout = 0xFFFF;
@@ -815,6 +837,20 @@ void RadioSetTxConfig( RadioModems_t modem, int8_t power, uint32_t fdev,
SX126xSetPacketParams( &SX126x.PacketParams );
break;
}
// WORKAROUND - Modulation Quality with 500 kHz LoRa Bandwidth, see DS_SX1261-2_V1.2 datasheet chapter 15.1
if( ( modem == MODEM_LORA ) && ( SX126x.ModulationParams.Params.LoRa.Bandwidth == LORA_BW_500 ) )
{
// RegTxModulation = @address 0x0889
SX126xWriteRegister( 0x0889, SX126xReadRegister( 0x0889 ) & ~( 1 << 2 ) );
}
else
{
// RegTxModulation = @address 0x0889
SX126xWriteRegister( 0x0889, SX126xReadRegister( 0x0889 ) | ( 1 << 2 ) );
}
// WORKAROUND END
SX126xSetRfTxPower( power );
TxTimeout = timeout;
}
@@ -824,44 +860,158 @@ bool RadioCheckRfFrequency( uint32_t frequency )
return true;
}
uint32_t RadioTimeOnAir( RadioModems_t modem, uint8_t pktLen )
static uint32_t RadioGetLoRaBandwidthInHz( RadioLoRaBandwidths_t bw )
{
uint32_t airTime = 0;
uint32_t bandwidthInHz = 0;
switch( bw )
{
case LORA_BW_007:
bandwidthInHz = 7812UL;
break;
case LORA_BW_010:
bandwidthInHz = 10417UL;
break;
case LORA_BW_015:
bandwidthInHz = 15625UL;
break;
case LORA_BW_020:
bandwidthInHz = 20833UL;
break;
case LORA_BW_031:
bandwidthInHz = 31250UL;
break;
case LORA_BW_041:
bandwidthInHz = 41667UL;
break;
case LORA_BW_062:
bandwidthInHz = 62500UL;
break;
case LORA_BW_125:
bandwidthInHz = 125000UL;
break;
case LORA_BW_250:
bandwidthInHz = 250000UL;
break;
case LORA_BW_500:
bandwidthInHz = 500000UL;
break;
}
return bandwidthInHz;
}
static uint32_t RadioGetGfskTimeOnAirNumerator( uint32_t datarate, uint8_t coderate,
uint16_t preambleLen, bool fixLen, uint8_t payloadLen,
bool crcOn )
{
const RadioAddressComp_t addrComp = RADIO_ADDRESSCOMP_FILT_OFF;
const uint8_t syncWordLength = 3;
return ( preambleLen << 3 ) +
( ( fixLen == false ) ? 8 : 0 ) +
( syncWordLength << 3 ) +
( ( payloadLen +
( addrComp == RADIO_ADDRESSCOMP_FILT_OFF ? 0 : 1 ) +
( ( crcOn == true ) ? 2 : 0 )
) << 3
);
}
static uint32_t RadioGetLoRaTimeOnAirNumerator( uint32_t bandwidth,
uint32_t datarate, uint8_t coderate,
uint16_t preambleLen, bool fixLen, uint8_t payloadLen,
bool crcOn )
{
int32_t crDenom = coderate + 4;
bool lowDatareOptimize = false;
// Ensure that the preamble length is at least 12 symbols when using SF5 or
// SF6
if( ( datarate == 5 ) || ( datarate == 6 ) )
{
if( preambleLen < 12 )
{
preambleLen = 12;
}
}
if( ( ( bandwidth == 0 ) && ( ( datarate == 11 ) || ( datarate == 12 ) ) ) ||
( ( bandwidth == 1 ) && ( datarate == 12 ) ) )
{
lowDatareOptimize = true;
}
int32_t ceilDenominator;
int32_t ceilNumerator = ( payloadLen << 3 ) +
( crcOn ? 16 : 0 ) -
( 4 * datarate ) +
( fixLen ? 0 : 20 );
if( datarate <= 6 )
{
ceilDenominator = 4 * datarate;
}
else
{
ceilNumerator += 8;
if( lowDatareOptimize == true )
{
ceilDenominator = 4 * ( datarate - 2 );
}
else
{
ceilDenominator = 4 * datarate;
}
}
if( ceilNumerator < 0 )
{
ceilNumerator = 0;
}
// Perform integral ceil()
int32_t intermediate =
( ( ceilNumerator + ceilDenominator - 1 ) / ceilDenominator ) * crDenom + preambleLen + 12;
if( datarate <= 6 )
{
intermediate += 2;
}
return ( uint32_t )( ( 4 * intermediate + 1 ) * ( 1 << ( datarate - 2 ) ) );
}
uint32_t RadioTimeOnAir( RadioModems_t modem, uint32_t bandwidth,
uint32_t datarate, uint8_t coderate,
uint16_t preambleLen, bool fixLen, uint8_t payloadLen,
bool crcOn )
{
uint32_t numerator = 0;
uint32_t denominator = 1;
switch( modem )
{
case MODEM_FSK:
{
airTime = rint( ( 8 * ( SX126x.PacketParams.Params.Gfsk.PreambleLength +
( SX126x.PacketParams.Params.Gfsk.SyncWordLength >> 3 ) +
( ( SX126x.PacketParams.Params.Gfsk.HeaderType == RADIO_PACKET_FIXED_LENGTH ) ? 0.0 : 1.0 ) +
pktLen +
( ( SX126x.PacketParams.Params.Gfsk.CrcLength == RADIO_CRC_2_BYTES ) ? 2.0 : 0 ) ) /
SX126x.ModulationParams.Params.Gfsk.BitRate ) * 1e3 );
numerator = 1000U * RadioGetGfskTimeOnAirNumerator( datarate, coderate,
preambleLen, fixLen,
payloadLen, crcOn );
denominator = datarate;
}
break;
case MODEM_LORA:
{
double ts = RadioLoRaSymbTime[SX126x.ModulationParams.Params.LoRa.Bandwidth - 4][12 - SX126x.ModulationParams.Params.LoRa.SpreadingFactor];
// time of preamble
double tPreamble = ( SX126x.PacketParams.Params.LoRa.PreambleLength + 4.25 ) * ts;
// Symbol length of payload and time
double tmp = ceil( ( 8 * pktLen - 4 * SX126x.ModulationParams.Params.LoRa.SpreadingFactor +
28 + 16 * SX126x.PacketParams.Params.LoRa.CrcMode -
( ( SX126x.PacketParams.Params.LoRa.HeaderType == LORA_PACKET_FIXED_LENGTH ) ? 20 : 0 ) ) /
( double )( 4 * ( SX126x.ModulationParams.Params.LoRa.SpreadingFactor -
( ( SX126x.ModulationParams.Params.LoRa.LowDatarateOptimize > 0 ) ? 2 : 0 ) ) ) ) *
( ( SX126x.ModulationParams.Params.LoRa.CodingRate % 4 ) + 4 );
double nPayload = 8 + ( ( tmp > 0 ) ? tmp : 0 );
double tPayload = nPayload * ts;
// Time on air
double tOnAir = tPreamble + tPayload;
// return milli seconds
airTime = floor( tOnAir + 0.999 );
numerator = 1000U * RadioGetLoRaTimeOnAirNumerator( bandwidth, datarate,
coderate, preambleLen,
fixLen, payloadLen, crcOn );
denominator = RadioGetLoRaBandwidthInHz( Bandwidths[bandwidth] );
}
break;
}
return airTime;
// Perform integral ceil()
return ( numerator + denominator - 1 ) / denominator;
}
void RadioSend( uint8_t *buffer, uint8_t size )
@@ -954,21 +1104,19 @@ void RadioSetRxDutyCycle( uint32_t rxTime, uint32_t sleepTime )
void RadioStartCad( void )
{
SX126xSetDioIrqParams( IRQ_CAD_DONE | IRQ_CAD_ACTIVITY_DETECTED, IRQ_CAD_DONE | IRQ_CAD_ACTIVITY_DETECTED, IRQ_RADIO_NONE, IRQ_RADIO_NONE );
SX126xSetCad( );
}
void RadioTx( uint32_t timeout )
{
SX126xSetTx( timeout << 6 );
}
void RadioSetTxContinuousWave( uint32_t freq, int8_t power, uint16_t time )
{
uint32_t timeout = ( uint32_t )time * 1000;
SX126xSetRfFrequency( freq );
SX126xSetRfTxPower( power );
SX126xSetTxContinuousWave( );
TimerSetValue( &TxTimeoutTimer, time * 1e3 );
TimerSetValue( &TxTimeoutTimer, timeout );
TimerStart( &TxTimeoutTimer );
}
@@ -977,36 +1125,26 @@ int16_t RadioRssi( RadioModems_t modem )
return SX126xGetRssiInst( );
}
void RadioWrite( uint16_t addr, uint8_t data )
void RadioWrite( uint32_t addr, uint8_t data )
{
SX126xWriteRegister( addr, data );
}
uint8_t RadioRead( uint16_t addr )
uint8_t RadioRead( uint32_t addr )
{
return SX126xReadRegister( addr );
}
void RadioWriteBuffer( uint16_t addr, uint8_t *buffer, uint8_t size )
void RadioWriteBuffer( uint32_t addr, uint8_t *buffer, uint8_t size )
{
SX126xWriteRegisters( addr, buffer, size );
}
void RadioReadBuffer( uint16_t addr, uint8_t *buffer, uint8_t size )
void RadioReadBuffer( uint32_t addr, uint8_t *buffer, uint8_t size )
{
SX126xReadRegisters( addr, buffer, size );
}
void RadioWriteFifo( uint8_t *buffer, uint8_t size )
{
SX126xWriteBuffer( 0, buffer, size );
}
void RadioReadFifo( uint8_t *buffer, uint8_t size )
{
SX126xReadBuffer( 0, buffer, size );
}
void RadioSetMaxPayloadLength( RadioModems_t modem, uint8_t max )
{
if( modem == MODEM_LORA )
@@ -1094,32 +1232,41 @@ void RadioIrqProcess( void )
if( ( irqRegs & IRQ_RX_DONE ) == IRQ_RX_DONE )
{
uint8_t size;
if( ( irqRegs & IRQ_CRC_ERROR ) == IRQ_CRC_ERROR )
{
if( RxContinuous == false )
{
//!< Update operating mode state to a value lower than \ref MODE_STDBY_XOSC
SX126xSetOperatingMode( MODE_STDBY_RC );
}
if( ( RadioEvents != NULL ) && ( RadioEvents->RxError ) )
{
RadioEvents->RxError( );
}
}
else
{
uint8_t size;
TimerStop( &RxTimeoutTimer );
if( RxContinuous == false )
{
//!< Update operating mode state to a value lower than \ref MODE_STDBY_XOSC
SX126xSetOperatingMode( MODE_STDBY_RC );
}
SX126xGetPayload( RadioRxPayload, &size , 255 );
SX126xGetPacketStatus( &RadioPktStatus );
if( ( RadioEvents != NULL ) && ( RadioEvents->RxDone != NULL ) )
{
RadioEvents->RxDone( RadioRxPayload, size, RadioPktStatus.Params.LoRa.RssiPkt, RadioPktStatus.Params.LoRa.SnrPkt );
}
}
TimerStop( &RxTimeoutTimer );
if( RxContinuous == false )
{
//!< Update operating mode state to a value lower than \ref MODE_STDBY_XOSC
SX126xSetOperatingMode( MODE_STDBY_RC );
if( ( irqRegs & IRQ_CRC_ERROR ) == IRQ_CRC_ERROR )
{
if( RxContinuous == false )
{
//!< Update operating mode state to a value lower than \ref MODE_STDBY_XOSC
SX126xSetOperatingMode( MODE_STDBY_RC );
}
if( ( RadioEvents != NULL ) && ( RadioEvents->RxError ) )
{
RadioEvents->RxError( );
// WORKAROUND - Implicit Header Mode Timeout Behavior, see DS_SX1261-2_V1.2 datasheet chapter 15.3
// RegRtcControl = @address 0x0902
SX126xWriteRegister( 0x0902, 0x00 );
// RegEventMask = @address 0x0944
SX126xWriteRegister( 0x0944, SX126xReadRegister( 0x0944 ) | ( 1 << 1 ) );
// WORKAROUND END
}
SX126xGetPayload( RadioRxPayload, &size , 255 );
SX126xGetPacketStatus( &RadioPktStatus );
if( ( RadioEvents != NULL ) && ( RadioEvents->RxDone != NULL ) )
{
RadioEvents->RxDone( RadioRxPayload, size, RadioPktStatus.Params.LoRa.RssiPkt, RadioPktStatus.Params.LoRa.SnrPkt );
}
}
}

View File

@@ -47,6 +47,11 @@ static RadioOperatingModes_t OperatingMode;
*/
static RadioPacketTypes_t PacketType;
/*!
* \brief Stores the current packet header type set in the radio
*/
static volatile RadioLoRaPacketLengthsMode_t LoRaHeaderType;
/*!
* \brief Stores the last frequency error measured on LoRa received packet
*/
@@ -90,13 +95,8 @@ void SX126xInit( DioIrqHandler dioIrq )
SX126xWakeup( );
SX126xSetStandby( STDBY_RC );
#ifdef USE_TCXO
CalibrationParams_t calibParam;
SX126xSetDio3AsTcxoCtrl( TCXO_CTRL_1_7V, SX126xGetBoardTcxoWakeupTime( ) << 6 ); // convert from ms to SX126x time base
calibParam.Value = 0x7F;
SX126xCalibrate( calibParam );
#endif
// Initialize TCXO control
SX126xIoTcxoInit( );
SX126xSetDio2AsRfSwitchCtrl( true );
SX126xSetOperatingMode( MODE_STDBY_RC );
@@ -227,25 +227,37 @@ void SX126xSetWhiteningSeed( uint16_t seed )
uint32_t SX126xGetRandom( void )
{
uint8_t buf[] = { 0, 0, 0, 0 };
uint32_t number = 0;
uint8_t regAnaLna = 0;
uint8_t regAnaMixer = 0;
regAnaLna = SX126xReadRegister( REG_ANA_LNA );
SX126xWriteRegister( REG_ANA_LNA, regAnaLna & ~( 1 << 0 ) );
regAnaMixer = SX126xReadRegister( REG_ANA_MIXER );
SX126xWriteRegister( REG_ANA_MIXER, regAnaMixer & ~( 1 << 7 ) );
// Set radio in continuous reception
SX126xSetRx( 0 );
SX126xSetRx( 0xFFFFFF ); // Rx Continuous
DelayMs( 1 );
SX126xReadRegisters( RANDOM_NUMBER_GENERATORBASEADDR, buf, 4 );
SX126xReadRegisters( RANDOM_NUMBER_GENERATORBASEADDR, ( uint8_t* )&number, 4 );
SX126xSetStandby( STDBY_RC );
return ( buf[0] << 24 ) | ( buf[1] << 16 ) | ( buf[2] << 8 ) | buf[3];
SX126xWriteRegister( REG_ANA_LNA, regAnaLna );
SX126xWriteRegister( REG_ANA_MIXER, regAnaMixer );
return number;
}
void SX126xSetSleep( SleepParams_t sleepConfig )
{
SX126xAntSwOff( );
SX126xWriteCommand( RADIO_SET_SLEEP, &sleepConfig.Value, 1 );
uint8_t value = ( ( ( uint8_t )sleepConfig.Fields.WarmStart << 2 ) |
( ( uint8_t )sleepConfig.Fields.Reset << 1 ) |
( ( uint8_t )sleepConfig.Fields.WakeUpRTC ) );
SX126xWriteCommand( RADIO_SET_SLEEP, &value, 1 );
SX126xSetOperatingMode( MODE_SLEEP );
}
@@ -344,6 +356,19 @@ void SX126xSetStopRxTimerOnPreambleDetect( bool enable )
void SX126xSetLoRaSymbNumTimeout( uint8_t SymbNum )
{
SX126xWriteCommand( RADIO_SET_LORASYMBTIMEOUT, &SymbNum, 1 );
uint8_t mant = SymbNum >> 1;
uint8_t exp = 0;
uint8_t reg = 0;
while( mant > 31 )
{
mant >>= 2;
exp++;
}
reg = exp + ( mant << 3 );
SX126xWriteRegister( REG_LR_SYNCH_TIMEOUT, reg );
}
void SX126xSetRegulatorMode( RadioRegulatorMode_t mode )
@@ -353,7 +378,15 @@ void SX126xSetRegulatorMode( RadioRegulatorMode_t mode )
void SX126xCalibrate( CalibrationParams_t calibParam )
{
SX126xWriteCommand( RADIO_CALIBRATE, ( uint8_t* )&calibParam, 1 );
uint8_t value = ( ( ( uint8_t )calibParam.Fields.ImgEnable << 6 ) |
( ( uint8_t )calibParam.Fields.ADCBulkPEnable << 5 ) |
( ( uint8_t )calibParam.Fields.ADCBulkNEnable << 4 ) |
( ( uint8_t )calibParam.Fields.ADCPulseEnable << 3 ) |
( ( uint8_t )calibParam.Fields.PLLEnable << 2 ) |
( ( uint8_t )calibParam.Fields.RC13MEnable << 1 ) |
( ( uint8_t )calibParam.Fields.RC64KEnable ) );
SX126xWriteCommand( RADIO_CALIBRATE, &value, 1 );
}
void SX126xCalibrateImage( uint32_t freq )
@@ -501,6 +534,11 @@ void SX126xSetTxParams( int8_t power, RadioRampTimes_t rampTime )
}
else // sx1262
{
// WORKAROUND - Better Resistance of the SX1262 Tx to Antenna Mismatch, see DS_SX1261-2_V1.2 datasheet chapter 15.2
// RegTxClampConfig = @address 0x08D8
SX126xWriteRegister( 0x08D8, SX126xReadRegister( 0x08D8 ) | ( 0x0F << 1 ) );
// WORKAROUND END
SX126xSetPaConfig( 0x04, 0x07, 0x00, 0x01 );
if( power > 22 )
{
@@ -609,7 +647,7 @@ void SX126xSetPacketParams( PacketParams_t *packetParams )
n = 6;
buf[0] = ( packetParams->Params.LoRa.PreambleLength >> 8 ) & 0xFF;
buf[1] = packetParams->Params.LoRa.PreambleLength;
buf[2] = packetParams->Params.LoRa.HeaderType;
buf[2] = LoRaHeaderType = packetParams->Params.LoRa.HeaderType;
buf[3] = packetParams->Params.LoRa.PayloadLength;
buf[4] = packetParams->Params.LoRa.CrcMode;
buf[5] = packetParams->Params.LoRa.InvertIQ;
@@ -632,7 +670,7 @@ void SX126xSetCadParams( RadioLoRaCadSymbols_t cadSymbolNum, uint8_t cadDetPeak,
buf[4] = ( uint8_t )( ( cadTimeout >> 16 ) & 0xFF );
buf[5] = ( uint8_t )( ( cadTimeout >> 8 ) & 0xFF );
buf[6] = ( uint8_t )( cadTimeout & 0xFF );
SX126xWriteCommand( RADIO_SET_CADPARAMS, buf, 5 );
SX126xWriteCommand( RADIO_SET_CADPARAMS, buf, 7 );
SX126xSetOperatingMode( MODE_CAD );
}
@@ -648,10 +686,11 @@ void SX126xSetBufferBaseAddress( uint8_t txBaseAddress, uint8_t rxBaseAddress )
RadioStatus_t SX126xGetStatus( void )
{
uint8_t stat = 0;
RadioStatus_t status;
RadioStatus_t status = { .Value = 0 };
SX126xReadCommand( RADIO_GET_STATUS, ( uint8_t * )&stat, 1 );
status.Value = stat;
stat = SX126xReadCommand( RADIO_GET_STATUS, NULL, 0 );
status.Fields.CmdStatus = ( stat & ( 0x07 << 1 ) ) >> 1;
status.Fields.ChipMode = ( stat & ( 0x07 << 4 ) ) >> 4;
return status;
}
@@ -673,7 +712,7 @@ void SX126xGetRxBufferStatus( uint8_t *payloadLength, uint8_t *rxStartBufferPoin
// In case of LORA fixed header, the payloadLength is obtained by reading
// the register REG_LR_PAYLOADLENGTH
if( ( SX126xGetPacketType( ) == PACKET_TYPE_LORA ) && ( SX126xReadRegister( REG_LR_PACKETPARAMS ) >> 7 == 1 ) )
if( ( SX126xGetPacketType( ) == PACKET_TYPE_LORA ) && ( LoRaHeaderType == LORA_PACKET_FIXED_LENGTH ) )
{
*payloadLength = SX126xReadRegister( REG_LR_PAYLOADLENGTH );
}
@@ -720,9 +759,18 @@ void SX126xGetPacketStatus( PacketStatus_t *pktStatus )
RadioError_t SX126xGetDeviceErrors( void )
{
RadioError_t error;
uint8_t err[] = { 0, 0 };
RadioError_t error = { .Value = 0 };
SX126xReadCommand( RADIO_GET_ERROR, ( uint8_t * )&error, 2 );
SX126xReadCommand( RADIO_GET_ERROR, ( uint8_t* )err, 2 );
error.Fields.PaRamp = ( err[0] & ( 1 << 0 ) ) >> 0;
error.Fields.PllLock = ( err[1] & ( 1 << 6 ) ) >> 6;
error.Fields.XoscStart = ( err[1] & ( 1 << 5 ) ) >> 5;
error.Fields.ImgCalib = ( err[1] & ( 1 << 4 ) ) >> 4;
error.Fields.AdcCalib = ( err[1] & ( 1 << 3 ) ) >> 3;
error.Fields.PllCalib = ( err[1] & ( 1 << 2 ) ) >> 2;
error.Fields.Rc13mCalib = ( err[1] & ( 1 << 1 ) ) >> 1;
error.Fields.Rc64kCalib = ( err[1] & ( 1 << 0 ) ) >> 0;
return error;
}

View File

@@ -23,6 +23,11 @@
#ifndef __SX126x_H__
#define __SX126x_H__
#ifdef __cplusplus
extern "C"
{
#endif
#include <stdint.h>
#include <stdbool.h>
#include <math.h>
@@ -90,6 +95,11 @@
*/
#define REG_LR_PAYLOADLENGTH 0x0702
/*!
* \brief The address of the register holding the re-calculated number of symbols
*/
#define REG_LR_SYNCH_TIMEOUT 0x0706
/*!
* \brief The addresses of the registers holding SyncWords values
*/
@@ -110,11 +120,22 @@
*/
#define LORA_MAC_PUBLIC_SYNCWORD 0x3444
/*!
* The address of the register giving a 4 bytes random number
* The address of the register giving a 32-bit random number
*/
#define RANDOM_NUMBER_GENERATORBASEADDR 0x0819
/*!
* The address of the register used to disable the LNA
*/
#define REG_ANA_LNA 0x08E2
/*!
* The address of the register used to disable the mixer
*/
#define REG_ANA_MIXER 0x08E5
/*!
* The address of the register holding RX Gain value (0x94: power saving, 0x96: rx boosted)
*/
@@ -138,10 +159,10 @@ typedef union RadioStatus_u
uint8_t Value;
struct
{ //bit order is lsb -> msb
uint8_t Reserved : 1; //!< Reserved
uint8_t : 1; //!< Reserved
uint8_t CmdStatus : 3; //!< Command status
uint8_t ChipMode : 3; //!< Chip mode
uint8_t CpuBusy : 1; //!< Flag for CPU radio busy
uint8_t : 1; //!< Reserved
}Fields;
}RadioStatus_t;
@@ -643,7 +664,7 @@ typedef union
uint8_t ImgCalib : 1; //!< Image calibration failed
uint8_t XoscStart : 1; //!< XOSC oscillator failed to start
uint8_t PllLock : 1; //!< PLL lock failed
uint8_t BuckStart : 1; //!< Buck converter failed to start
uint8_t : 1; //!< Buck converter failed to start
uint8_t PaRamp : 1; //!< PA ramp failed
uint8_t : 7; //!< Reserved
}Fields;
@@ -796,9 +817,19 @@ void SX126xSetCrcPolynomial( uint16_t polynomial );
void SX126xSetWhiteningSeed( uint16_t seed );
/*!
* \brief Gets a 32 bits random value generated by the radio
* \brief Gets a 32-bit random value generated by the radio
*
* \remark A valid packet type must have been configured with \ref SX126xSetPacketType
* before using this command.
*
* \remark The radio must be in reception mode before executing this function
* This code can potentially result in interrupt generation. It is the responsibility of
* the calling code to disable radio interrupts before calling this function,
* and re-enable them afterwards if necessary, or be certain that any interrupts
* generated during this process will not cause undesired side-effects in the software.
*
* Please note that the random numbers produced by the generator do not have a uniform or Gaussian distribution. If
* uniformity is needed, perform appropriate software post-processing.
*
* \retval randomValue 32 bits random value
*/
@@ -1113,4 +1144,8 @@ void SX126xClearDeviceErrors( void );
*/
void SX126xClearIrqStatus( uint16_t irq );
#ifdef __cplusplus
}
#endif
#endif // __SX126x_H__

View File

@@ -260,6 +260,8 @@ bool SX1272IsChannelFree( RadioModems_t modem, uint32_t freq, int16_t rssiThresh
int16_t rssi = 0;
uint32_t carrierSenseTime = 0;
SX1272SetSleep( );
SX1272SetModem( modem );
SX1272SetChannel( freq );
@@ -610,61 +612,136 @@ void SX1272SetTxConfig( RadioModems_t modem, int8_t power, uint32_t fdev,
}
}
uint32_t SX1272GetTimeOnAir( RadioModems_t modem, uint8_t pktLen )
static uint32_t SX1272GetLoRaBandwidthInHz( uint32_t bw )
{
uint32_t airTime = 0;
uint32_t bandwidthInHz = 0;
switch( bw )
{
case 0: // 125 kHz
bandwidthInHz = 125000UL;
break;
case 1: // 250 kHz
bandwidthInHz = 250000UL;
break;
case 2: // 500 kHz
bandwidthInHz = 500000UL;
break;
}
return bandwidthInHz;
}
static uint32_t SX1272GetGfskTimeOnAirNumerator( uint32_t datarate, uint8_t coderate,
uint16_t preambleLen, bool fixLen, uint8_t payloadLen,
bool crcOn )
{
const uint8_t syncWordLength = 3;
return ( preambleLen << 3 ) +
( ( fixLen == false ) ? 8 : 0 ) +
( syncWordLength << 3 ) +
( ( payloadLen +
( 0 ) + // Address filter size
( ( crcOn == true ) ? 2 : 0 )
) << 3
);
}
static uint32_t SX1272GetLoRaTimeOnAirNumerator( uint32_t bandwidth,
uint32_t datarate, uint8_t coderate,
uint16_t preambleLen, bool fixLen, uint8_t payloadLen,
bool crcOn )
{
int32_t crDenom = coderate + 4;
bool lowDatareOptimize = false;
// Ensure that the preamble length is at least 12 symbols when using SF5 or
// SF6
if( ( datarate == 5 ) || ( datarate == 6 ) )
{
if( preambleLen < 12 )
{
preambleLen = 12;
}
}
if( ( ( bandwidth == 0 ) && ( ( datarate == 11 ) || ( datarate == 12 ) ) ) ||
( ( bandwidth == 1 ) && ( datarate == 12 ) ) )
{
lowDatareOptimize = true;
}
int32_t ceilDenominator;
int32_t ceilNumerator = ( payloadLen << 3 ) +
( crcOn ? 16 : 0 ) -
( 4 * datarate ) +
( fixLen ? 0 : 20 );
if( datarate <= 6 )
{
ceilDenominator = 4 * datarate;
}
else
{
ceilNumerator += 8;
if( lowDatareOptimize == true )
{
ceilDenominator = 4 * ( datarate - 2 );
}
else
{
ceilDenominator = 4 * datarate;
}
}
if( ceilNumerator < 0 )
{
ceilNumerator = 0;
}
// Perform integral ceil()
int32_t intermediate =
( ( ceilNumerator + ceilDenominator - 1 ) / ceilDenominator ) * crDenom + preambleLen + 12;
if( datarate <= 6 )
{
intermediate += 2;
}
return ( uint32_t )( ( 4 * intermediate + 1 ) * ( 1 << ( datarate - 2 ) ) );
}
uint32_t SX1272GetTimeOnAir( RadioModems_t modem, uint32_t bandwidth,
uint32_t datarate, uint8_t coderate,
uint16_t preambleLen, bool fixLen, uint8_t payloadLen,
bool crcOn )
{
uint32_t numerator = 0;
uint32_t denominator = 1;
switch( modem )
{
case MODEM_FSK:
{
airTime = round( ( 8 * ( SX1272.Settings.Fsk.PreambleLen +
( ( SX1272Read( REG_SYNCCONFIG ) & ~RF_SYNCCONFIG_SYNCSIZE_MASK ) + 1 ) +
( ( SX1272.Settings.Fsk.FixLen == 0x01 ) ? 0.0 : 1.0 ) +
( ( ( SX1272Read( REG_PACKETCONFIG1 ) & ~RF_PACKETCONFIG1_ADDRSFILTERING_MASK ) != 0x00 ) ? 1.0 : 0 ) +
pktLen +
( ( SX1272.Settings.Fsk.CrcOn == 0x01 ) ? 2.0 : 0 ) ) /
SX1272.Settings.Fsk.Datarate ) * 1000 );
numerator = 1000U * SX1272GetGfskTimeOnAirNumerator( datarate, coderate,
preambleLen, fixLen,
payloadLen, crcOn );
denominator = datarate;
}
break;
case MODEM_LORA:
{
double bw = 0.0;
switch( SX1272.Settings.LoRa.Bandwidth )
{
case 0: // 125 kHz
bw = 125000;
break;
case 1: // 250 kHz
bw = 250000;
break;
case 2: // 500 kHz
bw = 500000;
break;
}
// Symbol rate : time for one symbol (secs)
double rs = bw / ( 1 << SX1272.Settings.LoRa.Datarate );
double ts = 1 / rs;
// time of preamble
double tPreamble = ( SX1272.Settings.LoRa.PreambleLen + 4.25 ) * ts;
// Symbol length of payload and time
double tmp = ceil( ( 8 * pktLen - 4 * SX1272.Settings.LoRa.Datarate +
28 + 16 * SX1272.Settings.LoRa.CrcOn -
( SX1272.Settings.LoRa.FixLen ? 20 : 0 ) ) /
( double )( 4 * ( SX1272.Settings.LoRa.Datarate -
( ( SX1272.Settings.LoRa.LowDatarateOptimize > 0 ) ? 2 : 0 ) ) ) ) *
( SX1272.Settings.LoRa.Coderate + 4 );
double nPayload = 8 + ( ( tmp > 0 ) ? tmp : 0 );
double tPayload = nPayload * ts;
// Time on air
double tOnAir = tPreamble + tPayload;
// return ms secs
airTime = floor( tOnAir * 1000 + 0.999 );
numerator = 1000U * SX1272GetLoRaTimeOnAirNumerator( bandwidth, datarate,
coderate, preambleLen,
fixLen, payloadLen, crcOn );
denominator = SX1272GetLoRaBandwidthInHz( bandwidth );
}
break;
}
return airTime;
// Perform integral ceil()
return ( numerator + denominator - 1 ) / denominator;
}
void SX1272Send( uint8_t *buffer, uint8_t size )
@@ -745,8 +822,13 @@ void SX1272SetSleep( void )
{
TimerStop( &RxTimeoutTimer );
TimerStop( &TxTimeoutTimer );
TimerStop( &RxTimeoutSyncWord );
SX1272SetOpMode( RF_OPMODE_SLEEP );
// Disable TCXO radio is in SLEEP mode
SX1272SetBoardTcxo( false );
SX1272.Settings.State = RF_IDLE;
}
@@ -754,6 +836,7 @@ void SX1272SetStby( void )
{
TimerStop( &RxTimeoutTimer );
TimerStop( &TxTimeoutTimer );
TimerStop( &RxTimeoutSyncWord );
SX1272SetOpMode( RF_OPMODE_STANDBY );
SX1272.Settings.State = RF_IDLE;
@@ -762,6 +845,7 @@ void SX1272SetStby( void )
void SX1272SetRx( uint32_t timeout )
{
bool rxContinuous = false;
TimerStop( &TxTimeoutTimer );
switch( SX1272.Settings.Modem )
{
@@ -880,6 +964,8 @@ void SX1272SetRx( uint32_t timeout )
void SX1272SetTx( uint32_t timeout )
{
TimerStop( &RxTimeoutTimer );
TimerSetValue( &TxTimeoutTimer, timeout );
switch( SX1272.Settings.Modem )
@@ -976,7 +1062,7 @@ void SX1272StartCad( void )
void SX1272SetTxContinuousWave( uint32_t freq, int8_t power, uint16_t time )
{
uint32_t timeout = ( uint32_t )( time * 1000 );
uint32_t timeout = ( uint32_t )time * 1000;
SX1272SetChannel( freq );
@@ -1039,6 +1125,8 @@ void SX1272SetOpMode( uint8_t opMode )
}
else
{
// Enable TCXO if operating mode different from SLEEP.
SX1272SetBoardTcxo( true );
SX1272SetAntSwLowPower( false );
SX1272SetAntSw( opMode );
}
@@ -1066,14 +1154,14 @@ void SX1272SetModem( RadioModems_t modem )
{
default:
case MODEM_FSK:
SX1272SetSleep( );
SX1272SetOpMode( RF_OPMODE_SLEEP );
SX1272Write( REG_OPMODE, ( SX1272Read( REG_OPMODE ) & RFLR_OPMODE_LONGRANGEMODE_MASK ) | RFLR_OPMODE_LONGRANGEMODE_OFF );
SX1272Write( REG_DIOMAPPING1, 0x00 );
SX1272Write( REG_DIOMAPPING2, 0x30 ); // DIO5=ModeReady
break;
case MODEM_LORA:
SX1272SetSleep( );
SX1272SetOpMode( RF_OPMODE_SLEEP );
SX1272Write( REG_OPMODE, ( SX1272Read( REG_OPMODE ) & RFLR_OPMODE_LONGRANGEMODE_MASK ) | RFLR_OPMODE_LONGRANGEMODE_ON );
SX1272Write( REG_DIOMAPPING1, 0x00 );
@@ -1082,19 +1170,19 @@ void SX1272SetModem( RadioModems_t modem )
}
}
void SX1272Write( uint16_t addr, uint8_t data )
void SX1272Write( uint32_t addr, uint8_t data )
{
SX1272WriteBuffer( addr, &data, 1 );
}
uint8_t SX1272Read( uint16_t addr )
uint8_t SX1272Read( uint32_t addr )
{
uint8_t data;
SX1272ReadBuffer( addr, &data, 1 );
return data;
}
void SX1272WriteBuffer( uint16_t addr, uint8_t *buffer, uint8_t size )
void SX1272WriteBuffer( uint32_t addr, uint8_t *buffer, uint8_t size )
{
uint8_t i;
@@ -1111,7 +1199,7 @@ void SX1272WriteBuffer( uint16_t addr, uint8_t *buffer, uint8_t size )
GpioWrite( &SX1272.Spi.Nss, 1 );
}
void SX1272ReadBuffer( uint16_t addr, uint8_t *buffer, uint8_t size )
void SX1272ReadBuffer( uint32_t addr, uint8_t *buffer, uint8_t size )
{
uint8_t i;
@@ -1200,7 +1288,6 @@ void SX1272OnTimeoutIrq( void* context )
{
// Continuous mode restart Rx chain
SX1272Write( REG_RXCONFIG, SX1272Read( REG_RXCONFIG ) | RF_RXCONFIG_RESTARTRXWITHOUTPLLLOCK );
TimerStart( &RxTimeoutSyncWord );
}
else
{
@@ -1215,10 +1302,12 @@ void SX1272OnTimeoutIrq( void* context )
break;
case RF_TX_RUNNING:
// Tx timeout shouldn't happen.
// But it has been observed that when it happens it is a result of a corrupted SPI transfer
// it depends on the platform design.
//
// The workaround is to put the radio in a known state. Thus, we re-initialize it.
// Reported issue of SPI data corruption resulting in TX TIMEOUT
// is NOT related to a bug in radio transceiver.
// It is mainly caused by improper PCB routing of SPI lines and/or
// violation of SPI specifications.
// To mitigate redesign, Semtech offers a workaround which resets
// the radio transceiver and putting it into a known state.
// BEGIN WORKAROUND
@@ -1284,7 +1373,6 @@ void SX1272OnDio0Irq( void* context )
{
// Continuous mode restart Rx chain
SX1272Write( REG_RXCONFIG, SX1272Read( REG_RXCONFIG ) | RF_RXCONFIG_RESTARTRXWITHOUTPLLLOCK );
TimerStart( &RxTimeoutSyncWord );
}
if( ( RadioEvents != NULL ) && ( RadioEvents->RxError != NULL ) )
@@ -1330,7 +1418,6 @@ void SX1272OnDio0Irq( void* context )
{
// Continuous mode restart Rx chain
SX1272Write( REG_RXCONFIG, SX1272Read( REG_RXCONFIG ) | RF_RXCONFIG_RESTARTRXWITHOUTPLLLOCK );
TimerStart( &RxTimeoutSyncWord );
}
if( ( RadioEvents != NULL ) && ( RadioEvents->RxDone != NULL ) )
@@ -1432,6 +1519,9 @@ void SX1272OnDio1Irq( void* context )
switch( SX1272.Settings.Modem )
{
case MODEM_FSK:
// Stop timer
TimerStop( &RxTimeoutSyncWord );
// FifoLevel interrupt
// Read received packet size
if( ( SX1272.Settings.FskPacketHandler.Size == 0 ) && ( SX1272.Settings.FskPacketHandler.NbBytes == 0 ) )

View File

@@ -23,6 +23,11 @@
#ifndef __SX1272_H__
#define __SX1272_H__
#ifdef __cplusplus
extern "C"
{
#endif
#include <stdint.h>
#include <stdbool.h>
#include "gpio.h"
@@ -308,12 +313,31 @@ void SX1272SetTxConfig( RadioModems_t modem, int8_t power, uint32_t fdev,
*
* \Remark Can only be called once SetRxConfig or SetTxConfig have been called
*
* \param [IN] modem Radio modem to be used [0: FSK, 1: LoRa]
* \param [IN] pktLen Packet payload length
* \param [IN] modem Radio modem to be used [0: FSK, 1: LoRa]
* \param [IN] bandwidth Sets the bandwidth
* FSK : >= 2600 and <= 250000 Hz
* LoRa: [0: 125 kHz, 1: 250 kHz,
* 2: 500 kHz, 3: Reserved]
* \param [IN] datarate Sets the Datarate
* FSK : 600..300000 bits/s
* LoRa: [6: 64, 7: 128, 8: 256, 9: 512,
* 10: 1024, 11: 2048, 12: 4096 chips]
* \param [IN] coderate Sets the coding rate (LoRa only)
* FSK : N/A ( set to 0 )
* LoRa: [1: 4/5, 2: 4/6, 3: 4/7, 4: 4/8]
* \param [IN] preambleLen Sets the Preamble length
* FSK : Number of bytes
* LoRa: Length in symbols (the hardware adds 4 more symbols)
* \param [IN] fixLen Fixed length packets [0: variable, 1: fixed]
* \param [IN] payloadLen Sets payload length when fixed length is used
* \param [IN] crcOn Enables/Disables the CRC [0: OFF, 1: ON]
*
* \retval airTime Computed airTime (ms) for the given packet payload length
*/
uint32_t SX1272GetTimeOnAir( RadioModems_t modem, uint8_t pktLen );
uint32_t SX1272GetTimeOnAir( RadioModems_t modem, uint32_t bandwidth,
uint32_t datarate, uint8_t coderate,
uint16_t preambleLen, bool fixLen, uint8_t payloadLen,
bool crcOn );
/*!
* \brief Sends the buffer of size. Prepares the packet to be sent and sets
@@ -367,7 +391,7 @@ int16_t SX1272ReadRssi( RadioModems_t modem );
* \param [IN]: addr Register address
* \param [IN]: data New register value
*/
void SX1272Write( uint16_t addr, uint8_t data );
void SX1272Write( uint32_t addr, uint8_t data );
/*!
* \brief Reads the radio register at the specified address
@@ -375,7 +399,7 @@ void SX1272Write( uint16_t addr, uint8_t data );
* \param [IN]: addr Register address
* \retval data Register value
*/
uint8_t SX1272Read( uint16_t addr );
uint8_t SX1272Read( uint32_t addr );
/*!
* \brief Writes multiple radio registers starting at address
@@ -384,7 +408,7 @@ uint8_t SX1272Read( uint16_t addr );
* \param [IN] buffer Buffer containing the new register's values
* \param [IN] size Number of registers to be written
*/
void SX1272WriteBuffer( uint16_t addr, uint8_t *buffer, uint8_t size );
void SX1272WriteBuffer( uint32_t addr, uint8_t *buffer, uint8_t size );
/*!
* \brief Reads multiple radio registers starting at address
@@ -393,7 +417,7 @@ void SX1272WriteBuffer( uint16_t addr, uint8_t *buffer, uint8_t size );
* \param [OUT] buffer Buffer where to copy the registers data
* \param [IN] size Number of registers to be read
*/
void SX1272ReadBuffer( uint16_t addr, uint8_t *buffer, uint8_t size );
void SX1272ReadBuffer( uint32_t addr, uint8_t *buffer, uint8_t size );
/*!
* \brief Sets the maximum payload length.
@@ -419,4 +443,8 @@ void SX1272SetPublicNetwork( bool enable );
*/
uint32_t SX1272GetWakeupTime( void );
#ifdef __cplusplus
}
#endif
#endif // __SX1272_H__

View File

@@ -23,6 +23,11 @@
#ifndef __SX1272_REGS_FSK_H__
#define __SX1272_REGS_FSK_H__
#ifdef __cplusplus
extern "C"
{
#endif
/*!
* ============================================================================
* SX1272 Internal registers Address
@@ -1139,4 +1144,8 @@
*/
#define RF_BITRATEFRAC_MASK 0xF0
#ifdef __cplusplus
}
#endif
#endif // __SX1272_REGS_FSK_H__

View File

@@ -23,6 +23,11 @@
#ifndef __SX1272_REGS_LORA_H__
#define __SX1272_REGS_LORA_H__
#ifdef __cplusplus
extern "C"
{
#endif
/*!
* ============================================================================
* SX1272 Internal registers Address
@@ -550,4 +555,8 @@
* RegFormerTemp
*/
#ifdef __cplusplus
}
#endif
#endif // __SX1272_REGS_LORA_H__

View File

@@ -271,6 +271,8 @@ bool SX1276IsChannelFree( RadioModems_t modem, uint32_t freq, int16_t rssiThresh
int16_t rssi = 0;
uint32_t carrierSenseTime = 0;
SX1276SetSleep( );
SX1276SetModem( modem );
SX1276SetChannel( freq );
@@ -695,83 +697,136 @@ void SX1276SetTxConfig( RadioModems_t modem, int8_t power, uint32_t fdev,
}
}
uint32_t SX1276GetTimeOnAir( RadioModems_t modem, uint8_t pktLen )
static uint32_t SX1276GetLoRaBandwidthInHz( uint32_t bw )
{
uint32_t airTime = 0;
uint32_t bandwidthInHz = 0;
switch( bw )
{
case 0: // 125 kHz
bandwidthInHz = 125000UL;
break;
case 1: // 250 kHz
bandwidthInHz = 250000UL;
break;
case 2: // 500 kHz
bandwidthInHz = 500000UL;
break;
}
return bandwidthInHz;
}
static uint32_t SX1276GetGfskTimeOnAirNumerator( uint32_t datarate, uint8_t coderate,
uint16_t preambleLen, bool fixLen, uint8_t payloadLen,
bool crcOn )
{
const uint8_t syncWordLength = 3;
return ( preambleLen << 3 ) +
( ( fixLen == false ) ? 8 : 0 ) +
( syncWordLength << 3 ) +
( ( payloadLen +
( 0 ) + // Address filter size
( ( crcOn == true ) ? 2 : 0 )
) << 3
);
}
static uint32_t SX1276GetLoRaTimeOnAirNumerator( uint32_t bandwidth,
uint32_t datarate, uint8_t coderate,
uint16_t preambleLen, bool fixLen, uint8_t payloadLen,
bool crcOn )
{
int32_t crDenom = coderate + 4;
bool lowDatareOptimize = false;
// Ensure that the preamble length is at least 12 symbols when using SF5 or
// SF6
if( ( datarate == 5 ) || ( datarate == 6 ) )
{
if( preambleLen < 12 )
{
preambleLen = 12;
}
}
if( ( ( bandwidth == 0 ) && ( ( datarate == 11 ) || ( datarate == 12 ) ) ) ||
( ( bandwidth == 1 ) && ( datarate == 12 ) ) )
{
lowDatareOptimize = true;
}
int32_t ceilDenominator;
int32_t ceilNumerator = ( payloadLen << 3 ) +
( crcOn ? 16 : 0 ) -
( 4 * datarate ) +
( fixLen ? 0 : 20 );
if( datarate <= 6 )
{
ceilDenominator = 4 * datarate;
}
else
{
ceilNumerator += 8;
if( lowDatareOptimize == true )
{
ceilDenominator = 4 * ( datarate - 2 );
}
else
{
ceilDenominator = 4 * datarate;
}
}
if( ceilNumerator < 0 )
{
ceilNumerator = 0;
}
// Perform integral ceil()
int32_t intermediate =
( ( ceilNumerator + ceilDenominator - 1 ) / ceilDenominator ) * crDenom + preambleLen + 12;
if( datarate <= 6 )
{
intermediate += 2;
}
return ( uint32_t )( ( 4 * intermediate + 1 ) * ( 1 << ( datarate - 2 ) ) );
}
uint32_t SX1276GetTimeOnAir( RadioModems_t modem, uint32_t bandwidth,
uint32_t datarate, uint8_t coderate,
uint16_t preambleLen, bool fixLen, uint8_t payloadLen,
bool crcOn )
{
uint32_t numerator = 0;
uint32_t denominator = 1;
switch( modem )
{
case MODEM_FSK:
{
airTime = round( ( 8 * ( SX1276.Settings.Fsk.PreambleLen +
( ( SX1276Read( REG_SYNCCONFIG ) & ~RF_SYNCCONFIG_SYNCSIZE_MASK ) + 1 ) +
( ( SX1276.Settings.Fsk.FixLen == 0x01 ) ? 0.0 : 1.0 ) +
( ( ( SX1276Read( REG_PACKETCONFIG1 ) & ~RF_PACKETCONFIG1_ADDRSFILTERING_MASK ) != 0x00 ) ? 1.0 : 0 ) +
pktLen +
( ( SX1276.Settings.Fsk.CrcOn == 0x01 ) ? 2.0 : 0 ) ) /
SX1276.Settings.Fsk.Datarate ) * 1000 );
numerator = 1000U * SX1276GetGfskTimeOnAirNumerator( datarate, coderate,
preambleLen, fixLen,
payloadLen, crcOn );
denominator = datarate;
}
break;
case MODEM_LORA:
{
double bw = 0.0;
// REMARK: When using LoRa modem only bandwidths 125, 250 and 500 kHz are supported
switch( SX1276.Settings.LoRa.Bandwidth )
{
//case 0: // 7.8 kHz
// bw = 7800;
// break;
//case 1: // 10.4 kHz
// bw = 10400;
// break;
//case 2: // 15.6 kHz
// bw = 15600;
// break;
//case 3: // 20.8 kHz
// bw = 20800;
// break;
//case 4: // 31.2 kHz
// bw = 31200;
// break;
//case 5: // 41.4 kHz
// bw = 41400;
// break;
//case 6: // 62.5 kHz
// bw = 62500;
// break;
case 7: // 125 kHz
bw = 125000;
break;
case 8: // 250 kHz
bw = 250000;
break;
case 9: // 500 kHz
bw = 500000;
break;
}
// Symbol rate : time for one symbol (secs)
double rs = bw / ( 1 << SX1276.Settings.LoRa.Datarate );
double ts = 1 / rs;
// time of preamble
double tPreamble = ( SX1276.Settings.LoRa.PreambleLen + 4.25 ) * ts;
// Symbol length of payload and time
double tmp = ceil( ( 8 * pktLen - 4 * SX1276.Settings.LoRa.Datarate +
28 + 16 * SX1276.Settings.LoRa.CrcOn -
( SX1276.Settings.LoRa.FixLen ? 20 : 0 ) ) /
( double )( 4 * ( SX1276.Settings.LoRa.Datarate -
( ( SX1276.Settings.LoRa.LowDatarateOptimize > 0 ) ? 2 : 0 ) ) ) ) *
( SX1276.Settings.LoRa.Coderate + 4 );
double nPayload = 8 + ( ( tmp > 0 ) ? tmp : 0 );
double tPayload = nPayload * ts;
// Time on air
double tOnAir = tPreamble + tPayload;
// return ms secs
airTime = floor( tOnAir * 1000 + 0.999 );
numerator = 1000U * SX1276GetLoRaTimeOnAirNumerator( bandwidth, datarate,
coderate, preambleLen,
fixLen, payloadLen, crcOn );
denominator = SX1276GetLoRaBandwidthInHz( bandwidth );
}
break;
}
return airTime;
// Perform integral ceil()
return ( numerator + denominator - 1 ) / denominator;
}
void SX1276Send( uint8_t *buffer, uint8_t size )
@@ -852,8 +907,13 @@ void SX1276SetSleep( void )
{
TimerStop( &RxTimeoutTimer );
TimerStop( &TxTimeoutTimer );
TimerStop( &RxTimeoutSyncWord );
SX1276SetOpMode( RF_OPMODE_SLEEP );
// Disable TCXO radio is in SLEEP mode
SX1276SetBoardTcxo( false );
SX1276.Settings.State = RF_IDLE;
}
@@ -861,6 +921,7 @@ void SX1276SetStby( void )
{
TimerStop( &RxTimeoutTimer );
TimerStop( &TxTimeoutTimer );
TimerStop( &RxTimeoutSyncWord );
SX1276SetOpMode( RF_OPMODE_STANDBY );
SX1276.Settings.State = RF_IDLE;
@@ -869,6 +930,7 @@ void SX1276SetStby( void )
void SX1276SetRx( uint32_t timeout )
{
bool rxContinuous = false;
TimerStop( &TxTimeoutTimer );
switch( SX1276.Settings.Modem )
{
@@ -1034,6 +1096,8 @@ void SX1276SetRx( uint32_t timeout )
void SX1276SetTx( uint32_t timeout )
{
TimerStop( &RxTimeoutTimer );
TimerSetValue( &TxTimeoutTimer, timeout );
switch( SX1276.Settings.Modem )
@@ -1130,7 +1194,7 @@ void SX1276StartCad( void )
void SX1276SetTxContinuousWave( uint32_t freq, int8_t power, uint16_t time )
{
uint32_t timeout = ( uint32_t )( time * 1000 );
uint32_t timeout = ( uint32_t )time * 1000;
SX1276SetChannel( freq );
@@ -1200,6 +1264,8 @@ void SX1276SetOpMode( uint8_t opMode )
}
else
{
// Enable TCXO if operating mode different from SLEEP.
SX1276SetBoardTcxo( true );
SX1276SetAntSwLowPower( false );
SX1276SetAntSw( opMode );
}
@@ -1227,14 +1293,14 @@ void SX1276SetModem( RadioModems_t modem )
{
default:
case MODEM_FSK:
SX1276SetSleep( );
SX1276SetOpMode( RF_OPMODE_SLEEP );
SX1276Write( REG_OPMODE, ( SX1276Read( REG_OPMODE ) & RFLR_OPMODE_LONGRANGEMODE_MASK ) | RFLR_OPMODE_LONGRANGEMODE_OFF );
SX1276Write( REG_DIOMAPPING1, 0x00 );
SX1276Write( REG_DIOMAPPING2, 0x30 ); // DIO5=ModeReady
break;
case MODEM_LORA:
SX1276SetSleep( );
SX1276SetOpMode( RF_OPMODE_SLEEP );
SX1276Write( REG_OPMODE, ( SX1276Read( REG_OPMODE ) & RFLR_OPMODE_LONGRANGEMODE_MASK ) | RFLR_OPMODE_LONGRANGEMODE_ON );
SX1276Write( REG_DIOMAPPING1, 0x00 );
@@ -1243,19 +1309,19 @@ void SX1276SetModem( RadioModems_t modem )
}
}
void SX1276Write( uint16_t addr, uint8_t data )
void SX1276Write( uint32_t addr, uint8_t data )
{
SX1276WriteBuffer( addr, &data, 1 );
}
uint8_t SX1276Read( uint16_t addr )
uint8_t SX1276Read( uint32_t addr )
{
uint8_t data;
SX1276ReadBuffer( addr, &data, 1 );
return data;
}
void SX1276WriteBuffer( uint16_t addr, uint8_t *buffer, uint8_t size )
void SX1276WriteBuffer( uint32_t addr, uint8_t *buffer, uint8_t size )
{
uint8_t i;
@@ -1272,7 +1338,7 @@ void SX1276WriteBuffer( uint16_t addr, uint8_t *buffer, uint8_t size )
GpioWrite( &SX1276.Spi.Nss, 1 );
}
void SX1276ReadBuffer( uint16_t addr, uint8_t *buffer, uint8_t size )
void SX1276ReadBuffer( uint32_t addr, uint8_t *buffer, uint8_t size )
{
uint8_t i;
@@ -1361,7 +1427,6 @@ void SX1276OnTimeoutIrq( void* context )
{
// Continuous mode restart Rx chain
SX1276Write( REG_RXCONFIG, SX1276Read( REG_RXCONFIG ) | RF_RXCONFIG_RESTARTRXWITHOUTPLLLOCK );
TimerStart( &RxTimeoutSyncWord );
}
else
{
@@ -1376,10 +1441,12 @@ void SX1276OnTimeoutIrq( void* context )
break;
case RF_TX_RUNNING:
// Tx timeout shouldn't happen.
// But it has been observed that when it happens it is a result of a corrupted SPI transfer
// it depends on the platform design.
//
// The workaround is to put the radio in a known state. Thus, we re-initialize it.
// Reported issue of SPI data corruption resulting in TX TIMEOUT
// is NOT related to a bug in radio transceiver.
// It is mainly caused by improper PCB routing of SPI lines and/or
// violation of SPI specifications.
// To mitigate redesign, Semtech offers a workaround which resets
// the radio transceiver and putting it into a known state.
// BEGIN WORKAROUND
@@ -1448,7 +1515,6 @@ void SX1276OnDio0Irq( void* context )
{
// Continuous mode restart Rx chain
SX1276Write( REG_RXCONFIG, SX1276Read( REG_RXCONFIG ) | RF_RXCONFIG_RESTARTRXWITHOUTPLLLOCK );
TimerStart( &RxTimeoutSyncWord );
}
if( ( RadioEvents != NULL ) && ( RadioEvents->RxError != NULL ) )
@@ -1494,7 +1560,6 @@ void SX1276OnDio0Irq( void* context )
{
// Continuous mode restart Rx chain
SX1276Write( REG_RXCONFIG, SX1276Read( REG_RXCONFIG ) | RF_RXCONFIG_RESTARTRXWITHOUTPLLLOCK );
TimerStart( &RxTimeoutSyncWord );
}
if( ( RadioEvents != NULL ) && ( RadioEvents->RxDone != NULL ) )
@@ -1611,6 +1676,9 @@ void SX1276OnDio1Irq( void* context )
switch( SX1276.Settings.Modem )
{
case MODEM_FSK:
// Stop timer
TimerStop( &RxTimeoutSyncWord );
// FifoLevel interrupt
// Read received packet size
if( ( SX1276.Settings.FskPacketHandler.Size == 0 ) && ( SX1276.Settings.FskPacketHandler.NbBytes == 0 ) )

View File

@@ -23,6 +23,11 @@
#ifndef __SX1276_H__
#define __SX1276_H__
#ifdef __cplusplus
extern "C"
{
#endif
#include <stdint.h>
#include <stdbool.h>
#include "gpio.h"
@@ -312,12 +317,31 @@ void SX1276SetTxConfig( RadioModems_t modem, int8_t power, uint32_t fdev,
*
* \Remark Can only be called once SetRxConfig or SetTxConfig have been called
*
* \param [IN] modem Radio modem to be used [0: FSK, 1: LoRa]
* \param [IN] pktLen Packet payload length
* \param [IN] modem Radio modem to be used [0: FSK, 1: LoRa]
* \param [IN] bandwidth Sets the bandwidth
* FSK : >= 2600 and <= 250000 Hz
* LoRa: [0: 125 kHz, 1: 250 kHz,
* 2: 500 kHz, 3: Reserved]
* \param [IN] datarate Sets the Datarate
* FSK : 600..300000 bits/s
* LoRa: [6: 64, 7: 128, 8: 256, 9: 512,
* 10: 1024, 11: 2048, 12: 4096 chips]
* \param [IN] coderate Sets the coding rate (LoRa only)
* FSK : N/A ( set to 0 )
* LoRa: [1: 4/5, 2: 4/6, 3: 4/7, 4: 4/8]
* \param [IN] preambleLen Sets the Preamble length
* FSK : Number of bytes
* LoRa: Length in symbols (the hardware adds 4 more symbols)
* \param [IN] fixLen Fixed length packets [0: variable, 1: fixed]
* \param [IN] payloadLen Sets payload length when fixed length is used
* \param [IN] crcOn Enables/Disables the CRC [0: OFF, 1: ON]
*
* \retval airTime Computed airTime (ms) for the given packet payload length
*/
uint32_t SX1276GetTimeOnAir( RadioModems_t modem, uint8_t pktLen );
uint32_t SX1276GetTimeOnAir( RadioModems_t modem, uint32_t bandwidth,
uint32_t datarate, uint8_t coderate,
uint16_t preambleLen, bool fixLen, uint8_t payloadLen,
bool crcOn );
/*!
* \brief Sends the buffer of size. Prepares the packet to be sent and sets
@@ -371,7 +395,7 @@ int16_t SX1276ReadRssi( RadioModems_t modem );
* \param [IN]: addr Register address
* \param [IN]: data New register value
*/
void SX1276Write( uint16_t addr, uint8_t data );
void SX1276Write( uint32_t addr, uint8_t data );
/*!
* \brief Reads the radio register at the specified address
@@ -379,7 +403,7 @@ void SX1276Write( uint16_t addr, uint8_t data );
* \param [IN]: addr Register address
* \retval data Register value
*/
uint8_t SX1276Read( uint16_t addr );
uint8_t SX1276Read( uint32_t addr );
/*!
* \brief Writes multiple radio registers starting at address
@@ -388,7 +412,7 @@ uint8_t SX1276Read( uint16_t addr );
* \param [IN] buffer Buffer containing the new register's values
* \param [IN] size Number of registers to be written
*/
void SX1276WriteBuffer( uint16_t addr, uint8_t *buffer, uint8_t size );
void SX1276WriteBuffer( uint32_t addr, uint8_t *buffer, uint8_t size );
/*!
* \brief Reads multiple radio registers starting at address
@@ -397,7 +421,7 @@ void SX1276WriteBuffer( uint16_t addr, uint8_t *buffer, uint8_t size );
* \param [OUT] buffer Buffer where to copy the registers data
* \param [IN] size Number of registers to be read
*/
void SX1276ReadBuffer( uint16_t addr, uint8_t *buffer, uint8_t size );
void SX1276ReadBuffer( uint32_t addr, uint8_t *buffer, uint8_t size );
/*!
* \brief Sets the maximum payload length.
@@ -423,4 +447,8 @@ void SX1276SetPublicNetwork( bool enable );
*/
uint32_t SX1276GetWakeupTime( void );
#ifdef __cplusplus
}
#endif
#endif // __SX1276_H__

View File

@@ -23,6 +23,11 @@
#ifndef __SX1276_REGS_FSK_H__
#define __SX1276_REGS_FSK_H__
#ifdef __cplusplus
extern "C"
{
#endif
/*!
* ============================================================================
* SX1276 Internal registers Address
@@ -1139,4 +1144,8 @@
#define RF_PLL_BANDWIDTH_225 0x80
#define RF_PLL_BANDWIDTH_300 0xC0 // Default
#ifdef __cplusplus
}
#endif
#endif // __SX1276_REGS_FSK_H__

View File

@@ -23,6 +23,11 @@
#ifndef __SX1276_REGS_LORA_H__
#define __SX1276_REGS_LORA_H__
#ifdef __cplusplus
extern "C"
{
#endif
/*!
* ============================================================================
* SX1276 Internal registers Address
@@ -570,4 +575,8 @@
#define RF_PLL_BANDWIDTH_225 0x80
#define RF_PLL_BANDWIDTH_300 0xC0 // Default
#ifdef __cplusplus
}
#endif
#endif // __SX1276_REGS_LORA_H__