diff --git a/.trunk/.gitignore b/.trunk/.gitignore index 8130ba6d1..695b51906 100644 --- a/.trunk/.gitignore +++ b/.trunk/.gitignore @@ -5,4 +5,4 @@ plugins user_trunk.yaml user.yaml -shims +tools diff --git a/.trunk/trunk.yaml b/.trunk/trunk.yaml index 8ab9166fb..7e81046a7 100644 --- a/.trunk/trunk.yaml +++ b/.trunk/trunk.yaml @@ -1,37 +1,42 @@ version: 0.1 cli: - version: 1.10.0 + version: 1.13.0 plugins: sources: - id: trunk - ref: v0.0.17 + ref: v1.1.1 uri: https://github.com/trunk-io/plugins lint: enabled: - - taplo@0.7.0 - - ruff@0.0.265 + - bandit@1.7.5 + - checkov@2.4.1 + - terrascan@1.18.3 + - trivy@0.44.1 + - trufflehog@3.48.0 + - taplo@0.8.1 + - ruff@0.0.284 - yamllint@1.32.0 - isort@5.12.0 - - markdownlint@0.34.0 + - markdownlint@0.35.0 - oxipng@8.0.0 - svgo@3.0.2 - - actionlint@1.6.24 - - flake8@6.0.0 + - actionlint@1.6.25 + - flake8@6.1.0 - hadolint@2.12.0 - - shfmt@3.5.0 + - shfmt@3.6.0 - shellcheck@0.9.0 - - black@23.3.0 + - black@23.7.0 - git-diff-check - - gitleaks@8.16.3 - - clang-format@14.0.0 - - prettier@2.8.8 + - gitleaks@8.17.0 + - clang-format@16.0.3 + - prettier@3.0.2 disabled: - - taplo@0.7.0 + - taplo@0.8.1 - shellcheck@0.9.0 - - shfmt@3.5.0 + - shfmt@3.6.0 - oxipng@8.0.0 - actionlint@1.6.22 - - markdownlint@0.34.0 + - markdownlint@0.35.0 - hadolint@2.12.0 - svgo@3.0.2 runtimes: diff --git a/protobufs b/protobufs index dc28ae3d1..468ff2e24 160000 --- a/protobufs +++ b/protobufs @@ -1 +1 @@ -Subproject commit dc28ae3d128b76707c0b87b6f3b2514c7f8514bd +Subproject commit 468ff2e2457d7534a907af0a21bdede9f4042cb7 diff --git a/src/Power.cpp b/src/Power.cpp index 533286fe9..dd9f70130 100644 --- a/src/Power.cpp +++ b/src/Power.cpp @@ -16,8 +16,8 @@ #include "buzz/buzz.h" #include "configuration.h" #include "main.h" +#include "meshUtils.h" #include "sleep.h" -#include "utils.h" #ifdef DEBUG_HEAP_MQTT #include "mqtt/MQTT.h" @@ -221,10 +221,7 @@ class AnalogBatteryLevel : public HasBatteryLevel /** * return true if there is a battery installed in this unit */ - virtual bool isBatteryConnect() override - { - return getBatteryPercent() != -1; - } + virtual bool isBatteryConnect() override { return getBatteryPercent() != -1; } /// If we see a battery voltage higher than physics allows - assume charger is pumping /// in power @@ -245,10 +242,7 @@ class AnalogBatteryLevel : public HasBatteryLevel /// Assume charging if we have a battery and external power is connected. /// we can't be smart enough to say 'full'? - virtual bool isCharging() override - { - return isBatteryConnect() && isVbusIn(); - } + virtual bool isCharging() override { return isBatteryConnect() && isVbusIn(); } private: /// If we see a battery voltage higher than physics allows - assume charger is pumping diff --git a/src/configuration.h b/src/configuration.h index fb96430bc..e116854c2 100644 --- a/src/configuration.h +++ b/src/configuration.h @@ -101,6 +101,7 @@ along with this program. If not, see . // I2C Keyboards (M5Stack, RAK14004, T-Deck) #define CARDKB_ADDR 0x5F #define TDECK_KB_ADDR 0x55 +#define BBQ10_KB_ADDR 0x1F // ----------------------------------------------------------------------------- // SENSOR diff --git a/src/detect/ScanI2C.cpp b/src/detect/ScanI2C.cpp index 996bdf62a..bf206c190 100644 --- a/src/detect/ScanI2C.cpp +++ b/src/detect/ScanI2C.cpp @@ -30,8 +30,8 @@ ScanI2C::FoundDevice ScanI2C::firstRTC() const ScanI2C::FoundDevice ScanI2C::firstKeyboard() const { - ScanI2C::DeviceType types[] = {CARDKB, TDECKKB, RAK14004}; - return firstOfOrNONE(3, types); + ScanI2C::DeviceType types[] = {CARDKB, TDECKKB, BBQ10KB, RAK14004}; + return firstOfOrNONE(4, types); } ScanI2C::FoundDevice ScanI2C::firstAccelerometer() const diff --git a/src/detect/ScanI2C.h b/src/detect/ScanI2C.h index 418a6bf5e..15d9b1342 100644 --- a/src/detect/ScanI2C.h +++ b/src/detect/ScanI2C.h @@ -17,6 +17,7 @@ class ScanI2C RTC_PCF8563, CARDKB, TDECKKB, + BBQ10KB, RAK14004, PMU_AXP192_AXP2101, BME_680, diff --git a/src/detect/ScanI2CTwoWire.cpp b/src/detect/ScanI2CTwoWire.cpp index d8bddee30..f4f490085 100644 --- a/src/detect/ScanI2CTwoWire.cpp +++ b/src/detect/ScanI2CTwoWire.cpp @@ -213,6 +213,7 @@ void ScanI2CTwoWire::scanPort(I2CPort port) break; SCAN_SIMPLE_CASE(TDECK_KB_ADDR, TDECKKB, "T-Deck keyboard found\n"); + SCAN_SIMPLE_CASE(BBQ10_KB_ADDR, BBQ10KB, "BB Q10 keyboard found\n"); SCAN_SIMPLE_CASE(ST7567_ADDRESS, SCREEN_ST7567, "st7567 display found\n"); #ifdef HAS_NCP5623 SCAN_SIMPLE_CASE(NCP5623_ADDR, NCP5623, "NCP5623 RGB LED found\n"); diff --git a/src/gps/GPS.cpp b/src/gps/GPS.cpp index 27fe36fe5..ab5156fab 100644 --- a/src/gps/GPS.cpp +++ b/src/gps/GPS.cpp @@ -188,8 +188,8 @@ bool GPS::setupGPS() config.position.tx_gpio = GPS_TX_PIN; #endif -//#define BAUD_RATE 115200 -// ESP32 has a special set of parameters vs other arduino ports +// #define BAUD_RATE 115200 +// ESP32 has a special set of parameters vs other arduino ports #if defined(ARCH_ESP32) if (config.position.rx_gpio) { LOG_DEBUG("Using GPIO%d for GPS RX\n", config.position.rx_gpio); @@ -267,7 +267,6 @@ bool GPS::setupGPS() LOG_INFO("GNSS configured for GPS+SBAS+GLONASS. Pause for 0.75s before sending next command.\n"); // Documentation say, we need wait atleast 0.5s after reconfiguration of GNSS module, before sending next commands delay(750); - return true; } // Enable interference resistance, because we are using LoRa, WiFi and Bluetooth on same board, @@ -535,7 +534,8 @@ bool GPS::setupGPS() _serial_gps->write(UBX_CFG_PMS, sizeof(UBX_CFG_PMS)); if (!getACK(0x06, 0x86)) { LOG_WARN("Unable to enable powersaving for GPS.\n"); - return true; + // T-beam doesn't support this mode. + // Don't bail from function early. } // We need save configuration to flash to make our config changes persistent @@ -675,6 +675,7 @@ void GPS::setAwake(bool on) if (isAwake != on) { LOG_DEBUG("WANT GPS=%d\n", on); if (on) { + clearBuffer(); // drop any old data waiting in the buffer lastWakeStartMsec = millis(); wake(); } else { @@ -858,7 +859,7 @@ GnssModel_t GPS::probe() { memset(&info, 0, sizeof(struct uBloxGnssModelInfo)); // return immediately if the model is set by the variant.h file -//#ifdef GPS_UBLOX (unless it's a ublox, because we might want to know the module info! +// #ifdef GPS_UBLOX (unless it's a ublox, because we might want to know the module info! // return GNSS_MODEL_UBLOX; think about removing this macro and return) #if defined(GPS_L76K) return GNSS_MODEL_MTK; @@ -891,7 +892,8 @@ GnssModel_t GPS::probe() } } - uint8_t cfg_rate[] = {0xB5, 0x62, 0x06, 0x08, 0x00, 0x00, 0x0E, 0x30}; + uint8_t cfg_rate[] = {0xB5, 0x62, 0x06, 0x08, 0x00, 0x00, 0x00, 0x00}; + UBXChecksum(cfg_rate, sizeof(cfg_rate)); _serial_gps->write(cfg_rate, sizeof(cfg_rate)); // Check that the returned response class and message ID are correct if (!getAck(buffer, 384, 0x06, 0x08)) { diff --git a/src/graphics/Screen.cpp b/src/graphics/Screen.cpp index d4ed6fdb6..9ccd28aba 100644 --- a/src/graphics/Screen.cpp +++ b/src/graphics/Screen.cpp @@ -36,11 +36,11 @@ along with this program. If not, see . #include "mesh-pb-constants.h" #include "mesh/Channels.h" #include "mesh/generated/meshtastic/deviceonly.pb.h" +#include "meshUtils.h" #include "modules/ExternalNotificationModule.h" #include "modules/TextMessageModule.h" #include "sleep.h" #include "target_specific.h" -#include "utils.h" #ifdef ARCH_ESP32 #include "esp_task_wdt.h" @@ -365,7 +365,7 @@ static void drawCriticalFaultFrame(OLEDDisplay *display, OLEDDisplayUiState *sta // Ignore messages originating from phone (from the current node 0x0) unless range test or store and forward module are enabled static bool shouldDrawMessage(const meshtastic_MeshPacket *packet) { - return packet->from != 0 && !moduleConfig.range_test.enabled && !moduleConfig.store_forward.enabled; + return packet->from != 0 && !moduleConfig.store_forward.enabled; } /// Draw the last text message we received diff --git a/src/input/BBQ10Keyboard.cpp b/src/input/BBQ10Keyboard.cpp new file mode 100644 index 000000000..8f8399aef --- /dev/null +++ b/src/input/BBQ10Keyboard.cpp @@ -0,0 +1,181 @@ +// Based on arturo182 arduino_bbq10kbd library https://github.com/arturo182/arduino_bbq10kbd + +#include + +#include "BBQ10Keyboard.h" + +#define _REG_VER 1 +#define _REG_CFG 2 +#define _REG_INT 3 +#define _REG_KEY 4 +#define _REG_BKL 5 +#define _REG_DEB 6 +#define _REG_FRQ 7 +#define _REG_RST 8 +#define _REG_FIF 9 + +#define _WRITE_MASK (1 << 7) + +#define CFG_OVERFLOW_ON (1 << 0) +#define CFG_OVERFLOW_INT (1 << 1) +#define CFG_CAPSLOCK_INT (1 << 2) +#define CFG_NUMLOCK_INT (1 << 3) +#define CFG_KEY_INT (1 << 4) +#define CFG_PANIC_INT (1 << 5) +#define CFG_REPORT_MODS (1 << 6) +#define CFG_USE_MODS (1 << 7) + +#define INT_OVERFLOW (1 << 0) +#define INT_CAPSLOCK (1 << 1) +#define INT_NUMLOCK (1 << 2) +#define INT_KEY (1 << 3) +#define INT_PANIC (1 << 4) + +#define KEY_CAPSLOCK (1 << 5) +#define KEY_NUMLOCK (1 << 6) +#define KEY_COUNT_MASK (0x1F) + +BBQ10Keyboard::BBQ10Keyboard() : m_wire(nullptr), m_addr(0), readCallback(nullptr), writeCallback(nullptr) {} + +void BBQ10Keyboard::begin(uint8_t addr, TwoWire *wire) +{ + m_addr = addr; + m_wire = wire; + + m_wire->begin(); + + reset(); +} + +void BBQ10Keyboard::begin(i2c_com_fptr_t r, i2c_com_fptr_t w, uint8_t addr) +{ + m_addr = addr; + m_wire = nullptr; + writeCallback = w; + readCallback = r; + reset(); +} + +void BBQ10Keyboard::reset() +{ + if (m_wire) { + m_wire->beginTransmission(m_addr); + m_wire->write(_REG_RST); + m_wire->endTransmission(); + } + if (writeCallback) { + uint8_t data = 0; + writeCallback(m_addr, _REG_RST, &data, 0); + } + delay(100); + writeRegister(_REG_CFG, readRegister8(_REG_CFG) | CFG_REPORT_MODS); + delay(100); +} + +void BBQ10Keyboard::attachInterrupt(uint8_t pin, void (*func)(void)) const +{ + pinMode(pin, INPUT_PULLUP); + ::attachInterrupt(digitalPinToInterrupt(pin), func, RISING); +} + +void BBQ10Keyboard::detachInterrupt(uint8_t pin) const +{ + ::detachInterrupt(pin); +} + +void BBQ10Keyboard::clearInterruptStatus() +{ + writeRegister(_REG_INT, 0x00); +} + +uint8_t BBQ10Keyboard::status() const +{ + return readRegister8(_REG_KEY); +} + +uint8_t BBQ10Keyboard::keyCount() const +{ + return status() & KEY_COUNT_MASK; +} + +BBQ10Keyboard::KeyEvent BBQ10Keyboard::keyEvent() const +{ + KeyEvent event = {.key = '\0', .state = StateIdle}; + + if (keyCount() == 0) + return event; + + const uint16_t buf = readRegister16(_REG_FIF); + event.key = buf >> 8; + event.state = KeyState(buf & 0xFF); + + return event; +} + +float BBQ10Keyboard::backlight() const +{ + return readRegister8(_REG_BKL) / 255.0f; +} + +void BBQ10Keyboard::setBacklight(float value) +{ + writeRegister(_REG_BKL, value * 255); +} + +uint8_t BBQ10Keyboard::readRegister8(uint8_t reg) const +{ + if (m_wire) { + m_wire->beginTransmission(m_addr); + m_wire->write(reg); + m_wire->endTransmission(); + + m_wire->requestFrom(m_addr, (uint8_t)1); + if (m_wire->available() < 1) + return 0; + + return m_wire->read(); + } + if (readCallback) { + uint8_t data; + readCallback(m_addr, reg, &data, 1); + return data; + } + return 0; +} + +uint16_t BBQ10Keyboard::readRegister16(uint8_t reg) const +{ + uint8_t data[2] = {0}; + // uint8_t low = 0, high = 0; + if (m_wire) { + m_wire->beginTransmission(m_addr); + m_wire->write(reg); + m_wire->endTransmission(); + + m_wire->requestFrom(m_addr, (uint8_t)2); + if (m_wire->available() < 2) + return 0; + data[0] = m_wire->read(); + data[1] = m_wire->read(); + } + if (readCallback) { + readCallback(m_addr, reg, data, 2); + } + return (data[1] << 8) | data[0]; +} + +void BBQ10Keyboard::writeRegister(uint8_t reg, uint8_t value) +{ + uint8_t data[2]; + data[0] = reg | _WRITE_MASK; + data[1] = value; + + if (m_wire) { + m_wire->beginTransmission(m_addr); + m_wire->write(data, sizeof(uint8_t) * 2); + m_wire->endTransmission(); + } + if (writeCallback) { + writeCallback(m_addr, data[0], &(data[1]), 1); + } +} diff --git a/src/input/BBQ10Keyboard.h b/src/input/BBQ10Keyboard.h new file mode 100644 index 000000000..07d02308f --- /dev/null +++ b/src/input/BBQ10Keyboard.h @@ -0,0 +1,51 @@ +// Based on arturo182 arduino_bbq10kbd library https://github.com/arturo182/arduino_bbq10kbd + +#include "configuration.h" +#include + +#define KEY_MOD_ALT (0x1A) +#define KEY_MOD_SHL (0x1B) +#define KEY_MOD_SHR (0x1C) +#define KEY_MOD_SYM (0x1D) + +class BBQ10Keyboard +{ + public: + typedef uint8_t (*i2c_com_fptr_t)(uint8_t dev_addr, uint8_t reg_addr, uint8_t *data, uint8_t len); + + enum KeyState { StateIdle = 0, StatePress, StateLongPress, StateRelease }; + + struct KeyEvent { + char key; + KeyState state; + }; + + BBQ10Keyboard(); + + void begin(uint8_t addr = BBQ10_KB_ADDR, TwoWire *wire = &Wire); + + void begin(i2c_com_fptr_t r, i2c_com_fptr_t w, uint8_t addr = BBQ10_KB_ADDR); + + void reset(void); + + void attachInterrupt(uint8_t pin, void (*func)(void)) const; + void detachInterrupt(uint8_t pin) const; + void clearInterruptStatus(void); + + uint8_t status(void) const; + uint8_t keyCount(void) const; + KeyEvent keyEvent(void) const; + + float backlight() const; + void setBacklight(float value); + + uint8_t readRegister8(uint8_t reg) const; + uint16_t readRegister16(uint8_t reg) const; + void writeRegister(uint8_t reg, uint8_t value); + + private: + TwoWire *m_wire; + uint8_t m_addr; + i2c_com_fptr_t readCallback; + i2c_com_fptr_t writeCallback; +}; diff --git a/src/input/cardKbI2cImpl.cpp b/src/input/cardKbI2cImpl.cpp index 44db1d952..e000f36eb 100644 --- a/src/input/cardKbI2cImpl.cpp +++ b/src/input/cardKbI2cImpl.cpp @@ -7,7 +7,7 @@ CardKbI2cImpl::CardKbI2cImpl() : KbI2cBase("cardKB") {} void CardKbI2cImpl::init() { - if (cardkb_found.address != CARDKB_ADDR && cardkb_found.address != TDECK_KB_ADDR) { + if (cardkb_found.address == 0x00) { disable(); return; } diff --git a/src/input/kbI2cBase.cpp b/src/input/kbI2cBase.cpp index f7fd62645..366e7fbb1 100644 --- a/src/input/kbI2cBase.cpp +++ b/src/input/kbI2cBase.cpp @@ -30,7 +30,7 @@ uint8_t read_from_14004(TwoWire *i2cBus, uint8_t reg, uint8_t *data, uint8_t len int32_t KbI2cBase::runOnce() { - if (cardkb_found.address != CARDKB_ADDR && cardkb_found.address != TDECK_KB_ADDR) { + if (cardkb_found.address == 0x00) { // Input device is not detected. return INT32_MAX; } @@ -41,11 +41,19 @@ int32_t KbI2cBase::runOnce() #ifdef I2C_SDA1 LOG_DEBUG("Using I2C Bus 1 (the second one)\n"); i2cBus = &Wire1; + if (cardkb_found.address == BBQ10_KB_ADDR) { + Q10keyboard.begin(BBQ10_KB_ADDR, &Wire1); + Q10keyboard.setBacklight(0); + } break; #endif case ScanI2C::WIRE: LOG_DEBUG("Using I2C Bus 0 (the first one)\n"); i2cBus = &Wire; + if (cardkb_found.address == BBQ10_KB_ADDR) { + Q10keyboard.begin(BBQ10_KB_ADDR, &Wire); + Q10keyboard.setBacklight(0); + } break; case ScanI2C::NO_I2C: default: @@ -53,7 +61,105 @@ int32_t KbI2cBase::runOnce() } } - if (kb_model == 0x02) { + switch (kb_model) { + case 0x11: { // BB Q10 + int keyCount = Q10keyboard.keyCount(); + while (keyCount--) { + const BBQ10Keyboard::KeyEvent key = Q10keyboard.keyEvent(); + if ((key.key != 0x00) && (key.state == BBQ10Keyboard::StateRelease)) { + InputEvent e; + e.inputEvent = meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_NONE; + e.source = this->_originName; + switch (key.key) { + case 'p': // TAB + case 't': // TAB as well + if (is_sym) { + e.inputEvent = ANYKEY; + e.kbchar = 0x09; // TAB Scancode + is_sym = false; // reset sym state after second keypress + } else { + e.inputEvent = ANYKEY; + e.kbchar = key.key; + } + break; + case 'q': // ESC + if (is_sym) { + e.inputEvent = meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_CANCEL; + e.kbchar = 0x1b; + is_sym = false; // reset sym state after second keypress + } else { + e.inputEvent = ANYKEY; + e.kbchar = key.key; + } + break; + case 0x08: // Back + e.inputEvent = meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_BACK; + e.kbchar = key.key; + break; + case 'e': // sym e + if (is_sym) { + e.inputEvent = meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_UP; + e.kbchar = 0xb5; + is_sym = false; // reset sym state after second keypress + } else { + e.inputEvent = ANYKEY; + e.kbchar = key.key; + } + break; + case 'x': // sym x + if (is_sym) { + e.inputEvent = meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_DOWN; + e.kbchar = 0xb6; + is_sym = false; // reset sym state after second keypress + } else { + e.inputEvent = ANYKEY; + e.kbchar = key.key; + } + break; + case 's': // sym s + if (is_sym) { + e.inputEvent = meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_LEFT; + e.kbchar = 0x00; // tweak for destSelect + is_sym = false; // reset sym state after second keypress + } else { + e.inputEvent = ANYKEY; + e.kbchar = key.key; + } + break; + case 'f': // sym f + if (is_sym) { + e.inputEvent = meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_RIGHT; + e.kbchar = 0x00; // tweak for destSelect + is_sym = false; // reset sym state after second keypress + } else { + e.inputEvent = ANYKEY; + e.kbchar = key.key; + } + break; + case 0x13: // Code scanner says the SYM key is 0x13 + is_sym = !is_sym; + break; + case 0x0a: // apparently Enter on Q10 is a line feed instead of carriage return + e.inputEvent = meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_SELECT; + break; + case 0x00: // nopress + e.inputEvent = meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_NONE; + break; + default: // all other keys + e.inputEvent = ANYKEY; + e.kbchar = key.key; + is_sym = false; // reset sym state after second keypress + break; + } + + if (e.inputEvent != meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_NONE) { + this->notifyObservers(&e); + } + } + } + break; + } + case 0x02: { // RAK14004 uint8_t rDataBuf[8] = {0}; uint8_t PrintDataBuf = 0; @@ -74,9 +180,12 @@ int32_t KbI2cBase::runOnce() e.kbchar = PrintDataBuf; this->notifyObservers(&e); } - } else if (kb_model == 0x00 || kb_model == 0x10) { - // m5 cardkb and T-Deck - i2cBus->requestFrom(kb_model == 0x00 ? CARDKB_ADDR : TDECK_KB_ADDR, 1); + break; + } + case 0x00: // CARDKB + case 0x10: { // T-DECK + + i2cBus->requestFrom((int)cardkb_found.address, 1); while (i2cBus->available()) { char c = i2cBus->read(); @@ -93,17 +202,19 @@ int32_t KbI2cBase::runOnce() break; case 0xb5: // Up e.inputEvent = meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_UP; + e.kbchar = 0xb5; break; case 0xb6: // Down e.inputEvent = meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_DOWN; + e.kbchar = 0xb6; break; case 0xb4: // Left e.inputEvent = meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_LEFT; - e.kbchar = c; + e.kbchar = 0xb4; break; case 0xb7: // Right e.inputEvent = meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_RIGHT; - e.kbchar = c; + e.kbchar = 0xb7; break; case 0x0d: // Enter e.inputEvent = meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_SELECT; @@ -121,7 +232,9 @@ int32_t KbI2cBase::runOnce() this->notifyObservers(&e); } } - } else { + break; + } + default: LOG_WARN("Unknown kb_model 0x%02x\n", kb_model); } return 300; diff --git a/src/input/kbI2cBase.h b/src/input/kbI2cBase.h index a0a4dd608..35b9b0901 100644 --- a/src/input/kbI2cBase.h +++ b/src/input/kbI2cBase.h @@ -1,5 +1,6 @@ #pragma once +#include "BBQ10Keyboard.h" #include "InputBroker.h" #include "Wire.h" #include "concurrency/OSThread.h" @@ -16,4 +17,7 @@ class KbI2cBase : public Observable, public concurrency::OST const char *_originName; TwoWire *i2cBus = 0; + + BBQ10Keyboard Q10keyboard; + bool is_sym = false; }; diff --git a/src/main.cpp b/src/main.cpp index d8311d555..987ed8962 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -387,6 +387,10 @@ void setup() // assign an arbitrary value to distinguish from other models kb_model = 0x10; break; + case ScanI2C::DeviceType::BBQ10KB: + // assign an arbitrary value to distinguish from other models + kb_model = 0x11; + break; default: // use this as default since it's also just zero LOG_WARN("kb_info.type is unknown(0x%02x), setting kb_model=0x00\n", kb_info.type); diff --git a/src/mesh/MeshService.cpp b/src/mesh/MeshService.cpp index 86a577b1b..3f93649bb 100644 --- a/src/mesh/MeshService.cpp +++ b/src/mesh/MeshService.cpp @@ -327,15 +327,15 @@ int MeshService::onGPSChanged(const meshtastic::GPSStatus *newStatus) // load data from GPS object, will add timestamp + battery further down pos = gps->p; } else { - // The GPS has lost lock, if we are fixed position we should just keep using - // the old position + // The GPS has lost lock #ifdef GPS_EXTRAVERBOSE LOG_DEBUG("onGPSchanged() - lost validLocation\n"); #endif - if (config.position.fixed_position) { - LOG_WARN("Using fixed position\n"); - pos = ConvertToPosition(node->position); - } + } + // Used fixed position if configured regalrdless of GPS lock + if (config.position.fixed_position) { + LOG_WARN("Using fixed position\n"); + pos = ConvertToPosition(node->position); } // Finally add a fresh timestamp and battery level reading diff --git a/src/mesh/MeshService.h b/src/mesh/MeshService.h index fa184b391..eb40b7712 100644 --- a/src/mesh/MeshService.h +++ b/src/mesh/MeshService.h @@ -48,6 +48,14 @@ class MeshService uint32_t oldFromNum = 0; public: + static bool isTextPayload(const meshtastic_MeshPacket *p) + { + if (moduleConfig.range_test.enabled && p->decoded.portnum == meshtastic_PortNum_RANGE_TEST_APP) { + return true; + } + return p->decoded.portnum == meshtastic_PortNum_TEXT_MESSAGE_APP || + p->decoded.portnum == meshtastic_PortNum_DETECTION_SENSOR_APP; + } /// Called when some new packets have arrived from one of the radios Observable fromNumChanged; diff --git a/src/mesh/generated/meshtastic/mesh.pb.h b/src/mesh/generated/meshtastic/mesh.pb.h index f319c58b9..887e4d11e 100644 --- a/src/mesh/generated/meshtastic/mesh.pb.h +++ b/src/mesh/generated/meshtastic/mesh.pb.h @@ -111,6 +111,8 @@ typedef enum _meshtastic_HardwareModel { meshtastic_HardwareModel_T_WATCH_S3 = 51, /* Bobricius Picomputer with ESP32-S3 CPU, Keyboard and IPS display */ meshtastic_HardwareModel_PICOMPUTER_S3 = 52, + /* Heltec HT-CT62 with ESP32-C3 CPU and SX1262 LoRa */ + meshtastic_HardwareModel_HELTEC_HT62 = 53, /* ------------------------------------------------------------------------------------------------------------------------------------------ Reserved ID For developing private Ports. These will show up in live traffic sparsely, so we can use a high number. Keep it within 8 bits. ------------------------------------------------------------------------------------------------------------------------------------------ */ diff --git a/src/mesh/generated/meshtastic/portnums.pb.h b/src/mesh/generated/meshtastic/portnums.pb.h index 44e9df70d..d354b7a42 100644 --- a/src/mesh/generated/meshtastic/portnums.pb.h +++ b/src/mesh/generated/meshtastic/portnums.pb.h @@ -69,6 +69,8 @@ typedef enum _meshtastic_PortNum { NOTE: audio frames contain a 3 byte header (0xc0 0xde 0xc2) and a one byte marker for the decompressed bitrate. This marker comes from the 'moduleConfig.audio.bitrate' enum minus one. */ meshtastic_PortNum_AUDIO_APP = 9, + /* Same as Text Message but originating from Detection Sensor Module. */ + meshtastic_PortNum_DETECTION_SENSOR_APP = 10, /* Provides a 'ping' service that replies to any packet it receives. Also serves as a small example module. ENCODING: ASCII Plaintext */ diff --git a/src/utils.h b/src/meshUtils.h similarity index 100% rename from src/utils.h rename to src/meshUtils.h diff --git a/src/modules/CannedMessageModule.cpp b/src/modules/CannedMessageModule.cpp index 1e605656f..ade9d0e5a 100644 --- a/src/modules/CannedMessageModule.cpp +++ b/src/modules/CannedMessageModule.cpp @@ -65,8 +65,8 @@ CannedMessageModule::CannedMessageModule() { if (moduleConfig.canned_message.enabled || CANNED_MESSAGE_MODULE_ENABLE) { this->loadProtoForModule(); - if ((this->splitConfiguredMessages() <= 0) && (cardkb_found.address != CARDKB_ADDR) && - (cardkb_found.address != TDECK_KB_ADDR) && !INPUTBROKER_MATRIX_TYPE && !CANNED_MESSAGE_MODULE_ENABLE) { + if ((this->splitConfiguredMessages() <= 0) && (cardkb_found.address == 0x00) && !INPUTBROKER_MATRIX_TYPE && + !CANNED_MESSAGE_MODULE_ENABLE) { LOG_INFO("CannedMessageModule: No messages are configured. Module is disabled\n"); this->runState = CANNED_MESSAGE_RUN_STATE_DISABLED; disable(); @@ -171,7 +171,7 @@ int CannedMessageModule::handleInputEvent(const InputEvent *event) (event->inputEvent == static_cast(meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_LEFT)) || (event->inputEvent == static_cast(meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_RIGHT))) { // LOG_DEBUG("Canned message event (%x)\n", event->kbchar); - // tweak for left/right events generated via trackball/touch with empty kbchar + // tweak for left/right events generated via trackball/touch with empty kbchar if (!event->kbchar) { if (event->inputEvent == static_cast(meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_LEFT)) { this->payload = 0xb4; @@ -195,6 +195,7 @@ int CannedMessageModule::handleInputEvent(const InputEvent *event) this->runState = CANNED_MESSAGE_RUN_STATE_FREETEXT; } // pass the pressed key + // LOG_DEBUG("Canned message ANYKEY (%x)\n", event->kbchar); this->payload = event->kbchar; this->lastTouchMillis = millis(); validEvent = true; @@ -649,4 +650,4 @@ String CannedMessageModule::drawWithCursor(String text, int cursor) return result; } -#endif \ No newline at end of file +#endif diff --git a/src/modules/DetectionSensorModule.cpp b/src/modules/DetectionSensorModule.cpp index c8eb7793b..f1fc26244 100644 --- a/src/modules/DetectionSensorModule.cpp +++ b/src/modules/DetectionSensorModule.cpp @@ -46,10 +46,7 @@ int32_t DetectionSensorModule::runOnce() if ((millis() - lastSentToMesh) >= getConfiguredOrDefaultMs(moduleConfig.detection_sensor.minimum_broadcast_secs) && hasDetectionEvent()) { sendDetectionMessage(); - return getConfiguredOrDefaultMs(moduleConfig.detection_sensor.minimum_broadcast_secs < - moduleConfig.detection_sensor.state_broadcast_secs - ? moduleConfig.detection_sensor.minimum_broadcast_secs - : moduleConfig.detection_sensor.state_broadcast_secs); + return DELAYED_INTERVAL; } // Even if we haven't detected an event, broadcast our current state to the mesh on the scheduled interval as a sort // of heartbeat. We only do this if the minimum broadcast interval is greater than zero, otherwise we'll only broadcast state @@ -57,10 +54,7 @@ int32_t DetectionSensorModule::runOnce() else if (moduleConfig.detection_sensor.state_broadcast_secs > 0 && (millis() - lastSentToMesh) >= getConfiguredOrDefaultMs(moduleConfig.detection_sensor.state_broadcast_secs)) { sendCurrentStateMessage(); - return getConfiguredOrDefaultMs(moduleConfig.detection_sensor.minimum_broadcast_secs < - moduleConfig.detection_sensor.state_broadcast_secs - ? moduleConfig.detection_sensor.minimum_broadcast_secs - : moduleConfig.detection_sensor.state_broadcast_secs); + return DELAYED_INTERVAL; } return GPIO_POLLING_INTERVAL; } diff --git a/src/modules/DetectionSensorModule.h b/src/modules/DetectionSensorModule.h index bcc0b9419..ed6cddda5 100644 --- a/src/modules/DetectionSensorModule.h +++ b/src/modules/DetectionSensorModule.h @@ -5,7 +5,7 @@ class DetectionSensorModule : public SinglePortModule, private concurrency::OSTh { public: DetectionSensorModule() - : SinglePortModule("detection", meshtastic_PortNum_TEXT_MESSAGE_APP), OSThread("DetectionSensorModule") + : SinglePortModule("detection", meshtastic_PortNum_DETECTION_SENSOR_APP), OSThread("DetectionSensorModule") { } diff --git a/src/modules/ExternalNotificationModule.cpp b/src/modules/ExternalNotificationModule.cpp index cbcf4e452..20191e706 100644 --- a/src/modules/ExternalNotificationModule.cpp +++ b/src/modules/ExternalNotificationModule.cpp @@ -128,6 +128,11 @@ int32_t ExternalNotificationModule::runOnce() } } +bool ExternalNotificationModule::wantPacket(const meshtastic_MeshPacket *p) +{ + return MeshService::isTextPayload(p); +} + /** * Sets the external notification on for the specified index. * @@ -212,8 +217,8 @@ void ExternalNotificationModule::stopNow() } ExternalNotificationModule::ExternalNotificationModule() - : SinglePortModule("ExternalNotificationModule", meshtastic_PortNum_TEXT_MESSAGE_APP), concurrency::OSThread( - "ExternalNotificationModule") + : SinglePortModule("ExternalNotificationModule", meshtastic_PortNum_TEXT_MESSAGE_APP), + concurrency::OSThread("ExternalNotificationModule") { /* Uncomment the preferences below if you want to use the module diff --git a/src/modules/ExternalNotificationModule.h b/src/modules/ExternalNotificationModule.h index f8ec053dd..3331ec428 100644 --- a/src/modules/ExternalNotificationModule.h +++ b/src/modules/ExternalNotificationModule.h @@ -52,6 +52,8 @@ class ExternalNotificationModule : public SinglePortModule, private concurrency: virtual int32_t runOnce() override; + virtual bool wantPacket(const meshtastic_MeshPacket *p) override; + bool isNagging = false; virtual AdminMessageHandleResult handleAdminMessageForModule(const meshtastic_MeshPacket &mp, @@ -59,4 +61,4 @@ class ExternalNotificationModule : public SinglePortModule, private concurrency: meshtastic_AdminMessage *response) override; }; -extern ExternalNotificationModule *externalNotificationModule; +extern ExternalNotificationModule *externalNotificationModule; \ No newline at end of file diff --git a/src/modules/NeighborInfoModule.cpp b/src/modules/NeighborInfoModule.cpp index 706b1db58..a5bb671f0 100644 --- a/src/modules/NeighborInfoModule.cpp +++ b/src/modules/NeighborInfoModule.cpp @@ -15,12 +15,12 @@ NOTE: For debugging only */ void NeighborInfoModule::printNeighborInfo(const char *header, const meshtastic_NeighborInfo *np) { - LOG_DEBUG("%s NEIGHBORINFO PACKET from Node %d to Node %d (last sent by %d)\n", header, np->node_id, nodeDB.getNodeNum(), - np->last_sent_by_id); + LOG_DEBUG("%s NEIGHBORINFO PACKET from Node 0x%x to Node 0x%x (last sent by 0x%x)\n", header, np->node_id, + nodeDB.getNodeNum(), np->last_sent_by_id); LOG_DEBUG("----------------\n"); LOG_DEBUG("Packet contains %d neighbors\n", np->neighbors_count); for (int i = 0; i < np->neighbors_count; i++) { - LOG_DEBUG("Neighbor %d: node_id=%d, snr=%.2f\n", i, np->neighbors[i].node_id, np->neighbors[i].snr); + LOG_DEBUG("Neighbor %d: node_id=0x%x, snr=%.2f\n", i, np->neighbors[i].node_id, np->neighbors[i].snr); } LOG_DEBUG("----------------\n"); } @@ -31,12 +31,12 @@ NOTE: for debugging only void NeighborInfoModule::printNodeDBNodes(const char *header) { int num_nodes = nodeDB.getNumMeshNodes(); - LOG_DEBUG("%s NODEDB SELECTION from Node %d:\n", header, nodeDB.getNodeNum()); + LOG_DEBUG("%s NODEDB SELECTION from Node 0x%x:\n", header, nodeDB.getNodeNum()); LOG_DEBUG("----------------\n"); LOG_DEBUG("DB contains %d nodes\n", num_nodes); for (int i = 0; i < num_nodes; i++) { const meshtastic_NodeInfoLite *dbEntry = nodeDB.getMeshNodeByIndex(i); - LOG_DEBUG(" Node %d: node_id=%d, snr=%.2f\n", i, dbEntry->num, dbEntry->snr); + LOG_DEBUG(" Node %d: node_id=0x%x, snr=%.2f\n", i, dbEntry->num, dbEntry->snr); } LOG_DEBUG("----------------\n"); } @@ -48,12 +48,12 @@ NOTE: for debugging only void NeighborInfoModule::printNodeDBNeighbors(const char *header) { int num_neighbors = getNumNeighbors(); - LOG_DEBUG("%s NODEDB SELECTION from Node %d:\n", header, nodeDB.getNodeNum()); + LOG_DEBUG("%s NODEDB SELECTION from Node 0x%x:\n", header, nodeDB.getNodeNum()); LOG_DEBUG("----------------\n"); LOG_DEBUG("DB contains %d neighbors\n", num_neighbors); for (int i = 0; i < num_neighbors; i++) { const meshtastic_Neighbor *dbEntry = getNeighborByIndex(i); - LOG_DEBUG(" Node %d: node_id=%d, snr=%.2f\n", i, dbEntry->node_id, dbEntry->snr); + LOG_DEBUG(" Node %d: node_id=0x%x, snr=%.2f\n", i, dbEntry->node_id, dbEntry->snr); } LOG_DEBUG("----------------\n"); } @@ -66,7 +66,7 @@ NOTE: For debugging only void NeighborInfoModule::printNodeDBSelection(const char *header, const meshtastic_NeighborInfo *np) { int num_neighbors = getNumNeighbors(); - LOG_DEBUG("%s NODEDB SELECTION from Node %d:\n", header, nodeDB.getNodeNum()); + LOG_DEBUG("%s NODEDB SELECTION from Node 0x%x:\n", header, nodeDB.getNodeNum()); LOG_DEBUG("----------------\n"); LOG_DEBUG("Selected %d neighbors of %d DB neighbors\n", np->neighbors_count, num_neighbors); for (int i = 0; i < num_neighbors; i++) { @@ -78,9 +78,9 @@ void NeighborInfoModule::printNodeDBSelection(const char *header, const meshtast } } if (!chosen) { - LOG_DEBUG(" Node %d: neighbor=%d, snr=%.2f\n", i, dbEntry->node_id, dbEntry->snr); + LOG_DEBUG(" Node %d: neighbor=0x%x, snr=%.2f\n", i, dbEntry->node_id, dbEntry->snr); } else { - LOG_DEBUG("---> Node %d: neighbor=%d, snr=%.2f\n", i, dbEntry->node_id, dbEntry->snr); + LOG_DEBUG("---> Node %d: neighbor=0x%x, snr=%.2f\n", i, dbEntry->node_id, dbEntry->snr); } } LOG_DEBUG("----------------\n"); @@ -120,7 +120,7 @@ Assumes that the neighborInfo packet has been allocated */ uint32_t NeighborInfoModule::collectNeighborInfo(meshtastic_NeighborInfo *neighborInfo) { - int my_node_id = nodeDB.getNodeNum(); + uint my_node_id = nodeDB.getNodeNum(); neighborInfo->node_id = my_node_id; neighborInfo->last_sent_by_id = my_node_id; neighborInfo->node_broadcast_interval_secs = moduleConfig.neighbor_info.update_interval; @@ -255,7 +255,7 @@ void NeighborInfoModule::updateNeighbors(const meshtastic_MeshPacket &mp, const } meshtastic_Neighbor *NeighborInfoModule::getOrCreateNeighbor(NodeNum originalSender, NodeNum n, - uint32_t node_broadcast_interval_secs, int snr) + uint32_t node_broadcast_interval_secs, float snr) { // our node and the phone are the same node (not neighbors) if (n == 0) { diff --git a/src/modules/NeighborInfoModule.h b/src/modules/NeighborInfoModule.h index 20f68ca87..0e3ec09ca 100644 --- a/src/modules/NeighborInfoModule.h +++ b/src/modules/NeighborInfoModule.h @@ -49,7 +49,7 @@ class NeighborInfoModule : public ProtobufModule, priva meshtastic_NeighborInfo *allocateNeighborInfoPacket(); // Find a neighbor in our DB, create an empty neighbor if missing - meshtastic_Neighbor *getOrCreateNeighbor(NodeNum originalSender, NodeNum n, uint32_t node_broadcast_interval_secs, int snr); + meshtastic_Neighbor *getOrCreateNeighbor(NodeNum originalSender, NodeNum n, uint32_t node_broadcast_interval_secs, float snr); /* * Send info on our node's neighbors into the mesh diff --git a/src/modules/PositionModule.cpp b/src/modules/PositionModule.cpp index cb49f0a8f..40dbf266e 100644 --- a/src/modules/PositionModule.cpp +++ b/src/modules/PositionModule.cpp @@ -11,8 +11,8 @@ PositionModule *positionModule; PositionModule::PositionModule() - : ProtobufModule("position", meshtastic_PortNum_POSITION_APP, &meshtastic_Position_msg), concurrency::OSThread( - "PositionModule") + : ProtobufModule("position", meshtastic_PortNum_POSITION_APP, &meshtastic_Position_msg), + concurrency::OSThread("PositionModule") { isPromiscuous = true; // We always want to update our nodedb, even if we are sniffing on others setIntervalFromNow(60 * 1000); // Send our initial position 60 seconds after we start (to give GPS time to setup) @@ -65,7 +65,7 @@ bool PositionModule::handleReceivedProtobuf(const meshtastic_MeshPacket &mp, mes meshtastic_MeshPacket *PositionModule::allocReply() { if (ignoreRequest) { - return NULL; + return nullptr; } meshtastic_NodeInfoLite *node = service.refreshLocalMeshNode(); // should guarantee there is now a position @@ -142,6 +142,11 @@ void PositionModule::sendOurPosition(NodeNum dest, bool wantReplies, uint8_t cha service.cancelSending(prevPacketId); meshtastic_MeshPacket *p = allocReply(); + if (p == nullptr) { + LOG_WARN("allocReply returned a nullptr"); + return; + } + p->to = dest; p->decoded.want_response = wantReplies; if (config.device.role == meshtastic_Config_DeviceConfig_Role_TRACKER) diff --git a/src/modules/RangeTestModule.h b/src/modules/RangeTestModule.h index ae2a8f182..b632d343e 100644 --- a/src/modules/RangeTestModule.h +++ b/src/modules/RangeTestModule.h @@ -29,7 +29,7 @@ class RangeTestModuleRadio : public SinglePortModule uint32_t lastRxID = 0; public: - RangeTestModuleRadio() : SinglePortModule("RangeTestModuleRadio", meshtastic_PortNum_TEXT_MESSAGE_APP) + RangeTestModuleRadio() : SinglePortModule("RangeTestModuleRadio", meshtastic_PortNum_RANGE_TEST_APP) { loopbackOk = true; // Allow locally generated messages to loop back to the client } diff --git a/src/modules/TextMessageModule.cpp b/src/modules/TextMessageModule.cpp index 8ff034fa9..0f86a6470 100644 --- a/src/modules/TextMessageModule.cpp +++ b/src/modules/TextMessageModule.cpp @@ -1,4 +1,5 @@ #include "TextMessageModule.h" +#include "MeshService.h" #include "NodeDB.h" #include "PowerFSM.h" #include "configuration.h" @@ -22,3 +23,8 @@ ProcessMessage TextMessageModule::handleReceived(const meshtastic_MeshPacket &mp return ProcessMessage::CONTINUE; // Let others look at this message also if they want } + +bool TextMessageModule::wantPacket(const meshtastic_MeshPacket *p) +{ + return MeshService::isTextPayload(p); +} \ No newline at end of file diff --git a/src/modules/TextMessageModule.h b/src/modules/TextMessageModule.h index 93b1bfaa2..cc0b0f9d5 100644 --- a/src/modules/TextMessageModule.h +++ b/src/modules/TextMessageModule.h @@ -20,6 +20,7 @@ class TextMessageModule : public SinglePortModule, public Observable #include #include @@ -220,4 +220,4 @@ void cpuDeepSleep(uint32_t msecToWake) esp_sleep_enable_timer_wakeup(msecToWake * 1000ULL); // call expects usecs esp_deep_sleep_start(); // TBD mA sleep current (battery) -} +} \ No newline at end of file diff --git a/variants/heltec_esp32c3/pins_arduino.h b/variants/heltec_esp32c3/pins_arduino.h new file mode 100644 index 000000000..db30a2f30 --- /dev/null +++ b/variants/heltec_esp32c3/pins_arduino.h @@ -0,0 +1,32 @@ +#ifndef Pins_Arduino_h +#define Pins_Arduino_h + +#include + +#define EXTERNAL_NUM_INTERRUPTS 22 +#define NUM_DIGITAL_PINS 22 +#define NUM_ANALOG_INPUTS 6 + +#define analogInputToDigitalPin(p) (((p) < NUM_ANALOG_INPUTS) ? (esp32_adc2gpio[(p)]) : -1) +#define digitalPinToInterrupt(p) (((p) < NUM_DIGITAL_PINS) ? (p) : -1) +#define digitalPinHasPWM(p) (p < EXTERNAL_NUM_INTERRUPTS) + +static const uint8_t TX = 21; +static const uint8_t RX = 20; + +static const uint8_t SDA = 1; +static const uint8_t SCL = 0; + +static const uint8_t SS = 8; +static const uint8_t MOSI = 7; +static const uint8_t MISO = 6; +static const uint8_t SCK = 10; + +static const uint8_t A0 = 0; +static const uint8_t A1 = 1; +static const uint8_t A2 = 2; +static const uint8_t A3 = 3; +static const uint8_t A4 = 4; +static const uint8_t A5 = 5; + +#endif /* Pins_Arduino_h */ \ No newline at end of file diff --git a/variants/heltec_esp32c3/platformio.ini b/variants/heltec_esp32c3/platformio.ini new file mode 100644 index 000000000..a9843ef85 --- /dev/null +++ b/variants/heltec_esp32c3/platformio.ini @@ -0,0 +1,12 @@ +[env:heltec-ht62-esp32c3-sx1262] +extends = esp32c3_base +board = esp32-c3-devkitm-1 +board_level = extra +build_flags = + ${esp32_base.build_flags} + -D HELTEC_HT62 + -I variants/heltec_esp32c3 +monitor_speed = 115200 +upload_protocol = esptool +upload_port = /dev/ttyUSB0 +upload_speed = 921600 diff --git a/variants/heltec_esp32c3/variant.h b/variants/heltec_esp32c3/variant.h new file mode 100644 index 000000000..29ed88080 --- /dev/null +++ b/variants/heltec_esp32c3/variant.h @@ -0,0 +1,36 @@ +#define I2C_SDA 1 +#define I2C_SCL 0 + +#define BUTTON_PIN 9 +#define BUTTON_NEED_PULLUP + +// LED flashes brighter +// https://resource.heltec.cn/download/HT-CT62/HT-CT62_Reference_Design.pdf +#define LED_PIN 18 // LED +#define LED_INVERTED 1 + +#define HAS_SCREEN 0 +#define HAS_GPS 0 +#undef GPS_RX_PIN +#undef GPS_TX_PIN + +#undef RF95_SCK +#undef RF95_MISO +#undef RF95_MOSI +#undef RF95_NSS + +#define USE_SX1262 +#define RF95_SCK 10 +#define RF95_MISO 6 +#define RF95_MOSI 7 +#define RF95_NSS 8 +#define LORA_DIO0 RADIOLIB_NC +#define LORA_RESET 5 +#define LORA_DIO1 3 +#define LORA_DIO2 RADIOLIB_NC +#define LORA_BUSY 4 +#define SX126X_CS RF95_NSS +#define SX126X_DIO1 LORA_DIO1 +#define SX126X_BUSY LORA_BUSY +#define SX126X_RESET LORA_RESET +#define SX126X_E22 diff --git a/version.properties b/version.properties index f26bc2b58..830d7970e 100644 --- a/version.properties +++ b/version.properties @@ -1,4 +1,4 @@ [VERSION] major = 2 minor = 2 -build = 2 +build = 4