diff --git a/bin/build-native.sh b/bin/build-native.sh index e8ed61bcf..cda77b064 100755 --- a/bin/build-native.sh +++ b/bin/build-native.sh @@ -27,5 +27,4 @@ rm -r $OUTDIR/* || true platformio pkg update --environment native || platformioFailed pio run --environment native || platformioFailed cp .pio/build/native/program "$OUTDIR/meshtasticd_linux_$(uname -m)" -cp bin/device-install.* $OUTDIR -cp bin/device-update.* $OUTDIR +cp bin/native-install.* $OUTDIR diff --git a/release/latest/.gitignore b/release/latest/.gitignore deleted file mode 100644 index fff416667..000000000 --- a/release/latest/.gitignore +++ /dev/null @@ -1 +0,0 @@ -curfirmwareversion.xml diff --git a/src/AudioThread.h b/src/AudioThread.h index bb23e8598..6d560ec55 100644 --- a/src/AudioThread.h +++ b/src/AudioThread.h @@ -64,7 +64,7 @@ class AudioThread : public concurrency::OSThread void initOutput() { audioOut = new AudioOutputI2S(1, AudioOutputI2S::EXTERNAL_I2S); - audioOut->SetPinout(DAC_I2S_BCK, DAC_I2S_WS, DAC_I2S_DOUT); + audioOut->SetPinout(DAC_I2S_BCK, DAC_I2S_WS, DAC_I2S_DOUT, DAC_I2S_MCLK); audioOut->SetGain(0.2); }; diff --git a/src/gps/GPS.h b/src/gps/GPS.h index cd61c5444..cb970f7db 100644 --- a/src/gps/GPS.h +++ b/src/gps/GPS.h @@ -64,6 +64,95 @@ const char *getDOPString(uint32_t dop); */ class GPS : private concurrency::OSThread { + public: + meshtastic_Position p = meshtastic_Position_init_default; + + /** This is normally bound to config.position.gps_en_gpio but some rare boards (like heltec tracker) need more advanced + * implementations. Those boards will set this public variable to a custom implementation. + * + * Normally set by GPS::createGPS() + */ + GpioVirtPin *enablePin = NULL; + + virtual ~GPS(); + + /** We will notify this observable anytime GPS state has changed meaningfully */ + Observable newStatus; + + /** + * Returns true if we succeeded + */ + virtual bool setup(); + + // re-enable the thread + void enable(); + + // Disable the thread + int32_t disable() override; + + // toggle between enabled/disabled + void toggleGpsMode(); + + // Change the power state of the GPS - for power saving / shutdown + void setPowerState(GPSPowerState newState, uint32_t sleepMs = 0); + + /// Returns true if we have acquired GPS lock. + virtual bool hasLock(); + + /// Returns true if there's valid data flow with the chip. + virtual bool hasFlow(); + + /// Return true if we are connected to a GPS + bool isConnected() const { return hasGPS; } + + bool isPowerSaving() const { return config.position.gps_mode != meshtastic_Config_PositionConfig_GpsMode_ENABLED; } + + // Empty the input buffer as quickly as possible + void clearBuffer(); + + virtual bool factoryReset(); + + // Creates an instance of the GPS class. + // Returns the new instance or null if the GPS is not present. + static GPS *createGps(); + + // Wake the GPS hardware - ready for an update + void up(); + + // Let the GPS hardware save power between updates + void down(); + + protected: + /// Record that we have a GPS + void setConnected(); + + /** Subclasses should look for serial rx characters here and feed it to their GPS parser + * + * Return true if we received a valid message from the GPS + */ + virtual bool whileActive(); + + /** + * Perform any processing that should be done only while the GPS is awake and looking for a fix. + * Override this method to check for new locations + * + * @return true if we've acquired a time + */ + virtual bool lookForTime(); + + /** + * Perform any processing that should be done only while the GPS is awake and looking for a fix. + * Override this method to check for new locations + * + * @return true if we've acquired a new location + */ + virtual bool lookForLocation(); + + GnssModel_t gnssModel = GNSS_MODEL_UNKNOWN; + + private: + GPS() : concurrency::OSThread("GPS") {} + TinyGPSPlus reader; uint8_t fixQual = 0; // fix quality from GPGGA uint32_t lastChecksumFailCount = 0; @@ -75,7 +164,6 @@ class GPS : private concurrency::OSThread TinyGPSCustom gsapdop; // custom extract PDOP from GPGSA uint8_t fixType = 0; // fix type from GPGSA #endif - private: #if GPS_BAUDRATE_FIXED // if GPS_BAUDRATE is specified in variant, only try that. const int serialSpeeds[1] = {GPS_BAUDRATE}; @@ -113,7 +201,6 @@ class GPS : private concurrency::OSThread CallbackObserver notifyDeepSleepObserver = CallbackObserver(this, &GPS::prepareDeepSleep); - public: /** If !NULL we will use this serial port to construct our GPS */ #if defined(ARCH_RP2040) static SerialUART *_serial_gps; @@ -167,53 +254,6 @@ class GPS : private concurrency::OSThread const char *ACK_SUCCESS_MESSAGE = "Get ack success!"; - meshtastic_Position p = meshtastic_Position_init_default; - - /** This is normally bound to config.position.gps_en_gpio but some rare boards (like heltec tracker) need more advanced - * implementations. Those boards will set this public variable to a custom implementation. - * - * Normally set by GPS::createGPS() - */ - GpioVirtPin *enablePin = NULL; - - GPS() : concurrency::OSThread("GPS") {} - - virtual ~GPS(); - - /** We will notify this observable anytime GPS state has changed meaningfully */ - Observable newStatus; - - /** - * Returns true if we succeeded - */ - virtual bool setup(); - - // re-enable the thread - void enable(); - - // Disable the thread - int32_t disable() override; - - // toggle between enabled/disabled - void toggleGpsMode(); - - // Change the power state of the GPS - for power saving / shutdown - void setPowerState(GPSPowerState newState, uint32_t sleepMs = 0); - - /// Returns true if we have acquired GPS lock. - virtual bool hasLock(); - - /// Returns true if there's valid data flow with the chip. - virtual bool hasFlow(); - - /// Return true if we are connected to a GPS - bool isConnected() const { return hasGPS; } - - bool isPowerSaving() const { return config.position.gps_mode != meshtastic_Config_PositionConfig_GpsMode_ENABLED; } - - // Empty the input buffer as quickly as possible - void clearBuffer(); - // Create a ublox packet for editing in memory uint8_t makeUBXPacket(uint8_t class_id, uint8_t msg_id, uint8_t payload_size, const uint8_t *msg); uint8_t makeCASPacket(uint8_t class_id, uint8_t msg_id, uint8_t payload_size, const uint8_t *msg); @@ -229,59 +269,6 @@ class GPS : private concurrency::OSThread GPS_RESPONSE getACKCas(uint8_t class_id, uint8_t msg_id, uint32_t waitMillis); - virtual bool factoryReset(); - - // Creates an instance of the GPS class. - // Returns the new instance or null if the GPS is not present. - static GPS *createGps(); - - // Wake the GPS hardware - ready for an update - void up(); - - // Let the GPS hardware save power between updates - void down(); - - protected: - /** - * Perform any processing that should be done only while the GPS is awake and looking for a fix. - * Override this method to check for new locations - * - * @return true if we've acquired a time - */ - - /** - * Perform any processing that should be done only while the GPS is awake and looking for a fix. - * Override this method to check for new locations - * - * @return true if we've acquired a new location - */ - - /// Record that we have a GPS - void setConnected(); - - /** Subclasses should look for serial rx characters here and feed it to their GPS parser - * - * Return true if we received a valid message from the GPS - */ - virtual bool whileActive(); - - /** - * Perform any processing that should be done only while the GPS is awake and looking for a fix. - * Override this method to check for new locations - * - * @return true if we've acquired a time - */ - virtual bool lookForTime(); - - /** - * Perform any processing that should be done only while the GPS is awake and looking for a fix. - * Override this method to check for new locations - * - * @return true if we've acquired a new location - */ - virtual bool lookForLocation(); - - private: /// Prepare the GPS for the cpu entering deep sleep, expect to be gone for at least 100s of msecs /// always returns 0 to indicate okay to sleep int prepareDeepSleep(void *unused); @@ -320,10 +307,7 @@ class GPS : private concurrency::OSThread uint8_t fixeddelayCtr = 0; const char *powerStateToString(); - - protected: - GnssModel_t gnssModel = GNSS_MODEL_UNKNOWN; }; extern GPS *gps; -#endif // Exclude GPS \ No newline at end of file +#endif // Exclude GPS diff --git a/src/graphics/Screen.cpp b/src/graphics/Screen.cpp index f18baf276..a875c11d6 100644 --- a/src/graphics/Screen.cpp +++ b/src/graphics/Screen.cpp @@ -396,7 +396,7 @@ static void drawBattery(OLEDDisplay *display, int16_t x, int16_t y, uint8_t *img display->drawFastImage(x, y, 16, 8, imgBuffer); } -#ifdef T_WATCH_S3 +#if defined(DISPLAY_CLOCK_FRAME) void Screen::drawWatchFaceToggleButton(OLEDDisplay *display, int16_t x, int16_t y, bool digitalMode, float scale) { @@ -2068,7 +2068,7 @@ void Screen::setFrames(FrameFocus focus) focus = FOCUS_FAULT; // Change our "focus" parameter, to ensure we show the fault frame } -#ifdef T_WATCH_S3 +#if defined(DISPLAY_CLOCK_FRAME) normalFrames[numframes++] = screen->digitalWatchFace ? &Screen::drawDigitalClockFrame : &Screen::drawAnalogClockFrame; #endif @@ -2699,7 +2699,7 @@ int Screen::handleUIFrameEvent(const UIFrameEvent *event) int Screen::handleInputEvent(const InputEvent *event) { -#ifdef T_WATCH_S3 +#if defined(DISPLAY_CLOCK_FRAME) // For the T-Watch, intercept touches to the 'toggle digital/analog watch face' button uint8_t watchFaceFrame = error_code ? 1 : 0; diff --git a/src/graphics/Screen.h b/src/graphics/Screen.h index ee8de69f0..2a77ca575 100644 --- a/src/graphics/Screen.h +++ b/src/graphics/Screen.h @@ -554,7 +554,7 @@ class Screen : public concurrency::OSThread static void drawDebugInfoWiFiTrampoline(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16_t y); -#ifdef T_WATCH_S3 +#if defined(DISPLAY_CLOCK_FRAME) static void drawAnalogClockFrame(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16_t y); static void drawDigitalClockFrame(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16_t y); diff --git a/src/graphics/images.h b/src/graphics/images.h index fb6b176fc..b757dcf30 100644 --- a/src/graphics/images.h +++ b/src/graphics/images.h @@ -14,7 +14,7 @@ const uint8_t imgUser[] PROGMEM = {0x3C, 0x42, 0x99, 0xA5, 0xA5, 0x99, 0x42, 0x3 const uint8_t imgPositionEmpty[] PROGMEM = {0x20, 0x30, 0x28, 0x24, 0x42, 0xFF}; const uint8_t imgPositionSolid[] PROGMEM = {0x20, 0x30, 0x38, 0x3C, 0x7E, 0xFF}; -#ifdef T_WATCH_S3 +#if defined(DISPLAY_CLOCK_FRAME) const uint8_t bluetoothConnectedIcon[36] PROGMEM = {0xfe, 0x01, 0xff, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x00, 0xe3, 0x1f, 0xf3, 0x3f, 0x33, 0x30, 0x33, 0x33, 0x33, 0x33, 0x03, 0x33, 0xff, 0x33, 0xfe, 0x31, 0x00, 0x30, 0x30, 0x30, 0x30, 0x30, 0xf0, 0x3f, 0xe0, 0x1f}; diff --git a/src/mesh/NodeDB.cpp b/src/mesh/NodeDB.cpp index 61bcc5bc9..44a28eea2 100644 --- a/src/mesh/NodeDB.cpp +++ b/src/mesh/NodeDB.cpp @@ -518,7 +518,7 @@ void NodeDB::installDefaultConfig(bool preserveKey = false) #ifdef RAK4630 config.display.wake_on_tap_or_motion = true; #endif -#ifdef T_WATCH_S3 +#if defined(T_WATCH_S3) || defined(SENSECAP_INDICATOR) config.display.screen_on_secs = 30; config.display.wake_on_tap_or_motion = true; #endif @@ -542,7 +542,7 @@ void NodeDB::initConfigIntervals() config.display.screen_on_secs = default_screen_on_secs; -#if defined(T_WATCH_S3) || defined(T_DECK) || defined(RAK14014) +#if defined(T_WATCH_S3) || defined(T_DECK) || defined(RAK14014) || defined(SENSECAP_INDICATOR) config.power.is_power_saving = true; config.display.screen_on_secs = 30; config.power.wait_bluetooth_secs = 30; diff --git a/src/modules/CannedMessageModule.cpp b/src/modules/CannedMessageModule.cpp index 6d1bfdc5c..a96fcc080 100644 --- a/src/modules/CannedMessageModule.cpp +++ b/src/modules/CannedMessageModule.cpp @@ -55,7 +55,7 @@ CannedMessageModule::CannedMessageModule() LOG_INFO("CannedMessageModule is enabled"); // T-Watch interface currently has no way to select destination type, so default to 'node' -#if defined(T_WATCH_S3) || defined(RAK14014) +#if defined(USE_VIRTUAL_KEYBOARD) this->destSelect = CANNED_MESSAGE_DESTINATION_TYPE_NODE; #endif @@ -81,7 +81,7 @@ int CannedMessageModule::splitConfiguredMessages() String canned_messages = cannedMessageModuleConfig.messages; -#if defined(T_WATCH_S3) || defined(RAK14014) +#if defined(USE_VIRTUAL_KEYBOARD) String separator = canned_messages.length() ? "|" : ""; canned_messages = "[---- Free Text ----]" + separator + canned_messages; @@ -150,7 +150,7 @@ int CannedMessageModule::handleInputEvent(const InputEvent *event) } if (event->inputEvent == static_cast(meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_SELECT)) { -#if defined(T_WATCH_S3) || defined(RAK14014) +#if defined(USE_VIRTUAL_KEYBOARD) if (this->currentMessageIndex == 0) { this->runState = CANNED_MESSAGE_RUN_STATE_FREETEXT; @@ -177,7 +177,7 @@ int CannedMessageModule::handleInputEvent(const InputEvent *event) e.action = UIFrameEvent::Action::REGENERATE_FRAMESET; // We want to change the list of frames shown on-screen this->currentMessageIndex = -1; -#if !defined(T_WATCH_S3) && !defined(RAK14014) +#if !defined(T_WATCH_S3) && !defined(RAK14014) && !defined(USE_VIRTUAL_KEYBOARD) this->freetext = ""; // clear freetext this->cursor = 0; this->destSelect = CANNED_MESSAGE_DESTINATION_TYPE_NONE; @@ -190,7 +190,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))) { -#if defined(T_WATCH_S3) || defined(RAK14014) +#if defined(USE_VIRTUAL_KEYBOARD) if (event->inputEvent == static_cast(meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_LEFT)) { this->payload = INPUT_BROKER_MSG_LEFT; } else if (event->inputEvent == static_cast(meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_RIGHT)) { @@ -312,7 +312,7 @@ int CannedMessageModule::handleInputEvent(const InputEvent *event) } } -#if defined(T_WATCH_S3) || defined(RAK14014) +#if defined(USE_VIRTUAL_KEYBOARD) if (this->runState == CANNED_MESSAGE_RUN_STATE_FREETEXT) { String keyTapped = keyForCoordinates(event->touchX, event->touchY); @@ -446,7 +446,7 @@ int32_t CannedMessageModule::runOnce() this->freetext = ""; // clear freetext this->cursor = 0; -#if !defined(T_WATCH_S3) && !defined(RAK14014) +#if !defined(T_WATCH_S3) && !defined(RAK14014) && !defined(SENSECAP_INDICATOR) this->destSelect = CANNED_MESSAGE_DESTINATION_TYPE_NONE; #endif @@ -459,7 +459,7 @@ int32_t CannedMessageModule::runOnce() this->freetext = ""; // clear freetext this->cursor = 0; -#if !defined(T_WATCH_S3) && !defined(RAK14014) +#if !defined(T_WATCH_S3) && !defined(RAK14014) && !defined(USE_VIRTUAL_KEYBOARD) this->destSelect = CANNED_MESSAGE_DESTINATION_TYPE_NONE; #endif @@ -479,7 +479,7 @@ int32_t CannedMessageModule::runOnce() powerFSM.trigger(EVENT_PRESS); return INT32_MAX; } else { -#if defined(T_WATCH_S3) || defined(RAK14014) +#if defined(USE_VIRTUAL_KEYBOARD) sendText(this->dest, indexChannels[this->channel], this->messages[this->currentMessageIndex], true); #else sendText(NODENUM_BROADCAST, channels.getPrimaryIndex(), this->messages[this->currentMessageIndex], true); @@ -496,7 +496,7 @@ int32_t CannedMessageModule::runOnce() this->freetext = ""; // clear freetext this->cursor = 0; -#if !defined(T_WATCH_S3) && !defined(RAK14014) +#if !defined(T_WATCH_S3) && !defined(RAK14014) && !defined(USE_VIRTUAL_KEYBOARD) this->destSelect = CANNED_MESSAGE_DESTINATION_TYPE_NONE; #endif @@ -513,7 +513,7 @@ int32_t CannedMessageModule::runOnce() this->freetext = ""; // clear freetext this->cursor = 0; -#if !defined(T_WATCH_S3) && !defined(RAK14014) +#if !defined(T_WATCH_S3) && !defined(RAK14014) && !defined(USE_VIRTUAL_KEYBOARD) this->destSelect = CANNED_MESSAGE_DESTINATION_TYPE_NONE; #endif @@ -526,7 +526,7 @@ int32_t CannedMessageModule::runOnce() this->freetext = ""; // clear freetext this->cursor = 0; -#if !defined(T_WATCH_S3) && !defined(RAK14014) +#if !defined(T_WATCH_S3) && !defined(RAK14014) && !defined(USE_VIRTUAL_KEYBOARD) this->destSelect = CANNED_MESSAGE_DESTINATION_TYPE_NONE; #endif @@ -769,7 +769,7 @@ void CannedMessageModule::showTemporaryMessage(const String &message) setIntervalFromNow(2000); } -#if defined(T_WATCH_S3) || defined(RAK14014) +#if defined(USE_VIRTUAL_KEYBOARD) String CannedMessageModule::keyForCoordinates(uint x, uint y) { @@ -1055,7 +1055,7 @@ void CannedMessageModule::drawFrame(OLEDDisplay *display, OLEDDisplayUiState *st display->drawString(10 + x, 0 + y + FONT_HEIGHT_SMALL, "Canned Message\nModule disabled."); } else if (cannedMessageModule->runState == CANNED_MESSAGE_RUN_STATE_FREETEXT) { requestFocus(); // Tell Screen::setFrames to move to our module's frame -#if defined(T_WATCH_S3) || defined(RAK14014) +#if defined(USE_VIRTUAL_KEYBOARD) drawKeyboard(display, state, 0, 0); #else diff --git a/src/modules/CannedMessageModule.h b/src/modules/CannedMessageModule.h index 4427be144..fd9ffc9b6 100644 --- a/src/modules/CannedMessageModule.h +++ b/src/modules/CannedMessageModule.h @@ -102,7 +102,7 @@ class CannedMessageModule : public SinglePortModule, public Observable