e1608: a configurable generator update rate, and the achieved rate in the Analog out panel

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Martino FerrariandClaude Opus 4.6 committed 2026-11-02 12:19:23 +01:00
1 parent 0c6e69957d
commit 0d8c583bbb
12 files changed
+181 -11

No files matched your search

+71
View File
@@ -1923,6 +1923,7 @@ gboolean source_kinds_probe(gpointer user) {
c.set("trigger", "rising");
c.set("dir1", "o");
c.set("plot0", "1");
c.set("gen_rate", "120");
} else if (id == "flatudp") {
c.set("port", "44600");
c.set("bind", "10.0.0.8");
@@ -2428,6 +2429,76 @@ gboolean e1608_probe(gpointer user) {
return G_SOURCE_REMOVE;
}
/// Phase 3 of the generator probe: the generator switched off 400 ms ago; the achieved rate and the
/// panel must both have gone back to "off".
gboolean e1608_gen_probe_stopped(gpointer user) {
App* a = static_cast<App*>(user);
if (a->window == nullptr) return G_SOURCE_REMOVE;
e1608::E1608Source* src = e1608_source(a);
if (src == nullptr) return G_SOURCE_REMOVE;
GtkWidget* row = find_named(source_panel_content(a, "source-ao"), "e1608-gen-rate");
const char* sub = row != nullptr ? adw_action_row_get_subtitle(ADW_ACTION_ROW(row)) : nullptr;
const double hz = src->readouts()->gen_hz.load();
const bool off = sub != nullptr && std::strncmp(sub, "off", 3) == 0;
std::fprintf(stderr, "[e1608] generator stopped: achieved=%.1f panel='%s' ok=%d\n", hz,
sub != nullptr ? sub : "", hz == 0.0 && off ? 1 : 0);
std::fflush(stderr);
return G_SOURCE_REMOVE;
}
/// Phase 2 of the generator probe, 2.5 s after a Sine generator was started on DAC 0: the achieved
/// update rate the source measured, and the text the Analog out panel shows for it.
gboolean e1608_gen_probe_report(gpointer user) {
App* a = static_cast<App*>(user);
if (a->window == nullptr) return G_SOURCE_REMOVE;
e1608::E1608Source* src = e1608_source(a);
if (src == nullptr) return G_SOURCE_REMOVE;
GtkWidget* ao = source_panel_content(a, "source-ao");
GtkWidget* row = find_named(ao, "e1608-gen-rate");
const char* sub = row != nullptr ? adw_action_row_get_subtitle(ADW_ACTION_ROW(row)) : nullptr;
const double req = src->settings().gen_rate;
const double hz = src->readouts()->gen_hz.load();
// The mock answers at once, so the achieved rate sits at the requested one; the band is loose.
const bool in_range = hz >= 0.7 * req && hz <= 1.1 * req;
char want[32];
std::snprintf(want, sizeof want, "(requested %.0f Hz)", req);
const bool shown = sub != nullptr && std::strstr(sub, want) != nullptr && std::strstr(sub, "Hz") != nullptr;
std::fprintf(stderr, "[e1608] generator: requested=%.1f achieved=%.1f panel='%s' ok=%d\n", req, hz,
sub != nullptr ? sub : "", in_range && shown ? 1 : 0);
std::fflush(stderr);
GtkWidget* run = find_named(ao, "e1608-ao0-run");
if (run != nullptr) adw_switch_row_set_active(ADW_SWITCH_ROW(run), FALSE);
g_timeout_add(400, e1608_gen_probe_stopped, a);
return G_SOURCE_REMOVE;
}
/// Starts a Sine generator on DAC 0 through the panel's own controls, then reads it 2.5 s later.
gboolean e1608_gen_probe(gpointer user) {
App* a = static_cast<App*>(user);
if (a->window == nullptr) return G_SOURCE_REMOVE;
e1608::E1608Source* src = e1608_source(a);
if (src == nullptr) {
std::fprintf(stderr, "[e1608] generator: no e1608 source (run with --source e1608)\n");
std::fflush(stderr);
return G_SOURCE_REMOVE;
}
GtkWidget* ao = source_panel_content(a, "source-ao");
GtkWidget* mode = find_named(ao, "e1608-ao0-mode");
GtkWidget* run = find_named(ao, "e1608-ao0-run");
if (mode == nullptr || run == nullptr) {
std::fprintf(stderr, "[e1608] generator: controls missing (mode=%d run=%d)\n", mode != nullptr ? 1 : 0,
run != nullptr ? 1 : 0);
std::fflush(stderr);
return G_SOURCE_REMOVE;
}
// The panel refreshes on its frame clock, which only ticks while the page is on screen.
if (a->side_stack != nullptr) adw_view_stack_set_visible_child_name(ADW_VIEW_STACK(a->side_stack), "source-ao");
adw_combo_row_set_selected(ADW_COMBO_ROW(mode), 1); // Sine
adw_switch_row_set_active(ADW_SWITCH_ROW(run), TRUE);
g_timeout_add(2500, e1608_gen_probe_report, a);
return G_SOURCE_REMOVE;
}
/// After the mock dropped the link: has the source reconnected, and does the stream move again?
gboolean e1608_probe_resumed(gpointer user) {
App* a = static_cast<App*>(user);