diff options
author | Michael J. Chudobiak <mjc@avtechpulse.com> | 2012-08-30 11:42:53 -0400 |
---|---|---|
committer | Michael J. Chudobiak <mjc@avtechpulse.com> | 2012-08-30 11:42:53 -0400 |
commit | 8f1eb077e1ad3c176b3399392edfd109c75551b4 (patch) | |
tree | 39453dab0d8d8f0b5ddd4a549c9721553a966ac9 | |
parent | 28d2cf9fc388d375a5ee6eef4f9e4d42e0fdc41a (diff) |
added missing files
-rw-r--r-- | menus.c | 3464 | ||||
-rw-r--r-- | menus.h | 4 |
2 files changed, 3468 insertions, 0 deletions
@@ -0,0 +1,3464 @@ +#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 <glib.h> + + +/* 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 Menu_Update_Display(void); */ +/* 4. update Submenu_Display(void), which builds the submenu */ +/* 5. update Submenu_Implement_Changes(void), to do the actual functions */ + +/* KEY SUBROUTINES: */ + +/* Menu_Update_Display(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 Submenu_maximum_entries 8 /* 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 */ + +char temp[LCD_col_width+1]; +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 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,char *LCD_string); +static void Submenu_Display(int redraw); +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 void Menu_Check_Buttons(void); +static int Submenu_Implement_Changes(void); +static void Nonstd_menu_network(void); + + +void Menu_Refresh() +{ + globals.Changes.update_whole_main_menu = YES; + LCD_clear(); + Menu_Update_Display(); +} + + +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 Menu_Update_Display(void) +{ + + char units[2*LCD_col_width]; + char a_string[2*LCD_col_width]; + char b_string[2*LCD_col_width]; + 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; + char LCD_string[LCD_cols+1]; + + LCD_entry=-1; + sig_dig = 4; + globals.MenuStatus.Type_Of_Menu=Main_Menu_On; + Submenu_extra_fine=NO; + 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; + if (Main_Menu_Structure[LCD_entry]!=Submenu1_freq+chan) { + globals.Changes.update_whole_main_menu=YES; + } + 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) { + strcpy(a_string,"INT"); + show_item=Show_frequency+chan; + } else if (globals.ChannelState[chan].trigger_source==source_external) { + strcpy(a_string,"EXT TRIG"); + } else if (globals.ChannelState[chan].trigger_source==source_manual) { + strcpy(a_string,"MAN TRIG"); + } else if (globals.ChannelState[chan].trigger_source==source_hold) { + strcpy(a_string,"HOLD TRIG"); + } else if (globals.ChannelState[chan].trigger_source==source_immediate) { + strcpy(a_string,"IMMED TRIG"); + } + + if (globals.Flash.ChanKey_frequency) { + sprintf(b_string, "%d", chan+1); + strcat(a_string,b_string); + } + if (globals.ChannelState[chan].trigger_source==source_internal) { + strcat(a_string,":"); + } + + Display_Number_on_LCD((globals.Changes.update_whole_main_menu || globals.Changes.update_freq) && Menu_Is_Item_Visible(LCD_entry), + LCD_row,LCD_col,a_string,show_item,sig_dig,LCD_col_width-1,LCD_string); + } + } + + /*----- 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; + if (Main_Menu_Structure[LCD_entry]!=Submenu1_func+chan) { + globals.Changes.update_whole_main_menu=YES; + } + 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) { + strcpy(a_string,"SHAPE:PULSE"); + } else if (globals.ChannelState[chan].func_mode==sin_mode_on) { + strcpy(a_string,"SHAPE:SINE"); + } else if (globals.ChannelState[chan].func_mode==tri_mode_on) { + strcpy(a_string,"SHAPE:TRI"); + } else if (globals.ChannelState[chan].func_mode==squ_mode_on) { + strcpy(a_string,"SHAPE:SQU"); + } else if (globals.ChannelState[chan].func_mode==amp_mode_on) { + strcpy(a_string,"SHAPE:AMP"); + } + + if (globals.Flash.ChanKey_func_mode) { + sprintf(b_string, "%d", chan+1); + strcat(a_string,b_string); + } + + Display_Number_on_LCD((globals.Changes.update_whole_main_menu || globals.Changes.update_func) && Menu_Is_Item_Visible(LCD_entry), + LCD_row,LCD_col,a_string,show_item,sig_dig,LCD_col_width-1,LCD_string); + } + } + + /*----- 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; + if (Main_Menu_Structure[LCD_entry]!=Submenu1_delay+chan) { + globals.Changes.update_whole_main_menu=YES; + } + 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) { + strcpy(a_string,"DLY"); + } else { + strcpy(a_string,"DBL"); + } + if (globals.Flash.ChanKey_delay) { + sprintf(b_string, "%d", chan+1); + strcat(a_string,b_string); + } + strcat(a_string,":"); + + Display_Number_on_LCD((globals.Changes.update_whole_main_menu || globals.Changes.update_delay) && Menu_Is_Item_Visible(LCD_entry), + LCD_row,LCD_col,a_string,Show_delay+chan,sig_dig-globals.Flash.ChanKey_delay,LCD_col_width-1,LCD_string); + } + + + /*----- 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; + if (Main_Menu_Structure[LCD_entry]!=Submenu1_pw+chan) { + globals.Changes.update_whole_main_menu=YES; + } + 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; + strcpy(a_string,"PW"); + if (globals.Flash.ChanKey_pw) { + sprintf(b_string, "%d", chan+1); + strcat(a_string,b_string); + } + strcat(a_string,":"); + } else { + show_item=Show_duty_cycle+chan; + strcpy(a_string,"DUTY"); + if (globals.Flash.ChanKey_pw) { + sprintf(b_string, "%d", chan+1); + strcat(a_string,b_string); + } + strcat(a_string,":"); + } + } else { + strcpy(a_string,"PW"); + if (globals.Flash.ChanKey_pw) { + sprintf(b_string, "%d", chan+1); + strcat(a_string,b_string); + } + strcat(a_string," IN=OUT"); + } + } else { + strcpy(a_string,"PW"); + if (globals.Flash.ChanKey_pw) { + sprintf(b_string, "%d", chan+1); + strcat(a_string,b_string); + } + strcat(a_string,": DC"); + } + Display_Number_on_LCD((globals.Changes.update_whole_main_menu || globals.Changes.update_pw) && Menu_Is_Item_Visible(LCD_entry), + LCD_row,LCD_col,a_string,show_item,sig_dig-globals.Flash.ChanKey_pw,LCD_col_width-1,LCD_string); + } + } + + + /*----- 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; + if (Main_Menu_Structure[LCD_entry]!=Submenu1_rise_time+chan) { + globals.Changes.update_whole_main_menu=YES; + } + 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; + strcpy(a_string,"TR"); + if (globals.Flash.ChanKey_rise_time) { + sprintf(b_string, "%d", chan+1); + strcat(a_string,b_string); + } + strcat(a_string,":"); + Display_Number_on_LCD((globals.Changes.update_whole_main_menu || globals.Changes.update_rise_time) && Menu_Is_Item_Visible(LCD_entry), + LCD_row,LCD_col,a_string,show_item,sig_dig-globals.Flash.ChanKey_rise_time,LCD_col_width-1,LCD_string); + } + } + + + /*----- 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; + if (Main_Menu_Structure[LCD_entry]!=Submenu1_amp+chan) { + globals.Changes.update_whole_main_menu=YES; + } + 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; + strcpy(a_string,"AMP"); + if (globals.Flash.ChanKey_amplitude) { + sprintf(b_string, "%d", chan+1); + strcat(a_string,b_string); + } + strcat(a_string,":"); + } else if (globals.ChannelState[chan].amp_mode==amp_mode_ea) { + strcpy(a_string,"AMP"); + if (globals.Flash.ChanKey_amplitude) { + sprintf(b_string, "%d", chan+1); + strcat(a_string,b_string); + } + strcat(a_string,":EXT"); + } else if (globals.ChannelState[chan].amp_mode==amp_mode_amplify) { + strcpy(a_string,"AMP"); + if (globals.Flash.ChanKey_amplitude) { + sprintf(b_string, "%d", chan+1); + strcat(a_string,b_string); + } + strcat(a_string,":AMPLFY"); + } + Display_Number_on_LCD((globals.Changes.update_whole_main_menu || globals.Changes.update_amp) && Menu_Is_Item_Visible(LCD_entry), + LCD_row,LCD_col,a_string,show_item,sig_dig-globals.Flash.ChanKey_amplitude,LCD_col_width-1,LCD_string); + } + } + + + /*----- display AVRQ extra amplitudes -----*/ + + if (globals.Flash.enable_avrq_extra_ampls) { + for (chan=2; chan<5; ++chan) { + ++LCD_entry; + if (Main_Menu_Structure[LCD_entry]!=Submenu1_avrq+chan) { + globals.Changes.update_whole_main_menu=YES; + } + 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; + strcpy(a_string,"AMP"); + sprintf(b_string, "%d", chan+1); + strcat(a_string,b_string); + strcat(a_string,":"); + Display_Number_on_LCD((globals.Changes.update_whole_main_menu || globals.Changes.update_amp) && Menu_Is_Item_Visible(LCD_entry), + LCD_row,LCD_col,a_string,show_item,sig_dig-1,LCD_col_width-1,LCD_string); + } + } + + /*----- 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; + if (Main_Menu_Structure[LCD_entry]!=Submenu1_soft_current_limit+chan) { + globals.Changes.update_whole_main_menu=YES; + } + 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; + strcpy(a_string,"LIM"); + if (globals.Flash.ChanKey_current_limit) { + sprintf(b_string, "%d", chan+1); + strcat(a_string,b_string); + } + strcat(a_string,":"); + Display_Number_on_LCD((globals.Changes.update_whole_main_menu || globals.Changes.update_soft_current_limit) && Menu_Is_Item_Visible(LCD_entry), + LCD_row,LCD_col,a_string,show_item,sig_dig-globals.Flash.ChanKey_current_limit,LCD_col_width-1,LCD_string); + } + } + + + + /*----- 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; + if (Main_Menu_Structure[LCD_entry]!=Submenu1_slew+chan) { + globals.Changes.update_whole_main_menu=YES; + } + 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; + strcpy(a_string,"SL"); + if (globals.Flash.ChanKey_slew) { + sprintf(b_string, "%d", chan+1); + strcat(a_string,b_string); + } + strcat(a_string,":"); + Display_Number_on_LCD((globals.Changes.update_whole_main_menu || globals.Changes.update_slew) && Menu_Is_Item_Visible(LCD_entry), + LCD_row,LCD_col,a_string,show_item,sig_dig-globals.Flash.ChanKey_slew,LCD_col_width-1,LCD_string); + } + } + + + /*----- 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; + if (Main_Menu_Structure[LCD_entry]!=Submenu1_burst_count+chan) { + globals.Changes.update_whole_main_menu=YES; + } + 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; + strcpy(a_string,"N"); + if (globals.Flash.ChanKey_Burst_Count) { + sprintf(b_string, "%d", chan+1); + strcat(a_string,b_string); + } + strcat(a_string,":"); + Display_Number_on_LCD((globals.Changes.update_whole_main_menu || globals.Changes.update_burst_count) && Menu_Is_Item_Visible(LCD_entry), + LCD_row,LCD_col,a_string,show_item,0,LCD_col_width-1,LCD_string); + } + } + + + + /*----- 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; + if (Main_Menu_Structure[LCD_entry]!=Submenu1_burst_time+chan) { + globals.Changes.update_whole_main_menu=YES; + } + 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; + strcpy(a_string,"BUR"); + if (globals.Flash.ChanKey_Burst_Time) { + sprintf(b_string, "%d", chan+1); + strcat(a_string,b_string); + } + strcat(a_string,":"); + Display_Number_on_LCD((globals.Changes.update_whole_main_menu || globals.Changes.update_burst_time) && Menu_Is_Item_Visible(LCD_entry), + LCD_row,LCD_col,a_string,show_item,sig_dig-globals.Flash.ChanKey_Burst_Time,LCD_col_width-1,LCD_string); + } + } + + + + /*----- 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; + if (Main_Menu_Structure[LCD_entry]!=Submenu1_offset+chan) { + globals.Changes.update_whole_main_menu=YES; + } + 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; + strcpy(a_string,"OS"); + if (globals.Flash.ChanKey_offset) { + sprintf(b_string, "%d", chan+1); + strcat(a_string,b_string); + } + strcat(a_string,":"); + } else { + strcpy(a_string,"OS"); + if (globals.Flash.ChanKey_offset) { + sprintf(b_string, "%d", chan+1); + strcat(a_string,b_string); + } + strcat(a_string,":EXT"); + } + Display_Number_on_LCD((globals.Changes.update_whole_main_menu || globals.Changes.update_os) && Menu_Is_Item_Visible(LCD_entry), + LCD_row,LCD_col,a_string,show_item,sig_dig-globals.Flash.ChanKey_offset,LCD_col_width-1,LCD_string); + } + } + + /*----- 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; + + strcpy(a_string,"Mon"); + if (globals.Flash.ChanKey_Curr_Mon_value) { + sprintf(b_string, "%d", chan+1); + strcat(a_string,b_string); + } + strcat(a_string,":"); + Display_Number_on_LCD(Menu_Is_Item_Visible(LCD_entry),LCD_row,LCD_col,a_string,Show_monitor+chan,sig_dig-globals.Flash.ChanKey_Curr_Mon_value,LCD_col_width-1,LCD_string); + 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; + if (Main_Menu_Structure[LCD_entry]!=Submenu1_zout+chan) { + globals.Changes.update_whole_main_menu=YES; + } + 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; + + strcpy(a_string,"Zout"); + if (globals.Flash.ChanKey_zout) { + sprintf(b_string, "%d", chan+1); + strcat(a_string,b_string); + } + strcat(a_string,":"); + + if (globals.ChannelState[chan].zout==globals.Flash.zout_max[chan]) { + sprintf(temp, "%d", globals.Flash.zout_max[chan]); + strcat(a_string,temp); + strcat(a_string,"\xf4 "); + } else { + sprintf(temp, "%d", globals.Flash.zout_min[chan]); + strcat(a_string,temp); + strcat(a_string,"\xf4 "); + } + + Display_Number_on_LCD((globals.Changes.update_whole_main_menu || globals.Changes.update_zout) && Menu_Is_Item_Visible(LCD_entry), + LCD_row,LCD_col,a_string,Show_No_Number,sig_dig-globals.Flash.ChanKey_zout,LCD_col_width-1,LCD_string); + } + } + + + /*----- 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; + if (Main_Menu_Structure[LCD_entry]!=Submenu1_loadtype+chan) { + globals.Changes.update_whole_main_menu=YES; + } + 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; + strcpy(a_string,"Load"); + if (globals.Flash.ChanKey_load_type) { + sprintf(b_string, "%d", chan+1); + strcat(a_string,b_string); + } + strcat(a_string,":"); + Display_Number_on_LCD((globals.Changes.update_whole_main_menu || globals.Changes.update_load) && Menu_Is_Item_Visible(LCD_entry), + LCD_row,LCD_col,a_string,show_item,sig_dig-globals.Flash.ChanKey_load_type,LCD_col_width-1,LCD_string); + } + } + + + /*----- 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; + if (Main_Menu_Structure[LCD_entry]!=Submenu1_output_state+chan) { + globals.Changes.update_whole_main_menu=YES; + } + 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; + + + strcpy(a_string,"Output"); + if (globals.Flash.ChanKey_output_state) { + sprintf(b_string, "%d", chan+1); + strcat(a_string,b_string); + } + strcat(a_string,":"); + + if (globals.ChannelState[chan].output_state==output_on) { + strcat(a_string,"ON"); + } else { + strcat(a_string,"OFF"); + } + + Display_Number_on_LCD((globals.Changes.update_whole_main_menu || globals.Changes.update_output) && Menu_Is_Item_Visible(LCD_entry), + LCD_row,LCD_col,a_string,Show_No_Number,sig_dig-globals.Flash.ChanKey_output_state,LCD_col_width-1,LCD_string); + } + + /*----- 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; + if (Main_Menu_Structure[LCD_entry]!=Submenu1_route_primary+chan) { + globals.Changes.update_whole_main_menu=YES; + } + 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) { + strcpy(a_string,"Route"); + } else { + strcpy(a_string,"ANOD"); + } + + if (globals.Flash.ChanKey_route) { + sprintf(b_string, "%d", chan+1); + strcat(a_string,b_string); + } + strcat(a_string,":"); + Display_Number_on_LCD((globals.Changes.update_whole_main_menu || globals.Changes.update_routes) && Menu_Is_Item_Visible(LCD_entry), + LCD_row,LCD_col,a_string,show_item,0,LCD_col_width-1,LCD_string); + } + } + + + /*----- 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; + if (Main_Menu_Structure[LCD_entry]!=Submenu1_route_secondary+chan) { + globals.Changes.update_whole_main_menu=YES; + } + 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; + + strcpy(a_string,"CATH"); + + if (globals.Flash.ChanKey_route) { + sprintf(b_string, "%d", chan+1); + strcat(a_string,b_string); + } + strcat(a_string,":"); + Display_Number_on_LCD((globals.Changes.update_whole_main_menu || globals.Changes.update_routes) && Menu_Is_Item_Visible(LCD_entry), + LCD_row,LCD_col,a_string,show_item,0,LCD_col_width-1,LCD_string); + } + } + + + /*----- 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; + if (Main_Menu_Structure[LCD_entry]!=Submenu1_invert+chan) { + globals.Changes.update_whole_main_menu=YES; + } + 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; + + strcpy(a_string,"INVERT"); + if (globals.Flash.ChanKey_polarity) { + sprintf(b_string, "%d", chan+1); + strcat(a_string,b_string); + } + strcat(a_string,":"); + + if (globals.ChannelState[chan].polarity==pol_norm) { + strcat(a_string,"NO"); + } else { + strcat(a_string,"YES"); + } + + Display_Number_on_LCD((globals.Changes.update_whole_main_menu || globals.Changes.update_inv) && Menu_Is_Item_Visible(LCD_entry), + LCD_row,LCD_col,a_string,Show_No_Number,sig_dig-globals.Flash.ChanKey_polarity,LCD_col_width-1,LCD_string); + } + } + + + /*----- 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; + if (Main_Menu_Structure[LCD_entry]!=Submenu1_logic_level+chan) { + globals.Changes.update_whole_main_menu=YES; + } + 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; + + strcpy(a_string,"Logic"); + if (globals.Flash.ChanKey_logic_level) { + sprintf(b_string, "%d", chan+1); + strcat(a_string,b_string); + } + strcat(a_string,":"); + if (globals.ChannelState[chan].logic_level==logic_ttl) { + strcat(a_string,"TTL"); + } else { + strcat(a_string,"ECL"); + } + + Display_Number_on_LCD((globals.Changes.update_whole_main_menu || globals.Changes.update_logic_level) && Menu_Is_Item_Visible(LCD_entry), + LCD_row,LCD_col,a_string,Show_No_Number,sig_dig-globals.Flash.ChanKey_logic_level,LCD_col_width-1,LCD_string); + } + } + + + /*----- 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; + if (Main_Menu_Structure[LCD_entry]!=Submenu1_gate+chan) { + globals.Changes.update_whole_main_menu=YES; + } + 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; + + strcpy(a_string,"GAT"); + if (globals.Flash.ChanKey_gate_type || globals.Flash.ChanKey_gate_level) { + sprintf(b_string, "%d", chan+1); + strcat(a_string,b_string); + } + strcat(a_string,":"); + + if (globals.ChannelState[chan].gate_type==gate_sync && globals.ChannelState[chan].gate_level==gate_low) { + strcat(a_string,"SYN,LO"); + } else if (globals.ChannelState[chan].gate_type==gate_sync && globals.ChannelState[chan].gate_level==gate_high) { + strcat(a_string,"SYN,HI"); + } else if (globals.ChannelState[chan].gate_type==gate_async && globals.ChannelState[chan].gate_level==gate_low) { + strcat(a_string,"ASY,LO"); + } else { + strcat(a_string,"ASY,HI"); + } + + Display_Number_on_LCD((globals.Changes.update_whole_main_menu || globals.Changes.update_gate) && Menu_Is_Item_Visible(LCD_entry), + LCD_row,LCD_col,a_string,Show_No_Number, + sig_dig-(globals.Flash.ChanKey_gate_level | globals.Flash.ChanKey_gate_type),LCD_col_width-1,LCD_string); + } + } + + /*----- display remote/local, always -----*/ + + ++LCD_entry; + if (Main_Menu_Structure[LCD_entry]!=Submenu1_rem_loc) { + globals.Changes.update_whole_main_menu=YES; + } + 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; + + switch (globals.control_mode) { + case LOCS_ctrl: + strcpy(LCD_string,"LOCAL CTRL "); + break; + case LWLS_ctrl: + strcpy(LCD_string,"LOCAL LOCK "); + break; + case REMS_ctrl: + strcpy(LCD_string,"GPIB CTRL "); + break; + case RWLS_ctrl: + strcpy(LCD_string,"GPIB LOCK "); + break; + case RS232_ctrl: + strcpy(LCD_string,"RS232 CTRL "); + break; + case WEB_ctrl: + strcpy(LCD_string,"WEB CTRL "); + break; + case TELNET_ctrl: + strcpy(LCD_string,"TELNET CTRL "); + break; + } + + if (globals.Changes.update_whole_main_menu && Menu_Is_Item_Visible(LCD_entry)) { + LCD_write(LCD_row,LCD_col,LCD_string); + } + + + /*----- display memory, always -----*/ + + ++LCD_entry; + if (Main_Menu_Structure[LCD_entry]!=Submenu1_memory) { + globals.Changes.update_whole_main_menu=YES; + } + 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; + + strcpy(LCD_string,"Memory menu "); + if (globals.Changes.update_whole_main_menu && Menu_Is_Item_Visible(LCD_entry)) { + LCD_write(LCD_row,LCD_col,LCD_string); + } + + + /*----- display setup, always -----*/ + + ++LCD_entry; + if (Main_Menu_Structure[LCD_entry]!=Submenu1_setup) { + globals.Changes.update_whole_main_menu=YES; + } + 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; + + strcpy(LCD_string,"Setup menu "); + if (globals.Changes.update_whole_main_menu && Menu_Is_Item_Visible(LCD_entry)) { + LCD_write(LCD_row,LCD_col,LCD_string); + } + + + /*----- 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; + /*1234567890123*/ + LCD_write(LCD_row,LCD_col," "); + } + + globals.Changes.update_whole_main_menu=NO; +} + + +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) { + globals.Changes.update_whole_main_menu=YES; + LCD_clear(); + Menu_Update_Display(); + } + +} + + +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,char *LCD_string) +{ + char units[10]; + int show_plus_sign; + int i; + int channel; + + LCD_string[0]=0; + + channel=Show_What%100; + + if (Show_What!=Show_No_Number) { + switch (Show_What-channel) { + case Show_frequency: + Submenu_Value=globals.ChannelState[channel].frequency; + strcpy(units,"Hz"); + show_plus_sign=NO; + break; + + case Show_delay: + Submenu_Value=globals.ChannelState[channel].delay; + strcpy(units,"s"); + show_plus_sign=YES; + break; + + case Show_pw: + Submenu_Value=globals.ChannelState[channel].pw; + strcpy(units,"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]) { + strcpy(units,"V"); + } else { + strcpy(units,"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; + strcpy(units,"V"); + break; + + case Show_offset: + Submenu_Value=globals.ChannelState[channel].offset; + show_plus_sign=YES; + if (globals.Flash.voltage_offset_enabled[channel]) { + strcpy(units,"V"); + } else { + strcpy(units,"A"); + } + break; + + case Show_monitor: + Submenu_Value=globals.ChannelState[channel].Curr_Mon_value; + show_plus_sign=YES; + if (globals.ChannelState[channel].pw<globals.Flash.mon_pw_threshold[channel]) { + strcpy(units,"A*"); + --significant_digits; + } else { + strcpy(units,"A"); + } + break; + + case Show_duty_cycle: + Submenu_Value=100*globals.ChannelState[channel].pw*globals.ChannelState[channel].frequency; + show_plus_sign=NO; + strcpy(units,"%"); + break; + + case Show_route_primary: + Submenu_Value=(float) globals.ChannelState[channel].route_primary; + significant_digits=0; + show_plus_sign=NO; + strcpy(units,""); + break; + + case Show_route_secondary: + Submenu_Value=(float) globals.ChannelState[channel].route_secondary; + significant_digits=0; + show_plus_sign=NO; + strcpy(units,""); + break; + + case Show_Burst_Count: + Submenu_Value=(float) globals.ChannelState[channel].burst_count; + significant_digits=0; + show_plus_sign=NO; + strcpy(units,""); + break; + + case Show_Burst_Time: + Submenu_Value=globals.ChannelState[channel].burst_time; + strcpy(units,"s"); + show_plus_sign=NO; + break; + + case Show_rise_time: + Submenu_Value=globals.ChannelState[channel].rise_time; + strcpy(units,"s"); + show_plus_sign=NO; + break; + + case Show_slew: + Submenu_Value=globals.ChannelState[channel].slew; + strcpy(units,"A/s"); + show_plus_sign=NO; + break; + + case Show_load_type: + Submenu_Value=globals.ChannelState[channel].load_type; + strcpy(units,"\xf4"); + show_plus_sign=NO; + break; + + case Show_soft_current_limit: + Submenu_Value=globals.ChannelState[channel].soft_current_limit; + strcpy(units,"A"); + show_plus_sign=YES; + break; + + case Show_gpib_address: + Submenu_Value=(float) globals.GPIB.PRIMARY_ADDRESS; + significant_digits=0; + strcpy(units,""); + show_plus_sign=NO; + break; + } + + String_Parameter_To_Text(Submenu_Value,(int) Submenu_Value,significant_digits,start_string,units,LCD_string,show_plus_sign); + } else { + strcpy(LCD_string,start_string); + } + + /* tack on spaces on end of string, but no wider than column */ + for (i=strlen(LCD_string); i<width_of_column; ++i) { + LCD_string[i]=' '; + } + LCD_string[width_of_column]=0; + + if (Is_Item_Visible) { + LCD_write(LCD_row,LCD_col,LCD_string); + } +} + + +static void Submenu_Display(int redraw) +{ + char title[LCD_chars_total+1]; + char mode_name[Submenu_maximum_entries][LCD_col_width+1]; + int i; + int j; + int channel; + int current_operating_mode; + int add_spaces; + int error_num; + char LCD_string[LCD_cols+1]; + + current_operating_mode=0; + + globals.MenuStatus.Type_Of_Menu=Submenu_On; + globals.MenuStatus.Error_Screen=NO; + globals.MenuStatus.Nonstd_Display=NO; + + if (!redraw) { + LCD_clear(); + } + + Submenu_Numeric_Parameter=Show_No_Number; + Submenu_max_entry=0; + + + channel=globals.MenuStatus.Selected_Submenu%100; + + switch (globals.MenuStatus.Selected_Submenu-channel) { + case Submenu1_freq: + + if (globals.ChannelState[channel].trigger_source==source_internal) { + strcpy(title,"Internal Clock:"); + Submenu_Numeric_Parameter=Show_frequency+channel; + } else { + strcpy(title,"Trigger Menu"); + } + + if (globals.Flash.is_func_gen[channel]) { + Submenu_max_entry=0; + } else { + Submenu_max_entry=3; + Submenu_Structure[0]=mode_freq_int; + Submenu_Structure[1]=mode_freq_ext; + Submenu_Structure[2]=mode_freq_man; + Submenu_Structure[3]=mode_freq_hold; + } + + break; + + case Submenu1_func: + + strcpy(title,"Shape Menu"); + Submenu_max_entry=4; + Submenu_Structure[0]=mode_func_sin; + Submenu_Structure[1]=mode_func_tri; + Submenu_Structure[2]=mode_func_squ; + Submenu_Structure[3]=mode_func_pulse; + Submenu_Structure[4]=mode_func_amp; + + break; + + case Submenu1_delay: + + if (globals.ChannelState[channel].double_pulse==double_off) { + strcpy(title,"Delay:"); + } else { + strcpy(title,"Pulse Spacing:"); + } + Submenu_Numeric_Parameter=Show_delay+channel; + + if (globals.Flash.double_pulse_allowed[channel]) { + Submenu_max_entry=1; + Submenu_Structure[0]=mode_delay_norm; + Submenu_Structure[1]=mode_delay_dbl; + } else { + Submenu_max_entry=0; + } + + + break; + + case Submenu1_pw: + if (globals.ChannelState[channel].ab_mode==pw_normal) { + if (globals.ChannelState[channel].hold_setting==hold_width) { + strcpy(title,"Pulse Width:"); + Submenu_Numeric_Parameter=Show_pw+channel; + } else { + strcpy(title,"Duty Cycle:"); + Submenu_Numeric_Parameter=Show_duty_cycle+channel; + } + } else { + strcpy(title,"Pulse Width:"); + } + + Submenu_max_entry=0; + Submenu_Structure[0]=mode_pw_norm; + + if (globals.ChannelState[channel].trigger_source==source_external && (globals.Flash.ab_mode_allowed[channel])) { + Submenu_max_entry=1; + Submenu_Structure[1]=mode_pw_inout; + } else if (globals.ChannelState[channel].trigger_source==source_internal && (globals.Flash.dc_mode_allowed[channel])) { + Submenu_max_entry=2; + Submenu_Structure[1]=mode_pw_duty; + Submenu_Structure[2]=mode_pw_dc; + } else if (globals.ChannelState[channel].trigger_source==source_internal) { + Submenu_max_entry=1; + Submenu_Structure[1]=mode_pw_duty; + } + break; + + case Submenu1_amp: + strcpy(title,"Amplitude"); + + if (globals.Flash.enable_avrq_extra_ampls) { + if (channel==0) { + strcat(title,"1 (HV):"); + } else { + strcat(title,"2 (IBIAS):"); + } + } else { + strcat(title,":"); + } + + + if (globals.ChannelState[channel].amp_mode==amp_mode_normal && !globals.Flash.ampl_min_max_only[channel]) { + Submenu_Numeric_Parameter=Show_amplitude+channel; + } + + if (globals.Flash.ampl_min_max_only[channel]) { + Submenu_max_entry=1; + Submenu_Structure[0]=mode_amp_min; + Submenu_Structure[1]=mode_amp_max; + } + if (globals.Flash.ea_enabled[channel]) { + ++Submenu_max_entry; + Submenu_Structure[0]=mode_amp_normal; + Submenu_Structure[Submenu_max_entry]=mode_amp_ea; + } + if (globals.Flash.ext_amplify_enabled[channel]) { + ++Submenu_max_entry; + Submenu_Structure[0]=mode_amp_normal; + Submenu_Structure[Submenu_max_entry]=mode_amp_amplify; + } + + break; + + case Submenu1_avrq: + + switch (channel) { + case 2: + strcpy(title,"Amplitude3 (Vcc1):"); + break; + case 3: + strcpy(title,"Amplitude4 (Vcc2):"); + break; + case 4: + strcpy(title,"Amplitude5 (Vlogic):"); + break; + } + + Submenu_Numeric_Parameter=Show_avrq_ampl+channel; + break; + + case Submenu1_burst_count: + strcpy(title,"Pulses per burst:"); + Submenu_Numeric_Parameter=Show_Burst_Count+channel; + Submenu_max_entry=0; + break; + + case Submenu1_burst_time: + strcpy(title,"Burst Spacing (i.e., low interval):"); + Submenu_Numeric_Parameter=Show_Burst_Time+channel; + Submenu_max_entry=0; + break; + + case Submenu1_rise_time: + strcpy(title,"Rise time (10%-90%):"); + Submenu_Numeric_Parameter=Show_rise_time+channel; + Submenu_max_entry=0; + break; + + case Submenu1_slew: + strcpy(title,"Slew rate:"); + Submenu_Numeric_Parameter=Show_slew+channel; + Submenu_max_entry=0; + break; + + case Submenu1_soft_current_limit: + strcpy(title,"Current limit:"); + Submenu_Numeric_Parameter=Show_soft_current_limit+channel; + Submenu_max_entry=0; + break; + + case Submenu1_zout: + strcpy(title,"Output Impedance"); + Submenu_max_entry=1; + Submenu_Structure[0]=mode_zout_min; + Submenu_Structure[1]=mode_zout_max; + break; + + case Submenu1_loadtype: + strcpy(title,"Load Impedance"); + Submenu_Numeric_Parameter=Show_load_type+channel; + Submenu_max_entry=0; + break; + + case Submenu1_offset: + strcpy(title,"Offset:"); + + 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; + } else { + Submenu_max_entry=0; + } + + break; + + case Submenu1_mon: + Submenu_max_entry=0; + strcpy(title,"Monitor:"); + if (globals.ChannelState[channel].pw<globals.Flash.mon_pw_threshold[channel]) { + LCD_write(2,2,"*PW too narrow for accurate reading."); + } + Submenu_Numeric_Parameter=Show_monitor+channel; + break; + + case Submenu1_output_state: + strcpy(title,"Output State:"); + + Submenu_max_entry=1; + Submenu_Structure[0]=mode_output_on; + Submenu_Structure[1]=mode_output_off; + + break; + + case Submenu1_invert: + strcpy(title,"Inverted Output?:"); + + Submenu_max_entry=1; + Submenu_Structure[0]=mode_inv_no; + Submenu_Structure[1]=mode_inv_yes; + + break; + + case Submenu1_logic_level: + strcpy(title,"Logic Outputs:"); + Submenu_max_entry=1; + Submenu_Structure[0]=mode_logic_ttl; + Submenu_Structure[1]=mode_logic_ecl; + break; + + case Submenu1_gate: + strcpy(title,"Gate (trigger off) "); + + Submenu_max_entry=1; + Submenu_Structure[0]=mode_gate_losync; + Submenu_Structure[1]=mode_gate_hisync; + + /* async mode doesn't work properly in dual-channel units */ + if ((globals.Flash.channels<=1) && !globals.Flash.sync_only) { + Submenu_max_entry=3; + Submenu_Structure[2]=mode_gate_loasync; + Submenu_Structure[3]=mode_gate_hiasync; + } + + break; + + case Submenu1_rem_loc: + strcpy(title,"Control Mode:"); + Submenu_max_entry=1; + + Submenu_Structure[0]=mode_go_to_local; + Submenu_Structure[1]=mode_exit_normal_submenu; + break; + + case Submenu1_setup: + strcpy(title,"Setup Menu:"); + + Submenu_max_entry=5; + if (globals.Flash.self_cal) { + Submenu_max_entry=6; + Submenu_Structure[5]=mode_selfcal; + } + + Submenu_Structure[0]=mode_gpib_address; + Submenu_Structure[1]=mode_rs232_settings; + Submenu_Structure[2]=mode_model_info; + Submenu_Structure[3]=mode_network; + Submenu_Structure[4]=mode_password; + Submenu_Structure[Submenu_max_entry]=mode_exit_normal_submenu; + break; + + case Submenu2_save: + strcpy(title,"Save Settings:"); + Submenu_max_entry=3; + + Submenu_Structure[0]=mode_save_0; + Submenu_Structure[1]=mode_save_1; + Submenu_Structure[2]=mode_save_2; + Submenu_Structure[3]=mode_save_3; + break; + + case Submenu2_load: + strcpy(title,"Load Settings:"); + Submenu_max_entry=3; + + Submenu_Structure[0]=mode_load_0; + Submenu_Structure[1]=mode_load_1; + Submenu_Structure[2]=mode_load_2; + Submenu_Structure[3]=mode_load_3; + break; + + case Submenu1_memory: + strcpy(title,"Memory:"); + Submenu_max_entry=2; + + Submenu_Structure[0]=mode_load; + Submenu_Structure[1]=mode_save; + Submenu_Structure[2]=mode_exit_normal_submenu; + break; + + case Submenu2_rs232: + strcpy(title,"Serial Port:"); + Submenu_max_entry=2; + + Submenu_Structure[0]=mode_change_rs232; + Submenu_Structure[1]=mode_default_rs232; + Submenu_Structure[2]=mode_exit_rs232; + break; + + case Submenu2_rs232_baud: + strcpy(title,"Baud Rate:"); + Submenu_max_entry=3; + + Submenu_Structure[0]=mode_1200; + Submenu_Structure[1]=mode_2400; + Submenu_Structure[2]=mode_4800; + Submenu_Structure[3]=mode_9600; + break; + + case Submenu2_rs232_databits: + strcpy(title,"Data Bits:"); + Submenu_max_entry=1; + + Submenu_Structure[0]=mode_7bits; + Submenu_Structure[1]=mode_8bits; + break; + + case Submenu2_rs232_parity: + strcpy(title,"Parity:"); + Submenu_max_entry=2; + + Submenu_Structure[0]=mode_par_none; + Submenu_Structure[1]=mode_par_even; + Submenu_Structure[2]=mode_par_odd; + break; + + case Submenu2_rs232_stopbits: + strcpy(title,"Stop Bits:"); + Submenu_max_entry=1; + + Submenu_Structure[0]=mode_1bit; + Submenu_Structure[1]=mode_2bits; + break; + + case Submenu2_rs232_hardhand: + strcpy(title,"Handshaking:"); + Submenu_max_entry=1; + + Submenu_Structure[0]=mode_hand_hard; + Submenu_Structure[1]=mode_hand_off; + break; + + case Submenu2_rs232_echo: + strcpy(title,"Echo:"); + Submenu_max_entry=1; + + Submenu_Structure[0]=mode_echo_on; + Submenu_Structure[1]=mode_echo_off; + break; + + case Submenu2_gpib_address: + strcpy(title,"GPIB Address:"); + Submenu_Numeric_Parameter=Show_gpib_address+channel; + break; + + case Submenu1_route_primary: + if (globals.Flash.routing_required[channel] == 1) { + strcpy(title,"Output route:"); + } else { + strcpy(title,"Anode pin:"); + } + Submenu_Numeric_Parameter=Show_route_primary+channel; + Submenu_max_entry=0; + break; + + case Submenu1_route_secondary: + strcpy(title,"Cathode pin:"); + Submenu_Numeric_Parameter=Show_route_secondary+channel; + Submenu_max_entry=0; + break; + + + default: + strcpy(title,"error - not implemented"); + } + + for (i=0; i<=Submenu_max_entry; ++i) { + Submenu_Structure[i]+=channel; + } + + LCD_write(0,0,title); + Display_Number_on_LCD(YES,1,2,"",Submenu_Numeric_Parameter,4,LCD_col_width,LCD_string); + LCD_write(3,0,Press_Change_Message); + + if (Submenu_max_entry>0) { + LCD_write(0,19,"Mode:"); + + for (i=0; i<=Submenu_max_entry; ++i) { + switch (Submenu_Structure[i]-channel) { + case mode_freq_int: + strcpy(mode_name[i],"Internal"); + if (globals.ChannelState[channel].trigger_source==source_internal) { + current_operating_mode=i; + } + break; + case mode_freq_ext: + strcpy(mode_name[i],"External"); + if (globals.ChannelState[channel].trigger_source==source_external) { + current_operating_mode=i; + } + break; + case mode_freq_man: + strcpy(mode_name[i],"Manual"); + if (globals.ChannelState[channel].trigger_source==source_manual) { + current_operating_mode=i; + } + break; + case mode_freq_hold: + strcpy(mode_name[i],"Hold"); + if (globals.ChannelState[channel].trigger_source==source_hold) { + current_operating_mode=i; + } + break; + case mode_func_sin: + strcpy(mode_name[i],"Sine"); + if (globals.ChannelState[channel].func_mode==sin_mode_on) { + current_operating_mode=i; + } + break; + case mode_func_tri: + strcpy(mode_name[i],"Triangle"); + if (globals.ChannelState[channel].func_mode==tri_mode_on) { + current_operating_mode=i; + } + break; + case mode_func_squ: + strcpy(mode_name[i],"Square"); + if (globals.ChannelState[channel].func_mode==squ_mode_on) { + current_operating_mode=i; + } + break; + case mode_func_pulse: + strcpy(mode_name[i],"Pulse"); + if (globals.ChannelState[channel].func_mode==pulse_mode_on) { + current_operating_mode=i; + } + break; + case mode_func_amp: + strcpy(mode_name[i],"Amplify"); + if (globals.ChannelState[channel].func_mode==amp_mode_on) { + current_operating_mode=i; + } + break; + case mode_delay_norm: + strcpy(mode_name[i],"Normal"); + if (globals.ChannelState[channel].double_pulse==double_off) { + current_operating_mode=i; + } + break; + case mode_delay_dbl: + strcpy(mode_name[i],"Double Pulse"); + if (globals.ChannelState[channel].double_pulse==double_on) { + current_operating_mode=i; + } + break; + case mode_pw_norm: + strcpy(mode_name[i],"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: + strcpy(mode_name[i],"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: + strcpy(mode_name[i],"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: + strcpy(mode_name[i],"DC output"); + if (globals.ChannelState[channel].func_mode==dc_mode_on) { + current_operating_mode=i; + } + break; + case mode_output_on: + strcpy(mode_name[i],"Output On"); + if (globals.ChannelState[channel].output_state==output_on) { + current_operating_mode=i; + } + break; + case mode_output_off: + strcpy(mode_name[i],"Output Off"); + if (globals.ChannelState[channel].output_state==output_off) { + current_operating_mode=i; + } + break; + case mode_go_to_local: + strcpy(mode_name[i],"Go To Local"); + break; + case mode_inv_no: + strcpy(mode_name[i],"NO (normal)"); + if (globals.ChannelState[channel].polarity==pol_norm) { + current_operating_mode=i; + } + break; + case mode_inv_yes: + strcpy(mode_name[i],"YES (inverted)"); + if (globals.ChannelState[channel].polarity==pol_complement) { + current_operating_mode=i; + } + break; + case mode_gate_losync: + strcpy(mode_name[i],"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: + strcpy(mode_name[i],"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: + strcpy(mode_name[i],"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: + strcpy(mode_name[i],"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: + strcpy(mode_name[i],"GPIB address"); + break; + case mode_rs232_settings: + strcpy(mode_name[i],"RS232 setup"); + break; + case mode_model_info: + strcpy(mode_name[i],"Model info"); + break; + case mode_network: + strcpy(mode_name[i],"Network info"); + break; + case mode_password: + strcpy(mode_name[i],"Pwd~default"); + break; + case mode_selfcal: + strcpy(mode_name[i],"Self Cal"); + break; + case mode_exit_normal_submenu: + strcpy(mode_name[i],"Exit"); + break; + case mode_load: + strcpy(mode_name[i],"Load Settings"); + break; + case mode_save: + strcpy(mode_name[i],"Save Settings"); + break; + case mode_load_0: + strcpy(mode_name[i],"Storage 0"); + break; + case mode_load_1: + strcpy(mode_name[i],"Storage 1"); + break; + case mode_load_2: + strcpy(mode_name[i],"Storage 2"); + break; + case mode_load_3: + strcpy(mode_name[i],"Storage 3"); + break; + case mode_save_0: + strcpy(mode_name[i],"Storage 0"); + break; + case mode_save_1: + strcpy(mode_name[i],"Storage 1"); + break; + case mode_save_2: + strcpy(mode_name[i],"Storage 2"); + break; + case mode_save_3: + strcpy(mode_name[i],"Storage 3"); + break; + case mode_change_rs232: + strcpy(mode_name[i],"Change values"); + break; + case mode_default_rs232: + strcpy(mode_name[i],"Default"); + break; + case mode_exit_rs232: + strcpy(mode_name[i],"Exit"); + break; + case mode_zout_max: + strcpy(mode_name[i],"Zout = "); + sprintf(temp, "%d", globals.Flash.zout_max[channel]); + strcat(mode_name[i],temp); + strcat(mode_name[i],"\xf4"); + if (globals.ChannelState[channel].zout==globals.Flash.zout_max[channel]) { + current_operating_mode=i; + } + break; + case mode_zout_min: + strcpy(mode_name[i],"Zout = "); + sprintf(temp, "%d", globals.Flash.zout_min[channel]); + strcat(mode_name[i],temp); + strcat(mode_name[i],"\xf4"); + if (globals.ChannelState[channel].zout==globals.Flash.zout_min[channel]) { + current_operating_mode=i; + } + break; + case mode_logic_ttl: + strcpy(mode_name[i],"TTL levels"); + if (globals.ChannelState[channel].logic_level==logic_ttl) { + current_operating_mode=i; + } + break; + case mode_logic_ecl: + strcpy(mode_name[i],"ECL levels"); + if (globals.ChannelState[channel].logic_level==logic_ecl) { + current_operating_mode=i; + } + break; + case mode_amp_normal: + strcpy(mode_name[i],"Normal"); + if (globals.ChannelState[channel].amp_mode==amp_mode_normal) { + current_operating_mode=i; + } + break; + case mode_amp_ea: + strcpy(mode_name[i],"Ext Control"); + if (globals.ChannelState[channel].amp_mode==amp_mode_ea) { + current_operating_mode=i; + } + break; + case mode_amp_amplify: + strcpy(mode_name[i],"Ext Amplify"); + if (globals.ChannelState[channel].amp_mode==amp_mode_amplify) { + current_operating_mode=i; + } + break; + case mode_os_normal: + strcpy(mode_name[i],"Normal"); + if (globals.ChannelState[channel].os_mode==os_mode_normal) { + current_operating_mode=i; + } + break; + case mode_os_eo: + strcpy(mode_name[i],"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],0,2,"","V",mode_name[i],YES); + } else { + String_Parameter_To_Text(globals.Flash.min_ampl[channel],0,2,"","A",mode_name[i],YES); + } + + if (fabs(globals.ChannelState[channel].amplitude-globals.Flash.min_ampl[channel])<globals.Flash.ampl_zero_equiv[channel]) { + current_operating_mode=i; + } + break; + case mode_amp_max: + if (globals.Flash.voltage_enabled[channel]) { + String_Parameter_To_Text(globals.Flash.max_ampl[channel],0,2,"","V",mode_name[i],YES); + } else { + String_Parameter_To_Text(globals.Flash.max_ampl[channel],0,2,"","A",mode_name[i],YES); + } + + if (fabs(globals.ChannelState[channel].amplitude-globals.Flash.max_ampl[channel])<globals.Flash.ampl_zero_equiv[channel]) { + current_operating_mode=i; + } + break; + case mode_1200: + strcpy(mode_name[i],"1200 baud"); + if (globals.RS232.baud==rs232_1200_baud) { + current_operating_mode=i; + } + break; + case mode_2400: + strcpy(mode_name[i],"2400 baud"); + if (globals.RS232.baud==rs232_2400_baud) { + current_operating_mode=i; + } + break; + case mode_4800: + strcpy(mode_name[i],"4800 baud"); + if (globals.RS232.baud==rs232_4800_baud) { + current_operating_mode=i; + } + break; + case mode_9600: + strcpy(mode_name[i],"9600 baud"); + if (globals.RS232.baud==rs232_9600_baud) { + current_operating_mode=i; + } + break; + case mode_7bits: + strcpy(mode_name[i],"7 bits"); + if (globals.RS232.databits==rs232_7data_bits) { + current_operating_mode=i; + } + break; + case mode_8bits: + strcpy(mode_name[i],"8 bits"); + if (globals.RS232.databits==rs232_8data_bits) { + current_operating_mode=i; + } + break; + case mode_par_none: + strcpy(mode_name[i],"None"); + if (globals.RS232.parity==rs232_parity_none) { + current_operating_mode=i; + } + break; + case mode_par_even: + strcpy(mode_name[i],"Even"); + if (globals.RS232.parity==rs232_parity_even) { + current_operating_mode=i; + } + break; + case mode_par_odd: + strcpy(mode_name[i],"Odd"); + if (globals.RS232.parity==rs232_parity_odd) { + current_operating_mode=i; + } + break; + case mode_1bit: + strcpy(mode_name[i],"1 bit"); + if (globals.RS232.stopbits==rs232_1stop_bit) { + current_operating_mode=i; + } + break; + case mode_2bits: + strcpy(mode_name[i],"2 bits"); + if (globals.RS232.stopbits==rs232_2stop_bits) { + current_operating_mode=i; + } + break; + case mode_hand_hard: + strcpy(mode_name[i],"Hardware"); + if (globals.RS232.hardhand==rs232_hard_on) { + current_operating_mode=i; + } + break; + case mode_hand_off: + strcpy(mode_name[i],"None"); + if (globals.RS232.hardhand==rs232_hard_off) { + current_operating_mode=i; + } + break; + case mode_echo_on: + strcpy(mode_name[i],"On"); + if (globals.RS232.echo==rs232_echo_on) { + current_operating_mode=i; + } + break; + case mode_echo_off: + strcpy(mode_name[i],"Off"); + if (globals.RS232.echo==rs232_echo_off) { + current_operating_mode=i; + } + break; + } + } + + /* If redraw==NO, the submenu is being drawn from scratch. In this case, the arrow pointer points at the + current operating mode. If redraw=YES, the submenu is being redrawn to scroll the mode list. In this case, + the arrow pointer points at the current selection. */ + + if (redraw==NO && current_operating_mode<4) { + base_entry=0; + Submenu_Selected_Item=current_operating_mode; + } else if (redraw==NO) { + base_entry=current_operating_mode-3; + Submenu_Selected_Item=current_operating_mode; + } else if (redraw=YES && Submenu_Selected_Item<4) { + base_entry=0; + } else if (redraw=YES && Submenu_Selected_Item>=4) { + base_entry=Submenu_Selected_Item-3; + } + + for (i=base_entry; ( (i<=Submenu_max_entry) && (i< (base_entry+4)) ); ++i) { + add_spaces=LCD_col_width-strlen(mode_name[i]); + for (j=0; j<add_spaces; j++) { + strcat(mode_name[i]," "); + } + LCD_write(i-base_entry,26,mode_name[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"); + } + + } + + return OK; +} + + +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; + char LCD_string[LCD_cols+1]; + + 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)<zero_equiv_timing && mult_by>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)<zero_equiv_timing && mult_by>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)<globals.Flash.ampl_zero_equiv[channel] && mult_by>1.0) { + if (new_value<0.0 || globals.Flash.max_ampl[channel]<globals.Flash.ampl_zero_equiv[channel]) { + new_value=-globals.Flash.ampl_zero_equiv[channel]; + } else { + new_value=globals.Flash.ampl_zero_equiv[channel]; + } + } + if (fabs(new_value) < globals.Flash.ampl_zero_equiv[channel]) + if (new_value<0.0) { + new_value=-smallest_allowed_number; + } else { + new_value=smallest_allowed_number; + } + 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 (fabs(new_value)<AVRQ_ZERO_EQUIV && mult_by>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)<globals.Flash.ampl_zero_equiv[channel] && mult_by>1.0) { + if (new_value<0.0 || globals.Flash.max_offset[channel]<globals.Flash.ampl_zero_equiv[channel]) { + new_value=-globals.Flash.ampl_zero_equiv[channel]; + } else { + new_value=globals.Flash.ampl_zero_equiv[channel]; + } + } + if (fabs(new_value) < globals.Flash.ampl_zero_equiv[channel]) + if (new_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; + } + + Main_update_shift_registers(); + + Display_Number_on_LCD(YES,1,2,"",Submenu_Numeric_Parameter,4,LCD_col_width,LCD_string); + + return error_num; +} + + +static void Submenu_Service_Encoder(int encoder_change) +{ + + int error_num; + int new_encoder_change; + char num_string[32]; /* submenu_value in string form */ + char expon[32]; /* exponent portion of string */ + int equivalent_integer; /* non-exponent part stripped of its decimal point */ + char new_string[32]; /* new parameter value to be loaded, string format */ + float new_value; /* new parameter value to be loaded */ + float abs_Submenu_Value; /* absolute value of Submenu_Value */ + int increment_size; + int new_int_value; + int reset_encoder; + int channel; + char LCD_string[LCD_cols+1]; + + reset_encoder=YES; + + /* quit if RWLS mode */ + if (globals.control_mode==RWLS_ctrl) { + return; + } + + if (globals.MenuStatus.Type_Of_Menu==Main_Menu_On) { + if (encoder_change>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<zero_equiv_timing + && + ( ((Submenu_Numeric_Parameter-channel)==Show_delay) + || ((Submenu_Numeric_Parameter-channel)==Show_pw) + || ((Submenu_Numeric_Parameter-channel)==Show_Burst_Time) ) + ) { + abs_Submenu_Value=zero_equiv_timing; + } + + /* reverse direction for negative values if they are supposed + to smoothly transition through zero */ + if ( (Submenu_Value < 0.0) + && (((Submenu_Numeric_Parameter-channel)==Show_delay) + || ((Submenu_Numeric_Parameter-channel)==Show_pw)) ) { + encoder_change = -encoder_change; + } + + else if ((channel<max_channels) && abs_Submenu_Value<globals.Flash.ampl_zero_equiv[channel] && (Submenu_Numeric_Parameter-channel)==Show_amplitude) { + abs_Submenu_Value=globals.Flash.ampl_zero_equiv[channel]; + if (globals.Flash.max_ampl[channel]<globals.Flash.ampl_zero_equiv[channel]) { + Submenu_Value=-abs_Submenu_Value; + } + } + + else if (abs_Submenu_Value < AVRQ_ZERO_EQUIV && (Submenu_Numeric_Parameter-channel)==Show_avrq_ampl) { + abs_Submenu_Value=AVRQ_ZERO_EQUIV; + + if (channel == 4) { /* vlogic */ + if (encoder_change > 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 ((channel<max_channels) && abs_Submenu_Value<globals.Flash.ampl_zero_equiv[channel] && (Submenu_Numeric_Parameter-channel)==Show_offset) { + abs_Submenu_Value=globals.Flash.ampl_zero_equiv[channel]; + if (globals.Flash.max_offset[channel]<globals.Flash.ampl_zero_equiv[channel]) { + Submenu_Value=-abs_Submenu_Value; + } + } + + + /* get a string version of the floating value to be modified */ + Float_To_Text(3,abs_Submenu_Value,num_string); + + /* isolate the exponent and non-exponent parts */ + strcpy(expon,num_string+5); + num_string[5]=0; + + /* remove the decimal */ + strcpy(num_string+1,num_string+2); + num_string[4]=0; + + /* convert the non-exponent significant digits to an integer */ + if (Submenu_extra_fine==NO) { + num_string[3]='0'; /* go in steps of 10 */ + + /* now select encoder step size */ + if (num_string[0]=='1') { + increment_size=10; + } else if (num_string[0]<'5') { + /* now make sure that we go in steps of 20 - odd numbers can arise after switching out */ + /* of the extra fine mode */ + if (num_string[2]=='1' || num_string[2]=='3' || num_string[2]=='5' || num_string[2]=='7' || num_string[2]=='9' ) { + num_string[2]-=1; + } + increment_size=20; + } else { + /* now make sure that we go in steps of 50 */ + if (num_string[2]<'5') { + num_string[2]='0'; + } else { + num_string[2]='5'; + } + increment_size=50; + } + + equivalent_integer=atoi(num_string); + + /* new number is ... */ + equivalent_integer+=increment_size*encoder_change; + } else { + equivalent_integer=atoi(num_string); + equivalent_integer+=encoder_change; + } + + /* don't let it change too much */ + if (equivalent_integer<1000) { + equivalent_integer=995; + } + if (equivalent_integer>10000) { + equivalent_integer=10100; + } + + /* get first digit of new number */ + new_string[0]=' '; + sprintf(new_string+1, "%d", equivalent_integer); + + /* put in sign if required */ + if (Submenu_Value<0) { + new_string[0]='-'; + } + + sprintf(new_string+2, "%d", equivalent_integer); + new_string[2]='.'; + + /* finish by adding exponent*/ + strcat(new_string,expon); + + new_value=atof(new_string); + if (equivalent_integer>9999) { + new_value*=10; + } + if (equivalent_integer<1000) { + new_value/=10; + } + } + + /* update display - correct later if required */ + Display_Number_on_LCD(YES,1,2,"",Submenu_Numeric_Parameter,4,LCD_col_width,LCD_string); + + 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,LCD_string); + + 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,"8 data bits, no parity, 1 stop bit,"); + LCD_write(2,0,"hardware handshaking on, and echo on."); + LCD_write(3,0,Press_Change_Message); + + globals.RS232.baud = rs232_1200_baud; + globals.RS232.parity = rs232_parity_none; + globals.RS232.stopbits = rs232_1stop_bit; + globals.RS232.databits = rs232_8data_bits; + globals.RS232.hardhand = rs232_hard_on; + globals.RS232.echo = rs232_echo_on; + IO_Setup_RS232(); + + Menu_Clear_Buttons(); + + globals.MenuStatus.Nonstd_Display=YES; +} + + +static void Nonstd_menu_model_info(void) +{ + // FIXME - better string handling + + char response[LCD_cols+1]; + int i; + char model[32]; + char serial_num[16]; + + LCD_clear(); + + i=-1; + do { + ++i; + model[i] = toupper(globals.Flash.model_num[i]); + } while (model[i]); + i=-1; + do { + ++i; + serial_num[i] = toupper(globals.Flash.serial_num[i]); + } while (serial_num[i]); + + /*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,model); + + strcpy(response,"SN:"); + strcat(response,serial_num); + strcat(response,","); + strcat(response,FW_VERSION); + + LCD_write(3,0,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); +} + + +/*** BeginHeader Read_Keypad */ +int Read_Keypad(int *button_port_val, int *upper_encoder_val, int *lower_encoder_val); +/*** EndHeader */ +/*----------------------------------------------------------------------------------------------------------*/ +int 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; + + int chan; + int outputs_turned_off; + + /* 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 */ + outputs_turned_off = 0; + if (globals.Flash.on_off_used) { + 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); + } + } + } +} + + +static void Menu_Check_Buttons(void) +{ + int error_num; + int button_port_val; + int upper_encoder_val; + int lower_encoder_val; + int encoder_change; + int chan; + + /* 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; + } + + if (!(button_port_val & Change_Button)) { /* ----- CHANGE BUTTON --------- */ + if ( globals.control_mode==LOCS_ctrl || globals.control_mode==LWLS_ctrl || + ( + ( globals.control_mode==REMS_ctrl + || globals.control_mode==RS232_ctrl + || globals.control_mode==WEB_ctrl + || globals.control_mode==TELNET_ctrl) + && globals.MenuStatus.Selected_Submenu==Submenu1_rem_loc + ) + ) { + if ((globals.MenuStatus.Type_Of_Menu==Main_Menu_On && globals.MenuStatus.Error_Screen==YES) || globals.MenuStatus.Nonstd_Display==YES) { + Menu_Update_Display(); + } 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) { + 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 && (globals.control_mode==LOCS_ctrl || globals.control_mode==LWLS_ctrl)) { + 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 && (globals.control_mode==LOCS_ctrl || globals.control_mode==LWLS_ctrl)) { + 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 && (globals.control_mode==LOCS_ctrl || globals.control_mode==LWLS_ctrl)) { + 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 && + (globals.control_mode==LOCS_ctrl || globals.control_mode==LWLS_ctrl)) { + 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 check_valid; + int channel,eprom_loc; + + call_new_submenu=NO; + + /* this routine changes the pulse generator parameters, as chosen by the submenu settings */ + + if (Submenu_max_entry==0) { + Menu_Update_Display(); + 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: + Main_return_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: + Nonstd_menu_default_rs232(); + globals.MenuStatus.Selected_Submenu=Submenu1_setup; + 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: + strcpy(globals.Flash.password,"default"); + // FIXME - save password to /etc/shadow here + + eprom_loc = (char *) &(globals.Flash.password) - (char *) &(globals.Flash.flash_start); + writeUserBlock(&globals.Flash, eprom_loc, strlen(globals.Flash.password)+1); + 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: + globals.RS232.baud = rs232_1200_baud; + globals.MenuStatus.Selected_Submenu=Submenu2_rs232_databits; + call_new_submenu=YES; + Submenu_Display(NO); + break; + case mode_2400: + globals.RS232.baud = rs232_2400_baud; + globals.MenuStatus.Selected_Submenu=Submenu2_rs232_databits; + call_new_submenu=YES; + Submenu_Display(NO); + break; + case mode_4800: + globals.RS232.baud = rs232_4800_baud; + globals.MenuStatus.Selected_Submenu=Submenu2_rs232_databits; + call_new_submenu=YES; + Submenu_Display(NO); + break; + case mode_9600: + globals.RS232.baud = rs232_9600_baud; + globals.MenuStatus.Selected_Submenu=Submenu2_rs232_databits; + call_new_submenu=YES; + Submenu_Display(NO); + break; + case mode_7bits: + globals.RS232.databits = rs232_7data_bits; + globals.MenuStatus.Selected_Submenu=Submenu2_rs232_parity; + call_new_submenu=YES; + Submenu_Display(NO); + break; + case mode_8bits: + globals.RS232.databits = rs232_8data_bits; + globals.MenuStatus.Selected_Submenu=Submenu2_rs232_parity; + call_new_submenu=YES; + Submenu_Display(NO); + break; + case mode_par_none: + globals.RS232.parity = rs232_parity_none; + globals.MenuStatus.Selected_Submenu=Submenu2_rs232_stopbits; + call_new_submenu=YES; + Submenu_Display(NO); + break; + case mode_par_odd: + globals.RS232.parity = rs232_parity_odd; + globals.MenuStatus.Selected_Submenu=Submenu2_rs232_stopbits; + call_new_submenu=YES; + Submenu_Display(NO); + break; + case mode_par_even: + globals.RS232.parity = rs232_parity_even; + globals.MenuStatus.Selected_Submenu=Submenu2_rs232_stopbits; + call_new_submenu=YES; + Submenu_Display(NO); + break; + case mode_1bit: + globals.RS232.stopbits = rs232_1stop_bit; + globals.MenuStatus.Selected_Submenu=Submenu2_rs232_hardhand; + call_new_submenu=YES; + Submenu_Display(NO); + break; + case mode_2bits: + globals.RS232.stopbits = rs232_2stop_bits; + globals.MenuStatus.Selected_Submenu=Submenu2_rs232_hardhand; + call_new_submenu=YES; + Submenu_Display(NO); + break; + case mode_hand_hard: + globals.RS232.hardhand = rs232_hard_on; + globals.MenuStatus.Selected_Submenu=Submenu2_rs232_echo; + call_new_submenu=YES; + Submenu_Display(NO); + break; + case mode_hand_off: + globals.RS232.hardhand = rs232_hard_off; + globals.MenuStatus.Selected_Submenu=Submenu2_rs232_echo; + call_new_submenu=YES; + Submenu_Display(NO); + break; + case mode_echo_on: + globals.RS232.echo = rs232_echo_on; + globals.MenuStatus.Selected_Submenu=Submenu1_setup; + break; + case mode_echo_off: + globals.RS232.echo = rs232_echo_off; + globals.MenuStatus.Selected_Submenu=Submenu1_setup; + break; + } + + Main_update_shift_registers(); /* update values in pulse generator circuit */ + + if (call_new_submenu==NO) { + globals.Changes.update_whole_main_menu=YES; + Menu_Update_Display(); + } + + /* 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) +{ + char ip_buf[LCD_cols+1]; + char mac_buf[6]; + char response[LCD_cols+1]; + int i; + char model[32]; + char serial_num[16]; + + LCD_clear(); + /* FIXME - network info + if (globals.Flash.network_enabled==0) { + LCD_write(0,0,"This instrument does not have the"); + LCD_write(1,0,"TCP/IP telnet access networking option"); + LCD_write(2,0,"installed."); + } else { + pd_getaddress(0,mac_buf); + + sprintf(response,"MAC address: %02x:%02x:%02x:%02x:%02x:%02x", + mac_buf[0], mac_buf[1], mac_buf[2], mac_buf[3], mac_buf[4], mac_buf[5]); + LCD_write(0,0,response); + + sprintf(response,"IP address: %s",inet_ntoa(ip_buf,gethostid())); + LCD_write(1,0,response); + } + + LCD_write(3,0,response); + */ + LCD_write(3,0,"Press CHANGE to continue."); + + globals.MenuStatus.Nonstd_Display=YES; +} + @@ -0,0 +1,4 @@ +void Menu_Refresh(); +void Menu_Update_Display(void); +void Menu_Clear_Buttons(void); + |