From cae8f8d9e1b443f67c6db6acf69985c16aa91f99 Mon Sep 17 00:00:00 2001 From: Frank Mori Hess Date: Sat, 19 Apr 2003 04:56:05 +0000 Subject: [PATCH] added analog output calibration for measurement computing 60xx series --- comedi_calibrate/calib.h | 3 +- comedi_calibrate/cb.c | 222 +++++++++++++++++++++++----- comedi_calibrate/comedi_calibrate.c | 65 ++++---- 3 files changed, 213 insertions(+), 77 deletions(-) diff --git a/comedi_calibrate/calib.h b/comedi_calibrate/calib.h index 39c1afa..b3888af 100644 --- a/comedi_calibrate/calib.h +++ b/comedi_calibrate/calib.h @@ -83,6 +83,7 @@ void observe( calibration_setup_t *setup ); int preobserve( calibration_setup_t *setup, int obs); void observable_dependence( calibration_setup_t *setup, int obs); void measure_observable( calibration_setup_t *setup, int obs); +void reset_caldac( calibration_setup_t *setup, unsigned int caldac_index ); void reset_caldacs( calibration_setup_t *setup); /* drivers */ @@ -96,7 +97,7 @@ int cb_setup( calibration_setup_t*, const char *device_name ); /* low level */ void set_target( calibration_setup_t *setup, int obs,double target); -void update_caldac( calibration_setup_t *setup, unsigned int caldac_index ); +void update_caldac( calibration_setup_t *setup, unsigned int caldac_index, int value ); void setup_caldacs( calibration_setup_t *setup, int caldac_subdev); void postgain_cal( calibration_setup_t *setup, int obs1, int obs2, int dac); void cal1( calibration_setup_t *setup, int obs, int dac); diff --git a/comedi_calibrate/cb.c b/comedi_calibrate/cb.c index 8cebc25..71c2911 100644 --- a/comedi_calibrate/cb.c +++ b/comedi_calibrate/cb.c @@ -269,16 +269,38 @@ int init_observables_64xx( calibration_setup_t *setup ) return 0; } -unsigned int high_observable_index_60xx( unsigned int ai_range ) +unsigned int ai_high_observable_index_60xx( unsigned int ai_range ) { return ai_range * 2 + 1; } -unsigned int ground_observable_index_60xx( unsigned int ai_range ) +unsigned int ai_ground_observable_index_60xx( unsigned int ai_range ) { return ai_range * 2; } +unsigned int ao_high_observable_index_60xx( const calibration_setup_t *setup, + unsigned int channel, unsigned int ao_range ) +{ + int num_ai_ranges; + + num_ai_ranges = comedi_get_n_ranges( setup->dev, setup->ad_subdev, 0 ); + assert( num_ai_ranges >= 0 ); + + return 2 * num_ai_ranges + 2 * channel + 4 * ao_range + 1; +} + +unsigned int ao_low_observable_index_60xx( const calibration_setup_t *setup, + unsigned int channel, unsigned int ao_range ) +{ + int num_ai_ranges; + + num_ai_ranges = comedi_get_n_ranges( setup->dev, setup->ad_subdev, 0 ); + assert( num_ai_ranges >= 0 ); + + return 2 * num_ai_ranges + 2 * channel + 4 * ao_range; +} + int ai_cal_src_voltage_60xx( calibration_setup_t *setup, unsigned int calibration_source, float *voltage ) { @@ -341,23 +363,38 @@ int high_ai_cal_src_60xx( calibration_setup_t *setup, unsigned int ai_range ) return -1; } +int ao_cal_src_60xx( unsigned int channel ) +{ + switch( channel ) + { + case 0: + return 6; + break; + case 1: + return 7; + break; + default: + return -1; + break; + } +} + int init_observables_60xx( calibration_setup_t *setup ) { - comedi_insn tmpl;//, po_tmpl; + comedi_insn tmpl; observable *o; int retval, num_ranges, i; float target; - static const int CAL_SRC_GROUND = 0; -#if 0 - memset( &po_tmpl, 0, sizeof(po_tmpl) ); - po_tmpl.insn = INSN_CONFIG; - po_tmpl.n = 2; - po_tmpl.subdev = setup->ad_subdev; -#endif + enum + { + CAL_SRC_GROUND = 0, + }; + memset( &tmpl, 0, sizeof(tmpl) ); tmpl.insn = INSN_READ; tmpl.n = 1; tmpl.subdev = setup->ad_subdev; + setup->n_observables = 0; num_ranges = comedi_get_n_ranges( setup->dev, setup->ad_subdev, 0 ); @@ -365,7 +402,7 @@ int init_observables_60xx( calibration_setup_t *setup ) for( i = 0; i < num_ranges; i++ ) { - o = setup->observables + ground_observable_index_60xx( i ); + o = setup->observables + ai_ground_observable_index_60xx( i ); o->reference_source = CAL_SRC_GROUND; assert( o->name == NULL ); asprintf( &o->name, "calibration source %i, range %i, ground referenced", @@ -374,10 +411,8 @@ int init_observables_60xx( calibration_setup_t *setup ) o->observe_insn.chanspec = CR_PACK( 0, 0, AREF_GROUND) | CR_ALT_SOURCE | CR_ALT_FILTER; o->target = 0.0; setup->n_observables++; - DPRINT( 0, "cal src %i, range %i, target %g\n", - o->reference_source, i, o->target ); - o = setup->observables + high_observable_index_60xx( i ); + o = setup->observables + ai_high_observable_index_60xx( i ); retval = high_ai_cal_src_60xx( setup, i ); if( retval < 0 ) return -1; o->reference_source = retval; @@ -390,8 +425,51 @@ int init_observables_60xx( calibration_setup_t *setup ) if( retval < 0 ) return -1; o->target = target; setup->n_observables++; - DPRINT( 0, "cal src %i, range %i, target %g\n", - o->reference_source, i, o->target ); + } + + if( setup->da_subdev >= 0 ) + { + comedi_insn po_tmpl; + + memset( &po_tmpl, 0, sizeof(po_tmpl) ); + po_tmpl.insn = INSN_WRITE; + po_tmpl.n = 1; + po_tmpl.subdev = setup->da_subdev; + + num_ranges = comedi_get_n_ranges( setup->dev, setup->da_subdev, 0 ); + if( num_ranges < 0 ) return -1; + + for( i = 0; i < num_ranges; i++ ) + { + int dac_chan; + for( dac_chan = 0; dac_chan < 2; dac_chan++ ) + { + o = setup->observables + ao_low_observable_index_60xx( setup, + dac_chan, i ); + o->reference_source = ao_cal_src_60xx( dac_chan ); + assert( o->name == NULL ); + asprintf( &o->name, "dac%i low, range %i, ground referenced", dac_chan, i ); + o->preobserve_insn = po_tmpl; + o->preobserve_insn.chanspec = CR_PACK( dac_chan, i, AREF_GROUND ); + o->preobserve_insn.data = o->preobserve_data; + o->observe_insn = tmpl; + o->observe_insn.chanspec = CR_PACK( 0, 0, AREF_GROUND) | CR_ALT_SOURCE | CR_ALT_FILTER; + set_target( setup, ao_low_observable_index_60xx( setup, dac_chan, i ), 0.0 ); + setup->n_observables++; + + o = setup->observables + ao_high_observable_index_60xx( setup, dac_chan, i ); + o->reference_source = ao_cal_src_60xx( dac_chan ); + assert( o->name == NULL ); + asprintf( &o->name, "dac%i high, range %i, ground referenced", dac_chan, i ); + o->preobserve_insn = po_tmpl; + o->preobserve_insn.chanspec = CR_PACK( dac_chan, i, AREF_GROUND ); + o->preobserve_insn.data = o->preobserve_data; + o->observe_insn = tmpl; + o->observe_insn.chanspec = CR_PACK( 0, 0, AREF_GROUND) | CR_ALT_SOURCE | CR_ALT_FILTER; + set_target( setup, ao_high_observable_index_60xx( setup, dac_chan, i ), 9.0 ); + setup->n_observables++; + } + } } return 0; @@ -828,7 +906,7 @@ int cal_cb_pci_64xx( calibration_setup_t *setup ) int cal_cb_pci_60xx( calibration_setup_t *setup ) { - saved_calibration_t *saved_cals; + saved_calibration_t *saved_cals, *current_cal; enum cal_knobs_60xx { DAC0_OFFSET = 0, @@ -840,38 +918,102 @@ int cal_cb_pci_60xx( calibration_setup_t *setup ) ADC_GAIN_COARSE, ADC_GAIN_FINE, }; - int i, num_ranges, retval; + int i, num_ai_ranges, num_ao_ranges, num_calibrations, retval; + int adc_offset_fine_for_ao = -1, adc_offset_coarse_for_ao = -1, + adc_gain_fine_for_ao = -1, adc_gain_coarse_for_ao = -1; + static const int ai_range_for_ao = 0; comedi_set_global_oor_behavior( COMEDI_OOR_NUMBER ); - num_ranges = comedi_get_n_ranges( setup->dev, setup->ad_subdev, 0 ); - if( num_ranges < 1 ) return -1; + num_ai_ranges = comedi_get_n_ranges( setup->dev, setup->ad_subdev, 0 ); + if( num_ai_ranges < 1 ) return -1; + if( setup->da_subdev >= 0 ) + { + num_ao_ranges = comedi_get_n_ranges( setup->dev, setup->da_subdev, 0 ); + if( num_ai_ranges < 1 ) return -1; + }else + num_ao_ranges = 0; + + num_calibrations = num_ai_ranges + 2 * num_ao_ranges; - saved_cals = malloc( num_ranges * sizeof( saved_calibration_t ) ); + saved_cals = malloc( num_calibrations * sizeof( saved_calibration_t ) ); if( saved_cals == NULL ) return -1; - for( i = num_ranges - 1; i >= 0; i-- ) + current_cal = saved_cals; + for( i = 0; i < num_ai_ranges ; i++ ) { - reset_caldacs( setup ); - - cal_binary( setup, ground_observable_index_60xx( i ), ADC_OFFSET_COARSE ); - cal_binary( setup, ground_observable_index_60xx( i ), ADC_OFFSET_FINE ); - cal_binary( setup, high_observable_index_60xx( i ), ADC_GAIN_COARSE ); - cal_binary( setup, high_observable_index_60xx( i ), ADC_GAIN_FINE ); - - memset( &saved_cals[ i ], 0, sizeof( saved_calibration_t ) ); - saved_cals[ i ].subdevice = setup->ad_subdev; - sc_push_caldac( &saved_cals[ i ], setup->caldacs[ ADC_OFFSET_FINE ] ); - sc_push_caldac( &saved_cals[ i ], setup->caldacs[ ADC_OFFSET_COARSE ] ); - sc_push_caldac( &saved_cals[ i ], setup->caldacs[ ADC_GAIN_FINE ] ); - sc_push_caldac( &saved_cals[ i ], setup->caldacs[ ADC_GAIN_COARSE ] ); - sc_push_channel( &saved_cals[ i ], SC_ALL_CHANNELS ); - sc_push_range( &saved_cals[ i ], i ); - sc_push_aref( &saved_cals[ i ], SC_ALL_AREFS ); + reset_caldac( setup, ADC_OFFSET_COARSE ); + reset_caldac( setup, ADC_OFFSET_FINE ); + reset_caldac( setup, ADC_GAIN_COARSE ); + reset_caldac( setup, ADC_GAIN_FINE ); + + cal_binary( setup, ai_ground_observable_index_60xx( i ), ADC_OFFSET_COARSE ); + cal_binary( setup, ai_ground_observable_index_60xx( i ), ADC_OFFSET_FINE ); + cal_binary( setup, ai_high_observable_index_60xx( i ), ADC_GAIN_COARSE ); + cal_binary( setup, ai_high_observable_index_60xx( i ), ADC_GAIN_FINE ); + + memset( current_cal, 0, sizeof( saved_calibration_t ) ); + current_cal->subdevice = setup->ad_subdev; + sc_push_caldac( current_cal, setup->caldacs[ ADC_OFFSET_FINE ] ); + sc_push_caldac( current_cal, setup->caldacs[ ADC_OFFSET_COARSE ] ); + sc_push_caldac( current_cal, setup->caldacs[ ADC_GAIN_FINE ] ); + sc_push_caldac( current_cal, setup->caldacs[ ADC_GAIN_COARSE ] ); + sc_push_channel( current_cal, SC_ALL_CHANNELS ); + sc_push_range( current_cal, i ); + sc_push_aref( current_cal, SC_ALL_AREFS ); + + current_cal++; + + if( i == ai_range_for_ao ) + { + adc_offset_fine_for_ao = setup->caldacs[ ADC_OFFSET_FINE ].current; + adc_offset_coarse_for_ao = setup->caldacs[ ADC_OFFSET_COARSE ].current; + adc_gain_fine_for_ao = setup->caldacs[ ADC_GAIN_FINE ].current; + adc_gain_coarse_for_ao = setup->caldacs[ ADC_GAIN_COARSE ].current; + } } - retval = write_calibration_file( setup, saved_cals, num_ranges ); - for( i = 0; i < num_ranges; i++ ) + update_caldac( setup, ADC_OFFSET_FINE, adc_offset_fine_for_ao ); + update_caldac( setup, ADC_OFFSET_COARSE, adc_offset_coarse_for_ao ); + update_caldac( setup, ADC_GAIN_FINE, adc_gain_fine_for_ao ); + update_caldac( setup, ADC_GAIN_COARSE, adc_gain_coarse_for_ao ); + for( i = 0; i < num_ao_ranges ; i++ ) + { + reset_caldac( setup, DAC0_OFFSET ); + reset_caldac( setup, DAC0_GAIN ); + + cal_binary( setup, ao_low_observable_index_60xx( setup, 0, i ), DAC0_OFFSET ); + cal_binary( setup, ao_high_observable_index_60xx( setup, 0, i ), DAC0_GAIN ); + + memset( current_cal, 0, sizeof( saved_calibration_t ) ); + current_cal->subdevice = setup->da_subdev; + sc_push_caldac( current_cal, setup->caldacs[ DAC0_OFFSET ] ); + sc_push_caldac( current_cal, setup->caldacs[ DAC0_GAIN ] ); + sc_push_channel( current_cal, 0 ); + sc_push_range( current_cal, i ); + sc_push_aref( current_cal, SC_ALL_AREFS ); + + current_cal++; + + reset_caldac( setup, DAC1_OFFSET ); + reset_caldac( setup, DAC1_GAIN ); + + cal_binary( setup, ao_low_observable_index_60xx( setup, 1, i ), DAC1_OFFSET ); + cal_binary( setup, ao_high_observable_index_60xx( setup, 1, i ), DAC1_GAIN ); + + memset( current_cal, 0, sizeof( saved_calibration_t ) ); + current_cal->subdevice = setup->da_subdev; + sc_push_caldac( current_cal, setup->caldacs[ DAC1_OFFSET ] ); + sc_push_caldac( current_cal, setup->caldacs[ DAC1_GAIN ] ); + sc_push_channel( current_cal, 1 ); + sc_push_range( current_cal, i ); + sc_push_aref( current_cal, SC_ALL_AREFS ); + + current_cal++; + } + + retval = write_calibration_file( setup, saved_cals, num_calibrations); + for( i = 0; i < num_calibrations; i++ ) clear_saved_calibration( &saved_cals[ i ] ); free( saved_cals ); return retval; diff --git a/comedi_calibrate/comedi_calibrate.c b/comedi_calibrate/comedi_calibrate.c index 373eccb..5380e00 100644 --- a/comedi_calibrate/comedi_calibrate.c +++ b/comedi_calibrate/comedi_calibrate.c @@ -32,6 +32,7 @@ #include #include #include +#include #include "calib.h" @@ -375,8 +376,7 @@ void postgain_cal( calibration_setup_t *setup, int obs1, int obs2, int dac) a = (offset1-offset2)/(slope1-slope2); a=setup->caldacs[dac].current-a; - setup->caldacs[dac].current=rint(a); - update_caldac( setup, dac ); + update_caldac( setup, dac, rint(a) ); usleep(100000); DPRINT(0,"caldac[%d] set to %g (%g)\n",dac,rint(a),a); @@ -399,8 +399,7 @@ void cal1( calibration_setup_t *setup, int obs, int dac) check_gain_chan_x( setup, &l, setup->observables[obs].observe_insn.chanspec,dac); a=linear_fit_func_x(&l, setup->observables[obs].target); - setup->caldacs[dac].current=rint(a); - update_caldac( setup, dac ); + update_caldac( setup, dac, rint(a) ); usleep(100000); DPRINT(0,"caldac[%d] set to %g (%g)\n",dac,rint(a),a); @@ -419,8 +418,7 @@ void cal1_fine( calibration_setup_t *setup, int obs, int dac ) check_gain_chan_fine( setup, &l, setup->observables[obs].observe_insn.chanspec,dac); a=linear_fit_func_x(&l,setup->observables[obs].target); - setup->caldacs[dac].current=rint(a); - update_caldac( setup, dac ); + update_caldac( setup, dac, rint(a) ); usleep(100000); DPRINT(0,"caldac[%d] set to %g (%g)\n",dac,rint(a),a); @@ -445,16 +443,14 @@ void cal_binary( calibration_setup_t *setup, int obs, int dac) new_sv_init(&sv, setup->dev,0,chanspec); sv.settling_time_ns = setup->settling_time_ns; - setup->caldacs[dac].current = x1; - update_caldac( setup, dac ); + update_caldac( setup, dac, x1 ); usleep(100000); new_sv_measure( setup->dev, &sv); y1 = sv.average; new_sv_init(&sv, setup->dev,0,chanspec); sv.settling_time_ns = setup->settling_time_ns; - setup->caldacs[dac].current = x2; - update_caldac( setup, dac ); + update_caldac( setup, dac, x2 ); usleep(100000); new_sv_measure( setup->dev, &sv); y2 = sv.average; @@ -466,8 +462,7 @@ void cal_binary( calibration_setup_t *setup, int obs, int dac) new_sv_init(&sv, setup->dev,0,chanspec); sv.settling_time_ns = setup->settling_time_ns; - setup->caldacs[dac].current = x; - update_caldac( setup, dac ); + update_caldac( setup, dac, x ); usleep(100000); new_sv_measure( setup->dev, &sv); @@ -507,8 +502,7 @@ void cal_postgain_binary( calibration_setup_t *setup, int obs1, int obs2, int da x1 = 0; x2 = setup->caldacs[dac].maxdata; - setup->caldacs[dac].current = x1; - update_caldac( setup, dac ); + update_caldac( setup, dac, x1 ); usleep(100000); preobserve( setup, obs1); new_sv_init(&sv1, setup->dev,0,chanspec1); @@ -521,8 +515,7 @@ void cal_postgain_binary( calibration_setup_t *setup, int obs1, int obs2, int da new_sv_measure( setup->dev, &sv2); y1 -= sv2.average; - setup->caldacs[dac].current = x2; - update_caldac( setup, dac ); + update_caldac( setup, dac, x2 ); usleep(100000); preobserve( setup, obs1); new_sv_init(&sv1, setup->dev,0,chanspec1); @@ -540,8 +533,7 @@ void cal_postgain_binary( calibration_setup_t *setup, int obs1, int obs2, int da x = (x1 + x2 + 1)/2; DPRINT(3,"trying %d\n",x); - setup->caldacs[dac].current = x; - update_caldac( setup, dac ); + update_caldac( setup, dac, x ); usleep(100000); preobserve( setup, obs1); @@ -595,8 +587,7 @@ void chan_cal(int adc,int cdac,int range,double target) a=caldacs[cdac].current+(target-offset)/gain; - caldacs[cdac].current=rint(a); - update_caldac( setup, cdac); + update_caldac( setup, cdac, rint(a)); read_chan2(s,adc,range); DPRINT(1,"caldac[%d] set to %g, offset=%s\n",cdac,a,s); @@ -653,26 +644,34 @@ void setup_caldacs( calibration_setup_t *setup, int caldac_subdev ) setup->n_caldacs += n_chan; } +void reset_caldac( calibration_setup_t *setup, unsigned int caldac_index ) +{ + assert( caldac_index < setup->n_caldacs ); + update_caldac( setup, caldac_index, setup->caldacs[ caldac_index ].maxdata / 2 ); +} + void reset_caldacs( calibration_setup_t *setup ) { int i; for( i = 0; i < setup->n_caldacs; i++){ - setup->caldacs[i].current = setup->caldacs[i].maxdata / 2; - update_caldac( setup, i ); + reset_caldac( setup, i ); } } -void update_caldac( calibration_setup_t *setup, unsigned int caldac_index ) +void update_caldac( calibration_setup_t *setup, unsigned int caldac_index, + int value ) { int ret; - caldac_t *dac = &setup->caldacs[ caldac_index ]; + caldac_t *dac; if( caldac_index > setup->n_caldacs ) { fprintf( stderr, "invalid caldac index\n" ); return; } + dac = &setup->caldacs[ caldac_index ]; + dac->current = value; DPRINT(4,"update %d %d %d\n", dac->subdev, dac->chan, dac->current); if( dac->current < 0 ){ DPRINT(1,"caldac set out of range (%d<0)\n", dac->current); @@ -738,16 +737,14 @@ double check_gain_chan_x( calibration_setup_t *setup, linear_fit_t *l,unsigned i new_sv_init(&sv, setup->dev,0,ad_chanspec); sv.settling_time_ns = setup->settling_time_ns; - setup->caldacs[cdac].current=0; - update_caldac( setup, cdac ); + update_caldac( setup, cdac, 0 ); usleep(100000); new_sv_measure( setup->dev, &sv); sum_err=0; for(i=0;i*stepcaldacs[cdac].current=i*step; - update_caldac( setup, cdac ); + update_caldac( setup, cdac, i*step ); //usleep(100000); new_sv_measure( setup->dev, &sv); @@ -760,8 +757,7 @@ double check_gain_chan_x( calibration_setup_t *setup, linear_fit_t *l,unsigned i l->n++; } - setup->caldacs[cdac].current=orig; - update_caldac( setup, cdac ); + update_caldac( setup, cdac, orig ); l->yerr=sum_err/sum_err_count; l->dx=step; @@ -812,16 +808,14 @@ double check_gain_chan_fine( calibration_setup_t *setup, linear_fit_t *l,unsigne new_sv_init(&sv, setup->dev,0,ad_chanspec); sv.settling_time_ns = setup->settling_time_ns; - setup->caldacs[cdac].current=0; - update_caldac( setup, cdac ); + update_caldac( setup, cdac, 0 ); usleep(100000); new_sv_measure( setup->dev, &sv); sum_err=0; for(i=0;icaldacs[cdac].current=i+orig-fine_size; - update_caldac( setup, cdac ); + update_caldac( setup, cdac, i+orig-fine_size ); usleep(100000); new_sv_measure( setup->dev, &sv); @@ -834,8 +828,7 @@ double check_gain_chan_fine( calibration_setup_t *setup, linear_fit_t *l,unsigne l->n++; } - setup->caldacs[cdac].current=orig; - update_caldac( setup, cdac ); + update_caldac( setup, cdac, orig ); l->yerr=sum_err/sum_err_count; l->dx=1; -- 2.26.2