#pragma once #include #include class RadioLibWrapper : public mesh::Radio { protected: PhysicalLayer* _radio; mesh::MainBoard* _board; uint32_t n_recv, n_sent, n_recv_errors, _tx_start_ms; int16_t _noise_floor, _threshold; uint8_t _busy_count; // consecutive busy detections for exponential backoff uint16_t _num_floor_samples; int32_t _floor_sample_sum; void idle(); void startRecv(); float packetScoreInt(float snr, int sf, int packet_len); virtual bool isReceivingPacket() =0; virtual void doResetAGC(); public: RadioLibWrapper(PhysicalLayer& radio, mesh::MainBoard& board) : _radio(&radio), _board(&board) { n_recv = n_sent = 0; } void begin() override; virtual void powerOff() { _radio->sleep(); } int recvRaw(uint8_t* bytes, int sz) override; uint32_t getEstAirtimeFor(int len_bytes) override; bool startSendRaw(const uint8_t* bytes, int len) override; bool isSendComplete() override; void onSendFinished() override; bool isInRecvMode() const override; bool isChannelActive(); bool isReceiving() override { if (isReceivingPacket()) return true; return isChannelActive(); } virtual float getCurrentRSSI() =0; virtual uint8_t getCodingRate() const = 0; virtual float getFreqMHz() const = 0; bool isJapanMode() const { float freq = getFreqMHz(); return (fabsf(freq - 920.800f) < 0.05f || fabsf(freq - 921.000f) < 0.05f || fabsf(freq - 921.200f) < 0.05f); } int getMaxTextLen() const { if (!isJapanMode()) return 10 * 16; // default uint8_t cr = getCodingRate(); if (cr <= 5) return 3 * 16; // 48 bytes ~16 JP chars if (cr == 6) return 2 * 16; // 32 bytes ~10 JP chars if (cr == 7) return 1 * 16 + 8; // 24 bytes ~8 JP chars return 1 * 16; // 16 bytes ~5 JP chars } virtual int16_t performChannelScan(); int getNoiseFloor() const override { return _noise_floor; } void triggerNoiseFloorCalibrate(int threshold) override; void resetAGC() override; void loop() override; uint32_t getPacketsRecv() const { return n_recv; } uint32_t getPacketsRecvErrors() const { return n_recv_errors; } uint32_t getPacketsSent() const { return n_sent; } void resetStats() { n_recv = n_sent = n_recv_errors = 0; } virtual float getLastRSSI() const override; virtual float getLastSNR() const override; float packetScore(float snr, int packet_len) override { return packetScoreInt(snr, 10, packet_len); } // assume sf=10 virtual void setRxBoostedGainMode(bool) { } virtual bool getRxBoostedGainMode() const { return false; } }; /** * \brief an RNG impl using the noise from the LoRa radio as entropy. * NOTE: this is VERY SLOW! Use only for things like creating new LocalIdentity */ class RadioNoiseListener : public mesh::RNG { PhysicalLayer* _radio; public: RadioNoiseListener(PhysicalLayer& radio): _radio(&radio) { } void random(uint8_t* dest, size_t sz) override { for (int i = 0; i < sz; i++) { dest[i] = _radio->randomByte() ^ (::random(0, 256) & 0xFF); } } };