diff options
Diffstat (limited to 'error_utils.c')
-rw-r--r-- | error_utils.c | 902 |
1 files changed, 902 insertions, 0 deletions
diff --git a/error_utils.c b/error_utils.c index 50a0af8..6f9d85c 100644 --- a/error_utils.c +++ b/error_utils.c @@ -13,9 +13,11 @@ END DESCRIPTION **********************************************************/ #include <string.h> #include <glib/gprintf.h> +#include <math.h> #include "globals.h" #include "dummy_functions.h" #include "lcd.h" +#include "error_utils.h" /*** EndHeader */ @@ -507,3 +509,903 @@ void get_error_text(gchar **response, int error_num) } + +int Error_check(ChannelStruct ChannelStateToTest[max_channels]) +{ + + float max_duty_high_ampl,max_duty_low_ampl,max_duty_this_ampl; + float ampl_fixed_max_duty; + float temp; + float duty_scale; + float duty_cycle; + int report_error; + + int i; + int num_of_chan; + + /* todo: check avrq settings */ + + num_of_chan=globals.Flash.channels; + if (num_of_chan==0) { + num_of_chan=1; + } + + + if (num_of_chan>1) { + if (!globals.Flash.ChanKey_frequency) for (i=1; i<num_of_chan; ++i) { + ChannelStateToTest[i].frequency=ChannelStateToTest[0].frequency; + } + if (!globals.Flash.ChanKey_delay) for (i=1; i<num_of_chan; ++i) { + ChannelStateToTest[i].delay=ChannelStateToTest[0].delay; + } + if (!globals.Flash.ChanKey_pw) for (i=1; i<num_of_chan; ++i) { + ChannelStateToTest[i].pw=ChannelStateToTest[0].pw; + } + if (!globals.Flash.ChanKey_amplitude) for (i=1; i<num_of_chan; ++i) { + ChannelStateToTest[i].amplitude=ChannelStateToTest[0].amplitude; + } + if (!globals.Flash.ChanKey_offset) for (i=1; i<num_of_chan; ++i) { + ChannelStateToTest[i].offset=ChannelStateToTest[0].offset; + } + + if (!globals.Flash.ChanKey_Curr_Mon_value) for (i=1; i<num_of_chan; ++i) { + ChannelStateToTest[i].Curr_Mon_value=ChannelStateToTest[0].Curr_Mon_value; + } + if (!globals.Flash.ChanKey_Curr_Mon_offset) for (i=1; i<num_of_chan; ++i) { + ChannelStateToTest[i].Curr_Mon_offset=ChannelStateToTest[0].Curr_Mon_offset; + } + + if (!globals.Flash.ChanKey_zout) for (i=1; i<num_of_chan; ++i) { + ChannelStateToTest[i].zout=ChannelStateToTest[0].zout; + } + if (!globals.Flash.ChanKey_hold_setting) for (i=1; i<num_of_chan; ++i) { + ChannelStateToTest[i].hold_setting=ChannelStateToTest[0].hold_setting; + } + if (!globals.Flash.ChanKey_double_pulse) for (i=1; i<num_of_chan; ++i) { + ChannelStateToTest[i].double_pulse=ChannelStateToTest[0].double_pulse; + } + if (!globals.Flash.ChanKey_ab_mode) for (i=1; i<num_of_chan; ++i) { + ChannelStateToTest[i].ab_mode=ChannelStateToTest[0].ab_mode; + } + if (!globals.Flash.ChanKey_func_mode) for (i=1; i<num_of_chan; ++i) { + ChannelStateToTest[i].func_mode=ChannelStateToTest[0].func_mode; + } + if (!globals.Flash.ChanKey_polarity) for (i=1; i<num_of_chan; ++i) { + ChannelStateToTest[i].polarity=ChannelStateToTest[0].polarity; + } + if (!globals.Flash.ChanKey_output_state) for (i=1; i<num_of_chan; ++i) { + ChannelStateToTest[i].output_state=ChannelStateToTest[0].output_state; + } + if (!globals.Flash.ChanKey_gate_type) for (i=1; i<num_of_chan; ++i) { + ChannelStateToTest[i].gate_type=ChannelStateToTest[0].gate_type; + } + if (!globals.Flash.ChanKey_trigger_source) for (i=1; i<num_of_chan; ++i) { + ChannelStateToTest[i].trigger_source=ChannelStateToTest[0].trigger_source; + } + if (!globals.Flash.ChanKey_amp_mode) for (i=1; i<num_of_chan; ++i) { + ChannelStateToTest[i].amp_mode=ChannelStateToTest[0].amp_mode; + } + if (!globals.Flash.ChanKey_gate_level) for (i=1; i<num_of_chan; ++i) { + ChannelStateToTest[i].gate_level=ChannelStateToTest[0].gate_level; + } + if (!globals.Flash.ChanKey_load_type) for (i=1; i<num_of_chan; ++i) { + ChannelStateToTest[i].load_type=ChannelStateToTest[0].load_type; + } + if (!globals.Flash.ChanKey_test_delay_mode) for (i=1; i<num_of_chan; ++i) { + ChannelStateToTest[i].test_delay_mode=ChannelStateToTest[0].test_delay_mode; + } + if (!globals.Flash.ChanKey_os_mode) for (i=1; i<num_of_chan; ++i) { + ChannelStateToTest[i].os_mode=ChannelStateToTest[0].os_mode; + } + if (!globals.Flash.ChanKey_Burst_Count) for (i=1; i<num_of_chan; ++i) { + ChannelStateToTest[i].burst_count=ChannelStateToTest[0].burst_count; + } + if (!globals.Flash.ChanKey_Burst_Time) for (i=1; i<num_of_chan; ++i) { + ChannelStateToTest[i].burst_time=ChannelStateToTest[0].burst_time; + } + if (!globals.Flash.ChanKey_rise_time) for (i=1; i<num_of_chan; ++i) { + ChannelStateToTest[i].rise_time=ChannelStateToTest[0].rise_time; + } + if (!globals.Flash.ChanKey_slew) for (i=1; i<num_of_chan; ++i) { + ChannelStateToTest[i].slew=ChannelStateToTest[0].slew; + } + if (!globals.Flash.ChanKey_current_limit) for (i=1; i<num_of_chan; ++i) { + ChannelStateToTest[i].soft_current_limit=ChannelStateToTest[0].soft_current_limit; + } + for (i=1; i<num_of_chan; ++i) { + ChannelStateToTest[i].vcc1=ChannelStateToTest[0].vcc1; + } + for (i=1; i<num_of_chan; ++i) { + ChannelStateToTest[i].vcc2=ChannelStateToTest[0].vcc2; + } + for (i=1; i<num_of_chan; ++i) { + ChannelStateToTest[i].vlogic=ChannelStateToTest[0].vlogic; + } + } + + + report_error=OK; + + for (i=0; i<num_of_chan; ++i) { + /* Must be changing a setting */ + globals.last_activity_at[i] = sec_timer (); + + /* ignore errors if it is in programming mode */ + if (globals.Flash.fully_programmed != All_Programmed) { + return OK; + } + + if (globals.do_check_settings==NO) { + return OK; + } + + /* check for settings that would cause divide-by-zero errors in the error-checking routine */ + if (ChannelStateToTest[i].frequency<smallest_allowed_number) { + return freq_lower_limit; + } + + if (ChannelStateToTest[i].pw<smallest_allowed_number + && globals.Flash.min_pw[i]>0.0) { + return pw_lower_limit; + } + + /* calculate maximum duty cycle based on amplitude and load, for later use */ + + max_duty_high_ampl=globals.Flash.max_duty_high[i]; + max_duty_low_ampl=globals.Flash.max_duty_low[i]; + + /* Choose highest of 4 duty cycles that meet max ampl limits */ + if (globals.Flash.duty_ampl[i]>0.0 && (fabs(ChannelStateToTest[i].amplitude)<= globals.Flash.duty_ampl[i])) { + max_duty_this_ampl=max_duty_low_ampl; + } else { + max_duty_this_ampl=max_duty_high_ampl; + } + + if (globals.Flash.duty_ampl_mid1[i]>0.0 && + (fabs(ChannelStateToTest[i].amplitude)<= globals.Flash.duty_ampl_mid1[i]) && + (globals.Flash.max_duty_mid1[i] > max_duty_this_ampl)) { + max_duty_this_ampl = globals.Flash.max_duty_mid1[i]; + } + + if (globals.Flash.duty_ampl_mid2[i]>0.0 && + (fabs(ChannelStateToTest[i].amplitude)<= globals.Flash.duty_ampl_mid2[i]) && + (globals.Flash.max_duty_mid2[i] > max_duty_this_ampl)) { + max_duty_this_ampl = globals.Flash.max_duty_mid2[i]; + } + + ampl_fixed_max_duty = max_duty_this_ampl; + if (globals.Flash.switchable_load[i]) { + ampl_fixed_max_duty = max_duty_this_ampl * (ChannelStateToTest[i].load_type / globals.Flash.low_load_type[i]); + temp = globals.Flash.max_high_rl_duty[i]; + if (ampl_fixed_max_duty > temp) { + ampl_fixed_max_duty = temp; + } + } + + + /* take burst mode and double-pulse mode into account when setting the maximum duty cycle */ + duty_scale = 100.0; /* convert from percent */ + + if (ChannelStateToTest[i].double_pulse==double_on) { + duty_scale = 200.0; + } + if ( (ChannelStateToTest[i].burst_count>1) + && (globals.Flash.max_burst_count[i]>1) + && !globals.Flash.burst_func[i]) { + duty_scale *= (float) ChannelStateToTest[i].burst_count; + } + + + if (ChannelStateToTest[i].trigger_source==source_internal) { + + /* --- check minimum frequency --- */ + globals.Constraints.err_min_freq[i]=globals.Flash.min_freq[i]; + + if (ChannelStateToTest[i].frequency<(0.999*globals.Constraints.err_min_freq[i])) { + report_error=freq_lower_limit; + } + + if ((ChannelStateToTest[i].polarity!=pol_norm) && (globals.Flash.min_pw[i]>0.0)) { + temp=(1/ChannelStateToTest[i].pw)*( 1.0- ampl_fixed_max_duty/duty_scale ); + if (temp>globals.Constraints.err_min_freq[i]) { + globals.Constraints.err_min_freq[i]=temp; + if (ChannelStateToTest[i].frequency<(0.999*globals.Constraints.err_min_freq[i])) { + report_error=duty_cycle_upper_limit; + } + } + } + + + /* ------------------------------- */ + + /* --- check maximum frequency --- */ + globals.Constraints.err_max_freq[i]=globals.Flash.max_freq[i]; + + if (ChannelStateToTest[i].frequency>(1.001*globals.Constraints.err_max_freq[i])) { + report_error=freq_upper_limit; + } + + if (fabs(ChannelStateToTest[i].delay)>1.0e-15) { + temp=0.95/fabs(ChannelStateToTest[i].delay); + if (temp<globals.Constraints.err_max_freq[i]) { + globals.Constraints.err_max_freq[i]=temp; + if (ChannelStateToTest[i].frequency>(1.001*globals.Constraints.err_max_freq[i])) { + report_error=Delay_Exceeds_95Period; + } + } + } + + if (globals.Flash.min_pw[i] > 0.0) { + temp=1/ChannelStateToTest[i].pw; + if (temp<globals.Constraints.err_max_freq[i]) { + globals.Constraints.err_max_freq[i]=temp; + if (ChannelStateToTest[i].frequency>(1.001*globals.Constraints.err_max_freq[i])) { + report_error=PW_Exceeds_Period; + } + } + + if ( (ChannelStateToTest[i].burst_count>1) + && (globals.Flash.max_burst_count[i]>1) + && !globals.Flash.burst_func[i]) { + temp=1/(ChannelStateToTest[i].burst_count * (ChannelStateToTest[i].pw+ChannelStateToTest[i].burst_time)); + if (temp<globals.Constraints.err_max_freq[i]) { + globals.Constraints.err_max_freq[i]=temp; + if (ChannelStateToTest[i].frequency>(1.001*globals.Constraints.err_max_freq[i])) { + report_error=Burst_Exceeds_Period; + } + } + } + + if (ChannelStateToTest[i].polarity==pol_norm) { + temp=(1/ChannelStateToTest[i].pw)*(ampl_fixed_max_duty/duty_scale); + if (temp<globals.Constraints.err_max_freq[i]) { + globals.Constraints.err_max_freq[i]=temp; + if (ChannelStateToTest[i].frequency>(1.001*globals.Constraints.err_max_freq[i])) { + report_error=duty_cycle_upper_limit; + } + } + } + + if (ChannelStateToTest[i].double_pulse==double_on) { + temp=0.95/(ChannelStateToTest[i].pw+fabs(ChannelStateToTest[i].delay)); + if (temp<globals.Constraints.err_max_freq[i]) { + globals.Constraints.err_max_freq[i]=temp; + if (ChannelStateToTest[i].frequency>(1.001*globals.Constraints.err_max_freq[i])) { + report_error=Double_Separation_Too_Large; + } + } + } + + if ((globals.Flash.max_avg_ampl[i]) > 0.0 && (fabs(ChannelStateToTest[i].amplitude)) > 0.0) { + temp=100.0 * globals.Flash.max_avg_ampl[i] / + (fabs(ChannelStateToTest[i].amplitude) * ChannelStateToTest[i].pw * duty_scale); + if (temp<globals.Constraints.err_max_freq[i]) { + globals.Constraints.err_max_freq[i]=temp; + if (ChannelStateToTest[i].frequency>(1.001*globals.Constraints.err_max_freq[i])) { + report_error=Average_Amplitude_Too_High; + } + } + } + + if (globals.Flash.max_avg_power[i] > 0.0) { + temp = (globals.Flash.max_avg_power[i] * ChannelStateToTest[i].load_type) / (ChannelStateToTest[i].amplitude * ChannelStateToTest[i].amplitude * ChannelStateToTest[i].pw); + if (temp < globals.Constraints.err_max_freq[i]) { + globals.Constraints.err_max_freq[i] = temp; + if (ChannelStateToTest[i].frequency>(1.001*globals.Constraints.err_max_freq[i])) { + report_error=average_power_limit; + } + } + } + + } + + /* ------------------------------- */ + } + + /* --- check minimum pulse width --- */ + globals.Constraints.err_min_pw[i]=globals.Flash.min_pw[i]; + + if ( (globals.Constraints.err_min_pw[i]>=0.0 && ChannelStateToTest[i].pw<(0.999*globals.Constraints.err_min_pw[i])) + || (globals.Constraints.err_min_pw[i]<0.0 && ChannelStateToTest[i].pw<(1.001*globals.Constraints.err_min_pw[i])) ) { + report_error=pw_lower_limit; + } + + /* negative-pw units are special, ignore PRF / duty cycle / PW conflicts */ + if (globals.Constraints.err_min_pw[i]>=0.0) { + if (ChannelStateToTest[i].trigger_source==source_internal) { + if (ChannelStateToTest[i].polarity!=pol_norm) { + temp=(1/ChannelStateToTest[i].frequency)*( 1.0 - ampl_fixed_max_duty/duty_scale ); + if (temp>globals.Constraints.err_min_pw[i]) { + globals.Constraints.err_min_pw[i]=temp; + if (ChannelStateToTest[i].pw<(0.999*globals.Constraints.err_min_pw[i])) { + report_error=duty_cycle_upper_limit; + } + } + } + } + } + + /* ------------------------------- */ + + + /* --- check maximum pw ---------- */ + globals.Constraints.err_max_pw[i]=globals.Flash.max_pw[i]; + + /* polarity overrides */ + if ((ChannelStateToTest[i].amplitude >= 0.0) && (globals.Flash.max_pw_pol[i][0] > 0.0) && (globals.Constraints.err_max_pw[i] > globals.Flash.max_pw_pol[i][0])) { + globals.Constraints.err_max_pw[i] = globals.Flash.max_pw_pol[i][0]; + } else if ((ChannelStateToTest[i].amplitude <0.0) && (globals.Flash.max_pw_pol[i][1] > 0.0) && (globals.Constraints.err_max_pw[i] > globals.Flash.max_pw_pol[i][1])) { + globals.Constraints.err_max_pw[i] = globals.Flash.max_pw_pol[i][1]; + } + + if (ChannelStateToTest[i].pw>(1.001*globals.Constraints.err_max_pw[i])) { + report_error=pw_upper_limit; + } + + if (ChannelStateToTest[i].double_pulse==double_on) { + temp=ChannelStateToTest[i].delay; + if (temp<globals.Constraints.err_max_pw[i]) { + globals.Constraints.err_max_pw[i]=temp; + if (ChannelStateToTest[i].pw>(1.001*globals.Constraints.err_max_pw[i])) { + report_error=PW_Exceeds_Double_Separation; + } + } + } + + if (ChannelStateToTest[i].trigger_source==source_internal) { + temp=1/ChannelStateToTest[i].frequency; + if (temp<globals.Constraints.err_max_pw[i]) { + globals.Constraints.err_max_pw[i]=temp; + if (ChannelStateToTest[i].pw>(1.001*globals.Constraints.err_max_pw[i])) { + report_error=PW_Exceeds_Period; + } + } + + if ( (ChannelStateToTest[i].burst_count>1) + && (globals.Flash.max_burst_count[i]>1) + && !globals.Flash.burst_func[i]) { + temp=(1/ChannelStateToTest[i].frequency)/ChannelStateToTest[i].burst_count - ChannelStateToTest[i].burst_time; + if (temp<globals.Constraints.err_max_pw[i]) { + globals.Constraints.err_max_pw[i]=temp; + if (ChannelStateToTest[i].pw>(1.001*globals.Constraints.err_max_pw[i])) { + report_error=Burst_Exceeds_Period; + } + } + } + + if (ChannelStateToTest[i].polarity==pol_norm) { + temp=(1/ChannelStateToTest[i].frequency)*(ampl_fixed_max_duty/duty_scale); + if (temp<globals.Constraints.err_max_pw[i]) { + globals.Constraints.err_max_pw[i]=temp; + if (ChannelStateToTest[i].pw>(1.001*globals.Constraints.err_max_pw[i])) { + report_error=duty_cycle_upper_limit; + } + } + } + + if (ChannelStateToTest[i].double_pulse==double_on) { + temp=(0.95/ChannelStateToTest[i].frequency)-ChannelStateToTest[i].delay; + if (temp<globals.Constraints.err_max_pw[i]) { + globals.Constraints.err_max_pw[i]=temp; + if (ChannelStateToTest[i].pw>(1.001*globals.Constraints.err_max_pw[i])) { + report_error=Double_Separation_Too_Large; + } + } + } + + if ((globals.Flash.max_avg_ampl[i]) > 0.0 && (fabs(ChannelStateToTest[i].amplitude)) > 0.0) { + temp=100.0 * globals.Flash.max_avg_ampl[i] / + (fabs(ChannelStateToTest[i].amplitude) * ChannelStateToTest[i].frequency * duty_scale); + if (temp<globals.Constraints.err_max_pw[i]) { + globals.Constraints.err_max_pw[i]=temp; + if (ChannelStateToTest[i].pw>(1.001*globals.Constraints.err_max_pw[i])) { + report_error=Average_Amplitude_Too_High; + } + } + } + + if (globals.Flash.max_avg_power[i] > 0.0) { + temp = globals.Flash.max_avg_power[i] * ChannelStateToTest[i].load_type / (ChannelStateToTest[i].amplitude * ChannelStateToTest[i].amplitude * ChannelStateToTest[i].frequency); + if (temp < globals.Constraints.err_max_pw[i]) { + globals.Constraints.err_max_pw[i] = temp; + if (ChannelStateToTest[i].pw>(1.001*globals.Constraints.err_max_pw[i])) { + report_error=average_power_limit; + } + } + } + + } + /* ------------------------------- */ + + /* --- check minimum delay ------- */ + if (globals.Flash.min_delay[i] != 0.0) { + /* use programmed limit, if non-zero */ + globals.Constraints.err_min_delay[i]=globals.Flash.min_delay[i]; + } else { + /* otherwise, assume delay has equal +/- range */ + globals.Constraints.err_min_delay[i]=-globals.Flash.max_delay[i]; + + /* for dual-delay units, positive delay only */ + if ((globals.Flash.ChanKey_delay?globals.Flash.channels:1)>1) { + globals.Constraints.err_min_delay[i]=0.0; + } + } + + if ( (globals.Constraints.err_min_delay[i]>=0.0 && ChannelStateToTest[i].delay<(0.999*globals.Constraints.err_min_delay[i])) + || (globals.Constraints.err_min_delay[i]<0.0 && ChannelStateToTest[i].delay<(1.001*globals.Constraints.err_min_delay[i])) ) { + report_error=delay_lower_limit; + } + + if (ChannelStateToTest[i].trigger_source==source_internal) { + temp=-0.95/ChannelStateToTest[i].frequency; + if (temp>globals.Constraints.err_min_delay[i]) { + globals.Constraints.err_min_delay[i]=temp; + if ( (globals.Constraints.err_min_delay[i]>=0.0 && ChannelStateToTest[i].delay<(0.999*globals.Constraints.err_min_delay[i])) + || (globals.Constraints.err_min_delay[i]<0.0 && ChannelStateToTest[i].delay<(1.001*globals.Constraints.err_min_delay[i])) ) { + report_error=Delay_Exceeds_95Period; + } + } + } + + if (ChannelStateToTest[i].double_pulse==double_on) { + temp=ChannelStateToTest[i].pw; + if (temp>globals.Constraints.err_min_delay[i]) { + globals.Constraints.err_min_delay[i]=temp; + if ( (globals.Constraints.err_min_delay[i]>=0.0 && ChannelStateToTest[i].delay<(0.999*globals.Constraints.err_min_delay[i])) + || (globals.Constraints.err_min_delay[i]<0.0 && ChannelStateToTest[i].delay<(1.001*globals.Constraints.err_min_delay[i])) ) { + report_error=PW_Exceeds_Double_Separation; + } + } + } + /* ------------------------------- */ + + /* --- check maximum delay ------- */ + globals.Constraints.err_max_delay[i]=globals.Flash.max_delay[i]; + + if ( (globals.Constraints.err_max_delay[i]>=0.0 && ChannelStateToTest[i].delay>(1.001*globals.Constraints.err_max_delay[i])) + || (globals.Constraints.err_max_delay[i]<0.0 && ChannelStateToTest[i].delay>(0.999*globals.Constraints.err_max_delay[i])) ) { + report_error=delay_upper_limit; + } + + if (ChannelStateToTest[i].trigger_source==source_internal) { + temp=0.95/ChannelStateToTest[i].frequency; + if (temp<globals.Constraints.err_max_delay[i]) { + globals.Constraints.err_max_delay[i]=temp; + if ( (globals.Constraints.err_max_delay[i]>=0.0 && ChannelStateToTest[i].delay>(1.001*globals.Constraints.err_max_delay[i])) + || (globals.Constraints.err_max_delay[i]<0.0 && ChannelStateToTest[i].delay>(0.999*globals.Constraints.err_max_delay[i])) ) { + report_error=Delay_Exceeds_95Period; + } + } + + if (ChannelStateToTest[i].double_pulse==double_on) { + temp=(0.95/ChannelStateToTest[i].frequency)-ChannelStateToTest[i].pw; + if (temp<globals.Constraints.err_max_delay[i]) { + globals.Constraints.err_max_delay[i]=temp; + if ( (globals.Constraints.err_max_delay[i]>=0.0 && ChannelStateToTest[i].delay>(1.001*globals.Constraints.err_max_delay[i])) + || (globals.Constraints.err_max_delay[i]<0.0 && ChannelStateToTest[i].delay>(0.999*globals.Constraints.err_max_delay[i])) ) { + report_error=Double_Separation_Too_Large; + } + } + } + } + /* ------------------------------- */ + + /* disable amplitude checks if amplitude calibration is in progress */ + if (!globals.extended_ampl_min_max) { + + globals.Constraints.err_max_vcc1[i]=globals.Flash.vcc1_max[i]; + globals.Constraints.err_max_vcc2[i]=globals.Flash.vcc2_max[i]; + globals.Constraints.err_max_vlogic[i]=ChannelStateToTest[0].vcc1; + globals.Constraints.err_min_vcc1[i]=0.0; + globals.Constraints.err_min_vcc2[i]=globals.Flash.vcc2_min[i]; + globals.Constraints.err_min_vlogic[i]=0.0; + if ( ChannelStateToTest[i].vcc1>(1.001*globals.Constraints.err_max_vcc1[i])) { + report_error=amplitude_upper_limit; + } + if ( ChannelStateToTest[i].vcc2>(1.001*globals.Constraints.err_max_vcc2[i])) { + report_error=amplitude_upper_limit; + } + if ( ChannelStateToTest[i].vlogic>(1.001*globals.Constraints.err_max_vlogic[i])) { + report_error=amplitude_upper_limit; + } + if ( ChannelStateToTest[i].vcc1<globals.Constraints.err_min_vcc1[i]) { + report_error=amplitude_lower_limit; + } + if ( ChannelStateToTest[i].vcc2<globals.Constraints.err_min_vcc2[i]) { + report_error=amplitude_lower_limit; + } + if ( ChannelStateToTest[i].vlogic<globals.Constraints.err_min_vlogic[i]) { + report_error=amplitude_lower_limit; + } + + + /* --- check minimum amplitude --- */ + globals.Constraints.err_min_ampl[i]=globals.Flash.min_ampl[i]; + + if ( (globals.Constraints.err_min_ampl[i]>=0.0 && ChannelStateToTest[i].amplitude<(0.999*globals.Constraints.err_min_ampl[i])) + || (globals.Constraints.err_min_ampl[i]<0.0 && ChannelStateToTest[i].amplitude<(1.001*globals.Constraints.err_min_ampl[i])) ) { + report_error=amplitude_lower_limit; + } + + temp=globals.Flash.min_vout[i]-ChannelStateToTest[i].offset; + if (temp>globals.Constraints.err_min_ampl[i]) { + globals.Constraints.err_min_ampl[i]=temp; + if ( (globals.Constraints.err_min_ampl[i]>=0.0 && ChannelStateToTest[i].amplitude<(0.999*globals.Constraints.err_min_ampl[i])) + || (globals.Constraints.err_min_ampl[i]<0.0 && ChannelStateToTest[i].amplitude<(1.001*globals.Constraints.err_min_ampl[i])) ) { + report_error=ampl_plus_os_lower_limit; + } + } + + /* ------------------------------- */ + + + /* --- check intermediate amplitude --- */ + if (globals.Flash.ampl_min_max_only[i]) + + if ( !(fabs(ChannelStateToTest[i].amplitude - globals.Flash.min_ampl[i] ) < globals.Flash.ampl_zero_equiv[i] ) + && + !(fabs(ChannelStateToTest[i].amplitude - globals.Flash.max_ampl[i]) < globals.Flash.ampl_zero_equiv[i] ) + ) + + { + report_error=amplitude_confined_values; + } + /* ------------------------------- */ + + + + /* --- check maximum amplitude --- */ + globals.Constraints.err_max_ampl[i]=globals.Flash.max_ampl[i]; + if ( (globals.Constraints.err_max_ampl[i]>=0.0 && ChannelStateToTest[i].amplitude>(1.001*globals.Constraints.err_max_ampl[i])) + || (globals.Constraints.err_max_ampl[i]<0.0 && ChannelStateToTest[i].amplitude>(0.999*globals.Constraints.err_max_ampl[i])) ) { + report_error=amplitude_upper_limit; + } + + temp = sqrt(globals.Flash.max_peak_power[i] * ChannelStateToTest[i].load_type); + if ((temp > 0.0) && (temp < globals.Constraints.err_max_ampl[i])) { + globals.Constraints.err_max_ampl[i] = temp; + if (-temp > globals.Constraints.err_min_ampl[i]) { + globals.Constraints.err_min_ampl[i] = -temp; + } + + if ((1.001*globals.Constraints.err_max_ampl[i]) < fabs(ChannelStateToTest[i].amplitude)) { + report_error=peak_power_limit; + } + } + + if (ChannelStateToTest[i].trigger_source==source_internal) { + temp = sqrt(globals.Flash.max_avg_power[i] * ChannelStateToTest[i].load_type / (ChannelStateToTest[i].pw * ChannelStateToTest[i].frequency)); + if ((temp > 0.0) && (temp < globals.Constraints.err_max_ampl[i])) { + globals.Constraints.err_max_ampl[i] = temp; + if (-temp > globals.Constraints.err_min_ampl[i]) { + globals.Constraints.err_min_ampl[i] = -temp; + } + + if ((1.001*globals.Constraints.err_max_ampl[i]) < fabs(ChannelStateToTest[i].amplitude)) { + report_error=average_power_limit; + } + } + } + + temp=globals.Flash.max_vout[i]-ChannelStateToTest[i].offset; + if (temp<globals.Constraints.err_max_ampl[i]) { + globals.Constraints.err_max_ampl[i]=temp; + if ( (globals.Constraints.err_max_ampl[i]>=0.0 && ChannelStateToTest[i].amplitude>(1.001*globals.Constraints.err_max_ampl[i])) + || (globals.Constraints.err_max_ampl[i]<0.0 && ChannelStateToTest[i].amplitude>(0.999*globals.Constraints.err_max_ampl[i])) ) { + report_error=ampl_plus_os_upper_limit; + } + } + + if (globals.Flash.min_pw[i] > 0.0) { + /* Check average amplitude */ + if ((globals.Flash.max_avg_ampl[i]) > 0.0 && (fabs(ChannelStateToTest[i].amplitude)) > 0.0) { + temp=100.0 * globals.Flash.max_avg_ampl[i] / (ChannelStateToTest[i].frequency * ChannelStateToTest[i].pw * duty_scale); + if (temp<globals.Constraints.err_max_ampl[i]) { + globals.Constraints.err_max_ampl[i]=temp; + if ( (globals.Constraints.err_max_ampl[i]>=0.0 && ChannelStateToTest[i].amplitude>(1.001*globals.Constraints.err_max_ampl[i])) + || (globals.Constraints.err_max_ampl[i]<0.0 && ChannelStateToTest[i].amplitude>(0.999*globals.Constraints.err_max_ampl[i])) ) { + report_error=Average_Amplitude_Too_High; + } + } + } + + duty_cycle=ChannelStateToTest[i].pw*ChannelStateToTest[i].frequency*100; /* calculate duty cycle */ + if (ChannelStateToTest[i].polarity!=pol_norm) { + duty_cycle=100-duty_cycle; /* account for inversion */ + } + + if (duty_cycle>(100.0*ampl_fixed_max_duty/duty_scale)) + /* set at crossover voltage */ + { + temp=globals.Flash.duty_ampl[i]; + + if (temp<globals.Constraints.err_max_ampl[i]) { + globals.Constraints.err_max_ampl[i]=temp; + if ( ( (globals.Constraints.err_max_ampl[i]>=0.0 && ChannelStateToTest[i].amplitude>(1.001*globals.Constraints.err_max_ampl[i])) + || (globals.Constraints.err_max_ampl[i]<0.0 && ChannelStateToTest[i].amplitude>(0.999*globals.Constraints.err_max_ampl[i])) + ) + && (duty_cycle > 1.001*(100.0*max_duty_high_ampl/duty_scale)) + ) { + report_error=duty_cycle_upper_limit; + } + } + } + + } + + /* ------------------------------- */ + + + if ((globals.Flash.voltage_offset_enabled[i]) || (globals.Flash.current_offset_enabled[i])) { + /* --- check minimum offset ------ */ + globals.Constraints.err_min_offset[i]=globals.Flash.min_offset[i]; + + if ( (globals.Constraints.err_min_offset[i]>=0.0 && ChannelStateToTest[i].offset<(0.999*globals.Constraints.err_min_offset[i])) + || (globals.Constraints.err_min_offset[i]<0.0 && ChannelStateToTest[i].offset<(1.001*globals.Constraints.err_min_offset[i])) ) { + report_error=offset_lower_limit; + } + + temp=globals.Flash.min_vout[i]-ChannelStateToTest[i].amplitude; + if (temp>globals.Constraints.err_min_offset[i]) { + globals.Constraints.err_min_offset[i]=temp; + if ( (globals.Constraints.err_min_offset[i]>=0.0 && ChannelStateToTest[i].offset<(0.999*globals.Constraints.err_min_offset[i])) + || (globals.Constraints.err_min_offset[i]<0.0 && ChannelStateToTest[i].offset<(1.001*globals.Constraints.err_min_offset[i])) ) { + report_error=ampl_plus_os_lower_limit; + } + } + + /* 1011 models: high level of PG-P output must remain positive */ + if (globals.Flash.ampl_coupled_to_os[i]) { + if (ChannelStateToTest[i].amplitude>globals.Flash.ampl_zero_equiv[i]) { + temp=-ChannelStateToTest[i].amplitude; + if (temp>globals.Constraints.err_min_offset[i]) { + globals.Constraints.err_min_offset[i]=temp; + if (ChannelStateToTest[i].offset<=globals.Constraints.err_min_offset[i]) { + report_error=Coupled_OS_Ampl_Error; + } + } + } + } + + + /* ------------------------------- */ + + + /* --- check maximum offset ------ */ + globals.Constraints.err_max_offset[i]=globals.Flash.max_offset[i]; + + if ( (globals.Constraints.err_max_offset[i]>=0.0 && ChannelStateToTest[i].offset>(1.001*globals.Constraints.err_max_offset[i])) + || (globals.Constraints.err_max_offset[i]<0.0 && ChannelStateToTest[i].offset>(0.999*globals.Constraints.err_max_offset[i])) ) { + report_error=offset_upper_limit; + } + + temp=globals.Flash.max_vout[i]-ChannelStateToTest[i].amplitude; + if (temp<globals.Constraints.err_max_offset[i]) { + globals.Constraints.err_max_offset[i]=temp; + if ( (globals.Constraints.err_max_offset[i]>=0.0 && ChannelStateToTest[i].offset>(1.001*globals.Constraints.err_max_offset[i])) + || (globals.Constraints.err_max_offset[i]<0.0 && ChannelStateToTest[i].offset>(0.999*globals.Constraints.err_max_offset[i])) ) { + report_error=ampl_plus_os_upper_limit; + } + } + + /* 1011 models: low level of PG-N output must remain negative */ + if (globals.Flash.ampl_coupled_to_os[i]) { + if (ChannelStateToTest[i].amplitude<-globals.Flash.ampl_zero_equiv[i]) { + temp=-ChannelStateToTest[i].amplitude; + if (temp<globals.Constraints.err_max_offset[i]) { + globals.Constraints.err_max_offset[i]=temp; + if (ChannelStateToTest[i].offset>=globals.Constraints.err_max_offset[i]) { + report_error=Coupled_OS_Ampl_Error; + } + } + } + } + + /* ------------------------------- */ + } + } + + + /* --- check for nonsensical negatives ------ */ + if ( ChannelStateToTest[i].frequency<0.0 + || ((ChannelStateToTest[i].pw<0.0) && (globals.Flash.min_pw[i] > 0.0)) + || ChannelStateToTest[i].zout<0) { + report_error=Negative_Not_Allowed; + } + /* ------------------------------- */ + + + + /* --- check burst count settings --- */ + + if (globals.Flash.max_burst_count[i]>1) { + + /* --- check minimum setting --- */ + if ( (!globals.Flash.burst_func[i] && ChannelStateToTest[i].burst_count<1) + || + (globals.Flash.burst_func[i] && ChannelStateToTest[i].burst_count<0)) { + report_error=IllegalParameter; + } + + /* --- check maximum setting --- */ + + globals.Constraints.err_max_burst_count[i]=globals.Flash.max_burst_count[i]; + + if (ChannelStateToTest[i].burst_count>globals.Constraints.err_max_burst_count[i]) { + report_error=max_burst_count_error; + } + + + if (!globals.Flash.burst_func[i]) { + if (globals.Flash.min_pw[i] > 0.0) { + temp = (ChannelStateToTest[i].frequency * ampl_fixed_max_duty) / + (ChannelStateToTest[i].pw * 100.0); + + if (temp < (float) globals.Constraints.err_max_burst_count[i]) { + globals.Constraints.err_max_burst_count[i] = (int) temp; + if ( (ChannelStateToTest[i].burst_count>globals.Constraints.err_max_burst_count[i]) + && (ChannelStateToTest[i].burst_count>1)) { + report_error=max_burst_count_error; + } + } + + + temp = (1.0/ChannelStateToTest[i].frequency) / + (ChannelStateToTest[i].pw+ChannelStateToTest[i].burst_time); + + if (temp < (float) globals.Constraints.err_max_burst_count[i]) { + globals.Constraints.err_max_burst_count[i] = (int) temp; + if ( (ChannelStateToTest[i].burst_count>globals.Constraints.err_max_burst_count[i]) + && (ChannelStateToTest[i].burst_count>1)) { + report_error=Burst_Exceeds_Period; + } + } + } + + + /* --- check minimum burst gap settings --- */ + + globals.Constraints.err_min_burst_time[i]=globals.Flash.min_burst_gap[i]; + if ( (ChannelStateToTest[i].burst_count>1) + && (ChannelStateToTest[i].burst_time<(0.999*globals.Constraints.err_min_burst_time[i]))) { + report_error=min_burst_gap_error; + } + + + /* --- check minimum burst period settings --- */ + + if (globals.Flash.min_pw[i] > 0.0) { + temp = globals.Flash.min_burst_per[i] - ChannelStateToTest[i].pw; + if (temp > globals.Constraints.err_min_burst_time[i]) { + globals.Constraints.err_min_burst_time[i] = temp; + if ( (ChannelStateToTest[i].burst_count>1) + && (ChannelStateToTest[i].burst_time<(0.999*globals.Constraints.err_min_burst_time[i]))) { + report_error=min_burst_period_error; + } + } + + /* only report error when burst count is > 1, otherwise it gets annoying */ + temp = ChannelStateToTest[i].pw * (100.0/globals.Flash.max_burst_duty[i] - 1.0); + if (temp > globals.Constraints.err_min_burst_time[i]) { + globals.Constraints.err_min_burst_time[i] = temp; + if ( (ChannelStateToTest[i].burst_time<(0.999*globals.Constraints.err_min_burst_time[i])) + && (ChannelStateToTest[i].burst_count>1)) { + report_error=burst_duty_error; + } + } + } + + /* --- check maximum burst gap settings --- */ + + globals.Constraints.err_max_burst_time[i]=globals.Flash.max_burst_gap[i]; + if ( (ChannelStateToTest[i].burst_count>1) + && (ChannelStateToTest[i].burst_time>(1.001*globals.Constraints.err_max_burst_time[i]))) { + report_error=max_burst_gap_error; + } + + } + } + + /* --- check rise time settings --- */ + /* disable amplitude checks if calibration is in progress */ + if (!globals.Flash.fixed_rise_time[i]) + if (!globals.extended_ampl_min_max) { + globals.Constraints.err_min_rise_time[i]=globals.Flash.min_rise_time[i]; + if (ChannelStateToTest[i].rise_time<(0.999*globals.Constraints.err_min_rise_time[i])) { + report_error=min_rise_time_error; + } + + globals.Constraints.err_max_rise_time[i]=globals.Flash.max_rise_time[i]; + if (ChannelStateToTest[i].rise_time>(1.001*globals.Constraints.err_max_rise_time[i])) { + report_error=max_rise_time_error; + } + } + + /* --- check slew settings --- */ + /* disable amplitude checks if calibration is in progress */ + if (globals.Flash.curr_slew[i]) + if (!globals.extended_ampl_min_max) { + globals.Constraints.err_min_slew[i]=globals.Flash.min_slew[i]; + if (ChannelStateToTest[i].slew<(0.999*globals.Constraints.err_min_slew[i])) { + report_error=min_slew_error; + } + + globals.Constraints.err_max_slew[i]=globals.Flash.max_slew[i]; + if (ChannelStateToTest[i].slew>(1.001*globals.Constraints.err_max_slew[i])) { + report_error=max_slew_error; + } + } + + /* --- check resistance settings --- */ + + if (globals.Flash.switchable_load[i]) { + globals.Constraints.err_min_load_type[i]=globals.Flash.low_load_type[i]; + if ((ChannelStateToTest[i].trigger_source==source_internal) && (duty_cycle > max_duty_this_ampl)) { + globals.Constraints.err_min_load_type[i] *= duty_cycle / max_duty_this_ampl; + } + if (ChannelStateToTest[i].load_type<(0.999*globals.Constraints.err_min_load_type[i])) { + report_error=min_load_type_error; + } + } + + if (globals.Flash.max_peak_power[i] > 0.0) { + temp = ChannelStateToTest[i].amplitude * ChannelStateToTest[i].amplitude / globals.Flash.max_peak_power[i]; + if (temp > globals.Constraints.err_min_load_type[i]) { + globals.Constraints.err_min_load_type[i] = temp; + if (ChannelStateToTest[i].load_type<(0.999*globals.Constraints.err_min_load_type[i])) { + report_error=peak_power_limit; + } + } + } + + if (ChannelStateToTest[i].trigger_source==source_internal) { + if (globals.Flash.max_avg_power[i] > 0.0) { + temp = (ChannelStateToTest[i].amplitude * ChannelStateToTest[i].amplitude * ChannelStateToTest[i].pw * ChannelStateToTest[i].frequency) / globals.Flash.max_avg_power[i]; + if (temp > globals.Constraints.err_min_load_type[i]) { + globals.Constraints.err_min_load_type[i] = temp; + if (ChannelStateToTest[i].load_type<(0.999*globals.Constraints.err_min_load_type[i])) { + report_error=average_power_limit; + } + } + } + } + + globals.Constraints.err_max_load_type[i]=1.0*globals.Flash.high_load_type[i]; + if (ChannelStateToTest[i].load_type>(1.001*globals.Constraints.err_max_load_type[i])) { + report_error=max_load_type_error; + } + + /* --- check soft_current_limit settings --- */ + if (globals.Flash.soft_current_limit_enabled[i]) { + globals.Constraints.err_min_soft_current_limit[i]=globals.Flash.min_soft_current_limit[i]; + if (ChannelStateToTest[i].soft_current_limit<(0.999*globals.Constraints.err_min_soft_current_limit[i])) { + report_error=min_soft_current_limit_error; + } + + globals.Constraints.err_max_soft_current_limit[i]=globals.Flash.max_soft_current_limit[i]; + + temp=globals.Flash.current_limit_pulse_mode[i];; + if (temp < globals.Constraints.err_max_soft_current_limit[i]) { + globals.Constraints.err_max_soft_current_limit[i] = temp; + } + + if (ChannelStateToTest[i].func_mode==dc_mode_on) { + temp=globals.Flash.current_limit_dc_mode[i]; + if (temp < globals.Constraints.err_max_soft_current_limit[i]) { + globals.Constraints.err_max_soft_current_limit[i] = temp; + } + } + + if (ChannelStateToTest[i].soft_current_limit>(1.001*globals.Constraints.err_max_soft_current_limit[i])) { + report_error=max_soft_current_limit_error; + } + } + + + /* --- done all per-channel checking ---- */ + } + + return report_error; + +} + |