David Rimer / RadioHead-148
Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers RH_RF95.cpp Source File

RH_RF95.cpp

00001 // RH_RF22.cpp
00002 //
00003 // Copyright (C) 2011 Mike McCauley
00004 // $Id: RH_RF95.cpp,v 1.8 2015/08/12 23:18:51 mikem Exp $
00005 
00006 #include <RH_RF95.h>
00007 
00008 // Interrupt vectors for the 3 Arduino interrupt pins
00009 // Each interrupt can be handled by a different instance of RH_RF95, allowing you to have
00010 // 2 or more LORAs per Arduino
00011 RH_RF95* RH_RF95::_deviceForInterrupt[RH_RF95_NUM_INTERRUPTS] = {0, 0, 0};
00012 uint8_t RH_RF95::_interruptCount = 0; // Index into _deviceForInterrupt for next device
00013 
00014 // These are indexed by the values of ModemConfigChoice
00015 // Stored in flash (program) memory to save SRAM
00016 PROGMEM static const RH_RF95::ModemConfig MODEM_CONFIG_TABLE[] =
00017 {
00018     //  1d,     1e,      26
00019     { 0x72,   0x74,    0x00}, // Bw125Cr45Sf128 (the chip default)
00020     { 0x92,   0x74,    0x00}, // Bw500Cr45Sf128
00021     { 0x48,   0x94,    0x00}, // Bw31_25Cr48Sf512
00022     { 0x78,   0xc4,    0x00}, // Bw125Cr48Sf4096
00023     
00024 };
00025 
00026 RH_RF95::RH_RF95(PINS slaveSelectPin, PINS interruptPin, RHGenericSPI& spi)
00027     :
00028     RHSPIDriver(slaveSelectPin, spi),
00029     _rxBufValid(0),
00030     _interruptPin(interruptPin)
00031 {
00032     _myInterruptIndex = 0xff; // Not allocated yet
00033 }
00034 
00035 bool RH_RF95::init()
00036 {
00037     if (!RHSPIDriver::init())
00038     return false;
00039 
00040 #if (RH_PLATFORM != RH_PLATFORM_MBED)
00041     // Determine the interrupt number that corresponds to the interruptPin
00042     int interruptNumber = digitalPinToInterrupt(_interruptPin);
00043     if (interruptNumber == NOT_AN_INTERRUPT)
00044     return false;
00045 #endif
00046 
00047     // No way to check the device type :-(
00048     
00049     // Set sleep mode, so we can also set LORA mode:
00050     spiWrite(RH_RF95_REG_01_OP_MODE, RH_RF95_MODE_SLEEP | RH_RF95_LONG_RANGE_MODE);
00051     delay(10); // Wait for sleep mode to take over from say, CAD
00052     // Check we are in sleep mode, with LORA set
00053     if (spiRead(RH_RF95_REG_01_OP_MODE) != (RH_RF95_MODE_SLEEP | RH_RF95_LONG_RANGE_MODE))
00054     {
00055 //  Serial.println(spiRead(RH_RF95_REG_01_OP_MODE), HEX);
00056     return false; // No device present?
00057     }
00058 
00059 #if (RH_PLATFORM != RH_PLATFORM_MBED)
00060     // Add by Adrien van den Bossche <vandenbo@univ-tlse2.fr> for Teensy
00061     // ARM M4 requires the below. else pin interrupt doesn't work properly.
00062     // On all other platforms, its innocuous, belt and braces
00063     pinMode(_interruptPin, INPUT); 
00064 #endif
00065 
00066     // Set up interrupt handler
00067     // Since there are a limited number of interrupt glue functions isr*() available,
00068     // we can only support a limited number of devices simultaneously
00069     // ON some devices, notably most Arduinos, the interrupt pin passed in is actuallt the 
00070     // interrupt number. You have to figure out the interruptnumber-to-interruptpin mapping
00071     // yourself based on knwledge of what Arduino board you are running on.
00072     if (_myInterruptIndex == 0xff)
00073     {
00074     // First run, no interrupt allocated yet
00075     if (_interruptCount <= RH_RF95_NUM_INTERRUPTS)
00076         _myInterruptIndex = _interruptCount++;
00077     else
00078         return false; // Too many devices, not enough interrupt vectors
00079     }
00080     _deviceForInterrupt[_myInterruptIndex] = this;
00081     
00082 #if (RH_PLATFORM == RH_PLATFORM_MBED)
00083     if (_myInterruptIndex == 0)
00084         _interruptPin.rise(&isr0);
00085     else if (_myInterruptIndex == 1)
00086         _interruptPin.rise(&isr1);
00087     else if (_myInterruptIndex == 2)
00088         _interruptPin.rise(&isr2);
00089     else
00090     return false; // Too many devices, not enough interrupt vectors
00091 #else
00092     if (_myInterruptIndex == 0)
00093     attachInterrupt(interruptNumber, isr0, RISING);
00094     else if (_myInterruptIndex == 1)
00095     attachInterrupt(interruptNumber, isr1, RISING);
00096     else if (_myInterruptIndex == 2)
00097     attachInterrupt(interruptNumber, isr2, RISING);
00098     else
00099     return false; // Too many devices, not enough interrupt vectors
00100 #endif
00101     // Set up FIFO
00102     // We configure so that we can use the entire 256 byte FIFO for either receive
00103     // or transmit, but not both at the same time
00104     spiWrite(RH_RF95_REG_0E_FIFO_TX_BASE_ADDR, 0);
00105     spiWrite(RH_RF95_REG_0F_FIFO_RX_BASE_ADDR, 0);
00106 
00107     // Packet format is preamble + explicit-header + payload + crc
00108     // Explicit Header Mode
00109     // payload is TO + FROM + ID + FLAGS + message data
00110     // RX mode is implmented with RXCONTINUOUS
00111     // max message data length is 255 - 4 = 251 octets
00112 
00113     setModeIdle();
00114 
00115     // Set up default configuration
00116     // No Sync Words in LORA mode.
00117     setModemConfig(Bw125Cr45Sf128); // Radio default
00118 //    setModemConfig(Bw125Cr48Sf4096); // slow and reliable?
00119     setPreambleLength(8); // Default is 8
00120     // An innocuous ISM frequency, same as RF22's
00121     setFrequency(434.0);
00122     // Lowish power
00123     setTxPower(13);
00124 
00125     return true;
00126 }
00127 
00128 // C++ level interrupt handler for this instance
00129 // LORA is unusual in that it has several interrupt lines, and not a single, combined one.
00130 // On MiniWirelessLoRa, only one of the several interrupt lines (DI0) from the RFM95 is usefuly 
00131 // connnected to the processor.
00132 // We use this to get RxDone and TxDone interrupts
00133 void RH_RF95::handleInterrupt()
00134 {
00135     // Read the interrupt register
00136     uint8_t irq_flags = spiRead(RH_RF95_REG_12_IRQ_FLAGS);
00137     if (_mode == RHModeRx && irq_flags & (RH_RF95_RX_TIMEOUT | RH_RF95_PAYLOAD_CRC_ERROR))
00138     {
00139     _rxBad++;
00140     }
00141     else if (_mode == RHModeRx && irq_flags & RH_RF95_RX_DONE)
00142     {
00143     // Have received a packet
00144     uint8_t len = spiRead(RH_RF95_REG_13_RX_NB_BYTES);
00145 
00146     // Reset the fifo read ptr to the beginning of the packet
00147     spiWrite(RH_RF95_REG_0D_FIFO_ADDR_PTR, spiRead(RH_RF95_REG_10_FIFO_RX_CURRENT_ADDR));
00148     spiBurstRead(RH_RF95_REG_00_FIFO, _buf, len);
00149     _bufLen = len;
00150     spiWrite(RH_RF95_REG_12_IRQ_FLAGS, 0xff); // Clear all IRQ flags
00151 
00152     // Remember the RSSI of this packet
00153     // this is according to the doc, but is it really correct?
00154     // weakest receiveable signals are reported RSSI at about -66
00155     _lastRssi = spiRead(RH_RF95_REG_1A_PKT_RSSI_VALUE) - 137;
00156 
00157     // We have received a message.
00158     validateRxBuf(); 
00159     if (_rxBufValid)
00160         setModeIdle(); // Got one 
00161     }
00162     else if (_mode == RHModeTx && irq_flags & RH_RF95_TX_DONE)
00163     {
00164     _txGood++;
00165     setModeIdle();
00166     }
00167     
00168     spiWrite(RH_RF95_REG_12_IRQ_FLAGS, 0xff); // Clear all IRQ flags
00169 }
00170 
00171 // These are low level functions that call the interrupt handler for the correct
00172 // instance of RH_RF95.
00173 // 3 interrupts allows us to have 3 different devices
00174 void RH_RF95::isr0()
00175 {
00176     if (_deviceForInterrupt[0])
00177     _deviceForInterrupt[0]->handleInterrupt();
00178 }
00179 void RH_RF95::isr1()
00180 {
00181     if (_deviceForInterrupt[1])
00182     _deviceForInterrupt[1]->handleInterrupt();
00183 }
00184 void RH_RF95::isr2()
00185 {
00186     if (_deviceForInterrupt[2])
00187     _deviceForInterrupt[2]->handleInterrupt();
00188 }
00189 
00190 // Check whether the latest received message is complete and uncorrupted
00191 void RH_RF95::validateRxBuf()
00192 {
00193     if (_bufLen < 4)
00194     return; // Too short to be a real message
00195     // Extract the 4 headers
00196     _rxHeaderTo    = _buf[0];
00197     _rxHeaderFrom  = _buf[1];
00198     _rxHeaderId    = _buf[2];
00199     _rxHeaderFlags = _buf[3];
00200     if (_promiscuous ||
00201     _rxHeaderTo == _thisAddress ||
00202     _rxHeaderTo == RH_BROADCAST_ADDRESS)
00203     {
00204     _rxGood++;
00205     _rxBufValid = true;
00206     }
00207 }
00208 
00209 bool RH_RF95::available()
00210 {
00211     if (_mode == RHModeTx)
00212     return false;
00213     setModeRx();
00214     return _rxBufValid; // Will be set by the interrupt handler when a good message is received
00215 }
00216 
00217 void RH_RF95::clearRxBuf()
00218 {
00219     ATOMIC_BLOCK_START;
00220     _rxBufValid = false;
00221     _bufLen = 0;
00222     ATOMIC_BLOCK_END;
00223 }
00224 
00225 bool RH_RF95::recv(uint8_t* buf, uint8_t* len)
00226 {
00227     if (!available())
00228     return false;
00229     if (buf && len)
00230     {
00231     ATOMIC_BLOCK_START;
00232     // Skip the 4 headers that are at the beginning of the rxBuf
00233     if (*len > _bufLen-RH_RF95_HEADER_LEN)
00234         *len = _bufLen-RH_RF95_HEADER_LEN;
00235     memcpy(buf, _buf+RH_RF95_HEADER_LEN, *len);
00236     ATOMIC_BLOCK_END;
00237     }
00238     clearRxBuf(); // This message accepted and cleared
00239     return true;
00240 }
00241 
00242 bool RH_RF95::send(const uint8_t* data, uint8_t len)
00243 {
00244     if (len > RH_RF95_MAX_MESSAGE_LEN)
00245     return false;
00246 
00247     waitPacketSent(); // Make sure we dont interrupt an outgoing message
00248     setModeIdle();
00249 
00250     // Position at the beginning of the FIFO
00251     spiWrite(RH_RF95_REG_0D_FIFO_ADDR_PTR, 0);
00252     // The headers
00253     spiWrite(RH_RF95_REG_00_FIFO, _txHeaderTo);
00254     spiWrite(RH_RF95_REG_00_FIFO, _txHeaderFrom);
00255     spiWrite(RH_RF95_REG_00_FIFO, _txHeaderId);
00256     spiWrite(RH_RF95_REG_00_FIFO, _txHeaderFlags);
00257     // The message data
00258     spiBurstWrite(RH_RF95_REG_00_FIFO, data, len);
00259     spiWrite(RH_RF95_REG_22_PAYLOAD_LENGTH, len + RH_RF95_HEADER_LEN);
00260 
00261     setModeTx(); // Start the transmitter
00262     // when Tx is done, interruptHandler will fire and radio mode will return to STANDBY
00263     return true;
00264 }
00265 
00266 bool RH_RF95::printRegisters()
00267 {
00268 #ifdef RH_HAVE_SERIAL
00269     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};
00270 
00271     uint8_t i;
00272     for (i = 0; i < sizeof(registers); i++)
00273     {
00274     Serial.print(registers[i], HEX);
00275     Serial.print(": ");
00276     Serial.println(spiRead(registers[i]), HEX);
00277     }
00278 #endif
00279     return true;
00280 }
00281 
00282 uint8_t RH_RF95::maxMessageLength()
00283 {
00284     return RH_RF95_MAX_MESSAGE_LEN;
00285 }
00286 
00287 bool RH_RF95::setFrequency(float centre)
00288 {
00289     // Frf = FRF / FSTEP
00290     uint32_t frf = (centre * 1000000.0) / RH_RF95_FSTEP;
00291     spiWrite(RH_RF95_REG_06_FRF_MSB, (frf >> 16) & 0xff);
00292     spiWrite(RH_RF95_REG_07_FRF_MID, (frf >> 8) & 0xff);
00293     spiWrite(RH_RF95_REG_08_FRF_LSB, frf & 0xff);
00294 
00295     return true;
00296 }
00297 
00298 void RH_RF95::setModeIdle()
00299 {
00300     if (_mode != RHModeIdle)
00301     {
00302     spiWrite(RH_RF95_REG_01_OP_MODE, RH_RF95_MODE_STDBY);
00303     _mode = RHModeIdle;
00304     }
00305 }
00306 
00307 bool RH_RF95::sleep()
00308 {
00309     if (_mode != RHModeSleep)
00310     {
00311     spiWrite(RH_RF95_REG_01_OP_MODE, RH_RF95_MODE_SLEEP);
00312     _mode = RHModeSleep;
00313     }
00314     return true;
00315 }
00316 
00317 void RH_RF95::setModeRx()
00318 {
00319     if (_mode != RHModeRx)
00320     {
00321     spiWrite(RH_RF95_REG_01_OP_MODE, RH_RF95_MODE_RXCONTINUOUS);
00322     spiWrite(RH_RF95_REG_40_DIO_MAPPING1, 0x00); // Interrupt on RxDone
00323     _mode = RHModeRx;
00324     }
00325 }
00326 
00327 void RH_RF95::setModeTx()
00328 {
00329     if (_mode != RHModeTx)
00330     {
00331     spiWrite(RH_RF95_REG_01_OP_MODE, RH_RF95_MODE_TX);
00332     spiWrite(RH_RF95_REG_40_DIO_MAPPING1, 0x40); // Interrupt on TxDone
00333     _mode = RHModeTx;
00334     }
00335 }
00336 
00337 void RH_RF95::setTxPower(int8_t power)
00338 {
00339     if (power > 23)
00340     power = 23;
00341     if (power < 5)
00342     power = 5;
00343 
00344     // For RH_RF95_PA_DAC_ENABLE, manual says '+20dBm on PA_BOOST when OutputPower=0xf'
00345     // RH_RF95_PA_DAC_ENABLE actually adds about 3dBm to all power levels. We will us it
00346     // for 21, 22 and 23dBm
00347     if (power > 20)
00348     {
00349     spiWrite(RH_RF95_REG_4D_PA_DAC, RH_RF95_PA_DAC_ENABLE);
00350     power -= 3;
00351     }
00352     else
00353     {
00354     spiWrite(RH_RF95_REG_4D_PA_DAC, RH_RF95_PA_DAC_DISABLE);
00355     }
00356 
00357     // RFM95/96/97/98 does not have RFO pins connected to anything. Only PA_BOOST
00358     // pin is connected, so must use PA_BOOST
00359     // Pout = 2 + OutputPower.
00360     // The documentation is pretty confusing on this topic: PaSelect says the max power is 20dBm,
00361     // but OutputPower claims it would be 17dBm.
00362     // My measurements show 20dBm is correct
00363     spiWrite(RH_RF95_REG_09_PA_CONFIG, RH_RF95_PA_SELECT | (power-5));
00364 }
00365 
00366 // Sets registers from a canned modem configuration structure
00367 void RH_RF95::setModemRegisters(const ModemConfig* config)
00368 {
00369     spiWrite(RH_RF95_REG_1D_MODEM_CONFIG1,       config->reg_1d);
00370     spiWrite(RH_RF95_REG_1E_MODEM_CONFIG2,       config->reg_1e);
00371     spiWrite(RH_RF95_REG_26_MODEM_CONFIG3,       config->reg_26);
00372 }
00373 
00374 // Set one of the canned FSK Modem configs
00375 // Returns true if its a valid choice
00376 bool RH_RF95::setModemConfig(ModemConfigChoice index)
00377 {
00378     if (index > (signed int)(sizeof(MODEM_CONFIG_TABLE) / sizeof(ModemConfig)))
00379         return false;
00380 
00381     ModemConfig cfg;
00382     memcpy_P(&cfg, &MODEM_CONFIG_TABLE[index], sizeof(RH_RF95::ModemConfig));
00383     setModemRegisters(&cfg);
00384 
00385     return true;
00386 }
00387 
00388 void RH_RF95::setPreambleLength(uint16_t bytes)
00389 {
00390     spiWrite(RH_RF95_REG_20_PREAMBLE_MSB, bytes >> 8);
00391     spiWrite(RH_RF95_REG_21_PREAMBLE_LSB, bytes & 0xff);
00392 }
00393