summaryrefslogtreecommitdiff
path: root/monitor.c
diff options
context:
space:
mode:
Diffstat (limited to 'monitor.c')
-rw-r--r--monitor.c249
1 files changed, 249 insertions, 0 deletions
diff --git a/monitor.c b/monitor.c
new file mode 100644
index 0000000..0fc319a
--- /dev/null
+++ b/monitor.c
@@ -0,0 +1,249 @@
+#include "globals.h"
+#include "i2c.h"
+#include "device-functions.h"
+#include "lcd.h"
+#include "monitor.h"
+#include "error_utils.h"
+#include <glib.h>
+#include <math.h>
+
+
+long monitor_last_forced_trig[max_channels];
+
+
+void I2C_Setup_Monitor();
+void I2C_Setup_Monitor()
+{
+ int i;
+ float new_os;
+ float average_os;
+ float integrated_error;
+ int channel;
+ int total;
+
+ total=0;
+ average_os = 0.0;
+
+ for (channel=0; channel<(globals.Flash.ChanKey_Curr_Mon_value?globals.Flash.channels:1); ++channel)
+ if (globals.Flash.monitor_enabled[channel]) {
+ ++total;
+
+ LCD_clear();
+ LCD_write(0,0,"Nulling Current Monitor ....");
+ /* quiescent */
+ I2C_Write(PCF8574A+Curr_Mon_MSB+channel*4,0xff);
+ I2C_Write(PCF8574A+Curr_Mon_LSB+channel*4,0xff);
+
+ /* remove chip-select */
+ I2C_Write(PCF8574A+Curr_Mon_MSB+channel*4,0xbf);
+ /* pulse CAL line low */
+ I2C_Write(PCF8574A+Curr_Mon_MSB+channel*4,0x9f);
+ I2C_Write(PCF8574A+Curr_Mon_MSB+channel*4,0xbf);
+
+ for(i=0; i<50; i++);
+ /* quiescent */
+ I2C_Write(PCF8574A+Curr_Mon_MSB+channel*4,0xff);
+
+
+ /* wait for monitor output to become stable */
+ g_usleep(1e6);
+ do {
+ globals.ChannelState[channel].Curr_Mon_offset=0;
+ integrated_error=0;
+
+ /* repeat until stable for 50 iterations */
+ int j=0;
+ while (j<50) {
+ g_usleep(1e4);
+
+ /* pulse S/H line low for initial sample of monitor */
+ I2C_Write(PCF8574A+Curr_Mon_MSB+channel*4,0x7f);
+ for (i=0; i<100; ++i) {
+ ;
+ }
+ /* quiescent */
+ I2C_Write(PCF8574A+Curr_Mon_MSB+channel*4,0xff);
+
+ /* inactive, weak pull-up mode */
+ I2C_Read(PCF8574A+Curr_Mon_MSB+channel*4);
+
+ new_os = 1.0 * I2C_Get_Monitor_Word(channel);
+ average_os = (average_os*j+new_os) / (j+1.0);
+ integrated_error += (average_os-new_os);
+
+ if ( fabs(new_os-average_os) < 300.0) {
+ ++j;
+ } else {
+ j=0;
+ }
+ }
+ } while (fabs(integrated_error) > 25.0);
+
+ globals.ChannelState[channel].Curr_Mon_offset=(int) average_os;
+
+ LCD_write(0,0,"Current Monitor is now ready.");
+ }
+
+ if (total) {
+ I2C_Check_Monitors();
+ }
+
+ return;
+}
+
+
+void force_monitor_cal(int channel, int do_calibration);
+void force_monitor_cal(int channel, int do_calibration)
+{
+ if (do_calibration) {
+ /* quiescent */
+ I2C_Write(PCF8574A+Curr_Mon_MSB+channel*4,0xff);
+ I2C_Write(PCF8574A+Curr_Mon_LSB+channel*4,0xff);
+
+ /* remove chip-select */
+ I2C_Write(PCF8574A+Curr_Mon_MSB+channel*4,0xbf);
+
+ /* pulse CAL line low */
+ I2C_Write(PCF8574A+Curr_Mon_MSB+channel*4,0x9f);
+ I2C_Write(PCF8574A+Curr_Mon_MSB+channel*4,0xbf);
+
+ g_usleep(2e3);
+ }
+
+ /* pulse trigger line low and remove chip-select to force an A/D conversion */
+ I2C_Write(PCF8574A+Curr_Mon_MSB+channel*4,0x3f);
+
+ /* quiescent */
+ I2C_Write(PCF8574A+Curr_Mon_MSB+channel*4,0xff);
+}
+
+
+int I2C_Get_Monitor_Word(int channel);
+int I2C_Get_Monitor_Word(int channel)
+{
+ int monitor_word;
+
+ /* remove chip-select, so that the value doesn't change while read */
+ I2C_Write(PCF8574A+Curr_Mon_MSB+channel*4,0xbf);
+
+ monitor_word=((I2C_Read(PCF8574A+Curr_Mon_MSB+channel*4) & 0x1f)<<8)
+ + I2C_Read(PCF8574A+Curr_Mon_LSB+channel*4);
+
+ /* restore chip-select */
+ I2C_Write(PCF8574A+Curr_Mon_MSB+channel*4,0xff);
+
+ /* PCB 116B and earlier had 13-bit ADC, PCB 116C has 12 bit. */
+ if (globals.Flash.pcb116c_mon == 1) {
+ monitor_word = (monitor_word & 0x0fff) << 1;
+ }
+
+ /* deal with sign bit */
+ if (monitor_word & 0x1000) {
+ monitor_word=-( ((~monitor_word)+1) & 0x0fff);
+ }
+
+ monitor_word*=-1;
+
+ monitor_word-=globals.ChannelState[channel].Curr_Mon_offset;
+
+ return monitor_word;
+}
+
+
+
+int I2C_Check_Monitors(void);
+int I2C_Check_Monitors(void)
+{
+ int monitor_word;
+ float step_size;
+ int channel;
+ int ampl_range,point_found,UseNegData,entry,word_out;
+
+ int update_display;
+ int use_neg_data;
+ int actual_pol;
+ int i;
+ int error_num;
+ long timer_check;
+
+ long seconds_since_last;
+
+ update_display=0;
+
+
+ for (channel=0; channel<(globals.Flash.ChanKey_Curr_Mon_value?globals.Flash.channels:1); ++channel) {
+ timer_check = sec_timer();
+ seconds_since_last = timer_check - monitor_last_forced_trig[channel];
+
+ if (seconds_since_last > 0) {
+ if ( (globals.ChannelState[channel].func_mode==dc_mode_on)
+ || (globals.ChannelState[channel].output_state==output_off)) {
+ /* force monitor measurement every second in DC mode (because no TTL
+ trigger is present) and output-off mode */
+ force_monitor_cal(channel,NO);
+ }
+ monitor_last_forced_trig[channel]=timer_check;
+ }
+
+ if (globals.Flash.sep_posneg_mon_ratio[channel] && globals.ChannelState[channel].amplitude<0.0) {
+ use_neg_data=1;
+ } else {
+ use_neg_data=0;
+ }
+
+ monitor_word=I2C_Get_Monitor_Word(channel);
+
+ /* determine current ampl_range */
+ Set_VI_Control(pwl_ampl_values,channel,globals.ChannelState[channel].amplitude,&point_found,
+ &ampl_range,&UseNegData,&entry,&word_out,&actual_pol);
+
+ /* 5.0V is the full-scale voltage of the 12bit ADC */
+ globals.ChannelState[channel].Curr_Mon_value=((((float) monitor_word)/4095.0) * 5.0)
+ / globals.Flash.mon_vi_ratio[channel][ampl_range][use_neg_data];
+
+ /* convert to even step size */
+ step_size=globals.Flash.monitor_step[channel];
+ globals.ChannelState[channel].Curr_Mon_value=
+ ((float)
+ ((long) (globals.ChannelState[channel].Curr_Mon_value/step_size))
+ )
+ * step_size;
+
+ /* AVO-8D2: check for duty cycle problems, as a function of measured amplitude */
+ if ( globals.Flash.hard_current_limit_enabled[channel] &&
+ (globals.ChannelState[channel].output_state == output_on)) {
+ for (i=0; i<max_channels; ++i) {
+ TestState[i]=globals.ChannelState[i];
+ }
+ TestState[channel].amplitude=globals.ChannelState[channel].Curr_Mon_value;
+ if ((error_num=Error_check(TestState))) {
+ Set_Output_State(channel,output_off);
+ queue_and_broadcast_sensor_alarm(error_num);
+ }
+ }
+
+ if (globals.Flash.soft_current_limit_enabled[channel] &&
+ (globals.Flash.fully_programmed != Being_Programmed) &&
+ (globals.ChannelState[channel].Curr_Mon_value > globals.ChannelState[channel].soft_current_limit)) {
+ Set_Output_State(channel,output_off);
+ queue_and_broadcast_sensor_alarm(Soft_Limit_Exceeded);
+ }
+ // FIXME - menus
+// else if (Type_Of_Menu==Main_Menu_On && Error_Screen==NO && Nonstd_Display==NO
+// && globals.ChannelState[channel].Curr_Mon_value!=globals.ChannelState[channel].displayed_mon_val
+// && (seconds_since_last > 0))
+// /* only update display once a second */
+// {
+// ++update_display;
+// }
+
+ }
+
+// FIXME - menus
+// if (update_display) {
+// Menu_Update_Display();
+// }
+
+ return OK;
+}
+