mirror of
https://github.com/meshtastic/firmware.git
synced 2025-06-07 21:52:05 +00:00
Compare commits
2 Commits
94e0b209bc
...
75e41c1604
Author | SHA1 | Date | |
---|---|---|---|
![]() |
75e41c1604 | ||
![]() |
3955a5616e |
@ -184,7 +184,6 @@ static void serialEnter()
|
||||
setBluetoothEnable(false);
|
||||
if (screen) {
|
||||
screen->setOn(true);
|
||||
screen->print("Serial connected\n");
|
||||
}
|
||||
}
|
||||
|
||||
@ -192,8 +191,6 @@ static void serialExit()
|
||||
{
|
||||
// Turn bluetooth back on when we leave serial stream API
|
||||
setBluetoothEnable(true);
|
||||
if (screen)
|
||||
screen->print("Serial disconnected\n");
|
||||
}
|
||||
|
||||
static void powerEnter()
|
||||
@ -208,12 +205,6 @@ static void powerEnter()
|
||||
screen->setOn(true);
|
||||
setBluetoothEnable(true);
|
||||
// within enter() the function getState() returns the state we came from
|
||||
|
||||
// Mothballed: print change of power-state to device screen
|
||||
/* if (strcmp(powerFSM.getState()->name, "BOOT") != 0 && strcmp(powerFSM.getState()->name, "POWER") != 0 &&
|
||||
strcmp(powerFSM.getState()->name, "DARK") != 0) {
|
||||
screen->print("Powered...\n");
|
||||
}*/
|
||||
}
|
||||
}
|
||||
|
||||
@ -231,10 +222,6 @@ static void powerExit()
|
||||
if (screen)
|
||||
screen->setOn(true);
|
||||
setBluetoothEnable(true);
|
||||
|
||||
// Mothballed: print change of power-state to device screen
|
||||
/*if (!isPowered())
|
||||
screen->print("Unpowered...\n");*/
|
||||
}
|
||||
|
||||
static void onEnter()
|
||||
|
@ -12,7 +12,6 @@ enum class Cmd {
|
||||
STOP_ALERT_FRAME,
|
||||
START_FIRMWARE_UPDATE_SCREEN,
|
||||
STOP_BOOT_SCREEN,
|
||||
PRINT,
|
||||
SHOW_PREV_FRAME,
|
||||
SHOW_NEXT_FRAME
|
||||
};
|
@ -1201,10 +1201,6 @@ int32_t Screen::runOnce()
|
||||
EINK_ADD_FRAMEFLAG(dispdev, COSMETIC); // E-Ink: Explicitly use full-refresh for next frame
|
||||
setFrames();
|
||||
break;
|
||||
case Cmd::PRINT:
|
||||
handlePrint(cmd.print_text);
|
||||
free(cmd.print_text);
|
||||
break;
|
||||
default:
|
||||
LOG_ERROR("Invalid screen cmd");
|
||||
}
|
||||
@ -1334,15 +1330,6 @@ void Screen::setFrames(FrameFocus focus)
|
||||
showingNormalScreen = true;
|
||||
|
||||
indicatorIcons.clear();
|
||||
#ifdef USE_EINK
|
||||
// If user has disabled the screensaver, warn them after boot
|
||||
static bool warnedScreensaverDisabled = false;
|
||||
if (config.display.screen_on_secs == 0 && !warnedScreensaverDisabled) {
|
||||
screen->print("Screensaver disabled\n");
|
||||
warnedScreensaverDisabled = true;
|
||||
}
|
||||
#endif
|
||||
|
||||
moduleFrames = MeshModule::GetMeshModulesWithUIFrames();
|
||||
LOG_DEBUG("Show %d module frames", moduleFrames.size());
|
||||
#ifdef DEBUG_PORT
|
||||
@ -1627,17 +1614,6 @@ void Screen::removeFunctionSymbol(std::string sym)
|
||||
setFastFramerate();
|
||||
}
|
||||
|
||||
void Screen::handlePrint(const char *text)
|
||||
{
|
||||
// the string passed into us probably has a newline, but that would confuse the logging system
|
||||
// so strip it
|
||||
LOG_DEBUG("Screen: %.*s", strlen(text) - 1, text);
|
||||
if (!useDisplay || !showingNormalScreen)
|
||||
return;
|
||||
|
||||
dispdev->print(text);
|
||||
}
|
||||
|
||||
void Screen::handleOnPress()
|
||||
{
|
||||
// If Canned Messages is using the "Scan and Select" input, dismiss the canned message frame when user button is pressed
|
||||
|
@ -30,7 +30,6 @@ class Screen
|
||||
void onPress() {}
|
||||
void setup() {}
|
||||
void setOn(bool) {}
|
||||
void print(const char *) {}
|
||||
void doDeepSleep() {}
|
||||
void forceDisplay(bool forceUiUpdate = false) {}
|
||||
void startFirmwareUpdateScreen() {}
|
||||
@ -320,20 +319,6 @@ class Screen : public concurrency::OSThread
|
||||
/// Stops showing the boot screen.
|
||||
void stopBootScreen() { enqueueCmd(ScreenCmd{.cmd = Cmd::STOP_BOOT_SCREEN}); }
|
||||
|
||||
/// Writes a string to the screen.
|
||||
void print(const char *text)
|
||||
{
|
||||
ScreenCmd cmd;
|
||||
cmd.cmd = Cmd::PRINT;
|
||||
// TODO(girts): strdup() here is scary, but we can't use std::string as
|
||||
// FreeRTOS queue is just dumbly copying memory contents. It would be
|
||||
// nice if we had a queue that could copy objects by value.
|
||||
cmd.print_text = strdup(text);
|
||||
if (!enqueueCmd(cmd)) {
|
||||
free(cmd.print_text);
|
||||
}
|
||||
}
|
||||
|
||||
/// Overrides the default utf8 character conversion, to replace empty space with question marks
|
||||
static char customFontTableLookup(const uint8_t ch)
|
||||
{
|
||||
@ -614,7 +599,6 @@ class Screen : public concurrency::OSThread
|
||||
void handleOnPress();
|
||||
void handleShowNextFrame();
|
||||
void handleShowPrevFrame();
|
||||
void handlePrint(const char *text);
|
||||
void handleStartFirmwareUpdateScreen();
|
||||
|
||||
// Info collected by setFrames method.
|
||||
|
@ -166,13 +166,6 @@ void ButtonThread::sendAdHocPosition()
|
||||
{
|
||||
service->refreshLocalMeshNode();
|
||||
auto sentPosition = service->trySendPosition(NODENUM_BROADCAST, true);
|
||||
if (screen) {
|
||||
if (sentPosition)
|
||||
screen->print("Sent ad-hoc position\n");
|
||||
else
|
||||
screen->print("Sent ad-hoc nodeinfo\n");
|
||||
screen->forceDisplay(true); // Force a new UI frame, then force an EInk update
|
||||
}
|
||||
playComboTune();
|
||||
}
|
||||
|
||||
@ -263,292 +256,294 @@ int32_t ButtonThread::runOnce()
|
||||
#endif
|
||||
|
||||
if (btnEvent != BUTTON_EVENT_NONE) {
|
||||
if (screen) {
|
||||
#if HAS_SCREEN
|
||||
switch (btnEvent) {
|
||||
case BUTTON_EVENT_PRESSED: {
|
||||
LOG_WARN("press!");
|
||||
switch (btnEvent) {
|
||||
case BUTTON_EVENT_PRESSED: {
|
||||
LOG_WARN("press!");
|
||||
|
||||
// Play boop sound for every button press
|
||||
playBoop();
|
||||
// Play boop sound for every button press
|
||||
playBoop();
|
||||
|
||||
// Forward single press to InputBroker (but NOT as DOWN/SELECT, just forward a "button press" event)
|
||||
if (inputBroker) {
|
||||
InputEvent evt = {"button", (char)INPUT_BROKER_MSG_BUTTON_PRESSED, 0, 0, 0};
|
||||
inputBroker->injectInputEvent(&evt);
|
||||
}
|
||||
|
||||
// Start tracking for potential combination
|
||||
waitingForLongPress = true;
|
||||
shortPressTime = millis();
|
||||
|
||||
break;
|
||||
}
|
||||
case BUTTON_EVENT_DOUBLE_PRESSED: {
|
||||
LOG_WARN("press!");
|
||||
|
||||
// Play boop sound for every button press
|
||||
playBoop();
|
||||
|
||||
// Forward single press to InputBroker (but NOT as DOWN/SELECT, just forward a "button press" event)
|
||||
if (inputBroker) {
|
||||
InputEvent evt = {"button", (char)INPUT_BROKER_MSG_BUTTON_DOUBLE_PRESSED, 0, 0, 0};
|
||||
inputBroker->injectInputEvent(&evt);
|
||||
}
|
||||
|
||||
waitingForLongPress = false;
|
||||
|
||||
break;
|
||||
}
|
||||
case BUTTON_EVENT_LONG_PRESSED: {
|
||||
LOG_WARN("Long press!");
|
||||
|
||||
// Play beep sound
|
||||
playBeep();
|
||||
|
||||
// Forward long press to InputBroker (but NOT as DOWN/SELECT, just forward a "button long press" event)
|
||||
if (inputBroker) {
|
||||
InputEvent evt = {"button", (char)INPUT_BROKER_MSG_BUTTON_LONG_PRESSED, 0, 0, 0};
|
||||
inputBroker->injectInputEvent(&evt);
|
||||
}
|
||||
|
||||
waitingForLongPress = false;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
// Ignore all other events on screen devices
|
||||
break;
|
||||
}
|
||||
btnEvent = BUTTON_EVENT_NONE;
|
||||
#else
|
||||
// On devices without screen: full legacy logic
|
||||
switch (btnEvent) {
|
||||
case BUTTON_EVENT_PRESSED: {
|
||||
LOG_BUTTON("press!");
|
||||
|
||||
// Play boop sound for every button press
|
||||
playBoop();
|
||||
|
||||
// If a nag notification is running, stop it and prevent other actions
|
||||
if (moduleConfig.external_notification.enabled && (externalNotificationModule->nagCycleCutoff != UINT32_MAX)) {
|
||||
externalNotificationModule->stopNow();
|
||||
break;
|
||||
}
|
||||
#ifdef ELECROW_ThinkNode_M1
|
||||
sendAdHocPosition();
|
||||
break;
|
||||
#endif
|
||||
|
||||
// Start tracking for potential combination
|
||||
waitingForLongPress = true;
|
||||
shortPressTime = millis();
|
||||
|
||||
switchPage();
|
||||
break;
|
||||
}
|
||||
|
||||
case BUTTON_EVENT_PRESSED_SCREEN: {
|
||||
LOG_BUTTON("AltPress!");
|
||||
|
||||
// Play boop sound for every button press
|
||||
playBoop();
|
||||
|
||||
// Reset combination tracking
|
||||
waitingForLongPress = false;
|
||||
|
||||
#ifdef ELECROW_ThinkNode_M1
|
||||
// If a nag notification is running, stop it and prevent other actions
|
||||
if (moduleConfig.external_notification.enabled && (externalNotificationModule->nagCycleCutoff != UINT32_MAX)) {
|
||||
externalNotificationModule->stopNow();
|
||||
break;
|
||||
}
|
||||
switchPage();
|
||||
break;
|
||||
#endif
|
||||
// turn screen on or off
|
||||
screen_flag = !screen_flag;
|
||||
if (screen)
|
||||
screen->setOn(screen_flag);
|
||||
break;
|
||||
}
|
||||
|
||||
case BUTTON_EVENT_DOUBLE_PRESSED: {
|
||||
LOG_BUTTON("Double press!");
|
||||
|
||||
// Play boop sound for every button press
|
||||
playBoop();
|
||||
|
||||
// Reset combination tracking
|
||||
waitingForLongPress = false;
|
||||
|
||||
#ifdef ELECROW_ThinkNode_M1
|
||||
digitalWrite(PIN_EINK_EN, digitalRead(PIN_EINK_EN) == LOW);
|
||||
break;
|
||||
#endif
|
||||
|
||||
// Send GPS position immediately
|
||||
sendAdHocPosition();
|
||||
|
||||
// Show temporary on-screen confirmation banner for 3 seconds
|
||||
screen->showOverlayBanner("Ad-hoc Ping Sent", 3000);
|
||||
break;
|
||||
}
|
||||
|
||||
case BUTTON_EVENT_MULTI_PRESSED: {
|
||||
LOG_BUTTON("Mulitipress! %hux", multipressClickCount);
|
||||
|
||||
// Play boop sound for every button press
|
||||
playBoop();
|
||||
|
||||
// Reset combination tracking
|
||||
waitingForLongPress = false;
|
||||
|
||||
switch (multipressClickCount) {
|
||||
#if HAS_GPS && !defined(ELECROW_ThinkNode_M1)
|
||||
// 3 clicks: toggle GPS
|
||||
case 3:
|
||||
if (!config.device.disable_triple_click && (gps != nullptr)) {
|
||||
gps->toggleGpsMode();
|
||||
|
||||
const char *statusMsg = (config.position.gps_mode == meshtastic_Config_PositionConfig_GpsMode_ENABLED)
|
||||
? "GPS Enabled"
|
||||
: "GPS Disabled";
|
||||
|
||||
if (screen) {
|
||||
screen->forceDisplay(true); // Force a new UI frame, then force an EInk update
|
||||
screen->showOverlayBanner(statusMsg, 3000);
|
||||
}
|
||||
// Forward single press to InputBroker (but NOT as DOWN/SELECT, just forward a "button press" event)
|
||||
if (inputBroker) {
|
||||
InputEvent evt = {"button", (char)INPUT_BROKER_MSG_BUTTON_PRESSED, 0, 0, 0};
|
||||
inputBroker->injectInputEvent(&evt);
|
||||
}
|
||||
|
||||
// Start tracking for potential combination
|
||||
waitingForLongPress = true;
|
||||
shortPressTime = millis();
|
||||
|
||||
break;
|
||||
}
|
||||
case BUTTON_EVENT_DOUBLE_PRESSED: {
|
||||
LOG_WARN("press!");
|
||||
|
||||
// Play boop sound for every button press
|
||||
playBoop();
|
||||
|
||||
// Forward single press to InputBroker (but NOT as DOWN/SELECT, just forward a "button press" event)
|
||||
if (inputBroker) {
|
||||
InputEvent evt = {"button", (char)INPUT_BROKER_MSG_BUTTON_DOUBLE_PRESSED, 0, 0, 0};
|
||||
inputBroker->injectInputEvent(&evt);
|
||||
}
|
||||
|
||||
waitingForLongPress = false;
|
||||
|
||||
break;
|
||||
}
|
||||
case BUTTON_EVENT_LONG_PRESSED: {
|
||||
LOG_WARN("Long press!");
|
||||
|
||||
// Play beep sound
|
||||
playBeep();
|
||||
|
||||
// Forward long press to InputBroker (but NOT as DOWN/SELECT, just forward a "button long press" event)
|
||||
if (inputBroker) {
|
||||
InputEvent evt = {"button", (char)INPUT_BROKER_MSG_BUTTON_LONG_PRESSED, 0, 0, 0};
|
||||
inputBroker->injectInputEvent(&evt);
|
||||
}
|
||||
|
||||
waitingForLongPress = false;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
// Ignore all other events on screen devices
|
||||
break;
|
||||
}
|
||||
btnEvent = BUTTON_EVENT_NONE;
|
||||
#endif
|
||||
} else {
|
||||
// On devices without screen: full legacy logic
|
||||
switch (btnEvent) {
|
||||
case BUTTON_EVENT_PRESSED: {
|
||||
LOG_BUTTON("press!");
|
||||
|
||||
// Play boop sound for every button press
|
||||
playBoop();
|
||||
|
||||
// If a nag notification is running, stop it and prevent other actions
|
||||
if (moduleConfig.external_notification.enabled && (externalNotificationModule->nagCycleCutoff != UINT32_MAX)) {
|
||||
externalNotificationModule->stopNow();
|
||||
break;
|
||||
}
|
||||
#ifdef ELECROW_ThinkNode_M1
|
||||
sendAdHocPosition();
|
||||
break;
|
||||
#endif
|
||||
|
||||
// Start tracking for potential combination
|
||||
waitingForLongPress = true;
|
||||
shortPressTime = millis();
|
||||
|
||||
switchPage();
|
||||
break;
|
||||
}
|
||||
|
||||
case BUTTON_EVENT_PRESSED_SCREEN: {
|
||||
LOG_BUTTON("AltPress!");
|
||||
|
||||
// Play boop sound for every button press
|
||||
playBoop();
|
||||
|
||||
// Reset combination tracking
|
||||
waitingForLongPress = false;
|
||||
|
||||
#ifdef ELECROW_ThinkNode_M1
|
||||
// If a nag notification is running, stop it and prevent other actions
|
||||
if (moduleConfig.external_notification.enabled && (externalNotificationModule->nagCycleCutoff != UINT32_MAX)) {
|
||||
externalNotificationModule->stopNow();
|
||||
break;
|
||||
}
|
||||
switchPage();
|
||||
break;
|
||||
#endif
|
||||
// turn screen on or off
|
||||
screen_flag = !screen_flag;
|
||||
if (screen)
|
||||
screen->setOn(screen_flag);
|
||||
break;
|
||||
}
|
||||
|
||||
case BUTTON_EVENT_DOUBLE_PRESSED: {
|
||||
LOG_BUTTON("Double press!");
|
||||
|
||||
// Play boop sound for every button press
|
||||
playBoop();
|
||||
|
||||
// Reset combination tracking
|
||||
waitingForLongPress = false;
|
||||
|
||||
#ifdef ELECROW_ThinkNode_M1
|
||||
digitalWrite(PIN_EINK_EN, digitalRead(PIN_EINK_EN) == LOW);
|
||||
break;
|
||||
#endif
|
||||
|
||||
// Send GPS position immediately
|
||||
sendAdHocPosition();
|
||||
|
||||
// Show temporary on-screen confirmation banner for 3 seconds
|
||||
screen->showOverlayBanner("Ad-hoc Ping Sent", 3000);
|
||||
break;
|
||||
}
|
||||
|
||||
case BUTTON_EVENT_MULTI_PRESSED: {
|
||||
LOG_BUTTON("Mulitipress! %hux", multipressClickCount);
|
||||
|
||||
// Play boop sound for every button press
|
||||
playBoop();
|
||||
|
||||
// Reset combination tracking
|
||||
waitingForLongPress = false;
|
||||
|
||||
switch (multipressClickCount) {
|
||||
#if HAS_GPS && !defined(ELECROW_ThinkNode_M1)
|
||||
// 3 clicks: toggle GPS
|
||||
case 3:
|
||||
if (!config.device.disable_triple_click && (gps != nullptr)) {
|
||||
gps->toggleGpsMode();
|
||||
|
||||
const char *statusMsg = (config.position.gps_mode == meshtastic_Config_PositionConfig_GpsMode_ENABLED)
|
||||
? "GPS Enabled"
|
||||
: "GPS Disabled";
|
||||
|
||||
if (screen) {
|
||||
screen->forceDisplay(true); // Force a new UI frame, then force an EInk update
|
||||
screen->showOverlayBanner(statusMsg, 3000);
|
||||
}
|
||||
}
|
||||
break;
|
||||
#elif defined(ELECROW_ThinkNode_M1) || defined(ELECROW_ThinkNode_M2)
|
||||
case 3:
|
||||
LOG_INFO("3 clicks: toggle buzzer");
|
||||
buzzer_flag = !buzzer_flag;
|
||||
if (!buzzer_flag)
|
||||
noTone(PIN_BUZZER);
|
||||
break;
|
||||
case 3:
|
||||
LOG_INFO("3 clicks: toggle buzzer");
|
||||
buzzer_flag = !buzzer_flag;
|
||||
if (!buzzer_flag)
|
||||
noTone(PIN_BUZZER);
|
||||
break;
|
||||
|
||||
#endif
|
||||
|
||||
#if defined(USE_EINK) && defined(PIN_EINK_EN) && !defined(ELECROW_ThinkNode_M1) // i.e. T-Echo
|
||||
// 4 clicks: toggle backlight
|
||||
case 4:
|
||||
digitalWrite(PIN_EINK_EN, digitalRead(PIN_EINK_EN) == LOW);
|
||||
break;
|
||||
// 4 clicks: toggle backlight
|
||||
case 4:
|
||||
digitalWrite(PIN_EINK_EN, digitalRead(PIN_EINK_EN) == LOW);
|
||||
break;
|
||||
#endif
|
||||
#if !MESHTASTIC_EXCLUDE_SCREEN && HAS_SCREEN
|
||||
// 5 clicks: start accelerometer/magenetometer calibration for 30 seconds
|
||||
case 5:
|
||||
if (accelerometerThread) {
|
||||
accelerometerThread->calibrate(30);
|
||||
}
|
||||
break;
|
||||
// 6 clicks: start accelerometer/magenetometer calibration for 60 seconds
|
||||
case 6:
|
||||
if (accelerometerThread) {
|
||||
accelerometerThread->calibrate(60);
|
||||
}
|
||||
break;
|
||||
// 5 clicks: start accelerometer/magenetometer calibration for 30 seconds
|
||||
case 5:
|
||||
if (accelerometerThread) {
|
||||
accelerometerThread->calibrate(30);
|
||||
}
|
||||
break;
|
||||
// 6 clicks: start accelerometer/magenetometer calibration for 60 seconds
|
||||
case 6:
|
||||
if (accelerometerThread) {
|
||||
accelerometerThread->calibrate(60);
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
// No valid multipress action
|
||||
default:
|
||||
// No valid multipress action
|
||||
default:
|
||||
break;
|
||||
} // end switch: click count
|
||||
|
||||
break;
|
||||
} // end switch: click count
|
||||
} // end multipress event
|
||||
|
||||
break;
|
||||
} // end multipress event
|
||||
case BUTTON_EVENT_LONG_PRESSED: {
|
||||
LOG_BUTTON("Long press!");
|
||||
|
||||
case BUTTON_EVENT_LONG_PRESSED: {
|
||||
LOG_BUTTON("Long press!");
|
||||
// Check if this is part of a short-press + long-press combination
|
||||
if (waitingForLongPress && (millis() - shortPressTime) <= BUTTON_COMBO_TIMEOUT_MS) {
|
||||
LOG_BUTTON("Combo detected: short-press + long-press!");
|
||||
btnEvent = BUTTON_EVENT_COMBO_SHORT_LONG;
|
||||
waitingForLongPress = false;
|
||||
break;
|
||||
}
|
||||
|
||||
// Check if this is part of a short-press + long-press combination
|
||||
if (waitingForLongPress && (millis() - shortPressTime) <= BUTTON_COMBO_TIMEOUT_MS) {
|
||||
LOG_BUTTON("Combo detected: short-press + long-press!");
|
||||
btnEvent = BUTTON_EVENT_COMBO_SHORT_LONG;
|
||||
// Reset combination tracking
|
||||
waitingForLongPress = false;
|
||||
break;
|
||||
}
|
||||
|
||||
// Reset combination tracking
|
||||
waitingForLongPress = false;
|
||||
|
||||
powerFSM.trigger(EVENT_PRESS);
|
||||
|
||||
if (screen) {
|
||||
// Show shutdown message as a temporary overlay banner
|
||||
screen->showOverlayBanner("Shutting Down..."); // Display for 3 seconds
|
||||
}
|
||||
|
||||
// Lead-up sound already played during button hold
|
||||
// Just a simple beep to confirm long press threshold reached
|
||||
playBeep();
|
||||
break;
|
||||
}
|
||||
|
||||
// Do actual shutdown when button released, otherwise the button release
|
||||
// may wake the board immediatedly.
|
||||
case BUTTON_EVENT_LONG_RELEASED: {
|
||||
LOG_INFO("Shutdown from long press");
|
||||
|
||||
// Reset combination tracking
|
||||
waitingForLongPress = false;
|
||||
|
||||
playShutdownMelody();
|
||||
delay(3000);
|
||||
power->shutdown();
|
||||
nodeDB->saveToDisk();
|
||||
break;
|
||||
}
|
||||
|
||||
#ifdef BUTTON_PIN_TOUCH
|
||||
case BUTTON_EVENT_TOUCH_LONG_PRESSED: {
|
||||
LOG_BUTTON("Touch press!");
|
||||
|
||||
// Play boop sound for every button press
|
||||
playBoop();
|
||||
|
||||
// Reset combination tracking
|
||||
waitingForLongPress = false;
|
||||
|
||||
// Ignore if: no screen
|
||||
if (!screen)
|
||||
break;
|
||||
|
||||
#ifdef TTGO_T_ECHO
|
||||
// Ignore if: TX in progress
|
||||
// Uncommon T-Echo hardware bug, LoRa TX triggers touch button
|
||||
if (!RadioLibInterface::instance || RadioLibInterface::instance->isSending())
|
||||
break;
|
||||
#endif
|
||||
|
||||
// Wake if asleep
|
||||
if (powerFSM.getState() == &stateDARK)
|
||||
powerFSM.trigger(EVENT_PRESS);
|
||||
|
||||
// Update display (legacy behaviour)
|
||||
screen->forceDisplay();
|
||||
break;
|
||||
}
|
||||
if (screen) {
|
||||
// Show shutdown message as a temporary overlay banner
|
||||
screen->showOverlayBanner("Shutting Down..."); // Display for 3 seconds
|
||||
}
|
||||
|
||||
// Lead-up sound already played during button hold
|
||||
// Just a simple beep to confirm long press threshold reached
|
||||
playBeep();
|
||||
break;
|
||||
}
|
||||
|
||||
// Do actual shutdown when button released, otherwise the button release
|
||||
// may wake the board immediatedly.
|
||||
case BUTTON_EVENT_LONG_RELEASED: {
|
||||
LOG_INFO("Shutdown from long press");
|
||||
|
||||
// Reset combination tracking
|
||||
waitingForLongPress = false;
|
||||
|
||||
playShutdownMelody();
|
||||
delay(3000);
|
||||
power->shutdown();
|
||||
nodeDB->saveToDisk();
|
||||
break;
|
||||
}
|
||||
|
||||
#ifdef BUTTON_PIN_TOUCH
|
||||
case BUTTON_EVENT_TOUCH_LONG_PRESSED: {
|
||||
LOG_BUTTON("Touch press!");
|
||||
|
||||
// Play boop sound for every button press
|
||||
playBoop();
|
||||
|
||||
// Reset combination tracking
|
||||
waitingForLongPress = false;
|
||||
|
||||
// Ignore if: no screen
|
||||
if (!screen)
|
||||
break;
|
||||
|
||||
#ifdef TTGO_T_ECHO
|
||||
// Ignore if: TX in progress
|
||||
// Uncommon T-Echo hardware bug, LoRa TX triggers touch button
|
||||
if (!RadioLibInterface::instance || RadioLibInterface::instance->isSending())
|
||||
break;
|
||||
#endif
|
||||
|
||||
// Wake if asleep
|
||||
if (powerFSM.getState() == &stateDARK)
|
||||
powerFSM.trigger(EVENT_PRESS);
|
||||
|
||||
// Update display (legacy behaviour)
|
||||
screen->forceDisplay();
|
||||
break;
|
||||
}
|
||||
#endif // BUTTON_PIN_TOUCH
|
||||
|
||||
case BUTTON_EVENT_COMBO_SHORT_LONG: {
|
||||
// Placeholder for short-press + long-press combination
|
||||
LOG_BUTTON("Short-press + Long-press combination detected!");
|
||||
case BUTTON_EVENT_COMBO_SHORT_LONG: {
|
||||
// Placeholder for short-press + long-press combination
|
||||
LOG_BUTTON("Short-press + Long-press combination detected!");
|
||||
|
||||
// Play the combination tune
|
||||
playComboTune();
|
||||
// Play the combination tune
|
||||
playComboTune();
|
||||
|
||||
// Optionally show a message on screen
|
||||
if (screen) {
|
||||
screen->showOverlayBanner("Combo Tune Played", 2000);
|
||||
// Optionally show a message on screen
|
||||
if (screen) {
|
||||
screen->showOverlayBanner("Combo Tune Played", 2000);
|
||||
}
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
btnEvent = BUTTON_EVENT_NONE;
|
||||
}
|
||||
btnEvent = BUTTON_EVENT_NONE;
|
||||
#endif
|
||||
}
|
||||
|
||||
return 50;
|
||||
|
17
src/main.cpp
17
src/main.cpp
@ -850,9 +850,21 @@ void setup()
|
||||
// Initialize the screen first so we can show the logo while we start up everything else.
|
||||
#if HAS_SCREEN
|
||||
if (config.display.displaymode != meshtastic_Config_DisplayConfig_DisplayMode_COLOR) {
|
||||
|
||||
#if defined(ST7701_CS) || defined(ST7735_CS) || defined(USE_EINK) || defined(ILI9341_DRIVER) || defined(ILI9342_DRIVER) || \
|
||||
defined(ST7789_CS) || defined(HX8357_CS) || defined(USE_ST7789) || defined(ILI9488_CS)
|
||||
screen = new graphics::Screen(screen_found, screen_model, screen_geometry);
|
||||
}
|
||||
#elif defined(ARCH_PORTDUINO)
|
||||
if ((screen_found.port != ScanI2C::I2CPort::NO_I2C || settingsMap[displayPanel]) &&
|
||||
config.display.displaymode != meshtastic_Config_DisplayConfig_DisplayMode_COLOR) {
|
||||
screen = new graphics::Screen(screen_found, screen_model, screen_geometry);
|
||||
}
|
||||
#else
|
||||
if (screen_found.port != ScanI2C::I2CPort::NO_I2C)
|
||||
screen = new graphics::Screen(screen_found, screen_model, screen_geometry);
|
||||
#endif
|
||||
}
|
||||
#endif // HAS_SCREEN
|
||||
// setup TZ prior to time actions.
|
||||
#if !MESHTASTIC_EXCLUDE_TZ
|
||||
LOG_DEBUG("Use compiled/slipstreamed %s", slipstreamTZString); // important, removing this clobbers our magic string
|
||||
@ -953,9 +965,6 @@ void setup()
|
||||
screen->setup();
|
||||
#endif
|
||||
#endif
|
||||
if (screen) {
|
||||
screen->print("Started...\n");
|
||||
}
|
||||
|
||||
#ifdef PIN_PWR_DELAY_MS
|
||||
// This may be required to give the peripherals time to power up.
|
||||
|
@ -1804,10 +1804,6 @@ bool NodeDB::restorePreferences(meshtastic_AdminMessage_BackupLocation location,
|
||||
/// Record an error that should be reported via analytics
|
||||
void recordCriticalError(meshtastic_CriticalErrorCode code, uint32_t address, const char *filename)
|
||||
{
|
||||
// Print error to screen and serial port
|
||||
String lcd = String("Critical error ") + code + "!\n";
|
||||
if (screen)
|
||||
screen->print(lcd.c_str());
|
||||
if (filename) {
|
||||
LOG_ERROR("NOTE! Record critical error %d at %s:%lu", code, filename, address);
|
||||
} else {
|
||||
|
@ -83,10 +83,6 @@ bool RemoteHardwareModule::handleReceivedProtobuf(const meshtastic_MeshPacket &r
|
||||
|
||||
switch (p.type) {
|
||||
case meshtastic_HardwareMessage_Type_WRITE_GPIOS: {
|
||||
// Print notification to LCD screen
|
||||
if (screen)
|
||||
screen->print("Write GPIOs\n");
|
||||
|
||||
pinModes(p.gpio_mask, OUTPUT, availablePins);
|
||||
for (uint8_t i = 0; i < NUM_GPIOS; i++) {
|
||||
uint64_t mask = 1ULL << i;
|
||||
@ -99,10 +95,6 @@ bool RemoteHardwareModule::handleReceivedProtobuf(const meshtastic_MeshPacket &r
|
||||
}
|
||||
|
||||
case meshtastic_HardwareMessage_Type_READ_GPIOS: {
|
||||
// Print notification to LCD screen
|
||||
if (screen)
|
||||
screen->print("Read GPIOs\n");
|
||||
|
||||
uint64_t res = digitalReads(p.gpio_mask, availablePins);
|
||||
|
||||
// Send the reply
|
||||
|
@ -14,8 +14,6 @@ meshtastic_MeshPacket *ReplyModule::allocReply()
|
||||
// The incoming message is in p.payload
|
||||
LOG_INFO("Received message from=0x%0x, id=%d, msg=%.*s", req.from, req.id, p.payload.size, p.payload.bytes);
|
||||
#endif
|
||||
if (screen)
|
||||
screen->print("Send reply\n");
|
||||
|
||||
const char *replyStr = "Message Received";
|
||||
auto reply = allocDataPacket(); // Allocate a packet for sending
|
||||
|
Loading…
Reference in New Issue
Block a user