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
13 - doesn't check unipolar ranges
17 /***************************************************************************
19 * This program is free software; you can redistribute it and/or modify *
20 * it under the terms of the GNU Lesser General Public License as *
22 * the Free Software Foundation; either version 2.1 of the License, or *
23 * (at your option) any later version. *
25 ***************************************************************************/
30 #include "comedilib.h"
44 char ni_id[] = "$Id$";
49 int (*cal)( calibration_setup_t *setup);
50 void (*setup_observables)( calibration_setup_t *setup );
55 static int ni_setup_board( calibration_setup_t *setup , const char *device_name );
56 static void ni_setup_observables( calibration_setup_t *setup );
57 static void ni_setup_observables_611x( calibration_setup_t *setup );
59 static int cal_ni_at_mio_16e_2(calibration_setup_t *setup);
60 static int cal_ni_daqcard_ai_16xe_50(calibration_setup_t *setup);
61 static int cal_ni_at_mio_16e_1(calibration_setup_t *setup);
62 static int cal_ni_pci_mio_16e_1(calibration_setup_t *setup);
63 static int cal_ni_pci_6025e(calibration_setup_t *setup);
64 static int cal_ni_pci_6035e(calibration_setup_t *setup);
65 static int cal_ni_pci_6071e(calibration_setup_t *setup);
66 static int cal_ni_pxi_6071e(calibration_setup_t *setup);
67 static int cal_ni_at_mio_16e_10(calibration_setup_t *setup);
68 static int cal_ni_pci_mio_16xe_50(calibration_setup_t *setup);
69 static int cal_ni_pci_6023e(calibration_setup_t *setup);
70 static int cal_ni_pci_6024e(calibration_setup_t *setup);
71 static int cal_ni_at_mio_16xe_50(calibration_setup_t *setup);
72 static int cal_ni_pci_mio_16xe_10(calibration_setup_t *setup);
73 static int cal_ni_pci_6052e(calibration_setup_t *setup);
74 static int cal_ni_pci_mio_16e_4(calibration_setup_t *setup);
75 static int cal_ni_pci_6032e(calibration_setup_t *setup);
76 static int cal_ni_daqcard_ai_16e_4(calibration_setup_t *setup);
77 static int cal_ni_pci_611x(calibration_setup_t *setup);
78 static int cal_ni_daqcard_6062e(calibration_setup_t *setup);
80 static double ni_get_reference( calibration_setup_t *setup, int lsb_loc,int msb_loc);
82 static struct board_struct boards[]={
83 { "at-mio-16e-2", STATUS_DONE, cal_ni_at_mio_16e_2, ni_setup_observables, 0x1a9, 0x1aa },
84 { "DAQCard-ai-16xe-50", STATUS_DONE, cal_ni_daqcard_ai_16xe_50, ni_setup_observables, 0x1be, 0x1bf },
85 { "at-mio-16xe-50", STATUS_SOME, cal_ni_at_mio_16xe_50, ni_setup_observables, 0x1b5, 0x1b6 },
86 { "at-mio-16e-1", STATUS_SOME, cal_ni_at_mio_16e_1, ni_setup_observables, 0x1a9, 0x1aa },
87 { "pci-mio-16e-1", STATUS_DONE, cal_ni_pci_mio_16e_1, ni_setup_observables, 0x1a9, 0x1aa },
88 { "pci-6025e", STATUS_SOME, cal_ni_pci_6025e, ni_setup_observables, 0x1af, 0x1b0 },
89 { "pci-6035e", STATUS_DONE, cal_ni_pci_6035e, ni_setup_observables, 0x1af, 0x1b0 },
90 { "pci-6071e", STATUS_SOME, cal_ni_pci_6071e, ni_setup_observables, 0x1a9, 0x1aa },
91 { "pxi-6071e", STATUS_GUESS, cal_ni_pxi_6071e, ni_setup_observables, -1, -1 },
92 { "at-mio-16e-10", STATUS_GUESS, cal_ni_at_mio_16e_10, ni_setup_observables, 0x1a7, 0x1a8 },
93 { "pci-mio-16xe-50", STATUS_SOME, cal_ni_pci_mio_16xe_50, ni_setup_observables, 0x1b5, 0x1b6 },
94 { "pci-6023e", STATUS_DONE, cal_ni_pci_6023e, ni_setup_observables, 0x1bb, 0x1bc },
95 { "pci-mio-16xe-10", STATUS_DONE, cal_ni_pci_mio_16xe_10, ni_setup_observables, 0x1ae, 0x1af },
96 { "pci-6052e", STATUS_DONE, cal_ni_pci_6052e, ni_setup_observables, 0x19f, 0x1a0 },
97 { "pci-6024e", STATUS_SOME, cal_ni_pci_6024e, ni_setup_observables, 0x1af, 0x1b0 },
98 { "pci-mio-16e-4", STATUS_SOME, cal_ni_pci_mio_16e_4, ni_setup_observables, 0x1a9, 0x1aa },
99 { "pci-6032e", STATUS_DONE, cal_ni_pci_6032e, ni_setup_observables, 0x1ae, 0x1af },
100 { "DAQCard-ai-16e-4", STATUS_DONE, cal_ni_daqcard_ai_16e_4, ni_setup_observables, 0x1b5, 0x1b6 },
101 { "pci-6110", STATUS_DONE, cal_ni_pci_611x, ni_setup_observables_611x, 0x1d4, 0x1d5 },
102 { "pci-6111", STATUS_DONE, cal_ni_pci_611x, ni_setup_observables_611x, 0x1d4, 0x1d5 },
103 { "DAQCard-6062E", STATUS_SOME, cal_ni_daqcard_6062e, ni_setup_observables, 0x1a9, 0x1aa },
104 { "DAQCard-6024E", STATUS_UNKNOWN, NULL, ni_setup_observables, -1, -1 },
105 { "at-mio-16de-10", STATUS_UNKNOWN, NULL, ni_setup_observables, 0x1a7, 0x1a8 },
106 { "at-mio-16xe-10", STATUS_UNKNOWN, NULL, ni_setup_observables, 0x1b7, 0x1b8 },
107 { "at-ai-16xe-10", STATUS_UNKNOWN, NULL, ni_setup_observables, 0x1b7, 0x1b8 },
108 { "pci-6031e", STATUS_UNKNOWN, NULL, ni_setup_observables, 0x1ae, 0x1af },
109 { "pci-6033e", STATUS_UNKNOWN, NULL, ni_setup_observables, 0x1ae, 0x1af },
111 { "at-mio-64e-3", cal_ni_16e_1 },
112 // { "at-mio-16xe-50", cal_ni_unknown },
113 // { "pxi-6030e", cal_ni_unknown },
114 // { "pxi-6040e", cal_ni_unknown },
115 { "pxi-6025e", cal_ni_6023e }, // guess
116 { "pci-6034e", cal_ni_6023e }, // guess
117 // { "pci-6711", cal_ni_unknown },
118 // { "pci-6713", cal_ni_unknown },
119 // { "pxi-6070e", cal_ni_unknown },
120 // { "pxi-6052e", cal_ni_unknown },
123 #define n_boards (sizeof(boards)/sizeof(boards[0]))
125 static const int ni_num_observables = 12;
127 ni_zero_offset_low = 0,
130 ni_unip_zero_offset_low,
131 ni_unip_zero_offset_high,
132 ni_unip_reference_low,
140 static inline unsigned int ni_ao_zero_offset( unsigned int channel )
142 if( channel ) return ni_ao1_zero_offset;
143 else return ni_ao0_zero_offset;
145 static inline unsigned int ni_ao_reference( unsigned int channel )
147 if( channel ) return ni_ao1_reference;
148 else return ni_ao0_reference;
150 static inline unsigned int ni_ao_linearity( unsigned int channel )
152 if( channel ) return ni_ao1_linearity;
153 else return ni_ao0_linearity;
156 enum observables_611x{
157 ni_ao0_zero_offset_611x = 0,
158 ni_ao0_reference_611x = 1,
159 ni_ao1_zero_offset_611x = 2,
160 ni_ao1_reference_611x = 3,
162 static inline unsigned int ni_zero_offset_611x( unsigned int channel ) {
163 return 4 + 2 * channel;
165 static inline unsigned int ni_reference_611x( unsigned int channel ) {
166 return 5 + 2 * channel;
169 enum reference_sources {
174 REF_CALSRC_CALSRC = 4,
179 static inline unsigned int REF_DAC_GND( unsigned int channel )
181 if( channel ) return REF_DAC1_GND;
182 else return REF_DAC0_GND;
184 static inline unsigned int REF_DAC_CALSRC( unsigned int channel )
186 if( channel ) return REF_DAC1_CALSRC;
187 else return REF_DAC0_CALSRC;
190 static struct board_struct* ni_board( calibration_setup_t *setup )
192 return setup->private_data;
195 int ni_setup( calibration_setup_t *setup , const char *device_name )
199 retval = ni_setup_board( setup, device_name );
200 if( retval < 0 ) return retval;
201 setup_caldacs( setup, setup->caldac_subdev );
206 static int ni_setup_board( calibration_setup_t *setup, const char *device_name )
210 for(i = 0; i < n_boards; i++ ){
211 if(!strcmp( device_name, boards[i].name )){
212 setup->status = boards[i].status;
213 setup->do_cal = boards[i].cal;
214 setup->private_data = &boards[ i ];
215 boards[i].setup_observables( setup );
219 if( i == n_boards ) return -1;
223 static void ni_setup_observables( calibration_setup_t *setup )
227 int bipolar_highgain;
228 int unipolar_lowgain;
229 int unipolar_highgain;
230 double voltage_reference;
233 bipolar_lowgain = get_bipolar_lowgain( setup->dev, setup->ad_subdev);
234 bipolar_highgain = get_bipolar_highgain( setup->dev, setup->ad_subdev);
235 unipolar_lowgain = get_unipolar_lowgain( setup->dev, setup->ad_subdev);
236 unipolar_highgain = get_unipolar_highgain( setup->dev, setup->ad_subdev);
238 if( ni_board( setup )->ref_eeprom_lsb >= 0 &&
239 ni_board( setup )->ref_eeprom_msb >= 0 )
241 voltage_reference = ni_get_reference( setup,
242 ni_board( setup )->ref_eeprom_lsb, ni_board( setup )->ref_eeprom_msb );
245 DPRINT( 0, "WARNING: unknown eeprom address for reference voltage\n"
246 "correction. This might be fixable if you send us an eeprom dump\n"
247 "(see the demo/eeprom_dump program).\n");
248 voltage_reference = 5.0;
251 memset(&tmpl,0,sizeof(tmpl));
252 tmpl.insn = INSN_READ;
254 tmpl.subdev = setup->ad_subdev;
256 setup->n_observables = ni_num_observables;
258 /* 0 offset, low gain */
259 o = setup->observables + ni_zero_offset_low;
260 o->name = "ai, bipolar zero offset, low gain";
261 o->observe_insn = tmpl;
262 o->observe_insn.chanspec = CR_PACK(REF_GND_GND,bipolar_lowgain,AREF_OTHER)
263 | CR_ALT_SOURCE | CR_ALT_FILTER;
264 o->reference_source = REF_GND_GND;
267 /* 0 offset, high gain */
268 o = setup->observables + ni_zero_offset_high;
269 o->name = "ai, bipolar zero offset, high gain";
270 o->observe_insn = tmpl;
271 o->observe_insn.chanspec = CR_PACK(REF_GND_GND,bipolar_highgain,AREF_OTHER)
272 | CR_ALT_SOURCE | CR_ALT_FILTER;
273 o->reference_source = REF_GND_GND;
276 /* voltage reference */
277 o = setup->observables + ni_reference_low;
278 o->name = "ai, bipolar voltage reference, low gain";
279 o->observe_insn = tmpl;
280 o->observe_insn.chanspec = CR_PACK(REF_CALSRC_GND,bipolar_lowgain,AREF_OTHER)
281 | CR_ALT_SOURCE | CR_ALT_FILTER;
282 o->reference_source = REF_CALSRC_GND;
283 o->target = voltage_reference;
285 if(unipolar_lowgain>=0){
289 range = comedi_get_range( setup->dev, setup->ad_subdev, 0, unipolar_lowgain );
290 assert( range != NULL );
291 max_data = comedi_get_maxdata( setup->dev, setup->ad_subdev, 0 );
292 assert( max_data > 0 );
294 o = setup->observables + ni_unip_zero_offset_low;
295 o->name = "ai, unipolar zero offset, low gain";
296 o->observe_insn = tmpl;
297 o->observe_insn.chanspec =
298 CR_PACK(REF_GND_GND,unipolar_lowgain,AREF_OTHER)
299 | CR_ALT_SOURCE | CR_ALT_FILTER;
300 o->reference_source = REF_GND_GND;
301 o->target = comedi_to_phys( 1, range, max_data ) / 2.0;
303 o = setup->observables + ni_unip_reference_low;
304 o->name = "ai, unipolar voltage reference, low gain";
305 o->observe_insn = tmpl;
306 o->observe_insn.chanspec =
307 CR_PACK(REF_CALSRC_GND,unipolar_lowgain,AREF_OTHER)
308 | CR_ALT_SOURCE | CR_ALT_FILTER;
309 o->reference_source = REF_CALSRC_GND;
310 o->target = voltage_reference;
313 if(unipolar_highgain >= 0)
318 range = comedi_get_range( setup->dev, setup->ad_subdev, 0, unipolar_highgain );
319 assert( range != NULL );
320 max_data = comedi_get_maxdata( setup->dev, setup->ad_subdev, 0 );
321 assert( max_data > 0 );
323 o = setup->observables + ni_unip_zero_offset_high;
324 o->name = "ai, unipolar zero offset, high gain";
325 o->observe_insn = tmpl;
326 o->observe_insn.chanspec =
327 CR_PACK(REF_GND_GND,unipolar_highgain,AREF_OTHER)
328 | CR_ALT_SOURCE | CR_ALT_FILTER;
329 o->reference_source = REF_GND_GND;
330 o->target = comedi_to_phys( 1, range, max_data ) / 2.0;
333 if(setup->da_subdev>=0){
335 unsigned int channel;
337 memset(&po_tmpl,0,sizeof(po_tmpl));
338 po_tmpl.insn = INSN_WRITE;
340 po_tmpl.subdev = setup->da_subdev;
342 for( channel = 0; channel < 2; channel++ )
345 o = setup->observables + ni_ao_zero_offset( channel );
346 assert( o->name == NULL );
347 asprintf( &o->name, "ao %i, zero offset, low gain", channel );
348 o->preobserve_insn = po_tmpl;
349 o->preobserve_insn.chanspec = CR_PACK(channel,0,0);
350 o->preobserve_insn.data = o->preobserve_data;
351 o->observe_insn = tmpl;
352 o->observe_insn.chanspec =
353 CR_PACK(REF_DAC_GND( channel ),bipolar_lowgain,AREF_OTHER)
354 | CR_ALT_SOURCE | CR_ALT_FILTER;
355 o->reference_source = REF_DAC_GND( channel );
356 set_target( setup, ni_ao_zero_offset( channel ),0.0);
359 o = setup->observables + ni_ao_reference( channel );
360 assert( o->name == NULL );
361 asprintf( &o->name, "ao %i, reference voltage, low gain", channel );
362 o->preobserve_insn = po_tmpl;
363 o->preobserve_insn.chanspec = CR_PACK(channel,0,0);
364 o->preobserve_insn.data = o->preobserve_data;
365 o->observe_insn = tmpl;
366 o->observe_insn.chanspec =
367 CR_PACK(REF_DAC_GND( channel ),bipolar_lowgain,AREF_OTHER)
368 | CR_ALT_SOURCE | CR_ALT_FILTER;
369 o->reference_source = REF_DAC_GND( channel );
370 set_target( setup, ni_ao_reference( channel ),5.0);
372 /* ao linearity, negative */
373 o = setup->observables + ni_ao_linearity( channel );
374 assert( o->name == NULL );
375 asprintf( &o->name, "ao %i, linearity (negative), low gain", channel );
376 o->preobserve_insn = po_tmpl;
377 o->preobserve_insn.chanspec = CR_PACK(channel,0,0);
378 o->preobserve_insn.data = o->preobserve_data;
379 o->observe_insn = tmpl;
380 o->observe_insn.chanspec =
381 CR_PACK(REF_DAC_GND( channel ),bipolar_lowgain,AREF_OTHER)
382 | CR_ALT_SOURCE | CR_ALT_FILTER;
383 o->reference_source = REF_DAC_GND( channel );
384 set_target( setup, ni_ao_linearity( channel ),-5.0);
389 /* XXX for +-50V and +-20V ranges, the reference source goes 0V
390 * to 50V instead of 0V to 5V */
391 static unsigned int cal_gain_register_bits_611x( double reference, double *voltage )
395 bits = 200.0 * ( *voltage / reference );
396 if( bits > 200 ) bits = 200;
398 *voltage = reference * ( bits / 200.0 );
402 static unsigned int ref_source_611x( unsigned int ref_source, unsigned int cal_gain_bits )
404 return ( ref_source & 0xf ) | ( ( cal_gain_bits << 4 ) & 0xff0 );
407 static void ni_setup_observables_611x( calibration_setup_t *setup )
411 int range, ai_range_for_ao;
412 double voltage_reference, master_reference;
416 int cal_gain_reg_bits;
418 setup->settling_time_ns = 1000000;
422 master_reference = ni_get_reference( setup,
423 ni_board( setup )->ref_eeprom_lsb, ni_board( setup )->ref_eeprom_msb );
424 voltage_reference = 5.0;
425 cal_gain_reg_bits = cal_gain_register_bits_611x( master_reference, &voltage_reference );
427 memset(&tmpl,0,sizeof(tmpl));
428 tmpl.insn = INSN_READ;
430 tmpl.subdev = setup->ad_subdev;
432 num_chans = comedi_get_n_channels( setup->dev, setup->ad_subdev );
434 for( ai_chan = 0; ai_chan < num_chans; ai_chan++ )
437 o = setup->observables + ni_zero_offset_611x( ai_chan );
438 o->name = "ai, bipolar zero offset";
439 o->observe_insn = tmpl;
440 o->observe_insn.chanspec = CR_PACK(ai_chan, range, AREF_DIFF)
441 | CR_ALT_SOURCE | CR_ALT_FILTER;
442 o->reference_source = REF_GND_GND;
445 /* voltage reference */
446 o = setup->observables + ni_reference_611x( ai_chan );
447 o->name = "ai, bipolar voltage reference";
448 o->observe_insn = tmpl;
449 o->observe_insn.chanspec = CR_PACK(ai_chan, range, AREF_DIFF)
450 | CR_ALT_SOURCE | CR_ALT_FILTER;
451 o->reference_source = ref_source_611x( REF_CALSRC_GND, cal_gain_reg_bits );
452 o->target = voltage_reference;
455 memset(&po_tmpl,0,sizeof(po_tmpl));
456 po_tmpl.insn = INSN_WRITE;
458 po_tmpl.subdev = setup->da_subdev;
462 /* ao 0, zero offset */
463 o = setup->observables + ni_ao0_zero_offset_611x;
464 o->name = "ao 0, zero offset";
465 o->preobserve_insn = po_tmpl;
466 o->preobserve_insn.chanspec = CR_PACK( 0, 0, AREF_GROUND );
467 o->preobserve_insn.data = o->preobserve_data;
468 o->observe_insn = tmpl;
469 o->observe_insn.chanspec = CR_PACK( 0, ai_range_for_ao, AREF_DIFF )
470 | CR_ALT_SOURCE | CR_ALT_FILTER;
471 o->reference_source = REF_DAC0_GND;
472 set_target( setup, ni_ao0_zero_offset_611x, 0.0 );
475 o = setup->observables + ni_ao0_reference_611x;
476 o->name = "ao 0, reference voltage";
477 o->preobserve_insn = po_tmpl;
478 o->preobserve_insn.chanspec = CR_PACK( 0, 0, AREF_GROUND );
479 o->preobserve_insn.data = o->preobserve_data;
480 o->observe_insn = tmpl;
481 o->observe_insn.chanspec = CR_PACK( 0, ai_range_for_ao, AREF_DIFF )
482 | CR_ALT_SOURCE | CR_ALT_FILTER;
483 o->reference_source = REF_DAC0_GND;
484 set_target( setup, ni_ao0_reference_611x, 5.0 );
486 /* ao 1, zero offset */
487 o = setup->observables + ni_ao1_zero_offset_611x;
488 o->name = "ao 1, zero offset";
489 o->preobserve_insn = po_tmpl;
490 o->preobserve_insn.chanspec = CR_PACK( 1, 0, AREF_GROUND );
491 o->preobserve_insn.data = o->preobserve_data;
492 o->observe_insn = tmpl;
493 o->observe_insn.chanspec = CR_PACK( 0, ai_range_for_ao, AREF_DIFF)
494 | CR_ALT_SOURCE | CR_ALT_FILTER;
495 o->reference_source = REF_DAC1_GND;
496 set_target( setup, ni_ao1_zero_offset_611x, 0.0 );
499 o = setup->observables + ni_ao1_reference_611x;
500 o->name = "ao 1, reference voltage";
501 o->preobserve_insn = po_tmpl;
502 o->preobserve_insn.chanspec = CR_PACK( 1, 0, AREF_GROUND );
503 o->preobserve_insn.data = o->preobserve_data;
504 o->observe_insn = tmpl;
505 o->observe_insn.chanspec = CR_PACK( 0, ai_range_for_ao, AREF_DIFF )
506 | CR_ALT_SOURCE | CR_ALT_FILTER;
507 o->reference_source = REF_DAC1_GND;
508 set_target( setup, ni_ao1_reference_611x, 5.0 );
510 setup->n_observables = 4 + 2 * num_chans;
513 static int cal_ni_at_mio_16e_2(calibration_setup_t *setup)
515 postgain_cal( setup, ni_zero_offset_low,ni_zero_offset_high,1);
516 cal1( setup, ni_zero_offset_high,0);
517 cal1( setup, ni_reference_low,3);
518 cal1( setup, ni_unip_zero_offset_low,2);
519 if(setup->do_output){
520 cal1( setup, ni_ao0_zero_offset,5);
521 cal1( setup, ni_ao0_reference,6);
522 cal1( setup, ni_ao1_zero_offset,8);
523 cal1( setup, ni_ao1_reference,9);
529 * Device name: DAQCard-ai-16xe-50
530 * Comedi version: 0.7.60
531 * ai, bipolar zero offset, low gain
532 * offset 5.87(63)e-3, target 0
533 * caldac[0] gain=-2.243(21)e-6 V/bit S_min=208.079 dof=254
534 * caldac[2] gain=1.56378(22)e-4 V/bit S_min=1782.91 dof=254
535 * caldac[8] gain=2.499(14)e-7 V/bit S_min=234.915 dof=254
536 * ai, bipolar zero offset, high gain
537 * offset 4.251(49)e-5, target 0
538 * caldac[0] gain=-2.396(30)e-8 V/bit S_min=231.387 dof=254
539 * caldac[2] gain=1.56428(28)e-6 V/bit S_min=829.096 dof=254
540 * caldac[8] gain=2.61244(18)e-7 V/bit S_min=773.092 dof=254
541 * ai, bipolar voltage reference, low gain
542 * offset 4.99650(81), target 5
543 * caldac[0] gain=-3.78250(23)e-4 V/bit S_min=12207.6 dof=254
544 * caldac[1] gain=-9.878(22)e-6 V/bit S_min=346.795 dof=254
545 * caldac[2] gain=1.57172(23)e-4 V/bit S_min=969.526 dof=254
546 * caldac[8] gain=2.795(14)e-7 V/bit S_min=245.703 dof=254
547 * ai, unipolar zero offset, low gain
548 * offset 0.0133(14), target 0
549 * caldac[0] gain=3.73923(29)e-4 V/bit S_min=2855.79 dof=151
550 * caldac[1] gain=9.784(11)e-6 V/bit S_min=727.295 dof=254
551 * caldac[2] gain=7.8670(11)e-5 V/bit S_min=903.291 dof=254
552 * caldac[8] gain=2.7732(74)e-7 V/bit S_min=415.399 dof=254
554 static int cal_ni_daqcard_ai_16xe_50(calibration_setup_t *setup)
556 postgain_cal( setup, ni_zero_offset_low,ni_zero_offset_high,2);
557 cal1( setup, ni_zero_offset_high,8);
558 cal1( setup, ni_reference_low,0);
559 cal1_fine( setup, ni_reference_low,0);
560 cal1( setup, ni_reference_low,1);
564 static int cal_ni_at_mio_16xe_50(calibration_setup_t *setup)
566 postgain_cal( setup, ni_zero_offset_low,ni_zero_offset_high,2);
567 cal1( setup, ni_zero_offset_high,8);
568 cal1( setup, ni_reference_low,0);
569 cal1_fine( setup, ni_reference_low,0);
570 cal1( setup, ni_reference_low,1);
572 if(setup->do_output){
573 cal1( setup, ni_ao0_zero_offset,6);
574 cal1( setup, ni_ao0_reference,4);
575 cal1( setup, ni_ao1_zero_offset,7);
576 cal1( setup, ni_ao1_reference,5);
581 static int cal_ni_pci_mio_16xe_10(calibration_setup_t *setup)
583 postgain_cal( setup, ni_zero_offset_low, ni_zero_offset_high, 2);
584 postgain_cal( setup, ni_zero_offset_low, ni_zero_offset_high, 3);
585 cal1( setup, ni_zero_offset_high, 8);
586 cal1( setup, ni_reference_low, 0);
587 cal1( setup, ni_reference_low, 1);
589 if(setup->do_output){
590 cal1( setup, ni_ao0_zero_offset,6);
591 cal1( setup, ni_ao0_reference,4);
592 cal1( setup, ni_ao1_zero_offset,7);
593 cal1( setup, ni_ao1_reference,5);
598 static int cal_ni_at_mio_16e_1(calibration_setup_t *setup)
600 return cal_ni_at_mio_16e_2( setup );
603 static int cal_ni_pci_mio_16e_1(calibration_setup_t *setup)
605 //cal_ni_at_mio_16e_2();
607 postgain_cal( setup, ni_zero_offset_low,ni_zero_offset_high,1);
608 cal1( setup, ni_zero_offset_high,0);
609 cal1( setup, ni_reference_low,3);
610 cal1( setup, ni_unip_zero_offset_low,2);
611 if(setup->do_output){
612 cal1( setup, ni_ao0_zero_offset,5);
613 //cal1( setup, ni_ao0_zero_offset,4); /* linearity? */
614 cal1( setup, ni_ao0_reference,6);
615 cal1( setup, ni_ao1_zero_offset,8);
616 //cal1( setup, ni_ao1_zero_offset,7); /* linearity? */
617 cal1( setup, ni_ao1_reference,9);
622 static int cal_ni_pci_6032e(calibration_setup_t *setup)
624 postgain_cal(setup, ni_zero_offset_low, ni_zero_offset_high, 2);
625 postgain_cal(setup, ni_zero_offset_low, ni_zero_offset_high, 3);
627 cal1( setup, ni_zero_offset_high,8);
629 cal1( setup, ni_reference_low,0);
630 cal1_fine( setup, ni_reference_low,0);
631 cal1( setup, ni_reference_low,1);
636 static int cal_ni_pci_6035e(calibration_setup_t *setup)
638 /* this is for the ad8804_debug caldac */
640 postgain_cal( setup, ni_zero_offset_low,ni_zero_offset_high,4);
642 cal1( setup, ni_zero_offset_high,0);
643 cal1( setup, ni_zero_offset_high,8);
645 cal1( setup, ni_reference_low,2);
647 if(setup->do_output){
648 cal1( setup, ni_ao0_zero_offset,6);
649 //cal1( setup, ni_ao0_zero_offset,10); /* linearity? */
650 cal1( setup, ni_ao0_reference,11);
651 cal1( setup, ni_ao1_zero_offset,9);
652 //cal1( setup, ni_ao1_zero_offset,1); /* linearity? */
653 cal1( setup, ni_ao1_reference,5);
658 static int cal_ni_pci_6071e(calibration_setup_t *setup)
660 postgain_cal( setup, ni_zero_offset_low,ni_zero_offset_high,1);
661 cal1( setup, ni_zero_offset_high,0);
662 cal1( setup, ni_reference_low,3);
663 cal1_fine( setup, ni_reference_low,3);
664 if(setup->do_output){
665 cal1( setup, ni_ao0_zero_offset,5);
666 //cal1( setup, ni_ao0_zero_offset,4); /* linearity? */
667 /* caldac 6 should most likely be AO0 reference, but it
669 /*cal1( setup, ni_ao0_reference,6);*/
670 cal1( setup, ni_ao1_zero_offset,8);
671 //cal1( setup, ni_ao1_zero_offset,7); /* linearity? */
672 cal1( setup, ni_ao1_reference,9);
677 static int cal_ni_pxi_6071e(calibration_setup_t *setup)
680 postgain_cal( setup, ni_zero_offset_low,ni_zero_offset_high,1);
681 cal1( setup, ni_zero_offset_high,0);
682 cal1( setup, ni_reference_low,3);
683 if(setup->do_output){
689 static int cal_ni_at_mio_16e_10(calibration_setup_t *setup)
692 postgain_cal( setup, ni_zero_offset_low,ni_zero_offset_high,1);
693 cal1( setup, ni_zero_offset_high,10);
694 cal1( setup, ni_zero_offset_high,0);
695 cal1( setup, ni_reference_low,3);
696 cal1( setup, ni_unip_zero_offset_low,2);
697 if(setup->do_output){
698 cal1( setup, ni_ao0_zero_offset,5); // guess
699 cal1( setup, ni_ao0_reference,6); // guess
700 cal1( setup, ni_ao1_zero_offset,8); // guess
701 cal1( setup, ni_ao1_reference,9); // guess
706 static int cal_ni_pci_mio_16xe_50(calibration_setup_t *setup)
708 postgain_cal( setup, ni_zero_offset_low,ni_zero_offset_high,2);
709 cal1( setup, ni_zero_offset_high,8);
710 cal1( setup, ni_reference_low,0);
711 cal1_fine( setup, ni_reference_low,0);
712 cal1( setup, ni_reference_low,1);
714 if(setup->do_output){
715 cal1( setup, ni_ao0_zero_offset,6);
716 cal1( setup, ni_ao0_reference,4);
717 cal1( setup, ni_ao1_zero_offset,7);
718 cal1( setup, ni_ao1_reference,5);
723 static int cal_ni_pci_6023e(calibration_setup_t *setup)
725 /* for comedi-0.7.65 */
727 postgain_cal( setup, ni_zero_offset_low,ni_zero_offset_high,4);
728 cal1( setup, ni_zero_offset_high,0);
729 cal1( setup, ni_zero_offset_high,8); /* possibly wrong */
730 cal1( setup, ni_reference_low,2);
735 static int cal_ni_pci_6024e(calibration_setup_t *setup)
737 postgain_cal( setup, ni_zero_offset_low,ni_zero_offset_high,4);
738 cal1( setup, ni_zero_offset_high,0);
739 cal1( setup, ni_zero_offset_high,8);
740 cal1( setup, ni_reference_low,2);
741 if(setup->do_output){
742 cal1( setup, ni_ao0_zero_offset,6);
743 //cal1( setup, ni_ao0_zero_offset,10); // nonlinearity?
744 cal1( setup, ni_ao0_reference,11);
745 cal1( setup, ni_ao1_zero_offset,9);
746 //cal1( setup, ni_ao1_zero_offset,1); // nonlinearity?
747 cal1( setup, ni_ao1_reference,5);
752 static int cal_ni_pci_6025e(calibration_setup_t *setup)
754 postgain_cal( setup, ni_zero_offset_low,ni_zero_offset_high,4);
755 cal1( setup, ni_zero_offset_high,0);
756 cal1( setup, ni_zero_offset_high,8);
757 cal1( setup, ni_reference_low,2);
758 if(setup->do_output){
759 cal1( setup, ni_ao0_zero_offset,6);
760 //cal1( setup, ni_ao0_zero_offset,10); /* nonlinearity */
761 cal1( setup, ni_ao0_reference,11);
762 cal1( setup, ni_ao1_zero_offset,9);
763 //cal1( setup, ni_ao1_zero_offset,1); /* nonlinearity */
764 cal1( setup, ni_ao1_reference,5);
769 static int cal_ni_pci_6052e(calibration_setup_t *setup)
772 * This board has noisy caldacs
774 * The NI documentation says:
775 * 0, 8 AI pregain (coarse, fine) 3, 11
776 * 4, 12 AI postgain 15,7
777 * 2, 10 AI reference 1, 9
778 * 14, 7 AI unipolar offset 5, 13
781 * 8, 4 AO0 reference 23, 19 7, 3
782 * 12 AO0 offset 27 11
784 * 10, 6 AO1 reference 25, 21 9, 5
785 * 14 AO1 offset 29, 17 13, 1
795 * 8 11 19 7 1011 0111
797 * 10 9 21 9 1001 1001
801 * 14 5 13 1 0101 0001
805 cal_postgain_binary( setup, ni_zero_offset_low,ni_zero_offset_high,2);
806 postgain_cal( setup, ni_zero_offset_low,ni_zero_offset_high,3);
807 cal1( setup, ni_zero_offset_high,0);
808 cal1( setup, ni_zero_offset_high,1);
809 cal_binary( setup, ni_reference_low,4);
810 cal1_fine( setup, ni_reference_low,4);
811 cal1( setup, ni_reference_low,5);
812 cal1( setup, ni_unip_zero_offset_low,6);
813 cal1_fine( setup, ni_unip_zero_offset_low,6);
814 if(setup->do_output){
815 cal1( setup, ni_ao0_zero_offset,12+11);
816 cal1_fine( setup, ni_ao0_zero_offset,12+11);
817 cal1( setup, ni_ao0_reference,12+7);
818 cal1_fine( setup, ni_ao0_reference,12+7);
819 cal1( setup, ni_ao0_reference,12+3);
820 cal1( setup, ni_ao1_zero_offset,12+1);
821 cal1( setup, ni_ao1_reference,12+9);
822 cal1_fine( setup, ni_ao1_reference,12+9);
823 cal1( setup, ni_ao1_reference,12+5);
828 static int cal_ni_pci_mio_16e_4(calibration_setup_t *setup)
830 /* this is for the ad8804_debug caldac */
832 cal_postgain_binary( setup, ni_zero_offset_low,ni_zero_offset_high,4);
833 //cal_postgain_fine( setup, ni_zero_offset_low,ni_zero_offset_high,4);
834 cal1( setup, ni_zero_offset_high,8);
835 cal_binary( setup, ni_reference_low,2);
836 cal1_fine( setup, ni_reference_low,2);
838 cal1( setup, ni_unip_zero_offset_low,7);
839 cal1_fine( setup, ni_unip_zero_offset_low,7);
841 if(setup->do_output){
842 cal_binary( setup, ni_ao0_zero_offset,6);
843 cal1_fine( setup, ni_ao0_zero_offset,6);
844 //cal1( setup, ni_ao0_nonlinearity,10);
845 cal_binary( setup, ni_ao0_reference,11);
846 cal1_fine( setup, ni_ao0_reference,11);
847 cal_binary( setup, ni_ao1_zero_offset,9);
848 cal1_fine( setup, ni_ao1_zero_offset,9);
849 //cal1( setup, ni_ao1_nonlinearity,1);
850 cal_binary( setup, ni_ao1_reference,5);
851 cal1_fine( setup, ni_ao1_reference,5);
856 static int cal_ni_daqcard_ai_16e_4(calibration_setup_t *setup)
858 cal_postgain_binary(setup, ni_zero_offset_low, ni_zero_offset_high, 1);
859 //cal_postgain_fine(setup, ni_zero_offset_low, ni_zero_offset_high, 1);
861 cal_binary( setup, ni_zero_offset_high,0);
862 cal1_fine( setup, ni_zero_offset_high,0);
864 cal_binary( setup, ni_reference_low,3);
865 cal1_fine( setup, ni_reference_low,3);
867 cal1( setup, ni_unip_zero_offset_low,2);
872 static int cal_ni_pci_611x( calibration_setup_t *setup )
877 num_chans = comedi_get_n_channels( setup->dev, setup->ad_subdev );
879 for( i = 0; i < num_chans; i++ ){
880 cal1( setup, ni_zero_offset_611x( i ), ( 2 * i + 2 ) );
881 cal1( setup, ni_reference_611x( i ), ( 2 * i + 1 ) );
884 if(setup->do_output){
885 cal1( setup, ni_ao0_zero_offset_611x, 14 );
886 cal1( setup, ni_ao0_reference_611x, 13 );
887 cal1( setup, ni_ao1_zero_offset_611x, 16 );
888 cal1( setup, ni_ao1_reference_611x, 15 );
896 DAC1_LINEARITY_DC6062E = 1, /* not sure exactly what this does */
897 ADC_GAIN_DC6062E = 2, /* couples strongly to offset in bipolar ranges */
898 ADC_POSTGAIN_OFFSET_DC6062E = 4,
899 DAC1_GAIN_DC6062E = 5,
900 DAC0_OFFSET_DC6062E = 6,
901 ADC_UNIPOLAR_OFFSET_DC6062E = 7,
902 ADC_PREGAIN_OFFSET_DC6062E = 8,
903 DAC1_OFFSET_DC6062E = 9,
904 DAC0_LINEARITY_DC6062E = 10,
905 DAC0_GAIN_DC6062E = 11,
907 static inline unsigned int DAC_OFFSET_DC6062E( unsigned int channel )
909 if( channel ) return DAC1_OFFSET_DC6062E;
910 else return DAC0_OFFSET_DC6062E;
912 static inline unsigned int DAC_GAIN_DC6062E( unsigned int channel )
914 if( channel ) return DAC1_GAIN_DC6062E;
915 else return DAC0_GAIN_DC6062E;
917 static inline unsigned int DAC_LINEARITY_DC6062E( unsigned int channel )
919 if( channel ) return DAC1_LINEARITY_DC6062E;
920 else return DAC0_LINEARITY_DC6062E;
923 static void prep_adc_caldacs_dc6062e( calibration_setup_t *setup )
927 if( setup->do_reset )
929 reset_caldac( setup, ADC_PREGAIN_OFFSET_DC6062E );
930 reset_caldac( setup, ADC_POSTGAIN_OFFSET_DC6062E );
931 reset_caldac( setup, ADC_GAIN_DC6062E );
932 reset_caldac( setup, ADC_PREGAIN_OFFSET_DC6062E );
935 retval = comedi_apply_calibration( setup->dev, setup->ad_subdev,
936 0, 0, AREF_GROUND, setup->cal_save_file_path);
939 DPRINT( 0, "Failed to apply existing calibration, reseting adc caldacs.\n" );
940 reset_caldac( setup, ADC_PREGAIN_OFFSET_DC6062E );
941 reset_caldac( setup, ADC_POSTGAIN_OFFSET_DC6062E );
942 reset_caldac( setup, ADC_GAIN_DC6062E );
943 reset_caldac( setup, ADC_PREGAIN_OFFSET_DC6062E );
948 static void prep_dac_caldacs_dc6062e( calibration_setup_t *setup,
949 unsigned int channel )
953 if( setup->do_reset )
955 reset_caldac( setup, DAC_OFFSET_DC6062E( channel ) );
956 reset_caldac( setup, DAC_GAIN_DC6062E( channel ) );
957 reset_caldac( setup, DAC_LINEARITY_DC6062E( channel ) );
960 retval = comedi_apply_calibration( setup->dev, setup->da_subdev,
961 channel, 0, AREF_GROUND, setup->cal_save_file_path);
964 DPRINT( 0, "Failed to apply existing calibration, reseting dac caldacs.\n" );
965 reset_caldac( setup, DAC_OFFSET_DC6062E( channel ) );
966 reset_caldac( setup, DAC_GAIN_DC6062E( channel ) );
967 reset_caldac( setup, DAC_LINEARITY_DC6062E( channel ) );
972 static int cal_ni_daqcard_6062e( calibration_setup_t *setup )
974 saved_calibration_t saved_cals[ 3 ], *current_cal;
975 static const int num_calibrations = sizeof( saved_cals ) / sizeof( saved_cals[0] );
978 comedi_set_global_oor_behavior( COMEDI_OOR_NUMBER );
980 current_cal = saved_cals;
982 memset( saved_cals, 0, sizeof( saved_cals ) );
984 prep_adc_caldacs_dc6062e( setup );
986 cal_relative_binary( setup, ni_zero_offset_low, ni_reference_low, ADC_GAIN_DC6062E );
987 cal_relative_binary( setup, ni_zero_offset_low, ni_zero_offset_high,
988 ADC_POSTGAIN_OFFSET_DC6062E );
989 cal_binary( setup, ni_zero_offset_high, ADC_PREGAIN_OFFSET_DC6062E );
990 cal_binary( setup, ni_unip_zero_offset_high, ADC_UNIPOLAR_OFFSET_DC6062E );
992 current_cal->subdevice = setup->ad_subdev;
993 sc_push_caldac( current_cal, setup->caldacs[ ADC_PREGAIN_OFFSET_DC6062E ] );
994 sc_push_caldac( current_cal, setup->caldacs[ ADC_GAIN_DC6062E ] );
995 sc_push_caldac( current_cal, setup->caldacs[ ADC_POSTGAIN_OFFSET_DC6062E ] );
996 sc_push_caldac( current_cal, setup->caldacs[ ADC_UNIPOLAR_OFFSET_DC6062E ] );
997 sc_push_channel( current_cal, SC_ALL_CHANNELS );
998 sc_push_range( current_cal, SC_ALL_RANGES );
999 sc_push_aref( current_cal, SC_ALL_AREFS );
1002 if(setup->do_output)
1004 unsigned int channel;
1006 for( channel = 0; channel < 2; channel++ )
1008 prep_dac_caldacs_dc6062e( setup, channel );
1010 cal_linearity_binary( setup, ni_ao_linearity( channel ),
1011 ni_ao_zero_offset( channel ), ni_ao_reference( channel ),
1012 DAC_LINEARITY_DC6062E( channel ) );
1013 cal_binary( setup, ni_ao_zero_offset( channel ), DAC_OFFSET_DC6062E( channel ) );
1014 cal_binary( setup, ni_ao_reference( channel ), DAC_GAIN_DC6062E( channel ) );
1016 current_cal->subdevice = setup->da_subdev;
1017 sc_push_caldac( current_cal, setup->caldacs[ DAC_OFFSET_DC6062E( channel ) ] );
1018 sc_push_caldac( current_cal, setup->caldacs[ DAC_GAIN_DC6062E( channel ) ] );
1019 sc_push_caldac( current_cal, setup->caldacs[ DAC_LINEARITY_DC6062E( channel ) ] );
1020 sc_push_channel( current_cal, channel );
1021 sc_push_range( current_cal, SC_ALL_RANGES );
1022 sc_push_aref( current_cal, SC_ALL_AREFS );
1027 retval = write_calibration_file( setup, saved_cals, num_calibrations );
1028 for( i = 0; i < num_calibrations; i++ )
1029 clear_saved_calibration( &saved_cals[ i ] );
1034 static double ni_get_reference( calibration_setup_t *setup, int lsb_loc,int msb_loc)
1040 lsb=read_eeprom( setup, lsb_loc);
1041 msb=read_eeprom( setup, msb_loc);
1042 DPRINT(0,"eeprom reference lsb=%d msb=%d\n", lsb, msb);
1044 uv = ( lsb & 0xff ) | ( ( msb << 8 ) & 0xff00 );
1045 ref=5.000+1.0e-6*uv;
1046 DPRINT(0, "resulting reference voltage: %g\n", ref );
1047 if( fabs( ref - 5.0 ) > 0.005 )
1048 DPRINT( 0, "WARNING: eeprom indicates reference is more than 5mV away\n"
1049 "from 5V. Possible bad eeprom address?\n" );
1055 static void cal_ni_results(void)
1057 comedi_range *range;
1058 int bipolar_lowgain;
1059 int bipolar_highgain;
1060 int unipolar_lowgain;
1064 bipolar_lowgain = get_bipolar_lowgain(dev,setup->ad_subdev);
1065 bipolar_highgain = get_bipolar_highgain(dev,setup->ad_subdev);
1066 unipolar_lowgain = get_unipolar_lowgain(dev,setup->ad_subdev);
1068 /* 0 offset, low gain */
1069 range = comedi_get_range(dev,setup->ad_subdev,0,bipolar_lowgain);
1070 read_chan2(s,0,bipolar_lowgain);
1071 DPRINT(0,"bipolar zero offset, low gain [%g,%g]: %s\n",
1072 range->min,range->max,s);
1074 /* 0 offset, high gain */
1075 range = comedi_get_range(dev,setup->ad_subdev,0,bipolar_highgain);
1076 read_chan2(s,0,bipolar_highgain);
1077 DPRINT(0,"bipolar zero offset, high gain [%g,%g]: %s\n",
1078 range->min,range->max,s);
1080 /* unip/bip offset */
1081 range = comedi_get_range(dev,setup->ad_subdev,0,unipolar_lowgain);
1082 read_chan2(s,0,unipolar_lowgain);
1083 DPRINT(0,"unipolar zero offset, low gain [%g,%g]: %s\n",
1084 range->min,range->max,s);
1088 static void ni_mio_ai_postgain_cal(void)
1096 check_gain_chan_x(&l,CR_PACK(0,0,AREF_OTHER),1);
1097 offset_r0=linear_fit_func_y(&l,caldacs[1].current);
1098 printf("offset r0 %g\n",offset_r0);
1100 check_gain_chan_x(&l,CR_PACK(0,7,AREF_OTHER),1);
1101 offset_r7=linear_fit_func_y(&l,caldacs[1].current);
1102 printf("offset r7 %g\n",offset_r7);
1106 a=(offset_r0-offset_r7)/(200.0-1.0);
1107 a=caldacs[1].current-a/gain;
1111 caldacs[1].current=rint(a);
1115 static void ni_mio_ai_postgain_cal_2(int chan,int dac,int range_lo,int range_hi,double gain)
1117 double offset_lo,offset_hi;
1122 check_gain_chan_x(&l,CR_PACK(chan,range_lo,AREF_OTHER),dac);
1123 offset_lo=linear_fit_func_y(&l,caldacs[dac].current);
1124 printf("offset lo %g\n",offset_lo);
1126 check_gain_chan_x(&l,CR_PACK(chan,range_hi,AREF_OTHER),dac);
1127 offset_hi=linear_fit_func_y(&l,caldacs[dac].current);
1128 printf("offset hi %g\n",offset_hi);
1132 a=(offset_lo-offset_hi)/(gain-1.0);
1133 a=caldacs[dac].current-a/slope;
1137 caldacs[dac].current=rint(a);