📄 scope_horiz.c
字号:
/** This file, 'halsc_horiz.c', contains the portion of halscope that deals with horizontal stuff - sample rate, scaling, position and such.*//** Copyright (C) 2003 John Kasunich <jmkasunich AT users DOT sourceforge DOT net>*//** This program is free software; you can redistribute it and/or modify it under the terms of version 2.1 of the GNU General Public License as published by the Free Software Foundation. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this library; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111 USA THE AUTHORS OF THIS LIBRARY ACCEPT ABSOLUTELY NO LIABILITY FOR ANY HARM OR LOSS RESULTING FROM ITS USE. IT IS _EXTREMELY_ UNWISE TO RELY ON SOFTWARE ALONE FOR SAFETY. Any machinery capable of harming persons must have provisions for completely removing power from all motors, etc, before persons enter any danger area. All machinery must be designed to comply with local and national safety codes, and the authors of this software can not, and do not, take any responsibility for such compliance. This code was written as part of the EMC HAL project. For more information, go to www.linuxcnc.org.*/#ifndef ULAPI#error This is a user mode component only!#endif#include <sys/types.h>#include <unistd.h>#include <stdio.h>#include <stdlib.h>#include <ctype.h>#include <string.h>#include "rtapi.h" /* RTAPI realtime OS API */#include "hal.h" /* HAL public API decls */#include "../hal_priv.h" /* private HAL decls */#include <gtk/gtk.h>#include "miscgtk.h" /* generic GTK stuff */#include "scope_usr.h" /* scope related declarations */#define BUFLEN 80 /* length for sprintf buffers *//************************************************************************ GLOBAL VARIABLES DECLARATIONS *************************************************************************//************************************************************************ LOCAL FUNCTION PROTOTYPES *************************************************************************/static void init_horiz_window(void);static void init_acquire_function(void);static void acquire_popup(GtkWidget * widget, gpointer gdata);static void dialog_realtime_not_loaded(void);static void dialog_realtime_not_linked(void);static void dialog_realtime_not_running(void);static void acquire_selection_made(GtkWidget * clist, gint row, gint column, GdkEventButton * event, gpointer gdata);static int set_sample_thread_name(char *name);static int activate_sample_thread(void);static void deactivate_sample_thread(void);static void mult_changed(GtkAdjustment * adj, gpointer gdata);static void zoom_changed(GtkAdjustment * adj, gpointer gdata);static void pos_changed(GtkAdjustment * adj, gpointer gdata);static void rec_len_button(GtkWidget * widget, gpointer gdata);static void calc_horiz_scaling(void);static void refresh_horiz_info(void);static void refresh_pos_disp(void);/* helper functions */static void format_time_value(char *buf, int buflen, float timeval);static void format_freq_value(char *buf, int buflen, float freqval);/* manipulation functions */static gint horiz_press(GtkWidget *widget, GdkEventButton *event);static gint horiz_release(GtkWidget *widget, GdkEventButton *event);static gint horiz_motion(GtkWidget *widget, GdkEventMotion *event);/************************************************************************ PUBLIC FUNCTIONS *************************************************************************/void init_horiz(void){ scope_horiz_t *horiz; /* stop sampling */ ctrl_shm->state = IDLE; /* make a pointer to the horiz structure */ horiz = &(ctrl_usr->horiz); /* init non-zero members of the horizontal structure */ /* set up the window */ init_horiz_window(); /* set up the realtime function */ init_acquire_function(); /* make sure displays are up to date */ calc_horiz_scaling(); refresh_horiz_info();}static void init_horiz_window(void){ scope_horiz_t *horiz; GtkWidget *hbox, *vbox; horiz = &(ctrl_usr->horiz); /* upper region - main display */ hbox = gtk_hbox_new_in_box(FALSE, 0, 0, ctrl_usr->horiz_info_win, FALSE, TRUE, 0); /* first column - slider labels */ vbox = gtk_vbox_new_in_box(TRUE, 0, 0, hbox, FALSE, TRUE, 3); gtk_label_new_in_box("Zoom", vbox, FALSE, TRUE, 0); gtk_label_new_in_box(" Pos ", vbox, FALSE, TRUE, 0); /* second column - sliders */ vbox = gtk_vbox_new_in_box(TRUE, 0, 0, hbox, TRUE, TRUE, 3); /* add a slider for zoom level */ horiz->zoom_adj = gtk_adjustment_new(1, 1, 9, 1, 1, 0); horiz->zoom_slider = gtk_hscale_new(GTK_ADJUSTMENT(horiz->zoom_adj)); gtk_scale_set_digits(GTK_SCALE(horiz->zoom_slider), 0); gtk_scale_set_draw_value(GTK_SCALE(horiz->zoom_slider), FALSE); gtk_box_pack_start(GTK_BOX(vbox), horiz->zoom_slider, FALSE, FALSE, 0); /* store the current value of the slider */ horiz->zoom_setting = GTK_ADJUSTMENT(horiz->zoom_adj)->value; /* connect the slider to a function that re-calcs horizontal scaling */ gtk_signal_connect(GTK_OBJECT(horiz->zoom_adj), "value_changed", GTK_SIGNAL_FUNC(zoom_changed), NULL); gtk_widget_show(horiz->zoom_slider); /* add a slider for position control */ horiz->pos_adj = gtk_adjustment_new(500, 0, 1000, 1, 1, 0); horiz->pos_slider = gtk_hscale_new(GTK_ADJUSTMENT(horiz->pos_adj)); gtk_scale_set_digits(GTK_SCALE(horiz->pos_slider), 0); gtk_scale_set_draw_value(GTK_SCALE(horiz->pos_slider), FALSE); gtk_box_pack_start(GTK_BOX(vbox), horiz->pos_slider, FALSE, FALSE, 0); /* store the current value of the slider */ horiz->pos_setting = GTK_ADJUSTMENT(horiz->pos_adj)->value / 1000.0; /* connect the slider to a function that re-calcs horizontal position */ gtk_signal_connect(GTK_OBJECT(horiz->pos_adj), "value_changed", GTK_SIGNAL_FUNC(pos_changed), NULL); gtk_widget_show(horiz->pos_slider); /* third column - scale display */ horiz->scale_label = gtk_label_new_in_box("----", hbox, FALSE, FALSE, 5); gtk_label_size_to_fit(GTK_LABEL(horiz->scale_label), "99.9 mSec\nper div"); /* fourth column - record length and sample rate button */ horiz->record_button = gtk_button_new_with_label("----- Samples\nat ---- KHz"); horiz->record_label = (GTK_BIN(horiz->record_button))->child; gtk_label_size_to_fit(GTK_LABEL(horiz->record_label), "99999 Samples\nat 99.9 MHz"); gtk_box_pack_end(GTK_BOX(hbox), horiz->record_button, FALSE, FALSE, 0); /* activate the acquire menu if button is clicked */ gtk_signal_connect(GTK_OBJECT(horiz->record_button), "clicked", GTK_SIGNAL_FUNC(acquire_popup), NULL); gtk_widget_show(horiz->record_button); /* lower region, graphical status display */ gtk_hseparator_new_in_box(ctrl_usr->horiz_info_win, 0); hbox = gtk_hbox_new_in_box(FALSE, 0, 0, ctrl_usr->horiz_info_win, FALSE, TRUE, 0); /* graphic horizontal display */ horiz->disp_area = gtk_drawing_area_new(); gtk_signal_connect(GTK_OBJECT(horiz->disp_area), "button_press_event", GTK_SIGNAL_FUNC(horiz_press), 0); gtk_signal_connect(GTK_OBJECT(horiz->disp_area), "button_release_event", GTK_SIGNAL_FUNC(horiz_release), 0); gtk_signal_connect(GTK_OBJECT(horiz->disp_area), "motion_notify_event", GTK_SIGNAL_FUNC(horiz_motion), 0); gtk_widget_set_events(GTK_WIDGET(horiz->disp_area), GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK); gtk_box_pack_start(GTK_BOX(hbox), horiz->disp_area, TRUE, TRUE, 0); gtk_widget_show(horiz->disp_area); /* label for state */ gtk_vseparator_new_in_box(hbox, 3); vbox = gtk_vbox_new_in_box(TRUE, 0, 0, hbox, FALSE, TRUE, 3); horiz->state_label = gtk_label_new_in_box(" ---- ", vbox, FALSE, FALSE, 3); gtk_label_size_to_fit(GTK_LABEL(horiz->state_label), " TRIGGERED ");}static void init_acquire_function(void){ hal_funct_t *funct; int next_thread; hal_thread_t *thread; hal_list_t *list_root, *list_entry; hal_funct_entry_t *fentry; scope_horiz_t *horiz; horiz = &(ctrl_usr->horiz); /* set watchdog to trip immediately once heartbeat funct is called */ ctrl_shm->watchdog = 10; /* is the realtime function present? */ funct = halpr_find_funct_by_name("scope.sample"); if (funct == NULL) { /* realtime function not present - watchdog timeout will open a dialog asking the user to insmod the module */ return; } if (funct->users == 0) { /* function not in use - watchdog timeout will open a dialog asking the user to select a thread */ return; } /* function is in use, find out which thread it is linked to */ rtapi_mutex_get(&(hal_data->mutex)); next_thread = hal_data->thread_list_ptr; while (next_thread != 0) { thread = SHMPTR(next_thread); list_root = &(thread->funct_list); list_entry = list_next(list_root); while (list_entry != list_root) { fentry = (hal_funct_entry_t *) list_entry; if (funct == SHMPTR(fentry->funct_ptr)) { /* found a match, update structure members */ horiz->thread_name = thread->name; horiz->thread_period_ns = thread->period; /* done with hal data */ rtapi_mutex_give(&(hal_data->mutex)); /* reset watchdog to give RT code some time */ ctrl_shm->watchdog = 1; return; } list_entry = list_next(list_entry); } next_thread = thread->next_ptr; } /* didn't find a linked thread - should never get here, but... */ rtapi_mutex_give(&(hal_data->mutex)); return;}void handle_watchdog_timeout(void){ hal_funct_t *funct; /* stop sampling */ ctrl_shm->state = IDLE; ctrl_shm->samples = 0; /* does realtime function exist? */ funct = halpr_find_funct_by_name("scope.sample"); if (funct == NULL) { /* function is not loaded */ dialog_realtime_not_loaded(); } else if (funct->users == 0) { /* function is loaded, but not in a thread */ dialog_realtime_not_linked(); } else if (ctrl_shm->watchdog != 0) { /* function is in a thread, but thread is not running */ dialog_realtime_not_running(); } else { /* everything should be fine... */ return; }}void refresh_state_info(void){ scope_horiz_t *horiz; static gchar *state_names[] = { "IDLE", "INIT", "PRE-TRIG", "TRIGGER?", "TRIGGERED", "DONE", "RESET" }; horiz = &(ctrl_usr->horiz); if (ctrl_shm->state > RESET) { ctrl_shm->state = IDLE; } gtk_label_set_text_if(horiz->state_label, state_names[ctrl_shm->state]); refresh_pos_disp();}void write_horiz_config(FILE *fp){ scope_horiz_t *horiz; horiz = &(ctrl_usr->horiz); fprintf(fp, "THREAD %s\n", horiz->thread_name); fprintf(fp, "MAXCHAN %d\n", ctrl_shm->sample_len); fprintf(fp, "HMULT %d\n", ctrl_shm->mult); fprintf(fp, "HZOOM %d\n", horiz->zoom_setting); fprintf(fp, "HPOS %e\n", horiz->pos_setting);}int set_sample_thread(char *name){ int rv; /* This is broken into two parts. When called directly while reading config file commands, both execute in order. however, when the dialog is running, it calls the two separately, setting the sample_thread_name during the dialog, and sctivating it when the dialog is closed. This may not be neccessary, but that is how it works right now. */ rv = 0; rv = set_sample_thread_name(name); if ( rv < 0 ) { return rv; } rv = activate_sample_thread(); return rv;}int set_rec_len(int setting){ int count, n; switch ( setting ) { case 1: case 2: case 4: case 8: case 16: /* acceptable value */ break; default: /* bad value */ return -1; } /* count enabled channels */ count = 0; for (n = 0; n < 16; n++) { if (ctrl_usr->vert.chan_enabled[n]) { count++; } } if (count > setting) { /* too many channels already enabled */ return -1; } ctrl_shm->sample_len = setting; ctrl_shm->rec_len = ctrl_shm->buf_len / ctrl_shm->sample_len; calc_horiz_scaling(); refresh_horiz_info(); return 0;}int set_horiz_mult(int setting){ scope_horiz_t *horiz; long period_ns, max_mult; /* validate setting */ if ( setting < 1 ) { return -1; } /* point to data */ horiz = &(ctrl_usr->horiz); /* get period, make sure is is valid */ period_ns = horiz->thread_period_ns; if ( period_ns < 10 ) { return -1; } /* calc max possible mult (to keep sample period <= 1 sec */ max_mult = 1000000000 / period_ns; if (max_mult > 1000) { max_mult = 1000; } /* make sure we aren't too high */ if ( setting > max_mult ) { setting = max_mult; } /* save new value */ ctrl_shm->mult = setting; /* refresh other stuff */ calc_horiz_scaling(); refresh_horiz_info(); return 0;}int set_horiz_zoom(int setting){ scope_horiz_t *horiz; GtkAdjustment *adj; /* range check setting */ if (( setting < 1 ) || ( setting > 9 )) { return -1; } /* point to data */ horiz = &(ctrl_usr->horiz); /* save new value */ horiz->zoom_setting = setting; /* set zoom slider based on new setting */ adj = GTK_ADJUSTMENT(horiz->zoom_adj); gtk_adjustment_set_value(adj, setting); /* refresh other stuff */ calc_horiz_scaling(); refresh_horiz_info(); request_display_refresh(1); return 0;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -