From 22720e9f6339d3f4661ff471dc61794f8992647f Mon Sep 17 00:00:00 2001 From: geeksville Date: Thu, 30 Apr 2020 12:37:58 -0700 Subject: [PATCH] ex1262 receiving kinda works --- proto | 2 +- src/mesh/NodeDB.cpp | 2 + src/mesh/mesh.pb.h | 31 ++-- src/rf95/RadioLibInterface.cpp | 296 +++++---------------------------- src/rf95/RadioLibInterface.h | 31 ++-- src/rf95/SX1262Interface.cpp | 23 ++- src/rf95/SX1262Interface.h | 5 + 7 files changed, 98 insertions(+), 292 deletions(-) diff --git a/proto b/proto index e570ee983..bd002e5a1 160000 --- a/proto +++ b/proto @@ -1 +1 @@ -Subproject commit e570ee9836949d9f420fd19cc59a2595c8669a6e +Subproject commit bd002e5a144f209e42c97b64fea9a05a2e513b28 diff --git a/src/mesh/NodeDB.cpp b/src/mesh/NodeDB.cpp index 6348b7478..b27c49e12 100644 --- a/src/mesh/NodeDB.cpp +++ b/src/mesh/NodeDB.cpp @@ -289,6 +289,8 @@ void NodeDB::updateFrom(const MeshPacket &mp) info->position.time = mp.rx_time; } + info->snr = mp.rx_snr; // keep the most recent SNR we received for this node. + if (p.has_position) { // we carefully preserve the old time, because we always trust our local timestamps more uint32_t oldtime = info->position.time; diff --git a/src/mesh/mesh.pb.h b/src/mesh/mesh.pb.h index fdc266cdb..bf79305b8 100644 --- a/src/mesh/mesh.pb.h +++ b/src/mesh/mesh.pb.h @@ -102,8 +102,7 @@ typedef struct _NodeInfo { User user; bool has_position; Position position; - int32_t snr; - int32_t frequency_error; + float snr; } NodeInfo; typedef struct _RadioConfig { @@ -129,8 +128,8 @@ typedef struct _MeshPacket { bool has_payload; SubPacket payload; uint32_t rx_time; - int32_t rx_snr; uint32_t id; + float rx_snr; } MeshPacket; typedef struct _DeviceState { @@ -198,7 +197,7 @@ typedef struct _ToRadio { #define ChannelSettings_init_default {0, _ChannelSettings_ModemConfig_MIN, {0}, ""} #define RadioConfig_init_default {false, RadioConfig_UserPreferences_init_default, false, ChannelSettings_init_default} #define RadioConfig_UserPreferences_init_default {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} -#define NodeInfo_init_default {0, false, User_init_default, false, Position_init_default, 0, 0} +#define NodeInfo_init_default {0, false, User_init_default, false, Position_init_default, 0} #define MyNodeInfo_init_default {0, 0, 0, "", "", "", 0, 0, 0} #define DeviceState_init_default {false, RadioConfig_init_default, false, MyNodeInfo_init_default, false, User_init_default, 0, {NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default}, 0, {MeshPacket_init_default, MeshPacket_init_default, MeshPacket_init_default, MeshPacket_init_default, MeshPacket_init_default, MeshPacket_init_default, MeshPacket_init_default, MeshPacket_init_default, MeshPacket_init_default, MeshPacket_init_default, MeshPacket_init_default, MeshPacket_init_default, MeshPacket_init_default, MeshPacket_init_default, MeshPacket_init_default, MeshPacket_init_default, MeshPacket_init_default, MeshPacket_init_default, MeshPacket_init_default, MeshPacket_init_default, MeshPacket_init_default, MeshPacket_init_default, MeshPacket_init_default, MeshPacket_init_default, MeshPacket_init_default, MeshPacket_init_default, MeshPacket_init_default, MeshPacket_init_default, MeshPacket_init_default, MeshPacket_init_default, MeshPacket_init_default, MeshPacket_init_default}, false, MeshPacket_init_default, 0} #define DebugString_init_default {""} @@ -213,7 +212,7 @@ typedef struct _ToRadio { #define ChannelSettings_init_zero {0, _ChannelSettings_ModemConfig_MIN, {0}, ""} #define RadioConfig_init_zero {false, RadioConfig_UserPreferences_init_zero, false, ChannelSettings_init_zero} #define RadioConfig_UserPreferences_init_zero {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} -#define NodeInfo_init_zero {0, false, User_init_zero, false, Position_init_zero, 0, 0} +#define NodeInfo_init_zero {0, false, User_init_zero, false, Position_init_zero, 0} #define MyNodeInfo_init_zero {0, 0, 0, "", "", "", 0, 0, 0} #define DeviceState_init_zero {false, RadioConfig_init_zero, false, MyNodeInfo_init_zero, false, User_init_zero, 0, {NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero}, 0, {MeshPacket_init_zero, MeshPacket_init_zero, MeshPacket_init_zero, MeshPacket_init_zero, MeshPacket_init_zero, MeshPacket_init_zero, MeshPacket_init_zero, MeshPacket_init_zero, MeshPacket_init_zero, MeshPacket_init_zero, MeshPacket_init_zero, MeshPacket_init_zero, MeshPacket_init_zero, MeshPacket_init_zero, MeshPacket_init_zero, MeshPacket_init_zero, MeshPacket_init_zero, MeshPacket_init_zero, MeshPacket_init_zero, MeshPacket_init_zero, MeshPacket_init_zero, MeshPacket_init_zero, MeshPacket_init_zero, MeshPacket_init_zero, MeshPacket_init_zero, MeshPacket_init_zero, MeshPacket_init_zero, MeshPacket_init_zero, MeshPacket_init_zero, MeshPacket_init_zero, MeshPacket_init_zero, MeshPacket_init_zero}, false, MeshPacket_init_zero, 0} #define DebugString_init_zero {""} @@ -263,8 +262,7 @@ typedef struct _ToRadio { #define NodeInfo_num_tag 1 #define NodeInfo_user_tag 2 #define NodeInfo_position_tag 3 -#define NodeInfo_snr_tag 5 -#define NodeInfo_frequency_error_tag 6 +#define NodeInfo_snr_tag 7 #define RadioConfig_preferences_tag 1 #define RadioConfig_channel_settings_tag 2 #define SubPacket_position_tag 1 @@ -275,8 +273,8 @@ typedef struct _ToRadio { #define MeshPacket_to_tag 2 #define MeshPacket_payload_tag 3 #define MeshPacket_rx_time_tag 4 -#define MeshPacket_rx_snr_tag 5 #define MeshPacket_id_tag 6 +#define MeshPacket_rx_snr_tag 7 #define DeviceState_radio_tag 1 #define DeviceState_my_node_tag 2 #define DeviceState_owner_tag 3 @@ -342,8 +340,8 @@ X(a, STATIC, SINGULAR, INT32, from, 1) \ X(a, STATIC, SINGULAR, INT32, to, 2) \ X(a, STATIC, OPTIONAL, MESSAGE, payload, 3) \ X(a, STATIC, SINGULAR, UINT32, rx_time, 4) \ -X(a, STATIC, SINGULAR, SINT32, rx_snr, 5) \ -X(a, STATIC, SINGULAR, UINT32, id, 6) +X(a, STATIC, SINGULAR, UINT32, id, 6) \ +X(a, STATIC, SINGULAR, FLOAT, rx_snr, 7) #define MeshPacket_CALLBACK NULL #define MeshPacket_DEFAULT NULL #define MeshPacket_payload_MSGTYPE SubPacket @@ -385,8 +383,7 @@ X(a, STATIC, SINGULAR, BOOL, promiscuous_mode, 101) X(a, STATIC, SINGULAR, INT32, num, 1) \ X(a, STATIC, OPTIONAL, MESSAGE, user, 2) \ X(a, STATIC, OPTIONAL, MESSAGE, position, 3) \ -X(a, STATIC, SINGULAR, INT32, snr, 5) \ -X(a, STATIC, SINGULAR, INT32, frequency_error, 6) +X(a, STATIC, SINGULAR, FLOAT, snr, 7) #define NodeInfo_CALLBACK NULL #define NodeInfo_DEFAULT NULL #define NodeInfo_user_MSGTYPE User @@ -494,16 +491,16 @@ extern const pb_msgdesc_t ToRadio_msg; #define User_size 72 /* RouteDiscovery_size depends on runtime parameters */ #define SubPacket_size 383 -#define MeshPacket_size 426 +#define MeshPacket_size 425 #define ChannelSettings_size 44 #define RadioConfig_size 120 #define RadioConfig_UserPreferences_size 72 -#define NodeInfo_size 155 +#define NodeInfo_size 138 #define MyNodeInfo_size 85 -#define DeviceState_size 19502 +#define DeviceState_size 18925 #define DebugString_size 258 -#define FromRadio_size 435 -#define ToRadio_size 429 +#define FromRadio_size 434 +#define ToRadio_size 428 #ifdef __cplusplus } /* extern "C" */ diff --git a/src/rf95/RadioLibInterface.cpp b/src/rf95/RadioLibInterface.cpp index 57d64a3c5..156791ea3 100644 --- a/src/rf95/RadioLibInterface.cpp +++ b/src/rf95/RadioLibInterface.cpp @@ -1,5 +1,9 @@ #include "RadioLibInterface.h" +#include "MeshTypes.h" +#include "mesh-pb-constants.h" #include +#include +#include // FIXME, we default to 4MHz SPI, SPI mode 0, check if the datasheet says it can really do that static SPISettings spiSettings(4000000, MSBFIRST, SPI_MODE0); @@ -100,14 +104,19 @@ void RadioLibInterface::loop() 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(); - } + startNextWork(); + } +} + +void RadioLibInterface::startNextWork() +{ + // 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 + startReceive(); } } @@ -125,69 +134,39 @@ void RadioLibInterface::handleTransmitInterrupt() void RadioLibInterface::handleReceiveInterrupt() { - // FIXME -} + // read the number of actually received bytes + size_t length = iface.getPacketLength(); -#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 + int state = iface.readData(radiobuf, length); + if (state != ERR_NONE) { + DEBUG_MSG("ignoring received packet due to error=%d\n", state); + } else { + // Skip the 4 headers that are at the beginning of the rxBuf + int32_t payloadLen = length - sizeof(PacketHeader); + const uint8_t *payload = radiobuf + sizeof(PacketHeader); + const PacketHeader *h = (PacketHeader *)radiobuf; - if (_mode == RHModeIdle) // We are now done sending or receiving - { + // fixme check for short packets - // If we just finished receiving a packet, forward it into a queue - if (_rxBufValid) { - // We received a packet + MeshPacket *mp = packetPool.allocZeroed(); - // 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; + SubPacket *p = &mp->payload; - // 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); + mp->from = h->from; + mp->to = h->to; + mp->id = h->id; - MeshPacket *mp = packetPool.allocZeroed(); + if (!pb_decode_from_bytes(payload, payloadLen, SubPacket_fields, p)) { + DEBUG_MSG("Invalid protobufs in received mesh packet, discarding.\n"); + packetPool.release(mp); + } else { + // parsing was successful, queue for our recipient + mp->has_payload = true; - 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 + deliverToReceiver(mp); } - - handleIdleISR(); } } -#endif /** start an immediate transmit */ void RadioLibInterface::startSend(MeshPacket *txp) @@ -201,198 +180,3 @@ void RadioLibInterface::startSend(MeshPacket *txp) enableInterrupt(isrTxLevel0); } -/** - * - * - * -// include the library - - -// save transmission state between loops -int transmissionState = ERR_NONE; - -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 - 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}; - 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) { - // packet was successfully received - Serial.println(F("[SX1262] Received packet!")); - - // print data of the packet - Serial.print(F("[SX1262] Data:\t\t")); - Serial.println(str); - - // print RSSI (Received Signal Strength Indicator) - Serial.print(F("[SX1262] RSSI:\t\t")); - Serial.print(lora.getRSSI()); - Serial.println(F(" dBm")); - - // 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 - Serial.print(F("failed, code ")); - Serial.println(state); -} - -// put module back to listen mode -lora.startReceive(); - -// we're ready to receive more packets, -// enable interrupt service routine -enableInterrupt = true; -} -} -*/ \ No newline at end of file diff --git a/src/rf95/RadioLibInterface.h b/src/rf95/RadioLibInterface.h index dca7dda9d..3d0f8e04a 100644 --- a/src/rf95/RadioLibInterface.h +++ b/src/rf95/RadioLibInterface.h @@ -26,7 +26,7 @@ class RadioLibInterface : public RadioInterface /** * Raw ISR handler that just calls our polymorphic method */ - static void isrRxLevel0(), isrTxLevel0(); + static void isrTxLevel0(); protected: float bw = 125; @@ -39,7 +39,7 @@ class RadioLibInterface : public RadioInterface */ uint8_t syncWord = SX126X_SYNC_WORD_PRIVATE; - float currentLimit = 100; // FIXME + float currentLimit = 100; // FIXME uint16_t preambleLength = 8; // 8 is default, but FIXME use longer to increase the amount of sleep time when receiving Module module; // The HW interface to the radio @@ -78,13 +78,18 @@ class RadioLibInterface : public RadioInterface /// \param[in] thisAddress The address of this node. virtual void setThisAddress(uint8_t thisAddress) {} - /// 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() { return true; } - virtual void loop(); // Idle processing + private: + /** start an immediate transmit */ + void startSend(MeshPacket *txp); + + /** start a queued transmit (if we have one), else start receiving */ + void startNextWork(); + + void handleTransmitInterrupt(); + void handleReceiveInterrupt(); + protected: /** * Convert our modemConfig enum into wf, sf, etc... @@ -94,9 +99,13 @@ class RadioLibInterface : public RadioInterface /** 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); + /** + * Start waiting to receive a message + */ + virtual void startReceive() = 0; - void handleTransmitInterrupt(); - void handleReceiveInterrupt(); + /** + * Raw ISR handler that just calls our polymorphic method + */ + static void isrRxLevel0(); }; \ No newline at end of file diff --git a/src/rf95/SX1262Interface.cpp b/src/rf95/SX1262Interface.cpp index 88dfae80e..d72c828a0 100644 --- a/src/rf95/SX1262Interface.cpp +++ b/src/rf95/SX1262Interface.cpp @@ -12,9 +12,6 @@ SX1262Interface::SX1262Interface(RADIOLIB_PIN_TYPE cs, RADIOLIB_PIN_TYPE irq, RA /// \return true if initialisation succeeded. bool SX1262Interface::init() { - if (!RadioLibInterface::init()) - return false; - // FIXME, move this to main SPI.begin(); @@ -30,7 +27,10 @@ bool SX1262Interface::init() if (res == ERR_NONE) res = lora.setCRC(SX126X_LORA_CRC_ON); - return res == ERR_NONE; + if (res == ERR_NONE) + startReceive(); // start receiving + + return res; } bool SX1262Interface::reconfigure() @@ -68,9 +68,18 @@ bool SX1262Interface::reconfigure() err = lora.setOutputPower(power); assert(err == ERR_NONE); - assert(0); // FIXME - set mode back to receive? + startReceive(); // restart receiving - return true; + return ERR_NONE; +} + +void SX1262Interface::startReceive() +{ + int err = lora.startReceive(); + assert(err == ERR_NONE); + + // 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)? */ @@ -86,5 +95,5 @@ bool SX1262Interface::canSendImmediately() 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 +#endif } \ No newline at end of file diff --git a/src/rf95/SX1262Interface.h b/src/rf95/SX1262Interface.h index f480415ff..edb7cad78 100644 --- a/src/rf95/SX1262Interface.h +++ b/src/rf95/SX1262Interface.h @@ -32,4 +32,9 @@ class SX1262Interface : public RadioLibInterface /** 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(); }; \ No newline at end of file