#include "globals.h" #include "lcd.h" #include "i2c.h" #include "error_utils.h" #include "string_utils.h" #include "device-functions.h" #include "version.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 */ /* ----- 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_amp_min 5900 #define mode_amp_max 6000 #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 Submenu_maximum_entries 10 /* used to be 4, before scrolling lists were added */ /* 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 #define Show_avrq_ampl 1900 /* 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, step2, "LOCAL", "LO"); g_free (step2); // shorten as required gchar *step4 = conditional_regex_replace (strlen(step3) > LCD_col_width, step3, "TER", "T"); g_free (step3); // shorten as required gchar *step5 = conditional_regex_replace (strlen(step4) > LCD_col_width, step4, "GPIB", "GP"); g_free (step4); // shorten as required gchar *step6 = conditional_regex_replace (strlen(step5) > LCD_col_width, 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_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_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].ab_mode!=pw_in_out) && ((globals.ChannelState[chan].func_mode==pulse_mode_on) || (globals.ChannelState[chan].func_mode==dc_mode_on)) ) { ++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) { if (globals.ChannelState[chan].ab_mode==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, ":"); } } 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, " IN=OUT"); } } 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 AVRQ extra amplitudes -----*/ if (globals.Flash.enable_avrq_extra_ampls) { for (chan=2; chan<5; ++chan) { ++LCD_entry; Main_Menu_Structure[LCD_entry]=Submenu1_avrq+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_avrq_ampl+chan; menu_string = g_string_append (menu_string, "AMP"); 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 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_polarity?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_polarity) { g_string_append_printf (menu_string, "%d", chan+1); } menu_string = g_string_append (menu_string, ":"); if (globals.ChannelState[chan].polarity==pol_norm) { 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); } 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); } /*----- 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); } /*----- 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); } 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"); 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: Submenu_Value=globals.ChannelState[channel].amplitude; show_plus_sign=YES; if (globals.Flash.voltage_enabled[channel]) { units = g_strdup("V"); } else { units = g_strdup("A"); } break; case Show_avrq_ampl: switch (channel) { case 2: Submenu_Value=globals.ChannelState[0].vcc1; break; case 3: Submenu_Value=globals.ChannelState[0].vcc2; break; case 4: Submenu_Value=globals.ChannelState[0].vlogic; break; } show_plus_sign=YES; units = g_strdup("V"); 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) { 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; 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_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].ab_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].ab_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].ab_mode==pw_in_out) { 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].polarity==pol_norm) { current_operating_mode=i; } break; case mode_inv_yes: mode_name = g_strdup("YES (inverted)"); if (globals.ChannelState[channel].polarity==pol_complement) { 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_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; case mode_amp_min: if (globals.Flash.voltage_enabled[channel]) { String_Parameter_To_Text(globals.Flash.min_ampl[channel],2,"","V",&mode_name,YES,LCD_col_width); } else { String_Parameter_To_Text(globals.Flash.min_ampl[channel],2,"","A",&mode_name,YES,LCD_col_width); } if (fabs(globals.ChannelState[channel].amplitude-globals.Flash.min_ampl[channel])=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; new_value = Submenu_Value * mult_by; switch (Submenu_Numeric_Parameter-channel) { case Show_frequency: if (error_num=Set_frequency(0,0,0,channel,new_value)) { Submenu_Value=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; } } if (error_num=Set_Delay(0,0,0,channel,new_value)) { Submenu_Value=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; } } if (error_num=Set_Pw(0,0,0,channel,new_value,0)) { Submenu_Value=new_value; } break; case Show_amplitude: if (fabs(new_value)1.0) { if (new_value<0.0 || globals.Flash.max_ampl[channel]1.0) { new_value=AVRQ_ZERO_EQUIV; } else if (fabs(new_value) < AVRQ_ZERO_EQUIV) { new_value=smallest_allowed_number; } if (channel == 4) { /* vlogic */ if (mult_by > 1.0) { new_value = globals.ChannelState[0].vcc1; } else { new_value = 0.0; } } if (error_num=Set_Amplitude(0,0,0,0,0,0,channel,new_value,0)) { Submenu_Value=new_value; } break; case Show_Burst_Time: if (error_num=Set_Burst_Time(0,0,0,channel,new_value)) { Submenu_Value=new_value; } break; case Show_rise_time: if (error_num=Set_rise_time(0,0,0,channel,new_value)) { Submenu_Value=new_value; } break; case Show_slew: if (error_num=Set_slew(0,0,0,channel,new_value)) { Submenu_Value=new_value; } break; case Show_load_type: if (error_num=Set_Load(channel,new_value)) { Submenu_Value=new_value; } break; case Show_soft_current_limit: if (error_num=Set_current_limit(0,channel,new_value)) { Submenu_Value=new_value; } break; case Show_offset: if (fabs(new_value)1.0) { if (new_value<0.0 || globals.Flash.max_offset[channel]1) { Menu_Move_Pointer(1); } else if (encoder_change<-1) { Menu_Move_Pointer(-1); } g_usleep(2e5); 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] < 50) && (encoder_timer_change[1] < 50) && (encoder_timer_change[2] < 50) && (Submenu_extra_fine==NO) ) { ++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); reset_encoder=YES; /* to avoid extra unwanted increments */ 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); reset_encoder=YES; /* to avoid extra unwanted increments */ new_int_value=(int) (Submenu_Value); if (encoder_change>0) { ++new_int_value; } else { --new_int_value; } 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); reset_encoder=YES; /* to avoid extra unwanted increments */ 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_Value 0) { Submenu_Value = abs_Submenu_Value = globals.ChannelState[0].vcc1; encoder_change = 0; } else { Submenu_Value = abs_Submenu_Value = 0.0; encoder_change = 0; } } } else if ((channel10000) { 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; } if (error_num=Set_frequency(0,0,0,channel,new_value)) { Submenu_Value=new_value; } break; case Show_delay: /* 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; } } if (error_num=Set_Delay(0,0,0,channel,new_value)) { Submenu_Value=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; } } if (error_num=Set_Pw(0,0,0,channel,new_value,0)) { Submenu_Value=new_value; } break; case Show_Burst_Time: if (error_num=Set_Burst_Time(0,0,0,channel,new_value)) { Submenu_Value=new_value; } break; case Show_rise_time: if (error_num=Set_rise_time(0,0,0,channel,new_value)) { Submenu_Value=new_value; } break; case Show_slew: if (error_num=Set_slew(0,0,0,channel,new_value)) { Submenu_Value=new_value; } break; case Show_load_type: if (error_num=Set_Load(channel,new_value)) { Submenu_Value=new_value; } break; case Show_soft_current_limit: if (error_num=Set_current_limit(0,channel,new_value)) { Submenu_Value=new_value; } break; case Show_amplitude: if (globals.Flash.min_ampl[channel]==globals.Flash.max_ampl[channel]) { return; } if (fabs(new_value) < globals.Flash.ampl_zero_equiv[channel]) { if (Submenu_Value<0.0) { new_value=-smallest_allowed_number; } else { new_value=smallest_allowed_number; } } if (globals.Flash.ampl_min_max_only[channel]) { /* not used for two-state 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]; } } if (error_num=Set_Amplitude(0,0,0,0,0,0,channel,new_value,0)) { Submenu_Value=new_value; } break; case Show_avrq_ampl: if (new_value < AVRQ_ZERO_EQUIV) { new_value=0.0; } if (error_num=Set_Amplitude(0,0,0,0,0,0,channel,new_value,0)) { Submenu_Value=new_value; } break; case Show_offset: if (globals.Flash.min_offset[channel]==globals.Flash.max_offset[channel]) { return; } if (fabs(new_value) < globals.Flash.ampl_zero_equiv[channel]) { if (Submenu_Value<0.0) { new_value=-smallest_allowed_number; } else { new_value=smallest_allowed_number; } } if (error_num=Set_Offset(0,0,0,0,channel,new_value)) { Submenu_Value=new_value; } break; case Show_duty_cycle: if (error_num=Set_Pw(0,0,0,channel,new_value/(100*globals.ChannelState[channel].frequency),0)) { Submenu_Value=new_value; } break; case Show_gpib_address: GPIB_change_address(new_int_value); error_num=OK; break; case Show_Burst_Count: if (error_num=Set_Burst_Count(channel,new_int_value,globals.ChannelState[channel].burst_time)) { Submenu_Value=new_value; } break; case Show_route_primary: if (error_num=Set_Route(channel,ROUTE_PRIMARY,new_int_value)) { Submenu_Value=new_value; } break; case Show_route_secondary: if (error_num=Set_Route(channel,ROUTE_SECONDARY,new_int_value)) { Submenu_Value=new_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; if (reset_encoder) { Menu_Clear_Buttons(); } return; } static void Nonstd_menu_default_rs232(void) { Menu_Clear_Buttons(); 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, TRUE); Menu_Clear_Buttons(); globals.MenuStatus.Nonstd_Display=YES; } static void Nonstd_menu_model_info(void) { gchar *response; LCD_clear(); /*0123456789012345678901234567890123456789*/ LCD_write(0,0,"Avtech Electrosystems Ltd. - since 1975"); LCD_write(1,0,"Visit us at www.avtechpulse.com!"); LCD_write(2,0,"Model: "); LCD_write(2,7,globals.Flash.model_num); response = g_strdup_printf ("SN:%s,v%s", globals.Flash.serial_num, FW_VERSION); LCD_write(3,0,response); g_free (response); LCD_write(3,27,"Press CHANGE."); globals.MenuStatus.Nonstd_Display=YES; } void Menu_Clear_Buttons(void) { int dummy1,dummy2,dummy3; /* enable interrupt lines */ Read_Keypad(&dummy1,&dummy2,&dummy3); } 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 */ int new_button_state; /* 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); /* reset encoder-monitoring by presetting counters to mid range */ I2C_Write(PCF8574A+Upper_Encoder_Port,127); I2C_Write(PCF8574A+Upper_Encoder_Port,255); /* alarm condition */ /* valid for both local and remote modes */ if ( !(*upper_encoder_val & Over_Temp) || !(*upper_encoder_val & Over_Volt) || !(*upper_encoder_val & Over_Other) || !(*button_port_val & Overload_Input) ) { /* 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 (!(*upper_encoder_val & Over_Temp)) { queue_and_broadcast_sensor_alarm(Overtemp_Detected); } else if (!(*upper_encoder_val & Over_Volt)) { queue_and_broadcast_sensor_alarm(Overvolt_Detected); } else if (!(*upper_encoder_val & Over_Other)) { queue_and_broadcast_sensor_alarm(Device_Specific_Aux_Error_Detected); } else if (!(*button_port_val & Overload_Input)) { 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.beaglebone) { 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); } } } } 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(); } } 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)); } } 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)); } } 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)); } } 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)"); } } } /* 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==0) { 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_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].ab_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].ab_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_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_Pol(channel,pol_norm)) { return error_num; } break; case mode_inv_yes: if (error_num=Set_Pol(channel,pol_complement)) { 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_amp_min: if (error_num=Set_Amplitude(0,0,0,0,0,0,channel,globals.Flash.min_ampl[channel],0)) { return error_num; } break; case mode_amp_max: if (error_num=Set_Amplitude(0,0,0,0,0,0,channel,globals.Flash.max_ampl[channel],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_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_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, FALSE); 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, FALSE); 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, FALSE); 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, FALSE); 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, FALSE); 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, FALSE); 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, FALSE); 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, FALSE); 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, FALSE); globals.MenuStatus.Selected_Submenu=Submenu1_setup; call_new_submenu=YES; Submenu_Display(NO); break; case mode_hand_off: IO_Setup_RS232(globals.Flash.baud, 0, FALSE); globals.MenuStatus.Selected_Submenu=Submenu1_setup; call_new_submenu=YES; Submenu_Display(NO); 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; }