ui: the trigger panel offers a noise band and an HF reject
Two label-only rows in trigger-panel.ui (band_row, hf_row, after holdoff_row and before
mode_row) and the two spins the code appends into them: the band on the level spins' scale
in signal units, the HF reject at 0-1e7 Hz with 0 off. Both are published with the other
fields -- read before the model lock is taken, assigned inside it -- and both join the
value-changed loop, so editing either republishes the condition.
The rows are shown per type: the band for every type but Dropout, which is an absence a
band cannot describe, and the HF reject for all of them, since it sits before every
comparison. `sync_trigger_rows()` resolves a row as its spin's parent rather than keeping a
second handle to it: the row comes from the file and holds one child.
The exit dump counts the panel's controls, so it reads controls_inside=15/15 now -- and the
probe confirms it, along with both search readings and no Gtk-CRITICAL:
[udpscope] trigger panel: boxes=15 controls_inside=15/15 search_widgets=4/4 search_inside=4/4
This commit is contained in:
1 parent
d34bff3f03
commit
1583741e03
5 files changed
+51
-5
No files matched your search
+3
-1
@@ -5812,7 +5812,7 @@ int run_ui(int argc, char** argv, const Config& cfg, ScopeModel& model, Acquisit
|
||||
(app.search_run_button != nullptr) + (app.search_cancel_button != nullptr) +
|
||||
(app.search_prev_button != nullptr) + (app.search_next_button != nullptr);
|
||||
std::printf(
|
||||
"[udpscope] trigger panel: boxes=%d controls_inside=%d/13 search_widgets=%d/4 "
|
||||
"[udpscope] trigger panel: boxes=%d controls_inside=%d/15 search_widgets=%d/4 "
|
||||
"search_inside=%d/4\n",
|
||||
boxes,
|
||||
inside(app.trigger_signal_drop, app.trigger_panel) +
|
||||
@@ -5827,6 +5827,8 @@ int run_ui(int argc, char** argv, const Config& cfg, ScopeModel& model, Acquisit
|
||||
inside(app.trigger_level_spin, app.trigger_panel) +
|
||||
inside(app.trigger_pre_spin, app.trigger_panel) +
|
||||
inside(app.trigger_holdoff_spin, app.trigger_panel) +
|
||||
inside(app.trigger_band_spin, app.trigger_panel) +
|
||||
inside(app.trigger_hf_spin, app.trigger_panel) +
|
||||
inside(app.events_record_switch, app.trigger_panel),
|
||||
search_present,
|
||||
inside(app.search_run_button, search_root) + inside(app.search_cancel_button, search_root) +
|
||||
|
||||
@@ -162,6 +162,30 @@
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkBox" id="band_row">
|
||||
<property name="orientation">horizontal</property>
|
||||
<property name="spacing">6</property>
|
||||
<child>
|
||||
<object class="GtkLabel">
|
||||
<property name="label" translatable="yes">noise band</property>
|
||||
<property name="halign">start</property>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkBox" id="hf_row">
|
||||
<property name="orientation">horizontal</property>
|
||||
<property name="spacing">6</property>
|
||||
<child>
|
||||
<object class="GtkLabel">
|
||||
<property name="label" translatable="yes">HF reject Hz</property>
|
||||
<property name="halign">start</property>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkBox" id="mode_row">
|
||||
<property name="orientation">horizontal</property>
|
||||
|
||||
@@ -170,6 +170,8 @@ struct App {
|
||||
GtkWidget* trigger_level_spin = nullptr;
|
||||
GtkWidget* trigger_pre_spin = nullptr;
|
||||
GtkWidget* trigger_holdoff_spin = nullptr;
|
||||
GtkWidget* trigger_band_spin = nullptr; ///< EventCondition::noise_band
|
||||
GtkWidget* trigger_hf_spin = nullptr; ///< EventCondition::hf_fc, 0 is off
|
||||
GtkWidget* signal_list = nullptr;
|
||||
GtkWidget* pause_button = nullptr;
|
||||
/// When the pause began, on the **monotonic wall clock**, or 0 while running. The elapsed time
|
||||
|
||||
+18
-1
@@ -69,6 +69,8 @@ void publish_trigger_fields(App* app) {
|
||||
const double width2 = gtk_spin_button_get_value(GTK_SPIN_BUTTON(app->trigger_width2_spin));
|
||||
const double level2 = gtk_spin_button_get_value(GTK_SPIN_BUTTON(app->trigger_level2_spin));
|
||||
const double timeout = gtk_spin_button_get_value(GTK_SPIN_BUTTON(app->trigger_timeout_spin));
|
||||
const double band = gtk_spin_button_get_value(GTK_SPIN_BUTTON(app->trigger_band_spin));
|
||||
const double hf = gtk_spin_button_get_value(GTK_SPIN_BUTTON(app->trigger_hf_spin));
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(app->model->mutex());
|
||||
TriggerConfig& tc = app->model->trigger();
|
||||
@@ -85,6 +87,8 @@ void publish_trigger_fields(App* app) {
|
||||
tc.condition.width2_s = width2;
|
||||
tc.condition.level2 = level2;
|
||||
tc.condition.timeout_s = timeout;
|
||||
tc.condition.noise_band = band;
|
||||
tc.condition.hf_fc = hf;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -110,6 +114,11 @@ void sync_trigger_rows(App& app) {
|
||||
show(app.trigger_width2_row, pulse && (cmp == WidthCmp::Within || cmp == WidthCmp::Outside));
|
||||
show(app.trigger_level2_row, window);
|
||||
show(app.trigger_timeout_row, type == TriggerType::Dropout);
|
||||
// A band widens the comparator every type but Dropout compares with; a dropout is an absence and a
|
||||
// band cannot describe one. The HF reject sits before every comparison, so it applies to all types.
|
||||
// The rows come from the file and hold their spin, so the spin's parent *is* the row.
|
||||
show(gtk_widget_get_parent(app.trigger_band_spin), type != TriggerType::Dropout);
|
||||
show(gtk_widget_get_parent(app.trigger_hf_spin), true);
|
||||
// A band of zero width reduces the condition to a float-equality test on a real-valued
|
||||
// signal, which is unusable: it fires on the exact value and nothing else, which in practice
|
||||
// is never. The panel is where that is refused: the second level is pushed at least one
|
||||
@@ -282,6 +291,13 @@ GtkWidget* build_trigger_panel(App& app) {
|
||||
app.trigger_holdoff_spin = spin(0.0, 3600.0, 0.001, 4,
|
||||
app.model->config().trigger_holdoff_s);
|
||||
row_for(ui, "holdoff_row", app.trigger_holdoff_spin);
|
||||
// A band in signal units, on the same scale as the level spins.
|
||||
app.trigger_band_spin = spin(0.0, 1.0e12, 0.01, 4, 0.0);
|
||||
row_for(ui, "band_row", app.trigger_band_spin);
|
||||
// 0 is off. The upper bound is generous; `configure()` clamps to just under the stream's Nyquist,
|
||||
// which the panel cannot know.
|
||||
app.trigger_hf_spin = spin(0.0, 1.0e7, 1.0, 3, 0.0);
|
||||
row_for(ui, "hf_row", app.trigger_hf_spin);
|
||||
|
||||
const char* modes[] = {"normal", "single", nullptr};
|
||||
app.trigger_mode_drop = gtk_drop_down_new_from_strings(modes);
|
||||
@@ -314,7 +330,8 @@ GtkWidget* build_trigger_panel(App& app) {
|
||||
|
||||
for (GtkWidget* w : {app.trigger_level_spin, app.trigger_pre_spin, app.trigger_holdoff_spin,
|
||||
app.trigger_width_spin, app.trigger_width2_spin,
|
||||
app.trigger_level2_spin, app.trigger_timeout_spin}) {
|
||||
app.trigger_level2_spin, app.trigger_timeout_spin, app.trigger_band_spin,
|
||||
app.trigger_hf_spin}) {
|
||||
g_signal_connect(w, "value-changed", G_CALLBACK(on_trigger_field_changed), &app);
|
||||
}
|
||||
g_signal_connect(app.trigger_edge_drop, "notify::selected",
|
||||
|
||||
Reference in new issue
Block a user