#include "config.h"
#include <locale.h>
#include <libintl.h>
#define _(x) gettext(x)
#include <sys/types.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <string.h>
#include "rtapi.h"
#include "hal.h"
#include "../hal_priv.h"
#include <gtk/gtk.h>
#include "miscgtk.h"
#include "scope_usr.h"
#define BUFLEN 80
#define TRIG_LEVEL_RESOLUTION 100.0
#define TRIG_POS_RESOLUTION 100.0
static void init_trigger_mode_window(void);
static void init_trigger_info_window(void);
static void trigger_selection_made(GtkWidget * clist, gint row, gint column,
GdkEventButton * event, dialog_generic_t * dptr);
static void dialog_select_trigger_source(void);
static void auto_button_clicked(GtkWidget * widget, gpointer * gdata);
static void normal_button_clicked(GtkWidget * widget, gpointer * gdata);
static void force_button_clicked(GtkWidget * widget, gpointer * gdata);
static void source_button_clicked(GtkWidget * widget, gpointer * gdata);
static void edge_button_clicked(GtkWidget * widget, gpointer * gdata);
static void level_changed(GtkAdjustment * adj, gpointer gdata);
static void pos_changed(GtkAdjustment * adj, gpointer gdata);
void init_trig(void)
{
ctrl_shm->state = IDLE;
init_trigger_mode_window();
init_trigger_info_window();
}
void refresh_trigger(void)
{
scope_trig_t *trig;
scope_chan_t *chan;
gchar buf[BUFLEN + 1];
double fp_level;
trig = &(ctrl_usr->trig);
if (ctrl_shm->trig_edge == 0) {
snprintf(buf, BUFLEN, _("Falling"));
} else {
snprintf(buf, BUFLEN, _("Rising"));
}
gtk_label_set_text_if(trig->edge_label, buf);
if ((ctrl_shm->trig_chan < 1) || (ctrl_shm->trig_chan > 16)) {
ctrl_shm->trig_chan = 0;
gtk_label_set_text_if(trig->source_label, _("Source\nNone"));
gtk_label_set_text_if(trig->level_label, " ---- ");
return;
}
snprintf(buf, BUFLEN, _("Source\nChan %2d"), ctrl_shm->trig_chan);
gtk_label_set_text_if(trig->source_label, buf);
chan = &(ctrl_usr->chan[ctrl_shm->trig_chan - 1]);
fp_level =
chan->scale * ((chan->position - trig->level) * 10) +
chan->vert_offset;
switch (chan->data_type) {
case HAL_FLOAT:
ctrl_shm->trig_level.d_real = fp_level;
break;
case HAL_S32:
if (fp_level > 2147483647.0) {
fp_level = 2147483647.0;
}
if (fp_level < -2147483648.0) {
fp_level = -2147483648.0;
}
ctrl_shm->trig_level.d_s32 = fp_level;
break;
case HAL_U32:
if (fp_level > 4294967295.0) {
fp_level = 4294967295.0;
}
if (fp_level < 0.0) {
fp_level = 0.0;
}
ctrl_shm->trig_level.d_u32 = fp_level;
break;
default:
break;
}
if (chan->data_type == HAL_BIT) {
snprintf(buf, BUFLEN, " ---- ");
gtk_widget_set_sensitive(GTK_WIDGET(trig->level_slider), 0);
} else {
format_signal_value(buf, BUFLEN, fp_level);
gtk_widget_set_sensitive(GTK_WIDGET(trig->level_slider), 1);
}
gtk_label_set_text_if(trig->level_label, buf);
refresh_display();
}
void write_trig_config(FILE *fp)
{
scope_trig_t *trig;
trig = &(ctrl_usr->trig);
if (ctrl_shm->trig_chan > 0) {
fprintf(fp, "TSOURCE %d\n", ctrl_shm->trig_chan);
fprintf(fp, "TLEVEL %f\n", trig->level);
fprintf(fp, "TPOS %f\n", trig->position);
fprintf(fp, "TPOLAR %d\n", ctrl_shm->trig_edge);
}
fprintf(fp, "TMODE %d\n", ctrl_shm->auto_trig);
}
static void init_trigger_mode_window(void)
{
scope_trig_t *trig;
trig = &(ctrl_usr->trig);
ctrl_shm->auto_trig = 0;
trig->normal_button = gtk_radio_button_new_with_label(NULL, _("Normal"));
trig->auto_button =
gtk_radio_button_new_with_label(gtk_radio_button_group
(GTK_RADIO_BUTTON(trig->normal_button)), _("Auto"));
trig->force_button = gtk_button_new_with_label(_("Force"));
gtk_box_pack_start(GTK_BOX(ctrl_usr->trig_mode_win),
trig->normal_button, FALSE, FALSE, 0);
gtk_box_pack_start(GTK_BOX(ctrl_usr->trig_mode_win),
trig->auto_button, FALSE, FALSE, 0);
gtk_box_pack_start(GTK_BOX(ctrl_usr->trig_info_win),
trig->force_button, FALSE, FALSE, 0);
gtk_signal_connect(GTK_OBJECT(trig->normal_button), "clicked",
GTK_SIGNAL_FUNC(normal_button_clicked), NULL);
gtk_signal_connect(GTK_OBJECT(trig->auto_button), "clicked",
GTK_SIGNAL_FUNC(auto_button_clicked), NULL);
gtk_signal_connect(GTK_OBJECT(trig->force_button), "clicked",
GTK_SIGNAL_FUNC(force_button_clicked), NULL);
gtk_widget_show(trig->normal_button);
gtk_widget_show(trig->auto_button);
gtk_widget_show(trig->force_button);
}
static void init_trigger_info_window(void)
{
scope_trig_t *trig;
GtkWidget *hbox, *vbox;
trig = &(ctrl_usr->trig);
hbox =
gtk_hbox_new_in_box(TRUE, 0, 0, ctrl_usr->trig_info_win, TRUE, TRUE,
0);
vbox = gtk_vbox_new_in_box(FALSE, 0, 0, hbox, TRUE, TRUE, 0);
gtk_label_new_in_box(_("Level"), vbox, FALSE, FALSE, 0);
trig->level_adj =
gtk_adjustment_new(TRIG_LEVEL_RESOLUTION / 2, 0,
TRIG_LEVEL_RESOLUTION, 1, 1, 0);
trig->level_slider = gtk_vscale_new(GTK_ADJUSTMENT(trig->level_adj));
gtk_scale_set_digits(GTK_SCALE(trig->level_slider), 0);
gtk_scale_set_draw_value(GTK_SCALE(trig->level_slider), FALSE);
gtk_box_pack_start(GTK_BOX(vbox), trig->level_slider, TRUE, TRUE, 0);
trig->level =
(GTK_ADJUSTMENT(trig->level_adj))->value / TRIG_LEVEL_RESOLUTION;
gtk_signal_connect(GTK_OBJECT(trig->level_adj), "value_changed",
GTK_SIGNAL_FUNC(level_changed), NULL);
gtk_widget_show(trig->level_slider);
vbox = gtk_vbox_new_in_box(FALSE, 0, 0, hbox, TRUE, TRUE, 0);
gtk_label_new_in_box(_("Pos"), vbox, FALSE, FALSE, 0);
trig->pos_adj =
gtk_adjustment_new(TRIG_POS_RESOLUTION / 2, 0, TRIG_POS_RESOLUTION, 1,
1, 0);
trig->pos_slider = gtk_vscale_new(GTK_ADJUSTMENT(trig->pos_adj));
gtk_scale_set_digits(GTK_SCALE(trig->pos_slider), 0);
gtk_scale_set_draw_value(GTK_SCALE(trig->pos_slider), FALSE);
gtk_box_pack_start(GTK_BOX(vbox), trig->pos_slider, TRUE, TRUE, 0);
trig->position =
(GTK_ADJUSTMENT(trig->pos_adj))->value / TRIG_POS_RESOLUTION;
gtk_signal_connect(GTK_OBJECT(trig->pos_adj), "value_changed",
GTK_SIGNAL_FUNC(pos_changed), NULL);
gtk_widget_show(trig->pos_slider);
gtk_hseparator_new_in_box(ctrl_usr->trig_info_win, 3);
gtk_label_new_in_box(_("Level"), ctrl_usr->trig_info_win, FALSE, FALSE, 0);
trig->level_label =
gtk_label_new_in_box(" ---- ", ctrl_usr->trig_info_win, FALSE, FALSE,
0);
ctrl_shm->trig_edge = 1;
trig->edge_button = gtk_button_new_with_label(_("Rising"));
trig->edge_label = (GTK_BIN(trig->edge_button))->child;
gtk_box_pack_start(GTK_BOX(ctrl_usr->trig_info_win),
trig->edge_button, FALSE, FALSE, 0);
gtk_signal_connect(GTK_OBJECT(trig->edge_button), "clicked",
GTK_SIGNAL_FUNC(edge_button_clicked), NULL);
gtk_widget_show(trig->edge_button);
trig->source_button = gtk_button_new_with_label(_("Source\nNone"));
trig->source_label = (GTK_BIN(trig->source_button))->child;
gtk_box_pack_start(GTK_BOX(ctrl_usr->trig_info_win),
trig->source_button, FALSE, FALSE, 0);
gtk_signal_connect(GTK_OBJECT(trig->source_button), "clicked",
GTK_SIGNAL_FUNC(source_button_clicked), NULL);
gtk_widget_show(trig->source_button);
}
static void dialog_select_trigger_source(void)
{
dialog_generic_t dialog;
gchar *title, *msg;
int n, colwidth;
gchar *strs[2], *titles[2];
gchar buf[BUFLEN + 1];
GtkWidget *label, *button, *scrolled_window, *trig_list;
if (ctrl_shm->state != IDLE) { prepare_scope_restart(); }
title = _("Trigger Source");
msg = _("Select a channel to use for triggering.");
dialog.retval = 0;
dialog.window = gtk_dialog_new();
gtk_widget_set_usize(GTK_WIDGET(dialog.window), -2, 400);
gtk_window_set_policy(GTK_WINDOW(dialog.window), FALSE, TRUE, FALSE);
gtk_window_set_title(GTK_WINDOW(dialog.window), title);
label = gtk_label_new(msg);
gtk_misc_set_padding(GTK_MISC(label), 15, 5);
gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog.window)->vbox), label, FALSE,
TRUE, 0);
scrolled_window = gtk_scrolled_window_new(NULL, NULL);
gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled_window),
GTK_POLICY_AUTOMATIC, GTK_POLICY_ALWAYS);
gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog.window)->vbox),
scrolled_window, TRUE, TRUE, 5);
gtk_widget_show(scrolled_window);
titles[0] = _("Chan");
titles[1] = _("Source");
trig_list = gtk_clist_new_with_titles(2, titles);
gtk_clist_column_titles_passive(GTK_CLIST(trig_list));
gtk_signal_connect(GTK_OBJECT(trig_list), "select_row",
GTK_SIGNAL_FUNC(trigger_selection_made), &dialog);
gtk_clist_set_shadow_type(GTK_CLIST(trig_list), GTK_SHADOW_OUT);
gtk_clist_set_selection_mode(GTK_CLIST(trig_list), GTK_SELECTION_BROWSE);
gtk_container_add(GTK_CONTAINER(scrolled_window), trig_list);
gtk_widget_show(trig_list);
gtk_clist_clear(GTK_CLIST(trig_list));
for (n = 0; n < 16; n++) {
snprintf(buf, BUFLEN, "%d", n + 1);
strs[0] = buf;
if (ctrl_usr->chan[n].name != NULL) {
strs[1] = ctrl_usr->chan[n].name;
} else {
strs[1] = "----";
}
gtk_clist_append(GTK_CLIST(trig_list), strs);
}
colwidth = gtk_clist_optimal_column_width(GTK_CLIST(trig_list), 1);
gtk_clist_set_column_min_width(GTK_CLIST(trig_list), 1,
(colwidth * 17) / 16);
if (ctrl_shm->trig_chan > 0) {
gtk_clist_select_row(GTK_CLIST(trig_list), ctrl_shm->trig_chan - 1,
1);
}
gtk_signal_connect(GTK_OBJECT(dialog.window), "destroy",
GTK_SIGNAL_FUNC(dialog_generic_destroyed), &dialog);
button = gtk_button_new_with_label(_("Cancel"));
gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog.window)->action_area),
button, TRUE, TRUE, 4);
gtk_signal_connect(GTK_OBJECT(button), "clicked",
GTK_SIGNAL_FUNC(dialog_generic_button2), &dialog);
gtk_window_set_transient_for(GTK_WINDOW(dialog.window),
GTK_WINDOW(ctrl_usr->main_win));
gtk_window_set_modal(GTK_WINDOW(dialog.window), TRUE);
gtk_widget_show_all(dialog.window);
gtk_main();
trig_list = NULL;
}
int set_trigger_source(int chan_num)
{
ctrl_shm->trig_chan = chan_num;
if (ctrl_usr->chan[ctrl_shm->trig_chan - 1].name == NULL) {
ctrl_shm->trig_chan = 0;
}
refresh_trigger();
return 0;
}
static void trigger_selection_made(GtkWidget * clist, gint row, gint column,
GdkEventButton * event, dialog_generic_t * dptr)
{
GdkEventType type;
if ((event == NULL) || (clist == NULL)) {
return;
}
type = event->type;
if (type != 4) {
return;
}
set_trigger_source(row + 1);
dptr->retval = 1;
gtk_widget_destroy(dptr->window);
return;
}
int set_trigger_level(double setting)
{
scope_trig_t *trig;
GtkAdjustment *adj;
if (( setting < 0.0 ) || ( setting > 1.0 )) {
return -1;
}
trig = &(ctrl_usr->trig);
trig->level = setting;
adj = GTK_ADJUSTMENT(trig->level_adj);
gtk_adjustment_set_value(adj, trig->level * TRIG_LEVEL_RESOLUTION);
refresh_trigger();
return 0;
}
static void level_changed(GtkAdjustment * adj, gpointer gdata)
{
set_trigger_level(adj->value / TRIG_LEVEL_RESOLUTION);
}
int set_trigger_pos(double setting)
{
scope_trig_t *trig;
GtkAdjustment *adj;
if (( setting < 0.0 ) || ( setting > 1.0 )) {
return -1;
}
trig = &(ctrl_usr->trig);
if (ctrl_shm->state != IDLE) {
prepare_scope_restart();
}
trig->position = setting;
adj = GTK_ADJUSTMENT(trig->pos_adj);
gtk_adjustment_set_value(adj, trig->position * TRIG_POS_RESOLUTION);
refresh_trigger();
return 0;
}
static void pos_changed(GtkAdjustment * adj, gpointer gdata)
{
set_trigger_pos(adj->value / TRIG_POS_RESOLUTION);
}
int set_trigger_polarity(int setting)
{
if (setting == 0) {
ctrl_shm->trig_edge = 0;
} else if ( setting == 1 ) {
ctrl_shm->trig_edge = 1;
} else {
return -1;
}
refresh_trigger();
return 0;
}
static void edge_button_clicked(GtkWidget * widget, gpointer * gdata)
{
if (ctrl_shm->trig_edge == 0) {
set_trigger_polarity(1);
} else {
set_trigger_polarity(0);
}
}
int set_trigger_mode(int mode)
{
GtkWidget *button;
if ( mode == 0 ) {
button = ctrl_usr->trig.normal_button;
} else if ( mode == 1 ) {
button = ctrl_usr->trig.auto_button;
} else {
return -1;
}
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(button), 1);
return 0;
}
static void normal_button_clicked(GtkWidget * widget, gpointer * gdata)
{
if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)) != TRUE) {
return;
}
ctrl_shm->auto_trig = 0;
}
static void auto_button_clicked(GtkWidget * widget, gpointer * gdata)
{
if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)) != TRUE) {
return;
}
ctrl_shm->auto_trig = 1;
}
static void force_button_clicked(GtkWidget * widget, gpointer * gdata)
{
ctrl_shm->force_trig = 1;
}
static void source_button_clicked(GtkWidget * widget, gpointer * gdata)
{
dialog_select_trigger_source();
}