static int cal_ni_daqcard_ai_16xe_50(calibration_setup_t *setup);
static int cal_ni_at_mio_16e_1(calibration_setup_t *setup);
static int cal_ni_pci_mio_16e_1(calibration_setup_t *setup);
+static int cal_ni_pci_6014(calibration_setup_t *setup);
static int cal_ni_pci_6024e(calibration_setup_t *setup);
static int cal_ni_pci_6025e(calibration_setup_t *setup);
static int cal_ni_pci_6032e(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_daqcard_6036e(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);
static struct board_struct boards[]={
{ "at-ai-16xe-10", STATUS_UNKNOWN, NULL, ni_setup_observables, 0x1b7, 0x1b8 },
{ "at-mio-16de-10", STATUS_UNKNOWN, NULL, ni_setup_observables, 0x1a7, 0x1a8 },
- { "at-mio-16e-1", STATUS_SOME, cal_ni_at_mio_16e_1, ni_setup_observables, 0x1a9, 0x1aa },
+ { "at-mio-16e-1", STATUS_DONE, cal_ni_at_mio_16e_1, ni_setup_observables, 0x1a9, 0x1aa },
{ "at-mio-16e-2", STATUS_DONE, cal_ni_at_mio_16e_2, ni_setup_observables, 0x1a9, 0x1aa },
- { "at-mio-16e-10", STATUS_GUESS, cal_ni_at_mio_16e_10, ni_setup_observables, 0x1a7, 0x1a8 },
+ { "at-mio-16e-10", STATUS_DONE, cal_ni_at_mio_16e_10, ni_setup_observables, 0x1a7, 0x1a8 },
{ "at-mio-16xe-10", STATUS_UNKNOWN, NULL, ni_setup_observables, 0x1b7, 0x1b8 },
{ "at-mio-16xe-50", STATUS_SOME, cal_ni_at_mio_16xe_50, ni_setup_observables, 0x1b5, 0x1b6 },
{ "DAQCard-ai-16e-4", STATUS_DONE, cal_ni_daqcard_ai_16e_4, ni_setup_observables, 0x1b5, 0x1b6 },
{ "DAQCard-ai-16xe-50", STATUS_DONE, cal_ni_daqcard_ai_16xe_50, ni_setup_observables, 0x1be, 0x1bf },
{ "DAQCard-6024E", STATUS_SOME, cal_ni_daqcard_6024e, ni_setup_observables, -1, -1 },
- { "DAQCard-6036E", STATUS_UNKNOWN, NULL, ni_setup_observables, -1, -1 },
+ { "DAQCard-6036E", STATUS_DONE, cal_ni_daqcard_6036e, ni_setup_observables, 0x1ab, 0x1ac },
{ "DAQCard-6062E", STATUS_DONE, cal_ni_daqcard_6062e, ni_setup_observables, 0x1a9, 0x1aa },
{ "pci-mio-16e-1", STATUS_DONE, cal_ni_pci_mio_16e_1, ni_setup_observables, 0x1a9, 0x1aa },
{ "pci-mio-16e-4", STATUS_SOME, cal_ni_pci_mio_16e_4, ni_setup_observables, 0x1a9, 0x1aa },
{ "pci-mio-16xe-10", STATUS_DONE, cal_ni_pci_mio_16xe_10, ni_setup_observables, 0x1ae, 0x1af },
{ "pci-mio-16xe-50", STATUS_SOME, cal_ni_pci_mio_16xe_50, ni_setup_observables, 0x1b5, 0x1b6 },
+ { "pci-6014", STATUS_SOME, cal_ni_pci_6014, ni_setup_observables, 0x1ab, 0x1ac },
{ "pci-6023e", STATUS_DONE, cal_ni_pci_6023e, ni_setup_observables, 0x1bb, 0x1bc },
{ "pci-6024e", STATUS_SOME, cal_ni_pci_6024e, ni_setup_observables, 0x1af, 0x1b0 },
{ "pci-6025e", STATUS_SOME, cal_ni_pci_6025e, ni_setup_observables, 0x1af, 0x1b0 },
{ "pci-6031e", STATUS_DONE, cal_ni_pci_mio_16xe_10, ni_setup_observables, 0x1ae, 0x1af },
{ "pci-6032e", STATUS_DONE, cal_ni_pci_6032e, ni_setup_observables, 0x1ae, 0x1af },
- { "pci-6033e", STATUS_SOME, cal_ni_pci_6032e, ni_setup_observables, -1, -1 },
+ { "pci-6033e", STATUS_DONE, cal_ni_pci_6032e, ni_setup_observables, 0x1b7, 0x1b8 },
{ "pci-6034e", STATUS_UNKNOWN, NULL, ni_setup_observables, -1, -1 },
{ "pci-6035e", STATUS_DONE, cal_ni_pci_6035e, ni_setup_observables, 0x1af, 0x1b0 },
{ "pci-6036e", STATUS_DONE, cal_ni_pci_6036e, ni_setup_observables, 0x1ab, 0x1ac },
{ "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-6711", STATUS_DONE, cal_ni_pci_6711, ni67xx_setup_observables, 0x1d4, 0x1d5},
{ "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},
int adc_unip_offset;
int adc_unip_offset_fine;
int dac_offset[ 2 ];
+ int dac_offset_fine[ 2 ];
int dac_gain[ 2 ];
int dac_gain_fine[ 2 ];
int dac_linearity[ 2 ];
for( i = 0; i < 2; i++ )
{
layout->dac_offset[ i ] = -1;
+ layout->dac_offset_fine[ i ] = -1;
layout->dac_gain[ i ] = -1;
layout->dac_gain_fine[ i ] = -1;
layout->dac_linearity[ i ] = -1;
setup->n_observables = num_ao_observables_611x + 2 * num_ai_ranges * num_ai_channels;
}
-static int cal_ni_at_mio_16e_2(calibration_setup_t *setup)
-{
- ni_caldac_layout_t layout;
-
- init_ni_caldac_layout( &layout );
- layout.adc_pregain_offset = 0;
- layout.adc_postgain_offset = 1;
- layout.adc_gain = 3;
- layout.adc_unip_offset = 2;
- layout.dac_offset[ 0 ] = 5;
- layout.dac_gain[ 0 ] = 6;
- layout.dac_offset[ 1 ] = 8;
- layout.dac_gain[ 1 ] = 9;
-
- return cal_ni_generic( setup, &layout );
-}
-
static int cal_ni_daqcard_ai_16xe_50(calibration_setup_t *setup)
{
ni_caldac_layout_t layout;
static int cal_ni_at_mio_16e_1(calibration_setup_t *setup)
{
- return cal_ni_at_mio_16e_2( setup );
+ ni_caldac_layout_t layout;
+
+ init_ni_caldac_layout( &layout );
+ layout.adc_pregain_offset = 0;
+ layout.adc_postgain_offset = 1;
+ layout.adc_gain = 3;
+ layout.adc_unip_offset = 2;
+ layout.dac_offset[0] = 5;
+ layout.dac_gain[0] = 6;
+ layout.dac_linearity[0] = 4;
+ layout.dac_offset[1] = 8;
+ layout.dac_gain[1] = 9;
+ layout.dac_linearity[1] = 7;
+
+ return cal_ni_generic( setup, &layout );
+}
+
+static int cal_ni_at_mio_16e_2(calibration_setup_t *setup)
+{
+ return cal_ni_at_mio_16e_1(setup);
}
static int cal_ni_pci_mio_16e_1(calibration_setup_t *setup)
return cal_ni_generic( setup, &layout );
}
+static int cal_ni_pci_6014(calibration_setup_t *setup)
+{
+ ni_caldac_layout_t layout;
+
+ init_ni_caldac_layout( &layout );
+ layout.adc_pregain_offset = 0;
+ layout.adc_postgain_offset = 4;
+ layout.adc_pregain_offset_fine = 8;
+ layout.adc_gain = 2;
+ layout.dac_offset[0] = 6;
+ layout.dac_offset_fine[0] = 10;
+ layout.dac_gain[0] = 7;
+ layout.dac_gain_fine[0] = 11;
+ layout.dac_offset[1] = 9;
+ layout.dac_offset_fine[1] = 1;
+ layout.dac_gain[1] = 3;
+ layout.dac_gain_fine[1] = 5;
+ return cal_ni_generic( setup, &layout );
+}
+
static int cal_ni_pci_6032e(calibration_setup_t *setup)
{
ni_caldac_layout_t layout;
static int cal_ni_at_mio_16e_10(calibration_setup_t *setup)
{
- // 16e-10 (old)
ni_caldac_layout_t layout;
+ if(comedi_get_version_code(setup->dev) <= COMEDI_VERSION_CODE(0, 7, 68))
+ {
+ DPRINT(0, "WARNING: you need comedi driver version 0.7.69 or later\n"
+ "for this calibration to work properly\n" );
+ }
init_ni_caldac_layout( &layout );
- layout.adc_pregain_offset = 10;
- layout.adc_pregain_offset_fine = 0;
- layout.adc_postgain_offset = 1;
- layout.adc_gain = 3;
- layout.adc_unip_offset = 2;
- layout.dac_offset[ 0 ] = 5; /* guess */
- layout.dac_gain[ 0 ] = 6; /* guess */
- layout.dac_offset[ 1 ] = 8; /* guess */
- layout.dac_gain[ 1 ] = 9; /* guess */
-
+ layout.adc_pregain_offset = 0;
+ layout.adc_pregain_offset_fine = 8;
+ layout.adc_postgain_offset = 4;
+ layout.adc_gain = 2;
+ layout.adc_unip_offset = 7;
+ layout.dac_offset[ 0 ] = 6;
+ layout.dac_gain[ 0 ] = 11;
+ layout.dac_linearity[ 0 ] = 10;
+ layout.dac_offset[ 1 ] = 9;
+ layout.dac_gain[ 1 ] = 5;
+ layout.dac_linearity[1] = 1;
return cal_ni_generic( setup, &layout );
}
return cal_ni_generic( setup, &layout );
}
+static int cal_ni_daqcard_6036e( calibration_setup_t *setup )
+{
+ ni_caldac_layout_t layout;
+
+ if( comedi_get_version_code( setup->dev ) <= COMEDI_VERSION_CODE( 0, 7, 68 ) )
+ {
+ DPRINT(0, "WARNING: you need comedi driver version 0.7.69 or later\n"
+ "for this calibration to work properly\n" );
+ }
+
+ init_ni_caldac_layout( &layout );
+
+ layout.adc_pregain_offset = 0;
+ layout.adc_pregain_offset_fine = 8;
+ layout.adc_postgain_offset = 4;
+ layout.adc_gain = 2;
+
+ layout.dac_offset[0] = 6;
+ layout.dac_gain[0] = 7;
+ layout.dac_gain_fine[ 0 ] = 11;
+ layout.dac_linearity[0] = 10;
+
+ layout.dac_offset[ 1 ] = 9;
+ layout.dac_gain[ 1 ] = 3;
+ layout.dac_gain_fine[ 1 ] = 5;
+ layout.dac_linearity[1] = 1;
+
+ return cal_ni_generic( setup, &layout );
+}
+
static void prep_adc_caldacs_generic( calibration_setup_t *setup,
const ni_caldac_layout_t *layout, unsigned int range )
{
if( setup->old_calibration == NULL )
{
reset_caldac( setup, layout->dac_offset[ channel ] );
+ reset_caldac( setup, layout->dac_offset_fine[ channel ] );
reset_caldac( setup, layout->dac_gain[ channel ] );
reset_caldac( setup, layout->dac_gain_fine[ channel ] );
reset_caldac( setup, layout->dac_linearity[ channel ] );
{
DPRINT( 0, "Failed to apply existing calibration, reseting dac caldacs.\n" );
reset_caldac( setup, layout->dac_offset[ channel ] );
+ reset_caldac( setup, layout->dac_offset_fine[ channel ] );
reset_caldac( setup, layout->dac_gain[ channel ] );
reset_caldac( setup, layout->dac_gain_fine[ channel ] );
reset_caldac( setup, layout->dac_linearity[ channel ] );
layout->adc_unip_offset );
generic_do_cal( setup, current_cal, ni_unip_zero_offset_high,
layout->adc_unip_offset_fine );
+ /* if we don't have a unipolar offset caldac, do a fully
+ * independent calibration for unipolar ranges */
}else
{
prep_adc_caldacs_generic( setup, layout, ai_unipolar_lowgain );
generic_peg( setup, ni_unip_zero_offset_low,
layout->adc_pregain_offset, 1 );
- reset_caldac( setup, layout->adc_gain_fine );
+ generic_peg( setup, ni_unip_zero_offset_low,
+ layout->adc_postgain_offset, 1 );
generic_do_relative( setup, current_cal, ni_unip_zero_offset_low,
ni_unip_reference_low, layout->adc_gain );
- reset_caldac( setup, layout->adc_postgain_offset_fine );
generic_do_relative( setup, current_cal, ni_unip_zero_offset_low,
ni_unip_zero_offset_high, layout->adc_postgain_offset );
generic_do_relative( setup, current_cal, ni_unip_zero_offset_low,
ni_unip_zero_offset_high, layout->adc_postgain_offset_fine );
- reset_caldac( setup, layout->adc_pregain_offset_fine );
generic_do_cal( setup, current_cal, ni_unip_zero_offset_high,
layout->adc_pregain_offset );
generic_do_relative( setup, current_cal, ni_unip_zero_offset_low,
generic_do_linearity( setup, current_cal, ni_ao_zero_offset( channel ),
ni_ao_mid_linearity( channel ), ni_ao_reference( channel ),
layout->dac_linearity[ channel ] );
+ reset_caldac(setup, layout->dac_offset_fine[channel]);
generic_do_cal( setup, current_cal, ni_ao_zero_offset( channel ),
layout->dac_offset[ channel ] );
+ generic_do_cal( setup, current_cal, ni_ao_zero_offset( channel ),
+ layout->dac_offset_fine[ channel ] );
reset_caldac( setup, layout->dac_gain_fine[ channel ] );
generic_do_cal( setup, current_cal, ni_ao_reference( channel ),
layout->dac_gain[ channel ] );
generic_do_linearity( setup, current_cal, ni_ao_unip_low_linearity( channel ),
ni_ao_unip_mid_linearity( channel ), ni_ao_unip_reference( channel ),
layout->dac_linearity[ channel ] );
+ reset_caldac( setup, layout->dac_offset_fine[ channel ] );
generic_do_cal( setup, current_cal, ni_ao_unip_zero_offset( channel),
layout->dac_offset[ channel ] );
+ generic_do_cal( setup, current_cal, ni_ao_unip_zero_offset( channel),
+ layout->dac_offset_fine[ channel ] );
+ reset_caldac( setup, layout->dac_gain_fine[ channel ] );
generic_do_cal( setup, current_cal, ni_ao_unip_reference( channel ),
layout->dac_gain[ channel ] );
generic_do_cal( setup, current_cal, ni_ao_unip_reference( channel ),
static int ni67xx_ao_ground_observable_index( const calibration_setup_t *setup,
unsigned int channel, unsigned int ao_range )
{
- return 3 * channel;
+ return 3 * channel + 0;
}
static int ni67xx_ao_mid_observable_index( const calibration_setup_t *setup,
return 3 * channel + 2;
}
+static const double ni67xx_unitless_adc_offset = 0.5;
+
+/* determine conversion factor between actual voltage and
+ * interval [0,1) returned by reads from the calibration adc
+ * subdevice.
+ */
+static double ni67xx_unitless_adc_slope(calibration_setup_t *setup)
+{
+ double reference_in_volts;
+ double reference_unitless;
+ double slope;
+ comedi_insn insn;
+ lsampl_t data;
+ comedi_range *range;
+ static const int maxdata = 0x10000;
+ int retval;
+
+ if(ni_board(setup)->ref_eeprom_lsb >= 0 &&
+ ni_board(setup)->ref_eeprom_msb >= 0)
+ {
+ reference_in_volts = ni_get_reference(setup,
+ ni_board(setup)->ref_eeprom_lsb, ni_board(setup)->ref_eeprom_msb );
+ }else
+ {
+ DPRINT( 0, "WARNING: unknown eeprom address for reference voltage\n"
+ "correction. This might be fixable if you send us an eeprom dump\n"
+ "(see the demo/eeprom_dump program).\n");
+ reference_in_volts = 5.0;
+ }
+
+ memset(&insn, 0, sizeof(insn));
+ insn.insn = INSN_READ;
+ insn.n = 1;
+ insn.subdev = setup->ad_subdev;
+ insn.data = &data;
+ insn.chanspec = CR_PACK(0, 0, AREF_GROUND) | CR_ALT_SOURCE;
+ retval = comedi_do_insn(setup->dev, &insn);
+ assert(retval >= 0);
+
+ range = comedi_get_range(setup->dev, setup->ad_subdev, 0, 0);
+ assert( range );
+ reference_unitless = comedi_to_phys(data, range, maxdata);
+
+ slope = (reference_unitless - ni67xx_unitless_adc_offset) / reference_in_volts;
+
+ return slope;
+}
+
/* 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 void ni67xx_set_target( calibration_setup_t *setup, int obs, double target, double slope)
{
- 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;
+ /* convert target from volts to interval [0,1) which calibration
+ * adc returns */
+ setup->observables[obs].target *= slope;
+ setup->observables[obs].target += ni67xx_unitless_adc_offset;
}
static void ni67xx_setup_observables( calibration_setup_t *setup )
observable *o;
int num_ao_channels;
int i;
+ double slope;
+
+ slope = ni67xx_unitless_adc_slope(setup);
/* calibration adc is very slow (15HZ) but accurate, so only sample a few times */
setup->sv_order = 1;
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);
+ ni67xx_set_target(setup, ni67xx_ao_ground_observable_index(setup, i, 0), 0.0, slope);
setup->n_observables++;
o = setup->observables + ni67xx_ao_mid_observable_index( setup,
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);
+ ni67xx_set_target(setup, ni67xx_ao_mid_observable_index(setup, i, 0), 4.0, slope);
setup->n_observables++;
o = setup->observables + ni67xx_ao_high_observable_index( setup, i, 0);
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);
+ ni67xx_set_target(setup, ni67xx_ao_high_observable_index(setup, i, 0), 8.0, slope);
setup->n_observables++;
}