summaryrefslogtreecommitdiff
path: root/error_utils.c
diff options
context:
space:
mode:
authorMichael J. Chudobiak <mjc@avtechpulse.com>2012-08-23 14:49:16 -0400
committerMichael J. Chudobiak <mjc@avtechpulse.com>2012-08-23 14:49:16 -0400
commit8ca8f7fbf06ac9ce5f2817e31d6bae330f243aa1 (patch)
treec4c5f0f70234d8dc3a6e3fc4995af0053e144035 /error_utils.c
parent913fc3cf402788ec671102f76ad27dc9436be6f6 (diff)
added full error checker
Diffstat (limited to 'error_utils.c')
-rw-r--r--error_utils.c902
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;
+
+}
+