1 
2 #ifndef INST_H
3 
4 /*
5  * instlib API definition.
6  *
7  * See spotread.c, chartread.c, illumread.c & ccxxmake.c for examples of
8  * the API usage.
9  *
10  * Abstract base class for common color instrument interface
11  * and other common instrument stuff.
12  */
13 
14 /*
15  * Argyll Color Correction System
16  *
17  * Author: Graeme W. Gill
18  * Date:   15/3/2001
19  *
20  * Copyright 2001 - 2013 Graeme W. Gill
21  * All rights reserved.
22  *
23  * This material is licenced under the GNU GENERAL PUBLIC LICENSE Version 2 or later :-
24  * see the License2.txt file for licencing details.
25  *
26  */
27 
28 /*
29    If you make use of the instrument driver code here, please note
30    that it is the author(s) of the code who take responsibility
31    for its operation. Any problems or queries regarding driving
32    instruments with the Argyll drivers, should be directed to
33    the Argyll's author(s), and not to any other party.
34 
35    If there is some instrument feature or function that you
36    would like supported here, it is recommended that you
37    contact Argyll's author(s) first, rather than attempt to
38    modify the software yourself, if you don't have firm knowledge
39    of the instrument communicate protocols. There is a chance
40    that an instrument could be damaged by an incautious command
41    sequence, and the instrument companies generally cannot and
42    will not support developers that they have not qualified
43    and agreed to support.
44  */
45 
46 #include "insttypes.h"		/* libinst Includes this functionality */
47 #include "disptechs.h"		/* libinst Includes this functionality */
48 #include "icoms.h"			/* libinst Includes this functionality */
49 #include "conv.h"
50 
51 #ifdef __cplusplus
52 	extern "C" {
53 #endif
54 
55 /* ------------------------------------------------- */
56 /* aprox. debug level guide:
57 
58 	1,2  Applications, internal errors
59 	2,3  High level instrument drivers
60 	4,5  High level instrument communications
61 	6,7  High level serial/USB communications
62 	8,9  Low level serial/USB communications
63 
64 */
65 
66 /* ------------------------------------------------- */
67 /* Structure for holding an instrument patch reading */
68 
69 #ifdef NEVER	/* Declared in xicc/xspect.h */
70 
71 /* Type of measurement result */
72 typedef enum {						/* XYZ units,      Spectral units */
73 	inst_mrt_none           = 0,	/* Not set */
74 	inst_mrt_emission       = 1,	/* cd/m^2,         mW/(m^2.sr.nm) */
75 	inst_mrt_ambient        = 2,	/* Lux             mW/(m^2.nm) */
76 	inst_mrt_emission_flash = 3,	/* cd.s/m^2,       mW.s/(m^2.sr.nm) */
77 	inst_mrt_ambient_flash  = 4,	/* Lux.s           mW.s/(m^2.nm) */
78 	inst_mrt_reflective     = 5,	/* %,              %/nm */
79 	inst_mrt_transmissive   = 6,	/* %,              %/nm */
80 	inst_mrt_frequency      = 7		/* Hz */
81 } inst_meas_type;
82 
83 #endif // NEVER
84 
85 #define ICOM_MAX_LOC_LEN 10
86 
87 struct _ipatch {
88 	char loc[ICOM_MAX_LOC_LEN];	/* patch location */
89 
90 	inst_meas_type mtype;	/* Measurement type */
91 
92 	int XYZ_v;				/* XYZ valid */
93 	double XYZ[3];			/* XYZ values */
94 
95 	xspect sp;			/* Spectrum. sp.spec_n > 0 if valid */
96 						/* Reflectance/Transmittance 0.0 .. 100.0%, norm = 100.0 */
97 						/* or mW/nm/m^2, norm = 1.0, etc.  */
98 
99 	double duration;	/* Apparent total duration in seconds (flash measurement) */
100 						/* Typicall limited to sampling rate of instrument. */
101 
102 }; typedef struct _ipatch ipatch;
103 
104 /* ------------------------------------------------------ */
105 /* Gretag/X-Rite specific reflective measurement standard */
106 
107 typedef enum {
108 	xcalstd_none = -2,		/* Not set */
109 	xcalstd_native = -1,	/* No conversion */
110 	xcalstd_xrdi = 0,		/* Historical X-Rite */
111 	xcalstd_gmdi = 1,		/* Historical Gretag-Macbeth */
112 	xcalstd_xrga = 2,		/* Current X-Rite */
113 } xcalstd;
114 
115 /* Return a string for the xcalstd enum */
116 char *xcalstd2str(xcalstd std);
117 
118 /* ---------------------------------------- */
119 /* Instrument interface abstract base class */
120 
121 /* Abstract return codes in ms 8bits. */
122 /* Instrument dependant codes in ls 16 bits. */
123 /* Note :- update inst_interp_error() in inst.c if anything here is changed. */
124 /* and also check all the instrument specific XXX_interp_code() routines too. */
125 typedef enum {
126 	inst_ok                = 0x000000,
127 	inst_notify            = 0x010000,	/* A Notification */
128 	inst_warning           = 0x020000,	/* A Warning */
129 	inst_no_coms           = 0x030000,	/* init_coms() hasn't been called yet */
130 	inst_no_init           = 0x040000,	/* init_inst() hasn't been called yet */
131 	inst_unsupported       = 0x050000,	/* Unsupported function */
132 	inst_internal_error    = 0x060000,	/* Internal software error */
133 	inst_coms_fail         = 0x070000,	/* Communication failure */
134 	inst_unknown_model     = 0x080000,	/* Not the expected instrument */
135 	inst_protocol_error    = 0x090000, 	/* Read or Write protocol error */
136 	inst_user_abort        = 0x0A0000,	/* User hit escape */
137 	inst_user_trig         = 0x0C0000,	/* User hit trigger key */
138 	inst_misread           = 0x0E0000,	/* Bad reading, or strip misread */
139 	inst_nonesaved         = 0x0F0000,	/* No saved data to read */
140 	inst_nochmatch         = 0x100000,	/* Chart doesn't match */
141 	inst_needs_cal         = 0x110000,	/* Instrument needs calibration, and read retried */
142 	inst_cal_setup         = 0x120000,	/* Calibration retry with correct setup is needed */
143 	inst_wrong_config      = 0x130000,	/* Retry with correct inst. config./sensor posn. needed */
144 	inst_unexpected_reply  = 0x140000,	/* Unexpected Reply */
145 	inst_wrong_setup       = 0x150000,	/* Setup is wrong or conflicting */
146 	inst_hardware_fail     = 0x160000,	/* Hardware failure */
147 	inst_system_error      = 0x170000,	/* System call (ie malloc) fail */
148 	inst_bad_parameter     = 0x180000,	/* Bad parameter value */
149 	inst_other_error       = 0x190000,	/* Some other error */
150 	inst_mask              = 0xff0000,	/* inst_code mask value */
151 	inst_imask             = 0x00ffff	/* instrument specific mask value */
152 } inst_code;
153 
154 
155 /*
156 	possible UV modes:
157 
158 	Do the reflective measurement with UV rather than normal illuminant
159 	[ Should this be reflectivity against 'A', or absolute ?? ]
160 	(ie. spot, strip, xy or chart). inst_mode_ref_uv
161 
162 	Do a white & UV measurement at the start of each strip reading.
163 	Return result with special call after each strip read.
164 	                                inst_mode_ref_uv_strip_1
165 
166 	Do a dual white & UV measurement
167 	[ Can do in one hit for spot, but how should two strip passes be handled ?
168 	  ie. two separate strip reads of phase 1 & then 2 ? ]
169 	(ie. spot, strip, xy or chart). inst_mode_ref_uv_2pass
170 
171 	Get normal illuminant spectrum.
172 
173 	Get UV spectrum.
174 
175 	                                get_meas_illum_spectrum(mode);
176  */
177 
178 /* Instrument capabilities & modes */
179 /* Note that due to the binary combinations, capabilities is not definititive */
180 /* as to valid modes. check_mode() is definitive. */
181 /* #defines are for saving modes in a version independent way. */
182 /* Note :- update inst_mode_sym[] table in inst.c if anything here is changed. */
183 typedef enum {
184 	inst_mode_none               = 0x00000000, /* No capability or mode */
185 
186 	/* Light measurement mode */
187 	inst_mode_reflection         = 0x00000001,	/* General reflection mode */
188 #   define inst_mode_reflection_sym             "REFL"
189 	inst_mode_s_reflection       = 0x00000002,	/* General saved reflection mode */
190 #   define inst_mode_s_reflection_sym           "SRFL"
191 	inst_mode_transmission       = 0x00000004,	/* General transmission mode */
192 #   define inst_mode_transmission_sym           "TRAN"
193 	inst_mode_emission           = 0x00000008,	/* General emission mode */
194 #   define inst_mode_emission_sym               "EMIS"
195 	inst_mode_illum_mask         = 0x0000000f,	/* Mask of sample illumination sub mode */
196 
197 	/* Action of measurement */
198 	inst_mode_spot               = 0x00000010,	/* General spot measurement mode */
199 #   define inst_mode_spot_sym                   "SPOT"
200 	inst_mode_strip              = 0x00000020,	/* General strip measurement mode */
201 #   define inst_mode_strip_sym                  "STRP"
202 	inst_mode_xy                 = 0x00000040,	/* General X-Y measurement mode */
203 #   define inst_mode_xy_sym                     "CHXY"
204 	inst_mode_chart              = 0x00000080,	/* General chart measurement mode */
205 #   define inst_mode_chart_sym                  "CHRT"
206 	inst_mode_ambient            = 0x00000100,	/* General ambient measurement mode */
207 #   define inst_mode_ambient_sym                "AMBI"
208 	inst_mode_ambient_flash      = 0x00000200,	/* General ambient flash measurement mode */
209 #   define inst_mode_ambient_flash_sym          "ABFL"
210 	inst_mode_tele               = 0x00000400,	/* General telephoto measurement mode */
211 #   define inst_mode_tele_sym                   "TELE"
212 	// Hmm. Should there be a tele_flash mode ????
213 	inst_mode_sub_mask           = 0x000007f0,	/* Mask of sub-mode */
214 
215 	/* Basic mode */
216 	inst_mode_basic_mask         = inst_mode_illum_mask | inst_mode_sub_mask,
217 
218 	/* Extra dependent modes */
219 	inst_mode_emis_nonadaptive   = 0x00000800,	/* Emissom Non-adaptive mode */
220 #   define inst_mode_emis_nonadaptive_sys       "EMNA"
221 	inst_mode_ref_uv             = 0x00001000,	/* Ultra Violet measurement mode */
222 #   define inst_mode_ref_uv_sym                 "REUV"
223 	inst_mode_emis_refresh_ovd   = 0x00002000,	/* Emissom Refresh mode override */
224 #   define inst_mode_emis_refresh_ovd_sym       "EMRO"
225 	inst_mode_emis_norefresh_ovd = 0x00006000,	/* Emissom Non-refresh mode override */
226 #   define inst_mode_emis_norefresh_ovd_sym     "ENRO"
227 	inst_mode_dep_extra_mask     = 0x00007800,	/* Mask of measurement modifiers */
228 
229 	/* Extra independent modes */
230 	inst_mode_colorimeter        = 0x00004000,	/* Colorimetric mode */
231 #   define inst_mode_colorimeter_sym            "COLI"
232 	inst_mode_spectral           = 0x00008000,	/* Spectral mode */
233 #   define inst_mode_spectral_sym               "SPEC"
234 	inst_mode_highres            = 0x00010000,	/* High Resolution Spectral mode */
235 #   define inst_mode_highres_sym                "HIRZ"
236 	inst_mode_extra_mask         = 0x0001c000,	/* Mask of extra modes */
237 
238 	/* Configured for calibration & capable of returning it from inst_mode_calibration */
239 	inst_mode_calibration        = 0x80000000,	/* Configured for calibration */
240 #   define inst_mode_calibration_sym            "CALB"
241 
242 	/* Combined operating modes (from above): */
243 	/* These mode capabilities are also use to set the mode */
244 	/* Test for a mode should be IMODETST(flags, mode) */
245 	inst_mode_ref_spot           = inst_mode_spot	/* Reflection spot measurement mode */
246 	                             | inst_mode_reflection,
247 	inst_mode_ref_strip          = inst_mode_strip	/* Reflection strip measurement mode */
248 	                             | inst_mode_reflection,
249 	inst_mode_ref_xy             = inst_mode_xy		/* Reflection X-Y measurement mode */
250 	                             | inst_mode_reflection,
251 	inst_mode_ref_chart          = inst_mode_chart	/* Reflection Chart measurement mode */
252 	                             | inst_mode_reflection,
253 
254 	inst_mode_s_ref_spot         = inst_mode_spot	/* Saved reflection spot measurement mode */
255 	                             | inst_mode_s_reflection,
256 	inst_mode_s_ref_strip        = inst_mode_strip	/* Saved reflection strip measurement mode */
257 	                             | inst_mode_s_reflection,
258 	inst_mode_s_ref_xy           = inst_mode_xy		/* Saved reflection X-Y measurement mode */
259 	                             | inst_mode_s_reflection,
260 	inst_mode_s_ref_chart        = inst_mode_chart	/* Saved reflection Chart measurement mode */
261 	                             | inst_mode_s_reflection,
262 
263 	inst_mode_trans_spot         = inst_mode_spot	/* Transmission spot measurement mode */
264 	                             | inst_mode_transmission, 	/* Normal Diffuse/90 */
265 	inst_mode_trans_spot_a       = inst_mode_ambient /* Transmission spot measurement mode */
266 	                             | inst_mode_transmission, /* Alternate 90/diffuse */
267 	inst_mode_trans_strip        = inst_mode_strip	/* Transmission strip measurement mode */
268 	                             | inst_mode_transmission,
269 	inst_mode_trans_xy           = inst_mode_xy		/* Transmission X-Y measurement mode */
270 	                             | inst_mode_transmission,
271 	inst_mode_trans_chart        = inst_mode_chart	/* Transmission chart measurement mode */
272 	                             | inst_mode_transmission,
273 
274 	inst_mode_emis_spot          = inst_mode_spot	/* Spot emission measurement mode */
275 	                             | inst_mode_emission,
276 	inst_mode_emis_tele          = inst_mode_tele	/* Telephoto emission measurement mode */
277 	                             | inst_mode_emission,
278 	inst_mode_emis_ambient       = inst_mode_ambient	/* Ambient emission measurement mode */
279 	                             | inst_mode_emission,
280 	inst_mode_emis_ambient_flash = inst_mode_ambient_flash	/* Ambient emission flash measurement */
281 	                             | inst_mode_emission,
282 
283 	inst_mode_emis_strip         = inst_mode_strip	/* Strip emission measurement mode */
284 	                             | inst_mode_emission,
285 
286 	inst_mode_measurement_mask   = inst_mode_illum_mask	/* Mask of exclusive measurement modes */
287 	                             | inst_mode_sub_mask
288 	                             | inst_mode_dep_extra_mask
289 } inst_mode;
290 
291 /* Test for a specific mode */
292 /* (This isn't foolproof - it->check_mode() is better for modes */
293 /*  composed of more than one bit) */
294 #define IMODETST(mbits, mode) (((mbits) & (mode)) == (mode))
295 
296 /* Test for a specific mode in capability and mode */
297 #define IMODETST2(mcap, mbits, mode) (IMODETST(mcap, mode) && IMODETST(mbits, mode))
298 
299 #define MAX_INST_MODE_SYM_SZ (32 * (4 + 1))		/* Each bit sym is 4 chars */
300 
301 /* Return a string with a symbolic encoding of the mode flags */
302 void inst_mode_to_sym(char sym[MAX_INST_MODE_SYM_SZ], inst_mode mode);
303 
304 /* Return a set of mode flags that correspondf to the symbolic encoding */
305 /* Return nz if a symbol wasn't recognized */
306 int sym_to_inst_mode(inst_mode *mode, const char *sym);
307 
308 
309 /* Instrument capabilities 2 */
310 /* (Available capabilities may be mode dependent) */
311 typedef enum {
312 	inst2_none              = 0x00000000, /* No capabilities */
313 
314 	inst2_xy_holdrel        = 0x00000001, /* Needs paper hold/release between each sheet */
315 	inst2_xy_locate         = 0x00000002, /* Needs user to locate patch locations */
316 	inst2_xy_position       = 0x00000004, /* Can be positioned at a given location */
317 
318 	inst2_meas_disp_update  = 0x00000010, /* Is able to measure display update delay */
319 
320 	inst2_get_refresh_rate  = 0x00000020, /* Is able to get the calibrated refresh rate */
321 	inst2_set_refresh_rate  = 0x00000040, /* Is able to set the calibrated refresh rate */
322 
323 	inst2_emis_refr_meas    = 0x00000080, /* Has an emissive refresh rate measurement func. */
324 
325 	inst2_prog_trig         = 0x00000100, /* Progromatic trigger measure capability */
326 	inst2_user_trig         = 0x00000200, /* User trigger measure capability, */
327 										  /* i.e. via user button and uicallback. */
328 	inst2_switch_trig       = 0x00000400, /* Inst. switch trigger measure capability, */
329 										  /* i.e. instrument directly starts measurement */
330 										  /* via mechanical switch. */
331 	inst2_user_switch_trig  = 0x00000800, /* User or switch trigger measure capability */
332 
333 	inst2_bidi_scan         = 0x00001000, /* Try and recognise patches scanned from either dir. */
334 	inst2_cal_using_switch  = 0x00002000, /* DTP22 special - use switch triggered calibration */
335 	inst2_has_scan_toll     = 0x00004000, /* Instrument will honour modified scan tollerance */
336 	inst2_no_feedback       = 0x00008000, /* Instrument doesn't give any user feedback */
337 
338 	inst2_opt_calibs        = 0x00010000, /* Instrument has optional calibrations */
339 
340 	inst2_has_leds          = 0x00200000, /* Instrument has some user viewable indicator LEDs */
341 	inst2_has_target        = 0x00400000, /* Instrument has aiming target */
342 	inst2_has_sensmode      = 0x00800000, /* Instrument can report it's sensors mode */
343 
344 	inst2_has_battery       = 0x01000000, /* Instrument is battery powered */
345 
346 	inst2_disptype          = 0x02000000, /* Has a display/calibration type selector */
347 										  /* (ie. get_disptypesel(), set_disptype */
348 
349 	inst2_ccmx              = 0x04000000, /* Colorimeter Correction Matrix capability */
350 	inst2_ccss              = 0x08000000, /* Colorimeter Cal. Spectral Set capability */
351 
352 	inst2_ambient_mono      = 0x10000000, /* The ambient measurement is monochrome */
353 
354 	inst2_ambient_cardioid  = 0x20000000, /* The ambient measurement has a cardioid response */
355 
356 	inst2_get_min_int_time  = 0x40000000, /* Is able to get the minimum integration time */
357 	inst2_set_min_int_time  = 0x80000000  /* Is able to set the minimum integration time */
358 
359 } inst2_capability;
360 
361 /* Instrument capabilities 3 (room for expansion) */
362 /* (Available capabilities may be mode dependent) */
363 typedef enum {
364 	inst3_none              = 0x00000000, /* No capabilities */
365 
366 } inst3_capability;
367 
368 /* - - - - - - - - - - - - - - - - - - - */
369 
370 /* API ideas for supporting calibration management:
371 
372 	functions to:
373 
374 	 return number of used and free builtin slots, + password required flag.
375 
376 	 write builtin calibration or ccss/ccmx file
377 
378 	 write builtin calibration or ccss/ccmx file
379 
380 	 delete builtin calibration or ccss/ccmx file
381 
382 	Things to be allowed for:
383 
384 		optional password
385 		configuration specific calibrations. How are they marked ?
386 
387 
388 	Also for ccss capable instruments:
389 
390 	 write corresponding ccmx for given ccss.
391 */
392 
393 typedef enum {
394 	inst_dtflags_none    = 0x0000,			/* no flags - assume builtin calibration */
395 	inst_dtflags_mtx     = 0x0001,			/* matrix read from instrument */
396 	inst_dtflags_ccss    = 0x0002,			/* ccss file */
397 	inst_dtflags_ccmx    = 0x0004,			/* ccmx file */
398 	inst_dtflags_custom  = 0x0010,			/* custom (i.e. not built in or OEM) */
399 	inst_dtflags_wr      = 0x0020,			/* Writable slot */
400 	inst_dtflags_ld      = 0x0040,			/* mtx/ccss/ccmx is loaded */
401 	inst_dtflags_default = 0x1000,			/* Default calibration to use */
402 	inst_dtflags_end     = 0x8000			/* end marker */
403 } inst_dtflags;
404 
405 #define INST_DTYPE_SEL_LEN 10
406 #define INST_DTYPE_DESC_LEN 100
407 
408 /* Structure used to return display type selection information. */
409 /* Calibrations may be implicit (based on ix and driver code), or */
410 /* explicit mtx/ccss/ccmx information contained in structure. */
411 typedef struct _inst_disptypesel {
412 
413   /* Public: */
414 	inst_dtflags flags;		/* Attribute flags */
415 	int cbid;				/* Calibration base ID. NZ if valid ccmx calibration base. */
416 							/* Should remain constant between releases */
417 	char sel[INST_DTYPE_SEL_LEN];	/* String of selector character aliases */
418 	char desc[INST_DTYPE_DESC_LEN];	/* Textural description */
419 	int  refr;				/* Refresh mode flag */
420 
421 	disptech dtech;			/* display techology */
422 
423   /* Private: */
424 	int ix;					/* Internal index,  */
425 	char isel[INST_DTYPE_SEL_LEN];	/* String of potential selector characters */
426 
427 	// Stuff for ccss & ccmx
428 	char *path;				/* Path to ccss or ccmx. NULL if not valid */
429 	int cc_cbid;			/* cbid that matrix requires */
430 	double mat[3][3];		/* ccmx matrix */
431 	xspect *sets;   		/* ccss set of sample spectra. NULL if not valid */
432 	int no_sets;    		/* ccs number of sets. 0 if not valid */
433 
434 } inst_disptypesel;
435 
436 /* - - - - - - - - - - - - - - - - - - - */
437 
438 /* Instrument options for get_set_opt() */
439 typedef enum {
440 	inst_opt_unknown            = 0x0000,	/* Option not specified */
441 
442 	inst_stat_saved_readings    = 0x0001,	/* Return status of saved reading values */
443 											/* [1 argument type *inst_stat_savdrd] */
444 	inst_stat_s_spot            = 0x0002,	/* Return number of saved spot readings */
445 											/* [1 argument type *int] */
446 	inst_stat_s_strip           = 0x0003,	/* Return saved strip details */
447 											/* [args: int *no_patches, int *no_rows */
448 	                                        /*        int *pat_per_row] */
449 	inst_stat_s_xy              = 0x0004,	/* Return saved strip details */
450 											/* [args: int *no_sheets, int *no_patches, */
451 	                                        /*        int *no_rows, int *pat_per_row] */
452 	inst_stat_s_chart           = 0x0005,	/* Return number saved chart details */
453 											/* [args: int *no_patches, int *no_rows    */
454 	                                        /*        int *pat_per_row, int *chart_id, */
455 											/*        int *missing_row ]               */
456 
457 	inst_stat_battery           = 0x0006,	/* Return charged status of battery */
458 											/* [1 argument type *double : range 0.0 - 1.0 ] */
459 
460 	inst_stat_get_filter        = 0x0007,	/* Get a filter configuration */
461 											/* [1 argument type *inst_opt_filter ] */
462 
463 	inst_opt_initcalib          = 0x0008,	/* Enable initial calibration (default) [No args] */
464 	inst_opt_noinitcalib        = 0x0009,	/* Disable initial calibration if < losecs since last */											/* opened, or losecs == 0 [int losecs] */
465 
466 	inst_opt_askcalib           = 0x000A,	/* Ask before proceeding with calibration (default) */
467 											/* [ No args] */
468 	inst_opt_noaskcalib         = 0x000B,	/* Proceed with calibration immediately if possible */
469 											/* [ No args] */
470 
471 	inst_opt_set_ccss_obs       = 0x000C,	/* Set the observer used with ccss device types - */
472 											/* Not applicable to any other type of instrument. */
473 											/* [args: icxObserverType obType,*/
474 	                                        /*        xspect custObserver[3] */
475 
476 	inst_opt_set_filter         = 0x000D,	/* Set a filter configuration */
477 											/* [1 argument type inst_opt_filter] */
478 
479 	inst_opt_trig_prog          = 0x000E,	/* Trigger progromatically [No args] */
480 	inst_opt_trig_user          = 0x000F,	/* Trigger from user via uicallback [No args] */
481 	inst_opt_trig_switch        = 0x0010,	/* Trigger directly using instrument switch [No args] */
482 	inst_opt_trig_user_switch   = 0x0011,	/* Trigger from user via uicallback or switch (def) [No args] */
483 
484 	inst_opt_highres            = 0x0012,	/* Enable high res spectral mode indep. of set_mode() */
485 	inst_opt_stdres             = 0x0013,	/* Revert to standard resolution spectral mode */
486 
487 	inst_opt_scan_toll          = 0x0014,	/* Modify the patch scan recognition tollnce [double] */
488 
489 	inst_opt_get_gen_ledmask    = 0x0015,	/* Get the bitmask for general indication LEDs [*int] */
490 											/* (More specialized indicator masks go here) */
491 	inst_opt_set_led_state      = 0x0016,	/* Set the current LED state. 0 = off, 1 == on [int] */
492 	inst_opt_get_led_state      = 0x0017,	/* Get the current LED state. 0 = off, 1 == on [*int] */
493 	inst_opt_get_pulse_ledmask  = 0x0018,	/* Get the bitmask for pulseable ind. LEDs [*int] */
494 	inst_opt_set_led_pulse_state= 0x0019,	/* Set the current LED state. [double period_in_secs, */
495 	                                        /* double on_time_prop, double trans_time_prop] */
496 	inst_opt_get_led_pulse_state= 0x001A,	/* Get the current pulse LED state. [*double period] */
497 	inst_opt_get_target_state   = 0x001B,	/* Get the aiming target state 0 = off, 1 == on [*int] */
498 	inst_opt_set_target_state   = 0x001C,	/* Set the aiming target state 0 = off, 1 == on, 2 = toggle [int] */
499 
500 	inst_opt_get_min_int_time   = 0x001D,	/* Get the minimum integration time [*double time] */
501 	inst_opt_set_min_int_time   = 0x001E,	/* Set the minimum integration time [double time] */
502 
503 	inst_opt_opt_calibs_valid   = 0x001F,	/* Are optional (white/black/gloss etc.) calibrations */
504 	                                        /* valid?                     [*int valid] */
505 	inst_opt_clear_opt_calibs   = 0x0020,	/* Clear all optional calibrations. */
506 
507 	inst_opt_get_cal_tile_sp    = 0x0021,	/* Return refl. white tile reference spectrum. */
508 	                                        /* for current filter.          [*xspect tile] */
509 
510 	inst_opt_set_xcalstd        = 0x0022,	/* Set the X-Rite reflective calibration standard */
511 											/*                             [xcalstd standard] */
512 	inst_opt_get_xcalstd        = 0x0023,	/* Get the effective X-Rite ref. cal. standard */
513 											/*                             [xcalstd *standard] */
514 	inst_opt_lamp_remediate     = 0x0024	/* Remediate i1Pro lamp           [double seconds] */
515 
516 
517 } inst_opt_type;
518 
519 /* Optional filter fitted to instrument (for inst_opt_set_filter) */
520 /* Set this before calling init_coms() */
521 typedef enum {
522 	inst_opt_filter_unknown  = 0xffff,	/* Unspecified filter */
523 	inst_opt_filter_none     = 0x0000,	/* No filters fitted */
524 	inst_opt_filter_pol      = 0x0001,	/* Polarising filter */
525 	inst_opt_filter_D65      = 0x0002,	/* D65 Illuminant filter */
526 	inst_opt_filter_UVCut    = 0x0004,	/* U.V. Cut filter */
527 	inst_opt_filter_Custom   = 0x0008	/* Custom Filter */
528 } inst_opt_filter;
529 
530 /* Off-line pending readings available (status) */
531 typedef enum {
532 	inst_stat_savdrd_none    = 0x00,		/* No saved readings */
533 	inst_stat_savdrd_spot    = 0x01,		/* There are saved spot readings available */
534 	inst_stat_savdrd_strip   = 0x02,		/* There are saved strip readings available */
535 	inst_stat_savdrd_xy      = 0x04,		/* There are saved page readings available */
536 	inst_stat_savdrd_chart   = 0x08			/* There are saved chart readings available */
537 } inst_stat_savdrd;
538 
539 /* Type of calibration needed/available/requested - corresponds to capabilities */
540 /* [ inst_calt_trans_vwhite is "variable" white transmission calibration, needed */
541 /*   where transmission mode is being emulated. ] */
542 /* Remember to update calt2str() */
543 typedef enum {
544 	/* Response to needs_calibration() */
545 	inst_calt_none           = 0x00000000, 	/* No calibration or unknown */
546 
547 	/* Psudo-calibration types */
548 	inst_calt_all            = 0x00000001, 	/* Do required non-deferable cals for mode, but also */
549 										    /* do all possible calibrations for all other modes */
550 										    /* using the calibration conditions. This may be slow */
551 	/* Hmm. We don't have an "calt_all_needed" - do all needed cals of all possible modes. */
552 	/* This might be more useful than inst_calt_all ? */
553 	inst_calt_needed         = 0x00000002, 	/* Do all required non-deferable cals for c.m. */
554 	inst_calt_available      = 0x00000003, 	/* Do all available non-deferable cals for c.m. */
555 
556 	/* Specific type of calibration - corresponds to capabilities  */
557 	inst_calt_wavelength     = 0x00000010, 	/* Wavelength calibration using refl. cal. surface */
558 	inst_calt_ref_white      = 0x00000020, 	/* Reflective white/emissive dark calibration */
559 	inst_calt_ref_dark       = 0x00000040, 	/* Reflective dark calibration (light trap) */
560 	inst_calt_ref_dark_gl    = 0x00000080, 	/* Reflective gloss calibration (black gloss surface) */
561 	inst_calt_emis_offset    = 0x00000100, 	/* Emissive offset/black calibration (dark surface) */
562 	inst_calt_emis_ratio     = 0x00000200, 	/* Emissive ratio calibration */
563 	inst_calt_em_dark        = 0x00000400, 	/* Emissive dark calibration (in dark) */
564 	inst_calt_trans_white    = 0x00000800,	/* Transmissive white reference calibration */
565 	inst_calt_trans_vwhite   = 0x00001000,	/* Transmissive variable white reference calibration */
566 	inst_calt_trans_dark     = 0x00002000,	/* Transmissive dark reference calibration */
567 
568 	inst_calt_n_dfrble_mask  = 0x0000fff0,	/* Mask of non-deferrable calibrations */
569 
570 	/* Calibrations that might be deferred until measurement */
571 	inst_calt_emis_int_time  = 0x00100000, 	/* Emissive measurement range (integration time) */
572 	inst_calt_ref_freq       = 0x00200000, 	/* Display refresh frequency calibration */
573 
574 	inst_calt_dfrble_mask    = 0x00f00000, 	/* Mask of deferrable calibrations */
575 
576 	inst_calt_all_mask       = 0x00f0fff0, 	/* Mask of all specific calibrations */
577 
578 	inst_calt_ap_flag        = 0x80000000	/* Implementation flag indicating do all possible */
579 
580 } inst_cal_type;
581 
582 /* Return a description of the first calibration type */
583 char *calt2str(inst_cal_type calt);
584 
585 /* Calibration conditions. */
586 /* This is how the instrument communicates to the calling program */
587 /* about how to facilitate a calibration, or what it's current measurement */
588 /* configuration provides. */
589 /* [There is no provission for explictly indicating calibrations that can be */
590 /* performed automatically and transparently by the instrument - for instance */
591 /* in the case of the spectroscan, since the required condition can be obtained */
592 /* without the users interaction. ] */
593 typedef enum {
594 	inst_calc_none             = 0x00000000, /* Not suitable for calibration */
595 	inst_calc_unknown          = 0xffffffff, /* Unknown calibration setup */
596 
597 							/* uop means that user has to trigger the within instrument */
598 							/* calibration using its "front panel" or other direct keys */
599 	inst_calc_uop_ref_white    = 0x00000001, /* user operated reflective white calibration */
600 	inst_calc_uop_trans_white  = 0x00000002, /* user operated tranmissive white calibration */
601 	inst_calc_uop_trans_dark   = 0x00000003, /* user operated tranmissive dark calibration */
602 	inst_calc_uop_mask         = 0x0000000F, /* user operated calibration mask */
603 
604 							/* Man means that the user has to manualy configure the instrument */
605 							/* to be on the correct reference for the software triggered cal. */
606 	inst_calc_man_ref_white    = 0x00000010, /* place instrument on reflective white reference */
607 	inst_calc_man_ref_whitek   = 0x00000020, /* click instrument on reflective white reference */
608 	inst_calc_man_ref_dark     = 0x00000030, /* place instrument on light trap */
609 	inst_calc_man_dark_gloss   = 0x00000040, /* place instrument on gloss black reference */
610 	inst_calc_man_em_dark      = 0x00000050, /* place cap on instrument, put on dark surface or white ref. */
611 	inst_calc_man_am_dark      = 0x00000060, /* Place cap over ambient sensor (wl calib capable) */
612 	inst_calc_man_cal_smode    = 0x00000070, /* Put instrument sensor in calibration position */
613 
614 	inst_calc_man_trans_white  = 0x00000080, /* place instrument on transmissive white reference */
615 	inst_calc_man_trans_dark   = 0x00000090, /* place instrument on transmissive dark reference */
616 	inst_calc_man_man_mask     = 0x000000F0, /* user configured calibration mask */
617 
618 	inst_calc_emis_white       = 0x00000100, /* Provide a white test patch */
619 	inst_calc_emis_80pc        = 0x00000200, /* Provide an 80% white test patch */
620 	inst_calc_emis_grey        = 0x00000300, /* Provide a grey test patch */
621 	inst_calc_emis_grey_darker = 0x00000400, /* Provide a darker grey test patch */
622 	inst_calc_emis_grey_ligher = 0x00000500, /* Provide a darker grey test patch */
623 
624 	inst_calc_emis_mask        = 0x00000F00, /* Emmissive/display provided reference patch */
625 
626 	inst_calc_change_filter    = 0x00010000, /* Filter needs changing on device - see id[] */
627 	inst_calc_message          = 0x00020000, /* Issue a message. - see id[] */
628 
629 	inst_calc_cond_mask        = 0x0fffffff, /* Mask for conditions (i.e. remove flags) */
630 
631 	inst_calc_optional_flag    = 0x80000000  /* Flag indicating calibration can be skipped */
632 
633 } inst_cal_cond;
634 
635 /* Condition identifier message type. This can be useful in internationalizing the */
636 /* string returned in id[] from calibrate() */
637 typedef enum {
638 	inst_calc_id_none      = 0x00000000,	/* No id */
639 	inst_calc_id_ref_sn    = 0x00000001,	/* Calibration reference (ie. tile) serial number */
640 
641 	inst_calc_id_trans_low = 0x00010000,	/* Trans. Ref. light is too low for accuracy warning */
642 	inst_calc_id_trans_wl  = 0x00020000,	/* Trans. Ref. light is low at some wavelengths warning */
643 	inst_calc_id_filt_unkn = 0x00100000,	/* Request unknown filter */
644 	inst_calc_id_filt_none = 0x00200000,	/* Request no filter */
645 	inst_calc_id_filt_pol  = 0x00300000,	/* Request polarizing filter */
646 	inst_calc_id_filt_D65  = 0x00400000,	/* Request D65 filter */
647 	inst_calc_id_filt_UV   = 0x00500000,	/* Request UV cut filter */
648 	inst_calc_id_filt_cust = 0x00600000		/* Request custom filter */
649 } inst_calc_id_type;
650 
651 /* Clamping state */
652 typedef enum {
653     instNoClamp			= 0,	/* Don't clamp XYZ/Lab to +ve */
654     instClamp			= 1,	/* Clamp XYZ/Lab to +ve */
655 } instClamping;
656 
657 /* User interaction callback (uicallback()) function purpose */
658 typedef enum {
659     inst_negcoms,		/* Negotiating communications - can abort */
660     inst_armed,			/* Armed and waiting for a measurement trigger - can wait, trigger, abort */
661     inst_triggered,		/* Measurement triggered by switch or user (not progromatic) - notice */
662 						/* (Also triggered by switch driven calibration,i.e. DTP41) */
663     inst_measuring		/* Busy measuring - can abort */
664 } inst_ui_purp;
665 
666 /* Asynchronous event callback type */
667 typedef enum {
668     inst_event_switch,		/* Instrument measure/calibrate switch pressed. */
669     inst_event_mconf,		/* Change in measurement configuration (ie. sensor position) */
670     inst_event_scan_ready	/* Ready for manual strip scan (i.e. issue audible prompt) */
671 } inst_event_type;
672 
673 /* Instrument configuration/sensor position*/
674 typedef enum {
675     inst_conf_unknown,
676     inst_conf_projector,
677     inst_conf_surface,
678     inst_conf_emission,
679 	inst_conf_calibration,
680 	inst_conf_ambient
681 } inst_config;
682 
683 # define EXRA_INST_OBJ
684 
685 /* Off-line pending readings available (status) */
686 #define CALIDLEN 200	/* Maxumum length of calibration tile ID string */
687 
688 /* Color instrument interface base object */
689 /* Note that some methods work after creation, while many */
690 /* will return an error if communications hasn't been established and */
691 /* the instrument initialised. Some may change their response before and */
692 /* after initialisation. */
693 #define INST_OBJ_BASE															\
694 																				\
695 	EXRA_INST_OBJ																\
696 	a1log *log;			/* Pointer to debug & error logging class */			\
697 	instType  itype;	/* Instrument type determined by driver */				\
698 	icoms *icom;		/* Instrument coms object */							\
699 	int gotcoms;		/* Coms established flag */                             \
700 	int inited;			/* Instrument open and initialized flag */              \
701 	double cal_gy_level; /* Display calibration test window state */			\
702 	int cal_gy_count;	/* Display calibration test window state */				\
703 	inst_code (*uicallback)(void *cntx, inst_ui_purp purp);						\
704 	void *uic_cntx;		/* User interaction callback function */				\
705 	void (*eventcallback)(void *cntx, inst_event_type event);					\
706 	void *event_cntx;	/* Asynchronous event callback function */				\
707 	athread *scan_ready_thread;	/* msec_scan_ready() support */					\
708 	int scan_ready_delay;		/* msec_scan_ready() support */					\
709 																				\
710 	/* Virtual delete. Cleans up things done by new_inst(). */					\
711 	inst_code (*vdel)(															\
712         struct _inst *p);														\
713 																				\
714 	/* Establish communications at the indicated baud rate. */					\
715 	/* (Serial parameters are ignored for USB instrument) */					\
716 	/* Timout in to seconds, and return non-zero error code */					\
717 	inst_code (*init_coms)(														\
718         struct _inst *p,														\
719         baud_rate br,		/* Baud rate */										\
720         flow_control fc,	/* Flow control */									\
721         double tout);		/* Timeout */										\
722 																				\
723 	/* Initialise or re-initialise the INST */									\
724 	/* return non-zero on an error, with inst error code */						\
725 	inst_code (*init_inst)(  													\
726         struct _inst *p);														\
727 																				\
728 	/* Return the instrument type */											\
729 	/* (this could concievably change after init_inst()) */						\
730 	/* Can be called before init */												\
731 	instType (*get_itype)(  													\
732         struct _inst *p);														\
733 																				\
734 	/* Return the instrument serial number. */									\
735 	/* (This will be an empty string if there is no serial no) */               \
736 	char *(*get_serial_no)(  													\
737         struct _inst *p);														\
738 																				\
739 	/* Return the avilable instrument modes and capabilities. */				\
740 	/* Can be called before init, but may be different to */					\
741 	/* what's returned after initilisation. */									\
742 	/* Note that these may change with the mode. */								\
743 	/* Arguments may be NULL */													\
744 	void (*capabilities)(struct _inst *p,										\
745 	        inst_mode *cap1,													\
746 	        inst2_capability *cap2,												\
747 	        inst3_capability *cap3);											\
748 																				\
749 	/* Return current or given configuration available measurement modes. */	\
750 	/* Most instruments have only one detectable configuration. */				\
751 	/* If conf_ix == NULL or *conf_ix is an invalid configuration index, */		\
752 	/* then the current configuration modes are returned. */					\
753 	/* Otherwise the given configuration index is returned. */					\
754 	/* The i1d3 has 2, the Munki has 4, one being calibration. */				\
755 	/* *cconds is valid if *mmodes = inst_mode_calibration */					\
756 	inst_code (*meas_config)(struct _inst *p,									\
757 			inst_mode *mmodes,	/* Return all the valid measurement modes */	\
758 								/* for the current configuration */				\
759 			inst_cal_cond *cconds,	/* Return the valid calibration conditions */		\
760 			int *conf_ix);		/* Request mode for given configuration, and */			\
761 	                            /* return the index of the configuration returned */	\
762 																				\
763     /* Check that the particular device measurement mode is valid, */           \
764 	/* since it's not possible to be 100% sure from capabilities */				\
765     inst_code (*check_mode)(													\
766         struct _inst *p,														\
767         inst_mode m);		/* Requested mode */								\
768 																				\
769     /* Set the device measurement mode */                                       \
770 	/* Note that this may change the capabilities. */							\
771     inst_code (*set_mode)(														\
772         struct _inst *p,														\
773         inst_mode m);		/* Requested mode */								\
774 																				\
775 	/* Return array of display type selectors */								\
776 	inst_code (*get_disptypesel)(												\
777         struct _inst *p,														\
778 		int *no_selectors,		/* Return number of display types */			\
779 		inst_disptypesel **sels,/* Return the array of display types */			\
780 		int allconfig,			/* nz to return list for all configs, not just current. */	\
781 		int recreate);			/* nz to re-check for new ccmx & ccss files */	\
782 																				\
783 	/* Set the display type or calibration mode. */								\
784 	/* index is into the inst_disptypesel[] returned */   						\
785 	/* returned by get_disptypesel(). clears col_cor_mat() and */				\
786 	/* col_cal_spec_set(). */													\
787 	inst_code (*set_disptype)(													\
788         struct _inst *p,														\
789 		int index);                                                             \
790 	                                                                            \
791 	/* Get the disptech and other corresponding info for the current */		    \
792 	/* selected display type or calibration mode. Returns disptype_unknown */	\
793 	/* by default. Because refrmode can be overridden, it may not */			\
794 	/* match the refrmode of the dtech. */										\
795 	/* (Pointers may be NULL if not needed) */									\
796 	inst_code (*get_disptechi)(													\
797 		struct _inst *p,														\
798 		disptech *dtech,														\
799 		int *refrmode,															\
800 		int *cbid);																\
801 	                                                                            \
802     /* Get a status or get or set an option */                                  \
803 	/* option state. */															\
804 	/* Some options can be set before init */									\
805 	/* See inst_opt_type typedef for list of mode types */						\
806     inst_code (*get_set_opt)(													\
807         struct _inst *p,														\
808         inst_opt_type m,	/* Requested option mode */							\
809 		...);				/* Option parameters */                             \
810 																				\
811 	/* Read a full test chart composed of multiple sheets */					\
812 	/* DOESN'T use the trigger mode */											\
813 	/* Return the inst error code */											\
814 	inst_code (*read_chart)(													\
815 		struct _inst *p,														\
816 		int npatch,			/* Total patches/values in chart */					\
817 		int pich,			/* Passes (rows) in chart */						\
818 		int sip,			/* Steps in each pass (patches in each row) */		\
819 		int *pis,			/* Passes in each strip (rows in each sheet) */		\
820 		int chid,			/* Chart ID number */								\
821 		ipatch *vals);		/* Pointer to array of values */					\
822 																				\
823 																				\
824 	/* For an xy instrument, release the paper */								\
825 	/* (if cap has inst_xy_holdrel) */											\
826 	/* Return the inst error code */											\
827 	inst_code (*xy_sheet_release)(												\
828 		struct _inst *p);														\
829 																				\
830 	/* For an xy instrument, hold the paper */									\
831 	/* (if cap has inst_xy_holdrel) */											\
832 	/* Return the inst error code */											\
833 	inst_code (*xy_sheet_hold)(													\
834 		struct _inst *p);														\
835 																				\
836 	/* For an xy instrument, allow the user to locate a point */				\
837 	/* (if cap has inst_xy_locate) */											\
838 	/* Return the inst error code */											\
839 	inst_code (*xy_locate_start)(												\
840 		struct _inst *p);														\
841 																				\
842 	/* For an xy instrument, read back the location */							\
843 	/* (if cap has inst_xy_locate) */											\
844 	/* Return the inst error code */											\
845 	inst_code (*xy_get_location)(												\
846 		struct _inst *p,														\
847 		double *x, double *y);													\
848 																				\
849 	/* For an xy instrument, end allowing the user to locate a point */			\
850 	/* (if cap has inst_xy_locate) */											\
851 	/* Return the inst error code */											\
852 	inst_code (*xy_locate_end)(													\
853 		struct _inst *p);														\
854 																				\
855 	/* For an xy instrument, move the measurement point */						\
856 	/* (if cap has inst_xy_position) */											\
857 	/* Return the inst error code */											\
858 	inst_code (*xy_position)(													\
859 		struct _inst *p,														\
860 		int measure,	/* nz for measure point, z for locate point */	        \
861 		double x, double y);													\
862 																				\
863 	/* For an xy instrument, try and clear the table after an abort */			\
864 	/* Return the inst error code */											\
865 	inst_code (*xy_clear)(														\
866 		struct _inst *p);														\
867 																				\
868 	/* Read a sheet full of patches using xy mode */							\
869 	/* DOESN'T use the trigger mode */											\
870 	/* Return the inst error code */											\
871 	inst_code (*read_xy)(														\
872 		struct _inst *p,														\
873 		int pis,			/* Passes in strips (letters in sheet) */			\
874 		int sip,			/* Steps in pass (numbers in sheet) */				\
875 		int npatch,			/* Total patches in strip (skip in last pass) */	\
876 		char *pname,		/* Starting pass name (' A' to 'ZZ') */             \
877 		char *sname,		/* Starting step name (' 1' to '99') */             \
878 		double ox, double oy,	/* Origin of first patch */						\
879 		double ax, double ay,	/* pass increment */							\
880 		double aax, double aay,	/* pass offset for odd patches */				\
881 		double px, double py,	/* step/patch increment */						\
882 		ipatch *vals);		/* Pointer to array of values */					\
883 																				\
884 																				\
885 	/* Read a set of strips (applicable to strip reader) */						\
886 	/* Obeys the trigger mode set, and may return user trigger code, */			\
887 	/* to hint that a user command may be available. */							\
888 	/* Return the inst error code */											\
889 	inst_code (*read_strip)(													\
890 		struct _inst *p,														\
891 		char *name,			/* Strip name (up to 7 chars, for DTP51) */			\
892 		int npatch,			/* Number of patches in each pass */				\
893 		char *pname,		/* Pass name (3 chars, for DTP51) */				\
894 		int sguide,			/* Guide number (for DTP51, decrements by 5) */		\
895 		double pwid,		/* Patch width in mm (For DTP20/DTP41) */			\
896 		double gwid,		/* Gap width in mm  (For DTP20/DTP41) */			\
897 		double twid,		/* Trailer width in mm  (For DTP41T) */				\
898 		ipatch *vals);		/* Pointer to array of values */					\
899 																				\
900 																				\
901 	/* Read a single sample (applicable to spot instruments) */					\
902 	/* Obeys the trigger mode set, and may return user trigger code */			\
903 	/* Values are in XYZ % (0..100) for reflective & transmissive, */			\
904 	/* cd/m^2 for emissive, and Lux for ambient. */								\
905 	/* Spectral will be analogous to the XYZ (see inst_meas_type). */			\
906 	/* By default values may be -ve due to noise (depending on instrument) */	\
907 	/* Return the inst error code */											\
908 	inst_code (*read_sample)(													\
909 		struct _inst *p,														\
910 		char *name,				/* Patch identifier (up to 7 chars) */			\
911 		ipatch *val,			/* Pointer to value to be returned */			\
912 		instClamping clamp);	/* NZ to clamp XYZ to be +ve */					\
913 																				\
914 	/* Measure the emissive refresh rate in Hz. */								\
915 	/* (Available if cap2 & inst2_emis_refr_meas) */ 							\
916 	/* Returns: */																\
917 	/* inst_unsupported - if this instrument doesn't suport this measuremet */	\
918 	/*                    or not in an emissive measurement mode */				\
919 	/* inst_misread     - if no refresh rate could be determined */				\
920 	/* inst_ok          - on returning a valid reading */						\
921 	inst_code (*read_refrate)(											        \
922 		struct _inst *p,														\
923 		double *ref_rate);		/* Return the Hz */								\
924 																				\
925 	/* Determine if a calibration is needed. Returns inst_calt_none if not */	\
926 	/* or unknown, or a mask of the needed calibrations. */						\
927 	/* This call checks if calibrations are invalid or have timed out. */		\
928 	/* With the exception of instruments with automated calibration */			\
929 	/* (ie. SpectroScan), an instrument will typically */						\
930 	/* not check for calibration timout any other way. */						\
931 	/* [What's returned is the same as get_n_a_cals() [ needed_calibrations.] */\
932 	inst_cal_type (*needs_calibration)(											\
933 		struct _inst *p);														\
934 																				\
935 	/* Return combined mask of needed and available inst_cal_type's */			\
936 	/* for the current mode. */													\
937 	inst_code (*get_n_a_cals)(													\
938 		struct _inst *p,														\
939 		inst_cal_type *needed_calibrations,										\
940 		inst_cal_type *available_calibrations);									\
941 																				\
942 	/* Request an instrument calibration. */									\
943 	/* This is use if the user decides they want to do a calibration */			\
944 	/* in anticipation of a calibration (needs_calibration()) to avoid */		\
945 	/* requiring one during measurement, or in response to measuring */			\
946 	/* returning inst_needs_cal before retrying the measurement, */				\
947 	/* or to do one or more re-calibrations. */									\
948 																				\
949 	/* *calt should contain the mask of calibrations to be performed, */		\
950 	/* with *calc set to the current calibration condition. */					\
951 	/* Alternately, one of the psudo-calibration types inst_calt_all, */		\
952 	/* inst_calt_needed or inst_calt_available can be used, */			\
953 	/* and/or the *calc of inst_calc_none to get calibrate() */					\
954 	/* to determine the required calibration types and conditions. */			\
955 	/* (The corresponding calibration types will be used & returned. */			\
956 																				\
957 	/* If no error is returned to the first call to calibrate() */				\
958 	/* then the instrument was capable of calibrating without user or */		\
959 	/* application intervention. If on the other hand calibrate() returns */	\
960 	/* inst_cal_setup, then the appropriate action indicated by the value */	\
961 	/* returned in *calc should be taken by the user or application, */			\
962 	/* before retrying calibration() with the current setup indicated */		\
963 	/* by *calc. If more than one calibration type is requested, then */		\
964 	/* several retries may be needed with different calibration conditions. */	\
965  	/* Each call to calibrate() will update *calt to reflect the remaining */	\
966 	/* calibration to be performed.  calibrate() returns inst_ok when no */		\
967 	/* more calibrations remain. */												\
968 																				\
969 	/* If the calc has the inst_calc_optional_flag flag set, */					\
970 	/* then the user should be offered the option of skipping the */			\
971 	/* calibration. If they decide to skip it, return a calc with */			\
972 	/* inst_calc_optional_flag set, and if they want to proceed, */				\
973 	/* make sure the inst_calc_optional_flag is cleared in the returned */		\
974 	/* calc. */																	\
975 																				\
976 	/* DOESN'T use the trigger mode */											\
977 	/* Return inst_unsupported if *calt is not appropriate, */					\
978 	/* inst_cal_setup if *calc is not appropriate. */							\
979 	inst_code (*calibrate)(														\
980 		struct _inst *p,														\
981 		inst_cal_type *calt,	/* Calibration type to do/remaining */			\
982 		inst_cal_cond *calc,	/* Current condition/desired condition */		\
983 		inst_calc_id_type *idtype,	/* Condition identifier type */				\
984 		char id[CALIDLEN]);		/* Condition identifier (ie. white */			\
985 								/* reference ID, filter ID, message string, */	\
986 								/* etc.) */										\
987 																				\
988 	/* Measure a display update, and instrument reaction time. It is */			\
989 	/* assumed that a white to black change will be made to the */				\
990 	/* displayed color during this call, and this is used to measure */			\
991 	/* the time it took for the update to be noticed by the instrument, */		\
992 	/* up to 1.0 second. */												   		\
993 	/* The instrument reaction time accounts for the time between */			\
994 	/* when the measure function is called and the samples actually being */	\
995 	/* taken. This value may be negative if there is a filter delay. */			\
996 	/* The method white_change() should be called with init=1 before */			\
997 	/* calling meas_delay, and then with init=0 during the meas_delay() */	\
998 	/* call to timestamp the transition. */										\
999 	/* Note that a default instmsec will be returned even on error. */			\
1000 	inst_code (*meas_delay)(											        \
1001 		struct _inst *p,														\
1002 		int *dispmsec,		/* Return display update delay in msec */			\
1003 		int *instmsec);		/* Return instrument reaction time in msec */		\
1004 																				\
1005 	/* Call used by other thread to timestamp the patch transition. */			\
1006 	inst_code (*white_change)(											        \
1007 		struct _inst *p,														\
1008 		int init);			/* nz to init time stamp, z to mark transition */	\
1009 																				\
1010 	/* Return the last calibrated refresh rate in Hz. Returns: */				\
1011 	/* (Available if cap2 & inst2_get_refresh_rate) */ 							\
1012 	/* inst_unsupported - if this instrument doesn't suport a refresh mode */	\
1013 	/*                    or is unable to retrieve the refresh rate */			\
1014 	/* inst_needs_cal   - if the refresh rate value is not valid */				\
1015 	/* inst_misread     - if no refresh rate could be determined */				\
1016 	/* inst_ok          - on returning a valid reading */						\
1017 	inst_code (*get_refr_rate)(											        \
1018 		struct _inst *p,														\
1019 		double *ref_rate);		/* Return the Hz */								\
1020 																				\
1021 	/* Set the calibrated refresh rate in Hz. */								\
1022 	/* (Available if cap2 & inst2_set_refresh_rate) */ 							\
1023 	/* Set refresh rate to 0.0 to mark it as invalid */							\
1024 	/* Rates outside the range 5.0 to 150.0 Hz will return an error */			\
1025 	/* Note that not all instruments that can return a refresh rate, */			\
1026 	/* will permit one to be set (ie., DTP92) */								\
1027 	inst_code (*set_refr_rate)(											        \
1028 		struct _inst *p,														\
1029 		double ref_rate);		/* Rate in Hz */								\
1030 																				\
1031 	/* Insert a compensation filter in the instrument readings */				\
1032 	/* This is typically needed if an adapter is being used, that alters */     \
1033 	/* the spectrum of the light reaching the instrument */                     \
1034 	/* Not fully implemented across all instrument types (spectrolino only ?) */ \
1035 	/* To remove the filter, pass NULL for the filter filename */               \
1036 	inst_code (*comp_filter)(											        \
1037 		struct _inst *p,														\
1038 		char *filtername);		/* File containing compensating filter */		\
1039 																				\
1040 	/* Insert a colorimetric correction matrix in the instrument XYZ readings */ \
1041 	/* This is only valid for colorimetric instruments, and can only be */		\
1042 	/* applied over a base calibration display type. Setting a display */		\
1043 	/* type will clear the matrix. */											\
1044 	/* To clear the matrix, pass NULL for the matrix */							\
1045 	inst_code (*col_cor_mat)(											        \
1046 		struct _inst *p,														\
1047 		disptech dtech,		/* Use disptech_unknown if not known */				\
1048 		int cbid,       	/* Calibration display type base ID, needed 1 if unknown */\
1049 		double mtx[3][3]);	/* XYZ matrix */								    \
1050 																				\
1051 	/* Use a Colorimeter Calibration Spectral Set (ccss) to set the */			\
1052 	/* instrumen calibration. This will affect emissive readings. */			\
1053 	/* An alternate observer may also be set, and this will affect both */		\
1054 	/* emissive and ambient readings. */										\
1055 	/* This is only valid for colorimetric instruments. */						\
1056 	/* To set calibration back to default, pass NULL for sets, and */			\
1057 	/* icxOT_default for the observer. */										\
1058 	inst_code (*col_cal_spec_set)(												\
1059 		struct _inst *p,														\
1060 		disptech dtech,		/* Use disptech_unknown if not known */				\
1061 		xspect *sets,		/* Set of sample spectra */							\
1062 		int no_sets); 		/* Number on set */									\
1063 																				\
1064 	/* Supply a user interaction callback function.								\
1065 	 * This is called for one of three different purposes:						\
1066 	 *	To signal that the instrument measurement has been triggered.			\
1067 	 *	To poll for an abort while waiting to trigger.							\
1068 	 *	To poll for a user abort during measurement.							\
1069 	 *																			\
1070 	 * The callback function will have the purpose paramater appropriately.		\
1071 	 *																			\
1072      * For inst_negcoms, the return value of inst_user_abort					\
1073 	 * will abort the communication negotiation.								\
1074 	 *																			\
1075 	 * For inst_armed return value should be one of: 							\
1076 	 * inst_ok to do nothing, inst_user_abort to abort the measurement,			\
1077 	 * or inst_user_trig to trigger the measurement.							\
1078 	 *																			\
1079 	 * For inst_triggered, the return value of the callback is ignored.			\
1080 	 *																			\
1081 	 * For inst_measuring the return value should be one of:					\
1082 	 * inst_ok to do nothing, inst_user_abort to abort the measurement.			\
1083 	 *																			\
1084 	 * NULL can be set to disable the callback.									\
1085 	 */																			\
1086 	void (*set_uicallback)(struct _inst *p,										\
1087 		inst_code (*uicallback)(void *cntx, inst_ui_purp purp), 				\
1088 		void *cntx);															\
1089 																				\
1090 	/* Supply an aynchronous event callback function.							\
1091 	 * This is called from a different thread with the following possible events:		\
1092 	 *																			\
1093 	 * inst_event_switch: Instrument measure/calibrate switch pressed 			\
1094 	 * inst_event_mconf: The measurement configuration has changed (ie. sensor position)	\
1095      * inst_event_scan_ready: Ready for manual strip scan (i.e. issue audible prompt)	\
1096 	 *																			\
1097 	 * NULL can be set to disable the callback.									\
1098 	 */																			\
1099 	void (*set_event_callback)(struct _inst *p,									\
1100 		void (*eventcallback)(void *cntx, inst_event_type event),				\
1101 		void *cntx);															\
1102 																				\
1103 	/* Generic inst error codes interpretation */								\
1104 	char * (*inst_interp_error)(struct _inst *p, inst_code ec);					\
1105 																				\
1106 	/* Instrument specific error codes interpretation */						\
1107 	char * (*interp_error)(struct _inst *p, int ec);							\
1108 																				\
1109 	/* Convert instrument specific inst_wrong_config error to inst_config enum */	\
1110 	inst_config (*config_enum)(struct _inst *p, int ec);							\
1111 																				\
1112 	/* Return the last serial communication error code */						\
1113 	/* (This is used for deciding fallback/retry strategies) */					\
1114 	int (*last_scomerr)(struct _inst *p);										\
1115 																				\
1116 	/* Destroy ourselves */														\
1117 	void (*del)(struct _inst *p);												\
1118 
1119 /* The base object type */
1120 struct _inst {
1121 	INST_OBJ_BASE
1122 	}; typedef struct _inst inst;
1123 
1124 /* Virtual constructor. */
1125 /* Return NULL for unknown instrument, */
1126 /* or serial instrument if nocoms == 0. */
1127 /* (Doesn't copy icompaths log!) */
1128 /* If uicallback is provided, it will be set in the resulting inst */
1129 extern inst *new_inst(
1130 	icompath *path,		/* Device path this instrument */
1131 	int nocoms,			/* Don't open if communications are needed to establish inst type */
1132 	a1log *log,			/* Log to use */
1133 	inst_code (*uicallback)(void *cntx, inst_ui_purp purp),		/* optional uicallback */
1134 	void *cntx			/* Context for callback */
1135 );
1136 
1137 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
1138 /* Implementation functions used by instrument drivers */
1139 /* (Client code should not call these) */
1140 
1141 /* Get a status or set or get an option (default implementation) */
1142 inst_code inst_get_set_opt_def(
1143 inst *p,
1144 inst_opt_type m,	/* Option type */
1145 va_list args);		/* Option parameters */
1146 
1147 /* - - - - - - - - - - - - - - - - - - -- */
1148 
1149 /* Create the display type list */
1150 inst_code inst_creat_disptype_list(inst *p,
1151 int *pndtlist,					/* Number in returned list */
1152 inst_disptypesel **pdtlist,		/* Returned list */
1153 inst_disptypesel *sdtlist,		/* Static list */
1154 int doccss,						/* Add installed ccss files */
1155 int doccmx						/* Add matching installed ccmx files */
1156 );
1157 
1158 /* Free a display type list */
1159 void inst_del_disptype_list(inst_disptypesel *list, int no);
1160 
1161 /* - - - - - - - - - - - - - - - - - - -- */
1162 
1163 /* Issue an inst_event_scan_ready event after a delay */
1164 void issue_scan_ready(inst *p, int delay);
1165 
1166 /* - - - - - - - - - - - - - - - - - - -- */
1167 /* CCMX support - ccmx instrument proxy */
1168 
1169 typedef struct {
1170 	char *path;			/* Path to the file */
1171 	char *desc;			/* Technology + display description */
1172 	disptech dtech;		/* Display Technology enumeration (optional if disp) */
1173 	int cc_cbid;       	/* Calibration display type base ID required */
1174 	int  refr;			/* Refresh mode flag */
1175 	char *sel;			/* UI selector characters (may be NULL) */
1176 	int oem;			/* nz if oem origin */
1177 	double mat[3][3];	/* The matrix values */
1178 } iccmx;
1179 
1180 /* return a list of installed ccmx files. */
1181 /* if itype != instUnknown, return those that match the given instrument. */
1182 /* The list is sorted by description and terminated by a NULL entry. */
1183 /* If no is != NULL, return the number in the list */
1184 /* Return NULL and -1 if there is a malloc error */
1185 iccmx *list_iccmx(instType itype, int *no);
1186 
1187 /* Free up a iccmx list */
1188 void free_iccmx(iccmx *list);
1189 
1190 /* - - - - - - - - - - - - - - - - - - -- */
1191 /* CCSS support - ccss instrument proxy */
1192 
1193 typedef struct {
1194 	char *path;			/* Path to the file */
1195 	char *desc;			/* Technology + display description */
1196 	disptech dtech;		/* Display Technology enumeration (optional if disp) */
1197 	int  refr;			/* Refresh mode flag */
1198 	char *sel;			/* UI selector characters (may be NULL) */
1199 	int oem;			/* nz if oem origin */
1200 	xspect *sets;		/* Set of sample spectra */
1201 	int no_sets;		/* Number on set */
1202 } iccss;
1203 
1204 /* return a list of installed ccss files. */
1205 /* The list is sorted by description and terminated by a NULL entry. */
1206 /* If no is != NULL, return the number in the list */
1207 /* Return NULL and -1 if there is a malloc error */
1208 iccss *list_iccss(int *no);
1209 
1210 /* Free up a iccss list */
1211 void free_iccss(iccss *list);
1212 
1213 /* - - - - - - - - - - - - - - - - - - -- */
1214 
1215 #ifdef __cplusplus
1216 	}
1217 #endif
1218 
1219 
1220 #define INST_H
1221 #endif /* INST_H */
1222