{
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,
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 ) );
}
}
}
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 ),
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;
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;
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;
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;
-
- 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" );
+ 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 = 0;
if( setup->observables[obs].preobserve_insn.n != 0){
}
// 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;
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);
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);
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);
{ "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]))
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);
+}
+