128
118
if ((se = p->icom->write_read(p->icom, in, out, bsize, tc, ntc, to)) != 0) {
130
printf("dtp41 fcommand: serial i/o failure on write_read '%s'\n",icoms_fix(in));
119
a1logd(p->log, 1, "dtp41_fcommand: serial i/o failure 0x%x on write_read '%s'\n",se,icoms_fix(in));
132
120
return icoms2dtp41_err(se);
146
printf("command '%s'",icoms_fix(in));
147
printf(" returned '%s', value 0x%x\n",icoms_fix(out),rv);
133
a1logd(p->log, 4, "dtp41_fcommand: command '%s' returned '%s', value 0x%x\n",
134
icoms_fix(in), icoms_fix(out),rv);
161
147
/* Use the baud rate given, and timeout in to secs */
162
148
/* Return DTP_COMS_FAIL on failure to establish communications */
164
dtp41_init_coms(inst *pp, int port, baud_rate br, flow_control fc, double tout) {
150
dtp41_init_coms(inst *pp, baud_rate br, flow_control fc, double tout) {
165
151
dtp41 *p = (dtp41 *)pp;
166
152
static char buf[MAX_MES_SIZE];
167
153
baud_rate brt[9] = { baud_9600, baud_19200, baud_38400, baud_57600,
170
156
"4800BR\r", "2400BR\r", "1200BR\r", "600BR\r", "300BR\r" };
172
158
unsigned int etime;
174
160
inst_code ev = inst_ok;
177
p->icom->debug = p->debug; /* Turn on debugging */
162
a1logd(p->log, 2, "dtp41_init_coms: About to init Serial I/O\n");
179
164
/* Deal with flow control setting */
212
197
/* Until we time out, find the correct baud rate */
213
198
for (i = ci; msec_time() < etime;) {
214
p->icom->set_ser_port(p->icom, port, fc_none, brt[i], parity_none, stop_1, length_8);
199
if ((se = p->icom->set_ser_port(p->icom, fc_none, brt[i], parity_none,
200
stop_1, length_8)) != ICOM_OK) {
201
a1logd(p->log, 1, "dtp41_init_coms: set_ser_port failed ICOM err 0x%x\n",se);
202
return dtp41_interp_code((inst *)p, icoms2dtp41_err(se));
215
204
if (((ev = dtp41_command(p, "\r", buf, MAX_MES_SIZE, 0.5)) & inst_mask)
217
break; /* We've got coms or user abort */
206
break; /* We've got coms */
208
/* Check for user abort */
209
if (p->uicallback != NULL) {
211
if ((ev = p->uicallback(p->uic_cntx, inst_negcoms)) == inst_user_abort) {
212
a1logd(p->log, 1, "dtp41_init_coms: user aborted\n");
213
return inst_user_abort;
222
if ((ev & inst_mask) == inst_user_abort)
225
219
break; /* Got coms */
236
230
/* Set the handshaking (cope with coms breakdown) */
237
if ((rv = p->icom->write_read(p->icom, fcc, buf, MAX_MES_SIZE, '>', 1, 1.5)) != 0) {
231
if ((se = p->icom->write_read(p->icom, fcc, buf, MAX_MES_SIZE, '>', 1, 1.5)) != 0) {
238
232
if (extract_ec(buf) != DTP41_OK)
239
233
return inst_coms_fail;
242
236
/* Change the baud rate to the rate we've been told (cope with coms breakdown) */
243
if ((rv = p->icom->write_read(p->icom, brc[bi], buf, MAX_MES_SIZE, '>', 1, 1.5)) != 0) {
237
if ((se = p->icom->write_read(p->icom, brc[bi], buf, MAX_MES_SIZE, '>', 1, 1.5)) != 0) {
244
238
if (extract_ec(buf) != DTP41_OK)
245
239
return inst_coms_fail;
248
242
/* Configure our baud rate and handshaking as well */
249
p->icom->set_ser_port(p->icom, port, fc, brt[bi], parity_none, stop_1, length_8);
243
if ((se = p->icom->set_ser_port(p->icom, fc, brt[bi], parity_none, stop_1, length_8))
245
a1logd(p->log, 1, "dtp41_init_coms: set_ser_port failed ICOM err 0x%x\n",se);
246
return dtp41_interp_code((inst *)p, icoms2dtp41_err(se));
251
249
/* Loose a character (not sure why) */
252
250
p->icom->write_read(p->icom, "\r", buf, MAX_MES_SIZE, '>', 1, 0.5);
254
252
/* Check instrument is responding */
255
if ((ev = dtp41_command(p, "\r", buf, MAX_MES_SIZE, 1.5)) != inst_ok)
253
if ((ev = dtp41_command(p, "\r", buf, MAX_MES_SIZE, 1.5)) != inst_ok) {
254
a1logd(p->log, 1, "dtp41_init_coms: instrument failed to respond\n");
256
255
return inst_coms_fail;
259
printf("Got communications\n");
258
a1logd(p->log, 2, "dtp41_init_coms: init coms has suceeded\n");
299
298
if ((p->mode & inst_mode_illum_mask) == inst_mode_transmission) {
302
error ("build_strip given trailer length > 9999 mm");
300
if (twid >= 9999.5) {
301
a1logw(p->log, "DTP41 build_strip given trailer length %f > 9999 mm\n",twid);
303
304
/* Trailer length in mm, dddd */
304
305
sprintf(tp, "%04.0f",twid);
407
410
/* Enable the read microswitch */
408
411
if ((ev = dtp41_command(p, "01PB\r", buf, MAX_MES_SIZE, 1.5)) != inst_ok)
410
p->trig = inst_opt_trig_keyb_switch;
413
p->trig = inst_opt_trig_user_switch;
412
415
/* Set dynamic measurement mode */
413
416
if ((ev = dtp41_command(p, "0113CF\r", buf, MAX_MES_SIZE, 1.5)) != inst_ok)
438
441
if ((ev = dtp41_command(p, tbuf, buf, MAX_MES_SIZE, 1.5)) != inst_ok)
442
445
/* See what the transmission mode is up to */
443
446
dtp41_command(p, "DEVELOPERPW\r", buf, MAX_MES_SIZE, 1.5);
444
447
dtp41_command(p, "0119CF\r", buf, MAX_MES_SIZE, 1.5);
449
452
/* We are configured in this mode now */
450
453
p->mode = inst_mode_ref_strip;
452
if (p->lastmode != p->mode)
453
return activate_mode(p);
455
if (p->lastmode != p->mode) {
456
if ((ev = activate_mode(p)) != inst_ok)
462
a1logd(p->log, 2, "dtp41_init_inst: instrument inited OK\n");
494
500
if ((ev = dtp41_command(p, tbuf, buf, MAX_MES_SIZE, 1.5)) != inst_ok)
497
if (p->trig == inst_opt_trig_keyb_switch) {
499
/* Wait for the Read status, or a user abort/command - allow 5 minuits */
500
if ((ev = dtp41_command(p, "", buf, MAX_MES_SIZE, 5 * 60.0)) != inst_ok) {
501
if ((ev & inst_mask) == inst_needs_cal)
503
if ((ev & inst_mask) != inst_user_trig)
512
} else if (p->trig == inst_opt_trig_keyb) {
513
if ((se = icoms_poll_user(p->icom, 1)) != ICOM_TRIG) {
514
/* Abort, term or command */
515
return dtp41_interp_code((inst *)p, icoms2dtp41_err(se));
503
if (p->trig == inst_opt_trig_user_switch) {
505
/* Wait for the Read status, or a user trigger/abort */
507
if ((ev = dtp41_command(p, "", buf, MAX_MES_SIZE, 0.5)) != inst_ok) {
508
if ((ev & inst_mask) == inst_needs_cal)
511
if ((ev & inst_imask) != DTP41_TIMEOUT)
512
return ev; /* Instrument or comms error */
515
if (p->uicallback != NULL) { /* Check for user trigger */
516
if ((ev = p->uicallback(p->uic_cntx, inst_armed)) != inst_ok) {
517
if (ev == inst_user_abort)
518
return ev; /* User abort */
519
if (ev == inst_user_trig) {
526
} else { /* Got read status - assume triggered */
528
break; /* Switch activated */
531
/* Notify of trigger */
533
p->uicallback(p->uic_cntx, inst_triggered);
535
} else if (p->trig == inst_opt_trig_user) {
537
if (p->uicallback == NULL) {
538
a1logd(p->log, 1, "dtp41: inst_opt_trig_user but no uicallback function set!\n");
539
return inst_unsupported;
543
if ((ev = p->uicallback(p->uic_cntx, inst_armed)) != inst_ok) {
544
if (ev == inst_user_abort)
545
return ev; /* Abort */
546
if (ev == inst_user_trig) {
553
/* Notify of trigger */
555
p->uicallback(p->uic_cntx, inst_triggered);
557
/* Progromatic Trigger */
559
/* Check for abort */
560
if (p->uicallback != NULL
561
&& (ev = p->uicallback(p->uic_cntx, inst_armed)) == inst_user_abort)
562
return ev; /* Abort */
522
565
/* Trigger a read if the switch has not been used */
626
673
if ((ev = dtp41_command(p, "0013CF\r", buf, MAX_MES_SIZE, 1.5)) != inst_ok)
629
if (p->trig == inst_opt_trig_keyb_switch) {
631
/* Wait for the Read status, or a user abort/command - allow 5 minuits */
632
if ((ev = dtp41_command(p, "", buf, MAX_MES_SIZE, 5 * 60.0)) != inst_ok) {
633
if ((ev & inst_mask) == inst_needs_cal)
635
if ((ev & inst_mask) != inst_user_trig)
644
} else if (p->trig == inst_opt_trig_keyb) {
645
if ((se = icoms_poll_user(p->icom, 1)) != ICOM_TRIG) {
646
/* Abort, term or command */
647
return dtp41_interp_code((inst *)p, icoms2dtp41_err(se));
676
if (p->trig == inst_opt_trig_user_switch) {
678
/* Wait for the Read status, or a user trigger/abort */
680
if ((ev = dtp41_command(p, "", buf, MAX_MES_SIZE, 0.5)) != inst_ok) {
681
if ((ev & inst_mask) == inst_needs_cal)
684
if ((ev & inst_imask) != DTP41_TIMEOUT)
685
return ev; /* Instrument or comms error */
688
if (p->uicallback != NULL) { /* Check for user trigger */
689
if ((ev = p->uicallback(p->uic_cntx, inst_armed)) != inst_ok) {
690
if (ev == inst_user_abort)
691
return ev; /* User abort */
692
if (ev == inst_user_trig) {
694
break; /* User trigger */
699
} else { /* Assume read status and trigger */
701
break; /* Switch activated */
704
/* Notify of trigger */
706
p->uicallback(p->uic_cntx, inst_triggered);
708
} else if (p->trig == inst_opt_trig_user) {
710
if (p->uicallback == NULL) {
711
a1logd(p->log, 1, "dtp41: inst_opt_trig_user but no uicallback function set!\n");
712
return inst_unsupported;
716
if ((ev = p->uicallback(p->uic_cntx, inst_armed)) != inst_ok) {
717
if (ev == inst_user_abort)
718
return ev; /* Abort */
719
if (ev == inst_user_trig) {
726
/* Notify of trigger */
728
p->uicallback(p->uic_cntx, inst_triggered);
730
/* Progromatic Trigger */
732
/* Check for abort */
733
if (p->uicallback != NULL
734
&& (ev = p->uicallback(p->uic_cntx, inst_armed)) == inst_user_abort)
735
return ev; /* Abort */
654
738
/* Trigger a read if the switch has not been used */
694
778
val->XYZ[0] /= (double)p->nstaticr;
695
779
val->XYZ[1] /= (double)p->nstaticr;
696
780
val->XYZ[2] /= (double)p->nstaticr;
781
/* This may not change anything since instrument may clamp */
783
icmClamp3(val->XYZ, val->XYZ);
784
val->loc[0] = '\000';
785
if ((p->mode & inst_mode_illum_mask) == inst_mode_transmission)
786
val->mtype = inst_mrt_transmissive;
788
val->mtype = inst_mrt_reflective;
700
790
val->sp.spec_n = 0;
701
791
val->duration = 0.0;
759
/* Determine if a calibration is needed. Returns inst_calt_none if not, */
760
/* inst_calt_unknown if it is unknown, or inst_calt_XXX if needs calibration, */
761
/* and the first type of calibration needed. */
762
/* Can't know ahead of time with the DTP41, but we track if an error */
763
/* was returned from a read. */
764
inst_cal_type dtp41_needs_calibration(inst *pp) {
848
/* Return needed and available inst_cal_type's */
849
static inst_code dtp41_get_n_a_cals(inst *pp, inst_cal_type *pn_cals, inst_cal_type *pa_cals) {
765
850
dtp41 *p = (dtp41 *)pp;
773
if ((p->mode & inst_mode_illum_mask) == inst_mode_transmission)
774
return inst_calt_trans_white; /* ??? */
776
return inst_calt_ref_white;
851
inst_cal_type n_cals = inst_calt_none;
852
inst_cal_type a_cals = inst_calt_none;
854
if ((p->mode & inst_mode_illum_mask) == inst_mode_transmission) {
856
n_cals |= inst_calt_trans_white; /* ??? */
857
a_cals |= inst_calt_trans_white;
860
n_cals |= inst_calt_ref_white;
861
a_cals |= inst_calt_ref_white;
778
return inst_calt_unknown;
781
873
/* Request an instrument calibration. */
787
879
/* user to do so, each time the error inst_cal_setup is returned. */
788
880
inst_code dtp41_calibrate(
790
inst_cal_type calt, /* Calibration type. inst_calt_all for all neeeded */
882
inst_cal_type *calt, /* Calibration type to do/remaining */
791
883
inst_cal_cond *calc, /* Current condition/desired condition */
792
884
char id[CALIDLEN] /* Condition identifier (ie. white reference ID) */
794
886
dtp41 *p = (dtp41 *)pp;
888
inst_cal_type needed, available;
797
891
return inst_no_coms;
897
if ((ev = dtp41_get_n_a_cals((inst *)p, &needed, &available)) != inst_ok)
900
/* Translate inst_calt_all/needed into something specific */
901
if (*calt == inst_calt_all
902
|| *calt == inst_calt_needed
903
|| *calt == inst_calt_available) {
904
if (*calt == inst_calt_all)
905
*calt = (needed & inst_calt_n_dfrble_mask) | inst_calt_ap_flag;
906
else if (*calt == inst_calt_needed)
907
*calt = needed & inst_calt_n_dfrble_mask;
908
else if (*calt == inst_calt_available)
909
*calt = available & inst_calt_n_dfrble_mask;
911
a1logd(p->log,4,"dtp41_calibrate: doing calt 0x%x\n",calt);
913
if ((*calt & inst_calt_n_dfrble_mask) == 0) /* Nothing todo */
917
/* See if it's a calibration we understand */
918
if (*calt & ~available & inst_calt_all_mask) {
919
return inst_unsupported;
803
923
if ((p->mode & inst_mode_illum_mask) == inst_mode_transmission) {
924
if (*calt & inst_calt_trans_white) {
805
if (calt == inst_calt_all)
806
calt = inst_calt_trans_white;
926
if (*calc != inst_calc_uop_trans_white)
927
*calc = inst_calc_uop_trans_white; /* Ask user to do calibration */
928
return inst_cal_setup;
808
if (calt != inst_calt_trans_white)
809
return inst_unsupported;
811
if (*calc == inst_calc_uop_trans_white) {
813
return inst_ok; /* Calibration done */
932
*calt &= ~inst_calt_trans_white;
816
*calc = inst_calc_uop_trans_white; /* Need to ask user to do calibration */
820
if (calt == inst_calt_all)
821
calt = inst_calt_ref_white;
823
if (calt != inst_calt_ref_white)
824
return inst_unsupported;
826
if (*calc == inst_calc_uop_ref_white) {
935
if (*calt & inst_calt_ref_white) {
937
if (*calc != inst_calc_uop_ref_white) {
938
*calc = inst_calc_uop_ref_white; /* Ask user to do calibration */
939
return inst_cal_setup;
828
return inst_ok; /* Calibration done */
943
*calt &= ~inst_calt_ref_white;
831
*calc = inst_calc_uop_ref_white; /* Need to ask user to do calibration */
834
return inst_cal_setup;
947
return inst_ok; /* Calibration done */
837
950
/* Error codes interpretation */
999
1093
static char buf[MAX_MES_SIZE];
1000
1094
inst_code rv = inst_ok;
1002
p->cap = inst_ref_spot
1096
p->cap = inst_mode_ref_spot
1097
| inst_mode_ref_strip
1098
| inst_mode_colorimeter
1099
| inst_mode_spectral
1008
p->cap2 = inst2_cal_ref_white /* User operated though */
1011
| inst2_keyb_switch_trig
1102
p->cap2 = inst2_prog_trig
1104
| inst2_user_switch_trig
1107
p->cap3 = inst3_none;
1014
1109
if (p->inited) {
1015
1110
/* Check whether we have transmission capability */
1016
1111
if ((rv = dtp41_command(p, "0119CF\r", buf, MAX_MES_SIZE, 1.5)) == inst_ok) {
1017
p->cap |= inst_trans_spot
1112
p->cap |= inst_mode_trans_spot
1113
| inst_mode_trans_strip
1021
p->cap2 |= inst2_cal_trans_white; /* User operated though */
1023
1116
/* Set back to reflectance mode */
1024
1117
rv = dtp41_command(p, "0019CF\r", buf, MAX_MES_SIZE, 1.5);
1028
1121
/* Return the instrument capabilities */
1029
inst_capability dtp41_capabilities(inst *pp) {
1030
dtp41 *p = (dtp41 *)pp;
1032
if (p->cap == inst_unknown)
1033
discover_capabilities(p);
1037
/* Return the instrument capabilities 2 */
1038
inst2_capability dtp41_capabilities2(inst *pp) {
1039
dtp41 *p = (dtp41 *)pp;
1040
inst2_capability rv;
1042
if (p->cap2 == inst2_unknown)
1043
discover_capabilities(p);
1122
void dtp41_capabilities(inst *pp,
1124
inst2_capability *pcap2,
1125
inst3_capability *pcap3) {
1126
dtp41 *p = (dtp41 *)pp;
1128
if (p->cap == inst_mode_none)
1129
discover_capabilities(p);
1050
1139
/* Activate the last set mode */
1176
* check measurement mode
1177
* We assume that the instrument has been initialised.
1180
dtp41_check_mode(inst *pp, inst_mode m) {
1181
dtp41 *p = (dtp41 *)pp;
1184
pp->capabilities(pp, &cap, NULL, NULL);
1186
if (m & ~cap) /* Simple elimination test */
1187
return inst_unsupported;
1189
/* Check specific modes */
1190
if (!IMODETST(m, inst_mode_ref_spot)
1191
&& !IMODETST(m, inst_mode_ref_strip)
1192
&& !IMODETST2(cap, m, inst_mode_trans_spot)
1193
&& !IMODETST2(cap, m, inst_mode_trans_strip)) {
1194
return inst_unsupported;
1087
1201
* set measurement mode
1088
1202
* We assume that the instrument has been initialised.
1090
1204
static inst_code
1091
1205
dtp41_set_mode(inst *pp, inst_mode m) {
1092
1206
dtp41 *p = (dtp41 *)pp;
1093
inst_capability cap = pp->capabilities(pp);
1094
inst_mode mm; /* Measurement mode */
1096
/* The measurement mode portion of the mode */
1097
mm = m & inst_mode_measurement_mask;
1099
/* General check mode against specific capabilities logic: */
1100
if (mm == inst_mode_ref_spot) {
1101
if (!(cap & inst_ref_spot))
1102
return inst_unsupported;
1103
} else if (mm == inst_mode_ref_strip) {
1104
if (!(cap & inst_ref_strip))
1105
return inst_unsupported;
1106
} else if (mm == inst_mode_ref_xy) {
1107
if (!(cap & inst_ref_xy))
1108
return inst_unsupported;
1109
} else if (mm == inst_mode_trans_spot) {
1110
if (!(cap & inst_trans_spot))
1111
return inst_unsupported;
1112
} else if (mm == inst_mode_trans_strip) {
1113
if (!(cap & inst_trans_strip))
1114
return inst_unsupported;
1115
} else if (mm == inst_mode_trans_xy) {
1116
if (!(cap & inst_trans_xy))
1117
return inst_unsupported;
1118
} else if (mm == inst_mode_emis_disp) {
1119
if (!(cap & inst_emis_disp))
1120
return inst_unsupported;
1122
return inst_unsupported;
1125
if (m & inst_mode_colorimeter)
1126
if (!(cap & inst_colorimeter))
1127
return inst_unsupported;
1129
if (m & inst_mode_spectral)
1130
if (!(cap & inst_spectral))
1131
return inst_unsupported;
1209
if ((ev = dtp41_check_mode(pp, m)) != inst_ok)
1133
1212
p->lastmode = m;
1135
1213
if (p->lastmode != p->mode) {
1136
1214
return activate_mode(p);
1138
1217
return inst_ok;
1145
1224
* set or reset an optional mode
1146
* We assume that the instrument has been initialised.
1226
* Some options talk to the instrument, and these will
1227
* error if it hasn't been initialised.
1148
1229
static inst_code
1149
dtp41_set_opt_mode(inst *pp, inst_opt_mode m, ...)
1230
dtp41_get_set_opt(inst *pp, inst_opt_type m, ...)
1151
1232
dtp41 *p = (dtp41 *)pp;
1152
1233
inst_code rv = inst_ok;
1157
1238
if (!p->inited)
1158
1239
return inst_no_init;
1160
/* Record the trigger mode */
1241
/* Set the trigger mode */
1161
1242
if (m == inst_opt_trig_prog
1162
|| m == inst_opt_trig_keyb
1163
|| m == inst_opt_trig_keyb_switch) {
1243
|| m == inst_opt_trig_user
1244
|| m == inst_opt_trig_user_switch) {
1166
if (m == inst_opt_trig_keyb_switch) {
1247
if (m == inst_opt_trig_user_switch) {
1167
1248
/* Enable the read microswitch */
1168
1249
if ((rv = dtp41_command(p, "01PB\r", buf, MAX_MES_SIZE, 0.2)) != inst_ok)
1175
1256
return inst_ok;
1178
if (m == inst_opt_trig_return) {
1181
} else if (m == inst_opt_trig_no_return) {
1186
1259
return inst_unsupported;
1189
1262
/* Constructor */
1190
extern dtp41 *new_dtp41(icoms *icom, instType itype, int debug, int verb)
1263
extern dtp41 *new_dtp41(icoms *icom, instType itype) {
1193
if ((p = (dtp41 *)calloc(sizeof(dtp41),1)) == NULL)
1194
error("dtp41: malloc failed!");
1197
p->icom = new_icoms();
1265
if ((p = (dtp41 *)calloc(sizeof(dtp41),1)) == NULL) {
1266
a1loge(icom->log, 1, "new_dtp41: malloc failed!\n");
1270
p->log = new_a1log(icom->log, 0, 0, NULL, NULL, NULL, NULL);
1204
1272
p->init_coms = dtp41_init_coms;
1205
1273
p->init_inst = dtp41_init_inst;
1206
1274
p->capabilities = dtp41_capabilities;
1207
p->capabilities2 = dtp41_capabilities2;
1275
p->check_mode = dtp41_check_mode;
1208
1276
p->set_mode = dtp41_set_mode;
1209
p->set_opt_mode = dtp41_set_opt_mode;
1277
p->get_set_opt = dtp41_get_set_opt;
1210
1278
p->read_strip = dtp41_read_strip;
1211
1279
p->read_sample = dtp41_read_sample;
1212
p->needs_calibration = dtp41_needs_calibration;
1280
p->get_n_a_cals = dtp41_get_n_a_cals;
1213
1281
p->calibrate = dtp41_calibrate;
1214
1282
p->interp_error = dtp41_interp_error;
1215
1283
p->del = dtp41_del;
1218
p->cap = inst_unknown; /* Unknown until set */
1219
p->mode = inst_mode_unknown; /* Not in a known mode yet */
1286
p->itype = icom->itype;
1287
p->cap = inst_mode_none; /* Unknown until set */
1288
p->mode = inst_mode_none; /* Not in a known mode yet */
1220
1289
p->nstaticr = 5; /* Number of static readings */