SX1276GenericLib to support sx1276 bassed LoRa modules, including HopeRF RFM95, Murata CMWX1ZZABZ and Semtech SX1276MB1MAS/SX1276MB1LAS modules

Dependents:   DISCO-L072CZ-LRWAN1_LoRa_PingPong DISCO-L072CZ-LRWAN1_LoRa_PingPong DISCO-L072CZ-LRWAN1_LoRa_PingPong DISCO-L072CZ-LRWAN1_LoRa_USB_Rx ... more

Fork of SX1276Lib by Semtech

Committer:
mluis
Date:
Thu Nov 26 10:39:03 2015 +0000
Revision:
21:2e496deb7858
Parent:
20:e05596ba4166
Child:
22:7f3aab69cca9
Made radio driver API compatible with GitHub radio driver

Who changed what in which revision?

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