RadioHead

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers RH_RF95.cpp Source File

RH_RF95.cpp

00001 // RH_RF95.cpp
00002 //
00003 // Copyright (C) 2011 Mike McCauley
00004 // $Id: RH_RF95.cpp,v 1.14 2017/03/04 00:59:41 mikem Exp $
00005 //
00006 // Ported to mbed - support only a single radio - Dan Julio - 5/2017 
00007 //
00008 
00009 #include <RH_RF95.h>
00010 
00011 // These are indexed by the values of ModemConfigChoice
00012 // Stored in flash (program) memory to save SRAM
00013 static const RH_RF95::ModemConfig MODEM_CONFIG_TABLE[] =
00014 {
00015     //  1d,     1e,      26
00016     { 0x72,   0x74,    0x00}, // Bw125Cr45Sf128 (the chip default)
00017     { 0x92,   0x74,    0x00}, // Bw500Cr45Sf128
00018     { 0x48,   0x94,    0x00}, // Bw31_25Cr48Sf512
00019     { 0x78,   0xc4,    0x00}, // Bw125Cr48Sf4096
00020     
00021 };
00022 
00023 RH_RF95::RH_RF95(swspi& spi, int ssNum)
00024     :
00025     _spi(spi),
00026     _ssn(ssNum),
00027     _rxBufValid(0)
00028 {
00029 }
00030 
00031 bool RH_RF95::init()
00032 {
00033     // Set sleep mode, so we can also set LORA mode:
00034     _spi.spiWrite(RH_RF95_REG_01_OP_MODE, RH_RF95_MODE_SLEEP | RH_RF95_LONG_RANGE_MODE, 0, _ssn);
00035     wait_ms(10); // Wait for sleep mode to take over from say, CAD
00036     // Check we are in sleep mode, with LORA set
00037     if (_spi.spiRead(RH_RF95_REG_01_OP_MODE, 0, _ssn) != (RH_RF95_MODE_SLEEP | RH_RF95_LONG_RANGE_MODE))
00038     {
00039 //        printf("REG_01_OP_MODE: 0x%2x\n", _spi.spiRead(RH_RF95_REG_01_OP_MODE, 0, _ssn));
00040         return false; // No device present?
00041     }
00042 
00043     // Set up FIFO
00044     // We configure so that we can use the entire 256 byte FIFO for either receive
00045     // or transmit, but not both at the same time
00046     _spi.spiWrite(RH_RF95_REG_0E_FIFO_TX_BASE_ADDR, 0, 0, _ssn);
00047     _spi.spiWrite(RH_RF95_REG_0F_FIFO_RX_BASE_ADDR, 0, 0, _ssn);
00048 
00049     // Packet format is preamble + explicit-header + payload + crc
00050     // Explicit Header Mode
00051     // payload is TO + FROM + ID + FLAGS + message data
00052     // RX mode is implmented with RXCONTINUOUS
00053     // max message data length is 255 - 4 = 251 octets
00054 
00055     setModeIdle();
00056 
00057     // Set up default configuration
00058     // No Sync Words in LORA mode.
00059     setModemConfig(Bw125Cr45Sf128); // Radio default
00060 //    setModemConfig(Bw125Cr48Sf4096); // slow and reliable?
00061     setPreambleLength(8); // Default is 8
00062     // An innocuous ISM frequency, same as RF22's
00063     setFrequency(434.0);
00064     // Lowish power
00065     setTxPower(13);
00066 
00067     return true;
00068 }
00069 
00070 // C++ level interrupt handler for this instance
00071 // LORA is unusual in that it has several interrupt lines, and not a single, combined one.
00072 // On MiniWirelessLoRa, only one of the several interrupt lines (DI0) from the RFM95 is usefuly 
00073 // connnected to the processor.
00074 // We use this to get RxDone and TxDone interrupts
00075 void RH_RF95::handleInterrupt()
00076 {
00077     // Read the interrupt register
00078     uint8_t irq_flags = _spi.spiRead(RH_RF95_REG_12_IRQ_FLAGS, 0, _ssn);
00079     if (_mode == RHModeRx && irq_flags & (RH_RF95_RX_TIMEOUT | RH_RF95_PAYLOAD_CRC_ERROR))
00080     {
00081         _rxBad++;
00082     }
00083     else if (_mode == RHModeRx && irq_flags & RH_RF95_RX_DONE)
00084     {
00085     // Have received a packet
00086     uint8_t len = _spi.spiRead(RH_RF95_REG_13_RX_NB_BYTES, 0, _ssn);
00087 
00088     // Reset the fifo read ptr to the beginning of the packet
00089     _spi.spiWrite(RH_RF95_REG_0D_FIFO_ADDR_PTR, _spi.spiRead(RH_RF95_REG_10_FIFO_RX_CURRENT_ADDR, 0, _ssn), 0, _ssn);
00090     _spi.spiBurstRead(RH_RF95_REG_00_FIFO, _buf, len, 0, _ssn);
00091     _bufLen = len;
00092     _spi.spiWrite(RH_RF95_REG_12_IRQ_FLAGS, 0xff, 0, _ssn); // Clear all IRQ flags
00093 
00094     // Remember the last signal to noise ratio, LORA mode
00095     // Per page 111, SX1276/77/78/79 datasheet
00096     _lastSNR = (int8_t)_spi.spiRead(RH_RF95_REG_19_PKT_SNR_VALUE, 0, _ssn) / 4;
00097 
00098     // Remember the RSSI of this packet, LORA mode
00099     // this is according to the doc, but is it really correct?
00100     // weakest receiveable signals are reported RSSI at about -66
00101     _lastRssi = _spi.spiRead(RH_RF95_REG_1A_PKT_RSSI_VALUE, 0, _ssn);
00102     // Adjust the RSSI, datasheet page 87
00103     if (_lastSNR < 0)
00104         _lastRssi = _lastRssi + _lastSNR;
00105     else
00106         _lastRssi = (int)_lastRssi * 16 / 15;
00107     if (_usingHFport)
00108         _lastRssi -= 157;
00109     else
00110         _lastRssi -= 164;
00111         
00112     // We have received a message.
00113     validateRxBuf(); 
00114     if (_rxBufValid)
00115         setModeIdle(); // Got one 
00116     }
00117     else if (_mode == RHModeTx && irq_flags & RH_RF95_TX_DONE)
00118     {
00119         _txGood++;
00120         setModeIdle();
00121     }
00122     else if (_mode == RHModeCad && irq_flags & RH_RF95_CAD_DONE)
00123     {
00124         _cad = irq_flags & RH_RF95_CAD_DETECTED;
00125         setModeIdle();
00126     }
00127     
00128     _spi.spiWrite(RH_RF95_REG_12_IRQ_FLAGS, 0xff, 0, _ssn); // Clear all IRQ flags
00129 }
00130 
00131 // Check whether the latest received message is complete and uncorrupted
00132 void RH_RF95::validateRxBuf()
00133 {
00134     if (_bufLen < 4)
00135         return; // Too short to be a real message
00136     
00137     // Extract the 4 headers
00138     _rxHeaderTo    = _buf[0];
00139     _rxHeaderFrom  = _buf[1];
00140     _rxHeaderId    = _buf[2];
00141     _rxHeaderFlags = _buf[3];
00142     if (_promiscuous ||
00143       _rxHeaderTo == _thisAddress ||
00144       _rxHeaderTo == RH_BROADCAST_ADDRESS)
00145     {
00146         _rxGood++;
00147         _rxBufValid = true;
00148     }
00149 }
00150 
00151 bool RH_RF95::available()
00152 {
00153     if (_mode == RHModeTx)
00154         return false;
00155     
00156     setModeRx();
00157     return _rxBufValid; // Will be set by the interrupt handler when a good message is received
00158 }
00159 
00160 void RH_RF95::clearRxBuf()
00161 {
00162     _rxBufValid = false;
00163     _bufLen = 0;
00164 }
00165 
00166 bool RH_RF95::recv(uint8_t* buf, uint8_t* len)
00167 {
00168     if (!available())
00169         return false;
00170     
00171     if (buf && len)
00172     {
00173         // Skip the 4 headers that are at the beginning of the rxBuf
00174         if (*len > _bufLen-RH_RF95_HEADER_LEN)
00175             *len = _bufLen-RH_RF95_HEADER_LEN;
00176         memcpy(buf, _buf+RH_RF95_HEADER_LEN, *len);
00177     }
00178     clearRxBuf(); // This message accepted and cleared
00179     return true;
00180 }
00181 
00182 bool RH_RF95::send(const uint8_t* data, uint8_t len)
00183 {
00184     if (len > RH_RF95_MAX_MESSAGE_LEN)
00185         return false;
00186 
00187     waitPacketSent(); // Make sure we dont interrupt an outgoing message
00188     setModeIdle();
00189 
00190     if (!waitCAD()) 
00191         return false;  // Check channel activity
00192 
00193     // Position at the beginning of the FIFO
00194     _spi.spiWrite(RH_RF95_REG_0D_FIFO_ADDR_PTR, 0, 0, _ssn);
00195     // The headers
00196     _spi.spiWrite(RH_RF95_REG_00_FIFO, _txHeaderTo, 0, _ssn);
00197     _spi.spiWrite(RH_RF95_REG_00_FIFO, _txHeaderFrom, 0, _ssn);
00198     _spi.spiWrite(RH_RF95_REG_00_FIFO, _txHeaderId, 0, _ssn);
00199     _spi.spiWrite(RH_RF95_REG_00_FIFO, _txHeaderFlags, 0, _ssn);
00200     // The message data
00201     _spi.spiBurstWrite(RH_RF95_REG_00_FIFO, data, len, 0, _ssn);
00202     _spi.spiWrite(RH_RF95_REG_22_PAYLOAD_LENGTH, len + RH_RF95_HEADER_LEN, 0, _ssn);
00203 
00204     setModeTx(); // Start the transmitter
00205     // when Tx is done, interruptHandler will fire and radio mode will return to STANDBY
00206     return true;
00207 }
00208 
00209 bool RH_RF95::printRegisters()
00210 {
00211     uint8_t registers[] = { 0x01, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x014, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27};
00212 
00213     uint8_t i;
00214     for (i = 0; i < sizeof(registers); i++)
00215     {
00216         printf("0x%x: 0x%x\n\r", registers[i], _spi.spiRead(registers[i], 0, _ssn));
00217     }
00218     return true;
00219 }
00220 
00221 uint8_t RH_RF95::maxMessageLength()
00222 {
00223     return RH_RF95_MAX_MESSAGE_LEN;
00224 }
00225 
00226 bool RH_RF95::setFrequency(float centre)
00227 {
00228     // Frf = FRF / FSTEP
00229     uint32_t frf = (centre * 1000000.0f) / RH_RF95_FSTEP;
00230     _spi.spiWrite(RH_RF95_REG_06_FRF_MSB, (frf >> 16) & 0xff, 0, _ssn);
00231     _spi.spiWrite(RH_RF95_REG_07_FRF_MID, (frf >> 8) & 0xff, 0, _ssn);
00232     _spi.spiWrite(RH_RF95_REG_08_FRF_LSB, frf & 0xff, 0, _ssn);
00233     _usingHFport = (centre >= 779.0f);
00234 
00235     return true;
00236 }
00237 
00238 void RH_RF95::setModeIdle()
00239 {
00240     if (_mode != RHModeIdle)
00241     {
00242         _spi.spiWrite(RH_RF95_REG_01_OP_MODE, RH_RF95_MODE_STDBY, 0, _ssn);
00243         _mode = RHModeIdle;
00244     }
00245 }
00246 
00247 bool RH_RF95::sleep()
00248 {
00249     if (_mode != RHModeSleep)
00250     {
00251         _spi.spiWrite(RH_RF95_REG_01_OP_MODE, RH_RF95_MODE_SLEEP, 0, _ssn);
00252         _mode = RHModeSleep;
00253     }
00254     return true;
00255 }
00256 
00257 void RH_RF95::setModeRx()
00258 {
00259     if (_mode != RHModeRx)
00260     {
00261         _spi.spiWrite(RH_RF95_REG_01_OP_MODE, RH_RF95_MODE_RXCONTINUOUS, 0, _ssn);
00262         _spi.spiWrite(RH_RF95_REG_40_DIO_MAPPING1, 0x00, 0, _ssn); // Interrupt on RxDone
00263         _mode = RHModeRx;
00264     }
00265 }
00266 
00267 void RH_RF95::setModeTx()
00268 {
00269     if (_mode != RHModeTx)
00270     {
00271         _spi.spiWrite(RH_RF95_REG_01_OP_MODE, RH_RF95_MODE_TX, 0, _ssn);
00272         _spi.spiWrite(RH_RF95_REG_40_DIO_MAPPING1, 0x40, 0, _ssn); // Interrupt on TxDone
00273         _mode = RHModeTx;
00274     }
00275 }
00276 
00277 void RH_RF95::setTxPower(int8_t power, bool useRFO)
00278 {
00279     // Sigh, different behaviours depending on whther the module use PA_BOOST or the RFO pin
00280     // for the transmitter output
00281     if (useRFO)
00282     {
00283         if (power > 14)
00284             power = 14;
00285         if (power < -1)
00286             power = -1;
00287         _spi.spiWrite(RH_RF95_REG_09_PA_CONFIG, RH_RF95_MAX_POWER | (power + 1), 0, _ssn);
00288     }
00289     else
00290     {
00291         if (power > 23)
00292             power = 23;
00293         if (power < 5)
00294             power = 5;
00295 
00296         // For RH_RF95_PA_DAC_ENABLE, manual says '+20dBm on PA_BOOST when OutputPower=0xf'
00297         // RH_RF95_PA_DAC_ENABLE actually adds about 3dBm to all power levels. We will us it
00298         // for 21, 22 and 23dBm
00299         if (power > 20)
00300         {
00301             _spi.spiWrite(RH_RF95_REG_4D_PA_DAC, RH_RF95_PA_DAC_ENABLE, 0, _ssn);
00302             power -= 3;
00303         }
00304         else
00305         {
00306             _spi.spiWrite(RH_RF95_REG_4D_PA_DAC, RH_RF95_PA_DAC_DISABLE, 0, _ssn);
00307         }
00308 
00309         // RFM95/96/97/98 does not have RFO pins connected to anything. Only PA_BOOST
00310         // pin is connected, so must use PA_BOOST
00311         // Pout = 2 + OutputPower.
00312         // The documentation is pretty confusing on this topic: PaSelect says the max power is 20dBm,
00313         // but OutputPower claims it would be 17dBm.
00314         // My measurements show 20dBm is correct
00315         _spi.spiWrite(RH_RF95_REG_09_PA_CONFIG, RH_RF95_PA_SELECT | (power-5), 0, _ssn);
00316     }
00317 }
00318 
00319 // Sets registers from a canned modem configuration structure
00320 void RH_RF95::setModemRegisters(const ModemConfig* config)
00321 {
00322     _spi.spiWrite(RH_RF95_REG_1D_MODEM_CONFIG1,       config->reg_1d, 0, _ssn);
00323     _spi.spiWrite(RH_RF95_REG_1E_MODEM_CONFIG2,       config->reg_1e, 0, _ssn);
00324     _spi.spiWrite(RH_RF95_REG_26_MODEM_CONFIG3,       config->reg_26, 0, _ssn);
00325 }
00326 
00327 // Set one of the canned FSK Modem configs
00328 // Returns true if its a valid choice
00329 bool RH_RF95::setModemConfig(ModemConfigChoice index)
00330 {
00331     if (index > (signed int)(sizeof(MODEM_CONFIG_TABLE) / sizeof(ModemConfig)))
00332         return false;
00333 
00334     ModemConfig cfg;
00335     memcpy(&cfg, &MODEM_CONFIG_TABLE[index], sizeof(RH_RF95::ModemConfig));
00336     setModemRegisters(&cfg);
00337 
00338     return true;
00339 }
00340 
00341 void RH_RF95::setPreambleLength(uint16_t bytes)
00342 {
00343     _spi.spiWrite(RH_RF95_REG_20_PREAMBLE_MSB, bytes >> 8, 0, _ssn);
00344     _spi.spiWrite(RH_RF95_REG_21_PREAMBLE_LSB, bytes & 0xff, 0, _ssn);
00345 }
00346 
00347 bool RH_RF95::isChannelActive()
00348 {
00349     // Set mode RHModeCad
00350     if (_mode != RHModeCad)
00351     {
00352         _spi.spiWrite(RH_RF95_REG_01_OP_MODE, RH_RF95_MODE_CAD, 0, _ssn);
00353         _spi.spiWrite(RH_RF95_REG_40_DIO_MAPPING1, 0x80, 0, _ssn); // Interrupt on CadDone
00354         _mode = RHModeCad;
00355     }
00356 
00357     while (_mode == RHModeCad)
00358         Thread::yield();
00359 
00360     return _cad;
00361 }
00362 
00363 void RH_RF95::enableTCXO()
00364 {
00365     while ((_spi.spiRead(RH_RF95_REG_4B_TCXO, 0, _ssn) & RH_RF95_TCXO_TCXO_INPUT_ON) != RH_RF95_TCXO_TCXO_INPUT_ON)
00366     {
00367         sleep();
00368         _spi.spiWrite(RH_RF95_REG_4B_TCXO, (_spi.spiRead(RH_RF95_REG_4B_TCXO, 0, _ssn) | RH_RF95_TCXO_TCXO_INPUT_ON), 0, _ssn);
00369     } 
00370 }
00371 
00372 // From section 4.1.5 of SX1276/77/78/79
00373 // Ferror = FreqError * 2**24 * BW / Fxtal / 500
00374 int RH_RF95::frequencyError()
00375 {
00376     int32_t freqerror = 0;
00377 
00378     // Convert 2.5 bytes (5 nibbles, 20 bits) to 32 bit signed int
00379     freqerror = _spi.spiRead(RH_RF95_REG_28_FEI_MSB, 0, _ssn) << 16;
00380     freqerror |= _spi.spiRead(RH_RF95_REG_29_FEI_MID, 0, _ssn) << 8;
00381     freqerror |= _spi.spiRead(RH_RF95_REG_2A_FEI_LSB, 0, _ssn);
00382     // Sign extension into top 3 nibbles
00383     if (freqerror & 0x80000)
00384         freqerror |= 0xfff00000;
00385 
00386     int error = 0; // In hertz
00387     float bw_tab[] = {7.8, 10.4, 15.6, 20.8, 31.25, 41.7, 62.5, 125, 250, 500};
00388     uint8_t bwindex = _spi.spiRead(RH_RF95_REG_1D_MODEM_CONFIG1, 0, _ssn) >> 4;
00389     if (bwindex < (sizeof(bw_tab) / sizeof(float)))
00390         error = (float)freqerror * bw_tab[bwindex] * ((float)(1L << 24) / (float)RH_RF95_FXOSC / 500.0f);
00391     // else not defined
00392 
00393     return error;
00394 }
00395 
00396 int RH_RF95::lastSNR()
00397 {
00398     return _lastSNR;
00399 }