2020-04-29 21:54:03 +00:00
|
|
|
#pragma once
|
|
|
|
|
|
|
|
#include "RadioInterface.h"
|
|
|
|
|
|
|
|
#include <RadioLib.h>
|
|
|
|
|
2020-04-30 16:44:16 +00:00
|
|
|
// ESP32 has special rules about ISR code
|
|
|
|
#ifdef ARDUINO_ARCH_ESP32
|
|
|
|
#define INTERRUPT_ATTR IRAM_ATTR
|
|
|
|
#else
|
|
|
|
#define INTERRUPT_ATTR
|
|
|
|
#endif
|
|
|
|
|
2020-04-29 21:54:03 +00:00
|
|
|
class RadioLibInterface : public RadioInterface
|
|
|
|
{
|
2020-05-01 19:11:04 +00:00
|
|
|
/// Used as our notification from the ISR
|
2020-05-02 15:29:51 +00:00
|
|
|
enum PendingISR { ISR_NONE = 0, ISR_RX, ISR_TX, TRANSMIT_DELAY_COMPLETED };
|
2020-04-30 16:44:16 +00:00
|
|
|
|
2020-04-30 22:43:41 +00:00
|
|
|
volatile PendingISR pending = ISR_NONE;
|
2020-05-02 15:29:51 +00:00
|
|
|
volatile bool timerRunning = false;
|
2020-04-30 16:44:16 +00:00
|
|
|
|
|
|
|
/** Our ISR code currently needs this to find our active instance
|
|
|
|
*/
|
|
|
|
static RadioLibInterface *instance;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Raw ISR handler that just calls our polymorphic method
|
|
|
|
*/
|
2020-05-02 15:29:51 +00:00
|
|
|
static void isrTxLevel0(), isrLevel0Common(PendingISR code);
|
2020-04-30 16:44:16 +00:00
|
|
|
|
2020-04-30 22:43:41 +00:00
|
|
|
/**
|
|
|
|
* Debugging counts
|
|
|
|
*/
|
|
|
|
uint32_t rxBad = 0, rxGood = 0, txGood = 0;
|
|
|
|
|
2020-04-29 23:28:11 +00:00
|
|
|
protected:
|
|
|
|
float bw = 125;
|
|
|
|
uint8_t sf = 9;
|
|
|
|
uint8_t cr = 7;
|
2020-04-30 01:46:32 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* FIXME, use a meshtastic sync word, but hashed with the Channel name. Currently picking the same default
|
|
|
|
* the RF95 used (0x14). Note: do not use 0x34 - that is reserved for lorawan
|
|
|
|
*/
|
|
|
|
uint8_t syncWord = SX126X_SYNC_WORD_PRIVATE;
|
|
|
|
|
2020-05-02 15:29:51 +00:00
|
|
|
float currentLimit = 100; // FIXME
|
|
|
|
uint16_t preambleLength = 32; // 8 is default, but FIXME use longer to increase the amount of sleep time when receiving
|
2020-04-29 23:28:11 +00:00
|
|
|
|
2020-04-29 21:54:03 +00:00
|
|
|
Module module; // The HW interface to the radio
|
2020-04-29 23:28:11 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* provides lowest common denominator RadioLib API
|
|
|
|
*/
|
2020-05-01 00:43:29 +00:00
|
|
|
PhysicalLayer *iface;
|
2020-04-29 21:54:03 +00:00
|
|
|
|
2020-04-30 20:50:40 +00:00
|
|
|
/// are _trying_ to receive a packet currently (note - we might just be waiting for one)
|
|
|
|
bool isReceiving;
|
|
|
|
|
2020-04-30 16:44:16 +00:00
|
|
|
/**
|
|
|
|
* Glue functions called from ISR land
|
|
|
|
*/
|
|
|
|
virtual void disableInterrupt() = 0;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Enable a particular ISR callback glue function
|
|
|
|
*/
|
|
|
|
virtual void enableInterrupt(void (*)()) = 0;
|
|
|
|
|
2020-04-29 21:54:03 +00:00
|
|
|
public:
|
2020-04-30 01:46:32 +00:00
|
|
|
RadioLibInterface(RADIOLIB_PIN_TYPE cs, RADIOLIB_PIN_TYPE irq, RADIOLIB_PIN_TYPE rst, RADIOLIB_PIN_TYPE busy, SPIClass &spi,
|
2020-05-01 00:43:29 +00:00
|
|
|
PhysicalLayer *iface = NULL);
|
2020-04-29 21:54:03 +00:00
|
|
|
|
|
|
|
virtual ErrorCode send(MeshPacket *p);
|
|
|
|
|
2020-04-30 22:50:07 +00:00
|
|
|
/**
|
|
|
|
* Return true if we think the board can go to sleep (i.e. our tx queue is empty, we are not sending or receiving)
|
|
|
|
*
|
|
|
|
* This method must be used before putting the CPU into deep or light sleep.
|
|
|
|
*/
|
|
|
|
virtual bool canSleep();
|
|
|
|
|
2020-04-30 19:37:58 +00:00
|
|
|
private:
|
|
|
|
/** start an immediate transmit */
|
|
|
|
void startSend(MeshPacket *txp);
|
|
|
|
|
2020-05-02 15:29:51 +00:00
|
|
|
/** if we have something waiting to send, start a short random timer so we can come check for collision before actually doing
|
2020-05-03 02:51:25 +00:00
|
|
|
* the transmit
|
|
|
|
*
|
2020-05-02 15:29:51 +00:00
|
|
|
* If the timer was already running, we just wait for that one to occur.
|
|
|
|
* */
|
|
|
|
void startTransmitTimer(bool withDelay = true);
|
2020-04-30 19:37:58 +00:00
|
|
|
|
|
|
|
void handleTransmitInterrupt();
|
|
|
|
void handleReceiveInterrupt();
|
|
|
|
|
2020-05-02 15:29:51 +00:00
|
|
|
static void timerCallback(void *p1, uint32_t p2);
|
|
|
|
|
2020-04-30 01:46:32 +00:00
|
|
|
protected:
|
|
|
|
/**
|
|
|
|
* Convert our modemConfig enum into wf, sf, etc...
|
|
|
|
*/
|
|
|
|
void applyModemConfig();
|
2020-04-30 16:44:16 +00:00
|
|
|
|
|
|
|
/** Could we send right now (i.e. either not actively receiving or transmitting)? */
|
2020-05-03 02:51:25 +00:00
|
|
|
virtual bool canSendImmediately();
|
2020-05-01 15:32:16 +00:00
|
|
|
|
|
|
|
/** are we actively receiving a packet (only called during receiving state) */
|
|
|
|
virtual bool isActivelyReceiving() = 0;
|
2020-04-30 16:44:16 +00:00
|
|
|
|
2020-04-30 19:37:58 +00:00
|
|
|
/**
|
|
|
|
* Start waiting to receive a message
|
|
|
|
*/
|
|
|
|
virtual void startReceive() = 0;
|
2020-04-30 16:44:16 +00:00
|
|
|
|
2020-04-30 19:37:58 +00:00
|
|
|
/**
|
|
|
|
* Raw ISR handler that just calls our polymorphic method
|
|
|
|
*/
|
|
|
|
static void isrRxLevel0();
|
2020-04-30 20:50:40 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* If a send was in progress finish it and return the buffer to the pool */
|
|
|
|
void completeSending();
|
2020-05-01 02:58:10 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Add SNR data to received messages
|
|
|
|
*/
|
|
|
|
virtual void addReceiveMetadata(MeshPacket *mp) = 0;
|
2020-05-01 19:11:04 +00:00
|
|
|
|
|
|
|
virtual void loop(); // Idle processing
|
2020-05-03 02:51:25 +00:00
|
|
|
|
|
|
|
virtual void setStandby() = 0;
|
2020-04-29 21:54:03 +00:00
|
|
|
};
|