From e9ca7792eb032e424b41f194e064c440c0770c17 Mon Sep 17 00:00:00 2001 From: geeksville Date: Thu, 30 Apr 2020 17:43:29 -0700 Subject: [PATCH] new RF95 driver is written --- src/rf95/RF95Interface.cpp | 132 +++++++++++++++++++++++++++++++++ src/rf95/RF95Interface.h | 50 +++++++++++++ src/rf95/RadioLibInterface.cpp | 8 +- src/rf95/RadioLibInterface.h | 4 +- src/rf95/SX1262Interface.cpp | 10 +-- src/rf95/SX1262Interface.h | 3 + 6 files changed, 195 insertions(+), 12 deletions(-) create mode 100644 src/rf95/RF95Interface.cpp create mode 100644 src/rf95/RF95Interface.h diff --git a/src/rf95/RF95Interface.cpp b/src/rf95/RF95Interface.cpp new file mode 100644 index 00000000..61508844 --- /dev/null +++ b/src/rf95/RF95Interface.cpp @@ -0,0 +1,132 @@ +#include "RF95Interface.h" +#include "MeshRadio.h" // kinda yucky, but we need to know which region we are in + +#include + +RF95Interface::RF95Interface(RADIOLIB_PIN_TYPE cs, RADIOLIB_PIN_TYPE irq, RADIOLIB_PIN_TYPE rst, SPIClass &spi) + : RadioLibInterface(cs, irq, rst, 0, spi) +{ + // FIXME - we assume devices never get destroyed +} + +/// Initialise the Driver transport hardware and software. +/// Make sure the Driver is properly configured before calling init(). +/// \return true if initialisation succeeded. +bool RF95Interface::init() +{ + // FIXME, move this to main + SPI.begin(); + + applyModemConfig(); + if (power > 20) // This chip has lower power limits than some + power = 20; + + int res; + /** + * We do a nasty check on freq range to figure our RFM96 vs RFM95 + */ + if (CH0 < 500.0) { + auto dev = new RFM96(&module); + lora = dev; + res = dev->begin(freq, bw, sf, cr, syncWord, power, currentLimit, preambleLength); + } else { + auto dev = new RFM95(&module); + lora = dev; + res = dev->begin(freq, bw, sf, cr, syncWord, power, currentLimit, preambleLength); + } + + DEBUG_MSG("LORA init result %d\n", res); + + if (res == ERR_NONE) + res = lora->setCRC(SX126X_LORA_CRC_ON); + + if (res == ERR_NONE) + startReceive(); // start receiving + + return res == ERR_NONE; +} + +bool RF95Interface::reconfigure() +{ + applyModemConfig(); + + // set mode to standby + setStandby(); + + // configure publicly accessible settings + int err = lora->setSpreadingFactor(sf); + assert(err == ERR_NONE); + + err = lora->setBandwidth(bw); + assert(err == ERR_NONE); + + err = lora->setCodingRate(cr); + assert(err == ERR_NONE); + + err = lora->setSyncWord(syncWord); + assert(err == ERR_NONE); + + err = lora->setCurrentLimit(currentLimit); + assert(err == ERR_NONE); + + err = lora->setPreambleLength(preambleLength); + assert(err == ERR_NONE); + + err = lora->setFrequency(freq); + assert(err == ERR_NONE); + + if (power > 20) // This chip has lower power limits than some + power = 20; + err = lora->setOutputPower(power); + assert(err == ERR_NONE); + + startReceive(); // restart receiving + + return ERR_NONE; +} + +void RF95Interface::setStandby() +{ + int err = lora->standby(); + assert(err == ERR_NONE); + + isReceiving = false; // If we were receiving, not any more + completeSending(); // If we were sending, not anymore + disableInterrupt(); +} + +void RF95Interface::startReceive() +{ + setStandby(); + int err = lora->startReceive(); + assert(err == ERR_NONE); + + isReceiving = true; + + // Must be done AFTER, starting transmit, because startTransmit clears (possibly stale) interrupt pending register bits + enableInterrupt(isrRxLevel0); +} + +/** Could we send right now (i.e. either not actively receving or transmitting)? */ +bool RF95Interface::canSendImmediately() +{ + // We wait _if_ we are partially though receiving a packet (rather than just merely waiting for one). + // To do otherwise would be doubly bad because not only would we drop the packet that was on the way in, + // we almost certainly guarantee no one outside will like the packet we are sending. + bool busyTx = sendingPacket != NULL; + bool busyRx = isReceiving && lora->getPacketLength() > 0; + + if (busyTx || busyRx) + DEBUG_MSG("Can not set now, busyTx=%d, busyRx=%d\n", busyTx, busyRx); + + return !busyTx && !busyRx; +} + +bool RF95Interface::sleep() +{ + // put chipset into sleep mode + disableInterrupt(); + lora->sleep(); + + return true; +} \ No newline at end of file diff --git a/src/rf95/RF95Interface.h b/src/rf95/RF95Interface.h new file mode 100644 index 00000000..4210f9ac --- /dev/null +++ b/src/rf95/RF95Interface.h @@ -0,0 +1,50 @@ +#pragma once + +#include "MeshRadio.h" // kinda yucky, but we need to know which region we are in +#include "RadioLibInterface.h" + +/** + * Our new not radiohead adapter for RF95 style radios + */ +class RF95Interface : public RadioLibInterface +{ + SX1278 *lora; // Either a RFM95 or RFM96 depending on what was stuffed on this board + + public: + RF95Interface(RADIOLIB_PIN_TYPE cs, RADIOLIB_PIN_TYPE irq, RADIOLIB_PIN_TYPE rst, SPIClass &spi); + + /// Initialise the Driver transport hardware and software. + /// Make sure the Driver is properly configured before calling init(). + /// \return true if initialisation succeeded. + virtual bool init(); + + /// Apply any radio provisioning changes + /// Make sure the Driver is properly configured before calling init(). + /// \return true if initialisation succeeded. + virtual bool reconfigure(); + + /// Prepare hardware for sleep. Call this _only_ for deep sleep, not needed for light sleep. + virtual bool sleep(); + + protected: + /** + * Glue functions called from ISR land + */ + virtual void INTERRUPT_ATTR disableInterrupt() { lora->clearDio0Action(); } + + /** + * Enable a particular ISR callback glue function + */ + virtual void enableInterrupt(void (*callback)()) { lora->setDio0Action(callback); } + + /** Could we send right now (i.e. either not actively receiving or transmitting)? */ + virtual bool canSendImmediately(); + + /** + * Start waiting to receive a message + */ + virtual void startReceive(); + + private: + void setStandby(); +}; \ No newline at end of file diff --git a/src/rf95/RadioLibInterface.cpp b/src/rf95/RadioLibInterface.cpp index dab0a124..655788a8 100644 --- a/src/rf95/RadioLibInterface.cpp +++ b/src/rf95/RadioLibInterface.cpp @@ -11,7 +11,7 @@ static SPISettings spiSettings(4000000, MSBFIRST, SPI_MODE0); RadioLibInterface::RadioLibInterface(RADIOLIB_PIN_TYPE cs, RADIOLIB_PIN_TYPE irq, RADIOLIB_PIN_TYPE rst, RADIOLIB_PIN_TYPE busy, SPIClass &spi, PhysicalLayer *_iface) - : module(cs, irq, rst, busy, spi, spiSettings), iface(*_iface) + : module(cs, irq, rst, busy, spi, spiSettings), iface(_iface) { assert(!instance); // We assume only one for now instance = this; @@ -156,9 +156,9 @@ void RadioLibInterface::handleReceiveInterrupt() DEBUG_MSG("handling lora RX interrupt\n"); // read the number of actually received bytes - size_t length = iface.getPacketLength(); + size_t length = iface->getPacketLength(); - int state = iface.readData(radiobuf, length); + int state = iface->readData(radiobuf, length); if (state != ERR_NONE) { DEBUG_MSG("ignoring received packet due to error=%d\n", state); rxBad++; @@ -207,7 +207,7 @@ void RadioLibInterface::startSend(MeshPacket *txp) { size_t numbytes = beginSending(txp); - int res = iface.startTransmit(radiobuf, numbytes); + int res = iface->startTransmit(radiobuf, numbytes); assert(res == ERR_NONE); // Must be done AFTER, starting transmit, because startTransmit clears (possibly stale) interrupt pending register bits diff --git a/src/rf95/RadioLibInterface.h b/src/rf95/RadioLibInterface.h index f0e9e01b..653869e8 100644 --- a/src/rf95/RadioLibInterface.h +++ b/src/rf95/RadioLibInterface.h @@ -52,7 +52,7 @@ class RadioLibInterface : public RadioInterface /** * provides lowest common denominator RadioLib API */ - PhysicalLayer &iface; + PhysicalLayer *iface; /// are _trying_ to receive a packet currently (note - we might just be waiting for one) bool isReceiving; @@ -69,7 +69,7 @@ class RadioLibInterface : public RadioInterface public: RadioLibInterface(RADIOLIB_PIN_TYPE cs, RADIOLIB_PIN_TYPE irq, RADIOLIB_PIN_TYPE rst, RADIOLIB_PIN_TYPE busy, SPIClass &spi, - PhysicalLayer *iface); + PhysicalLayer *iface = NULL); virtual ErrorCode send(MeshPacket *p); diff --git a/src/rf95/SX1262Interface.cpp b/src/rf95/SX1262Interface.cpp index 6a1bf851..aca0ac55 100644 --- a/src/rf95/SX1262Interface.cpp +++ b/src/rf95/SX1262Interface.cpp @@ -109,13 +109,11 @@ bool SX1262Interface::canSendImmediately() return !busyTx && !busyRx; } - - bool SX1262Interface::sleep() { - // we no longer care about interrupts from this device - // prepareDeepSleep(); + // put chipset into sleep mode + disableInterrupt(); + lora.sleep(); - // FIXME - put chipset into sleep mode - return false; + return true; } \ No newline at end of file diff --git a/src/rf95/SX1262Interface.h b/src/rf95/SX1262Interface.h index 8f1ed514..88a25187 100644 --- a/src/rf95/SX1262Interface.h +++ b/src/rf95/SX1262Interface.h @@ -2,6 +2,9 @@ #include "RadioLibInterface.h" +/** + * Our adapter for SX1262 radios + */ class SX1262Interface : public RadioLibInterface { SX1262 lora;