diff --git a/ext/lcd/ui/UILabel.h b/ext/lcd/ui/UILabel.h index 700f018..9bfde9e 100644 --- a/ext/lcd/ui/UILabel.h +++ b/ext/lcd/ui/UILabel.h @@ -27,7 +27,13 @@ public: setNeedsRedraw(); } + void setColorBackground(Color c) { + this->cBackground = c; + } + void setColorText(Color c) { + this->cText = c; + } /** draw the label */ void draw(UIPainter& p) override { diff --git a/ext/lcd/ui/UIPainter.h b/ext/lcd/ui/UIPainter.h index 689b788..65441cb 100644 --- a/ext/lcd/ui/UIPainter.h +++ b/ext/lcd/ui/UIPainter.h @@ -5,6 +5,8 @@ #include "../Draw.h" #include "UIStructs.h" +#include + class Setter; class FontWrap; @@ -34,6 +36,10 @@ public: void drawText(const uint16_t x, const uint16_t y, const char* str) { fnt_f1.draw(str, x, y, setter); } + + void drawText(const uint16_t x, const uint16_t y, const std::string& str) { + drawText(x, y, str.c_str()); + } void setFG(const Color fg) { drawer.setColor(fg); diff --git a/ext/rf/SX1276.h b/ext/rf/SX1276.h index b82997b..6148690 100644 --- a/ext/rf/SX1276.h +++ b/ext/rf/SX1276.h @@ -93,6 +93,10 @@ template class SX static constexpr const uint8_t REG_PAYLOAD_LENGTH = 0x22; static constexpr const uint8_t REG_MODEM_CONFIG_3 = 0x26; + static constexpr const uint8_t REG_DETECTION_OPTIMIZE = 0x31; + static constexpr const uint8_t REG_DETECTION_THRESHOLD =0x37; + + static constexpr const uint8_t REG_VERSION = 0x42; static constexpr const uint8_t REG_PA_DAC = 0x4d; @@ -177,12 +181,94 @@ public: // writeRegister(REG_MODEM_CONFIG_2, readRegister(REG_MODEM_CONFIG_2) & 0xfb); // } // } + + /** get the currently configured spreading factor */ + int getSpreadingFactor() { + return readRegister(REG_MODEM_CONFIG_2) >> 4; + } + + /** + * set the spreading factor to use + * BEWARE!! BOTH sides must agree on the same spreading factor or the transmission will fail!! + * 6 requires implicit header mode (you are responsible for sending the header) + * 7 = lowest quality, fastest + * 12 = highest quality, slowest + */ + void setSpreadingFactor(int sf) { + + if (sf < 6 || sf > 12) {debugMod1(NAME, "setSpreadingFactor(%d) out of range", sf); return;} + + if (sf == 6) { + writeRegister(REG_DETECTION_OPTIMIZE, 0xc5); + writeRegister(REG_DETECTION_THRESHOLD, 0x0c); + } else { + writeRegister(REG_DETECTION_OPTIMIZE, 0xc3); + writeRegister(REG_DETECTION_THRESHOLD, 0x0a); + } + + writeRegister(REG_MODEM_CONFIG_2, (readRegister(REG_MODEM_CONFIG_2) & 0x0f) | ((sf << 4) & 0xf0)); + setLdoFlag(); + } + + /** get the signal's transmit bandwidth (in Hz) */ + uint32_t getSignalBandwidth() { + const uint8_t bw = (readRegister(REG_MODEM_CONFIG_1) >> 4); + switch (bw) { + case 0: return 7.8E3; + case 1: return 10.4E3; + case 2: return 15.6E3; + case 3: return 20.8E3; + case 4: return 31.25E3; + case 5: return 41.7E3; + case 6: return 62.5E3; + case 7: return 125E3; + case 8: return 250E3; + case 9: return 500E3; + default: return -1; + } + } + + /** + * set the FEC (Forward Error Correction) (see Table14) + * available values are: 4/5, 4/6, 4/7, 4/8 + * the receiver is not required to know the FEC of the sender, as this value is transmitted within the header, which is always sent with 4/8 + */ + void setCodingRate4(int denominator) { + if (denominator < 5 || denominator > 8) {debugMod1(NAME, "setCodingRate4(%d) out of range", denominator); return;} + const int cr = denominator - 4; + writeRegister(REG_MODEM_CONFIG_1, (readRegister(REG_MODEM_CONFIG_1) & 0xf1) | (cr << 1)); + } + + /** get the current FEC denominator 4/x */ + int getCodingRate4() { + return ((readRegister(REG_MODEM_CONFIG_1) & 0b1110) >> 1) + 4; + } + + + /** calculate the current data-rate based on spreading-factor and bandwidth */ + int16_t getDataRate() { + // https://blog.dbrgn.ch/2017/6/23/lorawan-data-rates/ + const int sf = getSpreadingFactor(); + const int bw = getSignalBandwidth(); + if (bw == 125000) { + if (sf == 7) {return 5470;} + if (sf == 8) {return 3125;} + if (sf == 9) {return 1760;} + if (sf == 10) {return 980;} + if (sf == 11) {return 440;} + if (sf == 12) {return 250;} + } + return -1; + } + + /** switch to idle mode */ void idle() { debugMod(NAME, "idle()"); writeRegister(REG_OP_MODE, MODE_LONG_RANGE_MODE | MODE_STDBY); } + /** switch to sleep mode */ void sleep() { debugMod(NAME, "sleep()"); writeRegister(REG_OP_MODE, MODE_LONG_RANGE_MODE | MODE_SLEEP); @@ -194,6 +280,7 @@ public: return false; } + /** send the given data */ int send(const uint8_t* data, uint8_t len, bool async) { debugMod1(NAME, "send(%d bytes)", len); @@ -295,7 +382,10 @@ public: } - + /** debug output */ + void debugDump() { + printf("SX1276: spreadingFactor: %d, bandwidth: %d Hz, dataRate: %d bit/s FEC: 4/%d \n", getSpreadingFactor(), getSignalBandwidth(), getDataRate(), getCodingRate4()); + } private: @@ -395,6 +485,25 @@ private: writeRegister(REG_OCP, 0x20 | (0x1F & ocpTrim)); } + /** what exactly is this? Low-DataRate-Optimizer??? */ + void setLdoFlag() { + + // Section 4.1.1.5 + uint64_t symbolDuration = 1000 / ( getSignalBandwidth() / (1L << getSpreadingFactor()) ) ; + + // Section 4.1.1.6 + bool ldoOn = symbolDuration > 16; + + uint8_t config3 = readRegister(REG_MODEM_CONFIG_3); + if (ldoOn) {config3 = config3 | (1<<3);} else {config3 = config3 & ~(1<<3);} + //bitWrite(config3, 3, ldoOn); + writeRegister(REG_MODEM_CONFIG_3, config3); + + } + + +private: + /** write value to register */ void writeRegister(uint8_t address, uint8_t value) { transfer(address | 0x80, value);