add support for 67xx boards. Doesn't work yet, due to unknown reference

of internal calibration adc.  On my board, it's input seems to be about
2% off from +-10V.
This commit is contained in:
Frank Mori Hess 2004-02-15 22:24:57 +00:00
parent 2aeeb17080
commit 9097a55736
4 changed files with 231 additions and 20 deletions

View file

@ -101,8 +101,10 @@ void generic_prep_dac_caldacs( calibration_setup_t *setup,
{
reset_caldac( setup, layout->dac_offset( channel ) );
reset_caldac( setup, layout->dac_gain( channel ) );
reset_caldac( setup, layout->dac_linearity( channel ) );
reset_caldac( setup, layout->dac_offset_fine( channel ) );
reset_caldac( setup, layout->dac_gain_fine( channel ) );
reset_caldac( setup, layout->dac_linearity_fine( channel ) );
}else
{
retval = comedi_apply_parsed_calibration( setup->dev, setup->da_subdev,
@ -112,8 +114,10 @@ void generic_prep_dac_caldacs( calibration_setup_t *setup,
DPRINT( 0, "Failed to apply existing calibration, reseting dac caldacs.\n" );
reset_caldac( setup, layout->dac_offset( channel ) );
reset_caldac( setup, layout->dac_gain( channel ) );
reset_caldac( setup, layout->dac_linearity( channel ) );
reset_caldac( setup, layout->dac_offset_fine( channel ) );
reset_caldac( setup, layout->dac_gain_fine( channel ) );
reset_caldac( setup, layout->dac_linearity_fine( channel ) );
}
}
}
@ -161,10 +165,19 @@ static void generic_do_dac_channel( calibration_setup_t *setup, const generic_la
for( i = 0; i < max_iterations; i++ )
{
generic_do_linearity(setup, current_cal, layout->dac_ground_observable( setup, channel, range ),
layout->dac_mid_observable( setup, channel, range ),
layout->dac_high_observable( setup, channel, range ),
layout->dac_linearity(channel));
generic_do_relative( setup, current_cal, layout->dac_high_observable( setup, channel, range ),
layout->dac_ground_observable( setup, channel, range ),layout->dac_gain( channel ) );
generic_do_cal( setup, current_cal, layout->dac_ground_observable( setup, channel, range ),
layout->dac_offset( channel ) );
generic_do_linearity(setup, current_cal, layout->dac_ground_observable( setup, channel, range ),
layout->dac_mid_observable( setup, channel, range ),
layout->dac_high_observable( setup, channel, range ),
layout->dac_linearity_fine(channel));
generic_do_relative( setup, current_cal, layout->dac_high_observable( setup, channel, range ),
layout->dac_ground_observable( setup, channel, range ), layout->dac_gain_fine( channel ) );
generic_do_cal( setup, current_cal, layout->dac_ground_observable( setup, channel, range ),
@ -411,6 +424,39 @@ int generic_cal_by_range( calibration_setup_t *setup,
return retval;
}
int generic_cal_ao(calibration_setup_t *setup,
const generic_layout_t *layout )
{
int channel, range, num_ao_ranges,
num_ao_channels, retval;
comedi_calibration_setting_t *current_cal;
if(setup->da_subdev && setup->do_output)
{
assert( comedi_range_is_chan_specific( setup->dev, setup->da_subdev ) == 0 );
num_ao_ranges = comedi_get_n_ranges( setup->dev, setup->da_subdev, 0 );
if( num_ao_ranges < 0 ) return -1;
num_ao_channels = comedi_get_n_channels( setup->dev, setup->da_subdev );
if( num_ao_channels < 0 ) return -1;
}else
num_ao_ranges = num_ao_channels = 0;
for( channel = 0; channel < num_ao_channels; channel++ )
{
for( range = 0; range < num_ao_ranges; range++ )
{
current_cal = sc_alloc_calibration_setting( setup );
generic_prep_dac_caldacs( setup, layout, channel, range );
generic_do_dac_channel( setup, layout, setup->new_calibration,
current_cal, channel, range );
}
}
retval = write_calibration_file( setup );
return retval;
}
static int dummy_caldac( unsigned int channel )
{
return -1;
@ -429,11 +475,14 @@ void init_generic_layout( generic_layout_t *layout )
layout->adc_postgain_offset = dummy_caldac;
layout->dac_offset = dummy_caldac;
layout->dac_offset_fine = dummy_caldac;
layout->dac_linearity = dummy_caldac;
layout->dac_linearity_fine = dummy_caldac;
layout->dac_gain = dummy_caldac;
layout->dac_gain_fine = dummy_caldac;
layout->adc_high_observable = dummy_observable;
layout->adc_ground_observable = dummy_observable;
layout->dac_high_observable = dummy_observable;
layout->dac_mid_observable = dummy_observable;
layout->dac_ground_observable = dummy_observable;
layout->adc_fractional_tolerance = INFINITY;
layout->adc_fractional_tolerance = INFINITY;

View file

@ -51,9 +51,7 @@ typedef struct{
comedi_insn observe_insn;
//comedi_range *range;
//int maxdata;
lsampl_t reference_source;
int reference_source;
double target;
}observable;
@ -244,6 +242,8 @@ typedef struct
int (*adc_postgain_offset)( unsigned int channel );
int (*adc_gain)( unsigned int channel );
int (*adc_gain_fine)( unsigned int channel );
int (*dac_linearity)( unsigned int channel );
int (*dac_linearity_fine)( unsigned int channel );
int (*dac_offset)( unsigned int channel );
int (*dac_offset_fine)( unsigned int channel );
int (*dac_gain)( unsigned int channel );
@ -254,6 +254,8 @@ typedef struct
unsigned int channel, unsigned int range );
int (*dac_high_observable)( const calibration_setup_t *setup,
unsigned int channel, unsigned int range );
int (*dac_mid_observable)( const calibration_setup_t *setup,
unsigned int channel, unsigned int range );
int (*dac_ground_observable)( const calibration_setup_t *setup,
unsigned int channel, unsigned int range );
double adc_fractional_tolerance;
@ -265,6 +267,8 @@ int generic_cal_by_channel_and_range( calibration_setup_t *setup,
const generic_layout_t *layout );
int generic_cal_by_range( calibration_setup_t *setup,
const generic_layout_t *layout );
int generic_cal_ao(calibration_setup_t *setup,
const generic_layout_t *layout );
void generic_do_cal( calibration_setup_t *setup,
comedi_calibration_setting_t *saved_cal, int observable, int caldac );
void generic_do_relative( calibration_setup_t *setup,

View file

@ -319,7 +319,7 @@ ok:
return retval;
}
void set_target( calibration_setup_t *setup, int obs,double target)
void set_target( calibration_setup_t *setup, int obs, double target)
{
comedi_range *range;
lsampl_t maxdata, data;
@ -397,19 +397,22 @@ int preobserve( calibration_setup_t *setup, int obs)
lsampl_t ref_data[ 2 ];
// setup reference source
memset( &reference_source_config, 0, sizeof(reference_source_config) );
reference_source_config.insn = INSN_CONFIG;
reference_source_config.n = 2;
reference_source_config.subdev = setup->ad_subdev;
reference_source_config.data = ref_data;
reference_source_config.data[ 0 ] = INSN_CONFIG_ALT_SOURCE;
reference_source_config.data[ 1 ] = setup->observables[obs].reference_source;
if(setup->observables[obs].reference_source >= 0)
{
memset( &reference_source_config, 0, sizeof(reference_source_config) );
reference_source_config.insn = INSN_CONFIG;
reference_source_config.n = 2;
reference_source_config.subdev = setup->ad_subdev;
reference_source_config.data = ref_data;
reference_source_config.data[ 0 ] = INSN_CONFIG_ALT_SOURCE;
reference_source_config.data[ 1 ] = setup->observables[obs].reference_source;
retval = comedi_do_insn( setup->dev, &reference_source_config );
/* ignore errors for now since older ni driver doesn't
* support reference config insn */
if( retval < 0 )
perror("preobserve() ignoring reference config error" );
retval = comedi_do_insn( setup->dev, &reference_source_config );
/* ignore errors for now since older ni driver doesn't
* support reference config insn */
if( retval < 0 )
perror("preobserve() ignoring reference config error" );
}
retval = 0;
if( setup->observables[obs].preobserve_insn.n != 0){
@ -914,9 +917,10 @@ void setup_caldacs( calibration_setup_t *setup, int caldac_subdev )
}
// XXX check subdevice type is really calibration
// XXX check we dont exceed max number of allowable caldacs
n_chan = comedi_get_n_channels( setup->dev, caldac_subdev );
assert(n_chan >= 0);
assert(setup->n_caldacs + n_chan < N_CALDACS);
for(i = 0; i < n_chan; i++){
setup->caldacs[ setup->n_caldacs + i ].subdev = caldac_subdev;
@ -1461,7 +1465,7 @@ int linear_fit_monotonic(linear_fit_t *l)
l->sxx+=x*x;
}
sxp=l->sxx-l->sx*l->sx/l->s1;
l->ave_x=l->sx/l->s1;
l->ave_y=l->sy/l->s1;
l->slope=(l->s1*l->sxy-l->sx*l->sy)/(l->s1*l->sxx-l->sx*l->sx);

View file

@ -47,6 +47,7 @@ struct board_struct{
static int ni_setup_board( calibration_setup_t *setup , const char *device_name );
static void ni_setup_observables( calibration_setup_t *setup );
static void ni_setup_observables_611x( calibration_setup_t *setup );
static void ni67xx_setup_observables( calibration_setup_t *setup );
static int cal_ni_at_mio_16e_2(calibration_setup_t *setup);
static int cal_ni_daqcard_ai_16xe_50(calibration_setup_t *setup);
@ -70,6 +71,7 @@ static int cal_ni_pci_611x(calibration_setup_t *setup);
static int cal_ni_pci_mio_16e_4(calibration_setup_t *setup);
static int cal_ni_daqcard_6062e(calibration_setup_t *setup);
static int cal_ni_daqcard_6024e(calibration_setup_t *setup);
static int cal_ni_pci_6711(calibration_setup_t *setup);
static double ni_get_reference( calibration_setup_t *setup, int lsb_loc,int msb_loc);
@ -110,10 +112,16 @@ static struct board_struct boards[]={
{ "pxi-6052e", STATUS_UNKNOWN, NULL, ni_setup_observables, -1, -1 },
{ "pxi-6070e", STATUS_UNKNOWN, NULL, ni_setup_observables, -1, -1 },
{ "pxi-6071e", STATUS_GUESS, cal_ni_pxi_6071e, ni_setup_observables, -1, -1 },
{ "pci-6711", STATUS_GUESS, cal_ni_pci_6711, ni67xx_setup_observables, -1, -1},
{ "pci-6713", STATUS_GUESS, cal_ni_pci_6711, ni67xx_setup_observables, -1, -1},
{ "pci-6731", STATUS_GUESS, cal_ni_pci_6711, ni67xx_setup_observables, -1, -1},
{ "pci-6733", STATUS_GUESS, cal_ni_pci_6711, ni67xx_setup_observables, -1, -1},
{ "pxi-6711", STATUS_GUESS, cal_ni_pci_6711, ni67xx_setup_observables, -1, -1},
{ "pxi-6713", STATUS_GUESS, cal_ni_pci_6711, ni67xx_setup_observables, -1, -1},
{ "pxi-6731", STATUS_GUESS, cal_ni_pci_6711, ni67xx_setup_observables, -1, -1},
{ "pxi-6733", STATUS_GUESS, cal_ni_pci_6711, ni67xx_setup_observables, -1, -1},
#if 0
{ "at-mio-64e-3", cal_ni_16e_1 },
{ "pci-6711", cal_ni_unknown },
{ "pci-6713", cal_ni_unknown },
#endif
};
#define n_boards (sizeof(boards)/sizeof(boards[0]))
@ -1362,3 +1370,149 @@ static double ni_get_reference( calibration_setup_t *setup, int lsb_loc,int msb_
return ref;
}
/****************
NI 671x and 673x support
**************/
static const int channels_per_ad8804 = 16;
static inline int ni67xx_ao_gain_caldac(unsigned int ao_channel)
{
int ad8804_gain_channels[4] = {8, 2, 11, 5};
int caldac_channel = ad8804_gain_channels[ao_channel % 4];
int caldac_index = ao_channel / 4;
/* just guessing that second ad8804 is works for ao channels 4-7
* the same as the first ad8804 works for ao channels 0-3 */
return caldac_index * channels_per_ad8804 + caldac_channel;
}
static inline int ni67xx_ao_linearity_caldac(unsigned int ao_channel)
{
int ad8804_linearity_channels[4] = {4, 10, 1, 0};
int caldac_channel = ad8804_linearity_channels[ao_channel % 4];
int caldac_index = ao_channel / 4;
return caldac_index * channels_per_ad8804 + caldac_channel;
}
static inline int ni67xx_ao_offset_caldac(unsigned int ao_channel)
{
int ad8804_offset_channels[4] = {7, 6, 9, 3};
int caldac_channel = ad8804_offset_channels[ao_channel % 4];
int caldac_index = ao_channel / 4;
return caldac_index * channels_per_ad8804 + caldac_channel;
}
static int ni67xx_ao_ground_observable_index( const calibration_setup_t *setup,
unsigned int channel, unsigned int ao_range )
{
return 3 * channel;
}
static int ni67xx_ao_mid_observable_index( const calibration_setup_t *setup,
unsigned int channel, unsigned int ao_range )
{
return 3 * channel + 1;
}
static int ni67xx_ao_high_observable_index( const calibration_setup_t *setup,
unsigned int channel, unsigned int ao_range )
{
return 3 * channel + 2;
}
/* calibration adc uses RANGE_UNKNOWN, so it will return a value from
0.0 to 1.0 instead of a voltage, so we need to renormalize. */
void ni67xx_set_target( calibration_setup_t *setup, int obs,double target)
{
static const double reference = 5.0;
set_target(setup, obs, target);
/* calibration adc is roughly +=10V range, and inverted */
setup->observables[obs].target *= -1.0 / (reference * 4.0);
setup->observables[obs].target += 0.5;
}
static void ni67xx_setup_observables( calibration_setup_t *setup )
{
comedi_insn tmpl, po_tmpl;
observable *o;
int num_ao_channels;
int i;
/* calibration adc is very slow (15HZ) but accurate, so only sample a few times */
setup->sv_order = 1;
num_ao_channels = comedi_get_n_channels(setup->dev, setup->da_subdev);
assert(num_ao_channels >= 0);
memset( &tmpl, 0, sizeof(tmpl) );
tmpl.insn = INSN_READ;
tmpl.n = 1;
tmpl.subdev = setup->ad_subdev;
memset( &po_tmpl, 0, sizeof(po_tmpl) );
po_tmpl.insn = INSN_WRITE;
po_tmpl.n = 1;
po_tmpl.subdev = setup->da_subdev;
setup->n_observables = 0;
for(i = 0; i < num_ao_channels; i++)
{
o = setup->observables + ni67xx_ao_ground_observable_index( setup,
i, 0);
o->reference_source = -1;
assert( o->name == NULL );
asprintf(&o->name, "dac%i ground, ground referenced", i);
o->preobserve_insn = po_tmpl;
o->preobserve_insn.chanspec = CR_PACK(i, 0, AREF_GROUND);
o->preobserve_insn.data = o->preobserve_data;
o->observe_insn = tmpl;
o->observe_insn.chanspec = CR_PACK(i, 0, AREF_GROUND);
ni67xx_set_target(setup, ni67xx_ao_ground_observable_index(setup, i, 0), 0.0);
setup->n_observables++;
o = setup->observables + ni67xx_ao_mid_observable_index( setup,
i, 0);
o->reference_source = -1;
assert( o->name == NULL );
asprintf(&o->name, "dac%i mid, ground referenced", i);
o->preobserve_insn = po_tmpl;
o->preobserve_insn.chanspec = CR_PACK(i, 0, AREF_GROUND);
o->preobserve_insn.data = o->preobserve_data;
o->observe_insn = tmpl;
o->observe_insn.chanspec = CR_PACK(i, 0, AREF_GROUND);
ni67xx_set_target(setup, ni67xx_ao_mid_observable_index(setup, i, 0), 4.0);
setup->n_observables++;
o = setup->observables + ni67xx_ao_high_observable_index( setup, i, 0);
o->reference_source = -1;
assert( o->name == NULL );
asprintf(&o->name, "dac%i high, ground referenced", i);
o->preobserve_insn = po_tmpl;
o->preobserve_insn.chanspec = CR_PACK( i, 0, AREF_GROUND );
o->preobserve_insn.data = o->preobserve_data;
o->observe_insn = tmpl;
o->observe_insn.chanspec = CR_PACK(i, 0, AREF_GROUND);
ni67xx_set_target(setup, ni67xx_ao_high_observable_index(setup, i, 0), 8.0);
setup->n_observables++;
}
return;
}
static int cal_ni_pci_6711(calibration_setup_t *setup)
{
generic_layout_t layout;
init_generic_layout( &layout );
layout.dac_gain = ni67xx_ao_gain_caldac;
layout.dac_linearity = ni67xx_ao_linearity_caldac;
layout.dac_offset = ni67xx_ao_offset_caldac;
layout.dac_high_observable = ni67xx_ao_high_observable_index;
layout.dac_mid_observable = ni67xx_ao_mid_observable_index;
layout.dac_ground_observable = ni67xx_ao_ground_observable_index;
layout.dac_fractional_tolerance = get_tolerance( setup, setup->da_subdev, 1.0 );
return generic_cal_ao(setup, &layout);
}