~ubuntu-branches/ubuntu/trusty/argyll/trusty-proposed

« back to all changes in this revision

Viewing changes to spectro/dtp20.c

  • Committer: Package Import Robot
  • Author(s): Artur Rona
  • Date: 2014-02-12 00:35:39 UTC
  • mfrom: (13.1.24 sid)
  • Revision ID: package-import@ubuntu.com-20140212003539-24tautzlitsiz61w
Tags: 1.5.1-5ubuntu1
* Merge from Debian unstable. (LP: #1275572) Remaining changes:
  - debian/control:
    + Build-depend on libtiff-dev rather than libtiff4-dev.
  - debian/control, debian/patches/06_fix_udev_rule.patch:
    + Fix udev rules to actually work; ENV{ACL_MANAGE} has
      stopped working ages ago, and with logind it's now the
      "uaccess" tag. Dropping also consolekit from Recommends.
  - debian/patches/drop-usb-db.patch:
    + Use hwdb builtin, instead of the obsolete usb-db
      in the udev rules.
* debian/patches/05_ftbfs-underlinkage.diff:
  - Dropped change, no needed anymore.
* Refresh the patches.

Show diffs side-by-side

added added

removed removed

Lines of Context:
7
7
 * Author: Graeme W. Gill
8
8
 * Date:   10/3/2001
9
9
 *
10
 
 * Copyright 1996 - 2007, Graeme W. Gill
 
10
 * Copyright 1996 - 2013, Graeme W. Gill
11
11
 * All rights reserved.
12
12
 *
13
13
 * This material is licenced under the GNU GENERAL PUBLIC LICENSE Version 2 or later :-
47
47
#include "aconfig.h"
48
48
#else /* SALONEINSTLIB */
49
49
#include "sa_config.h"
 
50
#endif /* SALONEINSTLIB */
50
51
#include "numsup.h"
51
 
#endif /* SALONEINSTLIB */
52
52
#include "xspect.h"
53
53
#include "insttypes.h"
 
54
#include "conv.h"
54
55
#include "icoms.h"
55
 
#include "conv.h"
56
56
#include "dtp20.h"
57
57
 
58
 
#undef DEBUG
59
 
 
60
 
#ifdef DEBUG
61
 
#define DBG(xxx) printf xxx ;
62
 
#else
63
 
#define DBG(xxx) 
64
 
#endif
65
 
 
66
 
 
67
58
static inst_code dtp20_interp_code(inst *pp, int ec);
68
59
static inst_code activate_mode(dtp20 *p);
69
60
 
100
91
 
101
92
/* Interpret an icoms error into a DTP20 error */
102
93
static int icoms2dtp20_err(int se) {
103
 
        if (se & ICOM_USERM) {
104
 
                se &= ICOM_USERM;
105
 
                if (se == ICOM_TRIG)
106
 
                        return DTP20_USER_TRIG;
107
 
                if (se == ICOM_CMND)
108
 
                        return DTP20_USER_CMND;
109
 
                if (se == ICOM_TERM)
110
 
                        return DTP20_USER_TERM;
111
 
                return DTP20_USER_ABORT;
112
 
        }
113
94
        if (se != ICOM_OK) {
114
95
                if (se & ICOM_TO)
115
96
                        return DTP20_TIMEOUT; 
130
111
        char tc = '>';                  /* Terminating character */
131
112
        int ntc = 1;                    /* Number of terminating characters */
132
113
        int rv, se, insize;
133
 
        int isdeb = 0;
134
 
        int xuserm = 0;                 /* User flags from transmit operation */
135
114
 
136
 
        /* Turn off low level debug messages, and sumarise them here */
137
 
        isdeb = p->icom->debug;
138
 
        p->icom->debug = 0;
139
 
        
140
 
        if (isdeb) fprintf(stderr,"dtp20: Sending '%s'",icoms_fix(in));
 
115
        a1logd(p->log, 4, "dtp20: Sending '%s'",icoms_fix(in));
141
116
 
142
117
        insize = strlen(in);
143
118
        if (insize > 0) {
144
119
                if ((se = p->icom->usb_control(p->icom, 0x41, 0x00, 0x00, 0x00, (unsigned char *)in, insize, to)) != ICOM_OK) {
145
 
                        if (isdeb) fprintf(stderr,"send failed ICOM err 0x%x\n",se);
146
 
                        /* If something other than a user terminate, trigger or command */
147
 
                        if ((se & ~ICOM_USERM) != ICOM_OK || (se & ICOM_USERM) == ICOM_USER) {
148
 
                                p->icom->debug = isdeb;
149
 
                                return dtp20_interp_code((inst *)p, icoms2dtp20_err(se));
150
 
                        } else {
151
 
                                xuserm = (se & ICOM_USERM);
152
 
                        }
 
120
                        a1logd(p->log, 1, "dtp20: send command failed ICOM err 0x%x\n",se);
 
121
                        return dtp20_interp_code((inst *)p, icoms2dtp20_err(se));
153
122
                }
154
123
        }
155
124
 
156
125
        if ((se = p->icom->read(p->icom, out, bsize, tc, ntc, to)) != 0) {
157
 
                if (isdeb) fprintf(stderr,"response failed ICOM err 0x%x\n",se);
158
 
                p->icom->debug = isdeb;
 
126
                a1logd(p->log, 1, "dtp20: read response failed ICOM err 0x%x\n",se);
159
127
                return dtp20_interp_code((inst *)p, icoms2dtp20_err(se));
160
128
        }
161
129
 
162
 
        /* Deal with user terminate, trigger or command on send */
163
 
        if (xuserm != ICOM_OK)
164
 
                return dtp20_interp_code((inst *)p, icoms2dtp20_err(xuserm));
165
 
 
166
130
        rv = DTP20_OK;
167
131
        if (tc == '>' && ntc == 1) {    /* Expecting DTP type error code */
168
132
                rv = extract_ec(out);
176
140
                }
177
141
        }
178
142
 
179
 
        if (isdeb) fprintf(stderr,"response '%s' ICOM err 0x%x\n",icoms_fix(out),rv);
180
 
        p->icom->debug = isdeb;
 
143
        a1logd(p->log, 4, "dtp20: response '%s' ICOM err 0x%x\n",icoms_fix(out),rv);
181
144
        return dtp20_interp_code((inst *)p, rv);
182
145
}
183
146
 
195
158
        int rv, se, insize;
196
159
        int bread = 0;
197
160
        char *op;
198
 
        int isdeb = 0;
199
 
        int xuserm = 0;                 /* User flags from transmit operation */
200
161
 
201
 
        /* Turn off low level debug messages, and sumarise them here */
202
 
        isdeb = p->icom->debug;
203
 
        p->icom->debug = 0;
204
 
        
205
 
        if (isdeb) fprintf(stderr,"dtp20: Sending '%s'",icoms_fix(in));
 
162
        a1logd(p->log, 4, "dtp20: Sending '%s'",icoms_fix(in));
206
163
 
207
164
        insize = strlen(in);
208
165
        if (insize > 0) {
209
166
                if ((se = p->icom->usb_control(p->icom, 0x41, 0x00, 0x00, 0x00, (unsigned char *)in, insize, top)) != ICOM_OK) {
210
 
                        if (isdeb) fprintf(stderr,"send failed ICOM err 0x%x\n",se);
211
 
                        /* If something other than a user terminate, trigger or command */
212
 
                        if ((se & ~ICOM_USERM) != ICOM_OK || (se & ICOM_USERM) == ICOM_USER) {
213
 
                                p->icom->debug = isdeb;
214
 
                                return dtp20_interp_code((inst *)p, icoms2dtp20_err(se));
215
 
                        } else {
216
 
                                xuserm = (se & ICOM_USERM);
217
 
                        }
 
167
                        a1logd(p->log, 1, "dtp20: send failed ICOM err 0x%x\n",se);
 
168
                        return dtp20_interp_code((inst *)p, icoms2dtp20_err(se));
218
169
                }
219
170
        }
220
171
 
224
175
 
225
176
                if (rsize > bsize)
226
177
                        rsize = bsize;
227
 
//printf("~1 doing %d, %d to go\n",rsize, bsize);
228
178
 
229
 
                if ((se = p->icom->usb_read(p->icom, 0x81, (unsigned char *)op, rsize, &bread, top)) != ICOM_OK) {
 
179
                if ((se = p->icom->usb_read(p->icom, NULL, 0x81, (unsigned char *)op, rsize, &bread, top)) != ICOM_OK) {
230
180
                        if (se == ICOM_SHORT) {
231
 
                                if (isdeb) fprintf(stderr,"response failed expected %d got %d ICOM err 0x%x\n",rsize,bread,se);
 
181
                                a1logd(p->log, 1, "dtp20: response failed expected %d got %d ICOM err 0x%x\n",
 
182
                                                                                              rsize,bread,se);
232
183
                        } else {
233
 
                                if (isdeb) fprintf(stderr,"response failed ICOM err 0x%x\n",se);
 
184
                                a1logd(p->log, 1, "dtp20: response failed ICOM err 0x%x\n",se);
234
185
                        }
235
 
                        p->icom->debug = isdeb;
236
186
                        return dtp20_interp_code((inst *)p, icoms2dtp20_err(se));
237
187
                }
238
 
//printf("~1 read %d\n",bread);
239
188
                bsize -= bread;
240
189
                op += bread; 
241
190
        }
242
191
                
243
 
        /* Deal with user terminate, trigger or command on send */
244
 
        if (xuserm != ICOM_OK)
245
 
                return dtp20_interp_code((inst *)p, icoms2dtp20_err(xuserm));
246
 
 
247
192
        rv = DTP20_OK;
248
193
 
249
 
        if (isdeb) fprintf(stderr,"response '%s' ICOM err 0x%x\n",icoms_tohex((unsigned char *)out, bread),rv);
250
 
        p->icom->debug = isdeb;
 
194
        a1logd(p->log, 4, "dtp20: response '%s' ICOM err 0x%x\n",
 
195
                    icoms_tohex((unsigned char *)out, bread),rv);
251
196
        return dtp20_interp_code((inst *)p, rv);
252
197
}
253
198
 
254
199
/* Establish communications with a DTP20 */
255
 
/* Use the baud rate given, and timeout in to secs */
256
200
/* Return DTP_COMS_FAIL on failure to establish communications */
257
201
static inst_code
258
 
dtp20_init_coms(inst *pp, int port, baud_rate br, flow_control fc, double tout) {
 
202
dtp20_init_coms(inst *pp, baud_rate br, flow_control fc, double tout) {
259
203
        dtp20 *p = (dtp20 *)pp;
260
204
        char buf[MAX_MES_SIZE];
 
205
        int se;
261
206
        inst_code ev = inst_ok;
262
207
 
263
 
        if (p->debug) {
264
 
                p->icom->debug = p->debug;      /* Turn on debugging */
265
 
                fprintf(stderr,"dtp20: About to init coms\n");
266
 
        }
267
 
 
268
 
        if (p->icom->is_usb_portno(p->icom, port) != instUnknown) {
269
 
 
270
 
                if (p->debug) fprintf(stderr,"dtp20: About to init USB\n");
 
208
        if (p->icom->port_type(p->icom) == icomt_usb) {
 
209
 
 
210
                a1logd(p->log, 4, "dtp20: About to init USB\n");
271
211
 
272
212
                /* Set config, interface, write end point, read end point, read quanta */
273
 
                p->icom->set_usb_port(p->icom, port, 1, 0x00, 0x81, icomuf_none, 0, NULL); 
 
213
                if ((se = p->icom->set_usb_port(p->icom, 1, 0x00, 0x81, icomuf_none, 0, NULL)) != ICOM_OK) { 
 
214
                        a1logd(p->log, 1, "dtp20: set_usbe_port failed ICOM err 0x%x\n",se);
 
215
                        return dtp20_interp_code((inst *)p, icoms2dtp20_err(se));
 
216
                }
274
217
 
275
218
                /* Blind reset it twice - it seems to sometimes hang up */
276
219
                /* otherwise under OSX */
278
221
                dtp20_command(p, "0PR\r", buf, MAX_MES_SIZE, 0.5);
279
222
 
280
223
        } else {
281
 
                if (p->debug) fprintf(stderr,"dtp20: Failed to find connection to instrument\n");
 
224
                a1logd(p->log, 1, "dtp20: Failed to find connection to instrument\n");
282
225
                return inst_coms_fail;
283
226
        }
284
227
 
285
228
        /* Check instrument is responding */
286
229
        if ((ev = dtp20_command(p, "\r", buf, MAX_MES_SIZE, 1.5)) != inst_ok) {
287
 
                if (p->debug) fprintf(stderr,"dtp20: Failed to get a response from instrument\n");
 
230
                a1logd(p->log, 1, "dtp20: Failed to get a response from instrument\n");
288
231
                return inst_coms_fail;
289
232
        }
290
233
 
291
 
        if (p->verb) {
 
234
        /* Print the general information returned by instrument */
 
235
        if (p->log->verb) {
292
236
                int i, j;
293
 
                if ((ev = dtp20_command(p, "GI\r", buf, MAX_MES_SIZE, 0.2)) != inst_ok)
 
237
                if ((ev = dtp20_command(p, "GI\r", buf, MAX_MES_SIZE, 0.2)) != inst_ok) {
 
238
                        a1logd(p->log, 1, "dtp20: GI command failed with ICOM err 0x%x\n",ev);
294
239
                        return ev;
 
240
                }
295
241
                for (j = i = 0; ;i++) {
296
242
                        if (buf[i] == '<' || buf[i] == '\000')
297
243
                                break;
298
244
                        if (buf[i] == '\r') {
299
245
                                buf[i] = '\000';
300
 
                                printf(" %s\n",&buf[j]);
 
246
                                a1logv(p->log, 1, " %s\n",&buf[j]);
301
247
                                if (buf[i+1] == '\n')
302
248
                                        i++;
303
249
                                j = i+1;
305
251
                }
306
252
        }
307
253
 
308
 
        if (p->debug) fprintf(stderr,"dtp20: Got coms OK\n");
 
254
        a1logd(p->log, 4, "dtp20: Got coms OK\n");
309
255
 
310
256
        p->gotcoms = 1;
311
257
        return inst_ok;
380
326
        char buf[MAX_MES_SIZE];
381
327
        inst_code rv = inst_ok;
382
328
 
 
329
        a1logd(p->log, 2, "dtp20_init_inst: called\n");
 
330
 
383
331
        if (p->gotcoms == 0)
384
332
                return inst_no_coms;            /* Must establish coms before calling init */
385
333
 
394
342
                return rv;
395
343
 
396
344
        /* Get the model and version number */
397
 
        if ((rv = dtp20_command(p, "SV\r", buf, MAX_MES_SIZE, 0.2)) != inst_ok)
 
345
        if ((rv = dtp20_command(p, "SV\r", buf, MAX_MES_SIZE, 0.5)) != inst_ok)
398
346
                return rv;
399
347
 
400
348
        /* Check that it is a DTP20 */
405
353
//      /* Set Beeper to off */
406
354
//      if ((rv = dtp20_command(p, "0001CF\r", buf, MAX_MES_SIZE, 0.2)) != inst_ok)
407
355
//              return rv;
 
356
 
408
357
        /* Set Beeper to on */
409
358
        if ((rv = dtp20_command(p, "0101CF\r", buf, MAX_MES_SIZE, 0.2)) != inst_ok)
410
359
                return rv;
422
371
                return rv;
423
372
                
424
373
        /* set default trigger mode */
425
 
        p->trig = inst_opt_trig_keyb_switch;
 
374
        p->trig = inst_opt_trig_user_switch;
426
375
 
427
376
        /* - - - - - - - - - - - - - - - - - - - - - - - - */
428
377
        /* Setup for the type of measurements we want to do */
441
390
        /* Reset retrieval of saved spot readings */ 
442
391
        p->savix = 0;
443
392
 
444
 
        if (rv == inst_ok)
445
 
                p->inited = 1;
 
393
        a1logd(p->log, 2, "dtp20_init_inst: instrument inited OK\n");
 
394
        p->inited = 1;
446
395
 
447
396
        return inst_ok;
448
397
}
474
423
        if (!p->inited)
475
424
                return inst_no_init;
476
425
 
477
 
        if ((p->mode & inst_mode_measurement_mask) != inst_mode_s_ref_chart)
 
426
        if (!IMODETST(p->mode,inst_mode_s_ref_chart))
478
427
                return inst_unsupported;
479
428
 
480
429
        /* Confirm that there is a chart ready to read */
512
461
        if (ttlp != npatch
513
462
         || sl != sip
514
463
         || (id != -1 && id != chid)) {
515
 
                if (p->debug) fprintf(stderr,"Got %d, xpt %d patches, got %d xpt %d strip lgth, got %d xpt %d chart id\n",ttlp,npatch,sl,sip,id,chid);
 
464
                a1logd(p->log, 2, "dtp20: Got %d, xpt %d patches, got %d xpt %d strip lgth, "
 
465
                                       "got %d xpt %d chart id\n",ttlp,npatch,sl,sip,id,chid);
516
466
                return inst_nochmatch;
517
467
        }
518
468
 
519
 
        if (p->verb)
520
 
                printf("Chart has %d patches, %d per strip, chart id %d\n",ttlp,sl,id);
 
469
        a1logv(p->log, 1, "Chart has %d patches, %d per strip, chart id %d\n",ttlp,sl,id);
521
470
 
522
471
        /* Disable multiple data output */
523
472
        if ((ev = dtp20_command(p, "001ACF\r", buf, MAX_MES_SIZE, 0.5)) != inst_ok)
528
477
                char *tp, cmd[10];
529
478
                int i;
530
479
 
531
 
                if (p->verb)
532
 
                        printf("Reading saved strip %d of %d\n",six,pich);
 
480
                a1logv(p->log, 1, "Reading saved strip %d of %d\n",six,pich);
533
481
 
534
482
                /* Select the strip to read */
535
483
                sprintf(cmd, "%03d01TS\r",six);
558
506
                                        return inst_protocol_error;
559
507
                                }
560
508
                        }
 
509
                        tvals[i].loc[0] = '\000';
 
510
                        tvals[i].mtype = inst_mrt_reflective;
561
511
                        tvals[i].XYZ_v = 1;
562
 
                        tvals[i].aXYZ_v = 0;
563
 
                        tvals[i].Lab_v = 0;
564
512
                        tvals[i].sp.spec_n = 0;
565
513
                        tvals[i].duration = 0.0;
566
514
                        tp += strlen(tp) + 1;
605
553
                }
606
554
        }
607
555
 
608
 
        if (p->verb)
609
 
                printf("All saved strips read\n");
 
556
        a1logv(p->log, 1, "All saved strips read\n");
610
557
        return inst_ok;
611
558
}
612
559
 
637
584
                return inst_no_init;
638
585
 
639
586
        /* This funtion isn't valid in saved data mode */
640
 
        if ((p->mode & inst_mode_measurement_mask) != inst_mode_ref_strip)
641
 
                return inst_wrong_config;
 
587
        if (!IMODETST(p->mode, inst_mode_ref_strip))
 
588
                return inst_wrong_setup;
642
589
 
643
590
        /* Until we get the right status or give up */
644
591
        for (i = 0;;i++) {
653
600
                        return (inst_misread | DTP20_NOT_EMPTY);        /* Has onffline patches */      
654
601
                if (i < 20) {
655
602
                        if (cs == 0 || (cs >= 4 && cs <= 12)) { /* Ignore transient status */
656
 
                                msec_sleep(200);
 
603
                                msec_sleep(100);
657
604
                                continue;
658
605
                        }
659
606
                }
664
611
        build_strip(p, tbuf, name, npatch, pname, sguide, pwid, gwid, twid);
665
612
 
666
613
        if ((ev = dtp20_command(p, tbuf, buf, MAX_MES_SIZE, 1.5)) != inst_ok) {
667
 
                if (p->verb)
668
 
                        printf("Interactive strip reading won't work on Firmware earlier than V1.03 !\n");
 
614
                a1logv(p->log, 1, "Interactive strip reading won't work on Firmware earlier than V1.03 !\n");
669
615
                return ev;
670
616
        }
671
617
 
672
 
        if (p->trig == inst_opt_trig_keyb_switch) {
 
618
        if (p->trig == inst_opt_trig_user_switch) {
673
619
                int touts = 0;
674
620
 
675
 
                /* Wait for a strip value to turn up, or a user abort/command */
 
621
                /* Wait for a strip value to turn up, or a user command/abort */
676
622
                for (;;) {
677
 
                        if ((ev = dtp20_command(p, "CS\r", buf, MAX_MES_SIZE, 0.2)) != inst_ok) {
678
 
                                if (ev == (inst_coms_fail | DTP20_TIMEOUT)) {
679
 
                                        if (touts++ > 40)
680
 
                                                return ev;
681
 
                                        continue; 
682
 
                                }
 
623
 
 
624
                        ev = dtp20_command(p, "CS\r", buf, MAX_MES_SIZE, 0.2);
 
625
 
 
626
                        if (ev == (inst_coms_fail | DTP20_TIMEOUT)) {
 
627
                                /* Ignore transient timeouts */
 
628
                                if (touts++ > 40)
 
629
                                        return ev;
 
630
                                continue; 
 
631
 
 
632
                        } else if (ev != inst_ok) {
683
633
                                if ((ev & inst_mask) == inst_needs_cal)
684
634
                                        p->need_cal = 1;
685
 
                                if ((ev & inst_mask) != inst_user_trig)
686
 
                                        return ev;
687
 
                                user_trig = 1;
688
 
                        } else {
 
635
                                return ev;                              /* Error */
 
636
                        } else {                                        
689
637
                                int stat;
690
638
                                if (sscanf(buf, " %d ", &stat) != 1)
691
639
                                        stat = 6;
692
 
                                /* Ingnore benign status */
 
640
 
 
641
                                /* Ignore benign status */
693
642
                                if (stat != 4 && stat != 6 && stat != 7) {
 
643
                                        /* Not ready - Check for user trigger or command */
 
644
                                        if (p->uicallback != NULL) {
 
645
                                                if ((ev = p->uicallback(p->uic_cntx, inst_armed)) != inst_ok) {
 
646
                                                        if (ev == inst_user_abort) {
 
647
                                                                return ev;                      /* Error or user abort */
 
648
                                                        } else if (ev == inst_user_trig) {
 
649
                                                                user_trig = 1;          /* User trigger */
 
650
                                                                break;
 
651
                                                        }
 
652
                                                }
 
653
                                        }
 
654
                                        /* Keep waiting */
694
655
                                        msec_sleep(200);
695
656
                                        continue;
696
 
                                }
697
 
                                switch_trig = 1;
698
 
                        }
699
 
                        break;
700
 
                }
701
 
                if (p->trig_return)
702
 
                        printf("\n");
703
 
 
704
 
        } else if (p->trig == inst_opt_trig_keyb) {
705
 
                if ((se = icoms_poll_user(p->icom, 1)) != ICOM_TRIG) {
706
 
                        /* Abort, term or command */
707
 
                        return dtp20_interp_code((inst *)p, icoms2dtp20_err(se));
708
 
                }
709
 
                user_trig = 1;
710
 
                if (p->trig_return)
711
 
                        printf("\n");
 
657
 
 
658
                                } else {
 
659
                                        /* Ready - continue on */
 
660
                                        switch_trig = 1;
 
661
                                        break;
 
662
                                }
 
663
                        }
 
664
                }
 
665
                /* Notify of trigger */
 
666
                if (p->uicallback)
 
667
                        p->uicallback(p->uic_cntx, inst_triggered); 
 
668
 
 
669
        } else if (p->trig == inst_opt_trig_user) {
 
670
                if (p->uicallback == NULL) {
 
671
                        a1logd(p->log, 1, "dtp20: inst_opt_trig_user but no uicallback function set!\n");
 
672
                        return inst_unsupported;
 
673
                }
 
674
 
 
675
                for (;;) {
 
676
                        if ((ev = p->uicallback(p->uic_cntx, inst_armed)) != inst_ok) {
 
677
                                if (ev == inst_user_abort) 
 
678
                                        return ev;
 
679
                                if (ev == inst_user_trig) {
 
680
                                        user_trig = 1;
 
681
                                        break;                                  /* Trigger */
 
682
                                }
 
683
                        }
 
684
                        msec_sleep(200);
 
685
                }
 
686
                /* Notify of trigger */
 
687
                if (p->uicallback)
 
688
                        p->uicallback(p->uic_cntx, inst_triggered); 
 
689
        
 
690
        /* Progromatic Trigger */
 
691
        } else {
 
692
                /* Check for abort */
 
693
                if (p->uicallback != NULL
 
694
                 && (ev = p->uicallback(p->uic_cntx, inst_armed)) == inst_user_abort)
 
695
                        return ev;
712
696
        }
713
697
 
714
698
        /* Trigger a read if the switch has not been used */
748
732
                                return inst_protocol_error;
749
733
                        }
750
734
                }
 
735
                vals[i].loc[0] = '\000';
 
736
                vals[i].mtype = inst_mrt_reflective;
751
737
                vals[i].XYZ_v = 1;
752
 
                vals[i].aXYZ_v = 0;
753
 
                vals[i].Lab_v = 0;
754
738
                vals[i].sp.spec_n = 0;
755
739
                vals[i].duration = 0.0;
756
740
                tp += strlen(tp) + 1;
820
804
dtp20_read_sample(
821
805
inst *pp,
822
806
char *name,                     /* Strip name (7 chars) */
823
 
ipatch *val) {          /* Pointer to instrument patch value */
 
807
ipatch *val,            /* Pointer to instrument patch value */
 
808
instClamping clamp) {           /* NZ if clamp XYZ/Lab to be +ve */
824
809
        dtp20 *p = (dtp20 *)pp;
825
810
        char buf[MAX_MES_SIZE], *tp;
826
811
        int se;
834
819
                return inst_no_init;
835
820
 
836
821
        /* This combination doesn't make any sense... */
837
 
        if ((p->mode & inst_mode_measurement_mask) == inst_mode_s_ref_spot
838
 
         && p->trig == inst_opt_trig_keyb_switch) {
839
 
                return inst_wrong_config;
 
822
        if (IMODETST(p->mode, inst_mode_s_ref_spot) && p->trig == inst_opt_trig_user_switch) {
 
823
                return inst_wrong_setup;
840
824
        }
841
825
 
842
 
        if (p->trig == inst_opt_trig_keyb_switch) {
 
826
        if (p->trig == inst_opt_trig_user_switch) {
843
827
                int touts = 0;
844
828
 
845
 
                /* Wait for a spot value to turn up, or a user abort/command */
 
829
                /* Wait for a sample value to turn up, or a user abort */
846
830
                for (;;) {
847
 
                        if ((ev = dtp20_command(p, "CS\r", buf, MAX_MES_SIZE, 0.2)) != inst_ok) {
848
 
                                if (ev == (inst_coms_fail | DTP20_TIMEOUT)) {
849
 
                                        if (touts++ > 20)
850
 
                                                return ev;
851
 
                                        continue; 
 
831
 
 
832
                        /* Check for user trigger */
 
833
                        if (p->uicallback != NULL) {
 
834
                                if ((ev = p->uicallback(p->uic_cntx, inst_armed)) != inst_ok) {
 
835
                                        if (ev == inst_user_abort) 
 
836
                                                return ev;                      /* User abort */
 
837
                                        if (ev == inst_user_trig) {
 
838
                                                user_trig = 1;
 
839
                                                break;
 
840
                                        }
852
841
                                }
 
842
                        }
 
843
 
 
844
                        /* Check for an instrument switch trigger */
 
845
                        ev = dtp20_command(p, "CS\r", buf, MAX_MES_SIZE, 0.2);
 
846
 
 
847
                        if (ev == (inst_coms_fail | DTP20_TIMEOUT)) {   /* Assume we're waiting for trigger */
 
848
                                if (touts++ > 20)
 
849
                                        return ev;
 
850
                                continue; 
 
851
                        
 
852
                        } else if (ev != inst_ok) {
853
853
                                if ((ev & inst_mask) == inst_needs_cal)
854
854
                                        p->need_cal = 1;
855
 
                                if ((ev & inst_mask) != inst_user_trig)
856
 
                                        return ev;
857
 
                                user_trig = 1;
858
 
                        } else {
 
855
                                return ev;                              /* Error */
 
856
 
 
857
                        } else {        /* Got a CS response */
859
858
                                int stat;
860
859
                                if (sscanf(buf, " %d ", &stat) != 1)
861
860
                                        stat = 6;
865
864
                                        continue;
866
865
                                }
867
866
                                switch_trig = 1;
868
 
                        }
869
 
                        break;
870
 
                }
871
 
                if (p->trig_return)
872
 
                        printf("\n");
873
 
 
874
 
        } else if (p->trig == inst_opt_trig_keyb) {
875
 
                if ((se = icoms_poll_user(p->icom, 1)) != ICOM_TRIG) {
876
 
                        /* Abort, term or command */
877
 
                        return dtp20_interp_code((inst *)p, icoms2dtp20_err(se));
878
 
                }
879
 
                user_trig = 1;
880
 
                if (p->trig_return)
881
 
                        printf("\n");
 
867
                                break;
 
868
                        }
 
869
                }
 
870
                /* Notify of trigger */
 
871
                if (p->uicallback)
 
872
                        p->uicallback(p->uic_cntx, inst_triggered); 
 
873
 
 
874
        } else if (p->trig == inst_opt_trig_user) {
 
875
                if (p->uicallback == NULL) {
 
876
                        a1logd(p->log, 1, "dtp20: inst_opt_trig_user but no uicallback function set!\n");
 
877
                        return inst_unsupported;
 
878
                }
 
879
 
 
880
                for (;;) {
 
881
                        if ((ev = p->uicallback(p->uic_cntx, inst_armed)) != inst_ok) {
 
882
                                if (ev == inst_user_abort)
 
883
                                        return ev;                              /* Abort */
 
884
                                if (ev == inst_user_trig) {
 
885
                                        user_trig = 1;
 
886
                                        break;                                  /* Trigger */
 
887
                                }
 
888
                        }
 
889
                        msec_sleep(200);
 
890
                }
 
891
                /* Notify of trigger */
 
892
                if (p->uicallback)
 
893
                        p->uicallback(p->uic_cntx, inst_triggered); 
 
894
 
 
895
        /* Progromatic Trigger */
 
896
        } else {
 
897
                /* Check for abort */
 
898
                if (p->uicallback != NULL
 
899
                 && (ev = p->uicallback(p->uic_cntx, inst_armed)) == inst_user_abort)
 
900
                        return ev;                              /* Abort */
882
901
        }
883
902
 
884
903
        /* Read saved spot values */
885
 
        if ((p->mode & inst_mode_measurement_mask) == inst_mode_s_ref_spot) {
 
904
        if (IMODETST(p->mode, inst_mode_s_ref_spot)) {
886
905
                char cmd[10];
887
906
                int nsr;
888
907
 
941
960
        if (sscanf(buf, " %lf %lf %lf ", &val->XYZ[0], &val->XYZ[1], &val->XYZ[2]) != 3) {
942
961
                return inst_protocol_error;
943
962
        }
 
963
        /* This may not change anything since instrument may clamp */
 
964
        if (clamp)
 
965
                icmClamp3(val->XYZ, val->XYZ);
 
966
        val->loc[0] = '\000';
 
967
        val->mtype = inst_mrt_reflective;
944
968
        val->XYZ_v = 1;
945
 
        val->aXYZ_v = 0;
946
 
        val->Lab_v = 0;
947
969
        val->sp.spec_n = 0;
948
970
        val->duration = 0.0;
949
971
 
950
972
        if (p->mode & inst_mode_spectral) {
951
973
                int j;
952
974
 
953
 
                /* Set to read speactral reflectance */
 
975
                /* Set to read spectral reflectance */
954
976
                if ((ev = dtp20_command(p, "0318CF\r", buf, MAX_MES_SIZE, 0.5)) != inst_ok)
955
977
                        return ev;
956
978
                /* Set to binary */
984
1006
                        return ev;
985
1007
        }
986
1008
 
987
 
        if ((p->mode & inst_mode_measurement_mask) != inst_mode_s_ref_spot) {
 
1009
        if (!IMODETST(p->mode, inst_mode_s_ref_spot)) {
988
1010
 
989
1011
                /* Clear the spot database so our reading doesn't appear as a stored reading */
990
1012
                if ((ev = dtp20_command(p, "02CD\r", buf, MAX_MES_SIZE, 1.0)) != inst_ok)
1009
1031
        return inst_ok;
1010
1032
}
1011
1033
 
1012
 
 
1013
 
/* Determine if a calibration is needed. Returns inst_calt_none if not, */
1014
 
/* inst_calt_unknown if it is unknown, or inst_calt_XXX if needs calibration, */
1015
 
/* and the first type of calibration needed. */
1016
 
inst_cal_type dtp20_needs_calibration(inst *pp) {
 
1034
/* Return needed and available inst_cal_type's */
 
1035
static inst_code dtp20_get_n_a_cals(inst *pp, inst_cal_type *pn_cals, inst_cal_type *pa_cals) {
1017
1036
        dtp20 *p = (dtp20 *)pp;
1018
 
        
1019
 
        if (!p->gotcoms)
1020
 
                return inst_no_coms;
1021
 
        if (!p->inited)
1022
 
                return inst_no_init;
1023
 
 
1024
 
        if (p->need_cal) {
1025
 
                return inst_calt_ref_white;
1026
 
        }
1027
 
        return inst_calt_unknown;
 
1037
        inst_cal_type n_cals = inst_calt_none;
 
1038
        inst_cal_type a_cals = inst_calt_none;
 
1039
                
 
1040
        if (p->need_cal)
 
1041
                n_cals |= inst_calt_ref_white;
 
1042
        a_cals |= inst_calt_ref_white;
 
1043
 
 
1044
        if (pn_cals != NULL)
 
1045
                *pn_cals = n_cals;
 
1046
 
 
1047
        if (pa_cals != NULL)
 
1048
                *pa_cals = a_cals;
 
1049
 
 
1050
        return inst_ok;
1028
1051
}
1029
1052
 
1030
1053
/* Request an instrument calibration. */
1036
1059
/* user to do so, each time the error inst_cal_setup is returned. */
1037
1060
inst_code dtp20_calibrate(
1038
1061
inst *pp,
1039
 
inst_cal_type calt,             /* Calibration type. inst_calt_all for all neeeded */
 
1062
inst_cal_type *calt,    /* Calibration type to do/remaining */
1040
1063
inst_cal_cond *calc,    /* Current condition/desired condition */
1041
1064
char id[CALIDLEN]               /* Condition identifier (ie. white reference ID) */
1042
1065
) {
1043
1066
        dtp20 *p = (dtp20 *)pp;
1044
 
        inst_code ev = inst_ok;
1045
1067
        char buf[MAX_MES_SIZE];
 
1068
        inst_code ev;
 
1069
    inst_cal_type needed, available;
 
1070
 
 
1071
        if (!p->gotcoms)
 
1072
                return inst_no_coms;
 
1073
        if (!p->inited)
 
1074
                return inst_no_init;
 
1075
 
1046
1076
        id[0] = '\000';
1047
1077
 
1048
 
        if (!p->gotcoms)
1049
 
                return inst_no_coms;
1050
 
        if (!p->inited)
1051
 
                return inst_no_init;
1052
 
 
1053
 
        if (calt == inst_calt_all)
1054
 
                calt = inst_calt_ref_white;
1055
 
 
1056
 
        if (calt != inst_calt_ref_white) {
 
1078
        if ((ev = dtp20_get_n_a_cals((inst *)p, &needed, &available)) != inst_ok)
 
1079
                return ev;
 
1080
 
 
1081
        /* Translate inst_calt_all/needed into something specific */
 
1082
        if (*calt == inst_calt_all
 
1083
         || *calt == inst_calt_needed
 
1084
         || *calt == inst_calt_available) {
 
1085
                if (*calt == inst_calt_all) 
 
1086
                        *calt = (needed & inst_calt_n_dfrble_mask) | inst_calt_ap_flag;
 
1087
                else if (*calt == inst_calt_needed)
 
1088
                        *calt = needed & inst_calt_n_dfrble_mask;
 
1089
                else if (*calt == inst_calt_available)
 
1090
                        *calt = available & inst_calt_n_dfrble_mask;
 
1091
 
 
1092
                a1logd(p->log,4,"dtp20_calibrate: doing calt 0x%x\n",calt);
 
1093
 
 
1094
                if ((*calt & inst_calt_n_dfrble_mask) == 0)             /* Nothing todo */
 
1095
                        return inst_ok;
 
1096
        }
 
1097
 
 
1098
        /* See if it's a calibration we understand */
 
1099
        if (*calt & ~available & inst_calt_all_mask) { 
1057
1100
                return inst_unsupported;
1058
1101
        }
1059
1102
 
1060
 
        if (*calc == inst_calc_man_ref_white) {
 
1103
        if (*calt & inst_calt_ref_white) {
 
1104
 
 
1105
                if (*calc != inst_calc_man_ref_white) {
 
1106
                        char *cp;
 
1107
                        if ((ev = dtp20_command(p, "04SN\r", buf, MAX_MES_SIZE, 4.5)) != inst_ok)
 
1108
                                return ev;
 
1109
                        for (cp = buf; *cp >= '0' && *cp <= '9'; cp++)
 
1110
                                ;
 
1111
                        *cp = '\000';
 
1112
                        strcpy(id, buf);
 
1113
                        *calc = inst_calc_man_ref_white;
 
1114
                        return inst_cal_setup;
 
1115
                }
 
1116
 
1061
1117
                if ((ev = dtp20_command(p, "CR\r", buf, MAX_MES_SIZE, 4.5)) != inst_ok)
1062
1118
                        return ev;
1063
1119
                
1064
1120
                p->need_cal = 0;
1065
 
                return inst_ok; /* Calibration done */
1066
 
 
1067
 
        } else {
1068
 
                char *cp;
1069
 
                if ((ev = dtp20_command(p, "04SN\r", buf, MAX_MES_SIZE, 4.5)) != inst_ok)
1070
 
                        return ev;
1071
 
                for (cp = buf; *cp >= '0' && *cp <= '9'; cp++)
1072
 
                        ;
1073
 
                *cp = '\000';
1074
 
                strcpy(id, buf);
1075
 
                *calc = inst_calc_man_ref_white;        /* Need to ask user to do calibration */
1076
 
                return inst_cal_setup;
 
1121
                *calt &= ~inst_calt_ref_white;
1077
1122
        }
1078
 
        return inst_unsupported;
 
1123
 
 
1124
        return inst_ok;
1079
1125
}
1080
1126
 
1081
1127
/* Error codes interpretation */
1093
1139
                        return "Not a DTP20";
1094
1140
                case DTP20_DATA_PARSE_ERROR:
1095
1141
                        return "Data from DTP didn't parse as expected";
1096
 
                case DTP20_USER_ABORT:
1097
 
                        return "User hit Abort key";
1098
 
                case DTP20_USER_TERM:
1099
 
                        return "User hit Terminate key";
1100
 
                case DTP20_USER_TRIG:
1101
 
                        return "User hit Trigger key";
1102
 
                case DTP20_USER_CMND:
1103
 
                        return "User hit a Command key";
1104
1142
 
1105
1143
                case DTP20_NOT_EMPTY:
1106
1144
                        return "Trying to read strips when there is already\n"
1122
1160
                        return "One or more parameters are out of range";
1123
1161
                case DTP20_BUSY:
1124
1162
                        return "Instrument is busy - command ignored";
1125
 
                case DTP20_USER_ABORT_ERROR:
1126
 
                        return "User aborted process";
1127
1163
                        
1128
1164
                case DTP20_MEASUREMENT_ERROR:
1129
1165
                        return "General measurement error";
1262
1298
                case DTP20_BAD_PARAMETERS:
1263
1299
                case DTP20_PRM_RANGE_ERROR:
1264
1300
                case DTP20_BUSY:
1265
 
                case DTP20_USER_ABORT_ERROR:
1266
1301
                        return inst_protocol_error | ec;
1267
1302
 
1268
 
                case DTP20_USER_ABORT:
1269
 
                        return inst_user_abort | ec;
1270
 
                case DTP20_USER_TERM:
1271
 
                        return inst_user_term | ec;
1272
 
                case DTP20_USER_TRIG:
1273
 
                        return inst_user_trig | ec;
1274
 
                case DTP20_USER_CMND:
1275
 
                        return inst_user_cmnd | ec;
1276
 
 
1277
1303
                case DTP20_MEASUREMENT_ERROR:
1278
1304
                case DTP20_BAD_STRIP:
1279
1305
                case DTP20_BAD_SPOT:
1327
1353
                case DTP20_STRIP_DEFINE_TOO_LONG:
1328
1354
                case DTP20_BAD_STRIP_DEFINE:
1329
1355
                case DTP20_BOOTLOADER_MODE:
1330
 
                        return inst_wrong_config | ec;
 
1356
                        return inst_wrong_setup | ec;
1331
1357
        }
1332
1358
        return inst_other_error | ec;
1333
1359
}
1344
1370
/* Set the instrument capabilities */
1345
1371
static void     set_capabilities(dtp20 *p) {
1346
1372
 
1347
 
        p->cap = inst_ref_spot
1348
 
               | inst_ref_strip
1349
 
               | inst_s_ref_spot
1350
 
               | inst_s_ref_chart
1351
 
               | inst_colorimeter
1352
 
               | inst_spectral
 
1373
        p->cap = inst_mode_ref_spot
 
1374
               | inst_mode_ref_strip
 
1375
               | inst_mode_s_ref_spot
 
1376
               | inst_mode_s_ref_chart
 
1377
               | inst_mode_colorimeter
 
1378
               | inst_mode_spectral
1353
1379
               ;
1354
1380
 
1355
 
        p->cap2 = inst2_cal_ref_white
1356
 
                | inst2_prog_trig
1357
 
                    | inst2_keyb_switch_trig
1358
 
                | inst2_keyb_trig
 
1381
        p->cap2 = inst2_prog_trig
 
1382
                    | inst2_user_switch_trig
 
1383
                | inst2_user_trig
1359
1384
                | inst2_has_battery
1360
1385
                ;
 
1386
 
 
1387
        p->cap3 = inst3_none;
1361
1388
}
1362
1389
 
1363
1390
 
1364
1391
/* Return the instrument capabilities */
1365
 
inst_capability dtp20_capabilities(inst *pp) {
 
1392
void dtp20_capabilities(inst *pp,
 
1393
inst_mode *cap1,
 
1394
inst2_capability *cap2,
 
1395
inst3_capability *cap3) {
1366
1396
        dtp20 *p = (dtp20 *)pp;
1367
1397
 
1368
 
        if (p->cap == inst_unknown)
 
1398
        if (p->cap == inst_mode_none)
1369
1399
                set_capabilities(p);
1370
 
        return p->cap;
 
1400
 
 
1401
        if (cap1 != NULL)
 
1402
                *cap1 = p->cap;
 
1403
        if (cap2 != NULL)
 
1404
                *cap2 = p->cap2;
 
1405
        if (cap3 != NULL)
 
1406
                *cap3 = p->cap3;
1371
1407
}
1372
1408
 
1373
 
/* Return the instrument capabilities 2 */
1374
 
inst2_capability dtp20_capabilities2(inst *pp) {
 
1409
/* 
 
1410
 * check measurement mode
 
1411
 */
 
1412
static inst_code
 
1413
dtp20_check_mode(inst *pp, inst_mode m) {
1375
1414
        dtp20 *p = (dtp20 *)pp;
1376
 
 
1377
 
        if (p->cap2 == inst2_unknown)
1378
 
                set_capabilities(p);
1379
 
        return p->cap2;
 
1415
        inst_mode cap;
 
1416
 
 
1417
        if (!p->gotcoms)
 
1418
                return inst_no_coms;
 
1419
        if (!p->inited)
 
1420
                return inst_no_init;
 
1421
 
 
1422
        pp->capabilities(pp, &cap, NULL, NULL);
 
1423
 
 
1424
        /* Simple test */
 
1425
        if (m & ~cap)
 
1426
                return inst_unsupported;
 
1427
 
 
1428
        /* Check specific modes */
 
1429
        if (!IMODETST(m, inst_mode_ref_spot)
 
1430
         && !IMODETST(m, inst_mode_ref_strip)
 
1431
         && !IMODETST(m, inst_mode_s_ref_spot)
 
1432
         && !IMODETST(m, inst_mode_s_ref_chart)) {
 
1433
                return inst_unsupported;
 
1434
        }
 
1435
 
 
1436
        return inst_ok;
1380
1437
}
1381
1438
 
1382
1439
/* 
1383
1440
 * set measurement mode
1384
1441
 */
1385
1442
static inst_code
1386
 
dtp20_set_mode(inst *pp, inst_mode m)
1387
 
{
 
1443
dtp20_set_mode(inst *pp, inst_mode m) {
1388
1444
        dtp20 *p = (dtp20 *)pp;
1389
 
        inst_capability  cap  = pp->capabilities(pp);
1390
 
        inst_mode mm;           /* Measurement mode */
1391
 
 
1392
 
        if (!p->gotcoms)
1393
 
                return inst_no_coms;
1394
 
        if (!p->inited)
1395
 
                return inst_no_init;
1396
 
 
1397
 
        /* The measurement mode portion of the mode */
1398
 
        mm = m & inst_mode_measurement_mask;
1399
 
 
1400
 
        /* General check mode against specific capabilities logic: */
1401
 
        if (mm != inst_mode_ref_spot
1402
 
         && mm != inst_mode_ref_strip
1403
 
         && mm != inst_mode_s_ref_spot
1404
 
         && mm != inst_mode_s_ref_chart) {
1405
 
                return inst_unsupported;
1406
 
        }
1407
 
 
1408
 
        if (m & inst_mode_colorimeter)
1409
 
                if (!(cap & inst_colorimeter))
1410
 
                        return inst_unsupported;
1411
 
                
1412
 
        if (m & inst_mode_spectral)
1413
 
                if (!(cap & inst_spectral))
1414
 
                        return inst_unsupported;
 
1445
        inst_code ev;
 
1446
 
 
1447
        if ((ev = dtp20_check_mode(pp, m)) != inst_ok)
 
1448
                return ev;
1415
1449
 
1416
1450
        p->mode = m;
1417
1451
 
1418
1452
        return inst_ok;
1419
1453
}
1420
1454
 
1421
 
/* 
1422
 
 * set or reset an optional mode
1423
 
 */
1424
 
static inst_code
1425
 
dtp20_set_opt_mode(inst *pp, inst_opt_mode m, ...)
1426
 
{
 
1455
/* Get a status or get or set an option */
 
1456
static inst_code dtp20_get_set_opt(
 
1457
inst *pp,
 
1458
inst_opt_type m,        /* Requested status type */
 
1459
...) {                          /* Status parameters */                             
1427
1460
        dtp20 *p = (dtp20 *)pp;
1428
1461
 
1429
 
        if (!p->gotcoms)
1430
 
                return inst_no_coms;
1431
 
        if (!p->inited)
1432
 
                return inst_no_init;
1433
 
 
1434
1462
        /* Record the trigger mode */
1435
1463
        if (m == inst_opt_trig_prog
1436
 
         || m == inst_opt_trig_keyb
1437
 
         || m == inst_opt_trig_keyb_switch) {
 
1464
         || m == inst_opt_trig_user
 
1465
         || m == inst_opt_trig_user_switch) {
1438
1466
                p->trig = m;
1439
1467
 
1440
1468
                return inst_ok;
1441
1469
        }
1442
1470
 
1443
 
        if (m == inst_opt_trig_return) {
1444
 
                p->trig_return = 1;
1445
 
                return inst_ok;
1446
 
        } else if (m == inst_opt_trig_no_return) {
1447
 
                p->trig_return = 0;
1448
 
                return inst_ok;
1449
 
        }
1450
 
 
1451
 
        return inst_unsupported;
1452
 
}
1453
 
 
1454
 
/* Get a dynamic status */
1455
 
static inst_code dtp20_get_status(
1456
 
inst *pp,
1457
 
inst_status_type m,     /* Requested status type */
1458
 
...) {                          /* Status parameters */                             
1459
 
        dtp20 *p = (dtp20 *)pp;
1460
 
 
1461
1471
        if (!p->gotcoms)
1462
1472
                return inst_no_coms;
1463
1473
        if (!p->inited)
1639
1649
        /* !! It's not clear if there is a way of knowing */
1640
1650
        /* whether the instrument has a UV filter. */
1641
1651
 
1642
 
        return inst_unsupported;
 
1652
        /* Use default implementation of other inst_opt_type's */
 
1653
        {
 
1654
                inst_code rv;
 
1655
                va_list args;
 
1656
 
 
1657
                va_start(args, m);
 
1658
                rv = inst_get_set_opt_def(pp, m, args);
 
1659
                va_end(args);
 
1660
 
 
1661
                return rv;
 
1662
        }
1643
1663
}
1644
1664
 
1645
1665
/* Constructor */
1646
 
extern dtp20 *new_dtp20(icoms *icom, instType itype, int debug, int verb)
1647
 
{
 
1666
extern dtp20 *new_dtp20(icoms *icom, instType itype) {
1648
1667
        dtp20 *p;
1649
 
        if ((p = (dtp20 *)calloc(sizeof(dtp20),1)) == NULL)
1650
 
                error("dtp20: malloc failed!");
1651
 
 
1652
 
        if (icom == NULL)
1653
 
                p->icom = new_icoms();
1654
 
        else
1655
 
                p->icom = icom;
1656
 
 
1657
 
        p->debug = debug;
1658
 
        p->verb = verb;
1659
 
 
1660
 
        p->init_coms     = dtp20_init_coms;
1661
 
        p->init_inst     = dtp20_init_inst;
1662
 
        p->capabilities  = dtp20_capabilities;
1663
 
        p->capabilities2 = dtp20_capabilities2;
1664
 
        p->set_mode      = dtp20_set_mode;
1665
 
        p->set_opt_mode  = dtp20_set_opt_mode;
1666
 
        p->get_status    = dtp20_get_status;
1667
 
        p->read_chart    = dtp20_read_chart;
1668
 
        p->read_strip    = dtp20_read_strip;
1669
 
        p->read_sample   = dtp20_read_sample;
1670
 
        p->needs_calibration = dtp20_needs_calibration;
1671
 
        p->calibrate     = dtp20_calibrate;
1672
 
        p->interp_error  = dtp20_interp_error;
1673
 
        p->del           = dtp20_del;
1674
 
 
1675
 
        p->itype = itype;
1676
 
        p->cap = inst_unknown;                          /* Unknown until set */
1677
 
        p->mode = inst_mode_unknown;            /* Not in a known mode yet */
 
1668
        if ((p = (dtp20 *)calloc(sizeof(dtp20),1)) == NULL) {
 
1669
                a1loge(icom->log, 1, "new_dtp20: malloc failed!\n");
 
1670
                return NULL;
 
1671
        }
 
1672
 
 
1673
        p->log = new_a1log_d(icom->log);
 
1674
 
 
1675
        p->init_coms       = dtp20_init_coms;
 
1676
        p->init_inst       = dtp20_init_inst;
 
1677
        p->capabilities    = dtp20_capabilities;
 
1678
        p->check_mode      = dtp20_check_mode;
 
1679
        p->set_mode        = dtp20_set_mode;
 
1680
        p->get_set_opt     = dtp20_get_set_opt;
 
1681
        p->read_chart      = dtp20_read_chart;
 
1682
        p->read_strip      = dtp20_read_strip;
 
1683
        p->read_sample     = dtp20_read_sample;
 
1684
        p->get_n_a_cals    = dtp20_get_n_a_cals;
 
1685
        p->calibrate       = dtp20_calibrate;
 
1686
        p->interp_error    = dtp20_interp_error;
 
1687
        p->del             = dtp20_del;
 
1688
 
 
1689
        p->icom = icom;
 
1690
        p->itype = icom->itype;
 
1691
        p->cap = inst_mode_none;                /* Unknown until set */
 
1692
        p->mode = inst_mode_none;               /* Not in a known mode yet */
1678
1693
 
1679
1694
        return p;
1680
1695
}