static char *id __attribute__ ((__unused__)) = "@(#) ganesh:/mnt/gersemi/src/Vibrating_Drum/drum.c;" "Friday March 23, 2007 (11:56);" "Mark Orchard-Webb;" "Compiled: "__DATE__ " (" __TIME__ ")" ; /* * Friday March 23, 2007 (11:56) * ============================= * * Fixed up ChiSq calculation * * Thursday September 14, 2006 (11:29) * =================================== * * Add \t to whitespace delimiters in output for Ting-Kuei Chou to * appease his strange appetite for using Excel * */ #include #include #include #include #include #include #include #include #include #include "get_frequency.h" #include "motor.h" #include "scan.h" #include "struct.h" #include "defines.h" #include "config.h" int simulate = 0; struct graph { int left, right, bottom, top, width, height; struct axis x, y; GtkWidget *da; GtkWidget *win; GdkPixmap *pixmap; }; struct bs { GtkWidget *combo; GList *list; }; enum BUTTONS { BUTTON_CALIB, BUTTON_FREQSCAN, BUTTON_POSITION, BUTTON_QUIT, BUTTON_CALIB_RECALIBRATE, BUTTON_CALIB_SAVE, BUTTON_CALIB_CLOSE, BUTTON_FREQSCAN_CLOSE, BUTTON_FREQSCAN_SAVE, BUTTON_SAMPLE_CLOSE, BUTTON_SAMPLE_SAVE, BUTTON_POSITION_CLOSE, BUTTON_CALIB_SAVE_OK, BUTTON_CALIB_SAVE_CANCEL, BUTTON_FREQSCAN_SAVE_OK, BUTTON_FREQSCAN_SAVE_CANCEL, BUTTON_SAMPLE_SAVE_OK, BUTTON_SAMPLE_SAVE_CANCEL, BUTTON_SURFACE, BUTTON_SAMPLE, BUTTON_LAST }; GtkWidget *buttons[BUTTON_LAST]; #define MODE_CALIBRATE 1 #define MODE_FREQSCAN 2 #define MODE_SCAN 4 #define MODE_SAMPLE 8 int array_size = 0; short *array = NULL; struct graph calib, freqscan, position, sample; char scratch[256]; int f_count; int combo_nosave = 0; int debug = 1; int position_known = 0; GTimer *waittimer; int mode = 0; GtkWidget *entry_destination, *entry_points; GdkFont *font = NULL; int current_dac, dac_min, dac_max; double calib_slope, calib_offset; double f_low, f_high; int f_dir, f_step, f_N; GtkWidget *menu_f_dir, *menu_forward, *menu_reverse, *option_menu; GtkWidget *win_calib_save, *win_freqscan_save, *win_main, *win_sample_save; GtkWidget *entry_calib_save, *entry_freqscan_save, *entry_sample_save; GtkWidget *label_f_range, *label_f_equation, *label_f_chisqr; GtkWidget *spin_adc_sin, *spin_adc_cos, *spin_adc_raw, *spin_f_step, *spin_density, *spin_f_N; GtkWidget *label_status; GtkWidget *circular; struct bs bs_f_current = {NULL, NULL}; struct bs bs_f_low = {NULL, NULL}; struct bs bs_f_high = {NULL, NULL}; struct bs bs_angular = {NULL, NULL}; struct bs bs_radial = {NULL, NULL}; struct bs bs_angular_delay = {NULL, NULL}; struct bs bs_radial_delay = {NULL, NULL}; struct bs bs_angular_step_size = {NULL, NULL}; struct bs bs_radial_step_size = {NULL, NULL}; struct bs bs_filename = {NULL, NULL}; struct bs bs_f_samp = {NULL, NULL}; struct bs bs_duration = {NULL, NULL}; struct bs bs_wall_radius = {NULL, NULL}; int calibrated = 0; struct calib_data *calib_data = NULL; struct freqscan_data *freqscan_data = NULL; int adc_sin, adc_cos, adc_raw; float duration = 1; int period = 1000; int npts = 1000; int label_printf (GtkWidget *label, char *fmt, ...) { va_list ap; va_start(ap, fmt); vsprintf (scratch, fmt, ap); va_end(ap); gtk_label_set_text (GTK_LABEL(label), scratch); return 0; } void set_dac (int dac) { if (!simulate) out_dac (0, dac); sprintf (scratch, "%g", dac*calib_slope+calib_offset); gtk_entry_set_text (GTK_ENTRY(GTK_COMBO(bs_f_current.combo)->entry), scratch); } int f_to_dac (double f) { return rint ((f - calib_offset) / calib_slope); } void set_frequency (double frequency) { int dac; dac = f_to_dac (frequency); set_dac (dac); } void set_lower_frequency (double f) { freqscan.x.low = f; dac_min = (f - calib_offset) / calib_slope; sprintf (scratch, "%g", f); gtk_entry_set_text (GTK_ENTRY(GTK_COMBO(bs_f_low.combo)->entry), scratch); } void set_upper_frequency (double f) { freqscan.x.high = f; dac_max = (f - calib_offset) / calib_slope; sprintf (scratch, "%g", f); gtk_entry_set_text (GTK_ENTRY(GTK_COMBO(bs_f_high.combo)->entry), scratch); } void set_f_samp (double f) { period = rint(1e6 / f); f = 1e6 / period; sprintf (scratch, "%g", f); gtk_entry_set_text (GTK_ENTRY(GTK_COMBO(bs_f_samp.combo)->entry), scratch); } void set_duration (double t) { npts = 1e6*t / period; t = 1e-6*npts*period; sample.x.high = t; sprintf (scratch, "%g", t); gtk_entry_set_text (GTK_ENTRY(GTK_COMBO(bs_duration.combo)->entry), scratch); } int calib_plot (int dac, double frequency, double error); int calc_step (struct axis *axis) { int i, j, k; char buf[32]; axis->step = pow (axis->base, floor (log (axis->high - axis->low) / log (axis->base) - 0.5)); i = (axis->high - axis->low) / axis->step; if (i > 20) axis->step *= 5; else if (i > 10) axis->step *= 2; axis->start = floor (axis->low / axis->step); axis->stop = ceil (axis->high / axis->step); axis->min = axis->start * axis->step; axis->max = axis->stop * axis->step; axis->delta = axis->max - axis->min; i = floor (log10 (fabs (axis->max))); j = floor (log10 (fabs (axis->min))); if (j > i) i = j; if (axis->base >= 1) { sprintf (buf, "%%%d.0f", i+1); } else { k = floor (log10 (axis->base)); sprintf (buf, "%%%d.%d", i+k+2, k); } axis->fmt = strdup (buf); return 0; } void configure_common (struct graph *graph, GdkEventConfigure *event) { int w, h; int lb, rb, w_str, asc, desc; GdkImage *src, *dest; int x, y; int i; char buf[32]; int w_max; if (graph->pixmap) gdk_pixmap_unref(graph->pixmap); w = graph->da->allocation.width; h = graph->da->allocation.height; graph->pixmap = gdk_pixmap_new(graph->da->window, w, h, -1); gdk_draw_rectangle (graph->pixmap, graph->da->style->white_gc, TRUE, 0, 0, w, h); gdk_string_extents (font, graph->x.label, &lb, &rb, &w_str, &asc, &desc); gdk_draw_text (graph->pixmap, font, graph->da->style->black_gc, (w-w_str) >> 1, h-desc-2, graph->x.label, strlen (graph->x.label)); graph->bottom = h - desc - 2 - asc - 1 - desc - asc; gdk_string_extents (font, graph->y.label, &lb, &rb, &w_str, &asc, &desc); gdk_draw_text (graph->pixmap, font, graph->da->style->black_gc, 0, asc+1, graph->y.label, strlen (graph->y.label)); src = gdk_image_get (graph->pixmap, 0, 0, w_str, asc + desc + 2); gdk_draw_rectangle (graph->pixmap, graph->da->style->white_gc, TRUE, 0, 0, src->width, src->height); dest = gdk_image_new (GDK_IMAGE_FASTEST, gdk_visual_get_best (), src->height, src->width); for (x = 0; x < src->width; x++) for (y = 0; y < src->height; y++) gdk_image_put_pixel (dest, y, src->width - x - 1, gdk_image_get_pixel (src, x, y)); gdk_draw_image (graph->pixmap, graph->da->style->white_gc, dest, 0, 0, 0, (h - dest->height) >> 1, dest->width, dest->height); gdk_image_destroy (src); gdk_image_destroy (dest); graph->left = dest->width; calc_step (&graph->y); w_max = 0; for (i = graph->y.start; i <= graph->y.stop; i++) { sprintf (buf, graph->y.fmt, i*graph->y.step); w_str = gdk_string_width (font, buf); if (w_str > w_max) w_max = w_str; } graph->top = asc; graph->height = graph->bottom - graph->top; graph->left += w_max; for (i = graph->y.start; i <= graph->y.stop; i++) { sprintf (buf, graph->y.fmt, i*graph->y.step); y = graph->bottom - (graph->height)*(i - graph->y.start)/(graph->y.stop - graph->y.start); gdk_draw_text (graph->pixmap, font, graph->da->style->black_gc, graph->left - gdk_string_width(font,buf), y, buf, strlen (buf)); gdk_draw_line (graph->pixmap, graph->da->style->black_gc, graph->left, y, graph->left+5, y); } calc_step (&graph->x); sprintf (buf, graph->x.fmt, graph->x.max); w_str = gdk_string_width (font, buf); graph->right = w - (w_str >> 1); graph->width = graph->right - graph->left; gdk_draw_line (graph->pixmap, graph->da->style->black_gc, graph->left, graph->bottom, graph->right, graph->bottom); gdk_draw_line (graph->pixmap, graph->da->style->black_gc, graph->left, graph->top, graph->left, graph->bottom); for (i = graph->x.start; i <= graph->x.stop; i++) { sprintf (buf, graph->x.fmt, i*graph->x.step); x = graph->left + (graph->width) * (i-graph->x.start)/(graph->x.stop - graph->x.start); gdk_draw_text (graph->pixmap, font, graph->da->style->black_gc, x-gdk_string_width(font,buf)/2, graph->bottom+asc+2, buf, strlen (buf)); gdk_draw_line (graph->pixmap, graph->da->style->black_gc, x, graph->bottom, x, graph->bottom-5); } if (event == NULL) gdk_draw_pixmap(graph->da->window, graph->da->style->fg_gc[GTK_WIDGET_STATE (graph->da)], graph->pixmap, 0, 0, 0, 0, w, h); } static gint configure_calib (GtkWidget *widget, GdkEventConfigure *event) { struct calib_data *ptr; configure_common (&calib, event); for (ptr = calib_data; ptr; ptr = ptr->next) calib_plot (ptr->dac, ptr->frequency, ptr->error); return TRUE; } static gint configure_freqscan (GtkWidget *widget, GdkEventConfigure *event) { // struct freqscan_data *ptr; configure_common (&freqscan, event); /* for (ptr = freqscan_data; ptr; ptr = ptr->next) calib_plot (ptr->dac, ptr->frequency, ptr->error); */ return TRUE; } static gint configure_position (GtkWidget *widget, GdkEventConfigure *event) { int w, h; struct graph *graph = &position; if (graph->pixmap) gdk_pixmap_unref(graph->pixmap); w = graph->da->allocation.width; h = graph->da->allocation.height; graph->pixmap = gdk_pixmap_new(graph->da->window, w, h, -1); gdk_draw_rectangle (graph->pixmap, graph->da->style->white_gc, TRUE, 0, 0, w, h); if (event == NULL) gdk_draw_pixmap(graph->da->window, graph->da->style->fg_gc[GTK_WIDGET_STATE (graph->da)], graph->pixmap, 0, 0, 0, 0, w, h); return TRUE; } int freqscan_plot (double frequency, double v_sin, double v_cos, double e_sin, double e_cos) { GdkRectangle update_rect; int x, y, e; double v; v = sqrt (v_sin*v_sin + v_cos*v_cos); x = freqscan.left + (freqscan.width)*(frequency - freqscan.x.min)/freqscan.x.delta; y = freqscan.bottom - (freqscan.height)*(v - freqscan.y.min)/(freqscan.y.delta); e = e_sin * (freqscan.height) / (freqscan.y.delta); gdk_draw_line (freqscan.pixmap, freqscan.da->style->black_gc, x, y-e, x, y+e); update_rect.x = x; update_rect.y = y-e; update_rect.width = 1; update_rect.height = 2*e+1; gtk_widget_draw (freqscan.da, &update_rect); return 0; } int calib_plot (int dac, double frequency, double error) { GdkRectangle update_rect; int x, y, e; x = calib.left + (calib.width)*(dac - calib.x.min)/calib.x.delta; y = calib.bottom - (calib.height)*(frequency - calib.y.min)/(calib.y.delta); e = error * (calib.height) / (calib.y.delta); gdk_draw_line (calib.pixmap, calib.da->style->black_gc, x, y-e, x, y+e); update_rect.x = x; update_rect.y = y-e; update_rect.width = 1; update_rect.height = 2*e+1; gtk_widget_draw (calib.da, &update_rect); return 0; } static int sample_plot (double t, double v, double e_v) { GdkRectangle update_rect; int x, y, e; x = sample.left + (sample.width)*(t - sample.x.min)/sample.x.delta; y = sample.bottom - (sample.height)*(v - sample.y.min)/(sample.y.delta); e = e_v * (sample.height) / (sample.y.delta); gdk_draw_line (sample.pixmap, sample.da->style->black_gc, x, y-e, x, y+e); update_rect.x = x; update_rect.y = y-e; update_rect.width = 1; update_rect.height = 2*e+1; gtk_widget_draw (sample.da, &update_rect); return 0; } static gint configure_sample (GtkWidget *widget, GdkEventConfigure *event) { int i; configure_common (&sample, event); for (i = 0; i < array_size; i++) sample_plot (1e-6*period*i, array[i]/204.7, 1/204.7); return TRUE; } static gint expose_sample( GtkWidget *widget, GdkEventExpose *event ) { gdk_draw_pixmap(widget->window, widget->style->fg_gc[GTK_WIDGET_STATE (widget)], sample.pixmap, event->area.x, event->area.y, event->area.x, event->area.y, event->area.width, event->area.height); return FALSE; } static gint expose_calib( GtkWidget *widget, GdkEventExpose *event ) { gdk_draw_pixmap(widget->window, widget->style->fg_gc[GTK_WIDGET_STATE (widget)], calib.pixmap, event->area.x, event->area.y, event->area.x, event->area.y, event->area.width, event->area.height); return FALSE; } static gint expose_freqscan( GtkWidget *widget, GdkEventExpose *event ) { gdk_draw_pixmap(widget->window, widget->style->fg_gc[GTK_WIDGET_STATE (widget)], freqscan.pixmap, event->area.x, event->area.y, event->area.x, event->area.y, event->area.width, event->area.height); return FALSE; } static gint expose_position( GtkWidget *widget, GdkEventExpose *event ) { gdk_draw_pixmap(widget->window, widget->style->fg_gc[GTK_WIDGET_STATE (widget)], position.pixmap, event->area.x, event->area.y, event->area.x, event->area.y, event->area.width, event->area.height); return FALSE; } void quit () { goto_position (0, 0); gtk_main_quit (); } int idle_calibrate (void) { double yt, st, y, s, w; struct calib_data *ptr; double w_sigma_x = 0, /* the running summations */ w_sigma_x2 = 0, /* all nicely zeroed */ w_sigma_y = 0, w_sigma_xy = 0, w_sigma = 0; double delta, inv_delta; /* the ugly denominator */ double a, sigma_a, b, sigma_b; /* the parameters */ int counter; if (current_dac < 2048) { out_dac (0, current_dac); do { if (get_frequency (&yt, &st) == E_COUNTER_TIMEOUT) { fprintf (stderr, "Warning: the period counter is timing out\n" "this may mean the counter input is not recieving pulses\n"); } get_frequency (&y, &s); } while (y != yt); ptr = malloc (sizeof (struct calib_data)); if (!ptr) die ("malloc failed"); ptr->next = calib_data; ptr->dac = current_dac; ptr->frequency = y; ptr->error = s; calib_data = ptr; calib_plot (current_dac, y, s); current_dac += 16; return 1; } calib.y.low = calib_data->frequency - calib_data->error; calib.y.high = calib_data->frequency + calib_data->error; counter = 0; for (ptr = calib_data; ptr; ptr = ptr->next) { counter++; /* increment line counter */ w = 1 / (ptr->error * ptr->error); w_sigma_x += w * ptr->dac; w_sigma_x2 += w * ptr->dac * ptr->dac; w_sigma_y += w * ptr->frequency; w_sigma_xy += w * ptr->dac * ptr->frequency; w_sigma += w; if (ptr->frequency < calib.y.low) calib.y.low = ptr->frequency; if (ptr->frequency > calib.y.high) calib.y.high = ptr->frequency; } delta = w_sigma * w_sigma_x2 - w_sigma_x * w_sigma_x; inv_delta = 1 / delta; a = inv_delta * (w_sigma_x2 * w_sigma_y - w_sigma_x * w_sigma_xy); sigma_a = inv_delta * w_sigma_x2; b = inv_delta * (w_sigma * w_sigma_xy - w_sigma_x * w_sigma_y); sigma_b = inv_delta * w_sigma; calib_slope = b; calib_offset = a; configure_calib (calib.da, NULL); sprintf (scratch, "f = %g * DAC + %g", b, a); gtk_label_set_text (GTK_LABEL(label_f_equation), scratch); sprintf (scratch, "%5.1f - %5.1f Hz", -2048*b+a, 2047*b+a); gtk_label_set_text (GTK_LABEL(label_f_range), scratch); set_lower_frequency (-2048*b+a); set_upper_frequency (2047*b+a); w_sigma_x = 0; for (ptr = calib_data; ptr; ptr = ptr->next) { w = (ptr->frequency - (calib_slope * ptr->dac + calib_offset)) / ptr->error; w_sigma_x += w*w; } sprintf (scratch, "%g", w_sigma_x / counter); gtk_label_set_text (GTK_LABEL(label_f_chisqr), scratch); calibrated = 1; mode = 0; if (!mode) label_printf (label_status, "Calibration complete"); return 1; } int idle_freqscan (void) { const double VPB = 1.0 / 204.7; struct freqscan_data *ptr; int i, v_sin, v_cos; double sum_sin, sumsq_sin, sum_cos, sumsq_cos; if (g_timer_elapsed (waittimer, NULL) < 1.0) return 1; if (((f_dir < 0) && (current_dac >= dac_min)) || ((f_dir > 0) && (current_dac <= dac_max))) { set_dac (current_dac); sum_sin = sumsq_sin = sum_cos = sumsq_cos = 0; for (i = 0; i < f_N; i++) { if (!simulate) { v_sin = in_adc (adc_sin); v_cos = in_adc (adc_cos); } sum_sin += v_sin; sum_cos += v_cos; sumsq_sin += v_sin * v_sin; sumsq_cos += v_cos * v_cos; } ptr = malloc (sizeof (struct freqscan_data)); if (!ptr) die ("malloc failed"); ptr->next = freqscan_data; ptr->dac = current_dac; ptr->v_sin = VPB * sum_sin / f_N; ptr->v_cos = VPB * sum_cos / f_N; ptr->e_sin = VPB * sqrt (sumsq_sin/f_N - ptr->v_sin*ptr->v_sin)/sqrt(f_N); ptr->e_cos = VPB * sqrt (sumsq_cos/f_N - ptr->v_cos*ptr->v_cos)/sqrt(f_N); freqscan_data = ptr; f_count++; freqscan_plot (calib_slope*current_dac + calib_offset, ptr->v_sin, ptr->v_cos, ptr->e_sin, ptr->e_cos); current_dac += f_dir * f_step; return 1; } mode &= ~MODE_FREQSCAN; if (!mode) label_printf (label_status, "Frequency scan complete"); return 1; } int idle_sample (void) { int i; write_am9513_command (DISARM_COUNTERS | COUNTER_5); #ifdef OLD mode_E (5, SOURCE_F1, GATING_HIGH_LEVEL_GATE_N, OUTPUT_TC_PULSE_HIGH, COUNT_DOWN); #else mode_D (5, SOURCE_F1, OUTPUT_TC_PULSE_HIGH, COUNT_DOWN); #endif write_counter_load (5, period); write_am9513_command (LOAD_AND_ARM_COUNTERS | COUNTER_5); printf ("sampling %d values from ADC%d\n", array_size, adc_raw); adc_enable_external_start (); for (i = 0; i < array_size; i++) array[i] = in_adc (adc_raw); adc_disable_external_start (); configure_sample (sample.da, NULL); label_printf (label_status, "Sampling complete"); mode = 0; return 1; } int idle_function (gpointer da) { int angular, radial; if (!simulate) { if (!position_known) { if (at_position ()) position_known = 1; angular = get_angular (); radial = get_radial (); sprintf (scratch, "%d", angular); gtk_entry_set_text (GTK_ENTRY(GTK_COMBO(bs_angular.combo)->entry), scratch); sprintf (scratch, "%d", radial); gtk_entry_set_text (GTK_ENTRY(GTK_COMBO(bs_radial.combo)->entry), scratch); } } if (!mode) return 1; if (mode & MODE_CALIBRATE) { idle_calibrate (); return 1; } if (mode & MODE_FREQSCAN) { idle_freqscan (); return 1; } if (mode & MODE_SCAN) { position_known = 0; idle_scan (); return 1; } if (mode & MODE_SAMPLE) { idle_sample (); return 1; } fprintf (stderr, "mode = %d ... illegal\n", mode); exit (1); } int check_f_dir (void) { GtkWidget *menu_item; menu_item = gtk_menu_get_active (GTK_MENU(menu_f_dir)); if (menu_item == menu_forward) f_dir = 1; else f_dir = -1; return f_dir; } void action_calib (void) { struct calib_data *ptr; gtk_label_set_text (GTK_LABEL(label_f_equation), "unknown"); gtk_label_set_text (GTK_LABEL(label_f_range), "unknown"); gtk_label_set_text (GTK_LABEL(label_f_chisqr), "unknown"); calibrated = 0; for (ptr = calib_data; ptr; ptr = calib_data) { calib_data = ptr->next; free (ptr); } current_dac = -2048; gtk_widget_show_all (calib.win); mode = 1; } void action_freqscan (void) { struct freqscan_data *ptr; for (ptr = freqscan_data; ptr; ptr = freqscan_data) { freqscan_data = ptr->next; free (ptr); } f_count = 0; combo_nosave = 1; gtk_signal_emit_by_name (GTK_OBJECT(GTK_COMBO(bs_f_low.combo)->entry), "activate"); gtk_signal_emit_by_name (GTK_OBJECT(GTK_COMBO(bs_f_high.combo)->entry), "activate"); combo_nosave = 0; f_step = 1 << (gtk_spin_button_get_value_as_int (GTK_SPIN_BUTTON(spin_f_step)) - 1); f_N = gtk_spin_button_get_value_as_int (GTK_SPIN_BUTTON(spin_f_N)); if (check_f_dir () > 0) current_dac = dac_min; else current_dac = dac_max; set_dac (current_dac); g_timer_start (waittimer); mode = 2; gtk_widget_show_all (freqscan.win); configure_freqscan (freqscan.da, NULL); } void action_calib_save_ok (void) { struct calib_data *ptr; FILE *out; char buf[256]; sprintf (buf, "%s.gnu", gtk_entry_get_text (GTK_ENTRY (entry_calib_save))); out = fopen (buf, "w"); if (!out) { perror ("Opening the file `%s' failed"); return; } sprintf (buf, "%s.data", gtk_entry_get_text (GTK_ENTRY (entry_calib_save))); fprintf (out, "set xlabel \"DAC value\"\n"); fprintf (out, "set ylabel \"Frequency (Hz)\"\n"); fprintf (out, "m = %g\n", calib_slope); fprintf (out, "b = %g\n", calib_offset); fprintf (out, "plot \"%s\" using 1:2:3 notitle with error, m*x+b notitle\n", buf); fclose (out); out = fopen (buf, "w"); if (!out) { perror ("Opening the file `%s' failed"); return; } for (ptr = calib_data; ptr; ptr = ptr->next) { fprintf (out, "%d \t%g \t%g\n", ptr->dac, ptr->frequency, ptr->error); } fclose (out); gtk_widget_hide_all (win_calib_save); } void action_freqscan_save_ok (void) { struct freqscan_data *ptr; FILE *out; char buf[256]; sprintf (buf, "%s.gnu", gtk_entry_get_text (GTK_ENTRY (entry_freqscan_save))); out = fopen (buf, "w"); if (!out) { perror ("Opening the file `%s' failed"); return; } sprintf (buf, "%s.data", gtk_entry_get_text (GTK_ENTRY (entry_freqscan_save))); fprintf (out, "set xlabel \"Frequency (Hz)\"\n"); fprintf (out, "set ylabel \"Amplitude (V)\"\n"); fprintf (out, "set y2label \"Phase (radians)\"\n"); fprintf (out, "plot \"%s\" using 1:2:3 notitle with error\n", buf); fclose (out); out = fopen (buf, "w"); if (!out) { perror ("Opening the file `%s' failed"); return; } for (ptr = freqscan_data; ptr; ptr = ptr->next) { double e_ph; #define x (ptr->v_cos) #define y (ptr->v_sin) #define sx (ptr->e_cos) #define sy (ptr->e_sin) #define dphdx (-y/(x*x*(1+y*y/(x*x)))) #define dphdy (1/(x*(1+y*y/(x*x)))) e_ph = sqrt(sx*sx*dphdx*dphdx + sy*sy*dphdy*dphdy); fprintf (out, "%g \t%.20g \t%.20g \t%.20g \t%.20g\n", calib_slope*ptr->dac+calib_offset, sqrt(ptr->v_sin*ptr->v_sin+ptr->v_cos*ptr->v_cos), sqrt(ptr->e_sin*ptr->e_sin+ptr->e_cos*ptr->e_cos), atan2(y,x), e_ph); } #undef x #undef y #undef sx #undef sy #undef dphdx #undef dphdy fclose (out); gtk_widget_hide_all (win_freqscan_save); } static void action_sample (void) { combo_nosave = 1; gtk_signal_emit_by_name (GTK_OBJECT(GTK_COMBO(bs_f_samp.combo)->entry), "activate"); gtk_signal_emit_by_name (GTK_OBJECT(GTK_COMBO(bs_duration.combo)->entry), "activate"); combo_nosave = 0; if (npts > array_size) { if (array) free (array); array = calloc (npts, sizeof (short)); if (!array) die ("Malloc failed!\n"); } array_size = npts; gtk_widget_show_all (sample.win); label_printf (label_status, "Sampling ..."); } static void action_sample_save_ok (void) { int i; FILE *out; char buf[256]; sprintf (buf, "%s.gnu", gtk_entry_get_text (GTK_ENTRY (entry_sample_save))); out = fopen (buf, "w"); if (!out) { perror ("Opening the file `%s' failed"); return; } sprintf (buf, "%s.data", gtk_entry_get_text (GTK_ENTRY (entry_sample_save))); fprintf (out, "set xlabel \"Time (s)\"\n"); fprintf (out, "set ylabel \"Sensor voltage (V)\"\n"); fprintf (out, "plot \"%s\" using 1:2:3 notitle with error\n", buf); fclose (out); out = fopen (buf, "w"); if (!out) { perror ("Opening the file `%s' failed"); return; } for (i = 0; i < array_size; i++) fprintf (out, "%g \t%g \t%g\n", 1e-6*i*period, array[i]/204.8, 1/204.8); fclose (out); gtk_widget_hide_all (win_sample_save); } void callback_button (GtkWidget *button, gpointer foo) { const char *str; GtkWidget *ptr; enum BUTTONS b; double value, angular_delay, radial_delay; set_configuration_int ("adc_port_ninety", adc_sin = gtk_spin_button_get_value_as_int (GTK_SPIN_BUTTON(spin_adc_sin))); set_configuration_int ("adc_port_zero", adc_cos = gtk_spin_button_get_value_as_int (GTK_SPIN_BUTTON(spin_adc_cos))); set_configuration_int ("adc_port_raw", adc_raw = gtk_spin_button_get_value_as_int (GTK_SPIN_BUTTON(spin_adc_raw))); set_configuration_int ("grid_density", gtk_spin_button_get_value_as_int (GTK_SPIN_BUTTON(spin_density))); sscanf (gtk_entry_get_text (GTK_ENTRY (GTK_COMBO(bs_angular_delay.combo)->entry)), "%lg", &angular_delay); set_configuration_double ("angular_delay", angular_delay, "us"); sscanf (gtk_entry_get_text (GTK_ENTRY (GTK_COMBO(bs_radial_delay.combo)->entry)), "%lg", &radial_delay); set_configuration_double ("radial_delay", radial_delay, "us"); sscanf (gtk_entry_get_text (GTK_ENTRY (GTK_COMBO(bs_wall_radius.combo)->entry)), "%lg", &value); set_configuration_double ("wall_radius", value, "mm"); if (!simulate) initialize_motors (angular_delay, radial_delay); for (b = 0; b < BUTTON_LAST; b++) if (buttons[b] == button) { switch (b) { case BUTTON_CALIB: case BUTTON_CALIB_RECALIBRATE: label_printf (label_status, "Calibrating"); return action_calib (); case BUTTON_FREQSCAN: label_printf (label_status, "Frequency scanning"); return action_freqscan (); case BUTTON_POSITION: gtk_widget_show_all (position.win); configure_position (position.da, NULL); return; case BUTTON_QUIT: return quit (); case BUTTON_CALIB_SAVE: gtk_widget_show_all (win_calib_save); return; case BUTTON_CALIB_CLOSE: mode = 0; gtk_widget_hide_all (calib.win); return; case BUTTON_FREQSCAN_SAVE: gtk_widget_show_all (win_freqscan_save); return; case BUTTON_SAMPLE_SAVE: gtk_widget_show_all (win_sample_save); return; case BUTTON_FREQSCAN_CLOSE: mode = 0; gtk_widget_hide_all (freqscan.win); return; case BUTTON_POSITION_CLOSE: mode = 0; gtk_widget_hide_all (position.win); return; case BUTTON_SAMPLE_CLOSE: mode = 0; gtk_widget_hide_all (sample.win); return; case BUTTON_CALIB_SAVE_OK: return action_calib_save_ok (); case BUTTON_FREQSCAN_SAVE_OK: return action_freqscan_save_ok (); case BUTTON_SAMPLE_SAVE_OK: return action_sample_save_ok (); case BUTTON_CALIB_SAVE_CANCEL: case BUTTON_FREQSCAN_SAVE_CANCEL: case BUTTON_SAMPLE_SAVE_CANCEL: for (ptr = button; ptr->parent; ptr = ptr->parent); /* this is probably a SIN */ gtk_widget_hide_all (ptr); return; case BUTTON_SURFACE: label_printf (label_status, "Surface scanning"); goto_position (0, 0); str = gtk_entry_get_text (GTK_ENTRY (GTK_COMBO(bs_filename.combo)->entry)); if (!str || !str[0]) { sprintf (scratch, "scan_%.0f-%.0f_Hz", freqscan.x.low, freqscan.x.high); gtk_entry_set_text (GTK_ENTRY(GTK_COMBO(bs_filename.combo)->entry), scratch); } action_freqscan (); f_count = 1 + floor ((dac_max - dac_min) / f_step); action_scan_setup (gtk_entry_get_text (GTK_ENTRY (GTK_COMBO(bs_filename.combo)->entry)), gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (circular))); mode = 4; return; case BUTTON_SAMPLE: mode = 8; return action_sample (); case BUTTON_LAST: break; } } } void combo_callback(GtkWidget *widget, struct bs *bs) { GList *ptr; double f; int i; int save_incoming = 0; static char incoming[256]; gpointer *data; strcpy (incoming, gtk_entry_get_text (GTK_ENTRY (GTK_COMBO(bs->combo)->entry))); if (debug) printf ("combo_callback () ... incoming = '%s'\n", incoming); if (bs == &bs_f_current) { if (!calibrated) return; if (sscanf (incoming, "%lf", &f) != 1) return; if (f < calib.y.low) return; if (f > calib.y.high) return; save_incoming++; set_frequency (f); } if (bs == &bs_f_low) { if (!calibrated) return; if (sscanf (incoming, "%lf", &f) != 1) return; if (f < calib.y.low) return; if (f > calib.y.high) return; save_incoming++; set_lower_frequency (f); } if (bs == &bs_f_high) { if (!calibrated) return; if (sscanf (incoming, "%lf", &f) != 1) return; if (f < calib.y.low) return; if (f > calib.y.high) return; save_incoming++; set_upper_frequency (f); } if (bs == &bs_angular) { if (!at_position ()) return; if (sscanf (incoming, "%d", &i) != 1) return; goto_position (i, get_radial ()); position_known = 0; } if (bs == &bs_radial) { if (!at_position ()) return; if (sscanf (incoming, "%d", &i) != 1) return; goto_position (get_angular (), i); position_known = 0; } if (bs == &bs_angular_delay) { if (sscanf (incoming, "%d", &i) != 1) return; set_angular_delay (i); } if (bs == &bs_radial_delay) { if (sscanf (incoming, "%d", &i) != 1) return; set_radial_delay (i); } if (bs == &bs_f_samp) { if (sscanf (incoming, "%lf", &f) != 1) return; set_f_samp (f); } if (bs == &bs_duration) { if (sscanf (incoming, "%lf", &f) != 1) return; set_duration (f); } if (!combo_nosave && save_incoming) { if ((data = g_list_nth_data (bs->list, 5))) bs->list = g_list_remove (bs->list, data); for (ptr = g_list_first (bs->list); ptr; ptr = g_list_next (ptr)) if (!strcmp (ptr->data, incoming)) break; if (!ptr) bs->list = g_list_prepend (bs->list, strdup (incoming)); gtk_combo_set_popdown_strings (GTK_COMBO(bs->combo), bs->list); } } gboolean callback_events (GtkWidget *Widget, GdkEventButton *event, gpointer user_data) { double lower, upper, tmp; double fx, fy, radius, theta; static gdouble x_press, y_press, x_release, y_release, dx, dy; switch (event->type) { case GDK_BUTTON_PRESS: x_press = event->x; y_press = event->y; return TRUE; case GDK_BUTTON_RELEASE: x_release = event->x; y_release = event->y; dx = x_release - x_press; dy = y_release - y_press; if (Widget == freqscan.da) { lower = (x_press - freqscan.left)* freqscan.x.delta / (freqscan.width) + freqscan.x.min; upper = (x_release - freqscan.left) * freqscan.x.delta / (freqscan.width) + freqscan.x.min; if (lower > upper) { tmp = upper; upper = lower; lower = tmp; } if (fabs (dx) < 5) { set_frequency (0.5*(lower+upper)); } else { set_lower_frequency (lower); set_upper_frequency (upper); } } else if (Widget == position.da) { fx = x_press / (double) Widget->allocation.width - 0.5; fy = y_press / (double) Widget->allocation.height - 0.5; radius = 2 * 7500 * sqrt (fx*fx + fy*fy); theta = atan2 (-fy, -fx); goto_position (rint(360*theta/M_PI), (int) rint(radius)); position_known = 0; } return TRUE; default: printf ("callback_events () ... odd! Received event %d\n", event->type); return FALSE; } return FALSE; } GtkWidget *make_button (const char *label, enum BUTTONS index) { if (index >= BUTTON_LAST) { die ("Bad news from the front, incoming wounded with index after BUTTON_LAST"); } buttons[index] = gtk_button_new_with_label (label); gtk_signal_connect (GTK_OBJECT (buttons[index]), "clicked", GTK_SIGNAL_FUNC (callback_button), NULL); return buttons[index]; } GtkWidget *make_int_spin (int value, int min, int max) { GtkAdjustment *spinner_adj; spinner_adj = (GtkAdjustment *) gtk_adjustment_new((gdouble) value, (gdouble) min, (gdouble) max, 1.0, 1.0, 1.0); return gtk_spin_button_new (spinner_adj, 1.0, 0); } GtkWidget *make_combo (struct bs *bs) { bs->combo = gtk_combo_new(); gtk_combo_disable_activate (GTK_COMBO(bs->combo)); gtk_signal_connect(GTK_OBJECT(GTK_COMBO(bs->combo)->entry), "activate", GTK_SIGNAL_FUNC(combo_callback), bs); return bs->combo; } int gui_calibrate (void) { GtkWidget *vbox, *buttons; calib.x.base = 2; calib.x.low = -2048; calib.x.high = 2047; calib.x.label = "DAC value"; calib.y.base = 10; calib.y.low = 80; calib.y.high = 250; calib.y.label = "Frequency (Hz)"; calib.win = gtk_window_new (GTK_WINDOW_TOPLEVEL); gtk_widget_set_name (calib.win, "Vibrating Drum - Frequency calibration"); vbox = gtk_vbox_new (FALSE, 0); gtk_container_add (GTK_CONTAINER (calib.win), vbox); gtk_signal_connect (GTK_OBJECT (calib.win), "destroy", GTK_SIGNAL_FUNC (quit), NULL); calib.da = gtk_drawing_area_new (); gtk_drawing_area_size (GTK_DRAWING_AREA (calib.da), 512, 512); gtk_box_pack_start (GTK_BOX (vbox), calib.da, TRUE, TRUE, 0); gtk_signal_connect (GTK_OBJECT (calib.da), "expose_event", (GtkSignalFunc) expose_calib, NULL); gtk_signal_connect (GTK_OBJECT(calib.da),"configure_event", (GtkSignalFunc) configure_calib, NULL); buttons = gtk_hbox_new (TRUE, 0); gtk_widget_show (buttons); gtk_box_pack_start (GTK_BOX (vbox), buttons, FALSE, FALSE, 0); gtk_box_pack_start (GTK_BOX (buttons), make_button ("Recalibrate", BUTTON_CALIB_RECALIBRATE), FALSE, FALSE, 0); gtk_box_pack_start (GTK_BOX (buttons), make_button ("Save", BUTTON_CALIB_SAVE), FALSE, FALSE, 0); gtk_box_pack_start (GTK_BOX (buttons), make_button ("Close", BUTTON_CALIB_CLOSE), FALSE, FALSE, 0); return 0; } int gui_freqscan (void) { GtkWidget *vbox, *buttons; freqscan.x.base = 10; freqscan.x.low = 130; freqscan.x.high = 140; freqscan.x.label = "Frequency (Hz)"; freqscan.y.base = 10; freqscan.y.low = 0; freqscan.y.high = 15; freqscan.y.label = "Amplitude (V)"; freqscan.win = gtk_window_new (GTK_WINDOW_TOPLEVEL); gtk_widget_set_name (freqscan.win, "Vibrating Drum - Frequency Scan"); vbox = gtk_vbox_new (FALSE, 0); gtk_container_add (GTK_CONTAINER (freqscan.win), vbox); gtk_signal_connect (GTK_OBJECT (freqscan.win), "destroy", GTK_SIGNAL_FUNC (quit), NULL); freqscan.da = gtk_drawing_area_new (); gtk_drawing_area_size (GTK_DRAWING_AREA (freqscan.da), 512, 512); gtk_box_pack_start (GTK_BOX (vbox), freqscan.da, TRUE, TRUE, 0); /* Signals used to handle backing pixmap */ gtk_signal_connect (GTK_OBJECT (freqscan.da), "expose_event", (GtkSignalFunc) expose_freqscan, NULL); gtk_signal_connect (GTK_OBJECT(freqscan.da),"configure_event", (GtkSignalFunc) configure_freqscan, NULL); gtk_signal_connect (GTK_OBJECT(freqscan.da),"button_press_event", (GtkSignalFunc) callback_events, NULL); gtk_signal_connect (GTK_OBJECT(freqscan.da),"button_release_event", (GtkSignalFunc) callback_events, NULL); gtk_widget_set_events (freqscan.da, GDK_EXPOSURE_MASK | GDK_LEAVE_NOTIFY_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK); buttons = gtk_hbox_new (TRUE, 0); gtk_widget_show (buttons); gtk_box_pack_start (GTK_BOX (vbox), buttons, FALSE, FALSE, 0); gtk_box_pack_start (GTK_BOX (buttons), make_button ("Save", BUTTON_FREQSCAN_SAVE), FALSE, FALSE, 0); gtk_box_pack_start (GTK_BOX (buttons), make_button ("Close", BUTTON_FREQSCAN_CLOSE), FALSE, FALSE, 0); return 0; } int gui_position (void) { GtkWidget *vbox, *buttons; position.win = gtk_window_new (GTK_WINDOW_TOPLEVEL); gtk_widget_set_name (position.win, "Vibrating Drum - Frequency Scan"); vbox = gtk_vbox_new (FALSE, 0); gtk_container_add (GTK_CONTAINER (position.win), vbox); gtk_signal_connect (GTK_OBJECT (position.win), "destroy", GTK_SIGNAL_FUNC (quit), NULL); position.da = gtk_drawing_area_new (); gtk_drawing_area_size (GTK_DRAWING_AREA (position.da), 256, 256); gtk_box_pack_start (GTK_BOX (vbox), position.da, TRUE, TRUE, 0); /* Signals used to handle backing pixmap */ gtk_signal_connect (GTK_OBJECT (position.da), "expose_event", (GtkSignalFunc) expose_position, NULL); gtk_signal_connect (GTK_OBJECT(position.da),"configure_event", (GtkSignalFunc) configure_position, NULL); gtk_signal_connect (GTK_OBJECT(position.da),"button_press_event", (GtkSignalFunc) callback_events, NULL); gtk_signal_connect (GTK_OBJECT(position.da),"button_release_event", (GtkSignalFunc) callback_events, NULL); gtk_widget_set_events (position.da, GDK_EXPOSURE_MASK | GDK_LEAVE_NOTIFY_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK); buttons = gtk_hbox_new (TRUE, 0); gtk_widget_show (buttons); gtk_box_pack_start (GTK_BOX (vbox), buttons, FALSE, FALSE, 0); gtk_box_pack_start (GTK_BOX (buttons), make_button ("Close", BUTTON_POSITION_CLOSE), FALSE, FALSE, 0); return 0; } void gui_calib_save (void) { GtkWidget *vbox, *hbox; win_calib_save = gtk_window_new (GTK_WINDOW_TOPLEVEL); gtk_widget_set_name (win_calib_save, "Vibrating Drum"); vbox = gtk_vbox_new (FALSE, 0); gtk_container_add (GTK_CONTAINER (win_calib_save), vbox); gtk_signal_connect (GTK_OBJECT (win_calib_save), "destroy", GTK_SIGNAL_FUNC (quit), NULL); gtk_box_pack_start (GTK_BOX (vbox), gtk_label_new ("Enter file stem below\n"), FALSE, FALSE, 0); gtk_box_pack_start (GTK_BOX (vbox), gtk_label_new ("Extensions `.data' and `.gnu' will be added\n"), FALSE, FALSE, 0); entry_calib_save = gtk_entry_new (); gtk_entry_set_text (GTK_ENTRY(entry_calib_save), "freq-calib"); gtk_box_pack_start (GTK_BOX (vbox), entry_calib_save, FALSE, FALSE, 0); hbox = gtk_hbox_new (TRUE, 0); gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 0); gtk_box_pack_start (GTK_BOX (hbox), make_button("Ok", BUTTON_CALIB_SAVE_OK), FALSE, FALSE, 0); gtk_box_pack_start (GTK_BOX (hbox), make_button("Cancel", BUTTON_CALIB_SAVE_CANCEL), FALSE, FALSE, 0); } void gui_freqscan_save (void) { GtkWidget *vbox, *hbox; win_freqscan_save = gtk_window_new (GTK_WINDOW_TOPLEVEL); gtk_widget_set_name (win_freqscan_save, "Vibrating Drum"); vbox = gtk_vbox_new (FALSE, 0); gtk_container_add (GTK_CONTAINER (win_freqscan_save), vbox); gtk_signal_connect (GTK_OBJECT (win_freqscan_save), "destroy", GTK_SIGNAL_FUNC (quit), NULL); gtk_box_pack_start (GTK_BOX (vbox), gtk_label_new ("Enter file stem below\n"), FALSE, FALSE, 0); gtk_box_pack_start (GTK_BOX (vbox), gtk_label_new ("Extensions `.data' and `.gnu' will be added\n"), FALSE, FALSE, 0); entry_freqscan_save = gtk_entry_new (); gtk_box_pack_start (GTK_BOX (vbox), entry_freqscan_save, FALSE, FALSE, 0); hbox = gtk_hbox_new (TRUE, 0); gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 0); gtk_box_pack_start (GTK_BOX (hbox), make_button("Ok", BUTTON_FREQSCAN_SAVE_OK), FALSE, FALSE, 0); gtk_box_pack_start (GTK_BOX (hbox), make_button("Cancel", BUTTON_FREQSCAN_SAVE_CANCEL), FALSE, FALSE, 0); } static int gui_sample (void) { GtkWidget *vbox, *buttons; sample.x.base = 10; sample.x.low = 0; sample.x.high = 1; sample.x.label = "Time (s)"; sample.y.base = 10; sample.y.low = 0; sample.y.high = 10; sample.y.label = "Sensor voltage (V)"; sample.win = gtk_window_new (GTK_WINDOW_TOPLEVEL); gtk_widget_set_name (sample.win, "Vibrating Drum - Sample"); vbox = gtk_vbox_new (FALSE, 0); gtk_container_add (GTK_CONTAINER (sample.win), vbox); gtk_signal_connect (GTK_OBJECT (sample.win), "destroy", GTK_SIGNAL_FUNC (quit), NULL); sample.da = gtk_drawing_area_new (); gtk_drawing_area_size (GTK_DRAWING_AREA (sample.da), 512, 512); gtk_box_pack_start (GTK_BOX (vbox), sample.da, TRUE, TRUE, 0); /* Signals used to handle backing pixmap */ gtk_signal_connect (GTK_OBJECT (sample.da), "expose_event", (GtkSignalFunc) expose_sample, NULL); gtk_signal_connect (GTK_OBJECT(sample.da),"configure_event", (GtkSignalFunc) configure_sample, NULL); gtk_signal_connect (GTK_OBJECT(sample.da),"button_press_event", (GtkSignalFunc) callback_events, NULL); gtk_signal_connect (GTK_OBJECT(sample.da),"button_release_event", (GtkSignalFunc) callback_events, NULL); gtk_widget_set_events (sample.da, GDK_EXPOSURE_MASK | GDK_LEAVE_NOTIFY_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK); buttons = gtk_hbox_new (TRUE, 0); gtk_widget_show (buttons); gtk_box_pack_start (GTK_BOX (vbox), buttons, FALSE, FALSE, 0); gtk_box_pack_start (GTK_BOX (buttons), make_button ("Save", BUTTON_SAMPLE_SAVE), FALSE, FALSE, 0); gtk_box_pack_start (GTK_BOX (buttons), make_button ("Close", BUTTON_SAMPLE_CLOSE), FALSE, FALSE, 0); return 0; } static void gui_sample_save (void) { GtkWidget *vbox, *hbox; win_sample_save = gtk_window_new (GTK_WINDOW_TOPLEVEL); gtk_widget_set_name (win_sample_save, "Vibrating Drum"); vbox = gtk_vbox_new (FALSE, 0); gtk_container_add (GTK_CONTAINER (win_sample_save), vbox); gtk_signal_connect (GTK_OBJECT (win_sample_save), "destroy", GTK_SIGNAL_FUNC (quit), NULL); gtk_box_pack_start (GTK_BOX (vbox), gtk_label_new ("Enter file stem below\n"), FALSE, FALSE, 0); gtk_box_pack_start (GTK_BOX (vbox), gtk_label_new ("Extensions `.data' and `.gnu' will be added\n"), FALSE, FALSE, 0); entry_sample_save = gtk_entry_new (); gtk_box_pack_start (GTK_BOX (vbox), entry_sample_save, FALSE, FALSE, 0); hbox = gtk_hbox_new (TRUE, 0); gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 0); gtk_box_pack_start (GTK_BOX (hbox), make_button("Ok", BUTTON_SAMPLE_SAVE_OK), FALSE, FALSE, 0); gtk_box_pack_start (GTK_BOX (hbox), make_button("Cancel", BUTTON_SAMPLE_SAVE_CANCEL), FALSE, FALSE, 0); } int gui_main (void) { double value; GtkWidget *vbox, *frame, *table, *notebook; win_main = gtk_window_new (GTK_WINDOW_TOPLEVEL); gtk_widget_set_name (win_main, "Vibrating Drum"); vbox = gtk_vbox_new (FALSE, 0); gtk_container_add (GTK_CONTAINER (win_main), vbox); gtk_signal_connect (GTK_OBJECT (win_main), "destroy", GTK_SIGNAL_FUNC (quit), NULL); notebook = gtk_notebook_new (); gtk_box_pack_start (GTK_BOX(vbox), notebook, FALSE, FALSE, 0); /* ============================================================================== */ frame = gtk_frame_new ("Configuration"); /* gtk_box_pack_start (GTK_BOX(vbox), frame, FALSE, FALSE, 0); */ gtk_notebook_append_page (GTK_NOTEBOOK(notebook), frame, gtk_label_new ("Hardware")); table = gtk_table_new (2, 9, FALSE); gtk_container_add (GTK_CONTAINER (frame), table); gtk_table_attach_defaults (GTK_TABLE(table), gtk_label_new ("Sine phase (y) ADC:"), 0, 1, 0, 1); gtk_table_attach_defaults (GTK_TABLE(table), spin_adc_sin = make_int_spin (1, 0, 4), 1, 2, 0, 1); gtk_table_attach_defaults (GTK_TABLE(table), gtk_label_new ("Cosine phase (x) ADC:"), 0, 1, 1, 2); gtk_table_attach_defaults (GTK_TABLE(table), spin_adc_cos = make_int_spin (2, 0, 4), 1, 2, 1, 2); gtk_table_attach_defaults (GTK_TABLE(table), gtk_label_new ("Raw ADC:"), 0, 1, 2, 3); gtk_table_attach_defaults (GTK_TABLE(table), spin_adc_raw = make_int_spin (3, 1, 4), 1, 2, 2, 3); gtk_table_attach_defaults (GTK_TABLE(table), gtk_label_new ("Angular delay (uS):"), 0, 1, 3, 4); gtk_table_attach_defaults (GTK_TABLE(table), make_combo (&bs_angular_delay), 1, 2, 3, 4); gtk_table_attach_defaults (GTK_TABLE(table), gtk_label_new ("Radial delay (uS):"), 0, 1, 4, 5); gtk_table_attach_defaults (GTK_TABLE(table), make_combo (&bs_radial_delay), 1, 2, 4, 5); gtk_table_attach_defaults (GTK_TABLE(table), gtk_label_new ("Angular step size (degrees):"), 0, 1, 5, 6); gtk_table_attach_defaults (GTK_TABLE(table), make_combo (&bs_angular_step_size), 1, 2, 5, 6); gtk_table_attach_defaults (GTK_TABLE(table), gtk_label_new ("Radial step size (um):"), 0, 1, 6, 7); gtk_table_attach_defaults (GTK_TABLE(table), make_combo (&bs_radial_step_size), 1, 2, 6, 7); gtk_table_attach_defaults (GTK_TABLE(table), gtk_label_new ("Wall radius (mm):"), 0, 1, 7, 8); gtk_table_attach_defaults (GTK_TABLE(table), make_combo (&bs_wall_radius), 1, 2, 7, 8); get_configuration_double ("angular_step_size", &value, "degrees"); sprintf (scratch, "%g", value); gtk_entry_set_text (GTK_ENTRY(GTK_COMBO(bs_angular_step_size.combo)->entry), scratch); get_configuration_double ("radial_step_size", &value, "um"); sprintf (scratch, "%g", value); gtk_entry_set_text (GTK_ENTRY(GTK_COMBO(bs_radial_step_size.combo)->entry), scratch); get_configuration_double ("angular_delay", &value, "us"); sprintf (scratch, "%g", value); gtk_entry_set_text (GTK_ENTRY(GTK_COMBO(bs_angular_delay.combo)->entry), scratch); get_configuration_double ("radial_delay", &value, "us"); sprintf (scratch, "%g", value); gtk_entry_set_text (GTK_ENTRY(GTK_COMBO(bs_radial_delay.combo)->entry), scratch); get_configuration_double ("wall_radius", &value, "mm"); sprintf (scratch, "%g", value); gtk_entry_set_text (GTK_ENTRY(GTK_COMBO(bs_wall_radius.combo)->entry), scratch); /* ============================================================================== */ frame = gtk_frame_new ("Frequency calibration"); /* gtk_box_pack_start (GTK_BOX(vbox), frame, FALSE, FALSE, 0); */ gtk_notebook_append_page (GTK_NOTEBOOK(notebook), frame, gtk_label_new ("Freq Calib")); table = gtk_table_new (2, 4, FALSE); gtk_container_add (GTK_CONTAINER (frame), table); gtk_table_attach_defaults (GTK_TABLE(table), gtk_label_new ("Frequency range:"), 0, 1, 0, 1); gtk_table_attach_defaults (GTK_TABLE(table), label_f_range = gtk_label_new ("unknown"), 1, 2, 0, 1); gtk_table_attach_defaults (GTK_TABLE(table), gtk_label_new ("Calibration equation:"), 0, 1, 1, 2); gtk_table_attach_defaults (GTK_TABLE(table), label_f_equation = gtk_label_new ("unknown"), 1, 2, 1, 2); gtk_table_attach_defaults (GTK_TABLE(table), gtk_label_new ("Reduced Chi-squared:"), 0, 1, 2, 3); gtk_table_attach_defaults (GTK_TABLE(table), label_f_chisqr = gtk_label_new ("unknown"), 1, 2, 2, 3); gtk_table_attach_defaults (GTK_TABLE(table), make_button("Calibrate", BUTTON_CALIB), 0, 2, 3, 4); /* ============================================================================== */ frame = gtk_frame_new ("Frequency Scanning"); /* gtk_box_pack_start (GTK_BOX(vbox), frame, FALSE, FALSE, 0); */ gtk_notebook_append_page (GTK_NOTEBOOK(notebook), frame, gtk_label_new ("Frequency")); table = gtk_table_new (2, 7, FALSE); gtk_container_add (GTK_CONTAINER (frame), table); gtk_table_attach_defaults (GTK_TABLE(table), gtk_label_new ("Lower frequency:"), 0, 1, 0, 1); gtk_table_attach_defaults (GTK_TABLE(table), make_combo(&bs_f_low), 1, 2, 0, 1); gtk_table_attach_defaults (GTK_TABLE(table), gtk_label_new ("Upper frequency:"), 0, 1, 1, 2); gtk_table_attach_defaults (GTK_TABLE(table), make_combo(&bs_f_high), 1, 2, 1, 2); gtk_table_attach_defaults (GTK_TABLE(table), gtk_label_new ("Step size (DAC bits):"), 0, 1, 2, 3); gtk_table_attach_defaults (GTK_TABLE(table), spin_f_step = make_int_spin (1, 1, 11), 1, 2, 2, 3); gtk_table_attach_defaults (GTK_TABLE(table), gtk_label_new ("Samples per point:"), 0, 1, 3, 4); gtk_table_attach_defaults (GTK_TABLE(table), spin_f_N = make_int_spin (1024, 1, 65536), 1, 2, 3, 4); menu_f_dir = gtk_menu_new (); menu_forward = gtk_menu_item_new_with_label ("forward"); menu_reverse = gtk_menu_item_new_with_label ("reverse"); gtk_menu_append (GTK_MENU(menu_f_dir), menu_forward); gtk_menu_append (GTK_MENU(menu_f_dir), menu_reverse); option_menu = gtk_option_menu_new (); gtk_option_menu_set_menu (GTK_OPTION_MENU(option_menu), menu_f_dir); gtk_option_menu_set_history (GTK_OPTION_MENU(option_menu), 0); gtk_table_attach_defaults (GTK_TABLE(table), gtk_label_new ("Scanning direction:"), 0, 1, 4, 5); gtk_table_attach_defaults (GTK_TABLE(table), option_menu, 1, 2, 4, 5); gtk_table_attach_defaults (GTK_TABLE(table), gtk_label_new ("Current frequency:"), 0, 1, 5, 6); gtk_table_attach_defaults (GTK_TABLE(table), make_combo(&bs_f_current), 1, 2, 5, 6); gtk_table_attach_defaults (GTK_TABLE(table), make_button ("Frequency Scan", BUTTON_FREQSCAN), 0, 2, 6, 7); /* ============================================================================== */ frame = gtk_frame_new ("Sensor Position"); gtk_box_pack_start (GTK_BOX(vbox), frame, FALSE, FALSE, 0); table = gtk_table_new (2, 3, FALSE); gtk_container_add (GTK_CONTAINER (frame), table); gtk_table_attach_defaults (GTK_TABLE(table), gtk_label_new ("Angular motor:"), 0, 1, 0, 1); gtk_table_attach_defaults (GTK_TABLE(table), make_combo(&bs_angular), 1, 2, 0, 1); gtk_table_attach_defaults (GTK_TABLE(table), gtk_label_new ("Radial motor:"), 0, 1, 1, 2); gtk_table_attach_defaults (GTK_TABLE(table), make_combo(&bs_radial), 1, 2, 1, 2); gtk_table_attach_defaults (GTK_TABLE(table), make_button("Position", BUTTON_POSITION), 0, 2, 2, 3); /* ============================================================================== */ frame = gtk_frame_new ("Surface Scan"); gtk_box_pack_start (GTK_BOX(vbox), frame, FALSE, FALSE, 0); table = gtk_table_new (4, 3, FALSE); gtk_container_add (GTK_CONTAINER (frame), table); gtk_table_attach_defaults (GTK_TABLE(table), gtk_label_new ("Grid density:"), 0, 1, 0, 1); gtk_table_attach_defaults (GTK_TABLE(table), spin_density = make_int_spin (3, 3, 25), 1, 2, 0, 1); gtk_table_attach_defaults (GTK_TABLE(table), circular = gtk_check_button_new_with_label ("Circular plate"), 2,3,0,1); gtk_table_attach_defaults (GTK_TABLE(table), gtk_label_new ("Output filename:"), 0, 1, 1, 2); gtk_table_attach_defaults (GTK_TABLE(table), make_combo(&bs_filename), 1, 3, 1, 2); gtk_table_attach_defaults (GTK_TABLE(table), make_button("Surface Scan", BUTTON_SURFACE), 0, 3, 2, 3); /* ============================================================================== */ frame = gtk_frame_new ("Sampling"); gtk_box_pack_start (GTK_BOX(vbox), frame, FALSE, FALSE, 0); table = gtk_table_new (2, 7, FALSE); gtk_container_add (GTK_CONTAINER (frame), table); gtk_table_attach_defaults (GTK_TABLE(table), gtk_label_new ("Sampling frequency (Hz):"), 0, 1, 0, 1); gtk_table_attach_defaults (GTK_TABLE(table), make_combo (&bs_f_samp), 1, 2, 0, 1); gtk_table_attach_defaults (GTK_TABLE(table), gtk_label_new ("Sample duration (s):"), 0, 1, 1, 2); gtk_table_attach_defaults (GTK_TABLE(table), make_combo (&bs_duration), 1, 2, 1, 2); sprintf (scratch, "%f", 1e6/period); gtk_entry_set_text (GTK_ENTRY(GTK_COMBO(bs_f_samp.combo)->entry), scratch); sprintf (scratch, "%f", 1e-6*period*npts); gtk_entry_set_text (GTK_ENTRY(GTK_COMBO(bs_duration.combo)->entry), scratch); gtk_table_attach_defaults (GTK_TABLE(table), make_button("Sample", BUTTON_SAMPLE), 0, 2, 2, 3); /* ============================================================================== */ frame = gtk_frame_new ("Status"); gtk_box_pack_start (GTK_BOX(vbox), frame, FALSE, FALSE, 0); table = gtk_table_new (2, 3, FALSE); gtk_container_add (GTK_CONTAINER (frame), table); gtk_table_attach_defaults (GTK_TABLE(table), label_status = gtk_label_new ("Idle"), 0, 1, 0, 1); gtk_table_attach_defaults (GTK_TABLE(table), make_button("Quit", BUTTON_QUIT), 0, 2, 1, 2); gtk_table_attach_defaults (GTK_TABLE(table), gtk_label_new ("Build: " __DATE__ " " __TIME__), 0, 2, 2, 3); /* ============================================================================== */ return 0; } int main( int argc, char *argv[] ) { fprintf (stderr, "Waking up the GUI ... this could take a moment!\n"); gtk_init (&argc, &argv); waittimer = g_timer_new (); read_configuration (CONFIG_FILE); print_configuration (stderr); if (!simulate) labmaster_initialize (); font = gdk_font_load ("10x20"); gui_main (); gui_calibrate (); gui_freqscan (); gui_position (); gui_sample (); gui_calib_save (); gui_freqscan_save (); gui_sample_save (); gtk_widget_show_all (win_main); gtk_idle_add (idle_function, NULL); mode = 0; gtk_main (); if (!simulate) labmaster_terminate (); print_configuration (stderr); write_configuration (CONFIG_FILE); return 0; }