mirror of
https://github.com/pelgraine/Meck.git
synced 2026-07-29 04:42:41 +02:00
t-watch - initial step counter implementation
This commit is contained in:
@@ -1787,7 +1787,7 @@ static void lastHeardToggleContact() {
|
||||
if (row == 2 && col == 0) { ui_task.gotoTraceScreen(); return 0; }
|
||||
// row 2 col 1 = Maps -- TODO subscreen not yet built; no-op for now.
|
||||
if (row == 3 && col == 0) { ui_task.gotoNotesScreen(); return 0; }
|
||||
// row 3 col 1 = Games -- placeholder, no target yet; no-op for now.
|
||||
if (row == 3 && col == 1) { ui_task.gotoStepsScreen(); return 0; }
|
||||
}
|
||||
return 0; // consume long-press on the tile page
|
||||
}
|
||||
|
||||
@@ -81,6 +81,12 @@ static const uint8_t icon_gamepad[] PROGMEM = {
|
||||
0x40,0x20, 0x30,0xC0, 0x10,0x80, 0x1F,0x80, 0x00,0x00, 0x00,0x00,
|
||||
};
|
||||
|
||||
// Star -- 12x12 home tile icon (Steps). MSB-first, 2 bytes per row.
|
||||
static const uint8_t icon_star[] PROGMEM = {
|
||||
0x06,0x00, 0x06,0x00, 0x0F,0x00, 0xFF,0xF0, 0x7F,0xE0, 0x3F,0xC0,
|
||||
0x1F,0x80, 0x3F,0xC0, 0x39,0xC0, 0x70,0xE0, 0x60,0x60, 0x00,0x00,
|
||||
};
|
||||
|
||||
// 🔔 Bell -- 7x8 status bar indicator (alarm enabled)
|
||||
// MSB-first, 1 byte per row
|
||||
#define BELL_ICON_W 7
|
||||
|
||||
@@ -34,7 +34,7 @@
|
||||
#endif
|
||||
|
||||
#ifndef AUTO_OFF_MILLIS
|
||||
#define AUTO_OFF_MILLIS 45000 // 45 seconds
|
||||
#define AUTO_OFF_MILLIS 15000 // 15 seconds
|
||||
#endif
|
||||
// Right-aligned values on the dense home pages compensate for the e-ink X
|
||||
// origin offset so they are not clipped at the right edge. Default 0 for
|
||||
@@ -686,7 +686,7 @@ public:
|
||||
{ {icon_envelope, "Messages", 0x0CB1}, {icon_people, "Contacts", 0xCAA0} },
|
||||
{ {icon_gear, "Settings", 0x0560}, {icon_search, "Discover", 0xF81F} },
|
||||
{ {icon_trace, "Trace", 0xF800}, {icon_map, "Maps", 0x231D} },
|
||||
{ {icon_notepad, "Notes", 0x07FF}, {icon_gamepad, "Games", 0xFFE0} },
|
||||
{ {icon_notepad, "Notes", 0x07FF}, {icon_star, "Steps", 0xFFE0} },
|
||||
};
|
||||
const uint16_t TILE_FILL = 0x18C5; // dark navy
|
||||
|
||||
@@ -1485,6 +1485,27 @@ public:
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
// Steps screen: big daily step count in the clock font. Opened by long-pressing
|
||||
// the Steps home tile; any tap dismisses back to the tiles.
|
||||
class StepsScreen : public UIScreen {
|
||||
UITask* _task;
|
||||
public:
|
||||
StepsScreen(UITask* task) : _task(task) { }
|
||||
|
||||
int render(DisplayDriver& display) override {
|
||||
display.setColor(DisplayDriver::LIGHT);
|
||||
char buf[16];
|
||||
snprintf(buf, sizeof(buf), "%u", (unsigned)_task->getTodaySteps());
|
||||
((LGFXDisplay*)&display)->printClockFont(display.width() / 2, display.height() / 2 - 18, buf);
|
||||
return 1000;
|
||||
}
|
||||
|
||||
bool handleInput(char c) override {
|
||||
_task->gotoHomeScreen();
|
||||
return true;
|
||||
}
|
||||
};
|
||||
#endif
|
||||
|
||||
#if defined(LilyGo_T5S3_EPaper_Pro) || defined(LilyGo_TDeck_Pro)
|
||||
@@ -1658,6 +1679,7 @@ void UITask::begin(DisplayDriver* display, SensorManager* sensors, NodePrefs* no
|
||||
#endif
|
||||
#if defined(LILYGO_TWATCH_S3_PLUS)
|
||||
lock_screen = new ClockScreen(this, &rtc_clock, node_prefs);
|
||||
steps_screen = new StepsScreen(this);
|
||||
#endif
|
||||
#ifdef TWATCH_COMPOSE_ENABLED
|
||||
tw_picker = new TWatchChannelPicker(_display);
|
||||
@@ -2223,20 +2245,6 @@ void UITask::loop() {
|
||||
} else {
|
||||
c = checkDisplayOn(KEY_NEXT);
|
||||
}
|
||||
#elif defined(LILYGO_TWATCH_S3_PLUS)
|
||||
// Watch: on the contacts screen a button click opens the path editor for
|
||||
// the selected contact; elsewhere it wakes the display / emits KEY_NEXT.
|
||||
if (isOnContactsScreen()) {
|
||||
int idx = ((ContactsScreen*)contacts_screen)->getSelectedContactIdx();
|
||||
if (idx >= 0) {
|
||||
gotoPathEditor(idx);
|
||||
c = 0;
|
||||
} else {
|
||||
c = checkDisplayOn(KEY_NEXT);
|
||||
}
|
||||
} else {
|
||||
c = checkDisplayOn(KEY_NEXT);
|
||||
}
|
||||
#else
|
||||
c = checkDisplayOn(KEY_NEXT);
|
||||
#endif
|
||||
@@ -2635,6 +2643,17 @@ if (curr) curr->poll();
|
||||
setCurrScreen(lock_screen);
|
||||
_auto_off = millis() + AUTO_OFF_MILLIS;
|
||||
}
|
||||
|
||||
// Roll the daily step baseline over at local midnight (12am-to-12am total).
|
||||
// No hardware reset -- the displayed count is raw_count - baseline.
|
||||
{
|
||||
uint32_t now = rtc_clock.getCurrentTime();
|
||||
if (now > 1700000000) { // valid timestamp
|
||||
int32_t localDay = ((int32_t)now + ((int32_t)the_mesh.getNodePrefs()->utc_offset_hours * 3600)) / 86400;
|
||||
if (_lastStepDay == 0) _lastStepDay = localDay; // seed on first valid read
|
||||
else if (localDay != _lastStepDay) { _stepBaseline = board.getStepCount(); _lastStepDay = localDay; }
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
// Auto-lock idle timer — runs regardless of display on/off state
|
||||
@@ -3617,6 +3636,22 @@ void UITask::gotoTraceScreen() {
|
||||
_next_refresh = 100;
|
||||
}
|
||||
|
||||
#if defined(LILYGO_TWATCH_S3_PLUS)
|
||||
uint32_t UITask::getTodaySteps() {
|
||||
uint32_t raw = board.getStepCount();
|
||||
return (raw >= _stepBaseline) ? (raw - _stepBaseline) : raw;
|
||||
}
|
||||
|
||||
void UITask::gotoStepsScreen() {
|
||||
setCurrScreen(steps_screen);
|
||||
if (_display != NULL && !_display->isOn()) {
|
||||
_display->turnOn();
|
||||
}
|
||||
_auto_off = millis() + AUTO_OFF_MILLIS;
|
||||
_next_refresh = 100;
|
||||
}
|
||||
#endif
|
||||
|
||||
void UITask::gotoGamesMenu() {
|
||||
GamesMenuScreen* gm = (GamesMenuScreen*)games_menu_screen;
|
||||
gm->enter();
|
||||
|
||||
@@ -119,6 +119,11 @@ class UITask : public AbstractUITask {
|
||||
int _tileGridVY = 44; // Virtual Y of tile grid top (updated each render)
|
||||
#if defined(LilyGo_T5S3_EPaper_Pro) || defined(LILYGO_TWATCH_S3_PLUS)
|
||||
UIScreen* lock_screen; // Lock screen (big clock + battery + unread)
|
||||
#if defined(LILYGO_TWATCH_S3_PLUS)
|
||||
UIScreen* steps_screen; // Steps screen (big daily step count)
|
||||
int32_t _lastStepDay = 0; // local day-of-epoch, for the midnight step reset
|
||||
uint32_t _stepBaseline = 0; // raw step count at the start of the local day
|
||||
#endif
|
||||
UIScreen* _screenBeforeLock = nullptr;
|
||||
bool _locked = false;
|
||||
unsigned long _lastInputMillis = 0; // Auto-lock idle tracking
|
||||
@@ -220,6 +225,10 @@ public:
|
||||
void gotoGamesMenu(); // Navigate to games launcher menu
|
||||
void gotoSnakeScreen(); // Navigate to snake game
|
||||
void gotoMinesweeperScreen(); // Navigate to minesweeper game
|
||||
#if defined(LILYGO_TWATCH_S3_PLUS)
|
||||
void gotoStepsScreen(); // Navigate to the step counter screen
|
||||
uint32_t getTodaySteps(); // Daily step count (raw - baseline)
|
||||
#endif
|
||||
#if HAS_GPS
|
||||
void gotoMapScreen(); // Navigate to map tile screen
|
||||
#endif
|
||||
@@ -281,6 +290,9 @@ public:
|
||||
bool isOnTraceScreen() const { return curr == trace_screen; }
|
||||
bool isOnGamesMenu() const { return curr == games_menu_screen; }
|
||||
bool isOnSnakeScreen() const { return curr == snake_screen; }
|
||||
#if defined(LILYGO_TWATCH_S3_PLUS)
|
||||
bool isOnStepsScreen() const { return curr == steps_screen; }
|
||||
#endif
|
||||
bool isOnMinesweeperScreen() const { return curr == minesweeper_screen; }
|
||||
bool isOnMapScreen() const { return curr == map_screen; }
|
||||
#if defined(LilyGo_T5S3_EPaper_Pro) || defined(LilyGo_TDeck_Pro) || defined(LILYGO_TWATCH_S3_PLUS)
|
||||
@@ -370,6 +382,9 @@ public:
|
||||
UIScreen* getTraceScreen() const { return trace_screen; }
|
||||
UIScreen* getGamesMenuScreen() const { return games_menu_screen; }
|
||||
UIScreen* getSnakeScreen() const { return snake_screen; }
|
||||
#if defined(LILYGO_TWATCH_S3_PLUS)
|
||||
UIScreen* getStepsScreen() const { return steps_screen; }
|
||||
#endif
|
||||
UIScreen* getMinesweeperScreen() const { return minesweeper_screen; }
|
||||
UIScreen* getMapScreen() const { return map_screen; }
|
||||
#ifdef MECK_WEB_READER
|
||||
|
||||
Reference in New Issue
Block a user