wayne roberts / Mbed OS LoRaWAN_singlechannel_endnode

Dependencies:   SX127x sx12xx_hal TSL2561

Committer:
dudmuck
Date:
Fri Aug 04 13:23:38 2017 -0700
Revision:
20:42839629a5dc
Parent:
18:9ac71c0eb70d
add sleep() call, mbedignore rtos

Who changed what in which revision?

UserRevisionLine numberNew contents of line
dudmuck 0:8f0d0ae0a077 1 /*
dudmuck 0:8f0d0ae0a077 2 / _____) _ | |
dudmuck 0:8f0d0ae0a077 3 ( (____ _____ ____ _| |_ _____ ____| |__
dudmuck 0:8f0d0ae0a077 4 \____ \| ___ | (_ _) ___ |/ ___) _ \
dudmuck 0:8f0d0ae0a077 5 _____) ) ____| | | || |_| ____( (___| | | |
dudmuck 0:8f0d0ae0a077 6 (______/|_____)_|_|_| \__)_____)\____)_| |_|
dudmuck 0:8f0d0ae0a077 7 (C) 2014 Semtech
dudmuck 0:8f0d0ae0a077 8
dudmuck 0:8f0d0ae0a077 9 Description: Actual implementation of a SX1276 radio, inherits Radio
dudmuck 0:8f0d0ae0a077 10
dudmuck 0:8f0d0ae0a077 11 License: Revised BSD License, see LICENSE.TXT file include in the project
dudmuck 0:8f0d0ae0a077 12
dudmuck 0:8f0d0ae0a077 13 Maintainers: Miguel Luis, Gregory Cristian and Nicolas Huguenin
dudmuck 0:8f0d0ae0a077 14 */
dudmuck 0:8f0d0ae0a077 15 #include "sx1276.h"
dudmuck 3:aead8f8fdc1f 16 #ifdef ENABLE_SX1276
dudmuck 0:8f0d0ae0a077 17
dudmuck 0:8f0d0ae0a077 18 extern LowPowerTimer lp_timer; // from LoRaMac
dudmuck 0:8f0d0ae0a077 19
dudmuck 20:42839629a5dc 20 static volatile struct {
dudmuck 20:42839629a5dc 21 uint8_t dio0 : 1;
dudmuck 20:42839629a5dc 22 uint8_t dio1 : 1;
dudmuck 20:42839629a5dc 23 } flags;
dudmuck 20:42839629a5dc 24
dudmuck 0:8f0d0ae0a077 25 const FskBandwidth_t SX1276::FskBandwidths[] =
dudmuck 0:8f0d0ae0a077 26 {
dudmuck 0:8f0d0ae0a077 27 { 2600 , 0x17 },
dudmuck 0:8f0d0ae0a077 28 { 3100 , 0x0F },
dudmuck 0:8f0d0ae0a077 29 { 3900 , 0x07 },
dudmuck 0:8f0d0ae0a077 30 { 5200 , 0x16 },
dudmuck 0:8f0d0ae0a077 31 { 6300 , 0x0E },
dudmuck 0:8f0d0ae0a077 32 { 7800 , 0x06 },
dudmuck 0:8f0d0ae0a077 33 { 10400 , 0x15 },
dudmuck 0:8f0d0ae0a077 34 { 12500 , 0x0D },
dudmuck 0:8f0d0ae0a077 35 { 15600 , 0x05 },
dudmuck 0:8f0d0ae0a077 36 { 20800 , 0x14 },
dudmuck 0:8f0d0ae0a077 37 { 25000 , 0x0C },
dudmuck 0:8f0d0ae0a077 38 { 31300 , 0x04 },
dudmuck 0:8f0d0ae0a077 39 { 41700 , 0x13 },
dudmuck 0:8f0d0ae0a077 40 { 50000 , 0x0B },
dudmuck 0:8f0d0ae0a077 41 { 62500 , 0x03 },
dudmuck 0:8f0d0ae0a077 42 { 83333 , 0x12 },
dudmuck 0:8f0d0ae0a077 43 { 100000, 0x0A },
dudmuck 0:8f0d0ae0a077 44 { 125000, 0x02 },
dudmuck 0:8f0d0ae0a077 45 { 166700, 0x11 },
dudmuck 0:8f0d0ae0a077 46 { 200000, 0x09 },
dudmuck 0:8f0d0ae0a077 47 { 250000, 0x01 },
dudmuck 0:8f0d0ae0a077 48 { 300000, 0x00 }, // Invalid Bandwidth
dudmuck 0:8f0d0ae0a077 49 };
dudmuck 0:8f0d0ae0a077 50
dudmuck 0:8f0d0ae0a077 51
dudmuck 0:8f0d0ae0a077 52 SX1276::SX1276( RadioEvents_t *events,
dudmuck 0:8f0d0ae0a077 53 PinName mosi, PinName miso, PinName sclk, PinName nss, PinName reset,
dudmuck 0:8f0d0ae0a077 54 PinName dio0, PinName dio1, PinName dio2, PinName dio3, PinName dio4, PinName dio5 )
dudmuck 0:8f0d0ae0a077 55 : Radio( events ),
dudmuck 0:8f0d0ae0a077 56 spi( mosi, miso, sclk ),
dudmuck 0:8f0d0ae0a077 57 nss( nss ),
dudmuck 0:8f0d0ae0a077 58 reset( reset ),
dudmuck 0:8f0d0ae0a077 59 dio0( dio0 ), dio1( dio1 ), dio2( dio2 ), dio3( dio3 ), dio4( dio4 ), dio5( dio5 ),
dudmuck 0:8f0d0ae0a077 60 isRadioActive( false )
dudmuck 0:8f0d0ae0a077 61 {
dudmuck 0:8f0d0ae0a077 62 wait_ms( 10 );
dudmuck 0:8f0d0ae0a077 63 this->rxtxBuffer = new uint8_t[RX_BUFFER_SIZE];
dudmuck 0:8f0d0ae0a077 64
dudmuck 0:8f0d0ae0a077 65 this->RadioEvents = events;
dudmuck 0:8f0d0ae0a077 66
dudmuck 0:8f0d0ae0a077 67 this->dioIrq = new DioIrqHandler[6];
dudmuck 0:8f0d0ae0a077 68
dudmuck 0:8f0d0ae0a077 69 this->dioIrq[0] = &SX1276::OnDio0Irq;
dudmuck 0:8f0d0ae0a077 70 this->dioIrq[1] = &SX1276::OnDio1Irq;
dudmuck 0:8f0d0ae0a077 71 this->dioIrq[2] = &SX1276::OnDio2Irq;
dudmuck 0:8f0d0ae0a077 72 this->dioIrq[3] = &SX1276::OnDio3Irq;
dudmuck 0:8f0d0ae0a077 73 this->dioIrq[4] = &SX1276::OnDio4Irq;
dudmuck 0:8f0d0ae0a077 74 this->dioIrq[5] = NULL;
dudmuck 0:8f0d0ae0a077 75
dudmuck 0:8f0d0ae0a077 76 this->settings.State = RF_IDLE;
dudmuck 0:8f0d0ae0a077 77 }
dudmuck 0:8f0d0ae0a077 78
dudmuck 0:8f0d0ae0a077 79 SX1276::~SX1276( )
dudmuck 0:8f0d0ae0a077 80 {
dudmuck 0:8f0d0ae0a077 81 delete this->rxtxBuffer;
dudmuck 0:8f0d0ae0a077 82 delete this->dioIrq;
dudmuck 0:8f0d0ae0a077 83 }
dudmuck 0:8f0d0ae0a077 84
dudmuck 0:8f0d0ae0a077 85 void SX1276::Init( RadioEvents_t *events )
dudmuck 0:8f0d0ae0a077 86 {
dudmuck 0:8f0d0ae0a077 87 this->RadioEvents = events;
dudmuck 0:8f0d0ae0a077 88 }
dudmuck 0:8f0d0ae0a077 89
dudmuck 0:8f0d0ae0a077 90 RadioState SX1276::GetStatus( void )
dudmuck 0:8f0d0ae0a077 91 {
dudmuck 0:8f0d0ae0a077 92 return this->settings.State;
dudmuck 0:8f0d0ae0a077 93 }
dudmuck 0:8f0d0ae0a077 94
dudmuck 0:8f0d0ae0a077 95 void SX1276::SetChannel( uint32_t freq )
dudmuck 0:8f0d0ae0a077 96 {
dudmuck 0:8f0d0ae0a077 97 this->settings.Channel = freq;
dudmuck 0:8f0d0ae0a077 98 freq = ( uint32_t )( ( double )freq / ( double )FREQ_STEP );
dudmuck 0:8f0d0ae0a077 99 Write( REG_FRFMSB, ( uint8_t )( ( freq >> 16 ) & 0xFF ) );
dudmuck 0:8f0d0ae0a077 100 Write( REG_FRFMID, ( uint8_t )( ( freq >> 8 ) & 0xFF ) );
dudmuck 0:8f0d0ae0a077 101 Write( REG_FRFLSB, ( uint8_t )( freq & 0xFF ) );
dudmuck 0:8f0d0ae0a077 102 }
dudmuck 0:8f0d0ae0a077 103
dudmuck 0:8f0d0ae0a077 104 bool SX1276::IsChannelFree( RadioModems_t modem, uint32_t freq, int16_t rssiThresh )
dudmuck 0:8f0d0ae0a077 105 {
dudmuck 0:8f0d0ae0a077 106 int16_t rssi = 0;
dudmuck 0:8f0d0ae0a077 107
dudmuck 0:8f0d0ae0a077 108 SetModem( modem );
dudmuck 0:8f0d0ae0a077 109
dudmuck 0:8f0d0ae0a077 110 SetChannel( freq );
dudmuck 0:8f0d0ae0a077 111
dudmuck 0:8f0d0ae0a077 112 SetOpMode( RF_OPMODE_RECEIVER );
dudmuck 0:8f0d0ae0a077 113
dudmuck 0:8f0d0ae0a077 114 wait_ms( 1 );
dudmuck 0:8f0d0ae0a077 115
dudmuck 0:8f0d0ae0a077 116 rssi = GetRssi( modem );
dudmuck 0:8f0d0ae0a077 117
dudmuck 0:8f0d0ae0a077 118 Sleep( );
dudmuck 0:8f0d0ae0a077 119
dudmuck 0:8f0d0ae0a077 120 if( rssi > rssiThresh )
dudmuck 0:8f0d0ae0a077 121 {
dudmuck 0:8f0d0ae0a077 122 return false;
dudmuck 0:8f0d0ae0a077 123 }
dudmuck 0:8f0d0ae0a077 124 return true;
dudmuck 0:8f0d0ae0a077 125 }
dudmuck 0:8f0d0ae0a077 126
dudmuck 0:8f0d0ae0a077 127 uint32_t SX1276::Random( void )
dudmuck 0:8f0d0ae0a077 128 {
dudmuck 0:8f0d0ae0a077 129 uint8_t i;
dudmuck 0:8f0d0ae0a077 130 uint32_t rnd = 0;
dudmuck 0:8f0d0ae0a077 131
dudmuck 0:8f0d0ae0a077 132 /*
dudmuck 0:8f0d0ae0a077 133 * Radio setup for random number generation
dudmuck 0:8f0d0ae0a077 134 */
dudmuck 0:8f0d0ae0a077 135 // Set LoRa modem ON
dudmuck 0:8f0d0ae0a077 136 SetModem( MODEM_LORA );
dudmuck 0:8f0d0ae0a077 137
dudmuck 0:8f0d0ae0a077 138 // Disable LoRa modem interrupts
dudmuck 0:8f0d0ae0a077 139 Write( REG_LR_IRQFLAGSMASK, RFLR_IRQFLAGS_RXTIMEOUT |
dudmuck 0:8f0d0ae0a077 140 RFLR_IRQFLAGS_RXDONE |
dudmuck 0:8f0d0ae0a077 141 RFLR_IRQFLAGS_PAYLOADCRCERROR |
dudmuck 0:8f0d0ae0a077 142 RFLR_IRQFLAGS_VALIDHEADER |
dudmuck 0:8f0d0ae0a077 143 RFLR_IRQFLAGS_TXDONE |
dudmuck 0:8f0d0ae0a077 144 RFLR_IRQFLAGS_CADDONE |
dudmuck 0:8f0d0ae0a077 145 RFLR_IRQFLAGS_FHSSCHANGEDCHANNEL |
dudmuck 0:8f0d0ae0a077 146 RFLR_IRQFLAGS_CADDETECTED );
dudmuck 0:8f0d0ae0a077 147
dudmuck 0:8f0d0ae0a077 148 // Set radio in continuous reception
dudmuck 0:8f0d0ae0a077 149 SetOpMode( RF_OPMODE_RECEIVER );
dudmuck 0:8f0d0ae0a077 150
dudmuck 0:8f0d0ae0a077 151 for( i = 0; i < 32; i++ )
dudmuck 0:8f0d0ae0a077 152 {
dudmuck 0:8f0d0ae0a077 153 wait_ms( 1 );
dudmuck 0:8f0d0ae0a077 154 // Unfiltered RSSI value reading. Only takes the LSB value
dudmuck 0:8f0d0ae0a077 155 rnd |= ( ( uint32_t )Read( REG_LR_RSSIWIDEBAND ) & 0x01 ) << i;
dudmuck 0:8f0d0ae0a077 156 }
dudmuck 0:8f0d0ae0a077 157
dudmuck 0:8f0d0ae0a077 158 Sleep( );
dudmuck 0:8f0d0ae0a077 159
dudmuck 0:8f0d0ae0a077 160 return rnd;
dudmuck 0:8f0d0ae0a077 161 }
dudmuck 0:8f0d0ae0a077 162
dudmuck 0:8f0d0ae0a077 163 /*!
dudmuck 0:8f0d0ae0a077 164 * Performs the Rx chain calibration for LF and HF bands
dudmuck 0:8f0d0ae0a077 165 * \remark Must be called just after the reset so all registers are at their
dudmuck 0:8f0d0ae0a077 166 * default values
dudmuck 0:8f0d0ae0a077 167 */
dudmuck 0:8f0d0ae0a077 168 void SX1276::RxChainCalibration( void )
dudmuck 0:8f0d0ae0a077 169 {
dudmuck 0:8f0d0ae0a077 170 uint8_t regPaConfigInitVal;
dudmuck 0:8f0d0ae0a077 171 uint32_t initialFreq;
dudmuck 0:8f0d0ae0a077 172
dudmuck 0:8f0d0ae0a077 173 // Save context
dudmuck 0:8f0d0ae0a077 174 regPaConfigInitVal = this->Read( REG_PACONFIG );
dudmuck 0:8f0d0ae0a077 175 initialFreq = ( double )( ( ( uint32_t )this->Read( REG_FRFMSB ) << 16 ) |
dudmuck 0:8f0d0ae0a077 176 ( ( uint32_t )this->Read( REG_FRFMID ) << 8 ) |
dudmuck 0:8f0d0ae0a077 177 ( ( uint32_t )this->Read( REG_FRFLSB ) ) ) * ( double )FREQ_STEP;
dudmuck 0:8f0d0ae0a077 178
dudmuck 0:8f0d0ae0a077 179 // Cut the PA just in case, RFO output, power = -1 dBm
dudmuck 0:8f0d0ae0a077 180 this->Write( REG_PACONFIG, 0x00 );
dudmuck 0:8f0d0ae0a077 181
dudmuck 0:8f0d0ae0a077 182 // Launch Rx chain calibration for LF band
dudmuck 0:8f0d0ae0a077 183 Write ( REG_IMAGECAL, ( Read( REG_IMAGECAL ) & RF_IMAGECAL_IMAGECAL_MASK ) | RF_IMAGECAL_IMAGECAL_START );
dudmuck 0:8f0d0ae0a077 184 while( ( Read( REG_IMAGECAL ) & RF_IMAGECAL_IMAGECAL_RUNNING ) == RF_IMAGECAL_IMAGECAL_RUNNING )
dudmuck 0:8f0d0ae0a077 185 {
dudmuck 0:8f0d0ae0a077 186 }
dudmuck 0:8f0d0ae0a077 187
dudmuck 0:8f0d0ae0a077 188 // Sets a Frequency in HF band
dudmuck 0:8f0d0ae0a077 189 SetChannel( 868000000 );
dudmuck 0:8f0d0ae0a077 190
dudmuck 0:8f0d0ae0a077 191 // Launch Rx chain calibration for HF band
dudmuck 0:8f0d0ae0a077 192 Write ( REG_IMAGECAL, ( Read( REG_IMAGECAL ) & RF_IMAGECAL_IMAGECAL_MASK ) | RF_IMAGECAL_IMAGECAL_START );
dudmuck 0:8f0d0ae0a077 193 while( ( Read( REG_IMAGECAL ) & RF_IMAGECAL_IMAGECAL_RUNNING ) == RF_IMAGECAL_IMAGECAL_RUNNING )
dudmuck 0:8f0d0ae0a077 194 {
dudmuck 0:8f0d0ae0a077 195 }
dudmuck 0:8f0d0ae0a077 196
dudmuck 0:8f0d0ae0a077 197 // Restore context
dudmuck 0:8f0d0ae0a077 198 this->Write( REG_PACONFIG, regPaConfigInitVal );
dudmuck 0:8f0d0ae0a077 199 SetChannel( initialFreq );
dudmuck 0:8f0d0ae0a077 200 }
dudmuck 0:8f0d0ae0a077 201
dudmuck 0:8f0d0ae0a077 202 /*!
dudmuck 0:8f0d0ae0a077 203 * Returns the known FSK bandwidth registers value
dudmuck 0:8f0d0ae0a077 204 *
dudmuck 0:8f0d0ae0a077 205 * \param [IN] bandwidth Bandwidth value in Hz
dudmuck 0:8f0d0ae0a077 206 * \retval regValue Bandwidth register value.
dudmuck 0:8f0d0ae0a077 207 */
dudmuck 0:8f0d0ae0a077 208 uint8_t SX1276::GetFskBandwidthRegValue( uint32_t bandwidth )
dudmuck 0:8f0d0ae0a077 209 {
dudmuck 0:8f0d0ae0a077 210 uint8_t i;
dudmuck 0:8f0d0ae0a077 211
dudmuck 0:8f0d0ae0a077 212 for( i = 0; i < ( sizeof( FskBandwidths ) / sizeof( FskBandwidth_t ) ) - 1; i++ )
dudmuck 0:8f0d0ae0a077 213 {
dudmuck 0:8f0d0ae0a077 214 if( ( bandwidth >= FskBandwidths[i].bandwidth ) && ( bandwidth < FskBandwidths[i + 1].bandwidth ) )
dudmuck 0:8f0d0ae0a077 215 {
dudmuck 0:8f0d0ae0a077 216 return FskBandwidths[i].RegValue;
dudmuck 0:8f0d0ae0a077 217 }
dudmuck 0:8f0d0ae0a077 218 }
dudmuck 0:8f0d0ae0a077 219 // ERROR: Value not found
dudmuck 0:8f0d0ae0a077 220 while( 1 );
dudmuck 0:8f0d0ae0a077 221 }
dudmuck 0:8f0d0ae0a077 222
dudmuck 0:8f0d0ae0a077 223 void SX1276::SetRxConfig( RadioModems_t modem, uint32_t bandwidth,
dudmuck 0:8f0d0ae0a077 224 uint32_t datarate, uint8_t coderate,
dudmuck 0:8f0d0ae0a077 225 uint32_t bandwidthAfc, uint16_t preambleLen,
dudmuck 0:8f0d0ae0a077 226 uint16_t symbTimeout, bool fixLen,
dudmuck 0:8f0d0ae0a077 227 uint8_t payloadLen,
dudmuck 0:8f0d0ae0a077 228 bool crcOn, bool freqHopOn, uint8_t hopPeriod,
dudmuck 0:8f0d0ae0a077 229 bool iqInverted, bool rxContinuous )
dudmuck 0:8f0d0ae0a077 230 {
dudmuck 0:8f0d0ae0a077 231 SetModem( modem );
dudmuck 0:8f0d0ae0a077 232
dudmuck 0:8f0d0ae0a077 233 switch( modem )
dudmuck 0:8f0d0ae0a077 234 {
dudmuck 0:8f0d0ae0a077 235 case MODEM_FSK:
dudmuck 0:8f0d0ae0a077 236 {
dudmuck 0:8f0d0ae0a077 237 this->settings.Fsk.Bandwidth = bandwidth;
dudmuck 0:8f0d0ae0a077 238 this->settings.Fsk.Datarate = datarate;
dudmuck 0:8f0d0ae0a077 239 this->settings.Fsk.BandwidthAfc = bandwidthAfc;
dudmuck 0:8f0d0ae0a077 240 this->settings.Fsk.FixLen = fixLen;
dudmuck 0:8f0d0ae0a077 241 this->settings.Fsk.PayloadLen = payloadLen;
dudmuck 0:8f0d0ae0a077 242 this->settings.Fsk.CrcOn = crcOn;
dudmuck 0:8f0d0ae0a077 243 this->settings.Fsk.IqInverted = iqInverted;
dudmuck 0:8f0d0ae0a077 244 this->settings.Fsk.RxContinuous = rxContinuous;
dudmuck 0:8f0d0ae0a077 245 this->settings.Fsk.PreambleLen = preambleLen;
dudmuck 0:8f0d0ae0a077 246 this->settings.Fsk.RxSingleTimeout = symbTimeout * ( ( 1.0 / ( double )datarate ) * 8.0 ) * 1e3;
dudmuck 0:8f0d0ae0a077 247
dudmuck 0:8f0d0ae0a077 248 datarate = ( uint16_t )( ( double )XTAL_FREQ / ( double )datarate );
dudmuck 0:8f0d0ae0a077 249 Write( REG_BITRATEMSB, ( uint8_t )( datarate >> 8 ) );
dudmuck 0:8f0d0ae0a077 250 Write( REG_BITRATELSB, ( uint8_t )( datarate & 0xFF ) );
dudmuck 0:8f0d0ae0a077 251
dudmuck 0:8f0d0ae0a077 252 Write( REG_RXBW, GetFskBandwidthRegValue( bandwidth ) );
dudmuck 0:8f0d0ae0a077 253 Write( REG_AFCBW, GetFskBandwidthRegValue( bandwidthAfc ) );
dudmuck 0:8f0d0ae0a077 254
dudmuck 0:8f0d0ae0a077 255 Write( REG_PREAMBLEMSB, ( uint8_t )( ( preambleLen >> 8 ) & 0xFF ) );
dudmuck 0:8f0d0ae0a077 256 Write( REG_PREAMBLELSB, ( uint8_t )( preambleLen & 0xFF ) );
dudmuck 0:8f0d0ae0a077 257
dudmuck 0:8f0d0ae0a077 258 if( fixLen == 1 )
dudmuck 0:8f0d0ae0a077 259 {
dudmuck 0:8f0d0ae0a077 260 Write( REG_PAYLOADLENGTH, payloadLen );
dudmuck 0:8f0d0ae0a077 261 }
dudmuck 0:8f0d0ae0a077 262 else
dudmuck 0:8f0d0ae0a077 263 {
dudmuck 0:8f0d0ae0a077 264 Write( REG_PAYLOADLENGTH, 0xFF ); // Set payload length to the maximum
dudmuck 0:8f0d0ae0a077 265 }
dudmuck 0:8f0d0ae0a077 266
dudmuck 0:8f0d0ae0a077 267 Write( REG_PACKETCONFIG1,
dudmuck 0:8f0d0ae0a077 268 ( Read( REG_PACKETCONFIG1 ) &
dudmuck 0:8f0d0ae0a077 269 RF_PACKETCONFIG1_CRC_MASK &
dudmuck 0:8f0d0ae0a077 270 RF_PACKETCONFIG1_PACKETFORMAT_MASK ) |
dudmuck 0:8f0d0ae0a077 271 ( ( fixLen == 1 ) ? RF_PACKETCONFIG1_PACKETFORMAT_FIXED : RF_PACKETCONFIG1_PACKETFORMAT_VARIABLE ) |
dudmuck 0:8f0d0ae0a077 272 ( crcOn << 4 ) );
dudmuck 0:8f0d0ae0a077 273 Write( REG_PACKETCONFIG2, ( Read( REG_PACKETCONFIG2 ) | RF_PACKETCONFIG2_DATAMODE_PACKET ) );
dudmuck 0:8f0d0ae0a077 274 }
dudmuck 0:8f0d0ae0a077 275 break;
dudmuck 0:8f0d0ae0a077 276 case MODEM_LORA:
dudmuck 0:8f0d0ae0a077 277 {
dudmuck 0:8f0d0ae0a077 278 if( bandwidth > 2 )
dudmuck 0:8f0d0ae0a077 279 {
dudmuck 0:8f0d0ae0a077 280 // Fatal error: When using LoRa modem only bandwidths 125, 250 and 500 kHz are supported
dudmuck 0:8f0d0ae0a077 281 while( 1 );
dudmuck 0:8f0d0ae0a077 282 }
dudmuck 0:8f0d0ae0a077 283 bandwidth += 7;
dudmuck 0:8f0d0ae0a077 284 this->settings.LoRa.Bandwidth = bandwidth;
dudmuck 0:8f0d0ae0a077 285 this->settings.LoRa.Datarate = datarate;
dudmuck 0:8f0d0ae0a077 286 this->settings.LoRa.Coderate = coderate;
dudmuck 0:8f0d0ae0a077 287 this->settings.LoRa.PreambleLen = preambleLen;
dudmuck 0:8f0d0ae0a077 288 this->settings.LoRa.FixLen = fixLen;
dudmuck 0:8f0d0ae0a077 289 this->settings.LoRa.PayloadLen = payloadLen;
dudmuck 0:8f0d0ae0a077 290 this->settings.LoRa.CrcOn = crcOn;
dudmuck 0:8f0d0ae0a077 291 this->settings.LoRa.FreqHopOn = freqHopOn;
dudmuck 0:8f0d0ae0a077 292 this->settings.LoRa.HopPeriod = hopPeriod;
dudmuck 0:8f0d0ae0a077 293 this->settings.LoRa.IqInverted = iqInverted;
dudmuck 0:8f0d0ae0a077 294 this->settings.LoRa.RxContinuous = rxContinuous;
dudmuck 0:8f0d0ae0a077 295
dudmuck 0:8f0d0ae0a077 296 if( datarate > 12 )
dudmuck 0:8f0d0ae0a077 297 {
dudmuck 0:8f0d0ae0a077 298 datarate = 12;
dudmuck 0:8f0d0ae0a077 299 }
dudmuck 0:8f0d0ae0a077 300 else if( datarate < 6 )
dudmuck 0:8f0d0ae0a077 301 {
dudmuck 0:8f0d0ae0a077 302 datarate = 6;
dudmuck 0:8f0d0ae0a077 303 }
dudmuck 0:8f0d0ae0a077 304
dudmuck 0:8f0d0ae0a077 305 if( ( ( bandwidth == 7 ) && ( ( datarate == 11 ) || ( datarate == 12 ) ) ) ||
dudmuck 0:8f0d0ae0a077 306 ( ( bandwidth == 8 ) && ( datarate == 12 ) ) )
dudmuck 0:8f0d0ae0a077 307 {
dudmuck 0:8f0d0ae0a077 308 this->settings.LoRa.LowDatarateOptimize = 0x01;
dudmuck 0:8f0d0ae0a077 309 }
dudmuck 0:8f0d0ae0a077 310 else
dudmuck 0:8f0d0ae0a077 311 {
dudmuck 0:8f0d0ae0a077 312 this->settings.LoRa.LowDatarateOptimize = 0x00;
dudmuck 0:8f0d0ae0a077 313 }
dudmuck 0:8f0d0ae0a077 314
dudmuck 0:8f0d0ae0a077 315 Write( REG_LR_MODEMCONFIG1,
dudmuck 0:8f0d0ae0a077 316 ( Read( REG_LR_MODEMCONFIG1 ) &
dudmuck 0:8f0d0ae0a077 317 RFLR_MODEMCONFIG1_BW_MASK &
dudmuck 0:8f0d0ae0a077 318 RFLR_MODEMCONFIG1_CODINGRATE_MASK &
dudmuck 0:8f0d0ae0a077 319 RFLR_MODEMCONFIG1_IMPLICITHEADER_MASK ) |
dudmuck 0:8f0d0ae0a077 320 ( bandwidth << 4 ) | ( coderate << 1 ) |
dudmuck 0:8f0d0ae0a077 321 fixLen );
dudmuck 0:8f0d0ae0a077 322
dudmuck 0:8f0d0ae0a077 323 Write( REG_LR_MODEMCONFIG2,
dudmuck 0:8f0d0ae0a077 324 ( Read( REG_LR_MODEMCONFIG2 ) &
dudmuck 0:8f0d0ae0a077 325 RFLR_MODEMCONFIG2_SF_MASK &
dudmuck 0:8f0d0ae0a077 326 RFLR_MODEMCONFIG2_RXPAYLOADCRC_MASK &
dudmuck 0:8f0d0ae0a077 327 RFLR_MODEMCONFIG2_SYMBTIMEOUTMSB_MASK ) |
dudmuck 0:8f0d0ae0a077 328 ( datarate << 4 ) | ( crcOn << 2 ) |
dudmuck 0:8f0d0ae0a077 329 ( ( symbTimeout >> 8 ) & ~RFLR_MODEMCONFIG2_SYMBTIMEOUTMSB_MASK ) );
dudmuck 0:8f0d0ae0a077 330
dudmuck 0:8f0d0ae0a077 331 Write( REG_LR_MODEMCONFIG3,
dudmuck 0:8f0d0ae0a077 332 ( Read( REG_LR_MODEMCONFIG3 ) &
dudmuck 0:8f0d0ae0a077 333 RFLR_MODEMCONFIG3_LOWDATARATEOPTIMIZE_MASK ) |
dudmuck 0:8f0d0ae0a077 334 ( this->settings.LoRa.LowDatarateOptimize << 3 ) );
dudmuck 0:8f0d0ae0a077 335
dudmuck 0:8f0d0ae0a077 336 Write( REG_LR_SYMBTIMEOUTLSB, ( uint8_t )( symbTimeout & 0xFF ) );
dudmuck 0:8f0d0ae0a077 337
dudmuck 0:8f0d0ae0a077 338 Write( REG_LR_PREAMBLEMSB, ( uint8_t )( ( preambleLen >> 8 ) & 0xFF ) );
dudmuck 0:8f0d0ae0a077 339 Write( REG_LR_PREAMBLELSB, ( uint8_t )( preambleLen & 0xFF ) );
dudmuck 0:8f0d0ae0a077 340
dudmuck 0:8f0d0ae0a077 341 if( fixLen == 1 )
dudmuck 0:8f0d0ae0a077 342 {
dudmuck 0:8f0d0ae0a077 343 Write( REG_LR_PAYLOADLENGTH, payloadLen );
dudmuck 0:8f0d0ae0a077 344 }
dudmuck 0:8f0d0ae0a077 345
dudmuck 0:8f0d0ae0a077 346 if( this->settings.LoRa.FreqHopOn == true )
dudmuck 0:8f0d0ae0a077 347 {
dudmuck 0:8f0d0ae0a077 348 Write( REG_LR_PLLHOP, ( Read( REG_LR_PLLHOP ) & RFLR_PLLHOP_FASTHOP_MASK ) | RFLR_PLLHOP_FASTHOP_ON );
dudmuck 0:8f0d0ae0a077 349 Write( REG_LR_HOPPERIOD, this->settings.LoRa.HopPeriod );
dudmuck 0:8f0d0ae0a077 350 }
dudmuck 0:8f0d0ae0a077 351
dudmuck 0:8f0d0ae0a077 352 if( ( bandwidth == 9 ) && ( this->settings.Channel > RF_MID_BAND_THRESH ) )
dudmuck 0:8f0d0ae0a077 353 {
dudmuck 0:8f0d0ae0a077 354 // ERRATA 2.1 - Sensitivity Optimization with a 500 kHz Bandwidth
dudmuck 0:8f0d0ae0a077 355 Write( REG_LR_TEST36, 0x02 );
dudmuck 0:8f0d0ae0a077 356 Write( REG_LR_TEST3A, 0x64 );
dudmuck 0:8f0d0ae0a077 357 }
dudmuck 0:8f0d0ae0a077 358 else if( bandwidth == 9 )
dudmuck 0:8f0d0ae0a077 359 {
dudmuck 0:8f0d0ae0a077 360 // ERRATA 2.1 - Sensitivity Optimization with a 500 kHz Bandwidth
dudmuck 0:8f0d0ae0a077 361 Write( REG_LR_TEST36, 0x02 );
dudmuck 0:8f0d0ae0a077 362 Write( REG_LR_TEST3A, 0x7F );
dudmuck 0:8f0d0ae0a077 363 }
dudmuck 0:8f0d0ae0a077 364 else
dudmuck 0:8f0d0ae0a077 365 {
dudmuck 0:8f0d0ae0a077 366 // ERRATA 2.1 - Sensitivity Optimization with a 500 kHz Bandwidth
dudmuck 0:8f0d0ae0a077 367 Write( REG_LR_TEST36, 0x03 );
dudmuck 0:8f0d0ae0a077 368 }
dudmuck 0:8f0d0ae0a077 369
dudmuck 0:8f0d0ae0a077 370 if( datarate == 6 )
dudmuck 0:8f0d0ae0a077 371 {
dudmuck 0:8f0d0ae0a077 372 Write( REG_LR_DETECTOPTIMIZE,
dudmuck 0:8f0d0ae0a077 373 ( Read( REG_LR_DETECTOPTIMIZE ) &
dudmuck 0:8f0d0ae0a077 374 RFLR_DETECTIONOPTIMIZE_MASK ) |
dudmuck 0:8f0d0ae0a077 375 RFLR_DETECTIONOPTIMIZE_SF6 );
dudmuck 0:8f0d0ae0a077 376 Write( REG_LR_DETECTIONTHRESHOLD,
dudmuck 0:8f0d0ae0a077 377 RFLR_DETECTIONTHRESH_SF6 );
dudmuck 0:8f0d0ae0a077 378 }
dudmuck 0:8f0d0ae0a077 379 else
dudmuck 0:8f0d0ae0a077 380 {
dudmuck 0:8f0d0ae0a077 381 Write( REG_LR_DETECTOPTIMIZE,
dudmuck 0:8f0d0ae0a077 382 ( Read( REG_LR_DETECTOPTIMIZE ) &
dudmuck 0:8f0d0ae0a077 383 RFLR_DETECTIONOPTIMIZE_MASK ) |
dudmuck 0:8f0d0ae0a077 384 RFLR_DETECTIONOPTIMIZE_SF7_TO_SF12 );
dudmuck 0:8f0d0ae0a077 385 Write( REG_LR_DETECTIONTHRESHOLD,
dudmuck 0:8f0d0ae0a077 386 RFLR_DETECTIONTHRESH_SF7_TO_SF12 );
dudmuck 0:8f0d0ae0a077 387 }
dudmuck 0:8f0d0ae0a077 388 }
dudmuck 0:8f0d0ae0a077 389 break;
dudmuck 0:8f0d0ae0a077 390 }
dudmuck 0:8f0d0ae0a077 391 }
dudmuck 0:8f0d0ae0a077 392
dudmuck 0:8f0d0ae0a077 393 void SX1276::SetTxConfig( RadioModems_t modem, int8_t power, uint32_t fdev,
dudmuck 0:8f0d0ae0a077 394 uint32_t bandwidth, uint32_t datarate,
dudmuck 0:8f0d0ae0a077 395 uint8_t coderate, uint16_t preambleLen,
dudmuck 0:8f0d0ae0a077 396 bool fixLen, bool crcOn, bool freqHopOn,
dudmuck 0:8f0d0ae0a077 397 uint8_t hopPeriod, bool iqInverted, uint32_t timeout )
dudmuck 0:8f0d0ae0a077 398 {
dudmuck 0:8f0d0ae0a077 399 SetModem( modem );
dudmuck 0:8f0d0ae0a077 400
dudmuck 0:8f0d0ae0a077 401 SetRfTxPower( power );
dudmuck 0:8f0d0ae0a077 402
dudmuck 0:8f0d0ae0a077 403 switch( modem )
dudmuck 0:8f0d0ae0a077 404 {
dudmuck 0:8f0d0ae0a077 405 case MODEM_FSK:
dudmuck 0:8f0d0ae0a077 406 {
dudmuck 0:8f0d0ae0a077 407 this->settings.Fsk.Power = power;
dudmuck 0:8f0d0ae0a077 408 this->settings.Fsk.Fdev = fdev;
dudmuck 0:8f0d0ae0a077 409 this->settings.Fsk.Bandwidth = bandwidth;
dudmuck 0:8f0d0ae0a077 410 this->settings.Fsk.Datarate = datarate;
dudmuck 0:8f0d0ae0a077 411 this->settings.Fsk.PreambleLen = preambleLen;
dudmuck 0:8f0d0ae0a077 412 this->settings.Fsk.FixLen = fixLen;
dudmuck 0:8f0d0ae0a077 413 this->settings.Fsk.CrcOn = crcOn;
dudmuck 0:8f0d0ae0a077 414 this->settings.Fsk.IqInverted = iqInverted;
dudmuck 0:8f0d0ae0a077 415 this->settings.Fsk.TxTimeout = timeout;
dudmuck 0:8f0d0ae0a077 416
dudmuck 0:8f0d0ae0a077 417 fdev = ( uint16_t )( ( double )fdev / ( double )FREQ_STEP );
dudmuck 0:8f0d0ae0a077 418 Write( REG_FDEVMSB, ( uint8_t )( fdev >> 8 ) );
dudmuck 0:8f0d0ae0a077 419 Write( REG_FDEVLSB, ( uint8_t )( fdev & 0xFF ) );
dudmuck 0:8f0d0ae0a077 420
dudmuck 0:8f0d0ae0a077 421 datarate = ( uint16_t )( ( double )XTAL_FREQ / ( double )datarate );
dudmuck 0:8f0d0ae0a077 422 Write( REG_BITRATEMSB, ( uint8_t )( datarate >> 8 ) );
dudmuck 0:8f0d0ae0a077 423 Write( REG_BITRATELSB, ( uint8_t )( datarate & 0xFF ) );
dudmuck 0:8f0d0ae0a077 424
dudmuck 0:8f0d0ae0a077 425 Write( REG_PREAMBLEMSB, ( preambleLen >> 8 ) & 0x00FF );
dudmuck 0:8f0d0ae0a077 426 Write( REG_PREAMBLELSB, preambleLen & 0xFF );
dudmuck 0:8f0d0ae0a077 427
dudmuck 0:8f0d0ae0a077 428 Write( REG_PACKETCONFIG1,
dudmuck 0:8f0d0ae0a077 429 ( Read( REG_PACKETCONFIG1 ) &
dudmuck 0:8f0d0ae0a077 430 RF_PACKETCONFIG1_CRC_MASK &
dudmuck 0:8f0d0ae0a077 431 RF_PACKETCONFIG1_PACKETFORMAT_MASK ) |
dudmuck 0:8f0d0ae0a077 432 ( ( fixLen == 1 ) ? RF_PACKETCONFIG1_PACKETFORMAT_FIXED : RF_PACKETCONFIG1_PACKETFORMAT_VARIABLE ) |
dudmuck 0:8f0d0ae0a077 433 ( crcOn << 4 ) );
dudmuck 0:8f0d0ae0a077 434 Write( REG_PACKETCONFIG2, ( Read( REG_PACKETCONFIG2 ) | RF_PACKETCONFIG2_DATAMODE_PACKET ) );
dudmuck 0:8f0d0ae0a077 435 }
dudmuck 0:8f0d0ae0a077 436 break;
dudmuck 0:8f0d0ae0a077 437 case MODEM_LORA:
dudmuck 0:8f0d0ae0a077 438 {
dudmuck 0:8f0d0ae0a077 439 this->settings.LoRa.Power = power;
dudmuck 0:8f0d0ae0a077 440 if( bandwidth > 2 )
dudmuck 0:8f0d0ae0a077 441 {
dudmuck 0:8f0d0ae0a077 442 // Fatal error: When using LoRa modem only bandwidths 125, 250 and 500 kHz are supported
dudmuck 0:8f0d0ae0a077 443 while( 1 );
dudmuck 0:8f0d0ae0a077 444 }
dudmuck 0:8f0d0ae0a077 445 bandwidth += 7;
dudmuck 0:8f0d0ae0a077 446 this->settings.LoRa.Bandwidth = bandwidth;
dudmuck 0:8f0d0ae0a077 447 this->settings.LoRa.Datarate = datarate;
dudmuck 0:8f0d0ae0a077 448 this->settings.LoRa.Coderate = coderate;
dudmuck 0:8f0d0ae0a077 449 this->settings.LoRa.PreambleLen = preambleLen;
dudmuck 0:8f0d0ae0a077 450 this->settings.LoRa.FixLen = fixLen;
dudmuck 0:8f0d0ae0a077 451 this->settings.LoRa.FreqHopOn = freqHopOn;
dudmuck 0:8f0d0ae0a077 452 this->settings.LoRa.HopPeriod = hopPeriod;
dudmuck 0:8f0d0ae0a077 453 this->settings.LoRa.CrcOn = crcOn;
dudmuck 0:8f0d0ae0a077 454 this->settings.LoRa.IqInverted = iqInverted;
dudmuck 0:8f0d0ae0a077 455 this->settings.LoRa.TxTimeout = timeout;
dudmuck 0:8f0d0ae0a077 456
dudmuck 0:8f0d0ae0a077 457 if( datarate > 12 )
dudmuck 0:8f0d0ae0a077 458 {
dudmuck 0:8f0d0ae0a077 459 datarate = 12;
dudmuck 0:8f0d0ae0a077 460 }
dudmuck 0:8f0d0ae0a077 461 else if( datarate < 6 )
dudmuck 0:8f0d0ae0a077 462 {
dudmuck 0:8f0d0ae0a077 463 datarate = 6;
dudmuck 0:8f0d0ae0a077 464 }
dudmuck 0:8f0d0ae0a077 465 if( ( ( bandwidth == 7 ) && ( ( datarate == 11 ) || ( datarate == 12 ) ) ) ||
dudmuck 0:8f0d0ae0a077 466 ( ( bandwidth == 8 ) && ( datarate == 12 ) ) )
dudmuck 0:8f0d0ae0a077 467 {
dudmuck 0:8f0d0ae0a077 468 this->settings.LoRa.LowDatarateOptimize = 0x01;
dudmuck 0:8f0d0ae0a077 469 }
dudmuck 0:8f0d0ae0a077 470 else
dudmuck 0:8f0d0ae0a077 471 {
dudmuck 0:8f0d0ae0a077 472 this->settings.LoRa.LowDatarateOptimize = 0x00;
dudmuck 0:8f0d0ae0a077 473 }
dudmuck 0:8f0d0ae0a077 474
dudmuck 0:8f0d0ae0a077 475 if( this->settings.LoRa.FreqHopOn == true )
dudmuck 0:8f0d0ae0a077 476 {
dudmuck 0:8f0d0ae0a077 477 Write( REG_LR_PLLHOP, ( Read( REG_LR_PLLHOP ) & RFLR_PLLHOP_FASTHOP_MASK ) | RFLR_PLLHOP_FASTHOP_ON );
dudmuck 0:8f0d0ae0a077 478 Write( REG_LR_HOPPERIOD, this->settings.LoRa.HopPeriod );
dudmuck 0:8f0d0ae0a077 479 }
dudmuck 0:8f0d0ae0a077 480
dudmuck 0:8f0d0ae0a077 481 Write( REG_LR_MODEMCONFIG1,
dudmuck 0:8f0d0ae0a077 482 ( Read( REG_LR_MODEMCONFIG1 ) &
dudmuck 0:8f0d0ae0a077 483 RFLR_MODEMCONFIG1_BW_MASK &
dudmuck 0:8f0d0ae0a077 484 RFLR_MODEMCONFIG1_CODINGRATE_MASK &
dudmuck 0:8f0d0ae0a077 485 RFLR_MODEMCONFIG1_IMPLICITHEADER_MASK ) |
dudmuck 0:8f0d0ae0a077 486 ( bandwidth << 4 ) | ( coderate << 1 ) |
dudmuck 0:8f0d0ae0a077 487 fixLen );
dudmuck 0:8f0d0ae0a077 488
dudmuck 0:8f0d0ae0a077 489 Write( REG_LR_MODEMCONFIG2,
dudmuck 0:8f0d0ae0a077 490 ( Read( REG_LR_MODEMCONFIG2 ) &
dudmuck 0:8f0d0ae0a077 491 RFLR_MODEMCONFIG2_SF_MASK &
dudmuck 0:8f0d0ae0a077 492 RFLR_MODEMCONFIG2_RXPAYLOADCRC_MASK ) |
dudmuck 0:8f0d0ae0a077 493 ( datarate << 4 ) | ( crcOn << 2 ) );
dudmuck 0:8f0d0ae0a077 494
dudmuck 0:8f0d0ae0a077 495 Write( REG_LR_MODEMCONFIG3,
dudmuck 0:8f0d0ae0a077 496 ( Read( REG_LR_MODEMCONFIG3 ) &
dudmuck 0:8f0d0ae0a077 497 RFLR_MODEMCONFIG3_LOWDATARATEOPTIMIZE_MASK ) |
dudmuck 0:8f0d0ae0a077 498 ( this->settings.LoRa.LowDatarateOptimize << 3 ) );
dudmuck 0:8f0d0ae0a077 499
dudmuck 0:8f0d0ae0a077 500 Write( REG_LR_PREAMBLEMSB, ( preambleLen >> 8 ) & 0x00FF );
dudmuck 0:8f0d0ae0a077 501 Write( REG_LR_PREAMBLELSB, preambleLen & 0xFF );
dudmuck 0:8f0d0ae0a077 502
dudmuck 0:8f0d0ae0a077 503 if( datarate == 6 )
dudmuck 0:8f0d0ae0a077 504 {
dudmuck 0:8f0d0ae0a077 505 Write( REG_LR_DETECTOPTIMIZE,
dudmuck 0:8f0d0ae0a077 506 ( Read( REG_LR_DETECTOPTIMIZE ) &
dudmuck 0:8f0d0ae0a077 507 RFLR_DETECTIONOPTIMIZE_MASK ) |
dudmuck 0:8f0d0ae0a077 508 RFLR_DETECTIONOPTIMIZE_SF6 );
dudmuck 0:8f0d0ae0a077 509 Write( REG_LR_DETECTIONTHRESHOLD,
dudmuck 0:8f0d0ae0a077 510 RFLR_DETECTIONTHRESH_SF6 );
dudmuck 0:8f0d0ae0a077 511 }
dudmuck 0:8f0d0ae0a077 512 else
dudmuck 0:8f0d0ae0a077 513 {
dudmuck 0:8f0d0ae0a077 514 Write( REG_LR_DETECTOPTIMIZE,
dudmuck 0:8f0d0ae0a077 515 ( Read( REG_LR_DETECTOPTIMIZE ) &
dudmuck 0:8f0d0ae0a077 516 RFLR_DETECTIONOPTIMIZE_MASK ) |
dudmuck 0:8f0d0ae0a077 517 RFLR_DETECTIONOPTIMIZE_SF7_TO_SF12 );
dudmuck 0:8f0d0ae0a077 518 Write( REG_LR_DETECTIONTHRESHOLD,
dudmuck 0:8f0d0ae0a077 519 RFLR_DETECTIONTHRESH_SF7_TO_SF12 );
dudmuck 0:8f0d0ae0a077 520 }
dudmuck 0:8f0d0ae0a077 521 }
dudmuck 0:8f0d0ae0a077 522 break;
dudmuck 0:8f0d0ae0a077 523 }
dudmuck 0:8f0d0ae0a077 524 }
dudmuck 0:8f0d0ae0a077 525
dudmuck 0:8f0d0ae0a077 526 uint32_t SX1276::TimeOnAir( RadioModems_t modem, uint8_t pktLen )
dudmuck 0:8f0d0ae0a077 527 {
dudmuck 0:8f0d0ae0a077 528 uint32_t airTime = 0;
dudmuck 0:8f0d0ae0a077 529
dudmuck 0:8f0d0ae0a077 530 switch( modem )
dudmuck 0:8f0d0ae0a077 531 {
dudmuck 0:8f0d0ae0a077 532 case MODEM_FSK:
dudmuck 0:8f0d0ae0a077 533 {
dudmuck 0:8f0d0ae0a077 534 airTime = rint( ( 8 * ( this->settings.Fsk.PreambleLen +
dudmuck 0:8f0d0ae0a077 535 ( ( Read( REG_SYNCCONFIG ) & ~RF_SYNCCONFIG_SYNCSIZE_MASK ) + 1 ) +
dudmuck 0:8f0d0ae0a077 536 ( ( this->settings.Fsk.FixLen == 0x01 ) ? 0.0 : 1.0 ) +
dudmuck 0:8f0d0ae0a077 537 ( ( ( Read( REG_PACKETCONFIG1 ) & ~RF_PACKETCONFIG1_ADDRSFILTERING_MASK ) != 0x00 ) ? 1.0 : 0 ) +
dudmuck 0:8f0d0ae0a077 538 pktLen +
dudmuck 0:8f0d0ae0a077 539 ( ( this->settings.Fsk.CrcOn == 0x01 ) ? 2.0 : 0 ) ) /
dudmuck 0:8f0d0ae0a077 540 this->settings.Fsk.Datarate ) * 1e3 );
dudmuck 0:8f0d0ae0a077 541 }
dudmuck 0:8f0d0ae0a077 542 break;
dudmuck 0:8f0d0ae0a077 543 case MODEM_LORA:
dudmuck 0:8f0d0ae0a077 544 {
dudmuck 0:8f0d0ae0a077 545 double bw = 0.0;
dudmuck 0:8f0d0ae0a077 546 // REMARK: When using LoRa modem only bandwidths 125, 250 and 500 kHz are supported
dudmuck 0:8f0d0ae0a077 547 switch( this->settings.LoRa.Bandwidth )
dudmuck 0:8f0d0ae0a077 548 {
dudmuck 0:8f0d0ae0a077 549 //case 0: // 7.8 kHz
dudmuck 0:8f0d0ae0a077 550 // bw = 78e2;
dudmuck 0:8f0d0ae0a077 551 // break;
dudmuck 0:8f0d0ae0a077 552 //case 1: // 10.4 kHz
dudmuck 0:8f0d0ae0a077 553 // bw = 104e2;
dudmuck 0:8f0d0ae0a077 554 // break;
dudmuck 0:8f0d0ae0a077 555 //case 2: // 15.6 kHz
dudmuck 0:8f0d0ae0a077 556 // bw = 156e2;
dudmuck 0:8f0d0ae0a077 557 // break;
dudmuck 0:8f0d0ae0a077 558 //case 3: // 20.8 kHz
dudmuck 0:8f0d0ae0a077 559 // bw = 208e2;
dudmuck 0:8f0d0ae0a077 560 // break;
dudmuck 0:8f0d0ae0a077 561 //case 4: // 31.2 kHz
dudmuck 0:8f0d0ae0a077 562 // bw = 312e2;
dudmuck 0:8f0d0ae0a077 563 // break;
dudmuck 0:8f0d0ae0a077 564 //case 5: // 41.4 kHz
dudmuck 0:8f0d0ae0a077 565 // bw = 414e2;
dudmuck 0:8f0d0ae0a077 566 // break;
dudmuck 0:8f0d0ae0a077 567 //case 6: // 62.5 kHz
dudmuck 0:8f0d0ae0a077 568 // bw = 625e2;
dudmuck 0:8f0d0ae0a077 569 // break;
dudmuck 0:8f0d0ae0a077 570 case 7: // 125 kHz
dudmuck 0:8f0d0ae0a077 571 bw = 125e3;
dudmuck 0:8f0d0ae0a077 572 break;
dudmuck 0:8f0d0ae0a077 573 case 8: // 250 kHz
dudmuck 0:8f0d0ae0a077 574 bw = 250e3;
dudmuck 0:8f0d0ae0a077 575 break;
dudmuck 0:8f0d0ae0a077 576 case 9: // 500 kHz
dudmuck 0:8f0d0ae0a077 577 bw = 500e3;
dudmuck 0:8f0d0ae0a077 578 break;
dudmuck 0:8f0d0ae0a077 579 }
dudmuck 0:8f0d0ae0a077 580
dudmuck 0:8f0d0ae0a077 581 // Symbol rate : time for one symbol (secs)
dudmuck 0:8f0d0ae0a077 582 double rs = bw / ( 1 << this->settings.LoRa.Datarate );
dudmuck 0:8f0d0ae0a077 583 double ts = 1 / rs;
dudmuck 0:8f0d0ae0a077 584 // time of preamble
dudmuck 0:8f0d0ae0a077 585 double tPreamble = ( this->settings.LoRa.PreambleLen + 4.25 ) * ts;
dudmuck 0:8f0d0ae0a077 586 // Symbol length of payload and time
dudmuck 0:8f0d0ae0a077 587 double tmp = ceil( ( 8 * pktLen - 4 * this->settings.LoRa.Datarate +
dudmuck 0:8f0d0ae0a077 588 28 + 16 * this->settings.LoRa.CrcOn -
dudmuck 0:8f0d0ae0a077 589 ( this->settings.LoRa.FixLen ? 20 : 0 ) ) /
dudmuck 0:8f0d0ae0a077 590 ( double )( 4 * ( this->settings.LoRa.Datarate -
dudmuck 0:8f0d0ae0a077 591 ( ( this->settings.LoRa.LowDatarateOptimize > 0 ) ? 2 : 0 ) ) ) ) *
dudmuck 0:8f0d0ae0a077 592 ( this->settings.LoRa.Coderate + 4 );
dudmuck 0:8f0d0ae0a077 593 double nPayload = 8 + ( ( tmp > 0 ) ? tmp : 0 );
dudmuck 0:8f0d0ae0a077 594 double tPayload = nPayload * ts;
dudmuck 0:8f0d0ae0a077 595 // Time on air
dudmuck 0:8f0d0ae0a077 596 double tOnAir = tPreamble + tPayload;
dudmuck 0:8f0d0ae0a077 597 // return ms secs
dudmuck 0:8f0d0ae0a077 598 airTime = floor( tOnAir * 1e3 + 0.999 );
dudmuck 0:8f0d0ae0a077 599 }
dudmuck 0:8f0d0ae0a077 600 break;
dudmuck 0:8f0d0ae0a077 601 }
dudmuck 0:8f0d0ae0a077 602 return airTime;
dudmuck 0:8f0d0ae0a077 603 }
dudmuck 0:8f0d0ae0a077 604
dudmuck 0:8f0d0ae0a077 605 void SX1276::Send( uint8_t *buffer, uint8_t size )
dudmuck 0:8f0d0ae0a077 606 {
dudmuck 0:8f0d0ae0a077 607 uint32_t txTimeout = 0;
dudmuck 0:8f0d0ae0a077 608
dudmuck 0:8f0d0ae0a077 609 switch( this->settings.Modem )
dudmuck 0:8f0d0ae0a077 610 {
dudmuck 0:8f0d0ae0a077 611 case MODEM_FSK:
dudmuck 0:8f0d0ae0a077 612 {
dudmuck 0:8f0d0ae0a077 613 this->settings.FskPacketHandler.NbBytes = 0;
dudmuck 0:8f0d0ae0a077 614 this->settings.FskPacketHandler.Size = size;
dudmuck 0:8f0d0ae0a077 615
dudmuck 0:8f0d0ae0a077 616 if( this->settings.Fsk.FixLen == false )
dudmuck 0:8f0d0ae0a077 617 {
dudmuck 0:8f0d0ae0a077 618 WriteFifo( ( uint8_t* )&size, 1 );
dudmuck 0:8f0d0ae0a077 619 }
dudmuck 0:8f0d0ae0a077 620 else
dudmuck 0:8f0d0ae0a077 621 {
dudmuck 0:8f0d0ae0a077 622 Write( REG_PAYLOADLENGTH, size );
dudmuck 0:8f0d0ae0a077 623 }
dudmuck 0:8f0d0ae0a077 624
dudmuck 0:8f0d0ae0a077 625 if( ( size > 0 ) && ( size <= 64 ) )
dudmuck 0:8f0d0ae0a077 626 {
dudmuck 0:8f0d0ae0a077 627 this->settings.FskPacketHandler.ChunkSize = size;
dudmuck 0:8f0d0ae0a077 628 }
dudmuck 0:8f0d0ae0a077 629 else
dudmuck 0:8f0d0ae0a077 630 {
dudmuck 0:8f0d0ae0a077 631 memcpy( rxtxBuffer, buffer, size );
dudmuck 0:8f0d0ae0a077 632 this->settings.FskPacketHandler.ChunkSize = 32;
dudmuck 0:8f0d0ae0a077 633 }
dudmuck 0:8f0d0ae0a077 634
dudmuck 0:8f0d0ae0a077 635 // Write payload buffer
dudmuck 0:8f0d0ae0a077 636 WriteFifo( buffer, this->settings.FskPacketHandler.ChunkSize );
dudmuck 0:8f0d0ae0a077 637 this->settings.FskPacketHandler.NbBytes += this->settings.FskPacketHandler.ChunkSize;
dudmuck 0:8f0d0ae0a077 638 txTimeout = this->settings.Fsk.TxTimeout;
dudmuck 0:8f0d0ae0a077 639 }
dudmuck 0:8f0d0ae0a077 640 break;
dudmuck 0:8f0d0ae0a077 641 case MODEM_LORA:
dudmuck 0:8f0d0ae0a077 642 {
dudmuck 0:8f0d0ae0a077 643 if( this->settings.LoRa.IqInverted == true )
dudmuck 0:8f0d0ae0a077 644 {
dudmuck 0:8f0d0ae0a077 645 Write( REG_LR_INVERTIQ, ( ( Read( REG_LR_INVERTIQ ) & RFLR_INVERTIQ_TX_MASK & RFLR_INVERTIQ_RX_MASK ) | RFLR_INVERTIQ_RX_OFF | RFLR_INVERTIQ_TX_ON ) );
dudmuck 0:8f0d0ae0a077 646 Write( REG_LR_INVERTIQ2, RFLR_INVERTIQ2_ON );
dudmuck 0:8f0d0ae0a077 647 }
dudmuck 0:8f0d0ae0a077 648 else
dudmuck 0:8f0d0ae0a077 649 {
dudmuck 0:8f0d0ae0a077 650 Write( REG_LR_INVERTIQ, ( ( Read( REG_LR_INVERTIQ ) & RFLR_INVERTIQ_TX_MASK & RFLR_INVERTIQ_RX_MASK ) | RFLR_INVERTIQ_RX_OFF | RFLR_INVERTIQ_TX_OFF ) );
dudmuck 0:8f0d0ae0a077 651 Write( REG_LR_INVERTIQ2, RFLR_INVERTIQ2_OFF );
dudmuck 0:8f0d0ae0a077 652 }
dudmuck 0:8f0d0ae0a077 653
dudmuck 0:8f0d0ae0a077 654 this->settings.LoRaPacketHandler.Size = size;
dudmuck 0:8f0d0ae0a077 655
dudmuck 0:8f0d0ae0a077 656 // Initializes the payload size
dudmuck 0:8f0d0ae0a077 657 Write( REG_LR_PAYLOADLENGTH, size );
dudmuck 0:8f0d0ae0a077 658
dudmuck 0:8f0d0ae0a077 659 // Full buffer used for Tx
dudmuck 0:8f0d0ae0a077 660 Write( REG_LR_FIFOTXBASEADDR, 0 );
dudmuck 0:8f0d0ae0a077 661 Write( REG_LR_FIFOADDRPTR, 0 );
dudmuck 0:8f0d0ae0a077 662
dudmuck 0:8f0d0ae0a077 663 // FIFO operations can not take place in Sleep mode
dudmuck 0:8f0d0ae0a077 664 if( ( Read( REG_OPMODE ) & ~RF_OPMODE_MASK ) == RF_OPMODE_SLEEP )
dudmuck 0:8f0d0ae0a077 665 {
dudmuck 0:8f0d0ae0a077 666 Standby( );
dudmuck 0:8f0d0ae0a077 667 wait_ms( 1 );
dudmuck 0:8f0d0ae0a077 668 }
dudmuck 0:8f0d0ae0a077 669 // Write payload buffer
dudmuck 0:8f0d0ae0a077 670 WriteFifo( buffer, size );
dudmuck 0:8f0d0ae0a077 671 txTimeout = this->settings.LoRa.TxTimeout;
dudmuck 0:8f0d0ae0a077 672 }
dudmuck 0:8f0d0ae0a077 673 break;
dudmuck 0:8f0d0ae0a077 674 }
dudmuck 0:8f0d0ae0a077 675
dudmuck 0:8f0d0ae0a077 676 Tx( txTimeout );
dudmuck 0:8f0d0ae0a077 677 }
dudmuck 0:8f0d0ae0a077 678
dudmuck 0:8f0d0ae0a077 679 void SX1276::Sleep( void )
dudmuck 0:8f0d0ae0a077 680 {
dudmuck 0:8f0d0ae0a077 681 txTimeoutTimer.detach( );
dudmuck 0:8f0d0ae0a077 682 rxTimeoutTimer.detach( );
dudmuck 0:8f0d0ae0a077 683
dudmuck 0:8f0d0ae0a077 684 SetOpMode( RF_OPMODE_SLEEP );
dudmuck 0:8f0d0ae0a077 685 this->settings.State = RF_IDLE;
dudmuck 0:8f0d0ae0a077 686 }
dudmuck 0:8f0d0ae0a077 687
dudmuck 0:8f0d0ae0a077 688 void SX1276::Standby( void )
dudmuck 0:8f0d0ae0a077 689 {
dudmuck 0:8f0d0ae0a077 690 txTimeoutTimer.detach( );
dudmuck 0:8f0d0ae0a077 691 rxTimeoutTimer.detach( );
dudmuck 0:8f0d0ae0a077 692
dudmuck 0:8f0d0ae0a077 693 SetOpMode( RF_OPMODE_STANDBY );
dudmuck 0:8f0d0ae0a077 694 this->settings.State = RF_IDLE;
dudmuck 0:8f0d0ae0a077 695 }
dudmuck 0:8f0d0ae0a077 696
dudmuck 0:8f0d0ae0a077 697 void SX1276::Rx( uint32_t timeout )
dudmuck 0:8f0d0ae0a077 698 {
dudmuck 0:8f0d0ae0a077 699 bool rxContinuous = false;
dudmuck 0:8f0d0ae0a077 700
dudmuck 0:8f0d0ae0a077 701 switch( this->settings.Modem )
dudmuck 0:8f0d0ae0a077 702 {
dudmuck 0:8f0d0ae0a077 703 case MODEM_FSK:
dudmuck 0:8f0d0ae0a077 704 {
dudmuck 0:8f0d0ae0a077 705 rxContinuous = this->settings.Fsk.RxContinuous;
dudmuck 0:8f0d0ae0a077 706
dudmuck 0:8f0d0ae0a077 707 // DIO0=PayloadReady
dudmuck 0:8f0d0ae0a077 708 // DIO1=FifoLevel
dudmuck 0:8f0d0ae0a077 709 // DIO2=SyncAddr
dudmuck 0:8f0d0ae0a077 710 // DIO3=FifoEmpty
dudmuck 0:8f0d0ae0a077 711 // DIO4=Preamble
dudmuck 0:8f0d0ae0a077 712 // DIO5=ModeReady
dudmuck 0:8f0d0ae0a077 713 Write( REG_DIOMAPPING1, ( Read( REG_DIOMAPPING1 ) & RF_DIOMAPPING1_DIO0_MASK &
dudmuck 0:8f0d0ae0a077 714 RF_DIOMAPPING1_DIO1_MASK &
dudmuck 0:8f0d0ae0a077 715 RF_DIOMAPPING1_DIO2_MASK ) |
dudmuck 0:8f0d0ae0a077 716 RF_DIOMAPPING1_DIO0_00 |
dudmuck 0:8f0d0ae0a077 717 RF_DIOMAPPING1_DIO1_00 |
dudmuck 0:8f0d0ae0a077 718 RF_DIOMAPPING1_DIO2_11 );
dudmuck 0:8f0d0ae0a077 719
dudmuck 0:8f0d0ae0a077 720 Write( REG_DIOMAPPING2, ( Read( REG_DIOMAPPING2 ) & RF_DIOMAPPING2_DIO4_MASK &
dudmuck 0:8f0d0ae0a077 721 RF_DIOMAPPING2_MAP_MASK ) |
dudmuck 0:8f0d0ae0a077 722 RF_DIOMAPPING2_DIO4_11 |
dudmuck 0:8f0d0ae0a077 723 RF_DIOMAPPING2_MAP_PREAMBLEDETECT );
dudmuck 0:8f0d0ae0a077 724
dudmuck 0:8f0d0ae0a077 725 this->settings.FskPacketHandler.FifoThresh = Read( REG_FIFOTHRESH ) & 0x3F;
dudmuck 0:8f0d0ae0a077 726
dudmuck 0:8f0d0ae0a077 727 Write( REG_RXCONFIG, RF_RXCONFIG_AFCAUTO_ON | RF_RXCONFIG_AGCAUTO_ON | RF_RXCONFIG_RXTRIGER_PREAMBLEDETECT );
dudmuck 0:8f0d0ae0a077 728
dudmuck 0:8f0d0ae0a077 729 this->settings.FskPacketHandler.PreambleDetected = false;
dudmuck 0:8f0d0ae0a077 730 this->settings.FskPacketHandler.SyncWordDetected = false;
dudmuck 0:8f0d0ae0a077 731 this->settings.FskPacketHandler.NbBytes = 0;
dudmuck 0:8f0d0ae0a077 732 this->settings.FskPacketHandler.Size = 0;
dudmuck 0:8f0d0ae0a077 733 }
dudmuck 0:8f0d0ae0a077 734 break;
dudmuck 0:8f0d0ae0a077 735 case MODEM_LORA:
dudmuck 0:8f0d0ae0a077 736 {
dudmuck 0:8f0d0ae0a077 737 if( this->settings.LoRa.IqInverted == true )
dudmuck 0:8f0d0ae0a077 738 {
dudmuck 0:8f0d0ae0a077 739 Write( REG_LR_INVERTIQ, ( ( Read( REG_LR_INVERTIQ ) & RFLR_INVERTIQ_TX_MASK & RFLR_INVERTIQ_RX_MASK ) | RFLR_INVERTIQ_RX_ON | RFLR_INVERTIQ_TX_OFF ) );
dudmuck 0:8f0d0ae0a077 740 Write( REG_LR_INVERTIQ2, RFLR_INVERTIQ2_ON );
dudmuck 0:8f0d0ae0a077 741 }
dudmuck 0:8f0d0ae0a077 742 else
dudmuck 0:8f0d0ae0a077 743 {
dudmuck 0:8f0d0ae0a077 744 Write( REG_LR_INVERTIQ, ( ( Read( REG_LR_INVERTIQ ) & RFLR_INVERTIQ_TX_MASK & RFLR_INVERTIQ_RX_MASK ) | RFLR_INVERTIQ_RX_OFF | RFLR_INVERTIQ_TX_OFF ) );
dudmuck 0:8f0d0ae0a077 745 Write( REG_LR_INVERTIQ2, RFLR_INVERTIQ2_OFF );
dudmuck 0:8f0d0ae0a077 746 }
dudmuck 0:8f0d0ae0a077 747
dudmuck 0:8f0d0ae0a077 748 // ERRATA 2.3 - Receiver Spurious Reception of a LoRa Signal
dudmuck 0:8f0d0ae0a077 749 if( this->settings.LoRa.Bandwidth < 9 )
dudmuck 0:8f0d0ae0a077 750 {
dudmuck 0:8f0d0ae0a077 751 Write( REG_LR_DETECTOPTIMIZE, Read( REG_LR_DETECTOPTIMIZE ) & 0x7F );
dudmuck 0:8f0d0ae0a077 752 Write( REG_LR_TEST30, 0x00 );
dudmuck 0:8f0d0ae0a077 753 switch( this->settings.LoRa.Bandwidth )
dudmuck 0:8f0d0ae0a077 754 {
dudmuck 0:8f0d0ae0a077 755 case 0: // 7.8 kHz
dudmuck 0:8f0d0ae0a077 756 Write( REG_LR_TEST2F, 0x48 );
dudmuck 0:8f0d0ae0a077 757 SetChannel(this->settings.Channel + 7.81e3 );
dudmuck 0:8f0d0ae0a077 758 break;
dudmuck 0:8f0d0ae0a077 759 case 1: // 10.4 kHz
dudmuck 0:8f0d0ae0a077 760 Write( REG_LR_TEST2F, 0x44 );
dudmuck 0:8f0d0ae0a077 761 SetChannel(this->settings.Channel + 10.42e3 );
dudmuck 0:8f0d0ae0a077 762 break;
dudmuck 0:8f0d0ae0a077 763 case 2: // 15.6 kHz
dudmuck 0:8f0d0ae0a077 764 Write( REG_LR_TEST2F, 0x44 );
dudmuck 0:8f0d0ae0a077 765 SetChannel(this->settings.Channel + 15.62e3 );
dudmuck 0:8f0d0ae0a077 766 break;
dudmuck 0:8f0d0ae0a077 767 case 3: // 20.8 kHz
dudmuck 0:8f0d0ae0a077 768 Write( REG_LR_TEST2F, 0x44 );
dudmuck 0:8f0d0ae0a077 769 SetChannel(this->settings.Channel + 20.83e3 );
dudmuck 0:8f0d0ae0a077 770 break;
dudmuck 0:8f0d0ae0a077 771 case 4: // 31.2 kHz
dudmuck 0:8f0d0ae0a077 772 Write( REG_LR_TEST2F, 0x44 );
dudmuck 0:8f0d0ae0a077 773 SetChannel(this->settings.Channel + 31.25e3 );
dudmuck 0:8f0d0ae0a077 774 break;
dudmuck 0:8f0d0ae0a077 775 case 5: // 41.4 kHz
dudmuck 0:8f0d0ae0a077 776 Write( REG_LR_TEST2F, 0x44 );
dudmuck 0:8f0d0ae0a077 777 SetChannel(this->settings.Channel + 41.67e3 );
dudmuck 0:8f0d0ae0a077 778 break;
dudmuck 0:8f0d0ae0a077 779 case 6: // 62.5 kHz
dudmuck 0:8f0d0ae0a077 780 Write( REG_LR_TEST2F, 0x40 );
dudmuck 0:8f0d0ae0a077 781 break;
dudmuck 0:8f0d0ae0a077 782 case 7: // 125 kHz
dudmuck 0:8f0d0ae0a077 783 Write( REG_LR_TEST2F, 0x40 );
dudmuck 0:8f0d0ae0a077 784 break;
dudmuck 0:8f0d0ae0a077 785 case 8: // 250 kHz
dudmuck 0:8f0d0ae0a077 786 Write( REG_LR_TEST2F, 0x40 );
dudmuck 0:8f0d0ae0a077 787 break;
dudmuck 0:8f0d0ae0a077 788 }
dudmuck 0:8f0d0ae0a077 789 }
dudmuck 0:8f0d0ae0a077 790 else
dudmuck 0:8f0d0ae0a077 791 {
dudmuck 0:8f0d0ae0a077 792 Write( REG_LR_DETECTOPTIMIZE, Read( REG_LR_DETECTOPTIMIZE ) | 0x80 );
dudmuck 0:8f0d0ae0a077 793 }
dudmuck 0:8f0d0ae0a077 794
dudmuck 0:8f0d0ae0a077 795 rxContinuous = this->settings.LoRa.RxContinuous;
dudmuck 0:8f0d0ae0a077 796
dudmuck 0:8f0d0ae0a077 797 if( this->settings.LoRa.FreqHopOn == true )
dudmuck 0:8f0d0ae0a077 798 {
dudmuck 0:8f0d0ae0a077 799 Write( REG_LR_IRQFLAGSMASK, //RFLR_IRQFLAGS_RXTIMEOUT |
dudmuck 0:8f0d0ae0a077 800 //RFLR_IRQFLAGS_RXDONE |
dudmuck 0:8f0d0ae0a077 801 //RFLR_IRQFLAGS_PAYLOADCRCERROR |
dudmuck 0:8f0d0ae0a077 802 RFLR_IRQFLAGS_VALIDHEADER |
dudmuck 0:8f0d0ae0a077 803 RFLR_IRQFLAGS_TXDONE |
dudmuck 0:8f0d0ae0a077 804 RFLR_IRQFLAGS_CADDONE |
dudmuck 0:8f0d0ae0a077 805 //RFLR_IRQFLAGS_FHSSCHANGEDCHANNEL |
dudmuck 0:8f0d0ae0a077 806 RFLR_IRQFLAGS_CADDETECTED );
dudmuck 0:8f0d0ae0a077 807
dudmuck 0:8f0d0ae0a077 808 // DIO0=RxDone, DIO2=FhssChangeChannel
dudmuck 0:8f0d0ae0a077 809 Write( REG_DIOMAPPING1, ( Read( REG_DIOMAPPING1 ) & RFLR_DIOMAPPING1_DIO0_MASK & RFLR_DIOMAPPING1_DIO2_MASK ) | RFLR_DIOMAPPING1_DIO0_00 | RFLR_DIOMAPPING1_DIO2_00 );
dudmuck 0:8f0d0ae0a077 810 }
dudmuck 0:8f0d0ae0a077 811 else
dudmuck 0:8f0d0ae0a077 812 {
dudmuck 0:8f0d0ae0a077 813 Write( REG_LR_IRQFLAGSMASK, //RFLR_IRQFLAGS_RXTIMEOUT |
dudmuck 0:8f0d0ae0a077 814 //RFLR_IRQFLAGS_RXDONE |
dudmuck 0:8f0d0ae0a077 815 //RFLR_IRQFLAGS_PAYLOADCRCERROR |
dudmuck 0:8f0d0ae0a077 816 RFLR_IRQFLAGS_VALIDHEADER |
dudmuck 0:8f0d0ae0a077 817 RFLR_IRQFLAGS_TXDONE |
dudmuck 0:8f0d0ae0a077 818 RFLR_IRQFLAGS_CADDONE |
dudmuck 0:8f0d0ae0a077 819 RFLR_IRQFLAGS_FHSSCHANGEDCHANNEL |
dudmuck 0:8f0d0ae0a077 820 RFLR_IRQFLAGS_CADDETECTED );
dudmuck 0:8f0d0ae0a077 821
dudmuck 0:8f0d0ae0a077 822 // DIO0=RxDone
dudmuck 0:8f0d0ae0a077 823 Write( REG_DIOMAPPING1, ( Read( REG_DIOMAPPING1 ) & RFLR_DIOMAPPING1_DIO0_MASK ) | RFLR_DIOMAPPING1_DIO0_00 );
dudmuck 0:8f0d0ae0a077 824 }
dudmuck 0:8f0d0ae0a077 825 Write( REG_LR_FIFORXBASEADDR, 0 );
dudmuck 0:8f0d0ae0a077 826 Write( REG_LR_FIFOADDRPTR, 0 );
dudmuck 0:8f0d0ae0a077 827 }
dudmuck 0:8f0d0ae0a077 828 break;
dudmuck 0:8f0d0ae0a077 829 }
dudmuck 0:8f0d0ae0a077 830
dudmuck 0:8f0d0ae0a077 831 memset( rxtxBuffer, 0, ( size_t )RX_BUFFER_SIZE );
dudmuck 0:8f0d0ae0a077 832
dudmuck 0:8f0d0ae0a077 833 this->settings.State = RF_RX_RUNNING;
dudmuck 0:8f0d0ae0a077 834 if( timeout != 0 )
dudmuck 0:8f0d0ae0a077 835 {
dudmuck 0:8f0d0ae0a077 836 rxTimeoutTimer.attach_us( mbed::callback( this, &SX1276::OnTimeoutIrq ), timeout * 1e3 );
dudmuck 0:8f0d0ae0a077 837 }
dudmuck 0:8f0d0ae0a077 838
dudmuck 0:8f0d0ae0a077 839 if( this->settings.Modem == MODEM_FSK )
dudmuck 0:8f0d0ae0a077 840 {
dudmuck 0:8f0d0ae0a077 841 SetOpMode( RF_OPMODE_RECEIVER );
dudmuck 0:8f0d0ae0a077 842
dudmuck 0:8f0d0ae0a077 843 if( rxContinuous == false )
dudmuck 0:8f0d0ae0a077 844 {
dudmuck 0:8f0d0ae0a077 845 rxTimeoutSyncWord.attach_us( mbed::callback( this, &SX1276::OnTimeoutIrq ),
dudmuck 0:8f0d0ae0a077 846 this->settings.Fsk.RxSingleTimeout * 1e3 );
dudmuck 0:8f0d0ae0a077 847 }
dudmuck 0:8f0d0ae0a077 848 }
dudmuck 0:8f0d0ae0a077 849 else
dudmuck 0:8f0d0ae0a077 850 {
dudmuck 0:8f0d0ae0a077 851 if( rxContinuous == true )
dudmuck 0:8f0d0ae0a077 852 {
dudmuck 0:8f0d0ae0a077 853 SetOpMode( RFLR_OPMODE_RECEIVER );
dudmuck 0:8f0d0ae0a077 854 }
dudmuck 0:8f0d0ae0a077 855 else
dudmuck 0:8f0d0ae0a077 856 {
dudmuck 0:8f0d0ae0a077 857 SetOpMode( RFLR_OPMODE_RECEIVER_SINGLE );
dudmuck 0:8f0d0ae0a077 858 }
dudmuck 0:8f0d0ae0a077 859 }
dudmuck 0:8f0d0ae0a077 860 }
dudmuck 0:8f0d0ae0a077 861
dudmuck 0:8f0d0ae0a077 862 void SX1276::Tx( uint32_t timeout )
dudmuck 0:8f0d0ae0a077 863 {
dudmuck 0:8f0d0ae0a077 864
dudmuck 0:8f0d0ae0a077 865 switch( this->settings.Modem )
dudmuck 0:8f0d0ae0a077 866 {
dudmuck 0:8f0d0ae0a077 867 case MODEM_FSK:
dudmuck 0:8f0d0ae0a077 868 {
dudmuck 0:8f0d0ae0a077 869 // DIO0=PacketSent
dudmuck 0:8f0d0ae0a077 870 // DIO1=FifoEmpty
dudmuck 0:8f0d0ae0a077 871 // DIO2=FifoFull
dudmuck 0:8f0d0ae0a077 872 // DIO3=FifoEmpty
dudmuck 0:8f0d0ae0a077 873 // DIO4=LowBat
dudmuck 0:8f0d0ae0a077 874 // DIO5=ModeReady
dudmuck 0:8f0d0ae0a077 875 Write( REG_DIOMAPPING1, ( Read( REG_DIOMAPPING1 ) & RF_DIOMAPPING1_DIO0_MASK &
dudmuck 0:8f0d0ae0a077 876 RF_DIOMAPPING1_DIO1_MASK &
dudmuck 0:8f0d0ae0a077 877 RF_DIOMAPPING1_DIO2_MASK ) |
dudmuck 0:8f0d0ae0a077 878 RF_DIOMAPPING1_DIO1_01 );
dudmuck 0:8f0d0ae0a077 879
dudmuck 0:8f0d0ae0a077 880 Write( REG_DIOMAPPING2, ( Read( REG_DIOMAPPING2 ) & RF_DIOMAPPING2_DIO4_MASK &
dudmuck 0:8f0d0ae0a077 881 RF_DIOMAPPING2_MAP_MASK ) );
dudmuck 0:8f0d0ae0a077 882 this->settings.FskPacketHandler.FifoThresh = Read( REG_FIFOTHRESH ) & 0x3F;
dudmuck 0:8f0d0ae0a077 883 }
dudmuck 0:8f0d0ae0a077 884 break;
dudmuck 0:8f0d0ae0a077 885 case MODEM_LORA:
dudmuck 0:8f0d0ae0a077 886 {
dudmuck 0:8f0d0ae0a077 887 if( this->settings.LoRa.FreqHopOn == true )
dudmuck 0:8f0d0ae0a077 888 {
dudmuck 0:8f0d0ae0a077 889 Write( REG_LR_IRQFLAGSMASK, RFLR_IRQFLAGS_RXTIMEOUT |
dudmuck 0:8f0d0ae0a077 890 RFLR_IRQFLAGS_RXDONE |
dudmuck 0:8f0d0ae0a077 891 RFLR_IRQFLAGS_PAYLOADCRCERROR |
dudmuck 0:8f0d0ae0a077 892 RFLR_IRQFLAGS_VALIDHEADER |
dudmuck 0:8f0d0ae0a077 893 //RFLR_IRQFLAGS_TXDONE |
dudmuck 0:8f0d0ae0a077 894 RFLR_IRQFLAGS_CADDONE |
dudmuck 0:8f0d0ae0a077 895 //RFLR_IRQFLAGS_FHSSCHANGEDCHANNEL |
dudmuck 0:8f0d0ae0a077 896 RFLR_IRQFLAGS_CADDETECTED );
dudmuck 0:8f0d0ae0a077 897
dudmuck 0:8f0d0ae0a077 898 // DIO0=TxDone, DIO2=FhssChangeChannel
dudmuck 0:8f0d0ae0a077 899 Write( REG_DIOMAPPING1, ( Read( REG_DIOMAPPING1 ) & RFLR_DIOMAPPING1_DIO0_MASK & RFLR_DIOMAPPING1_DIO2_MASK ) | RFLR_DIOMAPPING1_DIO0_01 | RFLR_DIOMAPPING1_DIO2_00 );
dudmuck 0:8f0d0ae0a077 900 }
dudmuck 0:8f0d0ae0a077 901 else
dudmuck 0:8f0d0ae0a077 902 {
dudmuck 0:8f0d0ae0a077 903 Write( REG_LR_IRQFLAGSMASK, RFLR_IRQFLAGS_RXTIMEOUT |
dudmuck 0:8f0d0ae0a077 904 RFLR_IRQFLAGS_RXDONE |
dudmuck 0:8f0d0ae0a077 905 RFLR_IRQFLAGS_PAYLOADCRCERROR |
dudmuck 0:8f0d0ae0a077 906 RFLR_IRQFLAGS_VALIDHEADER |
dudmuck 0:8f0d0ae0a077 907 //RFLR_IRQFLAGS_TXDONE |
dudmuck 0:8f0d0ae0a077 908 RFLR_IRQFLAGS_CADDONE |
dudmuck 0:8f0d0ae0a077 909 RFLR_IRQFLAGS_FHSSCHANGEDCHANNEL |
dudmuck 0:8f0d0ae0a077 910 RFLR_IRQFLAGS_CADDETECTED );
dudmuck 0:8f0d0ae0a077 911
dudmuck 0:8f0d0ae0a077 912 // DIO0=TxDone
dudmuck 0:8f0d0ae0a077 913 Write( REG_DIOMAPPING1, ( Read( REG_DIOMAPPING1 ) & RFLR_DIOMAPPING1_DIO0_MASK ) | RFLR_DIOMAPPING1_DIO0_01 );
dudmuck 0:8f0d0ae0a077 914 }
dudmuck 0:8f0d0ae0a077 915 }
dudmuck 0:8f0d0ae0a077 916 break;
dudmuck 0:8f0d0ae0a077 917 }
dudmuck 0:8f0d0ae0a077 918
dudmuck 0:8f0d0ae0a077 919 this->settings.State = RF_TX_RUNNING;
dudmuck 0:8f0d0ae0a077 920 txTimeoutTimer.attach_us( mbed::callback( this, &SX1276::OnTimeoutIrq ), timeout * 1e3 );
dudmuck 0:8f0d0ae0a077 921 SetOpMode( RF_OPMODE_TRANSMITTER );
dudmuck 0:8f0d0ae0a077 922 }
dudmuck 0:8f0d0ae0a077 923
dudmuck 0:8f0d0ae0a077 924 void SX1276::StartCad( void )
dudmuck 0:8f0d0ae0a077 925 {
dudmuck 0:8f0d0ae0a077 926 switch( this->settings.Modem )
dudmuck 0:8f0d0ae0a077 927 {
dudmuck 0:8f0d0ae0a077 928 case MODEM_FSK:
dudmuck 0:8f0d0ae0a077 929 {
dudmuck 0:8f0d0ae0a077 930
dudmuck 0:8f0d0ae0a077 931 }
dudmuck 0:8f0d0ae0a077 932 break;
dudmuck 0:8f0d0ae0a077 933 case MODEM_LORA:
dudmuck 0:8f0d0ae0a077 934 {
dudmuck 0:8f0d0ae0a077 935 Write( REG_LR_IRQFLAGSMASK, RFLR_IRQFLAGS_RXTIMEOUT |
dudmuck 0:8f0d0ae0a077 936 RFLR_IRQFLAGS_RXDONE |
dudmuck 0:8f0d0ae0a077 937 RFLR_IRQFLAGS_PAYLOADCRCERROR |
dudmuck 0:8f0d0ae0a077 938 RFLR_IRQFLAGS_VALIDHEADER |
dudmuck 0:8f0d0ae0a077 939 RFLR_IRQFLAGS_TXDONE |
dudmuck 0:8f0d0ae0a077 940 //RFLR_IRQFLAGS_CADDONE |
dudmuck 0:8f0d0ae0a077 941 RFLR_IRQFLAGS_FHSSCHANGEDCHANNEL // |
dudmuck 0:8f0d0ae0a077 942 //RFLR_IRQFLAGS_CADDETECTED
dudmuck 0:8f0d0ae0a077 943 );
dudmuck 0:8f0d0ae0a077 944
dudmuck 0:8f0d0ae0a077 945 // DIO3=CADDone
dudmuck 0:8f0d0ae0a077 946 Write( REG_DIOMAPPING1, ( Read( REG_DIOMAPPING1 ) & RFLR_DIOMAPPING1_DIO3_MASK ) | RFLR_DIOMAPPING1_DIO3_00 );
dudmuck 0:8f0d0ae0a077 947
dudmuck 0:8f0d0ae0a077 948 this->settings.State = RF_CAD;
dudmuck 0:8f0d0ae0a077 949 SetOpMode( RFLR_OPMODE_CAD );
dudmuck 0:8f0d0ae0a077 950 }
dudmuck 0:8f0d0ae0a077 951 break;
dudmuck 0:8f0d0ae0a077 952 default:
dudmuck 0:8f0d0ae0a077 953 break;
dudmuck 0:8f0d0ae0a077 954 }
dudmuck 0:8f0d0ae0a077 955 }
dudmuck 0:8f0d0ae0a077 956
dudmuck 0:8f0d0ae0a077 957 void SX1276::SetTxContinuousWave( uint32_t freq, int8_t power, uint16_t time )
dudmuck 0:8f0d0ae0a077 958 {
dudmuck 0:8f0d0ae0a077 959 uint32_t timeout = ( uint32_t )( time * 1e6 );
dudmuck 0:8f0d0ae0a077 960
dudmuck 0:8f0d0ae0a077 961 SetChannel( freq );
dudmuck 0:8f0d0ae0a077 962
dudmuck 0:8f0d0ae0a077 963 SetTxConfig( MODEM_FSK, power, 0, 0, 4800, 0, 5, false, false, 0, 0, 0, timeout );
dudmuck 0:8f0d0ae0a077 964
dudmuck 0:8f0d0ae0a077 965 Write( REG_PACKETCONFIG2, ( Read( REG_PACKETCONFIG2 ) & RF_PACKETCONFIG2_DATAMODE_MASK ) );
dudmuck 0:8f0d0ae0a077 966 // Disable radio interrupts
dudmuck 0:8f0d0ae0a077 967 Write( REG_DIOMAPPING1, RF_DIOMAPPING1_DIO0_11 | RF_DIOMAPPING1_DIO1_11 );
dudmuck 0:8f0d0ae0a077 968 Write( REG_DIOMAPPING2, RF_DIOMAPPING2_DIO4_10 | RF_DIOMAPPING2_DIO5_10 );
dudmuck 0:8f0d0ae0a077 969
dudmuck 0:8f0d0ae0a077 970 this->settings.State = RF_TX_RUNNING;
dudmuck 0:8f0d0ae0a077 971 txTimeoutTimer.attach_us( mbed::callback( this, &SX1276::OnTimeoutIrq ), timeout );
dudmuck 0:8f0d0ae0a077 972 SetOpMode( RF_OPMODE_TRANSMITTER );
dudmuck 0:8f0d0ae0a077 973 }
dudmuck 0:8f0d0ae0a077 974
dudmuck 0:8f0d0ae0a077 975 int16_t SX1276::GetRssi( RadioModems_t modem )
dudmuck 0:8f0d0ae0a077 976 {
dudmuck 0:8f0d0ae0a077 977 int16_t rssi = 0;
dudmuck 0:8f0d0ae0a077 978
dudmuck 0:8f0d0ae0a077 979 switch( modem )
dudmuck 0:8f0d0ae0a077 980 {
dudmuck 0:8f0d0ae0a077 981 case MODEM_FSK:
dudmuck 0:8f0d0ae0a077 982 rssi = -( Read( REG_RSSIVALUE ) >> 1 );
dudmuck 0:8f0d0ae0a077 983 break;
dudmuck 0:8f0d0ae0a077 984 case MODEM_LORA:
dudmuck 0:8f0d0ae0a077 985 if( this->settings.Channel > RF_MID_BAND_THRESH )
dudmuck 0:8f0d0ae0a077 986 {
dudmuck 0:8f0d0ae0a077 987 rssi = RSSI_OFFSET_HF + Read( REG_LR_RSSIVALUE );
dudmuck 0:8f0d0ae0a077 988 }
dudmuck 0:8f0d0ae0a077 989 else
dudmuck 0:8f0d0ae0a077 990 {
dudmuck 0:8f0d0ae0a077 991 rssi = RSSI_OFFSET_LF + Read( REG_LR_RSSIVALUE );
dudmuck 0:8f0d0ae0a077 992 }
dudmuck 0:8f0d0ae0a077 993 break;
dudmuck 0:8f0d0ae0a077 994 default:
dudmuck 0:8f0d0ae0a077 995 rssi = -1;
dudmuck 0:8f0d0ae0a077 996 break;
dudmuck 0:8f0d0ae0a077 997 }
dudmuck 0:8f0d0ae0a077 998 return rssi;
dudmuck 0:8f0d0ae0a077 999 }
dudmuck 0:8f0d0ae0a077 1000
dudmuck 0:8f0d0ae0a077 1001 extern DigitalOut rx_debug_pin; // from board.cpp
dudmuck 10:00997daeb0c0 1002 extern bool expecting_beacon; // from LoRaMac
dudmuck 0:8f0d0ae0a077 1003
dudmuck 0:8f0d0ae0a077 1004 void SX1276::SetOpMode( uint8_t opMode )
dudmuck 0:8f0d0ae0a077 1005 {
dudmuck 18:9ac71c0eb70d 1006 if ((opMode == RF_OPMODE_RECEIVER || opMode == RFLR_OPMODE_RECEIVER_SINGLE) && expecting_beacon)
dudmuck 0:8f0d0ae0a077 1007 rx_debug_pin = 1;
dudmuck 0:8f0d0ae0a077 1008 else
dudmuck 0:8f0d0ae0a077 1009 rx_debug_pin = 0;
dudmuck 0:8f0d0ae0a077 1010
dudmuck 0:8f0d0ae0a077 1011 if( opMode == RF_OPMODE_SLEEP )
dudmuck 0:8f0d0ae0a077 1012 {
dudmuck 0:8f0d0ae0a077 1013 SetAntSwLowPower( true );
dudmuck 0:8f0d0ae0a077 1014 }
dudmuck 0:8f0d0ae0a077 1015 else
dudmuck 0:8f0d0ae0a077 1016 {
dudmuck 0:8f0d0ae0a077 1017 SetAntSwLowPower( false );
dudmuck 0:8f0d0ae0a077 1018 SetAntSw( opMode );
dudmuck 0:8f0d0ae0a077 1019 }
dudmuck 0:8f0d0ae0a077 1020 Write( REG_OPMODE, ( Read( REG_OPMODE ) & RF_OPMODE_MASK ) | opMode );
dudmuck 0:8f0d0ae0a077 1021 }
dudmuck 0:8f0d0ae0a077 1022
dudmuck 0:8f0d0ae0a077 1023 void SX1276::SetModem( RadioModems_t modem )
dudmuck 0:8f0d0ae0a077 1024 {
dudmuck 0:8f0d0ae0a077 1025 if( ( Read( REG_OPMODE ) & RFLR_OPMODE_LONGRANGEMODE_ON ) != 0 )
dudmuck 0:8f0d0ae0a077 1026 {
dudmuck 0:8f0d0ae0a077 1027 this->settings.Modem = MODEM_LORA;
dudmuck 0:8f0d0ae0a077 1028 }
dudmuck 0:8f0d0ae0a077 1029 else
dudmuck 0:8f0d0ae0a077 1030 {
dudmuck 0:8f0d0ae0a077 1031 this->settings.Modem = MODEM_FSK;
dudmuck 0:8f0d0ae0a077 1032 }
dudmuck 0:8f0d0ae0a077 1033
dudmuck 0:8f0d0ae0a077 1034 if( this->settings.Modem == modem )
dudmuck 0:8f0d0ae0a077 1035 {
dudmuck 0:8f0d0ae0a077 1036 return;
dudmuck 0:8f0d0ae0a077 1037 }
dudmuck 0:8f0d0ae0a077 1038
dudmuck 0:8f0d0ae0a077 1039 this->settings.Modem = modem;
dudmuck 0:8f0d0ae0a077 1040 switch( this->settings.Modem )
dudmuck 0:8f0d0ae0a077 1041 {
dudmuck 0:8f0d0ae0a077 1042 default:
dudmuck 0:8f0d0ae0a077 1043 case MODEM_FSK:
dudmuck 0:8f0d0ae0a077 1044 Sleep( );
dudmuck 0:8f0d0ae0a077 1045 Write( REG_OPMODE, ( Read( REG_OPMODE ) & RFLR_OPMODE_LONGRANGEMODE_MASK ) | RFLR_OPMODE_LONGRANGEMODE_OFF );
dudmuck 0:8f0d0ae0a077 1046
dudmuck 0:8f0d0ae0a077 1047 Write( REG_DIOMAPPING1, 0x00 );
dudmuck 0:8f0d0ae0a077 1048 Write( REG_DIOMAPPING2, 0x30 ); // DIO5=ModeReady
dudmuck 0:8f0d0ae0a077 1049 break;
dudmuck 0:8f0d0ae0a077 1050 case MODEM_LORA:
dudmuck 0:8f0d0ae0a077 1051 Sleep( );
dudmuck 0:8f0d0ae0a077 1052 Write( REG_OPMODE, ( Read( REG_OPMODE ) & RFLR_OPMODE_LONGRANGEMODE_MASK ) | RFLR_OPMODE_LONGRANGEMODE_ON );
dudmuck 0:8f0d0ae0a077 1053
dudmuck 0:8f0d0ae0a077 1054 Write( REG_DIOMAPPING1, 0x00 );
dudmuck 0:8f0d0ae0a077 1055 Write( REG_DIOMAPPING2, 0x00 );
dudmuck 0:8f0d0ae0a077 1056 break;
dudmuck 0:8f0d0ae0a077 1057 }
dudmuck 0:8f0d0ae0a077 1058 }
dudmuck 0:8f0d0ae0a077 1059
dudmuck 0:8f0d0ae0a077 1060 void SX1276::SetMaxPayloadLength( RadioModems_t modem, uint8_t max )
dudmuck 0:8f0d0ae0a077 1061 {
dudmuck 0:8f0d0ae0a077 1062 this->SetModem( modem );
dudmuck 0:8f0d0ae0a077 1063
dudmuck 0:8f0d0ae0a077 1064 switch( modem )
dudmuck 0:8f0d0ae0a077 1065 {
dudmuck 0:8f0d0ae0a077 1066 case MODEM_FSK:
dudmuck 0:8f0d0ae0a077 1067 if( this->settings.Fsk.FixLen == false )
dudmuck 0:8f0d0ae0a077 1068 {
dudmuck 0:8f0d0ae0a077 1069 this->Write( REG_PAYLOADLENGTH, max );
dudmuck 0:8f0d0ae0a077 1070 }
dudmuck 0:8f0d0ae0a077 1071 break;
dudmuck 0:8f0d0ae0a077 1072 case MODEM_LORA:
dudmuck 0:8f0d0ae0a077 1073 this->Write( REG_LR_PAYLOADMAXLENGTH, max );
dudmuck 0:8f0d0ae0a077 1074 break;
dudmuck 0:8f0d0ae0a077 1075 }
dudmuck 0:8f0d0ae0a077 1076 }
dudmuck 0:8f0d0ae0a077 1077
dudmuck 0:8f0d0ae0a077 1078 void SX1276::SetPublicNetwork( bool enable )
dudmuck 0:8f0d0ae0a077 1079 {
dudmuck 0:8f0d0ae0a077 1080 SetModem( MODEM_LORA );
dudmuck 0:8f0d0ae0a077 1081 this->settings.LoRa.PublicNetwork = enable;
dudmuck 0:8f0d0ae0a077 1082 if( enable == true )
dudmuck 0:8f0d0ae0a077 1083 {
dudmuck 0:8f0d0ae0a077 1084 // Change LoRa modem SyncWord
dudmuck 0:8f0d0ae0a077 1085 Write( REG_LR_SYNCWORD, LORA_MAC_PUBLIC_SYNCWORD );
dudmuck 0:8f0d0ae0a077 1086 }
dudmuck 0:8f0d0ae0a077 1087 else
dudmuck 0:8f0d0ae0a077 1088 {
dudmuck 0:8f0d0ae0a077 1089 // Change LoRa modem SyncWord
dudmuck 0:8f0d0ae0a077 1090 Write( REG_LR_SYNCWORD, LORA_MAC_PRIVATE_SYNCWORD );
dudmuck 0:8f0d0ae0a077 1091 }
dudmuck 0:8f0d0ae0a077 1092 }
dudmuck 0:8f0d0ae0a077 1093
dudmuck 0:8f0d0ae0a077 1094 void SX1276::OnTimeoutIrq( void )
dudmuck 0:8f0d0ae0a077 1095 {
dudmuck 0:8f0d0ae0a077 1096 switch( this->settings.State )
dudmuck 0:8f0d0ae0a077 1097 {
dudmuck 0:8f0d0ae0a077 1098 case RF_RX_RUNNING:
dudmuck 0:8f0d0ae0a077 1099 if( this->settings.Modem == MODEM_FSK )
dudmuck 0:8f0d0ae0a077 1100 {
dudmuck 0:8f0d0ae0a077 1101 this->settings.FskPacketHandler.PreambleDetected = false;
dudmuck 0:8f0d0ae0a077 1102 this->settings.FskPacketHandler.SyncWordDetected = false;
dudmuck 0:8f0d0ae0a077 1103 this->settings.FskPacketHandler.NbBytes = 0;
dudmuck 0:8f0d0ae0a077 1104 this->settings.FskPacketHandler.Size = 0;
dudmuck 0:8f0d0ae0a077 1105
dudmuck 0:8f0d0ae0a077 1106 // Clear Irqs
dudmuck 0:8f0d0ae0a077 1107 Write( REG_IRQFLAGS1, RF_IRQFLAGS1_RSSI |
dudmuck 0:8f0d0ae0a077 1108 RF_IRQFLAGS1_PREAMBLEDETECT |
dudmuck 0:8f0d0ae0a077 1109 RF_IRQFLAGS1_SYNCADDRESSMATCH );
dudmuck 0:8f0d0ae0a077 1110 Write( REG_IRQFLAGS2, RF_IRQFLAGS2_FIFOOVERRUN );
dudmuck 0:8f0d0ae0a077 1111
dudmuck 0:8f0d0ae0a077 1112 if( this->settings.Fsk.RxContinuous == true )
dudmuck 0:8f0d0ae0a077 1113 {
dudmuck 0:8f0d0ae0a077 1114 // Continuous mode restart Rx chain
dudmuck 0:8f0d0ae0a077 1115 Write( REG_RXCONFIG, Read( REG_RXCONFIG ) | RF_RXCONFIG_RESTARTRXWITHOUTPLLLOCK );
dudmuck 0:8f0d0ae0a077 1116 rxTimeoutSyncWord.attach_us( mbed::callback( this, &SX1276::OnTimeoutIrq ),
dudmuck 0:8f0d0ae0a077 1117 this->settings.Fsk.RxSingleTimeout * 1e3 );
dudmuck 0:8f0d0ae0a077 1118 }
dudmuck 0:8f0d0ae0a077 1119 else
dudmuck 0:8f0d0ae0a077 1120 {
dudmuck 0:8f0d0ae0a077 1121 this->settings.State = RF_IDLE;
dudmuck 0:8f0d0ae0a077 1122 rxTimeoutSyncWord.detach( );
dudmuck 0:8f0d0ae0a077 1123 }
dudmuck 0:8f0d0ae0a077 1124 }
dudmuck 0:8f0d0ae0a077 1125 if( ( this->RadioEvents != NULL ) && ( this->RadioEvents->RxTimeout != NULL ) )
dudmuck 0:8f0d0ae0a077 1126 {
dudmuck 0:8f0d0ae0a077 1127 this->RadioEvents->RxTimeout( );
dudmuck 0:8f0d0ae0a077 1128 }
dudmuck 0:8f0d0ae0a077 1129 break;
dudmuck 0:8f0d0ae0a077 1130 case RF_TX_RUNNING:
dudmuck 0:8f0d0ae0a077 1131 // Tx timeout shouldn't happen.
dudmuck 0:8f0d0ae0a077 1132 // But it has been observed that when it happens it is a result of a corrupted SPI transfer
dudmuck 0:8f0d0ae0a077 1133 // it depends on the platform design.
dudmuck 0:8f0d0ae0a077 1134 //
dudmuck 0:8f0d0ae0a077 1135 // The workaround is to put the radio in a known state. Thus, we re-initialize it.
dudmuck 0:8f0d0ae0a077 1136
dudmuck 0:8f0d0ae0a077 1137 // BEGIN WORKAROUND
dudmuck 0:8f0d0ae0a077 1138
dudmuck 0:8f0d0ae0a077 1139 // Reset the radio
dudmuck 0:8f0d0ae0a077 1140 Reset( );
dudmuck 0:8f0d0ae0a077 1141
dudmuck 0:8f0d0ae0a077 1142 // Calibrate Rx chain
dudmuck 0:8f0d0ae0a077 1143 RxChainCalibration( );
dudmuck 0:8f0d0ae0a077 1144
dudmuck 0:8f0d0ae0a077 1145 // Initialize radio default values
dudmuck 0:8f0d0ae0a077 1146 SetOpMode( RF_OPMODE_SLEEP );
dudmuck 0:8f0d0ae0a077 1147
dudmuck 0:8f0d0ae0a077 1148 RadioRegistersInit( );
dudmuck 0:8f0d0ae0a077 1149
dudmuck 0:8f0d0ae0a077 1150 SetModem( MODEM_FSK );
dudmuck 0:8f0d0ae0a077 1151
dudmuck 0:8f0d0ae0a077 1152 // Restore previous network type setting.
dudmuck 0:8f0d0ae0a077 1153 SetPublicNetwork( this->settings.LoRa.PublicNetwork );
dudmuck 0:8f0d0ae0a077 1154 // END WORKAROUND
dudmuck 0:8f0d0ae0a077 1155
dudmuck 0:8f0d0ae0a077 1156 this->settings.State = RF_IDLE;
dudmuck 0:8f0d0ae0a077 1157 if( ( this->RadioEvents != NULL ) && ( this->RadioEvents->TxTimeout != NULL ) )
dudmuck 0:8f0d0ae0a077 1158 {
dudmuck 0:8f0d0ae0a077 1159 this->RadioEvents->TxTimeout( );
dudmuck 0:8f0d0ae0a077 1160 }
dudmuck 0:8f0d0ae0a077 1161 break;
dudmuck 0:8f0d0ae0a077 1162 default:
dudmuck 0:8f0d0ae0a077 1163 break;
dudmuck 0:8f0d0ae0a077 1164 }
dudmuck 0:8f0d0ae0a077 1165 }
dudmuck 0:8f0d0ae0a077 1166
dudmuck 20:42839629a5dc 1167 void SX1276::dio0_bh( void )
dudmuck 0:8f0d0ae0a077 1168 {
dudmuck 0:8f0d0ae0a077 1169 volatile uint8_t irqFlags = 0;
dudmuck 0:8f0d0ae0a077 1170
dudmuck 0:8f0d0ae0a077 1171 switch( this->settings.State )
dudmuck 0:8f0d0ae0a077 1172 {
dudmuck 0:8f0d0ae0a077 1173 case RF_RX_RUNNING:
dudmuck 0:8f0d0ae0a077 1174 //TimerStop( &RxTimeoutTimer );
dudmuck 0:8f0d0ae0a077 1175 // RxDone interrupt
dudmuck 0:8f0d0ae0a077 1176 switch( this->settings.Modem )
dudmuck 0:8f0d0ae0a077 1177 {
dudmuck 0:8f0d0ae0a077 1178 case MODEM_FSK:
dudmuck 0:8f0d0ae0a077 1179 if( this->settings.Fsk.CrcOn == true )
dudmuck 0:8f0d0ae0a077 1180 {
dudmuck 0:8f0d0ae0a077 1181 irqFlags = Read( REG_IRQFLAGS2 );
dudmuck 0:8f0d0ae0a077 1182 if( ( irqFlags & RF_IRQFLAGS2_CRCOK ) != RF_IRQFLAGS2_CRCOK )
dudmuck 0:8f0d0ae0a077 1183 {
dudmuck 0:8f0d0ae0a077 1184 // Clear Irqs
dudmuck 0:8f0d0ae0a077 1185 Write( REG_IRQFLAGS1, RF_IRQFLAGS1_RSSI |
dudmuck 0:8f0d0ae0a077 1186 RF_IRQFLAGS1_PREAMBLEDETECT |
dudmuck 0:8f0d0ae0a077 1187 RF_IRQFLAGS1_SYNCADDRESSMATCH );
dudmuck 0:8f0d0ae0a077 1188 Write( REG_IRQFLAGS2, RF_IRQFLAGS2_FIFOOVERRUN );
dudmuck 0:8f0d0ae0a077 1189
dudmuck 0:8f0d0ae0a077 1190 rxTimeoutTimer.detach( );
dudmuck 0:8f0d0ae0a077 1191
dudmuck 0:8f0d0ae0a077 1192 if( this->settings.Fsk.RxContinuous == false )
dudmuck 0:8f0d0ae0a077 1193 {
dudmuck 0:8f0d0ae0a077 1194 rxTimeoutSyncWord.detach( );
dudmuck 0:8f0d0ae0a077 1195 this->settings.State = RF_IDLE;
dudmuck 0:8f0d0ae0a077 1196 }
dudmuck 0:8f0d0ae0a077 1197 else
dudmuck 0:8f0d0ae0a077 1198 {
dudmuck 0:8f0d0ae0a077 1199 // Continuous mode restart Rx chain
dudmuck 0:8f0d0ae0a077 1200 Write( REG_RXCONFIG, Read( REG_RXCONFIG ) | RF_RXCONFIG_RESTARTRXWITHOUTPLLLOCK );
dudmuck 0:8f0d0ae0a077 1201 rxTimeoutSyncWord.attach_us( mbed::callback( this, &SX1276::OnTimeoutIrq ),
dudmuck 0:8f0d0ae0a077 1202 this->settings.Fsk.RxSingleTimeout * 1e3 );
dudmuck 0:8f0d0ae0a077 1203 }
dudmuck 0:8f0d0ae0a077 1204
dudmuck 0:8f0d0ae0a077 1205 if( ( this->RadioEvents != NULL ) && ( this->RadioEvents->RxError != NULL ) )
dudmuck 0:8f0d0ae0a077 1206 {
dudmuck 0:8f0d0ae0a077 1207 this->RadioEvents->RxError( );
dudmuck 0:8f0d0ae0a077 1208 }
dudmuck 0:8f0d0ae0a077 1209 this->settings.FskPacketHandler.PreambleDetected = false;
dudmuck 0:8f0d0ae0a077 1210 this->settings.FskPacketHandler.SyncWordDetected = false;
dudmuck 0:8f0d0ae0a077 1211 this->settings.FskPacketHandler.NbBytes = 0;
dudmuck 0:8f0d0ae0a077 1212 this->settings.FskPacketHandler.Size = 0;
dudmuck 0:8f0d0ae0a077 1213 break;
dudmuck 0:8f0d0ae0a077 1214 }
dudmuck 0:8f0d0ae0a077 1215 }
dudmuck 0:8f0d0ae0a077 1216
dudmuck 0:8f0d0ae0a077 1217 // Read received packet size
dudmuck 0:8f0d0ae0a077 1218 if( ( this->settings.FskPacketHandler.Size == 0 ) && ( this->settings.FskPacketHandler.NbBytes == 0 ) )
dudmuck 0:8f0d0ae0a077 1219 {
dudmuck 0:8f0d0ae0a077 1220 if( this->settings.Fsk.FixLen == false )
dudmuck 0:8f0d0ae0a077 1221 {
dudmuck 0:8f0d0ae0a077 1222 ReadFifo( ( uint8_t* )&this->settings.FskPacketHandler.Size, 1 );
dudmuck 0:8f0d0ae0a077 1223 }
dudmuck 0:8f0d0ae0a077 1224 else
dudmuck 0:8f0d0ae0a077 1225 {
dudmuck 0:8f0d0ae0a077 1226 this->settings.FskPacketHandler.Size = Read( REG_PAYLOADLENGTH );
dudmuck 0:8f0d0ae0a077 1227 }
dudmuck 0:8f0d0ae0a077 1228 ReadFifo( rxtxBuffer + this->settings.FskPacketHandler.NbBytes, this->settings.FskPacketHandler.Size - this->settings.FskPacketHandler.NbBytes );
dudmuck 0:8f0d0ae0a077 1229 this->settings.FskPacketHandler.NbBytes += ( this->settings.FskPacketHandler.Size - this->settings.FskPacketHandler.NbBytes );
dudmuck 0:8f0d0ae0a077 1230 }
dudmuck 0:8f0d0ae0a077 1231 else
dudmuck 0:8f0d0ae0a077 1232 {
dudmuck 0:8f0d0ae0a077 1233 ReadFifo( rxtxBuffer + this->settings.FskPacketHandler.NbBytes, this->settings.FskPacketHandler.Size - this->settings.FskPacketHandler.NbBytes );
dudmuck 0:8f0d0ae0a077 1234 this->settings.FskPacketHandler.NbBytes += ( this->settings.FskPacketHandler.Size - this->settings.FskPacketHandler.NbBytes );
dudmuck 0:8f0d0ae0a077 1235 }
dudmuck 0:8f0d0ae0a077 1236
dudmuck 0:8f0d0ae0a077 1237 rxTimeoutTimer.detach( );
dudmuck 0:8f0d0ae0a077 1238
dudmuck 0:8f0d0ae0a077 1239 if( this->settings.Fsk.RxContinuous == false )
dudmuck 0:8f0d0ae0a077 1240 {
dudmuck 0:8f0d0ae0a077 1241 this->settings.State = RF_IDLE;
dudmuck 0:8f0d0ae0a077 1242 rxTimeoutSyncWord.detach( );
dudmuck 0:8f0d0ae0a077 1243 }
dudmuck 0:8f0d0ae0a077 1244 else
dudmuck 0:8f0d0ae0a077 1245 {
dudmuck 0:8f0d0ae0a077 1246 // Continuous mode restart Rx chain
dudmuck 0:8f0d0ae0a077 1247 Write( REG_RXCONFIG, Read( REG_RXCONFIG ) | RF_RXCONFIG_RESTARTRXWITHOUTPLLLOCK );
dudmuck 0:8f0d0ae0a077 1248 rxTimeoutSyncWord.attach_us( mbed::callback( this, &SX1276::OnTimeoutIrq ),
dudmuck 0:8f0d0ae0a077 1249 this->settings.Fsk.RxSingleTimeout * 1e3 );
dudmuck 0:8f0d0ae0a077 1250 }
dudmuck 0:8f0d0ae0a077 1251
dudmuck 0:8f0d0ae0a077 1252 if( ( this->RadioEvents != NULL ) && ( this->RadioEvents->RxDone != NULL ) )
dudmuck 0:8f0d0ae0a077 1253 {
dudmuck 20:42839629a5dc 1254 this->RadioEvents->RxDone(dio0_us, rxtxBuffer, this->settings.FskPacketHandler.Size, this->settings.FskPacketHandler.RssiValue, 0 );
dudmuck 0:8f0d0ae0a077 1255 }
dudmuck 0:8f0d0ae0a077 1256 this->settings.FskPacketHandler.PreambleDetected = false;
dudmuck 0:8f0d0ae0a077 1257 this->settings.FskPacketHandler.SyncWordDetected = false;
dudmuck 0:8f0d0ae0a077 1258 this->settings.FskPacketHandler.NbBytes = 0;
dudmuck 0:8f0d0ae0a077 1259 this->settings.FskPacketHandler.Size = 0;
dudmuck 0:8f0d0ae0a077 1260 break;
dudmuck 0:8f0d0ae0a077 1261 case MODEM_LORA:
dudmuck 0:8f0d0ae0a077 1262 {
dudmuck 0:8f0d0ae0a077 1263 int8_t snr = 0;
dudmuck 0:8f0d0ae0a077 1264
dudmuck 0:8f0d0ae0a077 1265 // Clear Irq
dudmuck 0:8f0d0ae0a077 1266 Write( REG_LR_IRQFLAGS, RFLR_IRQFLAGS_RXDONE );
dudmuck 0:8f0d0ae0a077 1267
dudmuck 0:8f0d0ae0a077 1268 irqFlags = Read( REG_LR_IRQFLAGS );
dudmuck 0:8f0d0ae0a077 1269 if( ( irqFlags & RFLR_IRQFLAGS_PAYLOADCRCERROR_MASK ) == RFLR_IRQFLAGS_PAYLOADCRCERROR )
dudmuck 0:8f0d0ae0a077 1270 {
dudmuck 0:8f0d0ae0a077 1271 // Clear Irq
dudmuck 0:8f0d0ae0a077 1272 Write( REG_LR_IRQFLAGS, RFLR_IRQFLAGS_PAYLOADCRCERROR );
dudmuck 0:8f0d0ae0a077 1273
dudmuck 0:8f0d0ae0a077 1274 if( this->settings.LoRa.RxContinuous == false )
dudmuck 0:8f0d0ae0a077 1275 {
dudmuck 0:8f0d0ae0a077 1276 this->settings.State = RF_IDLE;
dudmuck 0:8f0d0ae0a077 1277 }
dudmuck 0:8f0d0ae0a077 1278 rxTimeoutTimer.detach( );
dudmuck 0:8f0d0ae0a077 1279
dudmuck 0:8f0d0ae0a077 1280 if( ( this->RadioEvents != NULL ) && ( this->RadioEvents->RxError != NULL ) )
dudmuck 0:8f0d0ae0a077 1281 {
dudmuck 0:8f0d0ae0a077 1282 this->RadioEvents->RxError( );
dudmuck 0:8f0d0ae0a077 1283 }
dudmuck 0:8f0d0ae0a077 1284 break;
dudmuck 0:8f0d0ae0a077 1285 }
dudmuck 0:8f0d0ae0a077 1286
dudmuck 0:8f0d0ae0a077 1287 this->settings.LoRaPacketHandler.SnrValue = Read( REG_LR_PKTSNRVALUE );
dudmuck 0:8f0d0ae0a077 1288 if( this->settings.LoRaPacketHandler.SnrValue & 0x80 ) // The SNR sign bit is 1
dudmuck 0:8f0d0ae0a077 1289 {
dudmuck 0:8f0d0ae0a077 1290 // Invert and divide by 4
dudmuck 0:8f0d0ae0a077 1291 snr = ( ( ~this->settings.LoRaPacketHandler.SnrValue + 1 ) & 0xFF ) >> 2;
dudmuck 0:8f0d0ae0a077 1292 snr = -snr;
dudmuck 0:8f0d0ae0a077 1293 }
dudmuck 0:8f0d0ae0a077 1294 else
dudmuck 0:8f0d0ae0a077 1295 {
dudmuck 0:8f0d0ae0a077 1296 // Divide by 4
dudmuck 0:8f0d0ae0a077 1297 snr = ( this->settings.LoRaPacketHandler.SnrValue & 0xFF ) >> 2;
dudmuck 0:8f0d0ae0a077 1298 }
dudmuck 0:8f0d0ae0a077 1299
dudmuck 0:8f0d0ae0a077 1300 int16_t rssi = Read( REG_LR_PKTRSSIVALUE );
dudmuck 0:8f0d0ae0a077 1301 if( snr < 0 )
dudmuck 0:8f0d0ae0a077 1302 {
dudmuck 0:8f0d0ae0a077 1303 if( this->settings.Channel > RF_MID_BAND_THRESH )
dudmuck 0:8f0d0ae0a077 1304 {
dudmuck 0:8f0d0ae0a077 1305 this->settings.LoRaPacketHandler.RssiValue = RSSI_OFFSET_HF + rssi + ( rssi >> 4 ) +
dudmuck 0:8f0d0ae0a077 1306 snr;
dudmuck 0:8f0d0ae0a077 1307 }
dudmuck 0:8f0d0ae0a077 1308 else
dudmuck 0:8f0d0ae0a077 1309 {
dudmuck 0:8f0d0ae0a077 1310 this->settings.LoRaPacketHandler.RssiValue = RSSI_OFFSET_LF + rssi + ( rssi >> 4 ) +
dudmuck 0:8f0d0ae0a077 1311 snr;
dudmuck 0:8f0d0ae0a077 1312 }
dudmuck 0:8f0d0ae0a077 1313 }
dudmuck 0:8f0d0ae0a077 1314 else
dudmuck 0:8f0d0ae0a077 1315 {
dudmuck 0:8f0d0ae0a077 1316 if( this->settings.Channel > RF_MID_BAND_THRESH )
dudmuck 0:8f0d0ae0a077 1317 {
dudmuck 0:8f0d0ae0a077 1318 this->settings.LoRaPacketHandler.RssiValue = RSSI_OFFSET_HF + rssi + ( rssi >> 4 );
dudmuck 0:8f0d0ae0a077 1319 }
dudmuck 0:8f0d0ae0a077 1320 else
dudmuck 0:8f0d0ae0a077 1321 {
dudmuck 0:8f0d0ae0a077 1322 this->settings.LoRaPacketHandler.RssiValue = RSSI_OFFSET_LF + rssi + ( rssi >> 4 );
dudmuck 0:8f0d0ae0a077 1323 }
dudmuck 0:8f0d0ae0a077 1324 }
dudmuck 0:8f0d0ae0a077 1325
dudmuck 0:8f0d0ae0a077 1326 this->settings.LoRaPacketHandler.Size = Read( REG_LR_RXNBBYTES );
dudmuck 0:8f0d0ae0a077 1327 ReadFifo( rxtxBuffer, this->settings.LoRaPacketHandler.Size );
dudmuck 0:8f0d0ae0a077 1328
dudmuck 0:8f0d0ae0a077 1329 if( this->settings.LoRa.RxContinuous == false )
dudmuck 0:8f0d0ae0a077 1330 {
dudmuck 0:8f0d0ae0a077 1331 this->settings.State = RF_IDLE;
dudmuck 0:8f0d0ae0a077 1332 }
dudmuck 0:8f0d0ae0a077 1333 rxTimeoutTimer.detach( );
dudmuck 0:8f0d0ae0a077 1334
dudmuck 0:8f0d0ae0a077 1335 if( ( this->RadioEvents != NULL ) && ( this->RadioEvents->RxDone != NULL ) )
dudmuck 0:8f0d0ae0a077 1336 {
dudmuck 20:42839629a5dc 1337 this->RadioEvents->RxDone(dio0_us, rxtxBuffer, this->settings.LoRaPacketHandler.Size, this->settings.LoRaPacketHandler.RssiValue, this->settings.LoRaPacketHandler.SnrValue );
dudmuck 0:8f0d0ae0a077 1338 }
dudmuck 0:8f0d0ae0a077 1339 }
dudmuck 0:8f0d0ae0a077 1340 break;
dudmuck 0:8f0d0ae0a077 1341 default:
dudmuck 0:8f0d0ae0a077 1342 break;
dudmuck 0:8f0d0ae0a077 1343 }
dudmuck 0:8f0d0ae0a077 1344 break;
dudmuck 0:8f0d0ae0a077 1345 case RF_TX_RUNNING:
dudmuck 0:8f0d0ae0a077 1346 txTimeoutTimer.detach( );
dudmuck 0:8f0d0ae0a077 1347 // TxDone interrupt
dudmuck 0:8f0d0ae0a077 1348 switch( this->settings.Modem )
dudmuck 0:8f0d0ae0a077 1349 {
dudmuck 0:8f0d0ae0a077 1350 case MODEM_LORA:
dudmuck 0:8f0d0ae0a077 1351 // Clear Irq
dudmuck 0:8f0d0ae0a077 1352 Write( REG_LR_IRQFLAGS, RFLR_IRQFLAGS_TXDONE );
dudmuck 0:8f0d0ae0a077 1353 // Intentional fall through
dudmuck 0:8f0d0ae0a077 1354 case MODEM_FSK:
dudmuck 0:8f0d0ae0a077 1355 default:
dudmuck 0:8f0d0ae0a077 1356 this->settings.State = RF_IDLE;
dudmuck 0:8f0d0ae0a077 1357 if( ( this->RadioEvents != NULL ) && ( this->RadioEvents->TxDone != NULL ) )
dudmuck 0:8f0d0ae0a077 1358 {
dudmuck 20:42839629a5dc 1359 this->RadioEvents->TxDone( dio0_us );
dudmuck 0:8f0d0ae0a077 1360 }
dudmuck 0:8f0d0ae0a077 1361 break;
dudmuck 0:8f0d0ae0a077 1362 }
dudmuck 0:8f0d0ae0a077 1363 break;
dudmuck 0:8f0d0ae0a077 1364 default:
dudmuck 0:8f0d0ae0a077 1365 break;
dudmuck 0:8f0d0ae0a077 1366 }
dudmuck 0:8f0d0ae0a077 1367 }
dudmuck 0:8f0d0ae0a077 1368
dudmuck 20:42839629a5dc 1369 void SX1276::OnDio0Irq( void )
dudmuck 20:42839629a5dc 1370 {
dudmuck 20:42839629a5dc 1371 dio0_us = lp_timer.read_us();
dudmuck 20:42839629a5dc 1372
dudmuck 20:42839629a5dc 1373 flags.dio0 = 1;
dudmuck 20:42839629a5dc 1374 }
dudmuck 20:42839629a5dc 1375
dudmuck 20:42839629a5dc 1376 void SX1276::dio1_bh( void )
dudmuck 0:8f0d0ae0a077 1377 {
dudmuck 0:8f0d0ae0a077 1378 switch( this->settings.State )
dudmuck 0:8f0d0ae0a077 1379 {
dudmuck 0:8f0d0ae0a077 1380 case RF_RX_RUNNING:
dudmuck 0:8f0d0ae0a077 1381 switch( this->settings.Modem )
dudmuck 0:8f0d0ae0a077 1382 {
dudmuck 0:8f0d0ae0a077 1383 case MODEM_FSK:
dudmuck 0:8f0d0ae0a077 1384 // FifoLevel interrupt
dudmuck 0:8f0d0ae0a077 1385 // Read received packet size
dudmuck 0:8f0d0ae0a077 1386 if( ( this->settings.FskPacketHandler.Size == 0 ) && ( this->settings.FskPacketHandler.NbBytes == 0 ) )
dudmuck 0:8f0d0ae0a077 1387 {
dudmuck 0:8f0d0ae0a077 1388 if( this->settings.Fsk.FixLen == false )
dudmuck 0:8f0d0ae0a077 1389 {
dudmuck 0:8f0d0ae0a077 1390 ReadFifo( ( uint8_t* )&this->settings.FskPacketHandler.Size, 1 );
dudmuck 0:8f0d0ae0a077 1391 }
dudmuck 0:8f0d0ae0a077 1392 else
dudmuck 0:8f0d0ae0a077 1393 {
dudmuck 0:8f0d0ae0a077 1394 this->settings.FskPacketHandler.Size = Read( REG_PAYLOADLENGTH );
dudmuck 0:8f0d0ae0a077 1395 }
dudmuck 0:8f0d0ae0a077 1396 }
dudmuck 0:8f0d0ae0a077 1397
dudmuck 0:8f0d0ae0a077 1398 if( ( this->settings.FskPacketHandler.Size - this->settings.FskPacketHandler.NbBytes ) > this->settings.FskPacketHandler.FifoThresh )
dudmuck 0:8f0d0ae0a077 1399 {
dudmuck 0:8f0d0ae0a077 1400 ReadFifo( ( rxtxBuffer + this->settings.FskPacketHandler.NbBytes ), this->settings.FskPacketHandler.FifoThresh );
dudmuck 0:8f0d0ae0a077 1401 this->settings.FskPacketHandler.NbBytes += this->settings.FskPacketHandler.FifoThresh;
dudmuck 0:8f0d0ae0a077 1402 }
dudmuck 0:8f0d0ae0a077 1403 else
dudmuck 0:8f0d0ae0a077 1404 {
dudmuck 0:8f0d0ae0a077 1405 ReadFifo( ( rxtxBuffer + this->settings.FskPacketHandler.NbBytes ), this->settings.FskPacketHandler.Size - this->settings.FskPacketHandler.NbBytes );
dudmuck 0:8f0d0ae0a077 1406 this->settings.FskPacketHandler.NbBytes += ( this->settings.FskPacketHandler.Size - this->settings.FskPacketHandler.NbBytes );
dudmuck 0:8f0d0ae0a077 1407 }
dudmuck 0:8f0d0ae0a077 1408 break;
dudmuck 0:8f0d0ae0a077 1409 case MODEM_LORA:
dudmuck 0:8f0d0ae0a077 1410 // Sync time out
dudmuck 0:8f0d0ae0a077 1411 rxTimeoutTimer.detach( );
dudmuck 0:8f0d0ae0a077 1412 // Clear Irq
dudmuck 0:8f0d0ae0a077 1413 Write( REG_LR_IRQFLAGS, RFLR_IRQFLAGS_RXTIMEOUT );
dudmuck 0:8f0d0ae0a077 1414
dudmuck 0:8f0d0ae0a077 1415 this->settings.State = RF_IDLE;
dudmuck 0:8f0d0ae0a077 1416 if( ( this->RadioEvents != NULL ) && ( this->RadioEvents->RxTimeout != NULL ) )
dudmuck 0:8f0d0ae0a077 1417 {
dudmuck 0:8f0d0ae0a077 1418 this->RadioEvents->RxTimeout( );
dudmuck 0:8f0d0ae0a077 1419 }
dudmuck 0:8f0d0ae0a077 1420 break;
dudmuck 0:8f0d0ae0a077 1421 default:
dudmuck 0:8f0d0ae0a077 1422 break;
dudmuck 0:8f0d0ae0a077 1423 }
dudmuck 0:8f0d0ae0a077 1424 break;
dudmuck 0:8f0d0ae0a077 1425 case RF_TX_RUNNING:
dudmuck 0:8f0d0ae0a077 1426 switch( this->settings.Modem )
dudmuck 0:8f0d0ae0a077 1427 {
dudmuck 0:8f0d0ae0a077 1428 case MODEM_FSK:
dudmuck 0:8f0d0ae0a077 1429 // FifoEmpty interrupt
dudmuck 0:8f0d0ae0a077 1430 if( ( this->settings.FskPacketHandler.Size - this->settings.FskPacketHandler.NbBytes ) > this->settings.FskPacketHandler.ChunkSize )
dudmuck 0:8f0d0ae0a077 1431 {
dudmuck 0:8f0d0ae0a077 1432 WriteFifo( ( rxtxBuffer + this->settings.FskPacketHandler.NbBytes ), this->settings.FskPacketHandler.ChunkSize );
dudmuck 0:8f0d0ae0a077 1433 this->settings.FskPacketHandler.NbBytes += this->settings.FskPacketHandler.ChunkSize;
dudmuck 0:8f0d0ae0a077 1434 }
dudmuck 0:8f0d0ae0a077 1435 else
dudmuck 0:8f0d0ae0a077 1436 {
dudmuck 0:8f0d0ae0a077 1437 // Write the last chunk of data
dudmuck 0:8f0d0ae0a077 1438 WriteFifo( rxtxBuffer + this->settings.FskPacketHandler.NbBytes, this->settings.FskPacketHandler.Size - this->settings.FskPacketHandler.NbBytes );
dudmuck 0:8f0d0ae0a077 1439 this->settings.FskPacketHandler.NbBytes += this->settings.FskPacketHandler.Size - this->settings.FskPacketHandler.NbBytes;
dudmuck 0:8f0d0ae0a077 1440 }
dudmuck 0:8f0d0ae0a077 1441 break;
dudmuck 0:8f0d0ae0a077 1442 case MODEM_LORA:
dudmuck 0:8f0d0ae0a077 1443 break;
dudmuck 0:8f0d0ae0a077 1444 default:
dudmuck 0:8f0d0ae0a077 1445 break;
dudmuck 0:8f0d0ae0a077 1446 }
dudmuck 0:8f0d0ae0a077 1447 break;
dudmuck 0:8f0d0ae0a077 1448 default:
dudmuck 0:8f0d0ae0a077 1449 break;
dudmuck 0:8f0d0ae0a077 1450 }
dudmuck 0:8f0d0ae0a077 1451 }
dudmuck 0:8f0d0ae0a077 1452
dudmuck 20:42839629a5dc 1453 void SX1276::OnDio1Irq( void )
dudmuck 20:42839629a5dc 1454 {
dudmuck 20:42839629a5dc 1455 flags.dio1 = 1;
dudmuck 20:42839629a5dc 1456 }
dudmuck 20:42839629a5dc 1457
dudmuck 0:8f0d0ae0a077 1458 void SX1276::OnDio2Irq( void )
dudmuck 0:8f0d0ae0a077 1459 {
dudmuck 0:8f0d0ae0a077 1460 switch( this->settings.State )
dudmuck 0:8f0d0ae0a077 1461 {
dudmuck 0:8f0d0ae0a077 1462 case RF_RX_RUNNING:
dudmuck 0:8f0d0ae0a077 1463 switch( this->settings.Modem )
dudmuck 0:8f0d0ae0a077 1464 {
dudmuck 0:8f0d0ae0a077 1465 case MODEM_FSK:
dudmuck 0:8f0d0ae0a077 1466 // Checks if DIO4 is connected. If it is not PreambleDtected is set to true.
dudmuck 0:8f0d0ae0a077 1467 if( this->dioIrq[4] == NULL )
dudmuck 0:8f0d0ae0a077 1468 {
dudmuck 0:8f0d0ae0a077 1469 this->settings.FskPacketHandler.PreambleDetected = true;
dudmuck 0:8f0d0ae0a077 1470 }
dudmuck 0:8f0d0ae0a077 1471
dudmuck 0:8f0d0ae0a077 1472 if( ( this->settings.FskPacketHandler.PreambleDetected == true ) && ( this->settings.FskPacketHandler.SyncWordDetected == false ) )
dudmuck 0:8f0d0ae0a077 1473 {
dudmuck 0:8f0d0ae0a077 1474 rxTimeoutSyncWord.detach( );
dudmuck 0:8f0d0ae0a077 1475
dudmuck 0:8f0d0ae0a077 1476 this->settings.FskPacketHandler.SyncWordDetected = true;
dudmuck 0:8f0d0ae0a077 1477
dudmuck 0:8f0d0ae0a077 1478 this->settings.FskPacketHandler.RssiValue = -( Read( REG_RSSIVALUE ) >> 1 );
dudmuck 0:8f0d0ae0a077 1479
dudmuck 0:8f0d0ae0a077 1480 this->settings.FskPacketHandler.AfcValue = ( int32_t )( double )( ( ( uint16_t )Read( REG_AFCMSB ) << 8 ) |
dudmuck 0:8f0d0ae0a077 1481 ( uint16_t )Read( REG_AFCLSB ) ) *
dudmuck 0:8f0d0ae0a077 1482 ( double )FREQ_STEP;
dudmuck 0:8f0d0ae0a077 1483 this->settings.FskPacketHandler.RxGain = ( Read( REG_LNA ) >> 5 ) & 0x07;
dudmuck 0:8f0d0ae0a077 1484 }
dudmuck 0:8f0d0ae0a077 1485 break;
dudmuck 0:8f0d0ae0a077 1486 case MODEM_LORA:
dudmuck 0:8f0d0ae0a077 1487 if( this->settings.LoRa.FreqHopOn == true )
dudmuck 0:8f0d0ae0a077 1488 {
dudmuck 0:8f0d0ae0a077 1489 // Clear Irq
dudmuck 0:8f0d0ae0a077 1490 Write( REG_LR_IRQFLAGS, RFLR_IRQFLAGS_FHSSCHANGEDCHANNEL );
dudmuck 0:8f0d0ae0a077 1491
dudmuck 0:8f0d0ae0a077 1492 if( ( this->RadioEvents != NULL ) && ( this->RadioEvents->FhssChangeChannel != NULL ) )
dudmuck 0:8f0d0ae0a077 1493 {
dudmuck 0:8f0d0ae0a077 1494 this->RadioEvents->FhssChangeChannel( ( Read( REG_LR_HOPCHANNEL ) & RFLR_HOPCHANNEL_CHANNEL_MASK ) );
dudmuck 0:8f0d0ae0a077 1495 }
dudmuck 0:8f0d0ae0a077 1496 }
dudmuck 0:8f0d0ae0a077 1497 break;
dudmuck 0:8f0d0ae0a077 1498 default:
dudmuck 0:8f0d0ae0a077 1499 break;
dudmuck 0:8f0d0ae0a077 1500 }
dudmuck 0:8f0d0ae0a077 1501 break;
dudmuck 0:8f0d0ae0a077 1502 case RF_TX_RUNNING:
dudmuck 0:8f0d0ae0a077 1503 switch( this->settings.Modem )
dudmuck 0:8f0d0ae0a077 1504 {
dudmuck 0:8f0d0ae0a077 1505 case MODEM_FSK:
dudmuck 0:8f0d0ae0a077 1506 break;
dudmuck 0:8f0d0ae0a077 1507 case MODEM_LORA:
dudmuck 0:8f0d0ae0a077 1508 if( this->settings.LoRa.FreqHopOn == true )
dudmuck 0:8f0d0ae0a077 1509 {
dudmuck 0:8f0d0ae0a077 1510 // Clear Irq
dudmuck 0:8f0d0ae0a077 1511 Write( REG_LR_IRQFLAGS, RFLR_IRQFLAGS_FHSSCHANGEDCHANNEL );
dudmuck 0:8f0d0ae0a077 1512
dudmuck 0:8f0d0ae0a077 1513 if( ( this->RadioEvents != NULL ) && ( this->RadioEvents->FhssChangeChannel != NULL ) )
dudmuck 0:8f0d0ae0a077 1514 {
dudmuck 0:8f0d0ae0a077 1515 this->RadioEvents->FhssChangeChannel( ( Read( REG_LR_HOPCHANNEL ) & RFLR_HOPCHANNEL_CHANNEL_MASK ) );
dudmuck 0:8f0d0ae0a077 1516 }
dudmuck 0:8f0d0ae0a077 1517 }
dudmuck 0:8f0d0ae0a077 1518 break;
dudmuck 0:8f0d0ae0a077 1519 default:
dudmuck 0:8f0d0ae0a077 1520 break;
dudmuck 0:8f0d0ae0a077 1521 }
dudmuck 0:8f0d0ae0a077 1522 break;
dudmuck 0:8f0d0ae0a077 1523 default:
dudmuck 0:8f0d0ae0a077 1524 break;
dudmuck 0:8f0d0ae0a077 1525 }
dudmuck 0:8f0d0ae0a077 1526 }
dudmuck 0:8f0d0ae0a077 1527
dudmuck 0:8f0d0ae0a077 1528 void SX1276::OnDio3Irq( void )
dudmuck 0:8f0d0ae0a077 1529 {
dudmuck 0:8f0d0ae0a077 1530 switch( this->settings.Modem )
dudmuck 0:8f0d0ae0a077 1531 {
dudmuck 0:8f0d0ae0a077 1532 case MODEM_FSK:
dudmuck 0:8f0d0ae0a077 1533 break;
dudmuck 0:8f0d0ae0a077 1534 case MODEM_LORA:
dudmuck 0:8f0d0ae0a077 1535 if( ( Read( REG_LR_IRQFLAGS ) & RFLR_IRQFLAGS_CADDETECTED ) == RFLR_IRQFLAGS_CADDETECTED )
dudmuck 0:8f0d0ae0a077 1536 {
dudmuck 0:8f0d0ae0a077 1537 // Clear Irq
dudmuck 0:8f0d0ae0a077 1538 Write( REG_LR_IRQFLAGS, RFLR_IRQFLAGS_CADDETECTED | RFLR_IRQFLAGS_CADDONE );
dudmuck 0:8f0d0ae0a077 1539 if( ( this->RadioEvents != NULL ) && ( this->RadioEvents->CadDone != NULL ) )
dudmuck 0:8f0d0ae0a077 1540 {
dudmuck 0:8f0d0ae0a077 1541 this->RadioEvents->CadDone( true );
dudmuck 0:8f0d0ae0a077 1542 }
dudmuck 0:8f0d0ae0a077 1543 }
dudmuck 0:8f0d0ae0a077 1544 else
dudmuck 0:8f0d0ae0a077 1545 {
dudmuck 0:8f0d0ae0a077 1546 // Clear Irq
dudmuck 0:8f0d0ae0a077 1547 Write( REG_LR_IRQFLAGS, RFLR_IRQFLAGS_CADDONE );
dudmuck 0:8f0d0ae0a077 1548 if( ( this->RadioEvents != NULL ) && ( this->RadioEvents->CadDone != NULL ) )
dudmuck 0:8f0d0ae0a077 1549 {
dudmuck 0:8f0d0ae0a077 1550 this->RadioEvents->CadDone( false );
dudmuck 0:8f0d0ae0a077 1551 }
dudmuck 0:8f0d0ae0a077 1552 }
dudmuck 0:8f0d0ae0a077 1553 break;
dudmuck 0:8f0d0ae0a077 1554 default:
dudmuck 0:8f0d0ae0a077 1555 break;
dudmuck 0:8f0d0ae0a077 1556 }
dudmuck 0:8f0d0ae0a077 1557 }
dudmuck 0:8f0d0ae0a077 1558
dudmuck 0:8f0d0ae0a077 1559 void SX1276::OnDio4Irq( void )
dudmuck 0:8f0d0ae0a077 1560 {
dudmuck 0:8f0d0ae0a077 1561 switch( this->settings.Modem )
dudmuck 0:8f0d0ae0a077 1562 {
dudmuck 0:8f0d0ae0a077 1563 case MODEM_FSK:
dudmuck 0:8f0d0ae0a077 1564 {
dudmuck 0:8f0d0ae0a077 1565 if( this->settings.FskPacketHandler.PreambleDetected == false )
dudmuck 0:8f0d0ae0a077 1566 {
dudmuck 0:8f0d0ae0a077 1567 this->settings.FskPacketHandler.PreambleDetected = true;
dudmuck 0:8f0d0ae0a077 1568 }
dudmuck 0:8f0d0ae0a077 1569 }
dudmuck 0:8f0d0ae0a077 1570 break;
dudmuck 0:8f0d0ae0a077 1571 case MODEM_LORA:
dudmuck 0:8f0d0ae0a077 1572 break;
dudmuck 0:8f0d0ae0a077 1573 default:
dudmuck 0:8f0d0ae0a077 1574 break;
dudmuck 0:8f0d0ae0a077 1575 }
dudmuck 0:8f0d0ae0a077 1576 }
dudmuck 0:8f0d0ae0a077 1577
dudmuck 0:8f0d0ae0a077 1578 void SX1276::OnDio5Irq( void )
dudmuck 0:8f0d0ae0a077 1579 {
dudmuck 0:8f0d0ae0a077 1580 switch( this->settings.Modem )
dudmuck 0:8f0d0ae0a077 1581 {
dudmuck 0:8f0d0ae0a077 1582 case MODEM_FSK:
dudmuck 0:8f0d0ae0a077 1583 break;
dudmuck 0:8f0d0ae0a077 1584 case MODEM_LORA:
dudmuck 0:8f0d0ae0a077 1585 break;
dudmuck 0:8f0d0ae0a077 1586 default:
dudmuck 0:8f0d0ae0a077 1587 break;
dudmuck 0:8f0d0ae0a077 1588 }
dudmuck 0:8f0d0ae0a077 1589 }
dudmuck 20:42839629a5dc 1590
dudmuck 20:42839629a5dc 1591 void SX1276::BottomHalf()
dudmuck 20:42839629a5dc 1592 {
dudmuck 20:42839629a5dc 1593 if (flags.dio0) {
dudmuck 20:42839629a5dc 1594 dio0_bh();
dudmuck 20:42839629a5dc 1595 flags.dio0 = 0;
dudmuck 20:42839629a5dc 1596 }
dudmuck 20:42839629a5dc 1597
dudmuck 20:42839629a5dc 1598 if (flags.dio1) {
dudmuck 20:42839629a5dc 1599 dio1_bh();
dudmuck 20:42839629a5dc 1600 flags.dio1 = 0;
dudmuck 20:42839629a5dc 1601 }
dudmuck 20:42839629a5dc 1602 }
dudmuck 3:aead8f8fdc1f 1603 #endif /* ENABLE_SX1276 */