2 A little auto-calibration utility, for boards
5 copyright (C) 1999,2000,2001,2002 by David Schleef
6 copyright (C) 2003 by Frank Mori Hess
8 A few things need improvement here:
9 - current system gets "close", but doesn't
11 - statistics would be nice, to show how good
16 /***************************************************************************
18 * This program is free software; you can redistribute it and/or modify *
19 * it under the terms of the GNU Lesser General Public License as *
21 * the Free Software Foundation; either version 2.1 of the License, or *
22 * (at your option) any later version. *
24 ***************************************************************************/
42 char ni_id[] = "$Id$";
47 int (*cal)( calibration_setup_t *setup);
48 void (*setup_observables)( calibration_setup_t *setup );
53 static int ni_setup_board( calibration_setup_t *setup , const char *device_name );
54 static void ni_setup_observables( calibration_setup_t *setup );
55 static void ni_setup_observables_611x( calibration_setup_t *setup );
57 static int cal_ni_at_mio_16e_2(calibration_setup_t *setup);
58 static int cal_ni_daqcard_ai_16xe_50(calibration_setup_t *setup);
59 static int cal_ni_at_mio_16e_1(calibration_setup_t *setup);
60 static int cal_ni_pci_mio_16e_1(calibration_setup_t *setup);
61 static int cal_ni_pci_6024e(calibration_setup_t *setup);
62 static int cal_ni_pci_6025e(calibration_setup_t *setup);
63 static int cal_ni_pci_6035e(calibration_setup_t *setup);
64 static int cal_ni_pci_6071e(calibration_setup_t *setup);
65 static int cal_ni_pxi_6071e(calibration_setup_t *setup);
66 static int cal_ni_at_mio_16e_10(calibration_setup_t *setup);
67 static int cal_ni_pci_mio_16xe_50(calibration_setup_t *setup);
68 static int cal_ni_pci_6023e(calibration_setup_t *setup);
69 static int cal_ni_at_mio_16xe_50(calibration_setup_t *setup);
70 static int cal_ni_pci_mio_16xe_10(calibration_setup_t *setup);
71 static int cal_ni_pci_6052e(calibration_setup_t *setup);
72 static int cal_ni_pci_6032e(calibration_setup_t *setup);
73 static int cal_ni_daqcard_ai_16e_4(calibration_setup_t *setup);
74 static int cal_ni_pci_611x(calibration_setup_t *setup);
75 static int cal_ni_pci_mio_16e_4(calibration_setup_t *setup);
76 static int cal_ni_daqcard_6062e(calibration_setup_t *setup);
77 static int cal_ni_daqcard_6024e(calibration_setup_t *setup);
79 static double ni_get_reference( calibration_setup_t *setup, int lsb_loc,int msb_loc);
81 static struct board_struct boards[]={
82 { "at-mio-16e-2", STATUS_DONE, cal_ni_at_mio_16e_2, ni_setup_observables, 0x1a9, 0x1aa },
83 { "DAQCard-ai-16xe-50", STATUS_DONE, cal_ni_daqcard_ai_16xe_50, ni_setup_observables, 0x1be, 0x1bf },
84 { "at-mio-16xe-50", STATUS_SOME, cal_ni_at_mio_16xe_50, ni_setup_observables, 0x1b5, 0x1b6 },
85 { "at-mio-16e-1", STATUS_SOME, cal_ni_at_mio_16e_1, ni_setup_observables, 0x1a9, 0x1aa },
86 { "pci-mio-16e-1", STATUS_DONE, cal_ni_pci_mio_16e_1, ni_setup_observables, 0x1a9, 0x1aa },
87 { "pci-6025e", STATUS_SOME, cal_ni_pci_6025e, ni_setup_observables, 0x1af, 0x1b0 },
88 { "pci-6035e", STATUS_DONE, cal_ni_pci_6035e, ni_setup_observables, 0x1af, 0x1b0 },
89 { "pci-6071e", STATUS_SOME, cal_ni_pci_6071e, ni_setup_observables, 0x1a9, 0x1aa },
90 { "pxi-6071e", STATUS_GUESS, cal_ni_pxi_6071e, ni_setup_observables, -1, -1 },
91 { "at-mio-16e-10", STATUS_GUESS, cal_ni_at_mio_16e_10, ni_setup_observables, 0x1a7, 0x1a8 },
92 { "pci-mio-16xe-50", STATUS_SOME, cal_ni_pci_mio_16xe_50, ni_setup_observables, 0x1b5, 0x1b6 },
93 { "pci-6023e", STATUS_DONE, cal_ni_pci_6023e, ni_setup_observables, 0x1bb, 0x1bc },
94 { "pci-mio-16xe-10", STATUS_DONE, cal_ni_pci_mio_16xe_10, ni_setup_observables, 0x1ae, 0x1af },
95 { "pci-6052e", STATUS_DONE, cal_ni_pci_6052e, ni_setup_observables, 0x19f, 0x1a0 },
96 { "pci-6024e", STATUS_SOME, cal_ni_pci_6024e, ni_setup_observables, 0x1af, 0x1b0 },
97 { "pci-mio-16e-4", STATUS_SOME, cal_ni_pci_mio_16e_4, ni_setup_observables, 0x1a9, 0x1aa },
98 { "pci-6032e", STATUS_DONE, cal_ni_pci_6032e, ni_setup_observables, 0x1ae, 0x1af },
99 { "DAQCard-ai-16e-4", STATUS_DONE, cal_ni_daqcard_ai_16e_4, ni_setup_observables, 0x1b5, 0x1b6 },
100 { "pci-6110", STATUS_DONE, cal_ni_pci_611x, ni_setup_observables_611x, 0x1d4, 0x1d5 },
101 { "pci-6111", STATUS_DONE, cal_ni_pci_611x, ni_setup_observables_611x, 0x1d4, 0x1d5 },
102 { "DAQCard-6062E", STATUS_DONE, cal_ni_daqcard_6062e, ni_setup_observables, 0x1a9, 0x1aa },
103 { "DAQCard-6024E", STATUS_SOME, cal_ni_daqcard_6024e, ni_setup_observables, -1, -1 },
104 { "at-mio-16de-10", STATUS_UNKNOWN, NULL, ni_setup_observables, 0x1a7, 0x1a8 },
105 { "at-mio-16xe-10", STATUS_UNKNOWN, NULL, ni_setup_observables, 0x1b7, 0x1b8 },
106 { "at-ai-16xe-10", STATUS_UNKNOWN, NULL, ni_setup_observables, 0x1b7, 0x1b8 },
107 { "pci-6031e", STATUS_UNKNOWN, NULL, ni_setup_observables, 0x1ae, 0x1af },
108 { "pci-6033e", STATUS_UNKNOWN, NULL, ni_setup_observables, 0x1ae, 0x1af },
110 { "at-mio-64e-3", cal_ni_16e_1 },
111 // { "at-mio-16xe-50", cal_ni_unknown },
112 // { "pxi-6030e", cal_ni_unknown },
113 // { "pxi-6040e", cal_ni_unknown },
114 { "pxi-6025e", cal_ni_6023e }, // guess
115 { "pci-6034e", cal_ni_6023e }, // guess
116 // { "pci-6711", cal_ni_unknown },
117 // { "pci-6713", cal_ni_unknown },
118 // { "pxi-6070e", cal_ni_unknown },
119 // { "pxi-6052e", cal_ni_unknown },
122 #define n_boards (sizeof(boards)/sizeof(boards[0]))
124 static const int ni_num_observables = 18;
126 ni_zero_offset_low = 0,
129 ni_unip_zero_offset_low,
130 ni_unip_zero_offset_high,
131 ni_unip_reference_low,
138 ni_ao0_unip_zero_offset,
139 ni_ao0_unip_reference,
140 ni_ao0_unip_linearity,
141 ni_ao1_unip_zero_offset,
142 ni_ao1_unip_reference,
143 ni_ao1_unip_linearity,
145 static inline unsigned int ni_ao_zero_offset( unsigned int channel )
147 if( channel ) return ni_ao1_zero_offset;
148 else return ni_ao0_zero_offset;
150 static inline unsigned int ni_ao_reference( unsigned int channel )
152 if( channel ) return ni_ao1_reference;
153 else return ni_ao0_reference;
155 static inline unsigned int ni_ao_linearity( unsigned int channel )
157 if( channel ) return ni_ao1_linearity;
158 else return ni_ao0_linearity;
160 static inline unsigned int ni_ao_unip_zero_offset( unsigned int channel )
162 if( channel ) return ni_ao1_unip_zero_offset;
163 else return ni_ao0_unip_zero_offset;
165 static inline unsigned int ni_ao_unip_reference( unsigned int channel )
167 if( channel ) return ni_ao1_unip_reference;
168 else return ni_ao0_unip_reference;
170 static inline unsigned int ni_ao_unip_linearity( unsigned int channel )
172 if( channel ) return ni_ao1_unip_linearity;
173 else return ni_ao0_unip_linearity;
176 static const int num_ao_observables_611x = 4;
177 static int ni_ao_zero_offset_611x( const calibration_setup_t *setup,
178 unsigned int channel, unsigned int range ) {
182 static int ni_ao_reference_611x( const calibration_setup_t *setup,
183 unsigned int channel, unsigned int range ) {
185 return 2 * channel + 1;
187 static int ni_zero_offset_611x( const calibration_setup_t *setup,
188 unsigned int channel, unsigned int range ) {
189 return num_ao_observables_611x + 8 * range + 2 * channel;
191 static int ni_reference_611x( const calibration_setup_t *setup,
192 unsigned int channel, unsigned int range ) {
193 return num_ao_observables_611x + 8 * range + 2 * channel + 1;
196 enum reference_sources {
201 REF_CALSRC_CALSRC = 4,
206 static inline unsigned int REF_DAC_GND( unsigned int channel )
208 if( channel ) return REF_DAC1_GND;
209 else return REF_DAC0_GND;
211 static inline unsigned int REF_DAC_CALSRC( unsigned int channel )
213 if( channel ) return REF_DAC1_CALSRC;
214 else return REF_DAC0_CALSRC;
217 static struct board_struct* ni_board( calibration_setup_t *setup )
219 return setup->private_data;
224 int adc_pregain_offset;
225 int adc_postgain_offset;
227 int adc_pregain_offset_fine;
228 int adc_postgain_offset_fine;
233 int dac_gain_fine[ 2 ];
234 int dac_linearity[ 2 ];
235 } ni_caldac_layout_t;
237 static int cal_ni_generic( calibration_setup_t *setup,
238 const ni_caldac_layout_t *layout );
240 static inline void init_ni_caldac_layout( ni_caldac_layout_t *layout )
244 layout->adc_pregain_offset = -1;
245 layout->adc_postgain_offset = -1;
246 layout->adc_gain = -1;
247 layout->adc_unip_offset = -1;
248 layout->adc_pregain_offset_fine = -1;
249 layout->adc_postgain_offset_fine = -1;
250 layout->adc_gain_fine = -1;
251 for( i = 0; i < 2; i++ )
253 layout->dac_offset[ i ] = -1;
254 layout->dac_gain[ i ] = -1;
255 layout->dac_gain_fine[ i ] = -1;
256 layout->dac_linearity[ i ] = -1;
260 int ni_setup( calibration_setup_t *setup , const char *device_name )
264 retval = ni_setup_board( setup, device_name );
265 if( retval < 0 ) return retval;
266 setup_caldacs( setup, setup->caldac_subdev );
271 static int ni_setup_board( calibration_setup_t *setup, const char *device_name )
275 for(i = 0; i < n_boards; i++ ){
276 if(!strcmp( device_name, boards[i].name )){
277 setup->status = boards[i].status;
278 setup->do_cal = boards[i].cal;
279 setup->private_data = &boards[ i ];
280 boards[i].setup_observables( setup );
284 if( i == n_boards ) return -1;
288 static void ni_setup_ao_observables( calibration_setup_t *setup )
291 comedi_insn tmpl, po_tmpl;
292 unsigned int channel;
293 int ai_bipolar_lowgain;
294 int ao_bipolar_lowgain;
295 int ao_unipolar_lowgain;
297 ai_bipolar_lowgain = get_bipolar_lowgain( setup->dev, setup->ad_subdev);
298 ao_bipolar_lowgain = get_bipolar_lowgain( setup->dev, setup->da_subdev);
299 ao_unipolar_lowgain = get_unipolar_lowgain( setup->dev, setup->da_subdev);
301 memset(&tmpl,0,sizeof(tmpl));
302 tmpl.insn = INSN_READ;
304 tmpl.subdev = setup->ad_subdev;
306 memset(&po_tmpl, 0, sizeof(po_tmpl));
307 po_tmpl.insn = INSN_WRITE;
309 po_tmpl.subdev = setup->da_subdev;
311 for( channel = 0; channel < 2; channel++ )
314 o = setup->observables + ni_ao_zero_offset( channel );
315 assert( o->name == NULL );
316 asprintf( &o->name, "ao %i, zero offset, low gain", channel );
317 o->preobserve_insn = po_tmpl;
318 o->preobserve_insn.chanspec = CR_PACK(channel,ao_bipolar_lowgain,0);
319 o->preobserve_insn.data = o->preobserve_data;
320 o->observe_insn = tmpl;
321 o->observe_insn.chanspec =
322 CR_PACK(REF_DAC_GND( channel ),ai_bipolar_lowgain,AREF_OTHER)
323 | CR_ALT_SOURCE | CR_ALT_FILTER;
324 o->reference_source = REF_DAC_GND( channel );
325 set_target( setup, ni_ao_zero_offset( channel ),0.0);
328 o = setup->observables + ni_ao_reference( channel );
329 assert( o->name == NULL );
330 asprintf( &o->name, "ao %i, reference voltage, low gain", channel );
331 o->preobserve_insn = po_tmpl;
332 o->preobserve_insn.chanspec = CR_PACK(channel,ao_bipolar_lowgain,0);
333 o->preobserve_insn.data = o->preobserve_data;
334 o->observe_insn = tmpl;
335 o->observe_insn.chanspec =
336 CR_PACK(REF_DAC_GND( channel ),ai_bipolar_lowgain,AREF_OTHER)
337 | CR_ALT_SOURCE | CR_ALT_FILTER;
338 o->reference_source = REF_DAC_GND( channel );
339 set_target( setup, ni_ao_reference( channel ),5.0);
341 /* ao linearity, negative */
342 o = setup->observables + ni_ao_linearity( channel );
343 assert( o->name == NULL );
344 asprintf( &o->name, "ao %i, linearity (negative), low gain", channel );
345 o->preobserve_insn = po_tmpl;
346 o->preobserve_insn.chanspec = CR_PACK(channel,ao_bipolar_lowgain,0);
347 o->preobserve_insn.data = o->preobserve_data;
348 o->observe_insn = tmpl;
349 o->observe_insn.chanspec =
350 CR_PACK(REF_DAC_GND( channel ),ai_bipolar_lowgain,AREF_OTHER)
351 | CR_ALT_SOURCE | CR_ALT_FILTER;
352 o->reference_source = REF_DAC_GND( channel );
353 set_target( setup, ni_ao_linearity( channel ),-5.0);
355 if( ao_unipolar_lowgain >= 0 )
357 /* ao unipolar zero offset */
358 o = setup->observables + ni_ao_unip_zero_offset( channel );
359 assert( o->name == NULL );
360 asprintf( &o->name, "ao %i, unipolar zero offset, low gain", channel );
361 o->preobserve_insn = po_tmpl;
362 o->preobserve_insn.chanspec = CR_PACK(channel,ao_unipolar_lowgain,0);
363 o->preobserve_insn.data = o->preobserve_data;
364 o->observe_insn = tmpl;
365 o->observe_insn.chanspec =
366 CR_PACK(REF_DAC_GND( channel ),ai_bipolar_lowgain,AREF_OTHER)
367 | CR_ALT_SOURCE | CR_ALT_FILTER;
368 o->reference_source = REF_DAC_GND( channel );
369 set_target( setup, ni_ao_zero_offset( channel ),0.0);
371 /* ao unipolar gain */
372 o = setup->observables + ni_ao_unip_reference( channel );
373 assert( o->name == NULL );
374 asprintf( &o->name, "ao %i, unipolar high, low gain", channel );
375 o->preobserve_insn = po_tmpl;
376 o->preobserve_insn.chanspec = CR_PACK(channel,ao_unipolar_lowgain,0);
377 o->preobserve_insn.data = o->preobserve_data;
378 o->observe_insn = tmpl;
379 o->observe_insn.chanspec =
380 CR_PACK(REF_DAC_GND( channel ),ai_bipolar_lowgain,AREF_OTHER)
381 | CR_ALT_SOURCE | CR_ALT_FILTER;
382 o->reference_source = REF_DAC_GND( channel );
383 set_target( setup, ni_ao_reference( channel ),8.0);
385 /* ao unipolar linearity, negative */
386 o = setup->observables + ni_ao_unip_linearity( channel );
387 assert( o->name == NULL );
388 asprintf( &o->name, "ao %i, unipolar linearity (mid), low gain", channel );
389 o->preobserve_insn = po_tmpl;
390 o->preobserve_insn.chanspec = CR_PACK(channel,ao_unipolar_lowgain,0);
391 o->preobserve_insn.data = o->preobserve_data;
392 o->observe_insn = tmpl;
393 o->observe_insn.chanspec =
394 CR_PACK(REF_DAC_GND( channel ),ai_bipolar_lowgain,AREF_OTHER)
395 | CR_ALT_SOURCE | CR_ALT_FILTER;
396 o->reference_source = REF_DAC_GND( channel );
397 set_target( setup, ni_ao_linearity( channel ),4.0);
402 static void ni_setup_observables( calibration_setup_t *setup )
406 int bipolar_highgain;
407 int unipolar_lowgain;
408 int unipolar_highgain;
409 double voltage_reference;
412 bipolar_lowgain = get_bipolar_lowgain( setup->dev, setup->ad_subdev);
413 bipolar_highgain = get_bipolar_highgain( setup->dev, setup->ad_subdev);
414 unipolar_lowgain = get_unipolar_lowgain( setup->dev, setup->ad_subdev);
415 unipolar_highgain = get_unipolar_highgain( setup->dev, setup->ad_subdev);
417 if( ni_board( setup )->ref_eeprom_lsb >= 0 &&
418 ni_board( setup )->ref_eeprom_msb >= 0 )
420 voltage_reference = ni_get_reference( setup,
421 ni_board( setup )->ref_eeprom_lsb, ni_board( setup )->ref_eeprom_msb );
424 DPRINT( 0, "WARNING: unknown eeprom address for reference voltage\n"
425 "correction. This might be fixable if you send us an eeprom dump\n"
426 "(see the demo/eeprom_dump program).\n");
427 voltage_reference = 5.0;
430 memset(&tmpl,0,sizeof(tmpl));
431 tmpl.insn = INSN_READ;
433 tmpl.subdev = setup->ad_subdev;
435 setup->n_observables = ni_num_observables;
437 /* 0 offset, low gain */
438 o = setup->observables + ni_zero_offset_low;
439 o->name = "ai, bipolar zero offset, low gain";
440 o->observe_insn = tmpl;
441 o->observe_insn.chanspec = CR_PACK(REF_GND_GND,bipolar_lowgain,AREF_OTHER)
442 | CR_ALT_SOURCE | CR_ALT_FILTER;
443 o->reference_source = REF_GND_GND;
446 /* 0 offset, high gain */
447 o = setup->observables + ni_zero_offset_high;
448 o->name = "ai, bipolar zero offset, high gain";
449 o->observe_insn = tmpl;
450 o->observe_insn.chanspec = CR_PACK(REF_GND_GND,bipolar_highgain,AREF_OTHER)
451 | CR_ALT_SOURCE | CR_ALT_FILTER;
452 o->reference_source = REF_GND_GND;
455 /* voltage reference */
456 o = setup->observables + ni_reference_low;
457 o->name = "ai, bipolar voltage reference, low gain";
458 o->observe_insn = tmpl;
459 o->observe_insn.chanspec = CR_PACK(REF_CALSRC_GND,bipolar_lowgain,AREF_OTHER)
460 | CR_ALT_SOURCE | CR_ALT_FILTER;
461 o->reference_source = REF_CALSRC_GND;
462 o->target = voltage_reference;
464 if(unipolar_lowgain>=0){
465 o = setup->observables + ni_unip_zero_offset_low;
466 o->name = "ai, unipolar zero offset, low gain";
467 o->observe_insn = tmpl;
468 o->observe_insn.chanspec =
469 CR_PACK(REF_GND_GND,unipolar_lowgain,AREF_OTHER)
470 | CR_ALT_SOURCE | CR_ALT_FILTER;
471 o->reference_source = REF_GND_GND;
472 o->target = very_low_target( setup->dev, setup->ad_subdev, 0, unipolar_lowgain );
474 o = setup->observables + ni_unip_reference_low;
475 o->name = "ai, unipolar voltage reference, low gain";
476 o->observe_insn = tmpl;
477 o->observe_insn.chanspec =
478 CR_PACK(REF_CALSRC_GND,unipolar_lowgain,AREF_OTHER)
479 | CR_ALT_SOURCE | CR_ALT_FILTER;
480 o->reference_source = REF_CALSRC_GND;
481 o->target = voltage_reference;
484 if(unipolar_highgain >= 0)
486 o = setup->observables + ni_unip_zero_offset_high;
487 o->name = "ai, unipolar zero offset, high gain";
488 o->observe_insn = tmpl;
489 o->observe_insn.chanspec =
490 CR_PACK(REF_GND_GND,unipolar_highgain,AREF_OTHER)
491 | CR_ALT_SOURCE | CR_ALT_FILTER;
492 o->reference_source = REF_GND_GND;
493 o->target = very_low_target( setup->dev, setup->ad_subdev, 0, unipolar_highgain );
496 if(setup->da_subdev >= 0)
497 ni_setup_ao_observables( setup );
500 /* for +-50V and +-20V ranges, the reference source goes 0V
501 * to 50V instead of 0V to 5V */
502 static unsigned int cal_gain_register_bits_611x( double reference, double *voltage )
506 bits = 200.0 * ( *voltage / reference );
507 if( bits > 200 ) bits = 200;
509 *voltage = reference * ( bits / 200.0 );
513 static unsigned int ref_source_611x( unsigned int ref_source, unsigned int cal_gain_bits )
515 return ( ref_source & 0xf ) | ( ( cal_gain_bits << 4 ) & 0xff0 );
518 static void reference_target_611x( calibration_setup_t *setup,
519 observable *o, double master_reference, unsigned int range )
521 int cal_gain_reg_bits;
524 comedi_range *range_ptr;
526 range_ptr = comedi_get_range( setup->dev, setup->ad_subdev, 0, range );
527 assert( range_ptr != NULL );
528 if( range_ptr->max > 19.0 ) reference = 10 * master_reference;
529 else reference = master_reference;
530 target = range_ptr->max * 0.9;
532 cal_gain_reg_bits = cal_gain_register_bits_611x( reference, &target );
534 o->reference_source = ref_source_611x( REF_CALSRC_GND, cal_gain_reg_bits );
538 static void ni_setup_observables_611x( calibration_setup_t *setup )
543 double master_reference;
545 int num_ai_channels, num_ai_ranges;
546 static const int num_ao_channels = 2;
548 setup->settling_time_ns = 1000000;
550 master_reference = ni_get_reference( setup,
551 ni_board( setup )->ref_eeprom_lsb, ni_board( setup )->ref_eeprom_msb );
553 memset(&tmpl,0,sizeof(tmpl));
554 tmpl.insn = INSN_READ;
556 tmpl.subdev = setup->ad_subdev;
558 num_ai_channels = comedi_get_n_channels( setup->dev, setup->ad_subdev );
559 assert( num_ai_channels >= 0 );
560 num_ai_ranges = comedi_get_n_ranges( setup->dev, setup->ad_subdev, 0 );
561 assert( num_ai_ranges >= 0 );
563 for( channel = 0; channel < num_ai_channels; channel++ )
565 for( range = 0; range < num_ai_ranges; range++ )
568 o = setup->observables + ni_zero_offset_611x( setup, channel, range );
569 assert( o->name == NULL );
570 asprintf( &o->name, "ai, ch %i, range %i, zero offset",
572 o->observe_insn = tmpl;
573 o->observe_insn.chanspec = CR_PACK( channel, range, AREF_DIFF )
574 | CR_ALT_SOURCE | CR_ALT_FILTER;
575 o->reference_source = REF_GND_GND;
578 /* voltage reference */
579 o = setup->observables + ni_reference_611x( setup, channel, range );
580 assert( o->name == NULL );
581 asprintf( &o->name, "ai, ch %i, range %i, voltage reference",
583 o->observe_insn = tmpl;
584 o->observe_insn.chanspec = CR_PACK( channel, range, AREF_DIFF )
585 | CR_ALT_SOURCE | CR_ALT_FILTER;
586 reference_target_611x( setup, o, master_reference, range );
590 memset(&po_tmpl,0,sizeof(po_tmpl));
591 po_tmpl.insn = INSN_WRITE;
593 po_tmpl.subdev = setup->da_subdev;
595 for( channel = 0; channel < num_ao_channels; channel ++ )
597 static const int ai_range_for_ao = 2;
600 o = setup->observables + ni_ao_zero_offset_611x( setup, channel, 0 );
601 assert( o->name == NULL );
602 asprintf( &o->name, "ao ch %i, zero offset", channel );
603 o->preobserve_insn = po_tmpl;
604 o->preobserve_insn.chanspec = CR_PACK( channel, 0, AREF_GROUND );
605 o->preobserve_insn.data = o->preobserve_data;
606 o->observe_insn = tmpl;
607 o->observe_insn.chanspec = CR_PACK( 0, ai_range_for_ao, AREF_DIFF )
608 | CR_ALT_SOURCE | CR_ALT_FILTER;
609 o->reference_source = REF_DAC0_GND;
610 set_target( setup, ni_ao_zero_offset_611x( setup, channel, 0 ), 0.0 );
613 o = setup->observables + ni_ao_reference_611x( setup, channel, 0 );
614 assert( o->name == NULL );
615 asprintf( &o->name, "ao ch %i, reference voltage", channel );
616 o->preobserve_insn = po_tmpl;
617 o->preobserve_insn.chanspec = CR_PACK( channel, 0, AREF_GROUND );
618 o->preobserve_insn.data = o->preobserve_data;
619 o->observe_insn = tmpl;
620 o->observe_insn.chanspec = CR_PACK( 0, ai_range_for_ao, AREF_DIFF )
621 | CR_ALT_SOURCE | CR_ALT_FILTER;
622 o->reference_source = REF_DAC0_GND;
623 set_target( setup, ni_ao_reference_611x( setup, channel, 0 ), 5.0 );
626 setup->n_observables = num_ao_observables_611x + 2 * num_ai_ranges * num_ai_channels;
629 static int cal_ni_at_mio_16e_2(calibration_setup_t *setup)
631 ni_caldac_layout_t layout;
633 init_ni_caldac_layout( &layout );
634 layout.adc_pregain_offset = 0;
635 layout.adc_postgain_offset = 1;
637 layout.adc_unip_offset = 2;
638 layout.dac_offset[ 0 ] = 5;
639 layout.dac_gain[ 0 ] = 6;
640 layout.dac_offset[ 1 ] = 8;
641 layout.dac_gain[ 1 ] = 9;
643 return cal_ni_generic( setup, &layout );
647 * Device name: DAQCard-ai-16xe-50
648 * Comedi version: 0.7.60
649 * ai, bipolar zero offset, low gain
650 * offset 5.87(63)e-3, target 0
651 * caldac[0] gain=-2.243(21)e-6 V/bit S_min=208.079 dof=254
652 * caldac[2] gain=1.56378(22)e-4 V/bit S_min=1782.91 dof=254
653 * caldac[8] gain=2.499(14)e-7 V/bit S_min=234.915 dof=254
654 * ai, bipolar zero offset, high gain
655 * offset 4.251(49)e-5, target 0
656 * caldac[0] gain=-2.396(30)e-8 V/bit S_min=231.387 dof=254
657 * caldac[2] gain=1.56428(28)e-6 V/bit S_min=829.096 dof=254
658 * caldac[8] gain=2.61244(18)e-7 V/bit S_min=773.092 dof=254
659 * ai, bipolar voltage reference, low gain
660 * offset 4.99650(81), target 5
661 * caldac[0] gain=-3.78250(23)e-4 V/bit S_min=12207.6 dof=254
662 * caldac[1] gain=-9.878(22)e-6 V/bit S_min=346.795 dof=254
663 * caldac[2] gain=1.57172(23)e-4 V/bit S_min=969.526 dof=254
664 * caldac[8] gain=2.795(14)e-7 V/bit S_min=245.703 dof=254
665 * ai, unipolar zero offset, low gain
666 * offset 0.0133(14), target 0
667 * caldac[0] gain=3.73923(29)e-4 V/bit S_min=2855.79 dof=151
668 * caldac[1] gain=9.784(11)e-6 V/bit S_min=727.295 dof=254
669 * caldac[2] gain=7.8670(11)e-5 V/bit S_min=903.291 dof=254
670 * caldac[8] gain=2.7732(74)e-7 V/bit S_min=415.399 dof=254
672 static int cal_ni_daqcard_ai_16xe_50(calibration_setup_t *setup)
674 ni_caldac_layout_t layout;
676 init_ni_caldac_layout( &layout );
677 layout.adc_pregain_offset = 8;
678 layout.adc_postgain_offset = 2;
680 layout.adc_gain_fine = 1;
682 return cal_ni_generic( setup, &layout );
685 static int cal_ni_at_mio_16xe_50(calibration_setup_t *setup)
687 ni_caldac_layout_t layout;
689 init_ni_caldac_layout( &layout );
690 layout.adc_pregain_offset = 8;
691 layout.adc_postgain_offset = 2;
693 layout.adc_gain_fine = 1;
694 layout.dac_offset[ 0 ] = 6;
695 layout.dac_gain[ 0 ] = 4;
696 layout.dac_offset[ 1 ] = 7;
697 layout.dac_gain[ 1 ] = 5;
699 return cal_ni_generic( setup, &layout );
702 static int cal_ni_pci_mio_16xe_10(calibration_setup_t *setup)
704 ni_caldac_layout_t layout;
706 init_ni_caldac_layout( &layout );
707 layout.adc_pregain_offset = 8;
708 layout.adc_postgain_offset = 2;
709 layout.adc_postgain_offset_fine = 3;
711 layout.adc_gain_fine = 1;
712 layout.dac_offset[ 0 ] = 6;
713 layout.dac_gain[ 0 ] = 4;
714 layout.dac_offset[ 1 ] = 7;
715 layout.dac_gain[ 1 ] = 5;
717 return cal_ni_generic( setup, &layout );
720 static int cal_ni_at_mio_16e_1(calibration_setup_t *setup)
722 return cal_ni_at_mio_16e_2( setup );
725 static int cal_ni_pci_mio_16e_1(calibration_setup_t *setup)
727 ni_caldac_layout_t layout;
729 init_ni_caldac_layout( &layout );
730 layout.adc_pregain_offset = 0;
731 layout.adc_postgain_offset = 1;
732 layout.adc_unip_offset = 2;
734 layout.dac_offset[ 0 ] = 5;
735 layout.dac_gain[ 0 ] = 6;
736 layout.dac_linearity[ 0 ] = 4;
737 layout.dac_offset[ 1 ] = 8;
738 layout.dac_gain[ 1 ] = 9;
739 layout.dac_linearity[ 1 ] = 7;
741 return cal_ni_generic( setup, &layout );
744 static int cal_ni_pci_6032e(calibration_setup_t *setup)
746 ni_caldac_layout_t layout;
748 init_ni_caldac_layout( &layout );
749 layout.adc_pregain_offset = 8;
750 layout.adc_postgain_offset = 2;
751 layout.adc_postgain_offset_fine = 3;
753 layout.adc_gain_fine = 1;
755 return cal_ni_generic( setup, &layout );
758 static int cal_ni_pci_6035e(calibration_setup_t *setup)
760 /* this is for the ad8804_debug caldac */
761 ni_caldac_layout_t layout;
763 init_ni_caldac_layout( &layout );
764 layout.adc_pregain_offset = 0;
765 layout.adc_pregain_offset_fine = 8;
766 layout.adc_postgain_offset = 4;
768 layout.dac_offset[ 0 ] = 6;
769 layout.dac_gain[ 0 ] = 11;
770 layout.dac_linearity[ 0 ] = 10;
771 layout.dac_offset[ 1 ] = 9;
772 layout.dac_gain[ 1 ] = 5;
773 layout.dac_linearity[ 1 ] = 1;
775 return cal_ni_generic( setup, &layout );
778 static int cal_ni_pci_6071e(calibration_setup_t *setup)
780 ni_caldac_layout_t layout;
782 if( comedi_get_version_code( setup->dev ) <= COMEDI_VERSION_CODE( 0, 7, 66 ) )
784 DPRINT(0, "WARNING: you need comedi driver version 0.7.67 or later\n"
785 "for this calibration to work properly\n" );
788 init_ni_caldac_layout( &layout );
789 layout.adc_pregain_offset = 0;
790 layout.adc_pregain_offset_fine = 8;
791 layout.adc_postgain_offset = 4;
793 layout.dac_offset[ 0 ] = 6;
794 layout.dac_gain[ 0 ] = 11;
795 layout.dac_linearity[ 0 ] = 10;
796 layout.dac_offset[ 1 ] = 9;
797 layout.dac_gain[ 1 ] = 5;
798 layout.dac_linearity[ 1 ] = 1;
799 return cal_ni_generic( setup, &layout );
802 static int cal_ni_pxi_6071e(calibration_setup_t *setup)
804 ni_caldac_layout_t layout;
806 if( comedi_get_version_code( setup->dev ) <= COMEDI_VERSION_CODE( 0, 7, 66 ) )
808 DPRINT(0, "WARNING: you need comedi driver version 0.7.67 or later\n"
809 "for this calibration to work properly\n" );
812 init_ni_caldac_layout( &layout );
813 layout.adc_pregain_offset = 0;
814 layout.adc_pregain_offset_fine = 8;
815 layout.adc_postgain_offset = 4;
817 layout.dac_offset[ 0 ] = 6;
818 layout.dac_gain[ 0 ] = 11;
819 layout.dac_linearity[ 0 ] = 10;
820 layout.dac_offset[ 1 ] = 9;
821 layout.dac_gain[ 1 ] = 5;
822 layout.dac_linearity[ 1 ] = 1;
823 return cal_ni_generic( setup, &layout );
826 static int cal_ni_at_mio_16e_10(calibration_setup_t *setup)
829 ni_caldac_layout_t layout;
831 init_ni_caldac_layout( &layout );
832 layout.adc_pregain_offset = 10;
833 layout.adc_pregain_offset_fine = 0;
834 layout.adc_postgain_offset = 1;
836 layout.adc_unip_offset = 2;
837 layout.dac_offset[ 0 ] = 5; /* guess */
838 layout.dac_gain[ 0 ] = 6; /* guess */
839 layout.dac_offset[ 1 ] = 8; /* guess */
840 layout.dac_gain[ 1 ] = 9; /* guess */
842 return cal_ni_generic( setup, &layout );
845 static int cal_ni_pci_mio_16xe_50(calibration_setup_t *setup)
847 ni_caldac_layout_t layout;
849 init_ni_caldac_layout( &layout );
850 layout.adc_pregain_offset = 8;
851 layout.adc_postgain_offset = 2;
853 layout.adc_gain_fine = 1;
854 layout.adc_unip_offset = 7;
855 layout.dac_offset[ 0 ] = 6;
856 layout.dac_gain[ 0 ] = 4;
857 layout.dac_offset[ 1 ] = 7;
858 layout.dac_gain[ 1 ] = 5;
860 return cal_ni_generic( setup, &layout );
863 static int cal_ni_pci_6023e(calibration_setup_t *setup)
865 /* for comedi-0.7.65 */
866 ni_caldac_layout_t layout;
868 init_ni_caldac_layout( &layout );
869 layout.adc_pregain_offset = 8; /* possibly wrong */
870 layout.adc_pregain_offset_fine = 0;
871 layout.adc_postgain_offset = 4;
874 return cal_ni_generic( setup, &layout );
877 static int cal_ni_pci_6024e(calibration_setup_t *setup)
879 ni_caldac_layout_t layout;
881 init_ni_caldac_layout( &layout );
882 layout.adc_pregain_offset = 8;
883 layout.adc_postgain_offset = 4;
884 layout.adc_pregain_offset_fine = 0;
886 layout.dac_offset[ 0 ] = 6;
887 layout.dac_gain[ 0 ] = 11;
888 layout.dac_linearity[ 0 ] = 10;
889 layout.dac_offset[ 1 ] = 9;
890 layout.dac_gain[ 1 ] = 5;
891 layout.dac_linearity[ 1 ] = 1;
893 return cal_ni_generic( setup, &layout );
896 static int cal_ni_pci_6025e(calibration_setup_t *setup)
898 ni_caldac_layout_t layout;
900 init_ni_caldac_layout( &layout );
901 layout.adc_pregain_offset = 8;
902 layout.adc_postgain_offset = 4;
903 layout.adc_pregain_offset_fine = 0;
905 layout.dac_offset[ 0 ] = 6;
906 layout.dac_gain[ 0 ] = 11;
907 layout.dac_linearity[ 0 ] = 10;
908 layout.dac_offset[ 1 ] = 9;
909 layout.dac_gain[ 1 ] = 5;
910 layout.dac_linearity[ 1 ] = 1;
912 return cal_ni_generic( setup, &layout );
915 static int cal_ni_pci_6052e(calibration_setup_t *setup)
918 * This board has noisy caldacs
920 * The NI documentation says (true mb88341 addressing):
921 * 0, 8 AI pregain (coarse, fine)
924 * 14, 7 AI unipolar offset
930 * 10, 6 AO1 reference
933 * For us, these map to (ad8804 channels)
935 * 0, 1 AI pregain (coarse, fine)
938 * 7 AI unipolar offset
947 * or, with mb88341 channels
957 ni_caldac_layout_t layout;
959 init_ni_caldac_layout( &layout );
960 layout.adc_pregain_offset = 0;
961 layout.adc_postgain_offset = 2;
963 layout.adc_unip_offset = 6;
964 layout.adc_pregain_offset_fine = 1;
965 layout.adc_postgain_offset_fine = 3;
966 layout.adc_gain_fine = 5;
968 /* this seems broken, i think we need to change
969 * second caldac in driver to ad8804_debug */
970 layout.dac_offset[ 0 ] = 12 + 11;
971 layout.dac_gain[ 0 ] = 12 + 7;
972 layout.dac_gain_fine[ 0 ] = 12 + 3;
973 layout.dac_offset[ 1 ] = 12 + 1;
974 layout.dac_gain[ 1 ] = 12 + 9;
975 layout.dac_gain_fine[ 1 ] = 12 + 5;
977 /* this should work if the first two caldacs were ad8804_debug */
978 layout.dac_offset[ 0 ] = 16 + 3;
979 layout.dac_gain[ 0 ] = 16 + 1;
980 layout.dac_gain_fine[ 0 ] = 16 + 2;
981 layout.dac_linearity[ 0 ] = 16 + 0;
982 layout.dac_offset[ 1 ] = 16 + 7;
983 layout.dac_gain[ 1 ] = 16 + 5;
984 layout.dac_gain_fine[ 1 ] = 16 + 6;
985 layout.dac_linearity[ 1 ] = 16 + 4;
987 return cal_ni_generic( setup, &layout );
990 static int cal_ni_daqcard_ai_16e_4(calibration_setup_t *setup)
992 ni_caldac_layout_t layout;
994 init_ni_caldac_layout( &layout );
995 layout.adc_pregain_offset = 0;
996 layout.adc_postgain_offset = 1;
998 layout.adc_unip_offset = 2;
1000 return cal_ni_generic( setup, &layout );
1003 static int adc_offset_611x( unsigned int channel )
1005 return 2 * channel + 2;
1007 static int adc_gain_611x( unsigned int channel )
1009 return 2 * channel + 1;
1011 static int dac_offset_611x( unsigned int channel )
1013 return 12 + 2 + 2 * channel;
1015 static int dac_gain_611x( unsigned int channel )
1017 return 12 + 1 + 2 * channel;
1019 static int cal_ni_pci_611x( calibration_setup_t *setup )
1021 generic_layout_t layout;
1023 init_generic_layout( &layout );
1024 layout.adc_offset = adc_offset_611x;
1025 layout.adc_gain = adc_gain_611x;
1026 layout.dac_offset = dac_offset_611x;
1027 layout.dac_gain = dac_gain_611x;
1028 layout.adc_high_observable = ni_reference_611x;
1029 layout.adc_ground_observable = ni_zero_offset_611x;
1030 layout.dac_high_observable = ni_ao_reference_611x;
1031 layout.dac_ground_observable = ni_ao_zero_offset_611x;
1033 return generic_cal_by_channel_and_range( setup, &layout );
1036 static int cal_ni_pci_mio_16e_4( calibration_setup_t *setup )
1038 ni_caldac_layout_t layout;
1040 init_ni_caldac_layout( &layout );
1041 layout.adc_pregain_offset = 8;
1042 layout.adc_postgain_offset = 4;
1043 layout.adc_gain = 2;
1044 layout.adc_unip_offset = 7;
1045 layout.dac_offset[ 0 ] = 6;
1046 layout.dac_gain[ 0 ] = 11;
1047 layout.dac_linearity[ 0 ] = 10;
1048 layout.dac_offset[ 1 ] = 9;
1049 layout.dac_gain[ 1 ] = 5;
1050 layout.dac_linearity[ 1 ] = 1;
1052 return cal_ni_generic( setup, &layout );
1055 static int cal_ni_daqcard_6062e( calibration_setup_t *setup )
1057 ni_caldac_layout_t layout;
1059 if( comedi_get_version_code( setup->dev ) <= COMEDI_VERSION_CODE( 0, 7, 66 ) )
1061 DPRINT(0, "WARNING: you need comedi driver version 0.7.67 or later\n"
1062 "for this calibration to work properly\n" );
1064 init_ni_caldac_layout( &layout );
1065 layout.adc_pregain_offset = 8;
1066 layout.adc_postgain_offset = 4;
1067 layout.adc_gain = 2;
1068 layout.adc_unip_offset = 7;
1069 layout.dac_offset[ 0 ] = 6;
1070 layout.dac_gain[ 0 ] = 11;
1071 layout.dac_linearity[ 0 ] = 10;
1072 layout.dac_offset[ 1 ] = 9;
1073 layout.dac_gain[ 1 ] = 5;
1074 layout.dac_linearity[ 1 ] = 1;
1076 return cal_ni_generic( setup, &layout );
1079 static int cal_ni_daqcard_6024e( calibration_setup_t *setup )
1081 ni_caldac_layout_t layout;
1083 init_ni_caldac_layout( &layout );
1085 layout.adc_pregain_offset = 0;
1086 layout.adc_postgain_offset = 4;
1087 layout.adc_gain = 2;
1088 //layout.adc_unip_offset = 7;
1089 layout.dac_offset[ 0 ] = 6;
1090 layout.dac_gain[ 0 ] = 3;
1091 //layout.dac_linearity[ 0 ] = 10;
1092 layout.dac_offset[ 1 ] = 1;
1093 layout.dac_gain[ 1 ] = 5;
1094 //layout.dac_linearity[ 1 ] = 1;
1096 return cal_ni_generic( setup, &layout );
1099 static void prep_adc_caldacs_generic( calibration_setup_t *setup,
1100 const ni_caldac_layout_t *layout )
1104 if( setup->do_reset )
1106 reset_caldac( setup, layout->adc_pregain_offset );
1107 reset_caldac( setup, layout->adc_postgain_offset );
1108 reset_caldac( setup, layout->adc_gain );
1109 reset_caldac( setup, layout->adc_pregain_offset_fine );
1110 reset_caldac( setup, layout->adc_postgain_offset_fine );
1111 reset_caldac( setup, layout->adc_gain_fine );
1112 reset_caldac( setup, layout->adc_unip_offset );
1115 retval = comedi_apply_calibration( setup->dev, setup->ad_subdev,
1116 0, 0, AREF_GROUND, setup->cal_save_file_path);
1119 DPRINT( 0, "Failed to apply existing calibration, reseting adc caldacs.\n" );
1120 reset_caldac( setup, layout->adc_pregain_offset );
1121 reset_caldac( setup, layout->adc_postgain_offset );
1122 reset_caldac( setup, layout->adc_gain );
1123 reset_caldac( setup, layout->adc_pregain_offset_fine );
1124 reset_caldac( setup, layout->adc_postgain_offset_fine );
1125 reset_caldac( setup, layout->adc_gain_fine );
1126 reset_caldac( setup, layout->adc_unip_offset );
1131 static void prep_dac_caldacs_generic( calibration_setup_t *setup,
1132 const ni_caldac_layout_t *layout, unsigned int channel, unsigned int range )
1136 if( setup->da_subdev < 0 ) return;
1138 if( setup->do_reset )
1140 reset_caldac( setup, layout->dac_offset[ channel ] );
1141 reset_caldac( setup, layout->dac_gain[ channel ] );
1142 reset_caldac( setup, layout->dac_gain_fine[ channel ] );
1143 reset_caldac( setup, layout->dac_linearity[ channel ] );
1146 retval = comedi_apply_calibration( setup->dev, setup->da_subdev,
1147 channel, range, AREF_GROUND, setup->cal_save_file_path);
1150 DPRINT( 0, "Failed to apply existing calibration, reseting dac caldacs.\n" );
1151 reset_caldac( setup, layout->dac_offset[ channel ] );
1152 reset_caldac( setup, layout->dac_gain[ channel ] );
1153 reset_caldac( setup, layout->dac_gain_fine[ channel ] );
1154 reset_caldac( setup, layout->dac_linearity[ channel ] );
1159 static int cal_ni_generic( calibration_setup_t *setup, const ni_caldac_layout_t *layout )
1161 saved_calibration_t saved_cals[ 5 ], *current_cal;
1163 int num_calibrations;
1165 current_cal = saved_cals;
1167 memset( saved_cals, 0, sizeof( saved_cals ) );
1169 prep_adc_caldacs_generic( setup, layout );
1171 current_cal->subdevice = setup->ad_subdev;
1172 generic_do_relative( setup, current_cal, ni_zero_offset_low,
1173 ni_reference_low, layout->adc_gain );
1174 generic_do_relative( setup, current_cal, ni_zero_offset_low,
1175 ni_zero_offset_high, layout->adc_postgain_offset );
1176 generic_do_cal( setup, current_cal, ni_zero_offset_high, layout->adc_pregain_offset );
1177 generic_do_relative( setup, current_cal, ni_zero_offset_low,
1178 ni_reference_low, layout->adc_gain_fine );
1179 generic_do_relative( setup, current_cal, ni_zero_offset_low,
1180 ni_zero_offset_high, layout->adc_postgain_offset_fine );
1181 generic_do_cal( setup, current_cal, ni_zero_offset_high,
1182 layout->adc_pregain_offset_fine );
1183 generic_do_cal( setup, current_cal, ni_unip_zero_offset_high, layout->adc_unip_offset );
1184 sc_push_channel( current_cal, SC_ALL_CHANNELS );
1185 sc_push_range( current_cal, SC_ALL_RANGES );
1186 sc_push_aref( current_cal, SC_ALL_AREFS );
1189 if( setup->da_subdev >= 0 && setup->do_output )
1191 unsigned int channel, range;
1192 int ao_unipolar_lowgain = get_unipolar_lowgain( setup->dev, setup->da_subdev );
1193 int ao_bipolar_lowgain = get_bipolar_lowgain( setup->dev, setup->da_subdev );
1196 for( channel = 0; channel < 2; channel++ )
1198 num_ao_ranges = comedi_get_n_ranges( setup->dev, setup->da_subdev, channel );
1199 prep_dac_caldacs_generic( setup, layout, channel, ao_bipolar_lowgain );
1201 current_cal->subdevice = setup->da_subdev;
1202 generic_do_linearity( setup, current_cal, ni_ao_linearity( channel ),
1203 ni_ao_zero_offset( channel ), ni_ao_reference( channel ),
1204 layout->dac_linearity[ channel ] );
1205 generic_do_cal( setup, current_cal, ni_ao_zero_offset( channel ),
1206 layout->dac_offset[ channel ] );
1207 generic_do_cal( setup, current_cal, ni_ao_reference( channel ),
1208 layout->dac_gain[ channel ] );
1209 generic_do_cal( setup, current_cal, ni_ao_reference( channel ),
1210 layout->dac_gain_fine[ channel ] );
1211 sc_push_channel( current_cal, channel );
1212 for( range = 0; range < num_ao_ranges; range++ )
1214 if( is_bipolar( setup->dev, setup->da_subdev, channel, range ) )
1215 sc_push_range( current_cal, range );
1217 sc_push_aref( current_cal, SC_ALL_AREFS );
1220 if( ao_unipolar_lowgain >= 0 )
1222 prep_dac_caldacs_generic( setup, layout, channel, ao_unipolar_lowgain );
1224 current_cal->subdevice = setup->da_subdev;
1225 generic_do_linearity( setup, current_cal, ni_ao_unip_zero_offset( channel ),
1226 ni_ao_unip_linearity( channel ), ni_ao_unip_reference( channel ),
1227 layout->dac_linearity[ channel ] );
1228 generic_do_cal( setup, current_cal, ni_ao_unip_zero_offset( channel),
1229 layout->dac_offset[ channel ] );
1230 generic_do_cal( setup, current_cal, ni_ao_unip_reference( channel ),
1231 layout->dac_gain[ channel ] );
1232 generic_do_cal( setup, current_cal, ni_ao_unip_reference( channel ),
1233 layout->dac_gain_fine[ channel ] );
1234 sc_push_channel( current_cal, channel );
1235 for( range = 0; range < num_ao_ranges; range++ )
1237 if( is_unipolar( setup->dev, setup->da_subdev, channel, range ) )
1238 sc_push_range( current_cal, range );
1240 sc_push_aref( current_cal, SC_ALL_AREFS );
1246 num_calibrations = current_cal - saved_cals;
1247 retval = write_calibration_file( setup, saved_cals, num_calibrations );
1248 for( i = 0; i < num_calibrations; i++ )
1249 clear_saved_calibration( &saved_cals[ i ] );
1254 static double ni_get_reference( calibration_setup_t *setup, int lsb_loc,int msb_loc)
1260 lsb=read_eeprom( setup, lsb_loc);
1261 msb=read_eeprom( setup, msb_loc);
1262 DPRINT(0,"eeprom reference lsb=%d msb=%d\n", lsb, msb);
1264 uv = ( lsb & 0xff ) | ( ( msb << 8 ) & 0xff00 );
1265 ref=5.000+1.0e-6*uv;
1266 DPRINT(0, "resulting reference voltage: %g\n", ref );
1267 if( fabs( ref - 5.0 ) > 0.005 )
1268 DPRINT( 0, "WARNING: eeprom indicates reference is more than 5mV away\n"
1269 "from 5V. Possible bad eeprom address?\n" );
1275 static void cal_ni_results(void)
1277 comedi_range *range;
1278 int bipolar_lowgain;
1279 int bipolar_highgain;
1280 int unipolar_lowgain;
1284 bipolar_lowgain = get_bipolar_lowgain(dev,setup->ad_subdev);
1285 bipolar_highgain = get_bipolar_highgain(dev,setup->ad_subdev);
1286 unipolar_lowgain = get_unipolar_lowgain(dev,setup->ad_subdev);
1288 /* 0 offset, low gain */
1289 range = comedi_get_range(dev,setup->ad_subdev,0,bipolar_lowgain);
1290 read_chan2(s,0,bipolar_lowgain);
1291 DPRINT(0,"bipolar zero offset, low gain [%g,%g]: %s\n",
1292 range->min,range->max,s);
1294 /* 0 offset, high gain */
1295 range = comedi_get_range(dev,setup->ad_subdev,0,bipolar_highgain);
1296 read_chan2(s,0,bipolar_highgain);
1297 DPRINT(0,"bipolar zero offset, high gain [%g,%g]: %s\n",
1298 range->min,range->max,s);
1300 /* unip/bip offset */
1301 range = comedi_get_range(dev,setup->ad_subdev,0,unipolar_lowgain);
1302 read_chan2(s,0,unipolar_lowgain);
1303 DPRINT(0,"unipolar zero offset, low gain [%g,%g]: %s\n",
1304 range->min,range->max,s);
1308 static void ni_mio_ai_postgain_cal(void)
1316 check_gain_chan_x(&l,CR_PACK(0,0,AREF_OTHER),1);
1317 offset_r0=linear_fit_func_y(&l,caldacs[1].current);
1318 printf("offset r0 %g\n",offset_r0);
1320 check_gain_chan_x(&l,CR_PACK(0,7,AREF_OTHER),1);
1321 offset_r7=linear_fit_func_y(&l,caldacs[1].current);
1322 printf("offset r7 %g\n",offset_r7);
1326 a=(offset_r0-offset_r7)/(200.0-1.0);
1327 a=caldacs[1].current-a/gain;
1331 caldacs[1].current=rint(a);
1335 static void ni_mio_ai_postgain_cal_2(int chan,int dac,int range_lo,int range_hi,double gain)
1337 double offset_lo,offset_hi;
1342 check_gain_chan_x(&l,CR_PACK(chan,range_lo,AREF_OTHER),dac);
1343 offset_lo=linear_fit_func_y(&l,caldacs[dac].current);
1344 printf("offset lo %g\n",offset_lo);
1346 check_gain_chan_x(&l,CR_PACK(chan,range_hi,AREF_OTHER),dac);
1347 offset_hi=linear_fit_func_y(&l,caldacs[dac].current);
1348 printf("offset hi %g\n",offset_hi);
1352 a=(offset_lo-offset_hi)/(gain-1.0);
1353 a=caldacs[dac].current-a/slope;
1357 caldacs[dac].current=rint(a);