diff options
-rw-r--r-- | CMakeLists.txt | 1 | ||||
-rw-r--r-- | error_utils.c | 4 | ||||
-rw-r--r-- | error_utils.h | 1 | ||||
-rw-r--r-- | instr-daemon.c | 3 | ||||
-rw-r--r-- | monitor.c | 249 | ||||
-rw-r--r-- | monitor.h | 13 |
6 files changed, 267 insertions, 4 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt index d14929f..7ee6e81 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -20,6 +20,7 @@ add_executable(instr-daemon instr-daemon.c flash.c nicutils.c bus.c + monitor.c dummy_functions.c ) add_executable(instr-client instr-client.c) diff --git a/error_utils.c b/error_utils.c index 37908e7..a0c694d 100644 --- a/error_utils.c +++ b/error_utils.c @@ -141,9 +141,7 @@ void queue_error_and_display_on_LCD(int error_num) } -void queue_and_broadcast_sensor_alarm(int error_num); - -void queue_and_broadcast_sensor_alarm(int error_num) +void queue_and_broadcast_sensor_alarm(int error_num) // FIXME - implement { // not part of this project, but left in for coder's reference. Can be deleted for now } diff --git a/error_utils.h b/error_utils.h index 3153c0a..33f2448 100644 --- a/error_utils.h +++ b/error_utils.h @@ -9,5 +9,6 @@ void queue_error_from_parser(gchar** response, int error_num); void queue_error_and_get_text(gchar** response, int error_num); void Error_Remove_From_Queue(void); int Error_check(ChannelStruct ChannelStateToTest[max_channels]); +void queue_and_broadcast_sensor_alarm(int error_num); #endif diff --git a/instr-daemon.c b/instr-daemon.c index 4de0c95..329addc 100644 --- a/instr-daemon.c +++ b/instr-daemon.c @@ -6,6 +6,7 @@ #include "bus.h" #include "device-functions.h" #include "nicutils.h" +#include "monitor.h" #include <stdlib.h> #include <ctype.h> #include <glib.h> @@ -278,7 +279,7 @@ int main(int argc, char **argv) bus_init(); - // FIXME - I2C_Setup_Monitor(); + I2C_Setup_Monitor(); Main_Rst(); 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, + &l_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; +} + diff --git a/monitor.h b/monitor.h new file mode 100644 index 0000000..9114a84 --- /dev/null +++ b/monitor.h @@ -0,0 +1,13 @@ +#ifndef MONITOR_H_ +#define MONITOR_H_ + +#include <stdlib.h> + + +void I2C_Setup_Monitor(); +void force_monitor_cal(int channel, int do_calibration); +int I2C_Get_Monitor_Word(int channel); +int I2C_Check_Monitors(void); + + +#endif |