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:
parent
2aeeb17080
commit
9097a55736
4 changed files with 231 additions and 20 deletions
|
@ -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;
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue