change 6032e to DONE
[comedilib.git] / comedi_calibrate / ni.c
1 /*
2    A little auto-calibration utility, for boards
3    that support it.
4
5    Right now, it only supports NI E series boards,
6    but it should be easily portable.
7
8    A few things need improvement here:
9     - current system gets "close", but doesn't
10       do any fine-tuning
11     - no pre/post gain discrimination for the
12       A/D zero offset.
13     - should read (and use) the actual reference
14       voltage value from eeprom
15     - statistics would be nice, to show how good
16       the calibration is.
17     - doesn't check unipolar ranges
18     - "alternate calibrations" would be cool--to
19       accurately measure 0 in a unipolar range
20     - more portable
21  */
22
23 #define _GNU_SOURCE
24
25 #include <stdio.h>
26 #include <comedilib.h>
27 #include <fcntl.h>
28 #include <unistd.h>
29 #include <errno.h>
30 #include <getopt.h>
31 #include <ctype.h>
32 #include <math.h>
33 #include <stdlib.h>
34 #include <string.h>
35
36 #include "calib.h"
37
38
39 char ni_id[] = "$Id$";
40
41 struct board_struct{
42         char *name;
43         int status;
44         int (*cal)( calibration_setup_t *setup);
45 };
46
47 int ni_setup_board( calibration_setup_t *setup , const char *device_name );
48 void ni_setup_observables( calibration_setup_t *setup );
49
50 int cal_ni_at_mio_16e_2(calibration_setup_t *setup);
51 int cal_ni_daqcard_ai_16xe_50(calibration_setup_t *setup);
52 int cal_ni_at_mio_16e_1(calibration_setup_t *setup);
53 int cal_ni_pci_mio_16e_1(calibration_setup_t *setup);
54 int cal_ni_pci_6025e(calibration_setup_t *setup);
55 int cal_ni_pci_6035e(calibration_setup_t *setup);
56 int cal_ni_pci_6071e(calibration_setup_t *setup);
57 int cal_ni_pxi_6071e(calibration_setup_t *setup);
58 int cal_ni_at_mio_16e_10(calibration_setup_t *setup);
59 int cal_ni_pci_mio_16xe_50(calibration_setup_t *setup);
60 int cal_ni_pci_6023e(calibration_setup_t *setup);
61 int cal_ni_pci_6024e(calibration_setup_t *setup);
62 int cal_ni_at_mio_16xe_50(calibration_setup_t *setup);
63 int cal_ni_pci_mio_16xe_10(calibration_setup_t *setup);
64 int cal_ni_pci_6052e(calibration_setup_t *setup);
65 int cal_ni_pci_mio_16e_4(calibration_setup_t *setup);
66 int cal_ni_pci_6032e(calibration_setup_t *setup);
67
68 static struct board_struct boards[]={
69         { "at-mio-16e-2",       STATUS_DONE,    cal_ni_at_mio_16e_2 },
70         { "DAQCard-ai-16xe-50", STATUS_DONE,    cal_ni_daqcard_ai_16xe_50 },
71         { "at-mio-16xe-50",     STATUS_SOME,    cal_ni_at_mio_16xe_50 },
72         { "at-mio-16e-1",       STATUS_SOME,    cal_ni_at_mio_16e_1 },
73         { "pci-mio-16e-1",      STATUS_DONE,    cal_ni_pci_mio_16e_1 },
74         { "pci-6025e",          STATUS_SOME,    cal_ni_pci_6025e },
75         { "pci-6035e",          STATUS_DONE,    cal_ni_pci_6035e },
76         { "pci-6071e",          STATUS_SOME,    cal_ni_pci_6071e },
77         { "pxi-6071e",          STATUS_GUESS,   cal_ni_pxi_6071e },
78         { "at-mio-16e-10",      STATUS_GUESS,   cal_ni_at_mio_16e_10 },
79         { "pci-mio-16xe-50",    STATUS_SOME,    cal_ni_pci_mio_16xe_50 },
80         { "pci-6023e",          STATUS_SOME,    cal_ni_pci_6023e },
81         { "pci-mio-16xe-10",    STATUS_DONE,    cal_ni_pci_mio_16xe_10 },
82         { "pci-6052e",          STATUS_DONE,    cal_ni_pci_6052e },
83         { "pci-6024e",          STATUS_SOME,    cal_ni_pci_6024e },
84         { "pci-mio-16e-4",      STATUS_SOME,    cal_ni_pci_mio_16e_4 },
85         { "pci-6032e",          STATUS_DONE,    cal_ni_pci_6032e },
86 #if 0
87 //      { "at-mio-16de-10",     cal_ni_unknown },
88         { "at-mio-64e-3",       cal_ni_16e_1 },
89 //      { "at-mio-16xe-50",     cal_ni_unknown },
90 //      { "at-mio-16xe-10",     cal_ni_unknown },
91 //      { "at-ai-16xe-10",      cal_ni_unknown },
92 //      { "pxi-6030e",          cal_ni_unknown },
93 //      { "pxi-6040e",          cal_ni_unknown },
94 //      { "pci-6031e",          cal_ni_unknown },
95 //      { "pci-6033e",          cal_ni_unknown },
96         { "pxi-6025e",          cal_ni_6023e }, // guess
97         { "pci-6034e",          cal_ni_6023e }, // guess
98 //      { "pci-6110e",          cal_ni_unknown },
99 //      { "pci-6111e",          cal_ni_unknown },
100 //      { "pci-6711",           cal_ni_unknown },
101 //      { "pci-6713",           cal_ni_unknown },
102 //      { "pxi-6070e",          cal_ni_unknown },
103 //      { "pxi-6052e",          cal_ni_unknown },
104 //      { "DAQCard-ai-16e-4",   cal_ni_unknown },
105 //      { "DAQCard-6062e",      cal_ni_unknown },
106 //      { "DAQCard-6024e",      cal_ni_unknown },
107 #endif
108 };
109 #define n_boards (sizeof(boards)/sizeof(boards[0]))
110
111 enum {
112         ni_zero_offset_low = 0,
113         ni_zero_offset_high,
114         ni_reference_low,
115         ni_unip_offset_low,
116         ni_ao0_zero_offset,
117         ni_ao0_reference,
118         ni_ao1_zero_offset,
119         ni_ao1_reference,
120 };
121
122 int ni_setup( calibration_setup_t *setup , const char *device_name )
123 {
124         ni_setup_board( setup, device_name );
125         ni_setup_observables( setup );
126         setup_caldacs( setup, setup->caldac_subdev );
127
128         return 0;
129 }
130
131 int ni_setup_board( calibration_setup_t *setup, const char *device_name )
132 {
133         int i;
134
135         for(i = 0; i < n_boards; i++ ){
136                 if(!strcmp( device_name, boards[i].name )){
137                         setup->status = boards[i].status;
138                         setup->do_cal = boards[i].cal;
139                         break;
140                 }
141         }
142         return 0;
143 }
144
145 void ni_setup_observables( calibration_setup_t *setup )
146 {
147         comedi_insn tmpl;
148         comedi_insn po_tmpl2;
149         int bipolar_lowgain;
150         int bipolar_highgain;
151         int unipolar_lowgain;
152         double voltage_reference;
153         observable *o;
154
155         bipolar_lowgain = get_bipolar_lowgain( setup->dev, setup->ad_subdev);
156         bipolar_highgain = get_bipolar_highgain( setup->dev, setup->ad_subdev);
157         unipolar_lowgain = get_unipolar_lowgain( setup->dev, setup->ad_subdev);
158
159         voltage_reference = 5.000;
160
161         memset(&tmpl,0,sizeof(tmpl));
162         tmpl.insn = INSN_READ;
163         tmpl.n = 1;
164         tmpl.subdev = setup->ad_subdev;
165
166         memset(&po_tmpl2,0,sizeof(tmpl));
167         po_tmpl2.insn = INSN_CONFIG;
168         po_tmpl2.n = 2;
169         po_tmpl2.subdev = setup->ad_subdev;
170
171         /* 0 offset, low gain */
172         o = setup->observables + ni_zero_offset_low;
173         o->name = "ai, bipolar zero offset, low gain";
174 #if 0
175         o->preobserve_insn = po_tmpl2;
176         o->preobserve_insn.data = o->preobserve_data;
177         o->preobserve_insn.data[0] = INSN_CONFIG_ALT_SOURCE;
178         o->preobserve_insn.data[1] = CR_PACK(0,0,0);
179         o->observe_insn = tmpl;
180         o->observe_insn.chanspec = CR_ALT_SOURCE;
181         o->target = 0;
182 #else
183         o->observe_insn = tmpl;
184         o->observe_insn.chanspec = CR_PACK(0,bipolar_lowgain,AREF_OTHER);
185         o->target = 0;
186 #endif
187
188         /* 0 offset, high gain */
189         o = setup->observables + ni_zero_offset_high;
190         o->name = "ai, bipolar zero offset, high gain";
191         o->observe_insn = tmpl;
192         o->observe_insn.chanspec = CR_PACK(0,bipolar_highgain,AREF_OTHER);
193         o->target = 0;
194
195         /* voltage reference */
196         o = setup->observables + ni_reference_low;
197         o->name = "ai, bipolar voltage reference, low gain";
198         o->observe_insn = tmpl;
199         o->observe_insn.chanspec = CR_PACK(5,bipolar_lowgain,AREF_OTHER);
200         o->target = voltage_reference;
201
202         setup->n_observables = ni_reference_low + 1;
203
204         if(unipolar_lowgain>=0){
205                 /* unip/bip offset */
206                 o = setup->observables + ni_unip_offset_low;
207                 o->name = "ai, unipolar zero offset, low gain";
208                 o->observe_insn = tmpl;
209                 o->observe_insn.chanspec =
210                         CR_PACK(0,unipolar_lowgain,AREF_OTHER);
211                 o->target = 0;
212
213 #if 0
214                 /* unip gain */
215                 o = observables + ni_unip_reference_low;
216                 o->name = "ai, unipolar voltage reference, low gain";
217                 o->observe_insn = tmpl;
218                 o->observe_insn.chanspec =
219                         CR_PACK(5,unipolar_lowgain,AREF_OTHER);
220                 o->target = voltage_reference;
221                 i++;
222 #endif
223                 setup->n_observables = ni_unip_offset_low + 1;
224         }
225
226         if(setup->da_subdev>=0){
227                 comedi_insn po_tmpl;
228
229                 memset(&po_tmpl,0,sizeof(po_tmpl));
230                 po_tmpl.insn = INSN_WRITE;
231                 po_tmpl.n = 1;
232                 po_tmpl.subdev = setup->da_subdev;
233
234                 /* ao 0, zero offset */
235                 o = setup->observables + ni_ao0_zero_offset;
236                 o->name = "ao 0, zero offset, low gain";
237                 o->preobserve_insn = po_tmpl;
238                 o->preobserve_insn.chanspec = CR_PACK(0,0,0);
239                 o->preobserve_insn.data = o->preobserve_data;
240                 o->observe_insn = tmpl;
241                 o->observe_insn.chanspec =
242                         CR_PACK(2,bipolar_lowgain,AREF_OTHER);
243                 set_target( setup, ni_ao0_zero_offset,0.0);
244
245                 /* ao 0, gain */
246                 o = setup->observables + ni_ao0_reference;
247                 o->name = "ao 0, reference voltage, low gain";
248                 o->preobserve_insn = po_tmpl;
249                 o->preobserve_insn.chanspec = CR_PACK(0,0,0);
250                 o->preobserve_insn.data = o->preobserve_data;
251                 o->observe_insn = tmpl;
252                 o->observe_insn.chanspec = 
253                         CR_PACK(6,bipolar_lowgain,AREF_OTHER);
254                 set_target( setup, ni_ao0_reference,5.0);
255                 o->target -= voltage_reference;
256
257                 /* ao 1, zero offset */
258                 o = setup->observables + ni_ao1_zero_offset;
259                 o->name = "ao 1, zero offset, low gain";
260                 o->preobserve_insn = po_tmpl;
261                 o->preobserve_insn.chanspec = CR_PACK(1,0,0);
262                 o->preobserve_insn.data = o->preobserve_data;
263                 o->observe_insn = tmpl;
264                 o->observe_insn.chanspec =
265                         CR_PACK(3,bipolar_lowgain,AREF_OTHER);
266                 set_target( setup, ni_ao1_zero_offset,0.0);
267
268                 /* ao 1, gain */
269                 o = setup->observables + ni_ao1_reference;
270                 o->name = "ao 1, reference voltage, low gain";
271                 o->preobserve_insn = po_tmpl;
272                 o->preobserve_insn.chanspec = CR_PACK(1,0,0);
273                 o->preobserve_insn.data = o->preobserve_data;
274                 o->observe_insn = tmpl;
275                 o->observe_insn.chanspec =
276                         CR_PACK(7,bipolar_lowgain,AREF_OTHER);
277                 set_target( setup, ni_ao1_reference,5.0);
278                 o->target -= voltage_reference;
279
280                 setup->n_observables = ni_ao1_reference + 1;
281         }
282 }
283
284 int cal_ni_at_mio_16e_2(calibration_setup_t *setup)
285 {
286         postgain_cal( setup, ni_zero_offset_low,ni_zero_offset_high,1);
287         cal1( setup, ni_zero_offset_high,0);
288         cal1( setup, ni_reference_low,3);
289         cal1( setup, ni_unip_offset_low,2);
290         if(do_output){
291                 cal1( setup, ni_ao0_zero_offset,5);
292                 cal1( setup, ni_ao0_reference,6);
293                 cal1( setup, ni_ao1_zero_offset,8);
294                 cal1( setup, ni_ao1_reference,9);
295         }
296         return 0;
297 }
298
299 /*
300  * Device name: DAQCard-ai-16xe-50
301  * Comedi version: 0.7.60
302  * ai, bipolar zero offset, low gain
303  * offset 5.87(63)e-3, target 0
304  * caldac[0] gain=-2.243(21)e-6 V/bit S_min=208.079 dof=254
305  * caldac[2] gain=1.56378(22)e-4 V/bit S_min=1782.91 dof=254
306  * caldac[8] gain=2.499(14)e-7 V/bit S_min=234.915 dof=254
307  * ai, bipolar zero offset, high gain
308  * offset 4.251(49)e-5, target 0
309  * caldac[0] gain=-2.396(30)e-8 V/bit S_min=231.387 dof=254
310  * caldac[2] gain=1.56428(28)e-6 V/bit S_min=829.096 dof=254
311  * caldac[8] gain=2.61244(18)e-7 V/bit S_min=773.092 dof=254
312  * ai, bipolar voltage reference, low gain
313  * offset 4.99650(81), target 5
314  * caldac[0] gain=-3.78250(23)e-4 V/bit S_min=12207.6 dof=254
315  * caldac[1] gain=-9.878(22)e-6 V/bit S_min=346.795 dof=254
316  * caldac[2] gain=1.57172(23)e-4 V/bit S_min=969.526 dof=254
317  * caldac[8] gain=2.795(14)e-7 V/bit S_min=245.703 dof=254
318  * ai, unipolar zero offset, low gain
319  * offset 0.0133(14), target 0
320  * caldac[0] gain=3.73923(29)e-4 V/bit S_min=2855.79 dof=151
321  * caldac[1] gain=9.784(11)e-6 V/bit S_min=727.295 dof=254
322  * caldac[2] gain=7.8670(11)e-5 V/bit S_min=903.291 dof=254
323  * caldac[8] gain=2.7732(74)e-7 V/bit S_min=415.399 dof=254
324  */
325 int cal_ni_daqcard_ai_16xe_50(calibration_setup_t *setup)
326 {
327         postgain_cal( setup, ni_zero_offset_low,ni_zero_offset_high,2);
328         cal1( setup, ni_zero_offset_high,8);
329         cal1( setup, ni_reference_low,0);
330         cal1_fine( setup, ni_reference_low,0);
331         cal1( setup, ni_reference_low,1);
332         return 0;
333 }
334
335 int cal_ni_at_mio_16xe_50(calibration_setup_t *setup)
336 {
337         postgain_cal( setup, ni_zero_offset_low,ni_zero_offset_high,2);
338         cal1( setup, ni_zero_offset_high,8);
339         cal1( setup, ni_reference_low,0);
340         cal1_fine( setup, ni_reference_low,0);
341         cal1( setup, ni_reference_low,1);
342
343         if(do_output){
344                 cal1( setup, ni_ao0_zero_offset,6);
345                 cal1( setup, ni_ao0_reference,4);
346                 cal1( setup, ni_ao1_zero_offset,7);
347                 cal1( setup, ni_ao1_reference,5);
348         }
349         return 0;
350 }
351
352 int cal_ni_pci_mio_16xe_10(calibration_setup_t *setup)
353 {
354         postgain_cal( setup, ni_zero_offset_low, ni_zero_offset_high, 2);
355         postgain_cal( setup, ni_zero_offset_low, ni_zero_offset_high, 3);
356         cal1( setup, ni_zero_offset_high, 8);
357         cal1( setup, ni_reference_low, 0);
358         cal1( setup, ni_reference_low, 1);
359
360         if(do_output){
361                 cal1( setup, ni_ao0_zero_offset,6);
362                 cal1( setup, ni_ao0_reference,4);
363                 cal1( setup, ni_ao1_zero_offset,7);
364                 cal1( setup, ni_ao1_reference,5);
365         }
366         return 0;
367 }
368
369 int cal_ni_at_mio_16e_1(calibration_setup_t *setup)
370 {
371         return cal_ni_at_mio_16e_2( setup );
372 }
373
374 int cal_ni_pci_mio_16e_1(calibration_setup_t *setup)
375 {
376         //cal_ni_at_mio_16e_2();
377
378         postgain_cal( setup, ni_zero_offset_low,ni_zero_offset_high,1);
379         cal1( setup, ni_zero_offset_high,0);
380         cal1( setup, ni_reference_low,3);
381         cal1( setup, ni_unip_offset_low,2);
382         if(do_output){
383                 cal1( setup, ni_ao0_zero_offset,5);
384                 //cal1( setup, ni_ao0_zero_offset,4); /* linearity? */
385                 cal1( setup, ni_ao0_reference,6);
386                 cal1( setup, ni_ao1_zero_offset,8);
387                 //cal1( setup, ni_ao1_zero_offset,7); /* linearity? */
388                 cal1( setup, ni_ao1_reference,9);
389         }
390         return 0;
391 }
392
393 int cal_ni_pci_6032e(calibration_setup_t *setup)
394 {
395         postgain_cal(setup, ni_zero_offset_low, ni_zero_offset_high, 2);
396         postgain_cal(setup, ni_zero_offset_low, ni_zero_offset_high, 3);
397
398         cal1( setup, ni_zero_offset_high,8);
399
400         cal1( setup, ni_reference_low,0);
401         cal1_fine( setup, ni_reference_low,0);
402         cal1( setup, ni_reference_low,1);
403
404         return 0;
405 }
406
407 int cal_ni_pci_6035e(calibration_setup_t *setup)
408 {
409         /* this is for the ad8804_debug caldac */
410
411         postgain_cal( setup, ni_zero_offset_low,ni_zero_offset_high,4);
412
413         cal1( setup, ni_zero_offset_high,0);
414         cal1( setup, ni_zero_offset_high,8);
415
416         cal1( setup, ni_reference_low,2);
417
418         if(do_output){
419                 cal1( setup, ni_ao0_zero_offset,6);
420                 //cal1( setup, ni_ao0_zero_offset,10); /* linearity? */
421                 cal1( setup, ni_ao0_reference,11);
422                 cal1( setup, ni_ao1_zero_offset,9);
423                 //cal1( setup, ni_ao1_zero_offset,1); /* linearity? */
424                 cal1( setup, ni_ao1_reference,5);
425         }
426         return 0;
427 }
428
429 int cal_ni_pci_6071e(calibration_setup_t *setup)
430 {
431         postgain_cal( setup, ni_zero_offset_low,ni_zero_offset_high,1);
432         cal1( setup, ni_zero_offset_high,0);
433         cal1( setup, ni_reference_low,3);
434         cal1_fine( setup, ni_reference_low,3);
435         if(do_output){
436                 cal1( setup, ni_ao0_zero_offset,5);
437                 //cal1( setup, ni_ao0_zero_offset,4); /* linearity? */
438                 cal1( setup, ni_ao0_reference,6); /* guess.  Doesn't show up correctly in dump */
439                 cal1( setup, ni_ao1_zero_offset,8);
440                 //cal1( setup, ni_ao1_zero_offset,7); /* linearity? */
441                 cal1( setup, ni_ao1_reference,9);
442         }
443         return 0;
444 }
445
446 int cal_ni_pxi_6071e(calibration_setup_t *setup)
447 {
448         // 6071e (old)
449         postgain_cal( setup, ni_zero_offset_low,ni_zero_offset_high,1);
450         cal1( setup, ni_zero_offset_high,0);
451         cal1( setup, ni_reference_low,3);
452         if(do_output){
453                 // unknown
454         }
455         return 0;
456 }
457
458 int cal_ni_at_mio_16e_10(calibration_setup_t *setup)
459 {
460         // 16e-10 (old)
461         postgain_cal( setup, ni_zero_offset_low,ni_zero_offset_high,1);
462         cal1( setup, ni_zero_offset_high,10);
463         cal1( setup, ni_zero_offset_high,0);
464         cal1( setup, ni_reference_low,3);
465         cal1( setup, ni_unip_offset_low,2);
466         if(do_output){
467                 cal1( setup, ni_ao0_zero_offset,5); // guess
468                 cal1( setup, ni_ao0_reference,6); // guess
469                 cal1( setup, ni_ao1_zero_offset,8); // guess
470                 cal1( setup, ni_ao1_reference,9); // guess
471         }
472         return 0;
473 }
474
475 int cal_ni_pci_mio_16xe_50(calibration_setup_t *setup)
476 {
477         postgain_cal( setup, ni_zero_offset_low,ni_zero_offset_high,2);
478         cal1( setup, ni_zero_offset_high,8);
479         cal1( setup, ni_reference_low,0);
480         cal1_fine( setup, ni_reference_low,0);
481         cal1( setup, ni_reference_low,1);
482
483         if(do_output){
484                 cal1( setup, ni_ao0_zero_offset,6);
485                 cal1( setup, ni_ao0_reference,4);
486                 cal1( setup, ni_ao1_zero_offset,7);
487                 cal1( setup, ni_ao1_reference,5);
488         }
489         return 0;
490 }
491
492 int cal_ni_pci_6023e(calibration_setup_t *setup)
493 {
494         /* There seems to be a bug in the driver that doesn't allow
495          * access to caldac 10, and possibly others. */
496         postgain_cal( setup, ni_zero_offset_low,ni_zero_offset_high,1);
497         //cal1( setup, ni_zero_offset_high,10);
498         //cal1( setup, ni_zero_offset_high,0);
499         cal1( setup, ni_reference_low,3);
500         return 0;
501 }
502
503 int cal_ni_pci_6024e(calibration_setup_t *setup)
504 {
505         postgain_cal( setup, ni_zero_offset_low,ni_zero_offset_high,4);
506         cal1( setup, ni_zero_offset_high,0);
507         cal1( setup, ni_zero_offset_high,8);
508         cal1( setup, ni_reference_low,2);
509         if(do_output){
510                 cal1( setup, ni_ao0_zero_offset,6);
511                 //cal1( setup, ni_ao0_zero_offset,10); // nonlinearity?
512                 cal1( setup, ni_ao0_reference,11);
513                 cal1( setup, ni_ao1_zero_offset,9);
514                 //cal1( setup, ni_ao1_zero_offset,1); // nonlinearity?
515                 cal1( setup, ni_ao1_reference,5);
516         }
517         return 0;
518 }
519
520 int cal_ni_pci_6025e(calibration_setup_t *setup)
521 {
522         postgain_cal( setup, ni_zero_offset_low,ni_zero_offset_high,4); // was 1
523         //cal1( setup, ni_zero_offset_high,XXX); // was 10
524         cal1( setup, ni_zero_offset_high,8); // was 0
525         cal1( setup, ni_reference_low,2); // was 3
526         if(do_output){
527                 cal1( setup, ni_ao0_zero_offset,6); // was 5
528                 //cal1( setup, ni_ao0_zero_offset,10); // nonlinearity was 4
529                 //cal1( setup, ni_ao0_reference,XXX); // was 6
530                 cal1( setup, ni_ao1_zero_offset,9); // was 8
531                 //cal1( setup, ni_ao1_zero_offset,1); // nonlinearity was 7
532                 cal1( setup, ni_ao1_reference,5); // was 9
533         }
534         return 0;
535 }
536
537 int cal_ni_pci_6052e(calibration_setup_t *setup)
538 {
539         /*
540          * This board has noisy caldacs
541          *
542          * The NI documentation says:
543          *   0, 8   AI pregain  (coarse, fine)          3, 11
544          *   4, 12  AI postgain                         15,7
545          *   2, 10  AI reference                        1, 9
546          *   14, 7  AI unipolar offset                  5, 13
547          *
548          *   0      AO0 linearity
549          *   8, 4   AO0 reference               23, 19  7, 3
550          *   12     AO0 offset                  27      11
551          *   2      AO1 linearity                       
552          *   10, 6  AO1 reference               25, 21  9, 5
553          *   14     AO1 offset                  29, 17  13, 1
554          *
555          *   0  3       x       0011
556          *
557          *   2  1       x       0001
558          *
559          *   4  7       15 3    0111 0011
560          *
561          *   6          17 5         0101
562          *   7  x       
563          *   8  11      19 7    1011 0111
564          *
565          *   10 9       21 9    1001 1001
566          *
567          *   12 x       23 11        1011
568          *
569          *   14 5       13 1    0101 0001
570          *
571          */
572
573         cal_postgain_binary( setup, ni_zero_offset_low,ni_zero_offset_high,2);
574         postgain_cal( setup, ni_zero_offset_low,ni_zero_offset_high,3);
575         cal1( setup, ni_zero_offset_high,0);
576         cal1( setup, ni_zero_offset_high,1);
577         cal_binary( setup, ni_reference_low,4);
578         cal1_fine( setup, ni_reference_low,4);
579         cal1( setup, ni_reference_low,5);
580         cal1( setup, ni_unip_offset_low,6);
581         cal1_fine( setup, ni_unip_offset_low,6);
582         if(do_output){
583                 cal1( setup, ni_ao0_zero_offset,12+11);
584                 cal1_fine( setup, ni_ao0_zero_offset,12+11);
585                 cal1( setup, ni_ao0_reference,12+7);
586                 cal1_fine( setup, ni_ao0_reference,12+7);
587                 cal1( setup, ni_ao0_reference,12+3);
588                 cal1( setup, ni_ao1_zero_offset,12+1);
589                 cal1( setup, ni_ao1_reference,12+9);
590                 cal1_fine( setup, ni_ao1_reference,12+9);
591                 cal1( setup, ni_ao1_reference,12+5);
592         }
593         return 0;
594 }
595
596 int cal_ni_pci_mio_16e_4(calibration_setup_t *setup)
597 {
598         /* this is for the ad8804_debug caldac */
599
600         cal_postgain_binary( setup, ni_zero_offset_low,ni_zero_offset_high,4);
601         //cal_postgain_fine( setup, ni_zero_offset_low,ni_zero_offset_high,4);
602         cal1( setup, ni_zero_offset_high,8);
603         cal_binary( setup, ni_reference_low,2);
604         cal1_fine( setup, ni_reference_low,2);
605
606         cal1( setup, ni_unip_offset_low,7);
607         cal1_fine( setup, ni_unip_offset_low,7);
608
609         if(do_output){
610                 cal_binary( setup, ni_ao0_zero_offset,6);
611                 cal1_fine( setup, ni_ao0_zero_offset,6);
612                 //cal1( setup, ni_ao0_nonlinearity,10);
613                 cal_binary( setup, ni_ao0_reference,11);
614                 cal1_fine( setup, ni_ao0_reference,11);
615                 cal_binary( setup, ni_ao1_zero_offset,9);
616                 cal1_fine( setup, ni_ao1_zero_offset,9);
617                 //cal1( setup, ni_ao1_nonlinearity,1);
618                 cal_binary( setup, ni_ao1_reference,5);
619                 cal1_fine( setup, ni_ao1_reference,5);
620         }
621         return 0;
622 }
623
624 double ni_get_reference( calibration_setup_t *setup, int lsb_loc,int msb_loc)
625 {
626         int lsb,msb;
627         int uv;
628         double ref;
629
630         lsb=read_eeprom( setup, lsb_loc);
631         msb=read_eeprom( setup, msb_loc);
632         printf("lsb=%d msb=%d\n",read_eeprom( setup, 425),read_eeprom( setup, 426));
633
634         uv=lsb | (msb<<8);
635         if(uv>=0x8000)uv-=0x10000;
636         ref=5.000+1.0e-6*uv;
637         printf("ref=%g\n",ref);
638
639         return ref;
640 }
641
642 #if 0
643 void cal_ni_results(void)
644 {
645         comedi_range *range;
646         int bipolar_lowgain;
647         int bipolar_highgain;
648         int unipolar_lowgain;
649         //int have_ao;
650         char s[32];
651
652         bipolar_lowgain = get_bipolar_lowgain(dev,setup->ad_subdev);
653         bipolar_highgain = get_bipolar_highgain(dev,setup->ad_subdev);
654         unipolar_lowgain = get_unipolar_lowgain(dev,setup->ad_subdev);
655
656         /* 0 offset, low gain */
657         range = comedi_get_range(dev,setup->ad_subdev,0,bipolar_lowgain);
658         read_chan2(s,0,bipolar_lowgain);
659         DPRINT(0,"bipolar zero offset, low gain [%g,%g]: %s\n",
660                 range->min,range->max,s);
661
662         /* 0 offset, high gain */
663         range = comedi_get_range(dev,setup->ad_subdev,0,bipolar_highgain);
664         read_chan2(s,0,bipolar_highgain);
665         DPRINT(0,"bipolar zero offset, high gain [%g,%g]: %s\n",
666                 range->min,range->max,s);
667
668         /* unip/bip offset */
669         range = comedi_get_range(dev,setup->ad_subdev,0,unipolar_lowgain);
670         read_chan2(s,0,unipolar_lowgain);
671         DPRINT(0,"unipolar zero offset, low gain [%g,%g]: %s\n",
672                 range->min,range->max,s);
673
674 }
675
676 void ni_mio_ai_postgain_cal(void)
677 {
678         linear_fit_t l;
679         double offset_r0;
680         double offset_r7;
681         double gain;
682         double a;
683
684         check_gain_chan_x(&l,CR_PACK(0,0,AREF_OTHER),1);
685         offset_r0=linear_fit_func_y(&l,caldacs[1].current);
686         printf("offset r0 %g\n",offset_r0);
687
688         check_gain_chan_x(&l,CR_PACK(0,7,AREF_OTHER),1);
689         offset_r7=linear_fit_func_y(&l,caldacs[1].current);
690         printf("offset r7 %g\n",offset_r7);
691
692         gain=l.slope;
693         
694         a=(offset_r0-offset_r7)/(200.0-1.0);
695         a=caldacs[1].current-a/gain;
696
697         printf("%g\n",a);
698
699         caldacs[1].current=rint(a);
700         update_caldac(1);
701 }
702
703 void ni_mio_ai_postgain_cal_2(int chan,int dac,int range_lo,int range_hi,double gain)
704 {
705         double offset_lo,offset_hi;
706         linear_fit_t l;
707         double slope;
708         double a;
709
710         check_gain_chan_x(&l,CR_PACK(chan,range_lo,AREF_OTHER),dac);
711         offset_lo=linear_fit_func_y(&l,caldacs[dac].current);
712         printf("offset lo %g\n",offset_lo);
713
714         check_gain_chan_x(&l,CR_PACK(chan,range_hi,AREF_OTHER),dac);
715         offset_hi=linear_fit_func_y(&l,caldacs[dac].current);
716         printf("offset hi %g\n",offset_hi);
717
718         slope=l.slope;
719         
720         a=(offset_lo-offset_hi)/(gain-1.0);
721         a=caldacs[dac].current-a/slope;
722
723         printf("%g\n",a);
724
725         caldacs[dac].current=rint(a);
726         update_caldac(dac);
727 }
728 #endif
729