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
+19 -1
View File
@@ -1125,6 +1125,9 @@ static uint32_t _atoi(const char* sp) {
/* GLOBAL OBJECTS */
#ifdef DISPLAY_CLASS
#include "UITask.h"
#if defined(LILYGO_TWATCH_S3)
#include "WatchAlarmScreen.h" // After UITask.h -- needs NodePrefs
#endif
#if defined(MECK_TWATCH) && HAS_GPS
#include "WatchMapScreen.h" // After BLE -- PNGdec headers conflict with BLE if included earlier
#elif HAS_GPS && !defined(LILYGO_TECHO_CARD)
@@ -1360,6 +1363,18 @@ static void lastHeardToggleContact() {
if (wms) wms->handleTap(x, y);
return 0;
}
#endif
#if defined(LILYGO_TWATCH_S3)
// Alarm screen: rows, +/- steppers and the footer are all tap targets.
// readTouch() already returns logical (UI_ZOOM-divided) coords on the watch,
// which is the space WatchAlarmScreen lays out in. No further scaling.
if (ui_task.isOnWatchAlarmScreen()) {
WatchAlarmScreen* wa = (WatchAlarmScreen*)ui_task.getWatchAlarmScreen();
if (wa) wa->handleTap(x, y);
return 0;
}
#endif
#if defined(MECK_TWATCH)
// Watch: tiles open on long-press and pages change on swipe, so a plain tap
// on any home page does nothing -- skip the T5S3 tile hit-test below (wrong
// geometry for the 2-column watch grid) and the left/right page cycling.
@@ -1806,7 +1821,10 @@ static void lastHeardToggleContact() {
if (row == 1 && col == 0) { ui_task.gotoSettingsScreen(); return 0; }
if (row == 1 && col == 1) { ui_task.gotoDiscoveryScreen(); return 0; }
if (row == 2 && col == 0) { ui_task.gotoTraceScreen(); return 0; }
#if HAS_GPS
#if defined(LILYGO_TWATCH_S3)
// No GNSS on the plain S3, so this slot is the vibrate alarm clock.
if (row == 2 && col == 1) { ui_task.gotoWatchAlarmScreen(); return 0; }
#elif HAS_GPS
if (row == 2 && col == 1) {
// Maps: mark the tile FS ready (detectZoomRange in enter() needs it)
// before opening; GPS centre + markers are populated in the main loop.