gps fixes

This commit is contained in:
liquidraver
2026-07-01 22:31:18 +02:00
parent 8f933fd2c7
commit 1cbddc64da
6 changed files with 92 additions and 7 deletions
@@ -1491,6 +1491,16 @@ void gps_enable(bool enable)
gps_current_state = GPS_STATE_OFF;
consecutive_good_fixes = 0;
/* Zero the stale satellite count so a re-enable doesn't briefly
* report a live fix (e.g. joystick UI showing "3D FIX") off old
* data before any new NMEA sentence arrives. lat/lon/valid are
* deliberately left alone — telemetry/UI "last known position"
* reads (gps_get_position/gps_load_position) intentionally survive
* an on/off toggle; only the live fix-quality indicator resets. */
k_mutex_lock(&gps_mutex, K_FOREVER);
current_pos.satellites = 0;
k_mutex_unlock(&gps_mutex);
/* Clear first-fix flags so the next enable gets a fresh long
* first-acquisition window again — the user explicitly toggled GPS
* expecting it to try hard for a fix. */
@@ -916,6 +916,30 @@ void JoystickUITask::toggleGPS()
mesh_gps_set_enabled(!gps_is_enabled());
}
uint32_t JoystickUITask::getGpsDutySec() const
{
return gps_get_poll_interval_sec();
}
void JoystickUITask::adjustGpsDuty(int step)
{
static const uint32_t kPresets[] = {
0, 10, 30, 60, 120, 300, 600, 900, 1800, 3600,
7200, 21600, 43200, 86400, 172800, 604800
};
const int kCount = (int)(sizeof(kPresets) / sizeof(kPresets[0]));
uint32_t cur = gps_get_poll_interval_sec();
int idx = kCount - 1;
for (int i = 0; i < kCount; i++) {
if (kPresets[i] >= cur) { idx = i; break; }
}
idx += step;
if (idx < 0) idx = 0;
if (idx >= kCount) idx = kCount - 1;
mesh_save_gps_duty_sec(kPresets[idx]);
}
void JoystickUITask::playCountdownAlarm()
{
#ifdef CONFIG_ZEPHCORE_UI_BUZZER
@@ -104,6 +104,12 @@ public:
bool isGPSAvailable() const;
bool getGPSState() const;
void toggleGPS();
/* GPS duty-cycle interval, seconds (0 = always on). Steps through a fixed
* preset ladder (step = +1/-1) rather than raw seconds, since the valid
* range spans 0..604800 a linear per-press delta would be unusable at
* either end. Applied live + persists to prefs. */
uint32_t getGpsDutySec() const;
void adjustGpsDuty(int step);
bool isSerialEnabled() const { return _ble_enabled; }
void disableSerial();
void enableSerial();
@@ -722,13 +722,24 @@ int GPSSettingsScreen::render(JoystickDisplay &display)
bool gps_enabled = _task->getGPSState();
char gps_state_line[24];
char top_line[24];
char satellites_line[32];
char lat_lon_line[40];
char speed_line[32];
snprintf(gps_state_line, sizeof(gps_state_line), "GPS: %s",
gps_enabled ? "ON" : "OFF");
/* Line 0 doubles as the GPS on/off toggle and the duty-cycle setting —
* the display only has room for 4 lines total (64px OLED), so rather
* than add a 5th line, _selected swaps what line 0 shows/does. */
if (_selected == 0) {
snprintf(top_line, sizeof(top_line), "GPS: %s", gps_enabled ? "ON" : "OFF");
} else {
uint32_t duty = _task->getGpsDutySec();
if (duty == 0) {
snprintf(top_line, sizeof(top_line), "Duty: Always on");
} else {
snprintf(top_line, sizeof(top_line), "Duty: %us", (unsigned)duty);
}
}
bool has_fix = false;
@@ -787,9 +798,9 @@ int GPSSettingsScreen::render(JoystickDisplay &display)
}
}
const char *lines[4] = { gps_state_line, satellites_line, lat_lon_line, speed_line };
const char *lines[4] = { top_line, satellites_line, lat_lon_line, speed_line };
renderScreenHeader(display, "GPS", 0, 1);
renderScreenHeader(display, "GPS", _selected, 2);
display.setTextSize(1);
int y = kContentY + 2;
@@ -803,9 +814,21 @@ int GPSSettingsScreen::render(JoystickDisplay &display)
bool GPSSettingsScreen::handleInput(char key)
{
if (handleCommonListNavigation(key, _selected, 2)) return true;
if (key == KEY_LEFT || key == KEY_RIGHT) {
if (_selected == 1) {
_task->adjustGpsDuty(key == KEY_RIGHT ? 1 : -1);
return true;
}
return false;
}
if (key == KEY_ENTER) {
_task->toggleGPS();
_task->showAlert(_task->getGPSState() ? "GPS enabled" : "GPS disabled", 1000);
if (_selected == 0) {
_task->toggleGPS();
_task->showAlert(_task->getGPSState() ? "GPS enabled" : "GPS disabled", 1000);
} else {
_task->adjustGpsDuty(1);
}
return true;
}
if (key == KEY_CANCEL || key == KEY_HOME) { _task->gotoHomeScreen(); return true; }
+19
View File
@@ -43,6 +43,7 @@ LOG_MODULE_REGISTER(zephcore_ui_actions, CONFIG_ZEPHCORE_UI_ACTIONS_LOG_LEVEL);
#define UI_ACTION_WAKE_ON_MSG_SAVE BIT(9)
#define UI_ACTION_SCREEN_OFF_SAVE BIT(10)
#define UI_ACTION_PATH_HASH_MODE_SAVE BIT(11)
#define UI_ACTION_GPS_DUTY_SAVE BIT(12)
/* Module-local pointers, set by init */
static CompanionMesh *s_mesh;
@@ -68,6 +69,7 @@ static atomic_t pending_brightness;
static atomic_t pending_wake_on_msg;
static atomic_t pending_screen_off_secs;
static atomic_t pending_path_hash_mode;
static atomic_t pending_gps_duty_sec;
extern "C" void ui_mesh_actions_init(struct k_event *mesh_events,
uint32_t mesh_event_ui_action,
@@ -151,6 +153,17 @@ extern "C" void mesh_save_path_hash_mode(uint8_t mode)
k_event_post(s_mesh_events, s_mesh_event_ui_action);
}
extern "C" void mesh_save_gps_duty_sec(uint32_t sec)
{
/* Apply immediately (lightweight, no flash) — same split as mesh_gps_set_enabled. */
gps_set_poll_interval_sec(sec);
/* Defer the flash write (savePrefs) to mesh thread */
atomic_set(&pending_gps_duty_sec, (atomic_val_t)sec);
atomic_or(&pending_ui_actions, UI_ACTION_GPS_DUTY_SAVE);
k_event_post(s_mesh_events, s_mesh_event_ui_action);
}
extern "C" void mesh_set_buzzer_quiet(bool quiet)
{
/* Defer the flash write (savePrefs) to mesh thread */
@@ -289,6 +302,12 @@ extern "C" void mesh_handle_ui_actions(void)
need_save = true;
}
if (actions & UI_ACTION_GPS_DUTY_SAVE) {
s_mesh->prefs.gps_interval = (uint32_t)atomic_get(&pending_gps_duty_sec);
LOG_INF("gps_interval=%u (button)", s_mesh->prefs.gps_interval);
need_save = true;
}
if (need_save || (actions & UI_ACTION_SAVE_RESTART)) {
s_data_store->savePrefs(s_mesh->prefs);
LOG_INF("prefs saved (button action)");
+3
View File
@@ -66,6 +66,9 @@ void mesh_set_wake_on_msg(bool enabled);
void mesh_save_screen_off_secs(uint16_t secs);
/* path_hash_mode: 0/1/2 → 1/2/3 bytes per hop appended to outbound flood path */
void mesh_save_path_hash_mode(uint8_t mode);
/* GPS duty-cycle interval in seconds (0 = always on). Applied live immediately
* (lightweight); the flash write is deferred to the mesh thread. */
void mesh_save_gps_duty_sec(uint32_t sec);
#ifdef __cplusplus
}