Skip to content

Commit e30ea3d

Browse files
author
thingsapart
committed
MDI actions and observables, UI work and fixing crashes
1 parent 57c8a9f commit e30ea3d

9 files changed

Lines changed: 2348 additions & 1486 deletions

File tree

firmware/cnc_interface/src/ui/components/lv_cam_positioning.c

Lines changed: 271 additions & 6 deletions
Large diffs are not rendered by default.

firmware/cnc_interface/src/ui/components/lv_cam_positioning.h

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -188,6 +188,37 @@ void lv_cam_positioning_set_probe_cbs(lv_obj_t *obj,
188188
/// Calling this while a probe operation is in-flight also cancels the op.
189189
void lv_cam_positioning_wizard_cancel(lv_obj_t *obj);
190190

191+
// ---------------------------------------------------------------------------
192+
// Local camera-connection status label
193+
// ---------------------------------------------------------------------------
194+
195+
/**
196+
* @brief Show a status message overlaid on the camera area.
197+
*
198+
* Displays a semi-transparent label centred on the camera view. The message
199+
* is "locked in" — the auto-managed "Connecting to camera..." text will not
200+
* appear until lv_cam_positioning_clear_status_text() is called.
201+
*
202+
* Pass an empty string or call lv_cam_positioning_clear_status_text() to
203+
* return to automatic management (label shows when no frame, hides when
204+
* the camera starts streaming).
205+
*
206+
* @param obj The lv_cam_positioning widget.
207+
* @param text The message to display, or NULL / "" to clear.
208+
*/
209+
void lv_cam_positioning_show_status_text(lv_obj_t *obj, const char *text);
210+
211+
/**
212+
* @brief Clear any manually set status message and return to auto-management.
213+
*
214+
* After this call the widget manages the label automatically: the
215+
* "Connecting to camera..." message is shown when no frame has arrived and
216+
* hidden once the stream is live.
217+
*
218+
* @param obj The lv_cam_positioning widget.
219+
*/
220+
void lv_cam_positioning_clear_status_text(lv_obj_t *obj);
221+
191222
#ifdef __cplusplus
192223
}
193224
#endif

firmware/cnc_interface/src/ui/components/lv_probing_wizard.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
#define UI_DEBUG_LOCAL_LEVEL D_VERBOSE
1+
#define UI_DEBUG_LOCAL_LEVEL D_WARN
22
#include "debug.h"
33

44
#include "lv_probing_wizard.h"

firmware/cnc_interface/src/ui/interface.c

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -269,6 +269,11 @@ static bool on_log_message(machine_interface_t *machine, void *user_data,
269269
interface_t *interface = (interface_t *)user_data;
270270
// Log verbatim to the pendant's serial output regardless.
271271
LOGI(TAG, "Hub msg: %s", message);
272+
273+
// Let the MDI handler append to its log buffer and check for 'ok' acks.
274+
// This runs in the machine thread: mdi_handler_on_log() only sets flags.
275+
mdi_handler_on_log(&interface->mdi, message);
276+
272277
// Suppress noisy "Error: Bad command:" lines from the toast bar — these are
273278
// echoed back by the machine when it doesn't recognise a polled M409 query
274279
// and do not represent actionable errors for the operator.
@@ -278,6 +283,7 @@ static bool on_log_message(machine_interface_t *machine, void *user_data,
278283

279284
// If a prior handler already claimed this message, avoid showing the toast.
280285
if (machine && machine->last_log_message_handled) {
286+
LOGI(TAG, "Skipped log entry: %s", message);
281287
return false; // not handled by UI
282288
}
283289

@@ -288,6 +294,15 @@ static bool on_log_message(machine_interface_t *machine, void *user_data,
288294
return true;
289295
}
290296

297+
/**
298+
* @brief Long-press handler on the "all axes homed" LED in the title bar.
299+
* Opens the "Home all axes?" confirmation modal.
300+
*/
301+
static void homed_led_longpress_cb(lv_event_t *e) {
302+
machine_interface_t *machine = (machine_interface_t *)lv_event_get_user_data(e);
303+
if (machine) show_home_all_modal(machine);
304+
}
305+
291306
// --- Public API ---
292307

293308
void interface_init(interface_t *interface, machine_interface_t *machine) {
@@ -309,6 +324,10 @@ void interface_init(interface_t *interface, machine_interface_t *machine) {
309324

310325
ui_action_handler_init(interface);
311326

327+
// Initialise the MDI backend (allocates log buffer, finds widget IDs,
328+
// registers the LV_EVENT_READY handler on the input textarea).
329+
mdi_handler_init(&interface->mdi, machine);
330+
312331
// Register callbacks to get state updates from the machine
313332
machine_interface_add_state_change_cb(machine, interface,
314333
on_machine_state_change);
@@ -342,6 +361,15 @@ void interface_init(interface_t *interface, machine_interface_t *machine) {
342361
lv_obj_add_event_cb(disconnected_overlay, disconnected_overlay_event_handler, LV_EVENT_LONG_PRESSED, NULL);
343362
}
344363

364+
// Attach long-press handler to the "all axes homed" LED in the title bar
365+
// so the operator can quickly trigger a home-all confirmation.
366+
lv_obj_t* homed_led = obj_registry_get("homed_all_led");
367+
if (homed_led) {
368+
lv_obj_add_flag(homed_led, LV_OBJ_FLAG_CLICKABLE);
369+
lv_obj_add_event_cb(homed_led, homed_led_longpress_cb,
370+
LV_EVENT_LONG_PRESSED, machine);
371+
}
372+
345373
// Wire the machine's axis limits into the cam_positioning overlay so the
346374
// physical coordinate grid can be drawn.
347375
lv_obj_t* cam_pos = obj_registry_get("cam_positioning");
@@ -391,6 +419,9 @@ void interface_init(interface_t *interface, machine_interface_t *machine) {
391419
}
392420

393421
void interface_tick(interface_t *interface) {
422+
// Flush MDI log-buffer and busy-state to data-binding observers every tick.
423+
mdi_handler_tick(&interface->mdi);
424+
394425
if (interface->dirty_flags == UI_DIRTY_NONE) {
395426
return;
396427
}

firmware/cnc_interface/src/ui/interface.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ extern "C" {
88
#include "lvgl.h"
99
#include "machine/machine_interface.h"
1010
#include "probe/mos_probe_handler.h"
11+
#include "ui/mdi_handler.h"
1112

1213
#ifdef DWC_MACHINE_MODE
1314
#include "config/dwc_settings.h"
@@ -31,6 +32,7 @@ typedef enum {
3132
UI_DIRTY_FILES_GCODES = (1 << 10),
3233
UI_DIRTY_FILES_MACROS = (1 << 11),
3334
UI_DIRTY_LOG_MESSAGE = (1 << 12), // Verbatim message from hub to toast
35+
UI_DIRTY_MDI_LOG = (1 << 13), // New MDI log content / busy-state change
3436
UI_DIRTY_ALL = 0xFFFFFFFF,
3537
} ui_dirty_flags_t;
3638

@@ -44,6 +46,7 @@ typedef struct {
4446
lv_obj_t *toast_bar; // Currently visible toast bar, or NULL.
4547

4648
mos_probe_handler_t probe_handler; ///< MOS back-end for cam_positioning probe wizard
49+
mdi_handler_t mdi; ///< MDI (Manual Data Input) back-end
4750

4851
#ifdef DWC_MACHINE_MODE
4952
dwc_settings_t setup_settings; // Temporary storage for the DWC setup flow

firmware/cnc_interface/src/ui/ui_action_handler.c

Lines changed: 50 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66

77
#include "debug.h"
88
#include "lvgl_ui.h"
9+
#include "ui/mdi_handler.h"
910

1011
static const char *TAG = "UI_ACTION_HANDLER";
1112

@@ -50,7 +51,7 @@ static void home_all_modal_event_handler(lv_event_t * e) {
5051
* @brief Creates and displays a modal dialog asking the user to home all axes.
5152
* @param machine A pointer to the machine interface, passed to the event handler.
5253
*/
53-
static void show_home_all_modal(machine_interface_t * machine) {
54+
void show_home_all_modal(machine_interface_t * machine) {
5455
static const char * btns[] = {"Ok", "Cancel", ""};
5556
lv_obj_t * mbox = lv_msgbox_create(lv_screen_active());
5657
lv_msgbox_add_title(mbox, "Home all?");
@@ -167,6 +168,54 @@ static void app_action_handler(const char *action_name, binding_value_t value,
167168
machine->probe(machine, gcode);
168169
}
169170

171+
// --- MDI Actions ---
172+
// Forward all "MDI.*" actions to the MDI handler.
173+
else if (strncmp(action_name, "MDI.", 4) == 0) {
174+
mdi_handle_action(&interface->mdi, action_name, value);
175+
}
176+
177+
// --- Probe dimension settings (from the probe-mode tab numeric dialogs) ---
178+
// Each action receives the user-entered float value and:
179+
// 1. Notifies the bound observable so the label refreshes.
180+
// 2. (Future) Could persist the value here.
181+
else if (strcmp(action_name, "set_probe_width") == 0 &&
182+
value.type == BINDING_TYPE_FLOAT) {
183+
data_binding_notify_state_changed(
184+
"probe_w",
185+
(binding_value_t){.type = BINDING_TYPE_FLOAT, .as.f_val = value.as.f_val});
186+
}
187+
else if (strcmp(action_name, "set_probe_height") == 0 &&
188+
value.type == BINDING_TYPE_FLOAT) {
189+
data_binding_notify_state_changed(
190+
"probe_h",
191+
(binding_value_t){.type = BINDING_TYPE_FLOAT, .as.f_val = value.as.f_val});
192+
}
193+
else if (strcmp(action_name, "set_probe_cl") == 0 &&
194+
value.type == BINDING_TYPE_FLOAT) {
195+
data_binding_notify_state_changed(
196+
"probe_cl",
197+
(binding_value_t){.type = BINDING_TYPE_FLOAT, .as.f_val = value.as.f_val});
198+
}
199+
else if (strcmp(action_name, "set_probe_ov") == 0 &&
200+
value.type == BINDING_TYPE_FLOAT) {
201+
data_binding_notify_state_changed(
202+
"probe_ov",
203+
(binding_value_t){.type = BINDING_TYPE_FLOAT, .as.f_val = value.as.f_val});
204+
}
205+
else if (strcmp(action_name, "set_probe_quick") == 0) {
206+
// Boolean toggle from the quick-mode switch widget.
207+
bool quick = (value.type == BINDING_TYPE_BOOL) ? value.as.b_val
208+
: (value.as.f_val != 0.0f);
209+
data_binding_notify_state_changed(
210+
"probe_quick",
211+
(binding_value_t){.type = BINDING_TYPE_BOOL, .as.b_val = quick});
212+
}
213+
214+
// --- ask_home_all: programmatically triggered (e.g. from C callbacks) ---
215+
else if (strcmp(action_name, "action.ask_home_all") == 0) {
216+
show_home_all_modal(machine);
217+
}
218+
170219
else {
171220
LOGW(TAG, "Unhandled action: %s", action_name);
172221
}

firmware/cnc_interface/src/ui/ui_action_handler.h

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,4 +15,15 @@
1515
*/
1616
void ui_action_handler_init(interface_t *interface);
1717

18+
/**
19+
* @brief Creates and displays a "Home all axes?" confirmation modal.
20+
*
21+
* If the user confirms, machines->home_all() is called.
22+
* This function is also invoked from the long-press callback on the
23+
* "all axes homed" LED in the title bar.
24+
*
25+
* @param machine A pointer to the machine interface.
26+
*/
27+
void show_home_all_modal(machine_interface_t *machine);
28+
1829
#endif // UI_ACTION_HANDLER_H

0 commit comments

Comments
 (0)