void reset_hardware_trip() { if (!trip_disable) { write_adc(REG_IOCONTROL, (1 << 4)); // P1DIR=1,P1DAT=0 write_adc(REG_IOCONTROL, (1 << 4) | (1 << 0)); // P1DIR=1,P1DAT=1 } }
unsigned char adc_read(unsigned char channel, float *value) { unsigned long xdata d, start_time; unsigned char xdata i; /* start conversion */ channel = adc_index[channel % (N_HV_CHN*2)]; write_adc(REG_CONTROL, channel << 4 | 0x0F); // adc_chn, +2.56V range write_adc(REG_MODE, (1<<4) | (1<<1)); // single conversion, 10 channel mode start_time = time(); while (ADC_NRDY) { yield(); for (i=0 ; i<N_HV_CHN ; i++) ramp_hv(i); // do ramping while reading ADC /* abort if no ADC ready after 300ms */ if (time() - start_time > 30) { reset_adc(); return 0; } } read_adc24(REG_ADCDATA, &d); /* convert to volts */ *value = ((float)d / (1l<<24)) * 2.56; /* round result to 6 digits */ *value = floor(*value*1E6+0.5)/1E6; return 1; }
void reset_adc() { ADC_NRES = 0; delay_us(OPT_DELAY); ADC_NRES = 1; delay_us(OPT_DELAY); write_adc(REG_FILTER, ADC_SF_VALUE); #ifndef HARDWARE_TRIP /* disable hardware trip FF's */ write_adc(REG_IOCONTROL, (1 << 4)); #endif }
void adc_read() { unsigned char i; unsigned long value; float gvalue; if (ADC_NRDY) return; read_adc24(REG_ADCDATA, &value); /* convert to volts */ gvalue = ((float)value / (1l<<24)) * 2.56; /* round result to 5 digits */ gvalue = floor(gvalue*1E5+0.5)/1E5; /* apply range */ if (user_data.adc_25 == 0) { if (user_data.uni_adc) gvalue *= 10.0/2.56; else gvalue = gvalue/2.56*20.0 - 10; } DISABLE_INTERRUPTS; user_data.adc[adc_chn] = gvalue; ENABLE_INTERRUPTS; /* start next conversion */ adc_chn = (adc_chn + 1) % 8; i = adc_index[adc_chn]; write_adc(REG_CONTROL, i << 4 | 0x0F); // adc_chn, +2.56V range }
void set_current_limit(float value) { #ifdef HARDWARE_TRIP unsigned short d; if (value == 9999) { /* disable current trip */ d = 65535; trip_disable = 1; write_adc(REG_IOCONTROL, (1 << 4)); // P1DIR=1,P1DAT=0 } else { /* remove reset */ trip_disable = 0; write_adc(REG_IOCONTROL, (1 << 4) | (1 << 0)); // P1DIR=1,P1DAT=1 /* "inverse" calibration */ value /= user_data[0].cur_gain; value += user_data[0].cur_offset; /* omit cur_vgain calibration, because statistical mean of unbalanced dividers is zero */ if (value < 0) value = 0; /* convert current to voltage */ value = value / DIVIDER * CUR_MULT * RCURR / 1E6; /* convert to DAC units */ d = (unsigned short) ((value / 2.5 * 65535) + 0.5); } /* write current dac */ write_dac(5, d); #else // HARDWARE_TRIP if (value == 9999) trip_disable = 1; else trip_disable = 0; #endif // !HARDWARE_TRIP }
unsigned char adc_read(unsigned char channel, float *value) { unsigned long d, start_time; unsigned char i; /* start conversion */ channel = adc_index[channel % 8]; write_adc(REG_CONTROL, channel << 4 | 0x0F); // adc_chn, +2.56V range write_adc(REG_MODE, 2); // single conversion start_time = time(); while (ADC_NRDY) { yield(); for (i=0 ; i<N_HV_CHN ; i++) ramp_hv(i); // do ramping while reading ADC /* abort if no ADC ready after 300ms */ if (time() - start_time > 30) { /* reset ADC */ ADC_NRES = 0; delay_ms(100); ADC_NRES = 1; delay_ms(300); write_adc(REG_FILTER, ADC_SF_VALUE); return 0; } } read_adc24(REG_ADCDATA, &d); /* convert to volts */ *value = ((float)d / (1l<<24)) * 2.56; /* round result to 6 digits */ *value = floor(*value*1E6+0.5)/1E6; return 1; }
void adc_calib() { unsigned char i; for (i=0 ; i<8 ; i++) { write_adc(REG_CONTROL, i << 4 | 0x0F); /* zero calibration */ write_adc(REG_MODE, 4); while (ADC_NRDY) led_blink(1, 1, 100); /* full scale calibration */ write_adc(REG_MODE, 5); while (ADC_NRDY) led_blink(1, 1, 100); } /* restart continuous conversion */ write_adc(REG_MODE, 3); }
unsigned char hardware_current_trip(unsigned char channel) { unsigned char d; /* continuously set FF reset, in case ADC got HV flash */ if (trip_disable) { write_adc(REG_IOCONTROL, (1 << 4)); // P1DIR=1,P1DAT=0 return 0; } /* do not check if reset in progres */ if (trip_reset) return 0; read_adc8(REG_IOCONTROL, &d); /* P2 of AD7718 should be low in case of trip */ if ((d & 2) > 0) return 0; if (user_data[channel].adc_gain == 1) { /* uncalibrated */ if (user_data[channel].u_meas < 100 && user_data[channel].u_demand > 150) return 1; return 0; } else { /* calibrated */ if (user_data[channel].u_meas < 5 && user_data[channel].u_demand >= 5) return 1; return 0; } return 0; }
void user_init(unsigned char init) { unsigned char i; unsigned short address; /* all output open drain */ P1MDOUT = 0x00; P2MDOUT = 0x00; /* initial nonzero EEPROM values */ if (init) { memset(user_data, 0, sizeof(user_data)); for (i=0 ; i<N_HV_CHN ; i++) { user_data[i].ramp_up = 300; user_data[i].ramp_down = 300; user_data[i].u_limit = MAX_VOLTAGE; user_data[i].i_limit = MAX_CURRENT; user_data[i].ri_limit = MAX_CURRENT; user_data[i].trip_time = 10; user_data[i].adc_gain = 1; user_data[i].dac_gain = 1; user_data[i].cur_gain = 1; } } /* default control register */ for (i=0 ; i<N_HV_CHN ; i++) { user_data[i].control = CONTROL_REGULATION; user_data[i].status = 0; user_data[i].u_demand = 0; user_data[i].trip_cnt = 0; /* check maximum ratings */ if (user_data[i].u_limit > MAX_VOLTAGE) user_data[i].u_limit = MAX_VOLTAGE; if (user_data[i].i_limit > MAX_CURRENT && user_data[i].i_limit != 9999) user_data[i].i_limit = MAX_CURRENT; u_actual[i] = 0; t_ramp[i] = time(); } /* jumper and address bits as input */ JU1 = 1; JU2 = 1; SW1 = 1; SW2 = 1; GA_A0 = 1; GA_A1 = 1; GA_A2 = 1; GA_A3 = 1; GA_A4 = 1; GA_A5 = 1; /* read six address bits */ address = GA_A5; address = (address << 1) | GA_A4; address = (address << 1) | GA_A3; address = (address << 1) | GA_A2; address = (address << 1) | GA_A1; address = (address << 1) | GA_A0; /* each device has 5 channels */ address *= 5; /* keep high byte of node address */ address |= (sys_info.node_addr & 0xFF00); sys_info.node_addr = address; /* set default group address */ if (sys_info.group_addr == 0xFFFF) sys_info.group_addr = 500; /* sample initial state of switch */ old_sw1 = SW1; if (old_sw1) for (i=0 ; i<N_HV_CHN ; i++) user_data[i].status |= STATUS_DISABLED; /* set-up DAC & ADC */ DAC_CLR = 1; ADC_NRES = 1; ADC_NRDY = 1; // input ADC_DIN = 1; // input delay_ms(300); // wait for the ADC to come up after power on reset_adc(); #ifdef HARDWARE_TRIP /* reset current trip FF's */ reset_hardware_trip(); #else /* disable hardware trip FF's */ write_adc(REG_IOCONTROL, (1 << 4)); #endif /* force update */ for (i=0 ; i<N_HV_CHN ; i++) chn_bits[i] = DEMAND_CHANGED | CUR_LIMIT_CHANGED; /* LED normally off (inverted) */ for (i=0 ; i<N_HV_CHN ; i++) led_mode(i, 1); /* initially, trips are enabled */ trip_reset = 1; // reset once trip_disable = 0; // trip initially enabled for (i=0 ; i<N_HV_CHN ; i++) trip_time[i] = 0; }
void user_init(unsigned char init) { unsigned char i; P2MDOUT = 0xF0; // P2.4-7: enable Push/Pull for LEDs P3MDOUT = 0; /* initial nonzero EEPROM values */ if (init) { memset(user_data, 0, sizeof(user_data)); for (i=0 ; i<N_HV_CHN ; i++) { user_data[i].ramp_up = 300; user_data[i].ramp_down = 300; user_data[i].u_limit = MAX_VOLTAGE; user_data[i].i_limit = MAX_CURRENT; user_data[i].ri_limit = MAX_CURRENT; user_data[i].trip_time = 10; user_data[i].adc_gain = 1; user_data[i].dac_gain = 1; user_data[i].cur_gain = 1; } } /* default control register */ for (i=0 ; i<N_HV_CHN ; i++) { user_data[i].control = CONTROL_REGULATION; user_data[i].status = 0; user_data[i].u_demand = 0; user_data[i].trip_cnt = 0; /* check maximum ratings */ if (user_data[i].u_limit > MAX_VOLTAGE) user_data[i].u_limit = MAX_VOLTAGE; if (user_data[i].i_limit > MAX_CURRENT && user_data[i].i_limit != 9999) user_data[i].i_limit = MAX_CURRENT; u_actual[i] = 0; t_ramp[i] = time(); } /* set default group address */ if (sys_info.group_addr == 0xFFFF) sys_info.group_addr = 400; /* jumper as input */ JU0 = 1; JU1 = 1; JU2 = 1; /* read node configuration */ for (i=0 ; i<N_HV_CHN ; i++) { if (JU0 == 0) user_data[i].status |= STATUS_NEGATIVE; else user_data[i].status &= ~STATUS_NEGATIVE; if (JU1 == 0) user_data[i].status |= STATUS_LOWCUR; else user_data[i].status &= ~STATUS_LOWCUR; } /* set-up DAC & ADC */ DAC_CLR = 1; ADC_NRES = 1; ADC_NRDY = 1; // input ADC_DIN = 1; // input /* reset and wait for start-up of ADC */ ADC_NRES = 0; delay_ms(100); ADC_NRES = 1; delay_ms(300); write_adc(REG_FILTER, ADC_SF_VALUE); /* force update */ for (i=0 ; i<N_HV_CHN ; i++) chn_bits[i] = DEMAND_CHANGED | CUR_LIMIT_CHANGED; /* LED normally off (inverted) */ for (i=0 ; i<N_HV_CHN ; i++) led_mode(i, 1); for (i=0 ; i<N_HV_CHN ; i++) trip_time[i] = 0; }
void user_init(unsigned char init) { unsigned char i; unsigned short value; /* configure crossbar */ SFRPAGE = CONFIG_PAGE; XBR0 = 0x04; // Enable UART0 XBR1 = 0x14; // Enable INT0 and INT1 XBR2 = 0x40; // Enable crossbar /* enable external interrupts */ SFRPAGE = TIMER01_PAGE; PX0 = 1; // INT0 high priority PX1 = 1; // INT1 high priority IT0 = 1; // INT0 is edge sensitive IT1 = 1; // INT1 is edge sensitive IE0 = 0; // Clear pending INT0 IE1 = 0; // Clear pending INT1 EX0 = 0; // INTs will be enabled EX1 = 0; // later in hv_on() SFRPAGE = CONFIG_PAGE; P0MDOUT = 0x11; // P0.0: TX = Push Pull, P0.4: WD P1MDOUT = 0x00; // all open drain P2MDOUT = 0x60; // P2.5/6: HV_POWER P3MDOUT = 0x00; /* initial nonzero EEPROM values */ if (init) { for (i=0 ; i<N_HV_CHN ; i++) { user_data[i].u_demand = 0; user_data[i].trip_cnt = 0; user_data[i].ramp_up = 100; user_data[i].ramp_down = 100; user_data[i].u_limit = MAX_VOLTAGE; user_data[i].i_limit = MAX_CURRENT; user_data[i].ri_limit = MAX_CURRENT; user_data[i].trip_max = 0; user_data[i].trip_time = 10; user_data[i].adc_gain = 1; user_data[i].adc_offset = 0; user_data[i].dac_gain = 1; user_data[i].dac_offset = 0; user_data[i].cur_vgain = 0; user_data[i].cur_gain = 1; user_data[i].cur_offset = 0; } } /* default control register */ for (i=0 ; i<N_HV_CHN ; i++) { user_data[i].control = CONTROL_REGULATION; user_data[i].status = 0; user_data[i].u_demand = 0; user_data[i].trip_cnt = 0; /* check maximum ratings */ if (user_data[i].u_limit > MAX_VOLTAGE) user_data[i].u_limit = MAX_VOLTAGE; if (user_data[i].i_limit > MAX_CURRENT && user_data[i].i_limit != 9999) user_data[i].i_limit = MAX_CURRENT; if (user_data[i].ri_limit > MAX_CURRENT) user_data[i].ri_limit = MAX_CURRENT; u_actual[i] = 0; t_ramp[i] = time(); /* read pos/neg jumper */ JU1 = 1; if (JU1 == 0) user_data[i].status |= STATUS_NEGATIVE; else user_data[i].status &= ~STATUS_NEGATIVE; user_data[i].status |= STATUS_LOWCUR; } /* switch off HVs */ hv_on(0, 0); hv_on(1, 0); /* HV power reset */ HV1_POWER = 0; HV2_POWER = 0; delay_ms(400); HV1_POWER = 1; HV2_POWER = 1; /* set default group address */ if (sys_info.group_addr == 0xFFFF) sys_info.group_addr = 200; /* get address from crate backplane read through internal ADC */ SFRPAGE = LEGACY_PAGE; REF0CN = 0x03; // use internal voltage reference AMX0CF = 0x00; // select single ended analog inputs ADC0CF = 0x98; // ADC Clk 2.5 MHz @ 98 MHz, gain 1 ADC0CN = 0x80; // enable ADC SFRPAGE = ADC0_PAGE; sys_info.node_addr = 0; for (i=0 ; i<7 ; i++) { AMX0SL = i; // set multiplexer delay_ms(10); // wait for settling time DISABLE_INTERRUPTS; AD0INT = 0; AD0BUSY = 1; while (!AD0INT); // wait until conversion ready ENABLE_INTERRUPTS; value = ADC0L | (ADC0H << 8); if (value > 1000) sys_info.node_addr |= (1 << i); } /* each unit contains two addresses */ sys_info.node_addr <<= 1; /* set-up DAC & ADC */ ADC_NRDY = 1; // input ADC_DIN = 1; // input ADC_NRES = 1; // remove reset DAC_NCLR = 1; // remove clear write_adc(REG_FILTER, ADC_SF_VALUE); /* force update */ for (i=0 ; i<N_HV_CHN ; i++) chn_bits[i] = DEMAND_CHANGED | CUR_LIMIT_CHANGED; /* LED normally off (inverted) */ for (i=0 ; i<N_HV_CHN ; i++) led_mode(i, 1); /* initially, trips are enabled */ trip_enable(0, 1); trip_enable(0, 2); trip0 = trip1 = 0; trip0_reset = trip1_reset = 0; trip_change[0] = trip_change[1] = 0; trip_time[0] = trip_time[1] = 0; }
void user_init(unsigned char init) { unsigned char i; ADC0CN = 0x00; // disable ADC DAC0CN = 0x00; // disable DAC0 DAC1CN = 0x00; // disable DAC1 REF0CN = 0x00; // disenable internal reference /* push-pull: P0.0 TX P0.1 P0.2 SW_ADC P0.3 DAC_NCS P0.4 DAC_SCK P0.5 DAC_DIN P0.6 P0.7 DAC_CLR */ PRT0CF = 0xBD; P0 = 0xFF; /* push-pull: P1.0 SW_DAC P1.1 P1.2 ADC_NRES P1.3 ADC_SCLK P1.4 ADC_NCS P1.5 P1.6 P1.7 ADC_DIN */ PRT1CF = 0x9D; P1 = 0xFF; /* initial EEPROM value */ if (init) { for (i = 0; i < 8; i++) user_data.dac[i] = 0; } /* set-up DAC & ADC */ DAC_CLR = 1; ADC_NRES = 1; write_adc(REG_FILTER, 82); // SF value for 50Hz rejection write_adc(REG_MODE, 3); // continuous conversion write_adc(REG_CONTROL, adc_chn << 4 | 0x0F); // Chn. 1, +2.56V range /* write DACs and UNI_BIP */ for (i=0 ; i<8 ; i++) user_write(i+8); user_write(16); /* swich unipolar/bipolar */ user_data.uni_dac = 0; user_data.uni_adc = 0; user_data.adc_25 = 0; UNI_DAC = user_data.uni_dac; UNI_ADC = !user_data.uni_adc; }