diff --git a/comedi_calibrate/comedi_calibrate.c b/comedi_calibrate/comedi_calibrate.c index b0488e7..5e0d25f 100644 --- a/comedi_calibrate/comedi_calibrate.c +++ b/comedi_calibrate/comedi_calibrate.c @@ -33,8 +33,10 @@ #include #include +#define DPRINT(level,fmt,args...) do{if(verbose>=level)printf(fmt,args);}while(0) #define N_CALDACS 32 +#define N_OBSERVABLES 32 typedef struct{ int subdev; @@ -47,20 +49,49 @@ typedef struct{ double gain; }caldac; +typedef struct{ + char *name; + + comedi_insn preobserve_insn; + lsampl_t preobserve_data; + + comedi_insn observe_insn; + + //comedi_range *range; + //int maxdata; + + double target; +}observable; + static caldac caldacs[N_CALDACS]; +static observable observables[N_OBSERVABLES]; + static int n_caldacs; +static int n_observables; + static comedi_t *dev; static int ad_subdev; +static int da_subdev; static int eeprom_subdev; +static int caldac_subdev; double read_chan(int adc,int range); -void write_caldac(comedi_t *dev,int subdev,int addr,int val); +int read_chan2(char *s,int adc,int range); +void set_ao(comedi_t *dev,int subdev,int chan,int range,double value); void check_gain(int ad_chan,int range); double check_gain_chan(int ad_chan,int range,int cdac); int verbose = 0; +void observe(void); +void preobserve(int obs); +void observable_dependence(int obs); +void measure_observable(int obs); +void ni_setup(void); +void set_target(int obs,double target); + +void cal_ni_results(void); void update_caldac(int i); void reset_caldacs(void); @@ -110,7 +141,7 @@ typedef struct { }linear_fit_t; int linear_fit_monotonic(linear_fit_t *l); double linear_fit_func_y(linear_fit_t *l,double x); -double check_gain_chan_x(linear_fit_t *l,int ad_chan,int range,int cdac); +double check_gain_chan_x(linear_fit_t *l,unsigned int ad_chanspec,int cdac); typedef struct{ comedi_t *dev; @@ -151,56 +182,78 @@ struct board_struct boards[]={ { "at-mio-16e-1", cal_ni_16e_1 }, { "at-mio-16e-2", cal_ni_16e_1 }, { "at-mio-16e-10", cal_ni_16e_10 }, - { "at-mio-16de-10", cal_ni_unknown }, +// { "at-mio-16de-10", cal_ni_unknown }, { "at-mio-64e-3", cal_ni_16e_1 }, - { "at-mio-16xe-50", cal_ni_unknown }, - { "at-mio-16xe-10", cal_ni_unknown }, - { "at-ai-16xe-10", cal_ni_unknown }, +// { "at-mio-16xe-50", cal_ni_unknown }, +// { "at-mio-16xe-10", cal_ni_unknown }, +// { "at-ai-16xe-10", cal_ni_unknown }, { "pci-mio-16xe-50", cal_ni_16xe_50 }, { "pci-mio-16xe-10", cal_ni_16xe_10 }, - { "pxi-6030e", cal_ni_unknown }, +// { "pxi-6030e", cal_ni_unknown }, { "pci-mio-16e-1", cal_ni_16e_1 }, - { "pci-mio-16e-4", cal_ni_unknown }, - { "pxi-6040e", cal_ni_unknown }, - { "pci-6031e", cal_ni_unknown }, - { "pci-6032e", cal_ni_unknown }, - { "pci-6033e", cal_ni_unknown }, - { "pci-6071e", cal_ni_unknown }, +// { "pci-mio-16e-4", cal_ni_unknown }, +// { "pxi-6040e", cal_ni_unknown }, +// { "pci-6031e", cal_ni_unknown }, +// { "pci-6032e", cal_ni_unknown }, +// { "pci-6033e", cal_ni_unknown }, +// { "pci-6071e", cal_ni_unknown }, { "pci-6023e", cal_ni_6023e }, { "pci-6024e", cal_ni_6023e }, // guess { "pci-6025e", cal_ni_6023e }, // guess { "pxi-6025e", cal_ni_6023e }, // guess { "pci-6034e", cal_ni_6023e }, // guess { "pci-6035e", cal_ni_6023e }, - { "pci-6052e", cal_ni_unknown }, - { "pci-6110e", cal_ni_unknown }, - { "pci-6111e", cal_ni_unknown }, +// { "pci-6052e", cal_ni_unknown }, +// { "pci-6110e", cal_ni_unknown }, +// { "pci-6111e", cal_ni_unknown }, // { "pci-6711", cal_ni_unknown }, // { "pci-6713", cal_ni_unknown }, { "pxi-6071e", cal_ni_6071e }, - { "pxi-6070e", cal_ni_unknown }, - { "pxi-6052e", cal_ni_unknown }, -// { "DAQCard-ai-16xe-50", cal_ni_daqcard_ai_16xe_50 }, - { "DAQCard-ai-16xe-50", cal_ni_unknown }, - { "DAQCard-ai-16e-4", cal_ni_unknown }, - { "DAQCard-6062e", cal_ni_unknown }, - { "DAQCard-6024e", cal_ni_unknown }, +// { "pxi-6070e", cal_ni_unknown }, +// { "pxi-6052e", cal_ni_unknown }, + { "DAQCard-ai-16xe-50", cal_ni_daqcard_ai_16xe_50 }, +// { "DAQCard-ai-16e-4", cal_ni_unknown }, +// { "DAQCard-6062e", cal_ni_unknown }, +// { "DAQCard-6024e", cal_ni_unknown }, }; #define n_boards (sizeof(boards)/sizeof(boards[0])) +struct board_struct drivers[] = { + { "ni_pcimio", cal_ni_unknown }, + { "ni_atmio", cal_ni_unknown }, + { "ni_mio_cs", cal_ni_unknown }, +}; +#define n_drivers (sizeof(drivers)/sizeof(drivers[0])) + +int do_dump = 0; +int do_reset = 1; +int do_calibrate = 1; +int do_show = 1; + +struct option options[] = { + { "verbose", 0, 0, 'v' }, + { "quiet", 0, 0, 'q' }, + { "file", 0, 0, 'f' }, + { "dump", 0, 0, 'd' }, + { "reset", 0, 0, 'r' }, + { "show", 0, 0, 's' }, + { 0 }, +}; + int main(int argc, char *argv[]) { char *fn = NULL; int c; char *drivername; char *devicename; - int i; + //int i; + //struct board_struct *this_board; + int index; fn = "/dev/comedi0"; while (1) { - c = getopt(argc, argv, "f:vq"); - if (c == -1) - break; + c = getopt_long(argc, argv, "f:vqdr", options, &index); + if (c == -1)break; switch (c) { case 'f': fn = optarg; @@ -211,6 +264,15 @@ int main(int argc, char *argv[]) case 'q': verbose--; break; + case 'd': + do_dump = 1; + break; + case 'r': + do_reset = 1; + break; + case 's': + do_show = 1; + break; default: printf("bad option\n"); exit(1); @@ -223,26 +285,223 @@ int main(int argc, char *argv[]) exit(0); } - ad_subdev=0; - setup_caldacs(); - + ad_subdev=comedi_find_subdevice_by_type(dev,COMEDI_SUBD_AI,0); + da_subdev=comedi_find_subdevice_by_type(dev,COMEDI_SUBD_AO,0); + caldac_subdev=comedi_find_subdevice_by_type(dev,COMEDI_SUBD_CALIB,0); eeprom_subdev=comedi_find_subdevice_by_type(dev,COMEDI_SUBD_MEMORY,0); drivername=comedi_get_driver_name(dev); devicename=comedi_get_board_name(dev); + ni_setup(); + + reset_caldacs(); + + observe(); +#if 0 for(i=0;icalibrate(); +#endif return 0; } +void ni_setup(void) +{ + comedi_insn tmpl; + int bipolar_lowgain; + int bipolar_highgain; + int unipolar_lowgain; + int i; + double voltage_reference; + + bipolar_lowgain = get_bipolar_lowgain(dev,ad_subdev); + bipolar_highgain = get_bipolar_highgain(dev,ad_subdev); + unipolar_lowgain = get_unipolar_lowgain(dev,ad_subdev); + + voltage_reference = 5.000; + + memset(&tmpl,0,sizeof(tmpl)); + tmpl.insn = INSN_READ; + tmpl.n = 1; + tmpl.subdev = ad_subdev; + + i = 0; + /* 0 offset, low gain */ + observables[i].name = "ai, bipolar zero offset, low gain"; + observables[i].observe_insn = tmpl; + observables[i].observe_insn.chanspec = + CR_PACK(0,bipolar_lowgain,AREF_OTHER); + observables[i].target = 0; + i++; + + /* 0 offset, high gain */ + observables[i].name = "ai, bipolar zero offset, high gain"; + observables[i].observe_insn = tmpl; + observables[i].observe_insn.chanspec = + CR_PACK(0,bipolar_highgain,AREF_OTHER); + observables[i].target = 0; + i++; + + /* voltage reference */ + observables[i].name = "ai, bipolar voltage reference, low gain"; + observables[i].observe_insn = tmpl; + observables[i].observe_insn.chanspec = + CR_PACK(5,bipolar_lowgain,AREF_OTHER); + observables[i].target = voltage_reference; + i++; + + if(unipolar_lowgain>=0){ + /* unip/bip offset */ + observables[i].name = "ai, unipolar zero offset, low gain"; + observables[i].observe_insn = tmpl; + observables[i].observe_insn.chanspec = + CR_PACK(0,unipolar_lowgain,AREF_OTHER); + observables[i].target = 0; + i++; + } + + if(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 = da_subdev; + + /* ao 0, zero offset */ + observables[i].name = "ao 0, zero offset, low gain"; + observables[i].preobserve_insn = po_tmpl; + observables[i].preobserve_insn.chanspec = CR_PACK(0,0,0); + observables[i].preobserve_insn.data = &observables[i].preobserve_data; + observables[i].observe_insn = tmpl; + observables[i].observe_insn.chanspec = + CR_PACK(2,bipolar_lowgain,AREF_OTHER); + set_target(i,0.0); + i++; + + /* ao 0, gain */ + observables[i].name = "ao 0, reference voltage, low gain"; + observables[i].preobserve_insn = po_tmpl; + observables[i].preobserve_insn.chanspec = CR_PACK(0,0,0); + observables[i].preobserve_insn.data = &observables[i].preobserve_data; + observables[i].observe_insn = tmpl; + observables[i].observe_insn.chanspec = + CR_PACK(6,bipolar_lowgain,AREF_OTHER); + set_target(i,5.0); + observables[i].target -= voltage_reference; + i++; + + /* ao 1, zero offset */ + observables[i].name = "ao 1, zero offset, low gain"; + observables[i].preobserve_insn = po_tmpl; + observables[i].preobserve_insn.chanspec = CR_PACK(1,0,0); + observables[i].preobserve_insn.data = &observables[i].preobserve_data; + observables[i].observe_insn = tmpl; + observables[i].observe_insn.chanspec = + CR_PACK(3,bipolar_lowgain,AREF_OTHER); + set_target(i,0.0); + i++; + + /* ao 1, gain */ + observables[i].name = "ao 1, reference voltage, low gain"; + observables[i].preobserve_insn = po_tmpl; + observables[i].preobserve_insn.chanspec = CR_PACK(1,0,0); + observables[i].preobserve_insn.data = &observables[i].preobserve_data; + observables[i].observe_insn = tmpl; + observables[i].observe_insn.chanspec = + CR_PACK(7,bipolar_lowgain,AREF_OTHER); + set_target(i,5.0); + observables[i].target -= voltage_reference; + i++; + } + n_observables = i; + + setup_caldacs(); +} + +void set_target(int obs,double target) +{ + comedi_range *range; + lsampl_t maxdata, data; + + range = comedi_get_range(dev,observables[obs].preobserve_insn.subdev, + CR_CHAN(observables[obs].preobserve_insn.chanspec), + CR_RANGE(observables[obs].preobserve_insn.chanspec)); + maxdata = comedi_get_maxdata(dev,observables[obs].preobserve_insn.subdev, + CR_CHAN(observables[obs].preobserve_insn.chanspec)); + + data = comedi_from_phys(target,range,maxdata); + + observables[obs].preobserve_data = data; + observables[obs].target = comedi_to_phys(data,range,maxdata); +} + +void observe(void) +{ + int i; + + for(i=0;i\n"); printf("$Id$\n"); printf("Device name: %s\n",comedi_get_board_name(dev)); @@ -694,38 +975,100 @@ void cal_ni_unknown(void) /* 0 offset, low gain */ range = comedi_get_range(dev,ad_subdev,0,bipolar_lowgain); - if(verbose>=0){ - printf("bipolar zero offset, low gain [%g,%g]\n", - range->min,range->max); - } + DPRINT(0,"bipolar zero offset, low gain [%g,%g]\n", + range->min,range->max); channel_dependence(0,bipolar_lowgain); /* 0 offset, high gain */ range = comedi_get_range(dev,ad_subdev,0,bipolar_highgain); - if(verbose>=0){ - printf("bipolar zero offset, high gain [%g,%g]\n", - range->min,range->max); - } + DPRINT(0,"bipolar zero offset, high gain [%g,%g]\n", + range->min,range->max); channel_dependence(0,bipolar_highgain); /* unip/bip offset */ range = comedi_get_range(dev,ad_subdev,0,unipolar_lowgain); - if(verbose>=0){ - printf("unipolar zero offset, low gain [%g,%g]\n", - range->min,range->max); - } + DPRINT(0,"unipolar zero offset, low gain [%g,%g]\n", + range->min,range->max); channel_dependence(0,unipolar_lowgain); /* voltage reference */ range = comedi_get_range(dev,ad_subdev,0,bipolar_lowgain); - if(verbose>=0){ - printf("bipolar voltage reference, low gain [%g,%g]\n", - range->min,range->max); - } + DPRINT(0,"bipolar voltage reference, low gain [%g,%g]\n", + range->min,range->max); channel_dependence(5,bipolar_lowgain); + have_ao = (comedi_get_subdevice_type(dev,da_subdev)==COMEDI_SUBD_AO); + if(have_ao){ + int ao_chan; + + /* ao 0, zero offset */ + ao_chan = 0; + set_ao(dev,da_subdev,ao_chan,0,0.0); + range = comedi_get_range(dev,ad_subdev,0,bipolar_lowgain); + DPRINT(0,"ao 0, zero offset, low gain [%g,%g]\n", + range->min,range->max); + channel_dependence(2,bipolar_lowgain); + + /* ao 0, gain */ + ao_chan = 0; + set_ao(dev,da_subdev,ao_chan,0,5.0); + range = comedi_get_range(dev,ad_subdev,0,bipolar_lowgain); + DPRINT(0,"ao 0, gain, low gain [%g,%g]\n", + range->min,range->max); + channel_dependence(6,bipolar_lowgain); + + /* ao 1, zero offset */ + ao_chan = 1; + set_ao(dev,da_subdev,ao_chan,0,0.0); + range = comedi_get_range(dev,ad_subdev,0,bipolar_lowgain); + DPRINT(0,"ao 1, zero offset, low gain [%g,%g]\n", + range->min,range->max); + channel_dependence(3,bipolar_lowgain); + + /* ao 1, gain */ + ao_chan = 1; + set_ao(dev,da_subdev,ao_chan,0,5.0); + range = comedi_get_range(dev,ad_subdev,0,bipolar_lowgain); + DPRINT(0,"ao 1, gain, low gain [%g,%g]\n", + range->min,range->max); + channel_dependence(7,bipolar_lowgain); + } + + cal_ni_results(); } +void cal_ni_results(void) +{ + comedi_range *range; + int bipolar_lowgain; + int bipolar_highgain; + int unipolar_lowgain; + //int have_ao; + char s[32]; + + bipolar_lowgain = get_bipolar_lowgain(dev,ad_subdev); + bipolar_highgain = get_bipolar_highgain(dev,ad_subdev); + unipolar_lowgain = get_unipolar_lowgain(dev,ad_subdev); + + /* 0 offset, low gain */ + range = comedi_get_range(dev,ad_subdev,0,bipolar_lowgain); + read_chan2(s,0,bipolar_lowgain); + DPRINT(0,"bipolar zero offset, low gain [%g,%g]: %s\n", + range->min,range->max,s); + + /* 0 offset, high gain */ + range = comedi_get_range(dev,ad_subdev,0,bipolar_highgain); + read_chan2(s,0,bipolar_highgain); + DPRINT(0,"bipolar zero offset, high gain [%g,%g]: %s\n", + range->min,range->max,s); + + /* unip/bip offset */ + range = comedi_get_range(dev,ad_subdev,0,unipolar_lowgain); + read_chan2(s,0,unipolar_lowgain); + DPRINT(0,"unipolar zero offset, low gain [%g,%g]: %s\n", + range->min,range->max,s); + +} void ni_mio_ai_postgain_cal(void) { @@ -735,11 +1078,11 @@ void ni_mio_ai_postgain_cal(void) double gain; double a; - check_gain_chan_x(&l,0,0,1); + check_gain_chan_x(&l,CR_PACK(0,0,AREF_OTHER),1); offset_r0=linear_fit_func_y(&l,caldacs[1].current); printf("offset r0 %g\n",offset_r0); - check_gain_chan_x(&l,0,7,1); + check_gain_chan_x(&l,CR_PACK(0,7,AREF_OTHER),1); offset_r7=linear_fit_func_y(&l,caldacs[1].current); printf("offset r7 %g\n",offset_r7); @@ -761,11 +1104,11 @@ void ni_mio_ai_postgain_cal_2(int chan,int dac,int range_lo,int range_hi,double double slope; double a; - check_gain_chan_x(&l,chan,range_lo,dac); + check_gain_chan_x(&l,CR_PACK(chan,range_lo,AREF_OTHER),dac); offset_lo=linear_fit_func_y(&l,caldacs[dac].current); printf("offset lo %g\n",offset_lo); - check_gain_chan_x(&l,chan,range_hi,dac); + check_gain_chan_x(&l,CR_PACK(chan,range_hi,AREF_OTHER),dac); offset_hi=linear_fit_func_y(&l,caldacs[dac].current); printf("offset hi %g\n",offset_hi); @@ -786,17 +1129,19 @@ void chan_cal(int adc,int cdac,int range,double target) double offset; double gain; double a; + char s[32]; - check_gain_chan_x(&l,adc,range,cdac); + check_gain_chan_x(&l,CR_PACK(adc,range,AREF_OTHER),cdac); offset=linear_fit_func_y(&l,caldacs[cdac].current); - printf("offset %g\n",offset); gain=l.slope; a=caldacs[cdac].current+(target-offset)/gain; - printf("%g\n",a); caldacs[cdac].current=rint(a); update_caldac(cdac); + + read_chan2(s,adc,range); + DPRINT(0,"caldac[%d] set to %g, offset=%s\n",cdac,a,s); } @@ -825,29 +1170,26 @@ void dump_curve(int adc,int caldac) { linear_fit_t l; - check_gain_chan_x(&l,adc,0,caldac); + check_gain_chan_x(&l,CR_PACK(adc,0,AREF_OTHER),caldac); } void setup_caldacs(void) { - int s,n_chan,i; + int n_chan,i; - s=comedi_find_subdevice_by_type(dev,COMEDI_SUBD_CALIB,0); - if(s<0){ + if(caldac_subdev<0){ printf("no calibration subdevice\n"); return; } - //printf("calibration subdevice is %d\n",s); - n_chan=comedi_get_n_channels(dev,s); + n_chan=comedi_get_n_channels(dev,caldac_subdev); for(i=0;i1){ return sprintf(s,"%0.0f(%2.0f)",x,error); } if(maxsig<=0 && maxsig>=-2){ - return sprintf(s,"altnum %0.*f(%2.0f)",sigfigs-1-maxsig, + return sprintf(s,"%0.*f(%2.0f)",sigfigs-1-maxsig, mantissa*pow(10,maxsig),error); } return sprintf(s,"%0.*f(%2.0f)e%d",sigfigs-1,mantissa,error,maxsig);