#include "globals.h" #include "lcd.h" #include "i2c.h" #include "error_utils.h" #include "string_utils.h" #include "device-functions.h" #include "flash.h" #include "nicutils.h" #include "menus.h" #include "gpib.h" #include #include /* define common strings */ #define Press_Change_Message "Push CHANGE to continue." /* keypad hardware definitions */ #define Move_Button 1 /* mask for MOVE button */ #define Change_Button 2 /* mask for CHANGE button */ #define Mult10_Button 4 /* mask for x10 button */ #define Div10_Button 8 /* mask for /10 button */ #define Plus_Minus_Button 16 /* mask for +/- button */ #define Extra_Fine_Button 32 /* mask for extra-fine button */ #define MIN_ENCODER_CHANGE 3 #define MAX_MS_PER_STEP 2000 /* ----- HOW THE MENU SYSTEM WORKS -------------------------------------------------------------------------*/ /* To add a new menu: 1. add the menu name directly below */ /* 2. add the menu mode list choices directly below */ /* 3. if it is to be shown on the main menu, update Show_Main_Menu(void); */ /* 4. update Submenu_Display(void), which builds the submenu */ /* 5. update Submenu_Implement_Changes(void), to do the actual functions */ /* KEY SUBROUTINES: */ /* Show_Main_Menu(void); - displays the main menu */ /* Menu_Check_Buttons(void); - determines what to show based on button status */ /* (void); - clears any button presses */ /* Menu_Move_Pointer(int move_amount); - moves the pointer up and down the main menu */ /* Submenu_Display(void); - builds and displays submenus */ /* Submenu_Move_Pointer(void); - moves the pointer up and down submenu mode list */ /* Submenu_Implement_Changes(void); - once a mode in a submenu mode list has been chosen, */ /* this executes whatever is associated with that mode */ /* Submenu_Mult_Value(float mult_by); - this implements the x10, /10, +/- button functions */ /* Submenu_Service_Encoder(void); - this implements the adjust knob */ /* Nonstd_menu_RS232(void); - the RS232 menu is non-standard */ /* Nonstd_menu_default_rs232(void); - the default RS232 screen is non-standard */ /* Nonstd_menu_model_info(void); - the model info screen is non-standard */ /* MENU NAMES - these are menus with associated mode lists */ /* - Submenu1 are submenus linked from the main menu */ /* - Submenu2 are submenus linked from the other submenus */ /* MODE LIST CHOICES - if selected, these are fed into Submenu_Implement_Changes */ #define mode_freq_int 0 #define mode_freq_ext 100 #define mode_freq_man 200 #define mode_freq_hold 300 #define mode_delay_norm 400 #define mode_delay_dbl 500 #define mode_pw_norm 600 #define mode_pw_duty 700 #define mode_pw_inout 800 #define mode_pw_dc 900 #define mode_output_on 1000 #define mode_output_off 1100 #define mode_inv_no 1200 #define mode_inv_yes 1300 #define mode_gate_losync 1400 #define mode_gate_loasync 1500 #define mode_gpib_address 1600 #define mode_rs232_settings 1700 #define mode_model_info 1800 #define mode_exit_normal_submenu 1900 #define mode_zout_max 2000 #define mode_zout_min 2100 #define mode_save_0 2200 #define mode_save_1 2300 #define mode_save_2 2400 #define mode_save_3 2500 #define mode_load_0 2600 #define mode_load_1 2700 #define mode_load_2 2800 #define mode_load_3 2900 #define mode_load 3000 #define mode_save 3100 #define mode_change_rs232 3200 #define mode_default_rs232 3300 #define mode_1200 3400 #define mode_2400 3500 #define mode_4800 3600 #define mode_9600 3700 #define mode_7bits 3800 #define mode_8bits 3900 #define mode_par_none 4000 #define mode_par_even 4100 #define mode_par_odd 4200 #define mode_1bit 4300 #define mode_2bits 4400 #define mode_hand_hard 4500 #define mode_hand_off 4600 #define mode_echo_on 4700 #define mode_echo_off 4800 #define mode_amp_normal 4900 #define mode_amp_ea 5000 #define mode_gate_hisync 5100 #define mode_gate_hiasync 5200 #define mode_go_to_local 5500 #define mode_exit_rs232 5600 #define mode_logic_ttl 5700 #define mode_logic_ecl 5800 #define mode_os_normal 6300 #define mode_os_eo 6400 #define mode_amp_amplify 6500 #define mode_func_sin 6700 #define mode_func_tri 6800 #define mode_func_squ 6900 #define mode_func_pulse 7000 #define mode_func_amp 7100 #define mode_network 7200 #define mode_password 7300 #define mode_selfcal 7400 #define mode_19200 7500 #define mode_38400 7600 #define mode_57600 7700 #define mode_115200 7800 #define mode_pw_ew 7900 #define mode_ampl_fixed_point0 8000 #define mode_ampl_fixed_point1 8100 #define mode_ampl_fixed_point2 8200 #define mode_ampl_fixed_point3 8300 #define mode_ampl_fixed_point4 8400 #define mode_ampl_fixed_point5 8500 #define mode_ampl_fixed_point6 8600 #define mode_ampl_fixed_point7 8700 #define mode_ampl_fixed_point8 8800 #define mode_ampl_fixed_point9 8900 #define mode_freq_ext2 9000 #define mode_route1 9100 #define mode_route2 9200 #define mode_rise_time_min 9300 #define mode_rise_time_max 9400 #define mode_load_exit 9500 #define mode_save_exit 9600 #define mode_gpib_talklisten 9700 #define Submenu_maximum_entries 10 /* what parameter to adjust */ #define Show_frequency 0 #define Show_delay 100 #define Show_pw 200 #define Show_amplitude 300 #define Show_offset 400 #define Show_duty_cycle 500 #define Show_zout 600 #define Show_No_Number 700 #define Show_monitor 800 #define Show_Burst_Count 900 #define Show_Burst_Time 1000 #define Show_rise_time 1100 #define Show_gpib_address 1200 #define Show_soft_current_limit 1300 #define Show_route_primary 1500 #define Show_route_secondary 1600 #define Show_load_type 1700 #define Show_slew 1800 /* KEY MENU-JUGGLING VARIABLES - controlling what is actually shown on the display */ int menu_cursor_pos; int last_button_state; /* keeping track of button presses (software flip-flop) */ int last_encoder_adjust_error; unsigned long long encoder_last_adjust; unsigned long long encoder_timer_change[3]; int encoder_mult; int base_entry; /* for scrolling submenu mode lists */ /* KEY MAIN-MENU-RELATED VARIABLES */ /* - the main menu choices are indexed [0]-[Main_Menu_max_entry] */ /* - the actual item at each choice is stored in Main_Menu_Structure[] */ int Main_Menu_Structure[LCD_max_entries+1]; int Main_Menu_max_entry; /* KEY SUBMENU VARIABLES */ int Submenu_Structure[Submenu_maximum_entries]; /* this keeps track of the submenu mode-list */ int Submenu_Selected_Item; /* current submenu mode-list item selected */ int Submenu_Numeric_Parameter; /* when the adjust knob is varied, this is what gets changed */ /* for example, Show_No_Number */ /* Show_frequency */ /* Show_delay */ /* Show_pw */ /* Show_amplitude */ /* Show_offset */ /* Show_duty_cycle */ int Submenu_max_entry; /* highest mode-list menu item number */ float Submenu_Value; /* actual value of the shown parameter (like frequency) */ int Submenu_extra_fine; /* is the extra-fine mode on? */ static void update_remote_mode (); static int Menu_Is_Item_Visible(int LCD_entry); static void Menu_Move_Pointer(int move_amount); static void Display_Number_on_LCD(int Is_Item_Visible,int LCD_row,int LCD_col,char *start_string,int Show_What, int significant_digits, int width_of_column); static void Submenu_Display(int change_selection); static void Submenu_Move_Pointer(void); static int Submenu_Mult_Value(float mult_by); static void Submenu_Service_Encoder(int encoder_change); static void Nonstd_menu_default_rs232(void); static void Nonstd_menu_model_info(void); static int Submenu_Implement_Changes(void); static void Nonstd_menu_network(void); static void Read_Keypad(int *button_port_val, int *upper_encoder_val, int *lower_encoder_val); #define VXI_OR_GPIB_LOCK_ACTIVE ((globals.Remote.gpib_remote && globals.Remote.gpib_lock) || globals.Remote.vxi_panel_lock) static void update_remote_mode () { GPIB_check_remote_status (&globals.Remote.gpib_remote, &globals.Remote.gpib_lock); } static int Menu_Is_Item_Visible(int LCD_entry) { return ((LCD_entry/LCD_max_entries_per_page)==(menu_cursor_pos/LCD_max_entries_per_page)); } void Update_Main_Menu_If_Visible(void) { if ( (globals.MenuStatus.Type_Of_Menu == Main_Menu_On) && (globals.MenuStatus.Error_Screen == NO) && (globals.MenuStatus.Nonstd_Display == NO)) { Show_Main_Menu(); } } void Show_Main_Menu(void) { if (!globals.Sys.startup_complete) { return; } static GStaticMutex mutex = G_STATIC_MUTEX_INIT; g_static_mutex_lock (&mutex); // can be triggered simultaneously by local or remote users GString *menu_string = g_string_new (""); int LCD_entry, LCD_row, LCD_col; int sig_dig; /* number of significant digits to display */ int i; int chan; int show_item; int old_cursor_pos; // update remote/local info before starting screen writes, to avoid // odd-looking pauses update_remote_mode(); GString *raw_str = g_string_new (""); if (!VXI_OR_GPIB_LOCK_ACTIVE) { raw_str = g_string_append (raw_str, "LOCAL+"); } if (globals.Remote.gpib_remote) { raw_str = g_string_append (raw_str, "GPIB+"); } if (globals.Remote.terminal_connections > 0) { g_string_append_printf (raw_str, "%dTER+", globals.Remote.terminal_connections); } if (globals.Remote.vxi_connections > 0) { g_string_append_printf (raw_str, "%dVXI", globals.Remote.vxi_connections); } gchar *step1 = g_strdup (raw_str->str); g_string_free (raw_str, TRUE); // remove semicolon at end gchar *step2 = conditional_regex_replace (TRUE, step1, "\\+$", ""); g_free (step1); // shorten as required gchar *step3 = conditional_regex_replace (strlen(step2) > (LCD_col_width-1), step2, "LOCAL", "LO"); g_free (step2); // shorten as required gchar *step4 = conditional_regex_replace (strlen(step3) > (LCD_col_width-1), step3, "TER", "T"); g_free (step3); // shorten as required gchar *step5 = conditional_regex_replace (strlen(step4) > (LCD_col_width-1), step4, "GPIB", "GP"); g_free (step4); // shorten as required gchar *step6 = conditional_regex_replace (strlen(step5) > (LCD_col_width-1), step5, "VXI", "V"); g_free (step5); // finish gchar *ctrl_str = g_strdup (step6); g_free (step6); if ( (globals.MenuStatus.Type_Of_Menu != Main_Menu_On) || (globals.MenuStatus.Error_Screen == YES) || (globals.MenuStatus.Nonstd_Display == YES) ) { LCD_clear(); LCD_initialize(); } LCD_entry=-1; sig_dig = 4; Submenu_extra_fine=NO; globals.MenuStatus.Type_Of_Menu=Main_Menu_On; globals.MenuStatus.Error_Screen=NO; globals.MenuStatus.Nonstd_Display=NO; /* fill in unused cursor columns */ for (i=0; i<(menu_cursor_pos % LCD_max_entries_per_page); ++i) { LCD_row=i % LCD_rows; LCD_col=(i / LCD_rows) * LCD_col_width; LCD_write(LCD_row,LCD_col," "); } /* Don't overwrite the cursor. This would generate needless LCD accesses */ for (i=((menu_cursor_pos % LCD_max_entries_per_page)+1); i<15; ++i) { LCD_row=i % LCD_rows; LCD_col=(i / LCD_rows) * LCD_col_width; LCD_write(LCD_row,LCD_col," "); } old_cursor_pos=menu_cursor_pos; /*----- display freq, always (except func gen amplify mode) -----*/ for (chan=0; chan<(globals.Flash.ChanKey_frequency?globals.Flash.channels:1); ++chan) { if (globals.ChannelState[chan].func_mode!=amp_mode_on) { ++LCD_entry; Main_Menu_Structure[LCD_entry]=Submenu1_freq+chan; /* keep track of what is displayed */ LCD_row=LCD_entry % LCD_rows; /* find next available row */ LCD_col=((LCD_entry % LCD_max_entries_per_page) / LCD_rows) * LCD_col_width + 1; /* find next available column */ show_item=Show_No_Number; if (globals.ChannelState[chan].trigger_source==source_internal) { menu_string = g_string_append (menu_string, "INT"); show_item=Show_frequency+chan; } else if (globals.ChannelState[chan].trigger_source==source_external) { menu_string = g_string_append (menu_string, "EXT TRIG"); } else if (globals.ChannelState[chan].trigger_source==source_external2) { menu_string = g_string_append (menu_string, "EXT DBL"); } else if (globals.ChannelState[chan].trigger_source==source_manual) { menu_string = g_string_append (menu_string, "MAN TRIG"); } else if (globals.ChannelState[chan].trigger_source==source_hold) { menu_string = g_string_append (menu_string, "HOLD TRIG"); } else if (globals.ChannelState[chan].trigger_source==source_immediate) { menu_string = g_string_append (menu_string, "IMMED TRIG"); } if (globals.Flash.ChanKey_frequency) { g_string_append_printf (menu_string, "%d", chan+1); } if (globals.ChannelState[chan].trigger_source==source_internal) { menu_string = g_string_append (menu_string, ":"); } Display_Number_on_LCD(Menu_Is_Item_Visible(LCD_entry), LCD_row,LCD_col,menu_string->str,show_item,sig_dig,LCD_col_width-1); g_string_erase (menu_string, 0, -1); } } /*----- display shape, if appropriate -----*/ for (chan=0; chan<(globals.Flash.ChanKey_func_mode?globals.Flash.channels:1); ++chan) { if (globals.Flash.is_func_gen[chan]) { ++LCD_entry; Main_Menu_Structure[LCD_entry]=Submenu1_func+chan; /* keep track of what is displayed */ LCD_row=LCD_entry % LCD_rows; /* find next available row */ LCD_col=((LCD_entry % LCD_max_entries_per_page) / LCD_rows) * LCD_col_width + 1; /* find next available column */ show_item=Show_No_Number; if (globals.ChannelState[chan].func_mode==pulse_mode_on) { menu_string = g_string_append (menu_string, "SHAPE:PULSE"); } else if (globals.ChannelState[chan].func_mode==sin_mode_on) { menu_string = g_string_append (menu_string, "SHAPE:SINE"); } else if (globals.ChannelState[chan].func_mode==tri_mode_on) { menu_string = g_string_append (menu_string, "SHAPE:TRI"); } else if (globals.ChannelState[chan].func_mode==squ_mode_on) { menu_string = g_string_append (menu_string, "SHAPE:SQU"); } else if (globals.ChannelState[chan].func_mode==amp_mode_on) { menu_string = g_string_append (menu_string, "SHAPE:AMP"); } if (globals.Flash.ChanKey_func_mode) { g_string_append_printf (menu_string, "%d", chan+1); } Display_Number_on_LCD(Menu_Is_Item_Visible(LCD_entry), LCD_row,LCD_col,menu_string->str,show_item,sig_dig,LCD_col_width-1); g_string_erase (menu_string, 0, -1); } } /*----- display delay, except for pwin=pwout and ext amplify modes -----*/ for (chan=0; chan<(globals.Flash.ChanKey_delay?globals.Flash.channels:1); ++chan) if ( (globals.ChannelState[chan].amp_mode!=amp_mode_amplify) && (globals.ChannelState[chan].pw_ctrl_mode!=pw_in_out) && ((globals.ChannelState[chan].func_mode==pulse_mode_on) || (globals.ChannelState[chan].func_mode==dc_mode_on)) && (globals.Flash.max_delay[chan]>0.0) ) { ++LCD_entry; Main_Menu_Structure[LCD_entry]=Submenu1_delay+chan; LCD_row=LCD_entry % LCD_rows; LCD_col=((LCD_entry % LCD_max_entries_per_page) / LCD_rows) * LCD_col_width + 1; if (globals.ChannelState[chan].double_pulse==double_off) { menu_string = g_string_append (menu_string, "DLY"); } else { menu_string = g_string_append (menu_string, "DBL"); } if (globals.Flash.ChanKey_delay) { g_string_append_printf (menu_string, "%d", chan+1); } menu_string = g_string_append (menu_string, ":"); Display_Number_on_LCD(Menu_Is_Item_Visible(LCD_entry), LCD_row,LCD_col,menu_string->str,Show_delay+chan,sig_dig,LCD_col_width-1); g_string_erase (menu_string, 0, -1); } /*----- display pw, as appropriate -----*/ for (chan=0; chan<(globals.Flash.ChanKey_pw?globals.Flash.channels:1); ++chan) { if ( !globals.Flash.fixed_pw[chan] && (globals.ChannelState[chan].amp_mode!=amp_mode_amplify) && ((globals.ChannelState[chan].func_mode==pulse_mode_on) || (globals.ChannelState[chan].func_mode==dc_mode_on)) ) { ++LCD_entry; Main_Menu_Structure[LCD_entry]=Submenu1_pw+chan; LCD_row=LCD_entry % LCD_rows; LCD_col=((LCD_entry % LCD_max_entries_per_page) / LCD_rows) * LCD_col_width + 1; show_item=Show_No_Number; if (globals.ChannelState[chan].func_mode==pulse_mode_on) { switch (globals.ChannelState[chan].pw_ctrl_mode) { default: case pw_normal: if (globals.ChannelState[chan].hold_setting==hold_width) { show_item=Show_pw+chan; menu_string = g_string_append (menu_string, "PW"); if (globals.Flash.ChanKey_pw) { g_string_append_printf (menu_string, "%d", chan+1); } menu_string = g_string_append (menu_string, ":"); } else { show_item=Show_duty_cycle+chan; menu_string = g_string_append (menu_string, "DUTY"); if (globals.Flash.ChanKey_pw) { g_string_append_printf (menu_string, "%d", chan+1); } menu_string = g_string_append (menu_string, ":"); } break; case pw_in_out: menu_string = g_string_append (menu_string, "PW"); if (globals.Flash.ChanKey_pw) { g_string_append_printf (menu_string, "%d", chan+1); } menu_string = g_string_append (menu_string, ":IN=OUT"); break; case pw_ew_ext: menu_string = g_string_append (menu_string, "PW"); if (globals.Flash.ChanKey_pw) { g_string_append_printf (menu_string, "%d", chan+1); } menu_string = g_string_append (menu_string, ":EXT"); break; } } else { menu_string = g_string_append (menu_string, "PW"); if (globals.Flash.ChanKey_pw) { g_string_append_printf (menu_string, "%d", chan+1); } menu_string = g_string_append (menu_string, ": DC"); } Display_Number_on_LCD(Menu_Is_Item_Visible(LCD_entry), LCD_row,LCD_col,menu_string->str,show_item,sig_dig,LCD_col_width-1); g_string_erase (menu_string, 0, -1); } } /*----- display rise_time, as appropriate -----*/ for (chan=0; chan<(globals.Flash.ChanKey_rise_time?globals.Flash.channels:1); ++chan) { if ( !globals.Flash.fixed_rise_time[chan] && (globals.ChannelState[chan].amp_mode!=amp_mode_amplify) && ((globals.ChannelState[chan].func_mode==pulse_mode_on) || (globals.ChannelState[chan].func_mode==dc_mode_on)) ) { ++LCD_entry; Main_Menu_Structure[LCD_entry]=Submenu1_rise_time+chan; LCD_row=LCD_entry % LCD_rows; LCD_col=((LCD_entry % LCD_max_entries_per_page) / LCD_rows) * LCD_col_width + 1; show_item=Show_rise_time+chan; menu_string = g_string_append (menu_string, "TR"); if (globals.Flash.ChanKey_rise_time) { g_string_append_printf (menu_string, "%d", chan+1); } menu_string = g_string_append (menu_string, ":"); Display_Number_on_LCD(Menu_Is_Item_Visible(LCD_entry), LCD_row,LCD_col,menu_string->str,show_item,sig_dig,LCD_col_width-1); g_string_erase (menu_string, 0, -1); } } /*----- display amplitude, as appropriate -----*/ for (chan=0; chan<(globals.Flash.ChanKey_amplitude?globals.Flash.channels:1); ++chan) { if ((globals.Flash.voltage_enabled[chan] || globals.Flash.current_enabled[chan]) ) { ++LCD_entry; Main_Menu_Structure[LCD_entry]=Submenu1_amp+chan; LCD_row=LCD_entry % LCD_rows; LCD_col=((LCD_entry % LCD_max_entries_per_page) / LCD_rows) * LCD_col_width + 1; show_item=Show_No_Number; if (globals.ChannelState[chan].amp_mode==amp_mode_normal) { show_item=Show_amplitude+chan; menu_string = g_string_append (menu_string, "AMP"); if (globals.Flash.ChanKey_amplitude) { g_string_append_printf (menu_string, "%d", chan+1); } menu_string = g_string_append (menu_string, ":"); } else if (globals.ChannelState[chan].amp_mode==amp_mode_ea) { menu_string = g_string_append (menu_string, "AMP"); if (globals.Flash.ChanKey_amplitude) { g_string_append_printf (menu_string, "%d", chan+1); } menu_string = g_string_append (menu_string, ":EXT"); } else if (globals.ChannelState[chan].amp_mode==amp_mode_amplify) { menu_string = g_string_append (menu_string, "AMP"); if (globals.Flash.ChanKey_amplitude) { g_string_append_printf (menu_string, "%d", chan+1); } menu_string = g_string_append (menu_string, ":AMPLFY"); } Display_Number_on_LCD(Menu_Is_Item_Visible(LCD_entry), LCD_row,LCD_col,menu_string->str,show_item,sig_dig,LCD_col_width-1); g_string_erase (menu_string, 0, -1); } } /*----- display soft_current_limit, as appropriate -----*/ for (chan=0; chan<(globals.Flash.ChanKey_current_limit?globals.Flash.channels:1); ++chan) { if (globals.Flash.soft_current_limit_enabled[chan]) { ++LCD_entry; Main_Menu_Structure[LCD_entry]=Submenu1_soft_current_limit+chan; LCD_row=LCD_entry % LCD_rows; LCD_col=((LCD_entry % LCD_max_entries_per_page) / LCD_rows) * LCD_col_width + 1; show_item=Show_soft_current_limit+chan; menu_string = g_string_append (menu_string, "LIM"); if (globals.Flash.ChanKey_current_limit) { g_string_append_printf (menu_string, "%d", chan+1); } menu_string = g_string_append (menu_string, ":"); Display_Number_on_LCD(Menu_Is_Item_Visible(LCD_entry), LCD_row,LCD_col,menu_string->str,show_item,sig_dig,LCD_col_width-1); g_string_erase (menu_string, 0, -1); } } /*----- display current slew, as appropriate -----*/ for (chan=0; chan<(globals.Flash.ChanKey_slew?globals.Flash.channels:1); ++chan) { if ( globals.Flash.curr_slew[chan] ) { ++LCD_entry; Main_Menu_Structure[LCD_entry]=Submenu1_slew+chan; LCD_row=LCD_entry % LCD_rows; LCD_col=((LCD_entry % LCD_max_entries_per_page) / LCD_rows) * LCD_col_width + 1; show_item=Show_slew+chan; menu_string = g_string_append (menu_string, "SL"); if (globals.Flash.ChanKey_slew) { g_string_append_printf (menu_string, "%d", chan+1); } menu_string = g_string_append (menu_string, ":"); Display_Number_on_LCD(Menu_Is_Item_Visible(LCD_entry), LCD_row,LCD_col,menu_string->str,show_item,sig_dig,LCD_col_width-1); g_string_erase (menu_string, 0, -1); } } /*----- display burst count, as appropriate -----*/ for (chan=0; chan<(globals.Flash.ChanKey_Burst_Count?globals.Flash.channels:1); ++chan) { if (globals.Flash.max_burst_count[chan]>1) { ++LCD_entry; Main_Menu_Structure[LCD_entry]=Submenu1_burst_count+chan; LCD_row=LCD_entry % LCD_rows; LCD_col=((LCD_entry % LCD_max_entries_per_page) / LCD_rows) * LCD_col_width + 1; show_item=Show_Burst_Count+chan; menu_string = g_string_append (menu_string, "N"); if (globals.Flash.ChanKey_Burst_Count) { g_string_append_printf (menu_string, "%d", chan+1); } menu_string = g_string_append (menu_string, ":"); Display_Number_on_LCD(Menu_Is_Item_Visible(LCD_entry), LCD_row,LCD_col,menu_string->str,show_item,0,LCD_col_width-1); g_string_erase (menu_string, 0, -1); } } /*----- display burst timing, as appropriate -----*/ for (chan=0; chan<(globals.Flash.ChanKey_Burst_Time?globals.Flash.channels:1); ++chan) { if ((globals.Flash.max_burst_count[chan]>1) && !globals.Flash.burst_func[chan]) { ++LCD_entry; Main_Menu_Structure[LCD_entry]=Submenu1_burst_time+chan; LCD_row=LCD_entry % LCD_rows; LCD_col=((LCD_entry % LCD_max_entries_per_page) / LCD_rows) * LCD_col_width + 1; show_item=Show_Burst_Time+chan; menu_string = g_string_append (menu_string, "BUR"); if (globals.Flash.ChanKey_Burst_Time) { g_string_append_printf (menu_string, "%d", chan+1); } menu_string = g_string_append (menu_string, ":"); Display_Number_on_LCD(Menu_Is_Item_Visible(LCD_entry), LCD_row,LCD_col,menu_string->str,show_item,sig_dig,LCD_col_width-1); g_string_erase (menu_string, 0, -1); } } /*----- display offset, as appropriate -----*/ for (chan=0; chan<(globals.Flash.ChanKey_offset?globals.Flash.channels:1); ++chan) { if ((globals.Flash.voltage_offset_enabled[chan] || globals.Flash.current_offset_enabled[chan]) && (globals.ChannelState[chan].amp_mode!=amp_mode_amplify)) { ++LCD_entry; Main_Menu_Structure[LCD_entry]=Submenu1_offset+chan; LCD_row=LCD_entry % LCD_rows; LCD_col=((LCD_entry % LCD_max_entries_per_page) / LCD_rows) * LCD_col_width + 1; show_item=Show_No_Number; if (globals.ChannelState[chan].os_mode==os_mode_normal) { show_item=Show_offset+chan; menu_string = g_string_append (menu_string, "OS"); if (globals.Flash.ChanKey_offset) { g_string_append_printf (menu_string, "%d", chan+1); } menu_string = g_string_append (menu_string, ":"); } else { menu_string = g_string_append (menu_string, "OS"); if (globals.Flash.ChanKey_offset) { g_string_append_printf (menu_string, "%d", chan+1); } menu_string = g_string_append (menu_string, ":EXT"); } Display_Number_on_LCD(Menu_Is_Item_Visible(LCD_entry), LCD_row,LCD_col,menu_string->str,show_item,sig_dig,LCD_col_width-1); g_string_erase (menu_string, 0, -1); } } /*----- displayed monitor, as appropriate -----*/ for (chan=0; chan<(globals.Flash.ChanKey_Curr_Mon_value?globals.Flash.channels:1); ++chan) { if (globals.Flash.monitor_enabled[chan]) { ++LCD_entry; Main_Menu_Structure[LCD_entry]=Submenu1_mon+chan; LCD_row=LCD_entry % LCD_rows; LCD_col=((LCD_entry % LCD_max_entries_per_page) / LCD_rows) * LCD_col_width + 1; menu_string = g_string_append (menu_string, "Mon"); if (globals.Flash.ChanKey_Curr_Mon_value) { g_string_append_printf (menu_string, "%d", chan+1); } menu_string = g_string_append (menu_string, ":"); Display_Number_on_LCD(Menu_Is_Item_Visible(LCD_entry),LCD_row,LCD_col,menu_string->str,Show_monitor+chan,sig_dig,LCD_col_width-1); g_string_erase (menu_string, 0, -1); globals.ChannelState[chan].displayed_mon_val=globals.ChannelState[chan].Curr_Mon_value; } } /*----- display Zout, as appropriate -----*/ /* The Zout hardware and software is controlled by PW commands in the AVPP */ for (chan=0; chan<(globals.Flash.ChanKey_zout?globals.Flash.channels:1); ++chan) { if (globals.Flash.switchable_zout[chan] && !globals.Flash.volt_ctrl_pw[chan]) { ++LCD_entry; Main_Menu_Structure[LCD_entry]=Submenu1_zout+chan; LCD_row=LCD_entry % LCD_rows; LCD_col=((LCD_entry % LCD_max_entries_per_page) / LCD_rows) * LCD_col_width + 1; menu_string = g_string_append (menu_string, "Zout"); if (globals.Flash.ChanKey_zout) { g_string_append_printf (menu_string, "%d", chan+1); } menu_string = g_string_append (menu_string, ":"); if (globals.ChannelState[chan].zout==globals.Flash.zout_max[chan]) { g_string_append_printf (menu_string, "%d\xf4 ", globals.Flash.zout_max[chan]); } else { g_string_append_printf (menu_string, "%d\xf4 ", globals.Flash.zout_min[chan]); } Display_Number_on_LCD(Menu_Is_Item_Visible(LCD_entry), LCD_row,LCD_col,menu_string->str,Show_No_Number,sig_dig,LCD_col_width-1); g_string_erase (menu_string, 0, -1); } } /*----- display load type, as appropriate -----*/ for (chan=0; chan<(globals.Flash.ChanKey_load_type?globals.Flash.channels:1); ++chan) { if (globals.Flash.switchable_load[chan]) { ++LCD_entry; Main_Menu_Structure[LCD_entry]=Submenu1_loadtype+chan; LCD_row=LCD_entry % LCD_rows; LCD_col=((LCD_entry % LCD_max_entries_per_page) / LCD_rows) * LCD_col_width + 1; show_item=Show_load_type+chan; menu_string = g_string_append (menu_string, "Load"); if (globals.Flash.ChanKey_load_type) { g_string_append_printf (menu_string, "%d", chan+1); } menu_string = g_string_append (menu_string, ":"); Display_Number_on_LCD(Menu_Is_Item_Visible(LCD_entry), LCD_row,LCD_col,menu_string->str,show_item,sig_dig,LCD_col_width-1); g_string_erase (menu_string, 0, -1); } } /*----- display output state, if used -----*/ if (globals.Flash.on_off_used) for (chan=0; chan<(globals.Flash.ChanKey_output_state?globals.Flash.channels:1); ++chan) { ++LCD_entry; Main_Menu_Structure[LCD_entry]=Submenu1_output_state+chan; LCD_row=LCD_entry % LCD_rows; LCD_col=((LCD_entry % LCD_max_entries_per_page) / LCD_rows) * LCD_col_width + 1; menu_string = g_string_append (menu_string, "Output"); if (globals.Flash.ChanKey_output_state) { g_string_append_printf (menu_string, "%d", chan+1); } menu_string = g_string_append (menu_string, ":"); if (globals.ChannelState[chan].output_state==output_on) { menu_string = g_string_append (menu_string, "ON"); } else { menu_string = g_string_append (menu_string, "OFF"); } Display_Number_on_LCD(Menu_Is_Item_Visible(LCD_entry), LCD_row,LCD_col,menu_string->str,Show_No_Number,sig_dig,LCD_col_width-1); g_string_erase (menu_string, 0, -1); } /*----- display primary routing, as appropriate -----*/ for (chan=0; chan<(globals.Flash.ChanKey_route?globals.Flash.channels:1); ++chan) { if (globals.Flash.routing_required[chan] > 0) { ++LCD_entry; Main_Menu_Structure[LCD_entry]=Submenu1_route_primary+chan; LCD_row=LCD_entry % LCD_rows; LCD_col=((LCD_entry % LCD_max_entries_per_page) / LCD_rows) * LCD_col_width + 1; show_item=Show_route_primary+chan; if (globals.Flash.routing_required[chan] == 1) { menu_string = g_string_append (menu_string, "Route"); } else { menu_string = g_string_append (menu_string, "ANOD"); } if (globals.Flash.ChanKey_route) { g_string_append_printf (menu_string, "%d", chan+1); } menu_string = g_string_append (menu_string, ":"); Display_Number_on_LCD(Menu_Is_Item_Visible(LCD_entry), LCD_row,LCD_col,menu_string->str,show_item,0,LCD_col_width-1); g_string_erase (menu_string, 0, -1); } } /*----- display secondary routing, as appropriate -----*/ for (chan=0; chan<(globals.Flash.ChanKey_route?globals.Flash.channels:1); ++chan) { if (globals.Flash.routing_required[chan] == 2) { ++LCD_entry; Main_Menu_Structure[LCD_entry]=Submenu1_route_secondary+chan; LCD_row=LCD_entry % LCD_rows; LCD_col=((LCD_entry % LCD_max_entries_per_page) / LCD_rows) * LCD_col_width + 1; show_item=Show_route_secondary+chan; menu_string = g_string_append (menu_string, "CATH"); if (globals.Flash.ChanKey_route) { g_string_append_printf (menu_string, "%d", chan+1); } menu_string = g_string_append (menu_string, ":"); Display_Number_on_LCD(Menu_Is_Item_Visible(LCD_entry), LCD_row,LCD_col,menu_string->str,show_item,0,LCD_col_width-1); g_string_erase (menu_string, 0, -1); } } /*----- display inverted state, if allowed -----*/ for (chan=0; chan<(globals.Flash.ChanKey_inverted?globals.Flash.channels:1); ++chan) { if (globals.Flash.invert_allowed[chan]) { ++LCD_entry; Main_Menu_Structure[LCD_entry]=Submenu1_invert+chan; LCD_row=LCD_entry % LCD_rows; LCD_col=((LCD_entry % LCD_max_entries_per_page) / LCD_rows) * LCD_col_width + 1; menu_string = g_string_append (menu_string, "INVERT"); if (globals.Flash.ChanKey_inverted) { g_string_append_printf (menu_string, "%d", chan+1); } menu_string = g_string_append (menu_string, ":"); if (globals.ChannelState[chan].inverted==NO) { menu_string = g_string_append (menu_string, "NO"); } else { menu_string = g_string_append (menu_string, "YES"); } Display_Number_on_LCD(Menu_Is_Item_Visible(LCD_entry), LCD_row,LCD_col,menu_string->str,Show_No_Number,sig_dig,LCD_col_width-1); g_string_erase (menu_string, 0, -1); } } /*----- display logic level type, as appropriate -----*/ if (globals.Flash.logic_level_enabled) { for (chan=0; chan<(globals.Flash.ChanKey_logic_level?globals.Flash.channels:1); ++chan) { ++LCD_entry; Main_Menu_Structure[LCD_entry]=Submenu1_logic_level+chan; LCD_row=LCD_entry % LCD_rows; LCD_col=((LCD_entry % LCD_max_entries_per_page) / LCD_rows) * LCD_col_width + 1; menu_string = g_string_append (menu_string, "Logic"); if (globals.Flash.ChanKey_logic_level) { g_string_append_printf (menu_string, "%d", chan+1); } menu_string = g_string_append (menu_string, ":"); if (globals.ChannelState[chan].logic_level==logic_ttl) { menu_string = g_string_append (menu_string, "TTL"); } else { menu_string = g_string_append (menu_string, "ECL"); } Display_Number_on_LCD(Menu_Is_Item_Visible(LCD_entry), LCD_row,LCD_col,menu_string->str,Show_No_Number,sig_dig,LCD_col_width-1); g_string_erase (menu_string, 0, -1); } } /*----- display gate type, except on func gens -----*/ for (chan=0; chan<((globals.Flash.ChanKey_gate_level|globals.Flash.ChanKey_gate_type)?globals.Flash.channels:1); ++chan) if (!globals.Flash.is_func_gen[chan]) { { ++LCD_entry; Main_Menu_Structure[LCD_entry]=Submenu1_gate+chan; LCD_row=LCD_entry % LCD_rows; LCD_col=((LCD_entry % LCD_max_entries_per_page) / LCD_rows) * LCD_col_width + 1; menu_string = g_string_append (menu_string, "GAT"); if (globals.Flash.ChanKey_gate_type || globals.Flash.ChanKey_gate_level) { g_string_append_printf (menu_string, "%d", chan+1); } menu_string = g_string_append (menu_string, ":"); if (globals.ChannelState[chan].gate_type==gate_sync && globals.ChannelState[chan].gate_level==gate_low) { menu_string = g_string_append (menu_string, "SYN,LO"); } else if (globals.ChannelState[chan].gate_type==gate_sync && globals.ChannelState[chan].gate_level==gate_high) { menu_string = g_string_append (menu_string, "SYN,HI"); } else if (globals.ChannelState[chan].gate_type==gate_async && globals.ChannelState[chan].gate_level==gate_low) { menu_string = g_string_append (menu_string, "ASY,LO"); } else { menu_string = g_string_append (menu_string, "ASY,HI"); } Display_Number_on_LCD(Menu_Is_Item_Visible(LCD_entry), LCD_row,LCD_col,menu_string->str,Show_No_Number, sig_dig,LCD_col_width-1); g_string_erase (menu_string, 0, -1); } } /*----- display remote/local, always -----*/ ++LCD_entry; Main_Menu_Structure[LCD_entry]=Submenu1_rem_loc; LCD_row=LCD_entry % LCD_rows; LCD_col=((LCD_entry % LCD_max_entries_per_page) / LCD_rows) * LCD_col_width + 1; if (Menu_Is_Item_Visible(LCD_entry)) { LCD_write_padded_spaces(LCD_row,LCD_col,ctrl_str,LCD_col_width-1); } g_free (ctrl_str); /*----- display memory, always -----*/ ++LCD_entry; Main_Menu_Structure[LCD_entry]=Submenu1_memory; LCD_row=LCD_entry % LCD_rows; LCD_col=((LCD_entry % LCD_max_entries_per_page) / LCD_rows) * LCD_col_width + 1; if (Menu_Is_Item_Visible(LCD_entry)) { LCD_write_padded_spaces(LCD_row,LCD_col,"Memory menu",LCD_col_width-1); } /*----- display setup, always -----*/ ++LCD_entry; Main_Menu_Structure[LCD_entry]=Submenu1_setup; LCD_row=LCD_entry % LCD_rows; LCD_col=((LCD_entry % LCD_max_entries_per_page) / LCD_rows) * LCD_col_width + 1; if (Menu_Is_Item_Visible(LCD_entry)) { LCD_write_padded_spaces(LCD_row,LCD_col,"Setup menu",LCD_col_width-1); } /*----- display the pointer -----*/ Menu_Move_Pointer(0); /* display pointer, but don't move it */ if (old_cursor_pos!=menu_cursor_pos) { LCD_row=(old_cursor_pos % LCD_max_entries_per_page) % LCD_rows; LCD_col=((old_cursor_pos % LCD_max_entries_per_page) / LCD_rows) * LCD_col_width; LCD_write(LCD_row,LCD_col," "); } /*----- finish up -----*/ Main_Menu_max_entry=LCD_entry; /* record number of menu items */ if (Main_Menu_max_entry>=LCD_max_entries_per_page) { LCD_write(3,39,">"); } else { LCD_write(3,39," "); } if ((Main_Menu_max_entry/LCD_max_entries_per_page)==(menu_cursor_pos/LCD_max_entries_per_page)) for (i=(Main_Menu_max_entry%LCD_max_entries_per_page)+ 1; i<12; ++i) { LCD_row=i % LCD_rows; LCD_col=(i / LCD_rows) * LCD_col_width + 1; LCD_write_padded_spaces(LCD_row,LCD_col,"",LCD_col_width-1); } g_string_free (menu_string, TRUE); g_static_mutex_unlock (&mutex); } static void Menu_Move_Pointer(int move_amount) { int LCD_row,LCD_col; int old_page,new_page; /* find the menu index where the selected item is */ for (menu_cursor_pos=0; ((globals.MenuStatus.Selected_Submenu!=Main_Menu_Structure[menu_cursor_pos]) && (menu_cursor_pos < LCD_max_entries)); ++menu_cursor_pos) { ; } if (menu_cursor_pos==LCD_max_entries) { menu_cursor_pos=0; } /* this occurs when submenus not listed on the main menu are selected, like load/save */ old_page=menu_cursor_pos / LCD_max_entries_per_page; /* use the menu index to find where the cursor is currently pointing, and erase it */ if (move_amount) { LCD_row=menu_cursor_pos % LCD_rows; LCD_col=((menu_cursor_pos % LCD_max_entries_per_page) / LCD_rows) * LCD_col_width; LCD_write(LCD_row,LCD_col," "); /* erase pointer */ /* move the pointer, with wrap-around to zero */ menu_cursor_pos += move_amount; if (menu_cursor_pos > Main_Menu_max_entry) { menu_cursor_pos=0; } if (menu_cursor_pos < 0) { menu_cursor_pos=Main_Menu_max_entry; } } /* update the selected menu item */ globals.MenuStatus.Selected_Submenu=Main_Menu_Structure[menu_cursor_pos]; /* draw the pointer at the new location */ LCD_row=menu_cursor_pos % LCD_rows; LCD_col=((menu_cursor_pos % LCD_max_entries_per_page) / LCD_rows) * LCD_col_width; LCD_write(LCD_row,LCD_col,"~"); /* "~" equals "->" on LCD */ new_page=menu_cursor_pos / LCD_max_entries_per_page; if (new_page!=old_page) { Show_Main_Menu(); } } static void Display_Number_on_LCD(int Is_Item_Visible,int LCD_row,int LCD_col,char *start_string,int Show_What, int significant_digits, int width_of_column) { if (!Is_Item_Visible) { return; } gchar *LCD_string = NULL; gchar *units = NULL; int channel; channel=Show_What%100; if (Show_What!=Show_No_Number) { int show_plus_sign; switch (Show_What-channel) { case Show_frequency: Submenu_Value=globals.ChannelState[channel].frequency; units = g_strdup("Hz"); show_plus_sign=NO; break; case Show_delay: Submenu_Value=globals.ChannelState[channel].delay; units = g_strdup("s"); if (globals.Flash.min_delay[channel] > 0.0) { show_plus_sign=NO; } else { show_plus_sign=YES; } break; case Show_pw: Submenu_Value=globals.ChannelState[channel].pw; units = g_strdup("s"); show_plus_sign=NO; break; case Show_amplitude: if (globals.Flash.ignore_ampl_polarity[channel]) { show_plus_sign=NO; Submenu_Value=fabs(globals.ChannelState[channel].amplitude); } else { show_plus_sign=YES; Submenu_Value=globals.ChannelState[channel].amplitude; } if (globals.Flash.voltage_enabled[channel]) { units = g_strdup("V"); } else { units = g_strdup("A"); } break; case Show_offset: Submenu_Value=globals.ChannelState[channel].offset; show_plus_sign=YES; if (globals.Flash.voltage_offset_enabled[channel]) { units = g_strdup("V"); } else { units = g_strdup("A"); } break; case Show_monitor: Submenu_Value=globals.ChannelState[channel].Curr_Mon_value; show_plus_sign=YES; if (globals.ChannelState[channel].pw0) { int fixed_count; Submenu_max_entry = number_of_fixed_ampl_points(channel) - 1; for (fixed_count = 0; fixed_count < number_of_fixed_ampl_points(channel); ++fixed_count) { Submenu_Structure[fixed_count] = mode_ampl_fixed_point0 + (fixed_count*100); } } else if (globals.ChannelState[channel].amp_mode==amp_mode_normal) { Submenu_Numeric_Parameter=Show_amplitude+channel; } if ((globals.Flash.ea_enabled[channel]) || (globals.Flash.ext_amplify_enabled[channel])) { Submenu_max_entry=0; Submenu_Structure[0]=mode_amp_normal; } if (globals.Flash.ea_enabled[channel]) { ++Submenu_max_entry; Submenu_Structure[Submenu_max_entry]=mode_amp_ea; } if (globals.Flash.ext_amplify_enabled[channel]) { ++Submenu_max_entry; Submenu_Structure[Submenu_max_entry]=mode_amp_amplify; } if (globals.Flash.ignore_ampl_polarity[channel]) { LCD_write(2,2,"(+/- set by AMP1)"); } break; case Submenu1_burst_count: title = title_with_channel("Pulses per burst",globals.Flash.ChanKey_Burst_Count,channel); Submenu_Numeric_Parameter=Show_Burst_Count+channel; break; case Submenu1_burst_time: title = title_with_channel("Burst Spacing",globals.Flash.ChanKey_Burst_Time,channel); Submenu_Numeric_Parameter=Show_Burst_Time+channel; break; case Submenu1_rise_time: title = title_with_channel("Rise time",globals.Flash.ChanKey_rise_time,channel); if (globals.Flash.rise_time_min_max_only[channel]) { Submenu_max_entry=1; Submenu_Structure[0]=mode_rise_time_min; Submenu_Structure[1]=mode_rise_time_max; } else { Submenu_Numeric_Parameter=Show_rise_time+channel; } break; case Submenu1_slew: title = title_with_channel("Slew Rate",globals.Flash.ChanKey_slew,channel); Submenu_Numeric_Parameter=Show_slew+channel; break; case Submenu1_soft_current_limit: title = title_with_channel("Current Limit",globals.Flash.ChanKey_current_limit,channel); Submenu_Numeric_Parameter=Show_soft_current_limit+channel; break; case Submenu1_zout: title = title_with_channel("Output Impedance",globals.Flash.ChanKey_zout,channel); Submenu_max_entry=1; Submenu_Structure[0]=mode_zout_min; Submenu_Structure[1]=mode_zout_max; break; case Submenu1_loadtype: title = title_with_channel("Load Impedance",globals.Flash.ChanKey_load_type,channel); Submenu_Numeric_Parameter=Show_load_type+channel; break; case Submenu1_offset: title = title_with_channel("Offset",globals.Flash.ChanKey_offset,channel); if (globals.ChannelState[channel].os_mode==os_mode_normal) { Submenu_Numeric_Parameter=Show_offset+channel; } if (globals.Flash.eo_enabled[channel]) { Submenu_max_entry=1; Submenu_Structure[0]=mode_os_normal; Submenu_Structure[1]=mode_os_eo; } break; case Submenu1_mon: title = title_with_channel("Monitor",globals.Flash.ChanKey_Curr_Mon_value,channel); if (globals.ChannelState[channel].pw=0) { GPtrArray *gparray = g_ptr_array_new (); int current_operating_mode = 0; LCD_write(0,19,"Mode:"); for (i=0; i<=Submenu_max_entry; ++i) { gchar *mode_name; gchar *fixed_ampl_units; float use_ampl; if (globals.Flash.voltage_enabled[channel]) { fixed_ampl_units = g_strdup("V"); } else { fixed_ampl_units = g_strdup("A"); } switch (Submenu_Structure[i]-channel) { case mode_freq_int: mode_name = g_strdup("Internal"); if (globals.ChannelState[channel].trigger_source==source_internal) { current_operating_mode=i; } break; case mode_freq_ext: mode_name = g_strdup("External"); if (globals.ChannelState[channel].trigger_source==source_external) { current_operating_mode=i; } break; case mode_freq_ext2: mode_name = g_strdup("Ext Dbl"); if (globals.ChannelState[channel].trigger_source==source_external2) { current_operating_mode=i; } break; case mode_freq_man: mode_name = g_strdup("Manual"); if (globals.ChannelState[channel].trigger_source==source_manual) { current_operating_mode=i; } break; case mode_freq_hold: mode_name = g_strdup("Hold"); if (globals.ChannelState[channel].trigger_source==source_hold) { current_operating_mode=i; } break; case mode_func_sin: mode_name = g_strdup("Sine"); if (globals.ChannelState[channel].func_mode==sin_mode_on) { current_operating_mode=i; } break; case mode_func_tri: mode_name = g_strdup("Triangle"); if (globals.ChannelState[channel].func_mode==tri_mode_on) { current_operating_mode=i; } break; case mode_func_squ: mode_name = g_strdup("Square"); if (globals.ChannelState[channel].func_mode==squ_mode_on) { current_operating_mode=i; } break; case mode_func_pulse: mode_name = g_strdup("Pulse"); if (globals.ChannelState[channel].func_mode==pulse_mode_on) { current_operating_mode=i; } break; case mode_func_amp: mode_name = g_strdup("Amplify"); if (globals.ChannelState[channel].func_mode==amp_mode_on) { current_operating_mode=i; } break; case mode_delay_norm: mode_name = g_strdup("Normal"); if (globals.ChannelState[channel].double_pulse==double_off) { current_operating_mode=i; } break; case mode_delay_dbl: mode_name = g_strdup("Double Pulse"); if (globals.ChannelState[channel].double_pulse==double_on) { current_operating_mode=i; } break; case mode_pw_norm: mode_name = g_strdup("Normal"); if (globals.ChannelState[channel].func_mode==pulse_mode_on && globals.ChannelState[channel].hold_setting==hold_width && globals.ChannelState[channel].pw_ctrl_mode==pw_normal) { current_operating_mode=i; } break; case mode_pw_duty: mode_name = g_strdup("Duty Cycle"); if (globals.ChannelState[channel].func_mode==pulse_mode_on && globals.ChannelState[channel].hold_setting==hold_duty && globals.ChannelState[channel].pw_ctrl_mode==pw_normal) { current_operating_mode=i; } break; case mode_pw_inout: mode_name = g_strdup("PWin=PWout"); if (globals.ChannelState[channel].func_mode==pulse_mode_on && globals.ChannelState[channel].pw_ctrl_mode==pw_in_out) { current_operating_mode=i; } break; case mode_pw_ew: mode_name = g_strdup("Ext Control"); if (globals.ChannelState[channel].func_mode==pulse_mode_on && globals.ChannelState[channel].pw_ctrl_mode==pw_ew_ext) { current_operating_mode=i; } break; case mode_pw_dc: mode_name = g_strdup("DC output"); if (globals.ChannelState[channel].func_mode==dc_mode_on) { current_operating_mode=i; } break; case mode_output_on: mode_name = g_strdup("Output On"); if (globals.ChannelState[channel].output_state==output_on) { current_operating_mode=i; } break; case mode_output_off: mode_name = g_strdup("Output Off"); if (globals.ChannelState[channel].output_state==output_off) { current_operating_mode=i; } break; case mode_go_to_local: mode_name = g_strdup("Go To Local"); break; case mode_inv_no: mode_name = g_strdup("NO (normal)"); if (globals.ChannelState[channel].inverted==NO) { current_operating_mode=i; } break; case mode_inv_yes: mode_name = g_strdup("YES (inverted)"); if (globals.ChannelState[channel].inverted==YES) { current_operating_mode=i; } break; case mode_gate_losync: mode_name = g_strdup("Sync,TTL-low"); if (globals.ChannelState[channel].gate_type==gate_sync && globals.ChannelState[channel].gate_level==gate_low) { current_operating_mode=i; } break; case mode_gate_hisync: mode_name = g_strdup("Sync,TTL-hi"); if (globals.ChannelState[channel].gate_type==gate_sync && globals.ChannelState[channel].gate_level==gate_high) { current_operating_mode=i; } break; case mode_gate_loasync: mode_name = g_strdup("Async,TTL-low"); if (globals.ChannelState[channel].gate_type==gate_async && globals.ChannelState[channel].gate_level==gate_low) { current_operating_mode=i; } break; case mode_gate_hiasync: mode_name = g_strdup("Async,TTL-hi"); if (globals.ChannelState[channel].gate_type==gate_async && globals.ChannelState[channel].gate_level==gate_high) { current_operating_mode=i; } break; case mode_gpib_address: mode_name = g_strdup("GPIB address"); break; case mode_rs232_settings: mode_name = g_strdup("RS232 setup"); break; case mode_model_info: mode_name = g_strdup("Model info"); break; case mode_network: mode_name = g_strdup("Network info"); break; case mode_password: mode_name = g_strdup("Pwd~default"); break; case mode_selfcal: mode_name = g_strdup("Self Cal"); break; case mode_exit_normal_submenu: mode_name = g_strdup("Exit"); break; case mode_load: mode_name = g_strdup("Load Settings"); break; case mode_save: mode_name = g_strdup("Save Settings"); break; case mode_load_0: case mode_save_0: mode_name = g_strdup("Storage 0"); break; case mode_load_1: case mode_save_1: mode_name = g_strdup("Storage 1"); break; case mode_load_2: case mode_save_2: mode_name = g_strdup("Storage 2"); break; case mode_load_3: case mode_save_3: mode_name = g_strdup("Storage 3"); break; case mode_load_exit: case mode_save_exit: mode_name = g_strdup("Exit"); break; case mode_change_rs232: mode_name = g_strdup("Change values"); break; case mode_default_rs232: mode_name = g_strdup("Default"); break; case mode_exit_rs232: mode_name = g_strdup("Exit"); break; case mode_zout_max: mode_name = g_strdup_printf ("Zout = %d\xf4", globals.Flash.zout_max[channel]); if (globals.ChannelState[channel].zout==globals.Flash.zout_max[channel]) { current_operating_mode=i; } break; case mode_zout_min: mode_name = g_strdup_printf ("Zout = %d\xf4", globals.Flash.zout_min[channel]); if (globals.ChannelState[channel].zout==globals.Flash.zout_min[channel]) { current_operating_mode=i; } break; case mode_logic_ttl: mode_name = g_strdup("TTL levels"); if (globals.ChannelState[channel].logic_level==logic_ttl) { current_operating_mode=i; } break; case mode_logic_ecl: mode_name = g_strdup("ECL levels"); if (globals.ChannelState[channel].logic_level==logic_ecl) { current_operating_mode=i; } break; case mode_amp_normal: mode_name = g_strdup("Normal"); if (globals.ChannelState[channel].amp_mode==amp_mode_normal) { current_operating_mode=i; } break; case mode_amp_ea: mode_name = g_strdup("Ext Control"); if (globals.ChannelState[channel].amp_mode==amp_mode_ea) { current_operating_mode=i; } break; case mode_amp_amplify: mode_name = g_strdup("Ext Amplify"); if (globals.ChannelState[channel].amp_mode==amp_mode_amplify) { current_operating_mode=i; } break; case mode_os_normal: mode_name = g_strdup("Normal"); if (globals.ChannelState[channel].os_mode==os_mode_normal) { current_operating_mode=i; } break; case mode_os_eo: mode_name = g_strdup("Ext Control"); if (globals.ChannelState[channel].os_mode==os_mode_eo) { current_operating_mode=i; } break; // hard-coded count of 10 - not ideal! case (mode_ampl_fixed_point0): use_ampl = globals.Flash.fixed_ampl_points[channel][0]; String_Parameter_To_Text(use_ampl,3,"",fixed_ampl_units,&mode_name,YES,LCD_col_width); if (fabs(globals.ChannelState[channel].amplitude-use_ampl)=4) { base_entry=Submenu_Selected_Item-3; } for (i=base_entry; ( (i<=Submenu_max_entry) && (i< (base_entry+4)) ); ++i) { LCD_write_padded_to_end_of_line(i-base_entry, 26, g_ptr_array_index (gparray, i)); } LCD_write(Submenu_Selected_Item-base_entry,25,"~"); /* add scrolling indicators, if required */ LCD_write(0,39," "); LCD_write(3,39," "); if (base_entry) { LCD_write(0,39,"\x2"); } if ((base_entry+3) < Submenu_max_entry) { LCD_write(3,39,"\x3"); } g_ptr_array_foreach (gparray, (GFunc) g_free, NULL); g_ptr_array_free (gparray, TRUE); } } static void Submenu_Move_Pointer(void) { if (Submenu_max_entry>0) { LCD_write(Submenu_Selected_Item-base_entry,25," "); ++Submenu_Selected_Item; if (Submenu_Selected_Item>Submenu_max_entry) { Submenu_Selected_Item=0; } Submenu_Display(YES); } } static int Submenu_Mult_Value(float mult_by) { int error_num; int channel; float new_value; error_num=OK; /* return if the encoder is not useful for the displayed parameter */ if (Submenu_Numeric_Parameter==Show_No_Number) { return OK; } channel=Submenu_Numeric_Parameter%100; if (fabs(Submenu_Value) < smallest_allowed_number) { if (Submenu_Value < 0.0) { new_value = -smallest_allowed_number * mult_by; } else { new_value = smallest_allowed_number * mult_by; } } else { new_value = Submenu_Value * mult_by; } g_print_debug("chan %d, Submenu_Value %e, mult_by %e, new_value %e\n", channel, Submenu_Value, mult_by, new_value); switch (Submenu_Numeric_Parameter-channel) { case Show_frequency: error_num=Set_frequency(0,0,0,channel,new_value); break; case Show_delay: if (fabs(new_value)1.0) { if (new_value<0.0) { new_value=-zero_equiv_timing; } else { new_value=zero_equiv_timing; } } if (fabs(new_value) < zero_equiv_timing) { if (new_value<0.0) { new_value=-smallest_allowed_number; } else { new_value=smallest_allowed_number; } } error_num=Set_Delay(0,0,0,channel,new_value); break; case Show_pw: if (fabs(new_value)1.0) { if (new_value<0.0) { new_value=-zero_equiv_timing; } else { new_value=zero_equiv_timing; } } if (fabs(new_value) < zero_equiv_timing) { if (new_value<0.0) { new_value=-smallest_allowed_number; } else { new_value=smallest_allowed_number; } } error_num=Set_Pw(0,0,0,channel,new_value,0); break; case Show_amplitude: if (fabs(new_value)1.0) { if (new_value<0.0 || globals.Flash.max_ampl[channel]1.0) { if (new_value<0.0 || globals.Flash.max_offset[channel] 0) { encoder_change -= MIN_ENCODER_CHANGE; } else { encoder_change += MIN_ENCODER_CHANGE; } g_print_debug("encoder change: %d\n",encoder_change); /* quit if RWLS mode */ update_remote_mode (); if (VXI_OR_GPIB_LOCK_ACTIVE) { return; } if (globals.MenuStatus.Type_Of_Menu==Main_Menu_On) { if (encoder_change>0) { Menu_Move_Pointer(1); } else { Menu_Move_Pointer(-1); } g_usleep(2e5); Menu_Clear_Buttons(TRUE); return; } /* increase increments for rapid rotation */ encoder_timer_change[2] = encoder_timer_change[1]; encoder_timer_change[1] = encoder_timer_change[0]; encoder_timer_change[0] = ms_timer() - encoder_last_adjust; encoder_last_adjust = ms_timer(); if (encoder_timer_change[0]<0) { encoder_timer_change[0]=1000; } if (encoder_timer_change[0]>10000) { encoder_timer_change[0]=10000; } unsigned long ms_per_step = encoder_timer_change[0] / abs(encoder_change); g_print_debug("encoder ms per step: %lu\n",ms_per_step); if (ms_per_step > MAX_MS_PER_STEP) { g_print_debug("ignoring slow change\n"); Menu_Clear_Buttons(TRUE); return; } if ( (encoder_timer_change[0] < 50) && (encoder_timer_change[1] < 50) && (encoder_timer_change[2] < 50) && (Submenu_extra_fine==NO) ) { ++encoder_mult; g_print_debug("fast spin x%d\n", encoder_mult); if (encoder_mult>8) { encoder_mult=8; } encoder_change *= encoder_mult; } else { encoder_mult=1; } /* make changes minimal if last adjustment caused an error */ if (last_encoder_adjust_error != OK) { if (encoder_change>0) { encoder_change=1; } else { encoder_change=-1; } } channel=Submenu_Numeric_Parameter%100; /* return if the encoder is not useful for the displayed parameter */ if ((Submenu_Numeric_Parameter-channel)==Show_No_Number || (Submenu_Numeric_Parameter-channel)==Show_monitor) { return; } if (Submenu_Value<0) { abs_Submenu_Value=-Submenu_Value; } else { abs_Submenu_Value=Submenu_Value; } /* deal with special integer parameters first */ if ((Submenu_Numeric_Parameter-channel) == Show_gpib_address) { g_usleep (2e5); if (encoder_change>0) { new_int_value=(int) (Submenu_Value + 1.0); if (new_int_value>30) { new_int_value=0; } } else { new_int_value=(int) (Submenu_Value - 1.0); if (new_int_value<0) { new_int_value=30; } } } if ((Submenu_Numeric_Parameter-channel) == Show_Burst_Count) { g_usleep (2e5); new_int_value=(int) (Submenu_Value); #define LARGE_CHANGE 3 #define BURST_SMALL_INC 1 #define BURST_LARGE_INC 10 if (encoder_change>0) { if (encoder_change>LARGE_CHANGE) { new_int_value += BURST_LARGE_INC; } else { new_int_value += BURST_SMALL_INC; } } else if (encoder_change<0) { if (encoder_change<-LARGE_CHANGE) { new_int_value -= BURST_LARGE_INC; } else { new_int_value -= BURST_SMALL_INC; } } if (new_int_value>globals.Constraints.err_max_burst_count[channel]) { if (globals.Flash.burst_func[channel]) { new_int_value=0; } else { new_int_value=1; } } else if ( (new_int_value<1 && !globals.Flash.burst_func[channel]) || (new_int_value<0 && globals.Flash.burst_func[channel])) { new_int_value=globals.Constraints.err_max_burst_count[channel]; } } else if ( ((Submenu_Numeric_Parameter-channel) == Show_route_primary) || ((Submenu_Numeric_Parameter-channel) == Show_route_secondary) ) { g_usleep (2e5); new_int_value=(int) (Submenu_Value); if (encoder_change>0) { ++new_int_value; } else { --new_int_value; } if (new_int_value>globals.Flash.routing_max_pins[channel]) { new_int_value=1; } if (new_int_value<1) { new_int_value=globals.Flash.routing_max_pins[channel]; } } else { /* deal with normal floating point parameters */ /* if the value is zero, substitute small value */ if (abs_Submenu_Value10000) { equivalent_integer=10100; } /* get first digit of new number */ gchar* int_string = g_strdup_printf ("%d", equivalent_integer); gchar* new_string = g_strdup_printf (" %c.%s%s", int_string[0], int_string+1, expon); g_free (expon); g_free (int_string); /* put in sign if required */ if (Submenu_Value<0) { new_string[0]='-'; } // "moves" fractional digits to rear, to make room for the decimal point new_value=atof(new_string); if (equivalent_integer>9999) { new_value*=10; } if (equivalent_integer<1000) { new_value/=10; } g_free (new_string); } /* update display - correct later if required */ Display_Number_on_LCD(YES,1,2,"",Submenu_Numeric_Parameter,4,LCD_col_width); switch ((Submenu_Numeric_Parameter-channel)) { case Show_frequency: if (globals.Flash.min_freq[channel]==globals.Flash.max_freq[channel]) { return; } error_num=Set_frequency(0,0,0,channel,new_value); break; case Show_delay: if (globals.Flash.min_delay[channel]==globals.Flash.max_delay[channel]) { return; } /* If the new value is less than the zero_equiv_value, but the original was not, set the new value to the smallest allowed number with the same polarity (zero, basically) */ if ( (fabs(new_value) < zero_equiv_timing) && (abs_Submenu_Value > zero_equiv_timing)) { if (Submenu_Value<0.0) { new_value=-smallest_allowed_number; } else { new_value=smallest_allowed_number; } } /* If the new value is less than the zero_equiv_value, and so was the original, flip the polarity (i.e., cross zero) */ if ( (fabs(new_value) < zero_equiv_timing) && (abs_Submenu_Value = zero_equiv_timing)) { if (Submenu_Value<0.0) { new_value=zero_equiv_timing; } else { new_value=-zero_equiv_timing; } } error_num=Set_Delay(0,0,0,channel,new_value); break; case Show_pw: if (globals.Flash.min_pw[channel]==globals.Flash.max_pw[channel]) { return; } /* If the new value is less than the zero_equiv_value, but the original was not, set the new value to the smallest allowed number with the same polarity (zero, basically) */ if ( (fabs(new_value) < zero_equiv_timing) && (abs_Submenu_Value > zero_equiv_timing)) { if (Submenu_Value<0.0) { new_value=-smallest_allowed_number; } else { new_value=smallest_allowed_number; } } /* If the new value is less than the zero_equiv_value, and so was the original, flip the polarity (i.e., cross zero) */ if ( (fabs(new_value) < zero_equiv_timing) && (abs_Submenu_Value = zero_equiv_timing)) { if (Submenu_Value<0.0) { new_value=zero_equiv_timing; } else { new_value=-zero_equiv_timing; } } error_num=Set_Pw(0,0,0,channel,new_value,0); break; case Show_Burst_Time: error_num=Set_Burst_Time(0,0,0,channel,new_value); break; case Show_rise_time: error_num=Set_rise_time(0,0,0,channel,new_value); break; case Show_slew: error_num=Set_slew(0,0,0,channel,new_value); break; case Show_load_type: error_num=Set_Load(channel,new_value); break; case Show_soft_current_limit: error_num=Set_current_limit(0,channel,new_value); break; case Show_amplitude: if (globals.Flash.min_ampl[channel]==globals.Flash.max_ampl[channel]) { return; } if (fabs(new_value) < get_ampl_zero_equiv(channel)) { if (Submenu_Value<0.0) { new_value=-smallest_allowed_number; } else { new_value=smallest_allowed_number; } } if (number_of_fixed_ampl_points(channel)>0) { /* not used for fixed point amplitudes */ return; } /* For units with large amplitude step sizes (AVRQ-2-B-PN-EVE) */ if (globals.Flash.ampl_step_size[channel] > 0.0) { if (new_value < globals.ChannelState[channel].amplitude) { new_value = globals.ChannelState[channel].amplitude - globals.Flash.ampl_step_size[channel]; } else { new_value = globals.ChannelState[channel].amplitude + globals.Flash.ampl_step_size[channel]; } } error_num=Set_Amplitude(0,0,0,0,0,0,0,channel,new_value,0); break; case Show_offset: if (globals.Flash.min_offset[channel]==globals.Flash.max_offset[channel]) { return; } if (fabs(new_value) < globals.Flash.os_zero_equiv[channel]) { if (Submenu_Value<0.0) { new_value=-smallest_allowed_number; } else { new_value=smallest_allowed_number; } } error_num=Set_Offset(0,0,0,0,channel,new_value); break; case Show_duty_cycle: error_num=Set_Pw(0,0,0,channel,new_value/(100*globals.ChannelState[channel].frequency),0); break; case Show_gpib_address: globals.Flash.gpib_address = new_int_value; // must press CHANGE to take effect, through "talklisten" mode choice, to avoid flash write delays error_num=OK; break; case Show_Burst_Count: error_num=Set_Burst_Count(channel,new_int_value,globals.ChannelState[channel].burst_time); break; case Show_route_primary: error_num=Set_Route(channel,ROUTE_PRIMARY,new_int_value); break; case Show_route_secondary: error_num=Set_Route(channel,ROUTE_SECONDARY,new_int_value); break; } Main_update_shift_registers(); Display_Number_on_LCD(YES,1,2,"",Submenu_Numeric_Parameter,4,LCD_col_width); queue_error_and_display_on_LCD(error_num); last_encoder_adjust_error=error_num; Menu_Clear_Buttons(TRUE); return; } static void Nonstd_menu_default_rs232(void) { Menu_Clear_Buttons(TRUE); LCD_clear(); /*0123456789012345678901234567890123456789*/ LCD_write(0,0,"The RS232 settings are now: 1200 baud,"); LCD_write(1,0,"auto data bits / parity, 1 stop bit,"); LCD_write(2,0,"hardware handshaking on, echo on."); LCD_write(3,0,Press_Change_Message); IO_Setup_RS232(1200, 1); Menu_Clear_Buttons(TRUE); globals.MenuStatus.Nonstd_Display=YES; } static void Nonstd_menu_model_info(void) { gchar *message = g_strdup_printf ("Avtech Electrosystems Ltd., Model %s, S/N %s, FW v%s. Since 1975.", globals.Flash.model_num, globals.Flash.serial_num, globals.HWDetect.firmware); LCD_display_extended_message (message, TRUE, FALSE); g_free (message); globals.MenuStatus.Nonstd_Display=YES; } static void Reset_Encoder () { /* reset encoder-monitoring by presetting counters to mid range */ I2C_Write(PCF8574A+Upper_Encoder_Port,127); I2C_Write(PCF8574A+Upper_Encoder_Port,255); } void Menu_Clear_Buttons(int reset_encoder) { int dummy1,dummy2,dummy3; /* enable interrupt lines */ Read_Keypad(&dummy1,&dummy2,&dummy3); if (reset_encoder) { Reset_Encoder(); } } static void Read_Keypad(int *button_port_val, int *upper_encoder_val, int *lower_encoder_val) { #define Overload_Input 64 /* mask for main overload input */ #define Over_Temp 0x10 /* over-temperature */ #define Over_Volt 0x20 /* over-voltage */ #define Over_Other 0x40 /* over-other */ #define Jig_Input 0x08 /* jig open */ int new_button_state; bool Overload_Alarm, Over_Temp_Alarm, Over_Volt_Alarm, Over_Other_Alarm, Jig_Alarm; /* read the button data */ new_button_state = I2C_Read(PCF8574A+Button_Press_Port); /* invert bit 6 (of 0-7) = overload */ if ( (new_button_state & 0x40) == 0x40) { /* if high, set low */ new_button_state = new_button_state & (0xff - 0x40); } else { /* if low, set high */ new_button_state = new_button_state | 0x40; } /* ignore bit 7 (of 0-7) */ new_button_state = new_button_state & 0x7f; /* a button_port_val bit goes low if: The corresponding last_button_state was low (inactive) and The corresponding new_button_state is high (pressed) */ *button_port_val = ~ ((~last_button_state) & (new_button_state)); last_button_state = new_button_state; /* read the encoder data */ *upper_encoder_val = I2C_Read(PCF8574A+Upper_Encoder_Port); /* lowering the button clear line disables encoder counting */ I2C_Write(PCF8574A+Button_Press_Port,127); *lower_encoder_val = I2C_Read(PCF8574A+Lower_Encoder_Port); /* reenable encoder */ I2C_Write(PCF8574A+Button_Press_Port,255); // on all keypads Overload_Alarm = !(*button_port_val & Overload_Input); Over_Temp_Alarm = !(*upper_encoder_val & Over_Temp); Over_Volt_Alarm = !(*upper_encoder_val & Over_Volt); Over_Other_Alarm = !(*upper_encoder_val & Over_Other); Jig_Alarm = !(*upper_encoder_val & Jig_Input); /* alarm condition */ /* valid for both local and remote modes */ if (Over_Temp_Alarm || Over_Volt_Alarm || Jig_Alarm || Over_Other_Alarm || Overload_Alarm) { /* disable all outputs immediately */ int outputs_turned_off = 0; if (globals.Flash.on_off_used) { int chan; for (chan=0; chan<(globals.Flash.ChanKey_output_state?globals.Flash.channels:1); ++chan) { if (globals.ChannelState[chan].output_state == output_on) { ++outputs_turned_off; Set_Output_State(chan,output_off); } } } /* Report the problem if outputs had to be turned off. */ if ((outputs_turned_off > 0) || globals.Flash.warn_even_if_output_off) { /* flag the problem */ if (Over_Temp_Alarm) { queue_and_broadcast_sensor_alarm(Overtemp_Detected); } else if (Over_Volt_Alarm) { queue_and_broadcast_sensor_alarm(Overvolt_Detected); } else if (Jig_Alarm) { queue_and_broadcast_sensor_alarm(Jig_Open_Detected); } else if (Over_Other_Alarm) { queue_and_broadcast_sensor_alarm(Device_Specific_Aux_Error_Detected); } else if (Overload_Alarm) { queue_and_broadcast_sensor_alarm(Overload_Detected); } } } } void Menu_Check_Buttons(void) { int button_port_val; int upper_encoder_val; int lower_encoder_val; int encoder_change; // abort if not running on the target board with the I2C bus if (!globals.HWDetect.has_i2c) { return; } /* get keypad state */ Read_Keypad(&button_port_val,&upper_encoder_val,&lower_encoder_val); encoder_change=lower_encoder_val; /* handle negative changes */ if (encoder_change & 0x80) { encoder_change = encoder_change - 0x100; } update_remote_mode(); if (!(button_port_val & Change_Button)) { /* ----- CHANGE BUTTON --------- */ if (VXI_OR_GPIB_LOCK_ACTIVE) { // front panel is locked out Show_Main_Menu(); } else { if ((globals.MenuStatus.Type_Of_Menu==Main_Menu_On && globals.MenuStatus.Error_Screen==YES) || globals.MenuStatus.Nonstd_Display==YES) { Show_Main_Menu(); } else if (globals.MenuStatus.Type_Of_Menu==Submenu_On && globals.MenuStatus.Error_Screen==YES) { Submenu_Display(NO); } else if (globals.MenuStatus.Type_Of_Menu==Main_Menu_On && globals.MenuStatus.Error_Screen==NO) { Submenu_Display(NO); } else if (globals.MenuStatus.Type_Of_Menu==Submenu_On && globals.MenuStatus.Error_Screen==NO) { int error_num; if (error_num=Submenu_Implement_Changes()) { queue_error_and_display_on_LCD(error_num); } } } Menu_Clear_Buttons(TRUE); } else if (!(button_port_val & Move_Button)) { /* ----- MOVE BUTTON ----------- */ /* MOVE button hit, move pointer */ if (globals.MenuStatus.Type_Of_Menu==Main_Menu_On && globals.MenuStatus.Nonstd_Display==NO && globals.MenuStatus.Error_Screen==NO) { Menu_Move_Pointer(1); } else if (globals.MenuStatus.Type_Of_Menu==Submenu_On && globals.MenuStatus.Nonstd_Display==NO && globals.MenuStatus.Error_Screen==NO) { Submenu_Move_Pointer(); } Menu_Clear_Buttons(TRUE); } else if (!(button_port_val & Mult10_Button)) { /* ----- X10 BUTTON ------------ */ if (globals.MenuStatus.Type_Of_Menu==Submenu_On && !VXI_OR_GPIB_LOCK_ACTIVE) { if (globals.MenuStatus.Error_Screen==YES) { Submenu_Display(NO); } queue_error_and_display_on_LCD(Submenu_Mult_Value(10.0)); } Menu_Clear_Buttons(TRUE); } else if (!(button_port_val & Div10_Button)) { /* ----- /10 BUTTON ------------ */ if (globals.MenuStatus.Type_Of_Menu==Submenu_On && !VXI_OR_GPIB_LOCK_ACTIVE) { if (globals.MenuStatus.Error_Screen==YES) { Submenu_Display(NO); } queue_error_and_display_on_LCD(Submenu_Mult_Value(0.1)); } Menu_Clear_Buttons(TRUE); } else if (!(button_port_val & Plus_Minus_Button)) { /* ----- +/- BUTTON ------------ */ if (globals.MenuStatus.Type_Of_Menu==Submenu_On && !VXI_OR_GPIB_LOCK_ACTIVE) { if (globals.MenuStatus.Error_Screen==YES) { Submenu_Display(NO); } queue_error_and_display_on_LCD(Submenu_Mult_Value(-1.0)); } Menu_Clear_Buttons(TRUE); } else if (!(button_port_val & Extra_Fine_Button)) { /* ----- EXTRA FINE BUTTON ----- */ if (globals.MenuStatus.Type_Of_Menu==Submenu_On && globals.MenuStatus.Nonstd_Display==NO && globals.MenuStatus.Error_Screen==NO && !VXI_OR_GPIB_LOCK_ACTIVE) { if (Submenu_extra_fine==YES) { g_usleep (250e3); Submenu_extra_fine=NO; LCD_write(2,2," "); } else { g_usleep (250e3); Submenu_extra_fine=YES; LCD_write(2,2,"(extra fine adjust)"); } } Menu_Clear_Buttons(TRUE); } /* if none of the buttons are pressed, it must be the encoder */ else if (encoder_change) { /* ----- ENCODER --------------- */ /* ignore if the overload error screen is displayed */ if (!(globals.MenuStatus.Error_Screen==YES && globals.MenuStatus.Type_Of_Menu==Main_Menu_On)) { if (globals.MenuStatus.Error_Screen==YES && globals.MenuStatus.Type_Of_Menu==Submenu_On) { Submenu_Display(NO); } Submenu_Service_Encoder(encoder_change); } } } static int Submenu_Implement_Changes(void) { int error_num; int call_new_submenu; int channel; call_new_submenu=NO; /* this routine changes the pulse generator parameters, as chosen by the submenu settings */ if (Submenu_max_entry==-1) { Show_Main_Menu(); return OK; } /* Cases that involve third-level and greater menu must indicate what menu to return to, e.g */ /* globals.MenuStatus.Selected_Submenu=Submenu1_setup after finishing the default RS232 case. */ channel=Submenu_Structure[Submenu_Selected_Item]%100; switch (Submenu_Structure[Submenu_Selected_Item]-channel) { case mode_freq_int: if (globals.ChannelState[channel].trigger_source!=source_internal) { if (error_num=Set_Trig_Source(channel,source_internal)) { return error_num; } } break; case mode_freq_ext: if (error_num=Set_Trig_Source(channel,source_external)) { return error_num; } break; case mode_freq_ext2: if (error_num=Set_Trig_Source(channel,source_external2)) { return error_num; } break; case mode_freq_man: if (error_num=Set_Trig_Source(channel,source_manual)) { return error_num; } break; case mode_freq_hold: if (error_num=Set_Trig_Source(channel,source_hold)) { return error_num; } break; case mode_func_sin: if (error_num=Set_Func(channel,sin_mode_on)) { return error_num; } break; case mode_func_tri: if (error_num=Set_Func(channel,tri_mode_on)) { return error_num; } break; case mode_func_squ: if (error_num=Set_Func(channel,squ_mode_on)) { return error_num; } break; case mode_func_pulse: if (error_num=Set_Func(channel,pulse_mode_on)) { return error_num; } break; case mode_func_amp: if (error_num=Set_Func(channel,amp_mode_on)) { return error_num; } break; case mode_delay_norm: if (error_num=Set_Double(channel,double_off)) { return error_num; } break; case mode_delay_dbl: if (error_num=Set_Double(channel,double_on)) { return error_num; } break; case mode_pw_norm: globals.ChannelState[channel].hold_setting=hold_width; if ( (globals.ChannelState[channel].pw_ctrl_mode!=pw_normal) || (globals.ChannelState[channel].func_mode!=pulse_mode_on)) { if (error_num=Set_Func(channel,pulse_mode_on)) { return error_num; } if (error_num=Set_Pwmode(channel,pw_normal)) { return error_num; } if (Set_Pw(0,0,0,channel,globals.ChannelState[channel].pw,0)!=OK) { Set_Pw(0,0,0,channel,globals.Flash.min_pw[channel],0); } } break; case mode_pw_duty: globals.ChannelState[channel].hold_setting=hold_duty; if ( (globals.ChannelState[channel].pw_ctrl_mode!=pw_normal) || (globals.ChannelState[channel].func_mode!=pulse_mode_on)) { if (error_num=Set_Func(channel,pulse_mode_on)) { return error_num; } if (error_num=Set_Pwmode(channel,pw_normal)) { return error_num; } if (Set_Pw(0,0,0,channel,globals.ChannelState[channel].pw,0)!=OK) { Set_Pw(0,0,0,channel,globals.Flash.min_pw[channel],0); } } break; case mode_pw_inout: if (error_num=Set_Func(channel,pulse_mode_on)) { return error_num; } if (error_num=Set_Pwmode(channel,pw_in_out)) { return error_num; } break; case mode_pw_ew: if (error_num=Set_Func(channel,pulse_mode_on)) { return error_num; } if (error_num=Set_Pwmode(channel,pw_ew_ext)) { return error_num; } break; case mode_pw_dc: if (error_num=Set_Func(channel,dc_mode_on)) { return error_num; } break; case mode_output_on: if (error_num=Set_Output_State(channel,output_on)) { return error_num; } break; case mode_output_off: if (error_num=Set_Output_State(channel,output_off)) { return error_num; } break; case mode_go_to_local: GPIB_go_to_local(); break; case mode_inv_no: if (error_num=Set_Inverted(channel,NO)) { return error_num; } break; case mode_inv_yes: if (error_num=Set_Inverted(channel,YES)) { return error_num; } break; case mode_gate_losync: Set_Gate_Sync(channel,gate_sync); Set_Gate_Level(channel,gate_low); break; case mode_gate_hisync: Set_Gate_Sync(channel,gate_sync); Set_Gate_Level(channel,gate_high); break; case mode_gate_loasync: Set_Gate_Sync(channel,gate_async); Set_Gate_Level(channel,gate_low); break; case mode_gate_hiasync: Set_Gate_Sync(channel,gate_async); Set_Gate_Level(channel,gate_high); break; case mode_gpib_address: globals.MenuStatus.Selected_Submenu=Submenu2_gpib_address; call_new_submenu=YES; Submenu_Display(NO); /* return cursor to setup submenu afterwards */ globals.MenuStatus.Selected_Submenu=Submenu1_setup; break; case mode_zout_max: if (error_num=Set_zout(channel,globals.Flash.zout_max[channel],1)) { return error_num; } break; case mode_zout_min: if (error_num=Set_zout(channel,globals.Flash.zout_min[channel],1)) { return error_num; } break; case mode_logic_ttl: if (error_num=Set_Logic_Level(channel,logic_ttl)) { return error_num; } break; case mode_logic_ecl: if (error_num=Set_Logic_Level(channel,logic_ecl)) { return error_num; } break; case mode_rise_time_min: if (error_num=Set_rise_time(0,0,0,channel,globals.Flash.min_rise_time[channel])) { return error_num; } break; case mode_rise_time_max: if (error_num=Set_rise_time(0,0,0,channel,globals.Flash.max_rise_time[channel])) { return error_num; } break; // hard-coded count of 10 - not ideal! case (mode_ampl_fixed_point0): if (error_num=Set_Amplitude(0,0,0,0,0,0,0,channel,globals.Flash.fixed_ampl_points[channel][0],0)) { return error_num; } break; case (mode_ampl_fixed_point1): if (error_num=Set_Amplitude(0,0,0,0,0,0,0,channel,globals.Flash.fixed_ampl_points[channel][1],0)) { return error_num; } break; case (mode_ampl_fixed_point2): if (error_num=Set_Amplitude(0,0,0,0,0,0,0,channel,globals.Flash.fixed_ampl_points[channel][2],0)) { return error_num; } break; case (mode_ampl_fixed_point3): if (error_num=Set_Amplitude(0,0,0,0,0,0,0,channel,globals.Flash.fixed_ampl_points[channel][3],0)) { return error_num; } break; case (mode_ampl_fixed_point4): if (error_num=Set_Amplitude(0,0,0,0,0,0,0,channel,globals.Flash.fixed_ampl_points[channel][4],0)) { return error_num; } break; case (mode_ampl_fixed_point5): if (error_num=Set_Amplitude(0,0,0,0,0,0,0,channel,globals.Flash.fixed_ampl_points[channel][5],0)) { return error_num; } break; case (mode_ampl_fixed_point6): if (error_num=Set_Amplitude(0,0,0,0,0,0,0,channel,globals.Flash.fixed_ampl_points[channel][6],0)) { return error_num; } break; case (mode_ampl_fixed_point7): if (error_num=Set_Amplitude(0,0,0,0,0,0,0,channel,globals.Flash.fixed_ampl_points[channel][7],0)) { return error_num; } break; case (mode_ampl_fixed_point8): if (error_num=Set_Amplitude(0,0,0,0,0,0,0,channel,globals.Flash.fixed_ampl_points[channel][8],0)) { return error_num; } break; case (mode_ampl_fixed_point9): if (error_num=Set_Amplitude(0,0,0,0,0,0,0,channel,globals.Flash.fixed_ampl_points[channel][9],0)) { return error_num; } break; case mode_amp_normal: if (error_num=Set_EA(channel,amp_mode_normal)) { return error_num; } break; case mode_amp_ea: if (error_num=Set_EA(channel,amp_mode_ea)) { return error_num; } break; case mode_amp_amplify: if (error_num=Set_EA(channel,amp_mode_amplify)) { return error_num; } break; case mode_os_normal: if (error_num=Set_EO(channel,os_mode_normal)) { return error_num; } break; case mode_os_eo: if (error_num=Set_EO(channel,os_mode_eo)) { return error_num; } break; case mode_gpib_talklisten: // just one entry in this menu, so the address is only updated when CHANGE is pressed, not as encoder is turned GPIB_change_address(globals.Flash.gpib_address); break; case mode_route1: if (error_num=Set_Route(channel,ROUTE_PRIMARY,1)) { return error_num; } break; case mode_route2: if (error_num=Set_Route(channel,ROUTE_PRIMARY,2)) { return error_num; } break; case mode_load: globals.MenuStatus.Selected_Submenu=Submenu2_load; call_new_submenu=YES; Submenu_Display(NO); break; case mode_load_0: Set_Rcl(0); globals.MenuStatus.Selected_Submenu=Submenu1_memory; break; case mode_load_1: Set_Rcl(1); globals.MenuStatus.Selected_Submenu=Submenu1_memory; break; case mode_load_2: Set_Rcl(2); globals.MenuStatus.Selected_Submenu=Submenu1_memory; break; case mode_load_3: Set_Rcl(3); globals.MenuStatus.Selected_Submenu=Submenu1_memory; break; case mode_load_exit: case mode_save_exit: globals.MenuStatus.Selected_Submenu=Submenu1_memory; break; case mode_save: globals.MenuStatus.Selected_Submenu=Submenu2_save; call_new_submenu=YES; Submenu_Display(NO); break; case mode_save_0: Set_Sav(0); globals.MenuStatus.Selected_Submenu=Submenu1_memory; break; case mode_save_1: Set_Sav(1); globals.MenuStatus.Selected_Submenu=Submenu1_memory; break; case mode_save_2: Set_Sav(2); globals.MenuStatus.Selected_Submenu=Submenu1_memory; break; case mode_save_3: Set_Sav(3); globals.MenuStatus.Selected_Submenu=Submenu1_memory; break; case mode_rs232_settings: globals.MenuStatus.Selected_Submenu=Submenu2_rs232; call_new_submenu=YES; Submenu_Display(NO); break; case mode_default_rs232: call_new_submenu=YES; Nonstd_menu_default_rs232(); break; case mode_model_info: call_new_submenu=YES; Nonstd_menu_model_info(); break; case mode_network: call_new_submenu=YES; Nonstd_menu_network(); break; case mode_password: change_password (NULL, "default"); break; case mode_selfcal: if (error_num=self_cal()) { return error_num; } break; case mode_change_rs232: globals.MenuStatus.Selected_Submenu=Submenu2_rs232_baud; call_new_submenu=YES; Submenu_Display(NO); break; case mode_exit_rs232: globals.MenuStatus.Selected_Submenu=Submenu1_setup; break; case mode_1200: IO_Setup_RS232(1200, globals.Flash.hardhand); globals.MenuStatus.Selected_Submenu=Submenu2_rs232_hardhand; call_new_submenu=YES; Submenu_Display(NO); break; case mode_2400: IO_Setup_RS232(2400, globals.Flash.hardhand); globals.MenuStatus.Selected_Submenu=Submenu2_rs232_hardhand; call_new_submenu=YES; Submenu_Display(NO); break; case mode_4800: IO_Setup_RS232(4800, globals.Flash.hardhand); globals.MenuStatus.Selected_Submenu=Submenu2_rs232_hardhand; call_new_submenu=YES; Submenu_Display(NO); break; case mode_9600: IO_Setup_RS232(9600, globals.Flash.hardhand); globals.MenuStatus.Selected_Submenu=Submenu2_rs232_hardhand; call_new_submenu=YES; Submenu_Display(NO); break; case mode_19200: IO_Setup_RS232(19200, globals.Flash.hardhand); globals.MenuStatus.Selected_Submenu=Submenu2_rs232_hardhand; call_new_submenu=YES; Submenu_Display(NO); break; case mode_38400: IO_Setup_RS232(38400, globals.Flash.hardhand); globals.MenuStatus.Selected_Submenu=Submenu2_rs232_hardhand; call_new_submenu=YES; Submenu_Display(NO); break; case mode_57600: IO_Setup_RS232(57600, globals.Flash.hardhand); globals.MenuStatus.Selected_Submenu=Submenu2_rs232_hardhand; call_new_submenu=YES; Submenu_Display(NO); break; case mode_115200: IO_Setup_RS232(115200, globals.Flash.hardhand); globals.MenuStatus.Selected_Submenu=Submenu2_rs232_hardhand; call_new_submenu=YES; Submenu_Display(NO); break; case mode_hand_hard: IO_Setup_RS232(globals.Flash.baud, 1); globals.MenuStatus.Selected_Submenu=Submenu1_setup; break; case mode_hand_off: IO_Setup_RS232(globals.Flash.baud, 0); globals.MenuStatus.Selected_Submenu=Submenu1_setup; break; } Main_update_shift_registers(); /* update values in pulse generator circuit */ if (call_new_submenu==NO) { Show_Main_Menu(); } /* re-run error_check to update min/max values based on actual settings, not proposed settings */ Error_check(globals.ChannelState); return OK; } static void Nonstd_menu_network(void) { LCD_clear(); nicinfo info; if (nicutils_infofordefaultroute(&info)) { gchar *response = g_strdup_printf ("MAC address: %s", info.mac); LCD_write(0,0,response); g_free (response); response = g_strdup_printf ("IP address: %s", info.ip); LCD_write(1,0,response); g_free (response); LCD_write(3,0,"Press CHANGE to continue."); } else { LCD_display_extended_message("No network found.", TRUE, FALSE); } globals.MenuStatus.Nonstd_Display=YES; }