209
197
/* Set config, interface, write end point, read end point, read quanta */
210
198
if (itype == instDTP94)
211
p->icom->set_usb_port(p->icom, port, 1, 0x02, 0x81, icomuf_none, 0, NULL);
199
se = p->icom->set_usb_port(p->icom, 1, 0x02, 0x81, icomuf_none, 0, NULL);
213
p->icom->set_usb_port(p->icom, port, 1, 0x01, 0x81, icomuf_none, 0, NULL);
201
se = p->icom->set_usb_port(p->icom, 1, 0x01, 0x81, icomuf_none, 0, NULL);
204
a1logd(p->log, 1, "dtp92_init_coms: set_usb_port failed ICOM err 0x%x\n",se);
205
return dtp92_interp_code((inst *)p, icoms2dtp92_err(se));
215
208
/* Blind reset it twice - it seems to sometimes hang up */
216
209
/* otherwise under OSX */
217
210
dtp92_command(p, "0PR\r", buf, MAX_MES_SIZE, 0.5);
218
211
dtp92_command(p, "0PR\r", buf, MAX_MES_SIZE, 0.5);
212
#else /* !ENABLE_USB */
213
a1logd(p->log, 1, "dtp20: Failed to find USB connection to instrument\n");
214
return inst_coms_fail;
215
#endif /* !ENABLE_USB */
222
if (p->debug) fprintf(stderr,"dtp92: About to init Serial I/O\n");
220
a1logd(p->log, 2, "dtp92_init_coms: About to init Serial I/O\n");
224
222
/* Deal with flow control setting */
255
253
while (msec_time() < etime) {
257
if (p->debug) fprintf(stderr,"dtp92: Trying different baud rates (%u ticks to go)\n",etime - msec_time());
255
a1logd(p->log, 4, "dtp92_init_coms: Trying different baud rates (%u msec to go)\n",
256
etime - msec_time());
259
258
/* Until we time out, find the correct baud rate */
260
259
for (i = ci; msec_time() < etime;) {
261
p->icom->set_ser_port(p->icom, port, fc_none, brt[i], parity_none,
260
if ((se = p->icom->set_ser_port(p->icom, fc_none, brt[i], parity_none,
261
stop_1, length_8)) != ICOM_OK) {
262
a1logd(p->log, 1, "dtp92_init_coms: set_ser_port failed ICOM err 0x%x\n",se);
263
return dtp92_interp_code((inst *)p, icoms2dtp92_err(se));
263
266
if (((ev = dtp92_command(p, "\r", buf, MAX_MES_SIZE, 0.5)) & inst_mask)
265
268
break; /* We've got coms or user abort */
270
/* Check for user abort */
271
if (p->uicallback != NULL) {
273
if ((ev = p->uicallback(p->uic_cntx, inst_negcoms)) == inst_user_abort) {
274
a1logd(p->log, 1, "dtp92_init_coms: user aborted\n");
275
return inst_user_abort;
271
if ((ev & inst_mask) == inst_user_abort)
274
282
break; /* Got coms */
285
293
/* Change the baud rate to the rate we've been told */
286
if ((rv = p->icom->write_read(p->icom, brc[bi], buf, MAX_MES_SIZE, '>', 1, .2)) != 0) {
294
if ((se = p->icom->write_read(p->icom, brc[bi], buf, MAX_MES_SIZE, '>', 1, .2)) != 0) {
287
295
if (extract_ec(buf) != DTP92_OK)
288
296
return inst_coms_fail;
291
299
/* Configure our baud rate and handshaking as well */
292
p->icom->set_ser_port(p->icom, port, fc, brt[bi], parity_none, stop_1, length_8);
300
if ((se = p->icom->set_ser_port(p->icom, fc, brt[bi], parity_none,
301
stop_1, length_8)) != ICOM_OK) {
302
a1logd(p->log, 1, "dtp92_init_coms: set_ser_port failed ICOM err 0x%x\n",se);
303
return dtp92_interp_code((inst *)p, icoms2dtp92_err(se));
294
306
/* Loose a character (not sure why) */
295
307
p->icom->write_read(p->icom, "\r", buf, MAX_MES_SIZE, '>', 1, 0.1);
308
#else /* !ENABLE_SERIAL */
309
a1logd(p->log, 1, "dtp20: Failed to find serial connection to instrument\n");
310
return inst_coms_fail;
311
#endif /* !ENABLE_SERIAL */
298
314
/* Check instrument is responding, and reset it again. */
299
315
if ((ev = dtp92_command(p, "\r", buf, MAX_MES_SIZE, 0.2)) != inst_ok
300
316
|| (ev = dtp92_command(p, "0PR\r", buf, MAX_MES_SIZE, 2.0)) != inst_ok) {
302
if (p->debug) fprintf(stderr,"dtp92: init coms has failed\n");
318
a1logd(p->log, 1, "dtp92_init_coms: failed with ICOM 0x%x\n",ev);
304
320
#ifdef NEVER /* Experimental code for fixing 0x1B "Offset Drift invalid" error */
305
321
if ((ev & inst_mask) == inst_hardware_fail) {
648
730
/* returning inst_needs_cal. Initially use an inst_cal_cond of inst_calc_none, */
649
731
/* and then be prepared to setup the right conditions, or ask the */
650
732
/* user to do so, each time the error inst_cal_setup is returned. */
651
inst_code dtp92_calibrate(
733
static inst_code dtp92_calibrate(
653
inst_cal_type calt, /* Calibration type. inst_calt_all for all neeeded */
735
inst_cal_type *calt, /* Calibration type to do/remaining */
654
736
inst_cal_cond *calc, /* Current condition/desired condition */
655
737
char id[CALIDLEN] /* Condition identifier (ie. white reference ID) */
657
739
dtp92 *p = (dtp92 *)pp;
658
740
char buf[MAX_RD_SIZE];
659
inst_code rv = inst_ok;
741
inst_code ev = inst_ok;
742
inst_cal_type needed, available;
667
/* Default to most likely calibration type */
668
if (calt == inst_calt_all) {
669
if (p->need_offset_cal)
670
calt = inst_calt_disp_offset;
672
else if (p->need_ratio_cal)
673
calt = inst_calt_disp_ratio;
676
calt = inst_calt_disp_offset;
751
if ((ev = dtp92_get_n_a_cals((inst *)p, &needed, &available)) != inst_ok)
754
/* Translate inst_calt_all/needed into something specific */
755
if (*calt == inst_calt_all
756
|| *calt == inst_calt_needed
757
|| *calt == inst_calt_available) {
758
if (*calt == inst_calt_all)
759
*calt = (needed & inst_calt_n_dfrble_mask) | inst_calt_ap_flag;
760
else if (*calt == inst_calt_needed)
761
*calt = needed & inst_calt_n_dfrble_mask;
762
else if (*calt == inst_calt_available)
763
*calt = available & inst_calt_n_dfrble_mask;
765
a1logd(p->log,4,"dtp92_calibrate: doing calt 0x%x\n",calt);
767
if ((*calt & inst_calt_n_dfrble_mask) == 0) /* Nothing todo */
679
771
/* See if it's a calibration we understand */
680
if (calt != inst_calt_disp_offset
681
&& calt != inst_calt_disp_ratio)
772
if (*calt & ~available & inst_calt_all_mask) {
682
773
return inst_unsupported;
684
/* Make sure the conditions are right for the calbration */
685
if (calt == inst_calt_disp_offset) {
776
if (*calt & inst_calt_emis_offset) { /* Dark offset calibration */
686
778
if (*calc != inst_calc_man_em_dark) {
687
779
*calc = inst_calc_man_em_dark;
688
780
return inst_cal_setup;
690
} else if (calt == inst_calt_disp_ratio) {
691
if (*calc != inst_calc_disp_grey
692
&& *calc != inst_calc_disp_grey_darker
693
&& *calc != inst_calc_disp_grey_ligher) {
694
*calc = inst_calc_disp_grey;
695
return inst_cal_setup;
699
/* Now that setup is right, perform calibration */
701
if (calt == inst_calt_disp_offset) { /* Dark offset calibration */
703
783
/* Do offset calibration */
704
if ((rv = dtp92_command(p, "CO\r", buf, MAX_RD_SIZE, 12)) != inst_ok)
709
} else if (calt == inst_calt_disp_ratio) { /* Cell ratio calibration */
784
if ((ev = dtp92_command(p, "CO\r", buf, MAX_RD_SIZE, 12)) != inst_ok)
787
*calt &= inst_calt_emis_offset;
790
if (*calt & inst_calt_emis_ratio) { /* Cell ratio calibration */
792
if (*calc != inst_calc_emis_grey
793
&& *calc != inst_calc_emis_grey_darker
794
&& *calc != inst_calc_emis_grey_ligher) {
795
*calc = inst_calc_emis_grey;
796
return inst_cal_setup;
711
799
/* Do ratio calibration */
712
if ((rv = dtp92_command(p, "CR\r", buf, MAX_RD_SIZE, 25.0)) != inst_ok) {
800
if ((ev = dtp92_command(p, "CR\r", buf, MAX_RD_SIZE, 25.0)) != inst_ok) {
714
if ((rv & inst_imask) == DTP92_TOO_MUCH_LIGHT) {
715
*calc = inst_calc_disp_grey_darker;
802
if ((ev & inst_imask) == DTP92_TOO_MUCH_LIGHT) {
803
*calc = inst_calc_emis_grey_darker;
716
804
return inst_cal_setup;
717
} else if ((rv & inst_imask) == DTP92_NOT_ENOUGH_LIGHT) {
718
*calc = inst_calc_disp_grey_ligher;
805
} else if ((ev & inst_imask) == DTP92_NOT_ENOUGH_LIGHT) {
806
*calc = inst_calc_emis_grey_ligher;
719
807
return inst_cal_setup;
721
return rv; /* Error */
809
return ev; /* Error */
811
*calt &= inst_calt_emis_ratio;
817
/* Return the last reading refresh rate in Hz. */
818
static inst_code dtp92_get_refr_rate(inst *pp,
821
dtp92 *p = (dtp92 *)pp;
822
char buf[MAX_RD_SIZE];
823
char buf2[MAX_RD_SIZE];
824
double refrate = 0.0;
832
/* Get the last readings refresh rate */
833
rv = dtp92_command(p, "10103RM\r", buf, MAX_RD_SIZE, 5.0);
836
if ((rv & inst_imask) == DTP92_NO_DATA_AVAILABLE)
841
if (sscanf(buf, "Hz %lf ", &refrate) != 1) {
842
a1logd(p->log, 1, "dtp92_read_refresh rate: failed to parse string '%s'\n",buf);
846
if (refrate == 0.0) {
853
/* Set the calibrated refresh rate in Hz. */
854
/* Set refresh rate to 0.0 to mark it as invalid */
855
/* Rates outside the range 5.0 to 150.0 Hz will return an error */
856
static inst_code dtp92_set_refr_rate(inst *pp,
859
dtp92 *p = (dtp92 *)pp;
861
/* The DTP92 can't have a refresh rate set */
862
return inst_unsupported;
728
865
/* Error codes interpretation */
868
988
dtp92 *p = (dtp92 *)pp;
869
989
if (p->icom != NULL)
870
990
p->icom->del(p->icom);
991
inst_del_disptype_list(p->dtlist, p->ndtlist);
874
/* Return the instrument capabilities */
875
inst_capability dtp92_capabilities(inst *pp) {
995
/* Return the instrument mode capabilities */
996
void dtp92_capabilities(inst *pp,
998
inst2_capability *pcap2,
999
inst3_capability *pcap3) {
876
1000
dtp92 *p = (dtp92 *)pp;
1002
inst2_capability cap2 = 0;
1004
cap1 |= inst_mode_emis_spot
1005
| inst_mode_colorimeter
1008
cap2 |= inst2_prog_trig
1011
; /* The '92 does have a switch, but we're not currently supporting it */
885
1013
if (p->itype == instDTP94) {
886
rv |= inst_emis_disptype;
887
rv |= inst_emis_disptypem;
893
/* Return the instrument capabilities 2 */
894
inst2_capability dtp92_capabilities2(inst *pp) {
895
dtp92 *p = (dtp92 *)pp;
898
rv = inst2_cal_disp_offset
901
; /* The '92 does have a switch, but we're not currently supporting it */
903
if (p->itype == instDTP92)
904
rv |= inst2_cal_disp_ratio;
1014
cap2 |= inst2_disptype;
1016
cap2 |= inst2_refresh_rate;
1017
cap2 |= inst2_emis_refr_meas;
1025
*pcap3 = inst3_none;
1028
/* Check device measurement mode */
1029
inst_code dtp92_check_mode(inst *pp, inst_mode m) {
1033
return inst_no_coms;
1035
return inst_no_init;
1037
pp->capabilities(pp, &cap, NULL, NULL);
1041
return inst_unsupported;
1043
/* Only display emission mode supported */
1044
if (!IMODETST(m, inst_mode_emis_spot)) {
1045
return inst_unsupported;
1051
/* Set device measurement mode */
1052
inst_code dtp92_set_mode(inst *pp, inst_mode m) {
1055
if ((ev = dtp92_check_mode(pp, m)) != inst_ok)
909
1061
inst_disptypesel dtp92_disptypesel[2] = {
913
"DTP92: CRT display [Default]",
1063
inst_dtflags_default, /* flags */
1066
"CRT display", /* desc */
924
inst_disptypesel dtp94_disptypesel[3] = {
1080
inst_disptypesel dtp94_disptypesel[4] = {
1082
inst_dtflags_default,
928
"DTP94: CRT display",
934
"DTP94: LCD display",
1090
inst_dtflags_none, /* flags */
1093
"CRT display", /* desc */
1102
0, /* Might be auto refresh detect ? */
1115
static void set_base_disptype_list(dtp92 *p) {
1116
if (p->itype == instDTP94) {
1117
p->_dtlist = dtp94_disptypesel;
1119
p->_dtlist = dtp92_disptypesel;
945
1123
/* Get mode and option details */
946
static inst_code dtp92_get_opt_details(
1124
static inst_code dtp92_get_disptypesel(
948
inst_optdet_type m, /* Requested option detail type */
949
...) { /* Status parameters */
1126
int *pnsels, /* Return number of display types */
1127
inst_disptypesel **psels, /* Return the array of display types */
1128
int allconfig, /* nz to return list for all configs, not just current. */
1129
int recreate /* nz to re-check for new ccmx & ccss files */
950
1131
dtp92 *p = (dtp92 *)pp;
952
if (m == inst_optdet_disptypesel) {
955
inst_disptypesel **psels;
958
pnsels = va_arg(args, int *);
959
psels = va_arg(args, inst_disptypesel **);
962
if (p->itype == instDTP94) {
964
*psels = dtp94_disptypesel;
1132
inst_code rv = inst_ok;
1134
/* Create/Re-create a current list of abailable display types */
1135
if (p->dtlist == NULL || recreate) {
1136
if ((rv = inst_creat_disptype_list(pp, &p->ndtlist, &p->dtlist,
1137
p->_dtlist, 0 /* doccss*/, 1 /* doccmx */)) != inst_ok)
1142
*pnsels = p->ndtlist;
1150
/* Given a display type entry, setup for that type */
1151
static inst_code set_disp_type(dtp92 *p, inst_disptypesel *dentry) {
1153
p->icx = dentry->ix;
1154
p->cbid = dentry->cbid;
1155
p->refrmode = dentry->refr;
1157
if (p->itype == instDTP92) {
1159
return inst_unsupported;
1161
} else { /* DTP94 */
1162
static char buf[MAX_MES_SIZE];
1165
if (p->icx == 0) { /* Generic/Non-specific */
1166
if ((ev = dtp92_command(p, "0016CF\r", buf, MAX_MES_SIZE, 0.2)) != inst_ok)
1168
} else if (p->icx == 1) { /* CRT */
1169
if ((ev = dtp92_command(p, "0116CF\r", buf, MAX_MES_SIZE, 0.2)) != inst_ok)
1171
} else if (p->icx == 2) { /* LCD */
1172
if ((ev = dtp92_command(p, "0216CF\r", buf, MAX_MES_SIZE, 0.2)) != inst_ok)
967
*psels = dtp92_disptypesel;
1175
return inst_unsupported;
973
return inst_unsupported;
976
/* Set device measurement mode */
977
inst_code dtp92_set_mode(inst *pp, inst_mode m)
979
inst_mode mm; /* Measurement mode */
1179
if (dentry->flags & inst_dtflags_ccmx) {
1180
icmCpy3x3(p->ccmat, dentry->mat);
1182
icmSetUnity3x3(p->ccmat);
1188
/* Setup the default display type */
1189
static inst_code set_default_disp_type(dtp92 *p) {
1193
if (p->dtlist == NULL) {
1194
if ((ev = inst_creat_disptype_list((inst *)p, &p->ndtlist, &p->dtlist,
1195
p->_dtlist, 0 /* doccss*/, 1 /* doccmx */)) != inst_ok)
1199
for (i = 0; !(p->dtlist[i].flags & inst_dtflags_end); i++) {
1200
if (p->dtlist[i].flags & inst_dtflags_default)
1203
if (p->dtlist[i].flags & inst_dtflags_end) {
1204
a1loge(p->log, 1, "set_default_disp_type: failed to find type!\n");
1205
return inst_internal_error;
1207
if ((ev = set_disp_type(p, &p->dtlist[i])) != inst_ok) {
1214
/* Set the display type */
1215
static inst_code dtp92_set_disptype(inst *pp, int ix) {
1216
dtp92 *p = (dtp92 *)pp;
1218
inst_disptypesel *dentry;
982
1221
return inst_no_coms;
984
1223
return inst_no_init;
986
/* The measurement mode portion of the mode */
987
mm = m & inst_mode_measurement_mask;
989
/* only display emission mode supported */
990
if (mm != inst_mode_emis_disp
991
&& mm != inst_mode_emis_spot) {
992
return inst_unsupported;
995
/* Spectral mode is not supported */
996
if (m & inst_mode_spectral)
997
return inst_unsupported;
1225
if (p->dtlist == NULL) {
1226
if ((ev = inst_creat_disptype_list(pp, &p->ndtlist, &p->dtlist,
1227
p->_dtlist, 0 /* doccss*/, 1 /* doccmx */)) != inst_ok)
1231
if (ix < 0 || ix >= p->ndtlist)
1232
return inst_unsupported;
1234
dentry = &p->dtlist[ix];
1236
if ((ev = set_disp_type(p, dentry)) != inst_ok) {
1003
1244
* set or reset an optional mode
1004
* We assume that the instrument has been initialised.
1246
* Some options talk to the instrument, and these will
1247
* error if it hasn't been initialised.
1006
1249
static inst_code
1007
dtp92_set_opt_mode(inst *pp, inst_opt_mode m, ...)
1250
dtp92_get_set_opt(inst *pp, inst_opt_type m, ...)
1009
1252
dtp92 *p = (dtp92 *)pp;
1010
1253
char buf[MAX_MES_SIZE];
1011
1254
inst_code ev = inst_ok;
1014
return inst_no_coms;
1016
return inst_no_init;
1018
/* Set the display type */
1019
if (m == inst_opt_disp_type) {
1024
ix = va_arg(args, int);
1027
if (ix == 0 && p->itype == instDTP92)
1031
if (p->itype == instDTP94) {
1032
if ((ev = dtp92_command(p, "0116CF\r", buf, MAX_MES_SIZE, 0.2)) != inst_ok)
1036
} else if (ix == 2) {
1037
if (p->itype == instDTP92)
1038
return inst_unsupported;
1039
if ((ev = dtp92_command(p, "0216CF\r", buf, MAX_MES_SIZE, 0.2)) != inst_ok)
1043
return inst_unsupported;
1047
1256
/* Record the trigger mode */
1048
1257
if (m == inst_opt_trig_prog
1049
|| m == inst_opt_trig_keyb) {
1258
|| m == inst_opt_trig_user) {
1051
1260
return inst_ok;
1053
if (m == inst_opt_trig_return) {
1056
} else if (m == inst_opt_trig_no_return) {
1264
return inst_no_coms;
1266
return inst_no_init;
1268
/* Get the display type information */
1269
if (m == inst_opt_get_dtinfo) {
1271
int *refrmode, *cbid;
1274
refrmode = va_arg(args, int *);
1275
cbid = va_arg(args, int *);
1278
if (refrmode != NULL)
1279
*refrmode = p->refrmode;
1058
1283
return inst_ok;
1064
1289
/* Constructor */
1065
extern dtp92 *new_dtp92(icoms *icom, instType itype, int debug, int verb)
1290
extern dtp92 *new_dtp92(icoms *icom, instType itype) {
1068
if ((p = (dtp92 *)calloc(sizeof(dtp92),1)) == NULL)
1069
error("dtp92: malloc failed!");
1072
p->icom = new_icoms();
1079
icmSetUnity3x3(p->ccmat); /* Set the colorimeter correction matrix to do nothing */
1292
if ((p = (dtp92 *)calloc(sizeof(dtp92),1)) == NULL) {
1293
a1loge(icom->log, 1, "new_dtp92: malloc failed!\n");
1297
p->log = new_a1log_d(icom->log);
1081
1299
p->init_coms = dtp92_init_coms;
1082
1300
p->init_inst = dtp92_init_inst;
1083
1301
p->capabilities = dtp92_capabilities;
1084
p->capabilities2 = dtp92_capabilities2;
1085
p->get_opt_details = dtp92_get_opt_details;
1302
p->check_mode = dtp92_check_mode;
1086
1303
p->set_mode = dtp92_set_mode;
1087
p->set_opt_mode = dtp92_set_opt_mode;
1304
p->get_disptypesel = dtp92_get_disptypesel;
1305
p->set_disptype = dtp92_set_disptype;
1306
p->get_set_opt = dtp92_get_set_opt;
1088
1307
p->read_sample = dtp92_read_sample;
1089
p->needs_calibration = dtp92_needs_calibration;
1308
p->read_refrate = dtp92_read_refrate;
1309
p->get_n_a_cals = dtp92_get_n_a_cals;
1090
1310
p->calibrate = dtp92_calibrate;
1091
1311
p->col_cor_mat = dtp92_col_cor_mat;
1312
p->get_refr_rate = dtp92_get_refr_rate;
1313
p->set_refr_rate = dtp92_set_refr_rate;
1092
1314
p->interp_error = dtp92_interp_error;
1093
1315
p->del = dtp92_del;
1318
p->itype = icom->itype;
1320
icmSetUnity3x3(p->ccmat); /* Set the colorimeter correction matrix to do nothing */
1321
set_base_disptype_list(p);