T-Watch S3: vibrate alarm clock in place of the Maps tile

Fixes a regression from the MECK_TWATCH rename. main.cpp's tap dispatch had
'#if defined(MECK_TWATCH) && HAS_GPS' wrapped around two unrelated things: the
map tap handler AND the early return that stops the watch falling through to the
T5S3 tile hit-test. MECK_TOUCH_ENABLED is defined for MECK_TWATCH (main.cpp:712),
so on the S3 that early return vanished and a plain tap on the home tile page ran
the T5S3 geometry (tileW=40, tileH=22). Split into two gates. The other three
HAS_GPS gates were audited and are genuinely map-only.

Adds WatchAlarmScreen: four slots, day-of-week presets, vibrate-only. It keeps
AlarmScreen.h's conventions (bit 0 = Sunday, dowFromEpoch, effect 14, the
3-buzz / 1200ms / 4000ms-pause cadence) but shares no code, because AlarmScreen
is bound to ESP32-audioI2S, an SD card and a 1-21 Audio volume scale, none of
which exist here. Config lives on the LittleFS 'maps' partition, already mounted.

Alarms are ticked from UITask::loop, not the screen's poll(), so one fires with
the display off or another screen showing. Navigating away while ringing counts
as a dismiss.

DRV2605Haptic.h is copied into the watch variant rather than shared, so MAX
builds are untouched. The watch needs no motorEnable(): the DRV2605 sits on
BLDO2, which power_init() already brings up.

The Maps tile becomes Alarms on LILYGO_TWATCH_S3 only. The Plus keeps Maps.
The 'buzz' CLI command now also builds on the watch and takes an optional effect
number ('buzz 14'), for characterising the motor. Exact-match behaviour of plain
'buzz' on the MAX is unchanged.
This commit is contained in:
meck
2026-07-10 09:37:05 +00:00
committed by pelgraine
parent df00c435f9
commit 9754f93504
6 changed files with 595 additions and 10 deletions
+18 -9
View File
@@ -12,8 +12,8 @@
#include "ModemManager.h" // Serial CLI modem commands
#endif
#if defined(LilyGo_TDeck_Pro_Max)
#include "DRV2605Haptic.h" // TEMP: inline haptic driver for the 'buzz' CLI test command
#if defined(LilyGo_TDeck_Pro_Max) || defined(LILYGO_TWATCH_S3)
#include "DRV2605Haptic.h" // inline haptic driver for the 'buzz' CLI test command
#endif
#define CMD_APP_START 1
@@ -3613,20 +3613,29 @@ void MyMesh::checkCLIRescueCmd() {
}
}
#if defined(LilyGo_TDeck_Pro_Max)
else if (strcmp(cli_command, "buzz") == 0) {
// TEMP: fire the DRV2605 haptic motor once to confirm it works.
// Lazy-inits the driver (and motor power rail) on first invocation.
#if defined(LilyGo_TDeck_Pro_Max) || defined(LILYGO_TWATCH_S3)
else if (strncmp(cli_command, "buzz", 4) == 0 &&
(cli_command[4] == '\0' || cli_command[4] == ' ')) {
// Fire a DRV2605 library-1 effect to confirm the motor works.
// "buzz" uses effect 1 (strong click); "buzz <n>" fires effect n.
// Lazy-inits the driver (and, on the MAX, its motor power rail).
static DRV2605Haptic haptic;
static bool haptic_ready = false;
if (!haptic_ready) {
board.motorEnable();
#if defined(LilyGo_TDeck_Pro_Max)
board.motorEnable(); // MAX: motor rail is behind an XL9555 pin
delay(10); // let the motor rail settle before I2C
#endif
haptic_ready = haptic.begin();
}
if (haptic_ready) {
haptic.buzz(1);
Serial.println(" > buzz");
int effect = 1;
const char* arg = cli_command + 4;
while (*arg == ' ') arg++;
if (*arg) effect = atoi(arg);
if (effect < 1 || effect > 123) effect = 1;
haptic.buzz((uint8_t)effect);
Serial.printf(" > buzz: effect %d\n", effect);
} else {
Serial.println(" > buzz: DRV2605 not found");
}