This is code is part of a Technion course project in advanced IoT, implementing a device to read and transmit sensors data from a Formula racing car built by students at Technion - Israel Institute of Technology.

Dependencies:   mbed Buffer

Fork of DISCO-L072CZ-LRWAN1_LoRa_PingPong by ST

This is code is part of a Technion course project in advanced IoT, implementing a device to read and transmit sensors data from a Formula racing car built by students at Technion - Israel Institute of Technology.

How to install

  • Create an account on Mbed: https://os.mbed.com/account/signup/
  • Import project into Compiler
  • In the Program Workspace select "Formula_Nucleo_Reader"
  • Select a Platform like so:
  1. Click button at top-left
  2. Add Board
  3. Search "B-L072Z-LRWAN1" and then "Add to your Mbed Compiler"
  • Finally click "Compile", if the build was successful, the binary would download automatically
  • To install it on device simply plug it in to a PC, open device drive and drag then drop binary file in it
Committer:
wardm
Date:
Sat May 19 11:41:10 2018 +0000
Revision:
12:02d779e8c4f6
Code for Technion Formula car sensors reader transmit

Who changed what in which revision?

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