mirror of
https://github.com/meshtastic/firmware.git
synced 2025-04-24 17:32:18 +00:00
the mountain of changes needed to kinda make tx work compiles.
This commit is contained in:
parent
074ac33b8a
commit
fce31560c6
@ -47,6 +47,9 @@ Needed to be fully functional at least at the same level of the ESP32 boards. At
|
||||
|
||||
## Items to be 'feature complete'
|
||||
|
||||
- figure out what the correct current limit should be for the sx1262, currently we just use the default 100
|
||||
- use SX126x::startReceiveDutyCycleAuto to save power by sleeping and briefly waking to check for preamble bits. Change xmit rules to have more preamble bits.
|
||||
- put sx1262 in sleepmode when processor gets shutdown (or rebooted), ideally even for critical faults (to keep power draw low). repurpose deepsleep state for this.
|
||||
- good power management tips: https://devzone.nordicsemi.com/nordic/nordic-blog/b/blog/posts/optimizing-power-on-nrf52-designs
|
||||
- call PMU set_ADC_CONV(0) during sleep, to stop reading PMU adcs and decrease current draw
|
||||
- do final power measurements
|
||||
|
@ -7,11 +7,7 @@
|
||||
|
||||
#ifdef RF95_IRQ_GPIO
|
||||
|
||||
/// A temporary buffer used for sending/receving packets, sized to hold the biggest buffer we might need
|
||||
#define MAX_RHPACKETLEN 251
|
||||
static uint8_t radiobuf[MAX_RHPACKETLEN];
|
||||
|
||||
CustomRF95::CustomRF95() : RH_RF95(NSS_GPIO, RF95_IRQ_GPIO), txQueue(MAX_TX_QUEUE) {}
|
||||
CustomRF95::CustomRF95() : RH_RF95(NSS_GPIO, RF95_IRQ_GPIO) {}
|
||||
|
||||
bool CustomRF95::canSleep()
|
||||
{
|
||||
@ -52,13 +48,11 @@ ErrorCode CustomRF95::send(MeshPacket *p)
|
||||
// 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.
|
||||
if (_mode == RHModeIdle || (_mode == RHModeRx && !isReceiving())) {
|
||||
if (_mode == RHModeIdle || !isReceiving()) {
|
||||
// if the radio is idle, we can send right away
|
||||
DEBUG_MSG("immediate send on mesh fr=0x%x,to=0x%x,id=%d\n (txGood=%d,rxGood=%d,rxBad=%d)\n", p->from, p->to, p->id,
|
||||
txGood(), rxGood(), rxBad());
|
||||
|
||||
waitPacketSent(); // Make sure we dont interrupt an outgoing message
|
||||
|
||||
if (!waitCAD())
|
||||
return false; // Check channel activity
|
||||
|
||||
@ -159,29 +153,20 @@ void CustomRF95::handleIdleISR()
|
||||
/// This routine might be called either from user space or ISR
|
||||
void CustomRF95::startSend(MeshPacket *txp)
|
||||
{
|
||||
assert(!sendingPacket);
|
||||
|
||||
// DEBUG_MSG("sending queued packet on mesh (txGood=%d,rxGood=%d,rxBad=%d)\n", rf95.txGood(), rf95.rxGood(), rf95.rxBad());
|
||||
assert(txp->has_payload);
|
||||
|
||||
lastTxStart = millis();
|
||||
|
||||
size_t numbytes = pb_encode_to_bytes(radiobuf, sizeof(radiobuf), SubPacket_fields, &txp->payload);
|
||||
|
||||
sendingPacket = txp;
|
||||
size_t numbytes = beginSending(txp);
|
||||
|
||||
setHeaderTo(txp->to);
|
||||
setHeaderId(txp->id);
|
||||
|
||||
// if the sender nodenum is zero, that means uninitialized
|
||||
assert(txp->from);
|
||||
setHeaderFrom(txp->from); // We must do this before each send, because we might have just changed our nodenum
|
||||
|
||||
assert(numbytes <= 251); // Make sure we don't overflow the tiny max packet size
|
||||
|
||||
// uint32_t start = millis(); // FIXME, store this in the class
|
||||
|
||||
int res = RH_RF95::send(radiobuf, numbytes);
|
||||
// This legacy implementation doesn't use our inserted packet header
|
||||
int res = RH_RF95::send(radiobuf + sizeof(PacketHeader), numbytes - sizeof(PacketHeader));
|
||||
assert(res);
|
||||
}
|
||||
|
||||
|
@ -13,10 +13,6 @@ class CustomRF95 : public RH_RF95, public RadioInterface
|
||||
{
|
||||
friend class MeshRadio; // for debugging we let that class touch pool
|
||||
|
||||
PointerQueue<MeshPacket> txQueue;
|
||||
|
||||
uint32_t lastTxStart = 0L;
|
||||
|
||||
public:
|
||||
/** pool is the pool we will alloc our rx packets from
|
||||
* rxDest is where we will send any rx packets, it becomes receivers responsibility to return packet to the pool
|
||||
|
@ -6,7 +6,10 @@
|
||||
#include <pb_decode.h>
|
||||
#include <pb_encode.h>
|
||||
|
||||
RadioInterface::RadioInterface() {}
|
||||
RadioInterface::RadioInterface() : txQueue(MAX_TX_QUEUE)
|
||||
{
|
||||
assert(sizeof(PacketHeader) == 4); // make sure the compiler did what we expected
|
||||
}
|
||||
|
||||
ErrorCode SimRadio::send(MeshPacket *p)
|
||||
{
|
||||
@ -21,3 +24,32 @@ void RadioInterface::deliverToReceiver(MeshPacket *p)
|
||||
assert(rxDest->enqueue(p, 0)); // NOWAIT - fixme, if queue is full, delete older messages
|
||||
}
|
||||
|
||||
/***
|
||||
* given a packet set sendingPacket and decode the protobufs into radiobuf. Returns # of payload bytes to send
|
||||
*/
|
||||
size_t RadioInterface::beginSending(MeshPacket *p)
|
||||
{
|
||||
assert(!sendingPacket);
|
||||
|
||||
// DEBUG_MSG("sending queued packet on mesh (txGood=%d,rxGood=%d,rxBad=%d)\n", rf95.txGood(), rf95.rxGood(), rf95.rxBad());
|
||||
assert(p->has_payload);
|
||||
|
||||
lastTxStart = millis();
|
||||
|
||||
PacketHeader *h = (PacketHeader *)radiobuf;
|
||||
|
||||
h->from = p->from;
|
||||
h->to = p->to;
|
||||
h->flags = 0;
|
||||
h->id = p->id;
|
||||
|
||||
// if the sender nodenum is zero, that means uninitialized
|
||||
assert(h->from);
|
||||
|
||||
size_t numbytes = pb_encode_to_bytes(radiobuf + sizeof(PacketHeader), sizeof(radiobuf), SubPacket_fields, &p->payload) + sizeof(PacketHeader);
|
||||
|
||||
assert(numbytes <= MAX_RHPACKETLEN);
|
||||
|
||||
sendingPacket = p;
|
||||
return numbytes;
|
||||
}
|
@ -8,6 +8,18 @@
|
||||
|
||||
#define MAX_TX_QUEUE 16 // max number of packets which can be waiting for transmission
|
||||
|
||||
#define MAX_RHPACKETLEN 256
|
||||
|
||||
/**
|
||||
* This structure has to exactly match the wire layout when sent over the radio link. Used to keep compatibility
|
||||
* wtih the old radiohead implementation.
|
||||
*/
|
||||
typedef struct {
|
||||
uint8_t to, from, id, flags;
|
||||
} PacketHeader;
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Basic operations all radio chipsets must implement.
|
||||
*
|
||||
@ -20,6 +32,13 @@ class RadioInterface
|
||||
|
||||
protected:
|
||||
MeshPacket *sendingPacket = NULL; // The packet we are currently sending
|
||||
PointerQueue<MeshPacket> txQueue;
|
||||
uint32_t lastTxStart = 0L;
|
||||
|
||||
/**
|
||||
* A temporary buffer used for sending/receving packets, sized to hold the biggest buffer we might need
|
||||
* */
|
||||
uint8_t radiobuf[MAX_RHPACKETLEN];
|
||||
|
||||
/**
|
||||
* Enqueue a received packet for the registered receiver
|
||||
@ -82,6 +101,14 @@ class RadioInterface
|
||||
/// Make sure the Driver is properly configured before calling init().
|
||||
/// \return true if initialisation succeeded.
|
||||
virtual bool reconfigure() = 0;
|
||||
|
||||
protected:
|
||||
/***
|
||||
* given a packet set sendingPacket and decode the protobufs into radiobuf. Returns # of bytes to send (including the PacketHeader & payload).
|
||||
*
|
||||
* Used as the first step of
|
||||
*/
|
||||
size_t beginSending(MeshPacket *p);
|
||||
};
|
||||
|
||||
class SimRadio : public RadioInterface
|
||||
|
@ -8,8 +8,26 @@ RadioLibInterface::RadioLibInterface(RADIOLIB_PIN_TYPE cs, RADIOLIB_PIN_TYPE irq
|
||||
SPIClass &spi, PhysicalLayer *_iface)
|
||||
: module(cs, irq, rst, busy, spi, spiSettings), iface(*_iface)
|
||||
{
|
||||
assert(!instance); // We assume only one for now
|
||||
instance = this;
|
||||
}
|
||||
|
||||
void INTERRUPT_ATTR RadioLibInterface::isrRxLevel0()
|
||||
{
|
||||
instance->pending = ISR_RX;
|
||||
instance->disableInterrupt();
|
||||
}
|
||||
|
||||
void INTERRUPT_ATTR RadioLibInterface::isrTxLevel0()
|
||||
{
|
||||
instance->pending = ISR_TX;
|
||||
instance->disableInterrupt();
|
||||
}
|
||||
|
||||
/** Our ISR code currently needs this to find our active instance
|
||||
*/
|
||||
RadioLibInterface *RadioLibInterface::instance;
|
||||
|
||||
/**
|
||||
* Convert our modemConfig enum into wf, sf, etc...
|
||||
*/
|
||||
@ -41,9 +59,144 @@ void RadioLibInterface::applyModemConfig()
|
||||
}
|
||||
}
|
||||
|
||||
/// Send a packet (possibly by enquing in a private fifo). This routine will
|
||||
/// later free() the packet to pool. This routine is not allowed to stall because it is called from
|
||||
/// bluetooth comms code. If the txmit queue is empty it might return an error
|
||||
ErrorCode RadioLibInterface::send(MeshPacket *p)
|
||||
{
|
||||
return ERR_NONE;
|
||||
// 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.
|
||||
if (canSendImmediately()) {
|
||||
// if the radio is idle, we can send right away
|
||||
DEBUG_MSG("immediate send on mesh fr=0x%x,to=0x%x,id=%d\n (txGood=%d,rxGood=%d,rxBad=%d)\n", p->from, p->to, p->id, -1,
|
||||
-1, -1);
|
||||
|
||||
startSend(p);
|
||||
return ERRNO_OK;
|
||||
} else {
|
||||
DEBUG_MSG("enqueuing packet for send from=0x%x, to=0x%x\n", p->from, p->to);
|
||||
ErrorCode res = txQueue.enqueue(p, 0) ? ERRNO_OK : ERRNO_UNKNOWN;
|
||||
|
||||
if (res != ERRNO_OK) // we weren't able to queue it, so we must drop it to prevent leaks
|
||||
packetPool.release(p);
|
||||
|
||||
return res;
|
||||
}
|
||||
}
|
||||
|
||||
void RadioLibInterface::loop()
|
||||
{
|
||||
PendingISR wasPending = pending; // atomic read
|
||||
if (wasPending) {
|
||||
pending = ISR_NONE; // If the flag was set, it is _guaranteed_ the ISR won't be running, because it masked itself
|
||||
|
||||
if (wasPending == ISR_TX)
|
||||
handleTransmitInterrupt();
|
||||
else if (wasPending == ISR_RX)
|
||||
handleReceiveInterrupt();
|
||||
else
|
||||
assert(0);
|
||||
|
||||
// First send any outgoing packets we have ready
|
||||
MeshPacket *txp = txQueue.dequeuePtr(0);
|
||||
if (txp)
|
||||
startSend(txp);
|
||||
else {
|
||||
// Nothing to send, let's switch back to receive mode
|
||||
// FIXME - RH_RF95::setModeRx();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void RadioLibInterface::handleTransmitInterrupt()
|
||||
{
|
||||
assert(sendingPacket); // Were we sending?
|
||||
|
||||
// FIXME - check result code from ISR
|
||||
|
||||
// We are done sending that packet, release it
|
||||
packetPool.release(sendingPacket);
|
||||
sendingPacket = NULL;
|
||||
// DEBUG_MSG("Done with send\n");
|
||||
}
|
||||
|
||||
void RadioLibInterface::handleReceiveInterrupt()
|
||||
{
|
||||
// FIXME
|
||||
}
|
||||
|
||||
#if 0
|
||||
// After doing standard behavior, check to see if a new packet arrived or one was sent and start a new send or receive as
|
||||
// necessary
|
||||
void CustomRF95::handleInterrupt()
|
||||
{
|
||||
RH_RF95::handleInterrupt();
|
||||
enableInterrupt(); // Let ISR run again
|
||||
|
||||
if (_mode == RHModeIdle) // We are now done sending or receiving
|
||||
{
|
||||
|
||||
// If we just finished receiving a packet, forward it into a queue
|
||||
if (_rxBufValid) {
|
||||
// We received a packet
|
||||
|
||||
// Skip the 4 headers that are at the beginning of the rxBuf
|
||||
size_t payloadLen = _bufLen - RH_RF95_HEADER_LEN;
|
||||
uint8_t *payload = _buf + RH_RF95_HEADER_LEN;
|
||||
|
||||
// FIXME - throws exception if called in ISR context: frequencyError() - probably the floating point math
|
||||
int32_t freqerr = -1, snr = lastSNR();
|
||||
// DEBUG_MSG("Received packet from mesh src=0x%x,dest=0x%x,id=%d,len=%d rxGood=%d,rxBad=%d,freqErr=%d,snr=%d\n",
|
||||
// srcaddr, destaddr, id, rxlen, rf95.rxGood(), rf95.rxBad(), freqerr, snr);
|
||||
|
||||
MeshPacket *mp = packetPool.allocZeroed();
|
||||
|
||||
SubPacket *p = &mp->payload;
|
||||
|
||||
mp->from = _rxHeaderFrom;
|
||||
mp->to = _rxHeaderTo;
|
||||
mp->id = _rxHeaderId;
|
||||
|
||||
//_rxHeaderId = _buf[2];
|
||||
//_rxHeaderFlags = _buf[3];
|
||||
|
||||
// If we already have an entry in the DB for this nodenum, goahead and hide the snr/freqerr info there.
|
||||
// Note: we can't create it at this point, because it might be a bogus User node allocation. But odds are we will
|
||||
// already have a record we can hide this debugging info in.
|
||||
NodeInfo *info = nodeDB.getNode(mp->from);
|
||||
if (info) {
|
||||
info->snr = snr;
|
||||
info->frequency_error = freqerr;
|
||||
}
|
||||
|
||||
if (!pb_decode_from_bytes(payload, payloadLen, SubPacket_fields, p)) {
|
||||
packetPool.release(mp);
|
||||
} else {
|
||||
// parsing was successful, queue for our recipient
|
||||
mp->has_payload = true;
|
||||
|
||||
deliverToReceiver(mp);
|
||||
}
|
||||
|
||||
clearRxBuf(); // This message accepted and cleared
|
||||
}
|
||||
|
||||
handleIdleISR();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/** start an immediate transmit */
|
||||
void RadioLibInterface::startSend(MeshPacket *txp)
|
||||
{
|
||||
size_t numbytes = beginSending(txp);
|
||||
|
||||
int res = iface.startTransmit(radiobuf, numbytes);
|
||||
assert(res);
|
||||
|
||||
// Must be done AFTER, starting transmit, because startTransmit clears (possibly stale) interrupt pending register bits
|
||||
enableInterrupt(isrTxLevel0);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -53,39 +206,178 @@ ErrorCode RadioLibInterface::send(MeshPacket *p)
|
||||
// include the library
|
||||
|
||||
|
||||
// save transmission state between loops
|
||||
int transmissionState = ERR_NONE;
|
||||
|
||||
void loop() {
|
||||
Serial.print(F("[SX1262] Transmitting packet ... "));
|
||||
void setup() {
|
||||
Serial.begin(9600);
|
||||
|
||||
// initialize SX1262 with default settings
|
||||
Serial.print(F("[SX1262] Initializing ... "));
|
||||
// carrier frequency: 434.0 MHz
|
||||
// bandwidth: 125.0 kHz
|
||||
// spreading factor: 9
|
||||
// coding rate: 7
|
||||
// sync word: 0x12 (private network)
|
||||
// output power: 14 dBm
|
||||
// current limit: 60 mA
|
||||
// preamble length: 8 symbols
|
||||
// TCXO voltage: 1.6 V (set to 0 to not use TCXO)
|
||||
// regulator: DC-DC (set to true to use LDO)
|
||||
// CRC: enabled
|
||||
int state = lora.begin();
|
||||
if (state == ERR_NONE) {
|
||||
Serial.println(F("success!"));
|
||||
} else {
|
||||
Serial.print(F("failed, code "));
|
||||
Serial.println(state);
|
||||
while (true);
|
||||
}
|
||||
|
||||
// set the function that will be called
|
||||
// when packet transmission is finished
|
||||
lora.setDio1Action(setFlag);
|
||||
|
||||
// start transmitting the first packet
|
||||
Serial.print(F("[SX1262] Sending first packet ... "));
|
||||
|
||||
// you can transmit C-string or Arduino string up to
|
||||
// 256 characters long
|
||||
// NOTE: transmit() is a blocking method!
|
||||
// See example SX126x_Transmit_Interrupt for details
|
||||
// on non-blocking transmission method.
|
||||
int state = lora.transmit("Hello World!");
|
||||
transmissionState = lora.startTransmit("Hello World!");
|
||||
|
||||
// you can also transmit byte array up to 256 bytes long
|
||||
|
||||
byte byteArr[] = {0x01, 0x23, 0x45, 0x56, 0x78, 0xAB, 0xCD, 0xEF};
|
||||
int state = lora.transmit(byteArr, 8);
|
||||
byte byteArr[] = {0x01, 0x23, 0x45, 0x67,
|
||||
0x89, 0xAB, 0xCD, 0xEF};
|
||||
state = lora.startTransmit(byteArr, 8);
|
||||
|
||||
}
|
||||
|
||||
// flag to indicate that a packet was sent
|
||||
volatile bool transmittedFlag = false;
|
||||
|
||||
// disable interrupt when it's not needed
|
||||
volatile bool enableInterrupt = true;
|
||||
|
||||
// this function is called when a complete packet
|
||||
// is transmitted by the module
|
||||
// IMPORTANT: this function MUST be 'void' type
|
||||
// and MUST NOT have any arguments!
|
||||
void setFlag(void)
|
||||
{
|
||||
// check if the interrupt is enabled
|
||||
if (!enableInterrupt) {
|
||||
return;
|
||||
}
|
||||
|
||||
// we sent a packet, set the flag
|
||||
transmittedFlag = true;
|
||||
}
|
||||
|
||||
void loop()
|
||||
{
|
||||
// check if the previous transmission finished
|
||||
if (transmittedFlag) {
|
||||
// disable the interrupt service routine while
|
||||
// processing the data
|
||||
enableInterrupt = false;
|
||||
|
||||
// reset flag
|
||||
transmittedFlag = false;
|
||||
|
||||
if (transmissionState == ERR_NONE) {
|
||||
// packet was successfully sent
|
||||
Serial.println(F("transmission finished!"));
|
||||
|
||||
// NOTE: when using interrupt-driven transmit method,
|
||||
// it is not possible to automatically measure
|
||||
// transmission data rate using getDataRate()
|
||||
|
||||
} else {
|
||||
Serial.print(F("failed, code "));
|
||||
Serial.println(transmissionState);
|
||||
}
|
||||
|
||||
// wait a second before transmitting again
|
||||
delay(1000);
|
||||
|
||||
// send another one
|
||||
Serial.print(F("[SX1262] Sending another packet ... "));
|
||||
|
||||
// you can transmit C-string or Arduino string up to
|
||||
// 256 characters long
|
||||
transmissionState = lora.startTransmit("Hello World!");
|
||||
|
||||
// you can also transmit byte array up to 256 bytes long
|
||||
|
||||
byte byteArr[] = {0x01, 0x23, 0x45, 0x67,
|
||||
0x89, 0xAB, 0xCD, 0xEF};
|
||||
int state = lora.startTransmit(byteArr, 8);
|
||||
|
||||
|
||||
// we're ready to send more packets,
|
||||
// enable interrupt service routine
|
||||
enableInterrupt = true;
|
||||
}
|
||||
}
|
||||
|
||||
// this function is called when a complete packet
|
||||
// is received by the module
|
||||
// IMPORTANT: this function MUST be 'void' type
|
||||
// and MUST NOT have any arguments!
|
||||
void setFlag(void)
|
||||
{
|
||||
// check if the interrupt is enabled
|
||||
if (!enableInterrupt) {
|
||||
return;
|
||||
}
|
||||
|
||||
// we got a packet, set the flag
|
||||
receivedFlag = true;
|
||||
}
|
||||
|
||||
void loop()
|
||||
{
|
||||
// check if the flag is set
|
||||
if (receivedFlag) {
|
||||
// disable the interrupt service routine while
|
||||
// processing the data
|
||||
enableInterrupt = false;
|
||||
|
||||
// reset flag
|
||||
receivedFlag = false;
|
||||
|
||||
// you can read received data as an Arduino String
|
||||
String str;
|
||||
int state = lora.readData(str);
|
||||
|
||||
// you can also read received data as byte array
|
||||
|
||||
byte byteArr[8];
|
||||
int state = lora.readData(byteArr, 8);
|
||||
|
||||
|
||||
if (state == ERR_NONE) {
|
||||
// the packet was successfully transmitted
|
||||
Serial.println(F("success!"));
|
||||
// packet was successfully received
|
||||
Serial.println(F("[SX1262] Received packet!"));
|
||||
|
||||
// print measured data rate
|
||||
Serial.print(F("[SX1262] Datarate:\t"));
|
||||
Serial.print(lora.getDataRate());
|
||||
Serial.println(F(" bps"));
|
||||
// print data of the packet
|
||||
Serial.print(F("[SX1262] Data:\t\t"));
|
||||
Serial.println(str);
|
||||
|
||||
} else if (state == ERR_PACKET_TOO_LONG) {
|
||||
// the supplied packet was longer than 256 bytes
|
||||
Serial.println(F("too long!"));
|
||||
// print RSSI (Received Signal Strength Indicator)
|
||||
Serial.print(F("[SX1262] RSSI:\t\t"));
|
||||
Serial.print(lora.getRSSI());
|
||||
Serial.println(F(" dBm"));
|
||||
|
||||
} else if (state == ERR_TX_TIMEOUT) {
|
||||
// timeout occured while transmitting packet
|
||||
Serial.println(F("timeout!"));
|
||||
// print SNR (Signal-to-Noise Ratio)
|
||||
Serial.print(F("[SX1262] SNR:\t\t"));
|
||||
Serial.print(lora.getSNR());
|
||||
Serial.println(F(" dB"));
|
||||
|
||||
} else if (state == ERR_CRC_MISMATCH) {
|
||||
// packet was received, but is malformed
|
||||
Serial.println(F("CRC error!"));
|
||||
|
||||
} else {
|
||||
// some other error occurred
|
||||
@ -93,7 +385,12 @@ if (state == ERR_NONE) {
|
||||
Serial.println(state);
|
||||
}
|
||||
|
||||
// wait for a second before transmitting again
|
||||
delay(1000);
|
||||
// put module back to listen mode
|
||||
lora.startReceive();
|
||||
|
||||
// we're ready to receive more packets,
|
||||
// enable interrupt service routine
|
||||
enableInterrupt = true;
|
||||
}
|
||||
*/
|
||||
}
|
||||
*/
|
@ -4,8 +4,30 @@
|
||||
|
||||
#include <RadioLib.h>
|
||||
|
||||
// ESP32 has special rules about ISR code
|
||||
#ifdef ARDUINO_ARCH_ESP32
|
||||
#define INTERRUPT_ATTR IRAM_ATTR
|
||||
#else
|
||||
#define INTERRUPT_ATTR
|
||||
#endif
|
||||
|
||||
class RadioLibInterface : public RadioInterface
|
||||
{
|
||||
enum PendingISR { ISR_NONE = 0, ISR_RX, ISR_TX };
|
||||
|
||||
/**
|
||||
* What sort of interrupt do we expect our helper thread to now handle */
|
||||
volatile PendingISR pending;
|
||||
|
||||
/** Our ISR code currently needs this to find our active instance
|
||||
*/
|
||||
static RadioLibInterface *instance;
|
||||
|
||||
/**
|
||||
* Raw ISR handler that just calls our polymorphic method
|
||||
*/
|
||||
static void isrRxLevel0(), isrTxLevel0();
|
||||
|
||||
protected:
|
||||
float bw = 125;
|
||||
uint8_t sf = 9;
|
||||
@ -27,6 +49,16 @@ class RadioLibInterface : public RadioInterface
|
||||
*/
|
||||
PhysicalLayer &iface;
|
||||
|
||||
/**
|
||||
* Glue functions called from ISR land
|
||||
*/
|
||||
virtual void disableInterrupt() = 0;
|
||||
|
||||
/**
|
||||
* Enable a particular ISR callback glue function
|
||||
*/
|
||||
virtual void enableInterrupt(void (*)()) = 0;
|
||||
|
||||
public:
|
||||
RadioLibInterface(RADIOLIB_PIN_TYPE cs, RADIOLIB_PIN_TYPE irq, RADIOLIB_PIN_TYPE rst, RADIOLIB_PIN_TYPE busy, SPIClass &spi,
|
||||
PhysicalLayer *iface);
|
||||
@ -51,9 +83,20 @@ class RadioLibInterface : public RadioInterface
|
||||
/// \return true if initialisation succeeded.
|
||||
virtual bool init() { return true; }
|
||||
|
||||
virtual void loop(); // Idle processing
|
||||
|
||||
protected:
|
||||
/**
|
||||
* Convert our modemConfig enum into wf, sf, etc...
|
||||
*/
|
||||
void applyModemConfig();
|
||||
|
||||
/** Could we send right now (i.e. either not actively receiving or transmitting)? */
|
||||
virtual bool canSendImmediately() = 0;
|
||||
|
||||
/** start an immediate transmit */
|
||||
void startSend(MeshPacket *txp);
|
||||
|
||||
void handleTransmitInterrupt();
|
||||
void handleReceiveInterrupt();
|
||||
};
|
@ -27,6 +27,9 @@ bool SX1262Interface::init()
|
||||
int res = lora.begin(freq, bw, sf, cr, syncWord, power, currentLimit, preambleLength, tcxoVoltage, useRegulatorLDO);
|
||||
DEBUG_MSG("LORA init result %d\n", res);
|
||||
|
||||
if (res != ERR_NONE)
|
||||
res = lora.setCRC(SX126X_LORA_CRC_ON);
|
||||
|
||||
return res == ERR_NONE;
|
||||
}
|
||||
|
||||
@ -69,3 +72,19 @@ bool SX1262Interface::reconfigure()
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/** Could we send right now (i.e. either not actively receving or transmitting)? */
|
||||
bool SX1262Interface::canSendImmediately()
|
||||
{
|
||||
return true; // FIXME
|
||||
#if 0
|
||||
// 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.
|
||||
if (_mode == RHModeIdle || isReceiving()) {
|
||||
// if the radio is idle, we can send right away
|
||||
DEBUG_MSG("immediate send on mesh fr=0x%x,to=0x%x,id=%d\n (txGood=%d,rxGood=%d,rxBad=%d)\n", p->from, p->to, p->id,
|
||||
txGood(), rxGood(), rxBad());
|
||||
}
|
||||
#endif
|
||||
}
|
@ -18,4 +18,18 @@ class SX1262Interface : public RadioLibInterface
|
||||
/// Make sure the Driver is properly configured before calling init().
|
||||
/// \return true if initialisation succeeded.
|
||||
virtual bool reconfigure();
|
||||
|
||||
protected:
|
||||
/**
|
||||
* Glue functions called from ISR land
|
||||
*/
|
||||
virtual void INTERRUPT_ATTR disableInterrupt() { lora.clearDio1Action(); }
|
||||
|
||||
/**
|
||||
* Enable a particular ISR callback glue function
|
||||
*/
|
||||
virtual void enableInterrupt(void (*callback)()) { lora.setDio1Action(callback); }
|
||||
|
||||
/** Could we send right now (i.e. either not actively receiving or transmitting)? */
|
||||
virtual bool canSendImmediately();
|
||||
};
|
Loading…
Reference in New Issue
Block a user