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:
1 parent
0c6e69957d
commit
0d8c583bbb
12 files changed
+181
-11
No files matched your search
@@ -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);
|
||||
|
||||
Reference in new issue
Block a user