1 #ifndef I1PRO_IMP_H 2 3 /* 4 * Argyll Color Correction System 5 * 6 * Gretag i1Pro implementation defines 7 */ 8 9 /* 10 * Author: Graeme W. Gill 11 * Date: 20/12/2006 12 * 13 * Copyright 2006 - 2013 Graeme W. Gill 14 * All rights reserved. 15 * 16 * This material is licenced under the GNU GENERAL PUBLIC LICENSE Version 2 or later :- 17 * see the License2.txt file for licencing details. 18 */ 19 20 #ifdef __cplusplus 21 extern "C" { 22 #endif 23 24 /* 25 If you make use of the instrument driver code here, please note 26 that it is the author(s) of the code who take responsibility 27 for its operation. Any problems or queries regarding driving 28 instruments with the Argyll drivers, should be directed to 29 the Argyll's author(s), and not to any other party. 30 31 If there is some instrument feature or function that you 32 would like supported here, it is recommended that you 33 contact Argyll's author(s) first, rather than attempt to 34 modify the software yourself, if you don't have firm knowledge 35 of the instrument communicate protocols. There is a chance 36 that an instrument could be damaged by an incautious command 37 sequence, and the instrument companies generally cannot and 38 will not support developers that they have not qualified 39 and agreed to support. 40 */ 41 42 /* Implementation resources for i1pro driver */ 43 44 /* -------------------------------------------------- */ 45 /* Implementation class */ 46 47 typedef int i1pro_code; /* Type to use for error codes */ 48 49 /* I1PRO mode state. This is implementation data that */ 50 /* depends on the mode the instrument is in. */ 51 /* Each mode has a separate calibration, and configured instrument state. */ 52 53 typedef enum { 54 i1p_refl_spot = 0, 55 i1p_refl_scan = 1, 56 i1p_emiss_spot_na = 2, 57 i1p_emiss_spot = 3, 58 i1p_emiss_scan = 4, 59 i1p_amb_spot = 5, 60 i1p_amb_flash = 6, 61 i1p_trans_spot = 7, 62 i1p_trans_scan = 8, 63 i1p_no_modes = 9 /* Number of modes */ 64 } i1p_mode; 65 66 struct _i1pro_state { 67 i1p_mode mode; /* Mode number */ 68 69 /* Just one of the following 3 must always be set */ 70 int emiss; /* flag - Emissive mode */ 71 int trans; /* flag - Transmissive mode */ 72 int reflective; /* flag - Reflective mode */ 73 74 /* The following can be added to emiss */ 75 int ambient; /* flag - Ambient mode */ 76 77 /* The following can be added to any of the 3: */ 78 int scan; /* flag - Scanning mode */ 79 int adaptive; /* flag - adaptive mode */ 80 81 /* The following can be added to scan: */ 82 int flash; /* flag - Flash detection from scan mode */ 83 84 /* Configuration & state information */ 85 double targoscale; /* Optimal reading scale factor <= 1.0 */ 86 /* Would determine scan sample rate, except we're not doing it that way! */ 87 double targmaxitime;/* maximum integration time to aim for (ie. 2.0 sec) */ 88 double targoscale2;/* Proportion of targoscale allowed to meed targmaxitime */ 89 int gainmode; /* Gain mode, 0 = normal, 1 = high */ 90 double inttime; /* Integration time */ 91 double lamptime; /* Lamp turn on time */ 92 93 double dadaptime; /* Target adaptive dark read time - sets number of readings */ 94 double wadaptime; /* Target adaptive white/sample read time - sets number of readings */ 95 96 double dcaltime; /* Target dark calibration time - sets number of readings */ 97 double wcaltime; /* Target white calibration time - sets number of readings */ 98 99 double dreadtime; /* Target dark on-the-fly cal time - sets number of readings */ 100 double wreadtime; /* Target white/sample reading time - sets number of readings */ 101 102 double maxscantime; /* Maximum scan time sets buffer size allocated */ 103 104 double min_wl; /* Minimum wavelegth to report for this mode */ 105 106 /* calibration information for this mode */ 107 int wl_valid; /* wavelength calibration factor valid */ 108 time_t wldate; /* Date/time of last wavelength calibration */ 109 double wl_led_off; /* Wavelength LED reference spectrum current offset */ 110 111 int dark_valid; /* dark calibration factor valid */ 112 time_t ddate; /* Date/time of last dark calibration */ 113 double dark_int_time; /* Integration time used for dark data */ 114 double *dark_data; /* [-1 nraw] of dark level to subtract. Note that the dark value */ 115 /* depends on integration time. */ 116 int dark_gain_mode; /* Gain mode used for dark data */ 117 118 int cal_valid; /* calibration factor valid */ 119 time_t cfdate; /* Date/time of last cal factor calibration */ 120 double *cal_factor[2]; /* [low res, high res][nwav] calibration scale factor for this mode */ 121 double *white_data; /* [-1 nraw] linear absolute dark subtracted white data */ 122 /* used to compute cal_factor */ 123 124 /* Adaptive emission/transparency black data */ 125 int idark_valid; /* idark calibration factors valid */ 126 time_t iddate; /* Date/time of last dark idark calibration */ 127 double idark_int_time[4]; 128 double **idark_data; /* [4][-1 nraw] of dark level for inttime/gains of : */ 129 /* 0.01 norm, 4.0 norm, 0.01 high, 2.0 high */ 130 131 int want_calib; /* Want White calibration at start */ 132 int want_dcalib; /* Want Dark Calibration at start */ 133 134 /* Display mode calibration state (emmis && !scan && !adaptive) */ 135 int dispswap; /* 0 = default time, 1 = dark_int_time2, 2 = dark_int_time3 */ 136 /* 3 = dark_int_time4 */ 137 double done_dintsel; /* A display integration time selection has been done */ 138 time_t diseldate; /* Date/time of last display integration time selection */ 139 double dcaltime2; /* Target dark calibration time - sets number of readings */ 140 double dark_int_time2; /* Integration time used for dark data 2 */ 141 double *dark_data2; /* [-1 nraw] of dark level to subtract for dark_int_time2. */ 142 double dcaltime3; /* Target dark calibration time - sets number of readings */ 143 double dark_int_time3; /* Integration time used for dark data 3 */ 144 double *dark_data3; /* [-1 nraw] of dark level to subtract for dark_int_time3. */ 145 double dcaltime4; /* Target dark calibration time - sets number of readings */ 146 double dark_int_time4; /* Integration time used for dark data 4 */ 147 double *dark_data4; /* [-1 nraw] of dark level to subtract for dark_int_time4. */ 148 149 }; typedef struct _i1pro_state i1pro_state; 150 151 /* Pointers to the three tables that allow a raw to wave filter conversion */ 152 typedef struct { 153 int *index; /* [nwav] Matrix CCD sample starting index for each out wavelength */ 154 int *nocoef; /* [nwav] Number of matrix cooeficients for each out wavelength */ 155 double *coef; /* [nwav * mtx_nocoef] Matrix cooeficients to compute each wavelength */ 156 } i1pro_r2wtab; 157 158 /* RevE capability bits */ 159 #define I1PRO_CAP2_AMBIENT 0x01 /* Has ambient measurement capability */ 160 #define I1PRO_CAP2_WL_LED 0x02 /* Has wavelenght LED */ 161 #define I1PRO_CAP2_UV_LED 0x04 /* Has Ultra Violet LED */ 162 #define I1PRO_CAP2_ZEB_RUL 0x08 /* Has zerbra ruler sensor */ 163 #define I1PRO_CAP2_IND_LED 0x10 /* Has indicator LEDs */ 164 #define I1PRO_CAP2_UV_FILT 0x20 /* Has Ultra Violet Filter */ 165 166 /* I1PRO implementation class */ 167 struct _i1proimp { 168 i1pro *p; 169 170 /* Misc. and top level */ 171 struct _i1data *data; /* EEProm data container */ 172 athread *th; /* Switch monitoring thread (NULL if not used) */ 173 volatile int switch_count; /* Incremented in thread */ 174 volatile int hide_switch; /* Set to supress switch event during read */ 175 usb_cancelt sw_cancel; /* Token to allow cancelling switch I/O */ 176 volatile int th_term; /* Terminate thread on next return */ 177 volatile int th_termed; /* Thread has terminated */ 178 usb_cancelt rd_sync; /* Token to allow meas. read to be synchronized */ 179 inst_opt_type trig; /* Reading trigger mode */ 180 int noinitcalib; /* Disable initial calibration if not essential */ 181 int highres; /* High resolution mode */ 182 int hr_inited; /* High resolution has been initialized */ 183 184 /* Current settings */ 185 i1p_mode mmode; /* Current measurement mode selected */ 186 i1pro_state ms[i1p_no_modes]; /* Mode state */ 187 int spec_en; /* NZ to enable reporting of spectral data */ 188 int uv_en; /* NZ to do UV reflective measurement */ 189 /* ~~ change this to uv_mode of none, uv, strip1, 2pass */ 190 191 xcalstd native_calstd; /* Instrument native calibration standard */ 192 xcalstd target_calstd; /* Returned calibration standard */ 193 194 double intclkp; /* Integration clock period (typically 68 usec) */ 195 int subclkdiv; /* Sub clock divider ratio */ 196 int subtmode; /* Reading 127 subtract mode (version 301 or greater) */ 197 198 /* Current state of hardware, to avoid uncessary operations */ 199 double c_inttime; /* Integration time */ 200 double l_inttime; /* Last Integration time (for Rev A+/B quirk fix) */ 201 double c_lamptime; /* Lamp turn on time */ 202 int c_mcmode; /* special clock mode we're in (if rev >= 301) */ 203 int c_intclocks; /* Number of integration clocks (set using setmeasparams() */ 204 int c_lampclocks; /* Number of integration clocks (set using setmeasparams() */ 205 int c_nummeas; /* Number of measurements (set using setmeasparams() */ 206 int c_measmodeflags; /* Measurement mode flags (set using setmeasparams() */ 207 int c_measmodeflags2; /* Measurement mode flags Rev E (set using setmeasparams() */ 208 unsigned int slamponoff; /* The second last time the lamp was switched from on to off */ 209 unsigned int llampoffon; /* The last time the lamp was switched from off to on, in msec */ 210 unsigned int llamponoff; /* The last time the lamp was switched from on to off, in msec */ 211 212 213 /* Values read from GetMisc() */ 214 int fwrev; /* int - Firmware revision number, from getmisc() */ 215 /* Used for internal switching ?? */ 216 /* 101 = Rev A, 202 = Rev A update, 302 = Rev B, */ 217 /* 502, 505, 631 = Rev D, 629 = Rev E (i1pro2) */ 218 219 int cpldrev; /* int - CPLD revision number in EEProm */ 220 /* Not used internaly ???? */ 221 /* 101 = Rev A, 2 = Rev A update, 301 = Rev B, 999 = Rev D */ 222 223 unsigned char chipid[8]; /* HW serial number - Rev E */ 224 225 int eesize; /* EEProm size in bytes */ 226 int maxpve; /* Maximum +ve value of Sensor Data + 1 */ 227 int powmode; /* Power mode status, 0 = high, 8 = low */ 228 229 /* Values from i1pro2_getmeaschar() */ 230 double intclkp2; /* Rev E Integration clock period (typically 36 usec) */ 231 int subclkdiv2; /* Sub clock divider ratio (typically 136) */ 232 233 /* Values read from GetMeasureParameters() - are these needed ? */ 234 int r_intclocks; /* Number of integration clocks (read from instrument) */ 235 int r_lampclocks; /* Number of lamp turn on sub-clocks (read from instrument) */ 236 int r_nummeas; /* Number of measurements (read from instrument) */ 237 int r_measmodeflags; /* Measurement mode flags (read from instrument) */ 238 239 240 /* Information about the instrument from the EEprom */ 241 int serno; /* serial number */ 242 char sserno[14]; /* serial number as string */ 243 int dom; /* Date of manufacture DDMMYYYY ? */ 244 int capabilities; /* Capabilities flag */ 245 /* Ambient capability if val & 0x6000 != 0 */ 246 int physfilt; /* int - physical filter */ 247 /* 0x80 == no filter */ 248 /* 0x81 == emission only ?? */ 249 /* 0x82 == UV filter */ 250 int capabilities2; /* Rev E capabilities - set #defines above */ 251 /* Also set for RevA-D */ 252 253 /* Underlying calibration information */ 254 int nsen; /* Raw + extra sample bands read = 128 for i1pro, 136 for Rev E */ 255 /* Rev <= D have exactly 128 */ 256 /* Rev E has 134, of which 128 are measurements. */ 257 /* 5 are skipped at the start, and 1 at the end */ 258 /* The first 4 are used as a dark consistency check. */ 259 /* ie. 4 + 1 + 128 + 1 */ 260 int nraw; /* Raw sample bands stored = 128 (Must be signed!) */ 261 unsigned int nwav[2]; /* [low res, high res] cooked spectrum bands stored, ie = 36 */ 262 double wl_short[2]; /* [low res, high res] cooked spectrum bands short wavelength, ie 380 */ 263 double wl_long[2]; /* [low res, high res] cooked spectrum bands short wavelength, ie 730 */ 264 265 unsigned int nlin0; /* Number in array */ 266 double *lin0; /* Array of linearisation polinomial factors, normal gain. */ 267 268 unsigned int nlin1; /* Number in array */ 269 double *lin1; /* Array of linearisation polinomial factors, high gain. */ 270 271 double min_int_time; /* Minimum integration time (secs) */ 272 double max_int_time; /* Maximum integration time (secs) */ 273 274 i1pro_r2wtab mtx[2][2]; /* Raw to wav filters [normal res, high res][emis/trans, reflective] */ 275 /* These are all pointers to tables allocated below */ 276 277 i1pro_r2wtab mtx_o; /* Underlying original filters from EEProm calibration info. */ 278 i1pro_r2wtab mtx_c[2][2]; /* Underlying allocated for RevE wavelength and hi-res calibrated */ 279 280 double *white_ref[2]; /* [low res, high res][nwav] White cal tile reflectance values */ 281 double *emis_coef[2]; /* [low res, high res][nwav] Emission cal coefficients */ 282 double *amb_coef[2]; /* [low res, high res][nwav] Ambient light cal values */ 283 /* (compound with Emission), NULL if ambient not supported */ 284 int emis_hr_cal; /* NZ if emis_coef[1] has been fine calibrated using reflective cal. */ 285 286 double **straylight[2]; /* [nwav][nwav] Stray light convolution matrix (Rev E) */ 287 288 double highgain; /* High gain mode gain */ 289 double scan_toll_ratio; /* Modifier of scan tollerance */ 290 291 int sens_target; /* sensor optimal target value */ 292 int sens_dark; /* sensor dark reference threshold */ 293 int sens_sat0; /* Normal gain sensor saturated threshold */ 294 int sens_sat1; /* High gain sensor saturated threshold */ 295 296 /* RevA-D alternative to RevE calibration information */ 297 rspl *raw2wav; /* Lookup from CCD index to wavelength, NULL until highres inited */ 298 299 /* Rev E calibration information */ 300 double wl_cal_inttime; /* Wavelength calibration integration time */ 301 double wl_cal_min_level; /* Normalized wavelength calibration minumum peak level */ 302 double wl_cal_fwhm; /* Wavelength cal expected FWHM (nm) */ 303 double wl_cal_fwhm_tol; /* Wavelength cal expected FWHM tollerance (nm) */ 304 double *wl_led_spec; /* Wavelength LED reference spectrum */ 305 unsigned int wl_led_count; /* Wavelength LED reference spectrum number of entries */ 306 double wl_led_ref_off; /* Wavelength LED reference spectrum ref. offset */ 307 double wl_err_max; /* Wavelength error maximum value (ie. 5.0) */ 308 double *wlpoly1, *wlpoly2; /* CCD bin to wavelength polinomial equations */ 309 /* for reflective and emissive/transmissuce modes respectively. */ 310 311 /* log variables */ 312 int meascount; /* Total Measure (Emis/Remis/Ambient/Trans/Cal) count */ 313 /* but not the pre-Remission dark calibration. */ 314 time_t caldate; /* Remspotcal last calibration date */ 315 int calcount; /* Remission spot measure count at last Remspotcal. */ 316 double rpinttime; /* Last remision spot reading integration time */ 317 int rpcount; /* Remission spot measure count */ 318 int acount; /* Remission scan measure count (Or all scan ??) */ 319 double lampage; /* Total lamp usage time in seconds (??) */ 320 321 /* Trigger houskeeping & diagnostics */ 322 int transwarn; /* Transmission calibration warning state */ 323 int lo_secs; /* Seconds since last opened (from calibration file mod time) */ 324 int msec; /* msec_time() at creation */ 325 athread *trig_thread; /* Delayed trigger thread */ 326 int trig_delay; /* Trigger delay in msec */ 327 int tr_t1, tr_t2, tr_t3, tr_t4, tr_t5, tr_t6, tr_t7; /* Trigger/read timing diagnostics */ 328 /* 1->2 = time to execute trigger */ 329 /* 2->3 = time to between end trigger and start of first read */ 330 /* 3->4 = time to exectute first read */ 331 /* 6->5 = time between end of second last read and start of last read */ 332 int trig_se; /* Delayed trigger icoms error */ 333 i1pro_code trig_rv; /* Delayed trigger result */ 334 335 volatile double whitestamp; /* meas_delay() white timestamp */ 336 volatile double trigstamp; /* meas_delay() trigger timestamp */ 337 338 }; typedef struct _i1proimp i1proimp; 339 340 /* Add an implementation structure */ 341 i1pro_code add_i1proimp(i1pro *p); 342 343 /* Destroy implementation structure */ 344 void del_i1proimp(i1pro *p); 345 346 /* ============================================================ */ 347 /* Error codes returned from i1pro_imp */ 348 349 /* Note: update i1pro_interp_error() and i1pro_interp_code() in i1pro.c */ 350 /* if anything of these #defines are added or subtracted */ 351 352 /* Fake Error codes */ 353 #define I1PRO_INTERNAL_ERROR 0x71 /* Internal software error */ 354 #define I1PRO_COMS_FAIL 0x72 /* Communication failure */ 355 #define I1PRO_UNKNOWN_MODEL 0x73 /* Not an i1pro */ 356 #define I1PRO_DATA_PARSE_ERROR 0x74 /* Read data parsing error */ 357 358 #define I1PRO_USER_ABORT 0x75 /* uicallback returned abort */ 359 #define I1PRO_USER_TRIG 0x76 /* uicallback retuned trigger */ 360 361 #define I1PRO_UNSUPPORTED 0x79 /* Unsupported function */ 362 #define I1PRO_CAL_SETUP 0x7A /* Cal. retry with correct setup is needed */ 363 #define I1PRO_RD_TRANSWHITEWARN 0x7B /* Transmission white ref wl are low */ 364 365 /* Real error code */ 366 #define I1PRO_OK 0x00 367 368 #define I1PRO_DATA_COUNT 0x01 /* count unexpectedly small */ 369 #define I1PRO_DATA_BUFSIZE 0x02 /* buffer too small */ 370 #define I1PRO_DATA_MAKE_KEY 0x03 /* creating key failed */ 371 #define I1PRO_DATA_MEMORY 0x04 /* memory alloc failure */ 372 #define I1PRO_DATA_KEYNOTFOUND 0x05 /* a key value wasn't found */ 373 #define I1PRO_DATA_WRONGTYPE 0x06 /* a key is the wrong type */ 374 #define I1PRO_DATA_KEY_CORRUPT 0x07 /* key table seems to be corrupted */ 375 #define I1PRO_DATA_KEY_COUNT_SMALL 0x08 /* key table count is too small */ 376 #define I1PRO_DATA_KEY_COUNT_LARGE 0x09 /* key table count is too big */ 377 #define I1PRO_DATA_KEY_UNKNOWN 0x0a /* unknown key type */ 378 #define I1PRO_DATA_KEY_MEMRANGE 0x0b /* key data is out of range of EEProm */ 379 #define I1PRO_DATA_KEY_ENDMARK 0x0c /* And end section marker was missing */ 380 381 /* HW errors */ 382 #define I1PRO_HW_HIGHPOWERFAIL 0x10 /* Switch to high power mode failed */ 383 #define I1PRO_HW_EE_SIZE 0x11 /* EEProm is too small */ 384 #define I1PRO_HW_EE_SHORTREAD 0x12 /* Read fewer EEProm bytes than expected */ 385 #define I1PRO_HW_EE_SHORTWRITE 0x13 /* Read fewer EEProm bytes than expected */ 386 #define I1PRO_HW_ME_SHORTREAD 0x14 /* Read measurement bytes than expected */ 387 #define I1PRO_HW_ME_ODDREAD 0x15 /* Read measurement bytes was not mult 256 */ 388 #define I1PRO_HW_SW_SHORTREAD 0x16 /* Read less bytes for Switch read than expected */ 389 #define I1PRO_HW_LED_SHORTWRITE 0x17 /* Wrote fewer LED sequence bytes than expected */ 390 #define I1PRO_HW_UNEX_SPECPARMS 0x18 /* Unexpacted spectral parameter values */ 391 #define I1PRO_HW_CALIBINFO 0x19 /* calibration info is missing or corrupted */ 392 #define I1PRO_WL_TOOLOW 0x1A /* WL calibration measurement too low */ 393 #define I1PRO_WL_SHAPE 0x1B /* WL calibration measurement shape is wrong */ 394 #define I1PRO_WL_ERR2BIG 0x1C /* WL calibration correction is too big */ 395 396 /* Sample read operation errors */ 397 #define I1PRO_RD_DARKREADINCONS 0x30 /* Dark calibration reading inconsistent */ 398 #define I1PRO_RD_SENSORSATURATED 0x31 /* Sensor is saturated */ 399 #define I1PRO_RD_DARKNOTVALID 0x32 /* Dark reading is not valid (too light) */ 400 #define I1PRO_RD_NEEDS_CAL 0x33 /* Mode needs calibration */ 401 #define I1PRO_RD_WHITEREADINCONS 0x34 /* White reference readings are inconsistent */ 402 #define I1PRO_RD_WHITEREFERROR 0x35 /* White reference reading error */ 403 #define I1PRO_RD_LIGHTTOOLOW 0x36 /* Light level is too low */ 404 #define I1PRO_RD_LIGHTTOOHIGH 0x37 /* Light level is too high */ 405 #define I1PRO_RD_SHORTMEAS 0x38 /* Measurment was too short */ 406 #define I1PRO_RD_READINCONS 0x39 /* Reading is inconsistent */ 407 #define I1PRO_RD_TRANSWHITERANGE 0x3A /* Transmission white reference is out of range */ 408 #define I1PRO_RD_NOTENOUGHPATCHES 0x3B /* Not enough patches */ 409 #define I1PRO_RD_TOOMANYPATCHES 0x3C /* Too many patches */ 410 #define I1PRO_RD_NOTENOUGHSAMPLES 0x3D /* Not enough samples per patch */ 411 #define I1PRO_RD_NOFLASHES 0x3E /* No flashes recognized */ 412 #define I1PRO_RD_NOAMBB4FLASHES 0x3F /* No ambient before flashes found */ 413 #define I1PRO_RD_NOREFR_FOUND 0x40 /* Unable to measure refresh rate */ 414 #define I1PRO_RD_NOTRANS_FOUND 0x41 /* Unable to measure delay transition */ 415 416 /* Internal errors */ 417 #define I1PRO_INT_NO_COMS 0x50 418 #define I1PRO_INT_EETOOBIG 0x51 /* EEProm read size is too big */ 419 #define I1PRO_INT_ODDREADBUF 0x52 /* Measurment read buffer is not mult 256 */ 420 #define I1PRO_INT_SMALLREADBUF 0x53 /* Measurment read buffer too small */ 421 #define I1PRO_INT_INTTOOBIG 0x55 /* Integration time is too big */ 422 #define I1PRO_INT_INTTOOSMALL 0x56 /* Integration time is too small */ 423 #define I1PRO_INT_ILLEGALMODE 0x57 /* Illegal measurement mode selected */ 424 #define I1PRO_INT_WRONGMODE 0x58 /* In wrong mode for request */ 425 #define I1PRO_INT_ZEROMEASURES 0x59 /* Number of measurements requested is zero */ 426 #define I1PRO_INT_WRONGPATCHES 0x5A /* Number of patches to match is wrong */ 427 #define I1PRO_INT_MEASBUFFTOOSMALL 0x5B /* Measurement read buffer is too small */ 428 #define I1PRO_INT_NOTIMPLEMENTED 0x5C /* Support not implemented */ 429 #define I1PRO_INT_NOTCALIBRATED 0x5D /* Unexpectedely invalid calibration */ 430 #define I1PRO_INT_NOINTERPDARK 0x5E /* Need interpolated dark and don't have it */ 431 #define I1PRO_INT_THREADFAILED 0x5F /* Creation of thread failed */ 432 #define I1PRO_INT_BUTTONTIMEOUT 0x60 /* Switch status read timed out */ 433 #define I1PRO_INT_CIECONVFAIL 0x61 /* Creating spectral to CIE converted failed */ 434 #define I1PRO_INT_PREP_LOG_DATA 0x62 /* Error in preparing log data */ 435 #define I1PRO_INT_MALLOC 0x63 /* Error in mallocing memory */ 436 #define I1PRO_INT_CREATE_EEPROM_STORE 0x64 /* Error in creating EEProm store */ 437 #define I1PRO_INT_SAVE_SUBT_MODE 0x65 /* Can't save calibration if in subt mode */ 438 #define I1PRO_INT_NO_CAL_TO_SAVE 0x66 /* No calibration data to save */ 439 #define I1PRO_INT_EEPROM_DATA_MISSING 0x67 /* EEProm data is missing */ 440 #define I1PRO_INT_NEW_RSPL_FAILED 0x68 /* Creating RSPL object faild */ 441 #define I1PRO_INT_CAL_SAVE 0x69 /* Unable to save calibration to file */ 442 #define I1PRO_INT_CAL_RESTORE 0x6A /* Unable to restore calibration from file */ 443 #define I1PRO_INT_CAL_TOUCH 0x6B /* Unable to touch calibration file */ 444 #define I1PRO_INT_ADARK_INVALID 0x6C /* Adaptive dark calibration is invalid */ 445 #define I1PRO_INT_NO_HIGH_GAIN 0x6D /* Rev E mode doesn't support high gain mode */ 446 #define I1PRO_INT_ASSERT 0x6F /* Internal assert */ 447 448 int icoms2i1pro_err(int se); 449 450 /* ============================================================ */ 451 /* High level implementatation */ 452 453 /* Initialise our software state from the hardware */ 454 i1pro_code i1pro_imp_init(i1pro *p); 455 456 /* Return a pointer to the serial number */ 457 char *i1pro_imp_get_serial_no(i1pro *p); 458 459 /* Return non-zero if capable of ambient mode */ 460 int i1pro_imp_ambient(i1pro *p); 461 462 /* Set the measurement mode. It may need calibrating */ 463 i1pro_code i1pro_imp_set_mode( 464 i1pro *p, 465 i1p_mode mmode, /* i1pro mode to use */ 466 inst_mode m); /* full mode mask */ 467 468 /* Implement get_n_a_cals */ 469 i1pro_code i1pro_imp_get_n_a_cals(i1pro *p, inst_cal_type *pn_cals, inst_cal_type *pa_cals); 470 471 /* Calibrate for the current mode. */ 472 /* Request an instrument calibration of the current mode. */ 473 i1pro_code i1pro_imp_calibrate( 474 i1pro *p, 475 inst_cal_type *calt, /* Calibration type to do/remaining */ 476 inst_cal_cond *calc, /* Current condition/desired condition */ 477 inst_calc_id_type *idtype, /* Condition identifier type */ 478 char id[100] /* Condition identifier (ie. white reference ID) */ 479 ); 480 481 /* Measure a patch or strip in the current mode. */ 482 i1pro_code i1pro_imp_measure( 483 i1pro *p, 484 ipatch *val, /* Pointer to array of instrument patch value */ 485 int nvals, /* Number of values */ 486 instClamping clamp /* Clamp XYZ/Lab to be +ve */ 487 ); 488 489 /* Do a dummy reflective read, to fix Lamp Drift. */ 490 i1pro_code i1pro_imp_lamp_fix( 491 i1pro *p, 492 double seconds /* Number of seconds to turn lamp on for */ 493 ); 494 495 /* Measure the emissive refresh rate */ 496 i1pro_code i1pro_imp_meas_refrate( 497 i1pro *p, 498 double *ref_rate 499 ); 500 501 /* Measure the display update delay */ 502 i1pro_code i1pro_imp_meas_delay( 503 i1pro *p, 504 int *pdispmsec, 505 int *pinstmsec); 506 507 /* Timestamp the white patch change during meas_delay() */ 508 inst_code i1pro_imp_white_change(i1pro *p, int init); 509 510 /* Given a raw measurement of the wavelength LED, */ 511 /* Compute the base offset that best fits it to the reference */ 512 i1pro_code i1pro2_match_wl_meas(i1pro *p, double *pled_off, double *wlraw); 513 514 /* Compute downsampling filters using the default filters. */ 515 /* mtx_index1, mtx_nocoef1, mtx_coef1 given the */ 516 /* current wl_led_off */ 517 i1pro_code i1pro_compute_wav_filters(i1pro *p, int hires, int reflective); 518 519 /* return nz if high res is supported */ 520 int i1pro_imp_highres(i1pro *p); 521 522 /* Set to high resolution mode */ 523 i1pro_code i1pro_set_highres(i1pro *p); 524 525 /* Set to standard resolution mode */ 526 i1pro_code i1pro_set_stdres(i1pro *p); 527 528 /* Modify the scan consistency tollerance */ 529 i1pro_code i1pro_set_scan_toll(i1pro *p, double toll_ratio); 530 531 532 /* Update the single remission calibration and instrument usage log */ 533 i1pro_code i1pro_update_log(i1pro *p); 534 535 /* Save the reflective spot calibration information to the EEPRom data object. */ 536 /* Note we don't actually write to the EEProm here! */ 537 static i1pro_code i1pro_set_log_data(i1pro *p); 538 539 /* Restore the reflective spot calibration information from the EEPRom */ 540 /* Always returns success, even if the restore fails */ 541 i1pro_code i1pro_restore_refspot_cal(i1pro *p); 542 543 544 /* Save the calibration for all modes, stored on local system */ 545 i1pro_code i1pro_save_calibration(i1pro *p); 546 547 /* Restore the all modes calibration from the local system */ 548 i1pro_code i1pro_restore_calibration(i1pro *p); 549 550 /* Update the modification time on the file, so we can */ 551 /* track when the instrument was last open. */ 552 i1pro_code i1pro_touch_calibration(i1pro *p); 553 554 /* ============================================================ */ 555 /* Intermediate routines - composite commands/processing */ 556 557 i1pro_code i1pro_establish_high_power(i1pro *p); 558 559 /* Take a dark reference measurement - part 1 */ 560 i1pro_code i1pro_dark_measure_1( 561 i1pro *p, 562 int nummeas, /* Number of readings to take */ 563 double *inttime, /* Integration time to use/used */ 564 int gainmode, /* Gain mode to use, 0 = normal, 1 = high */ 565 unsigned char *buf, /* USB reading buffer to use */ 566 unsigned int bsize /* Size of buffer */ 567 ); 568 569 /* Take a dark reference measurement - part 2 */ 570 i1pro_code i1pro_dark_measure_2( 571 i1pro *p, 572 double *absraw, /* Return array [-1 nraw] of absraw values */ 573 int nummeas, /* Number of readings to take */ 574 double inttime, /* Integration time to use/used */ 575 int gainmode, /* Gain mode to use, 0 = normal, 1 = high */ 576 unsigned char *buf, /* raw USB reading buffer to process */ 577 unsigned int bsize /* Buffer size to process */ 578 ); 579 580 /* Take a dark measurement */ 581 i1pro_code i1pro_dark_measure( 582 i1pro *p, 583 double *absraw, /* Return array [-1 nraw] of absraw values */ 584 int nummeas, /* Number of readings to take */ 585 double *inttime, /* Integration time to use/used */ 586 int gainmode /* Gain mode to use, 0 = normal, 1 = high */ 587 ); 588 589 /* Take a white reference measurement - part 3 */ 590 /* Average, check, and convert to output wavelengths */ 591 i1pro_code i1pro_whitemeasure_3( 592 i1pro *p, 593 double *abswav1, /* Return array [nwav1] of abswav values (may be NULL) */ 594 double *abswav2, /* Return array [nwav2] of abswav values (if hr_init, may be NULL) */ 595 double *absraw, /* Return array [-1 nraw] of absraw values */ 596 double *optscale, /* Factor to scale gain/int time by to make optimal (may be NULL) */ 597 int nummeas, /* Number of readings to take */ 598 double inttime, /* Integration time to use/used */ 599 int gainmode, /* Gain mode to use, 0 = normal, 1 = high */ 600 double targoscale, /* Optimal reading target scale factor */ 601 double **multimes, /* Multiple measurement results */ 602 double darkthresh /* Raw dark threshold */ 603 ); 604 605 /* Take a white reference measurement */ 606 /* (Subtracts black and processes into wavelenths) */ 607 i1pro_code i1pro_whitemeasure( 608 i1pro *p, 609 double *abswav1, /* Return array [nwav1] of abswav values (may be NULL) */ 610 double *abswav2, /* Return array [nwav2] of abswav values (if hr_init, may be NULL) */ 611 double *absraw, /* Return array [-1 nraw] of absraw values */ 612 double *optscale, /* Factor to scale gain/int time by to make optimal (may be NULL) */ 613 int nummeas, /* Number of readings to take */ 614 double *inttime, /* Integration time to use/used */ 615 int gainmode, /* Gain mode to use, 0 = normal, 1 = high */ 616 double targoscale, /* Optimal reading scale factor */ 617 int ltocmode /* 1 = Lamp turn on compensation mode */ 618 ); 619 620 /* Process a single raw white reference measurement */ 621 /* (Subtracts black and processes into wavelenths) */ 622 i1pro_code i1pro_whitemeasure_buf( 623 i1pro *p, 624 double *abswav1, /* Return array [nwav1] of abswav values (may be NULL) */ 625 double *abswav2, /* Return array [nwav2] of abswav values (if hr_init, may be NULL) */ 626 double *absraw, /* Return array [-1 nraw] of absraw values */ 627 double inttime, /* Integration time to used */ 628 int gainmode, /* Gain mode to use, 0 = normal, 1 = high */ 629 unsigned char *buf /* Raw buffer */ 630 ); 631 632 /* Take a wavelength reference measurement */ 633 /* (Measure and subtracts black and convert to absraw) */ 634 i1pro_code i1pro2_wl_measure( 635 i1pro *p, 636 double *absraw, /* Return array [-1 nraw] of absraw values */ 637 double *optscale, /* Factor to scale gain/int time by to make optimal (may be NULL) */ 638 double *inttime, /* Integration time to use/used */ 639 double targoscale /* Optimal reading scale factor */ 640 ); 641 642 /* Take a measurement reading using the current mode (combined parts 1 & 2a) */ 643 /* Converts to completely processed output readings, without averaging or extracting */ 644 /* sample patches. */ 645 /* (NOTE:- this can't be used for calibration, as it implements uv mode) */ 646 i1pro_code i1pro_read_patches_all( 647 i1pro *p, 648 double **specrd, /* Return array [numpatches][nwav] of spectral reading values */ 649 int numpatches, /* Number of sample to measure */ 650 double *inttime, /* Integration time to use/used */ 651 int gainmode /* Gain mode to use, 0 = normal, 1 = high */ 652 ); 653 654 /* Take a measurement reading using the current mode, part 1 */ 655 /* Converts to completely processed output readings. */ 656 i1pro_code i1pro_read_patches_1( 657 i1pro *p, 658 int minnummeas, /* Minimum number of measurements to take */ 659 int maxnummeas, /* Maximum number of measurements to allow for */ 660 double *inttime, /* Integration time to use/used */ 661 int gainmode, /* Gain mode to use, 0 = normal, 1 = high */ 662 int *nmeasuered, /* Number actually measured */ 663 unsigned char *buf, /* Raw USB reading buffer */ 664 unsigned int bsize 665 ); 666 667 /* Take a measurement reading using the current mode, part 2 */ 668 /* Converts to completely processed output readings. */ 669 i1pro_code i1pro_read_patches_2( 670 i1pro *p, 671 double *duration, /* return flash duration (secs) */ 672 double **specrd, /* Return array [numpatches][nwav] of spectral reading values */ 673 int numpatches, /* Number of patches to return */ 674 double inttime, /* Integration time to used */ 675 int gainmode, /* Gain mode useed, 0 = normal, 1 = high */ 676 int nmeasuered, /* Number actually measured */ 677 unsigned char *buf, /* Raw USB reading buffer */ 678 unsigned int bsize 679 ); 680 681 /* Take a measurement reading using the current mode. */ 682 /* Converts to completely processed output readings. */ 683 i1pro_code i1pro_read_patches( 684 i1pro *p, 685 double *duration, /* Return flash duration */ 686 double **specrd, /* Return array [numpatches][nwav] of spectral reading values */ 687 int numpatches, /* Number of patches to return */ 688 int minnummeas, /* Minimum number of measurements to take */ 689 int maxnummeas, /* Maximum number of measurements to allow for */ 690 double *inttime, /* Integration time to use/used */ 691 int gainmode /* Gain mode to use, 0 = normal, 1 = high */ 692 ); 693 694 /* Take a trial measurement reading using the current mode. */ 695 /* Used to determine if sensor is saturated, or not optimal */ 696 i1pro_code i1pro_trialmeasure( 697 i1pro *p, 698 int *saturated, /* Return nz if sensor is saturated */ 699 double *optscale, /* Factor to scale gain/int time by to make optimal */ 700 int nummeas, /* Number of readings to take */ 701 double *inttime, /* Integration time to use/used */ 702 int gainmode, /* Gain mode to use, 0 = normal, 1 = high */ 703 double targoscale /* Optimal reading scale factor */ 704 ); 705 706 /* Measurement modifier. Modifes the default current measurement mode */ 707 /* for the measurement. Bit 0x10 indicates that incandescent illumination */ 708 /* is possible, bit 0x20 indicates that any scan mode is to be ignored */ 709 typedef enum { 710 i1p_norm = 0x10, /* Normal measurement for current mode */ 711 i1p2_UV = 0x01, /* Measurement using UV LED instead of incandescent (Rev E) */ 712 i1p_cal = 0x32, /* No scan, with current mode illumination */ 713 i1p_dark_cal = 0x23, /* No scan, no illumination */ 714 i1p2_wl_cal = 0x24 /* No scan, wavelength reference LED illumination (Rev E) */ 715 } i1p_mmodif; 716 717 /* Trigger a single measurement cycle. This could be a dark calibration, */ 718 /* a calibration, or a real measurement. Used to create the higher */ 719 /* level "calibrate" and "take reading" functions. */ 720 /* The setup for the operation is in the current mode state. */ 721 /* The called then needs to call i1pro_readmeasurement() */ 722 i1pro_code 723 i1pro_trigger_one_measure( 724 i1pro *p, 725 int nummeas, /* Number of measurements to make */ 726 double *inttime, /* Integration time to use/used */ 727 int gainmode, /* Gain mode to use, 0 = normal, 1 = high */ 728 i1p_mmodif mmodif /* Measurement modifier enum */ 729 ); 730 731 /* ============================================================ */ 732 /* lower level reading processing */ 733 734 /* Take a buffer full of sensor readings, and convert them to */ 735 /* absolute raw values. Linearise if Rev A..D */ 736 /* Note the rev E darkthresh returned has NOT been converted to an absolute raw value */ 737 i1pro_code i1pro_sens_to_absraw( 738 i1pro *p, 739 double **absraw, /* Array of [nummeas][-1 nraw] value to return */ 740 unsigned char *buf, /* Raw measurement data must be 256 * nummeas */ 741 int nummeas, /* Return number of readings measured */ 742 double inttime, /* Integration time used */ 743 int gainmode, /* Gain mode, 0 = normal, 1 = high */ 744 double *pdarkthresh /* Return a dark threshold value (Rev E) */ 745 ); 746 747 /* Take a raw value, and convert it into an absolute raw value. */ 748 /* Note that linearisation is ignored, since it is assumed to be insignificant */ 749 /* to the black threshold and saturation values. */ 750 double i1pro_raw_to_absraw( 751 i1pro *p, 752 double raw, /* Input value */ 753 double inttime, /* Integration time used */ 754 int gainmode /* Gain mode, 0 = normal, 1 = high */ 755 ); 756 757 /* Take a single set of absolute linearised sensor values and */ 758 /* convert them back into i1pro Rev A..D raw reading values. */ 759 i1pro_code i1pro_absraw_to_meas( 760 i1pro *p, 761 int *meas, /* Return raw measurement data */ 762 double *absraw, /* Array of [-1 nraw] value to process */ 763 double inttime, /* Integration time used */ 764 int gainmode /* Gain mode, 0 = normal, 1 = high */ 765 ); 766 767 /* Average a set of measurements into one. */ 768 /* Return zero if readings are consistent and not saturated. */ 769 /* Return nz with bit 1 set if the readings are not consistent */ 770 /* Return nz with bit 2 set if the readings are saturated */ 771 /* Return the highest individual element. */ 772 /* Return the overall average. */ 773 int i1pro_average_multimeas( 774 i1pro *p, 775 double *avg, /* return average [-1 nraw] */ 776 double **multimeas, /* Array of [nummeas][-1 nraw] value to average */ 777 int nummeas, /* Return number of readings measured */ 778 double *phighest, /* If not NULL, return highest value from all bands and msrmts. */ 779 double *poallavg, /* If not NULL, return overall average of bands and measurements */ 780 double satthresh, /* Sauration threshold, 0 for none */ 781 double darkthresh /* Dark threshold (used for consistency check scaling) */ 782 ); 783 784 /* Recognise the required number of ref/trans patch locations, */ 785 /* and average the measurements within each patch. */ 786 /* Return flags zero if readings are consistent and not saturated. */ 787 /* Return flags nz with bit 1 set if the readings are not consistent */ 788 /* Return flags nz with bit 2 set if the readings are saturated */ 789 /* Return the highest individual element. */ 790 i1pro_code i1pro_extract_patches_multimeas( 791 i1pro *p, 792 int *flags, /* return flags */ 793 double **pavg, /* return patch average [naptch][-1 nraw] */ 794 int npatch, /* number of patches to recognise */ 795 double **multimeas, /* Array of [nummeas][-1 nraw] value to extract from */ 796 int nummeas, /* number of readings to recognise them from */ 797 double *phighest, /* If not NULL, return highest value from all bands and msrmts. */ 798 double satthresh, /* Sauration threshold, 0 for none */ 799 double inttime /* Integration time (used to adjust consistency threshold) */ 800 ); 801 802 /* Recognise any flashes in the readings, and */ 803 /* and average their values together as well as summing their duration. */ 804 /* Return nz on an error */ 805 i1pro_code i1pro_extract_patches_flash( 806 i1pro *p, 807 int *flags, /* return flags */ 808 double *duration, /* return duration */ 809 double *pavg, /* return patch average [-1 nraw] */ 810 double **multimeas, /* Array of [nummeas][-1 nraw] value to extract from */ 811 int nummeas, /* number of readings made */ 812 double inttime /* Integration time (used to compute duration) */ 813 ); 814 815 /* Subtract one absraw array from another */ 816 /* If Rev E, also adjust according to shielded cells, and linearise. */ 817 void i1pro_sub_absraw( 818 i1pro *p, 819 int nummeas, /* Return number of readings measured */ 820 double inttime, /* Integration time used */ 821 int gainmode, /* Gain mode, 0 = normal, 1 = high */ 822 double **absraw, /* Source/Desination array [-1 nraw] */ 823 double *sub /* Black value to subtract [-1 nraw] */ 824 ); 825 826 /* Convert an absraw array from raw wavelengths to output wavelenths */ 827 /* for the current resolution */ 828 void i1pro_absraw_to_abswav( 829 i1pro *p, 830 int highres, 831 int reflective, 832 int nummeas, /* Return number of readings measured */ 833 double **abswav, /* Desination array [nwav] */ 834 double **absraw /* Source array [-1 nraw] */ 835 ); 836 837 /* Convert an abswav array of output wavelengths to scaled output readings. */ 838 void i1pro_scale_specrd( 839 i1pro *p, 840 double **outspecrd, /* Destination */ 841 int numpatches, /* Number of readings/patches */ 842 double **inspecrd /* Source */ 843 ); 844 845 /* Convert from spectral to XYZ, and transfer to the ipatch array */ 846 i1pro_code i1pro_conv2XYZ( 847 i1pro *p, 848 ipatch *vals, /* Values to return */ 849 int nvals, /* Number of values */ 850 double **specrd, /* Spectral readings */ 851 instClamping clamp /* Clamp XYZ/Lab to be +ve */ 852 ); 853 854 /* Check a reflective white measurement, and check that */ 855 /* it seems reasonable. Return inst_ok if it is, error if not. */ 856 i1pro_code i1pro_check_white_reference1( 857 i1pro *p, 858 double *abswav /* Measurement to check */ 859 ); 860 861 /* Compute a calibration factor given the reading of the white reference. */ 862 /* Return I1PRO_RD_TRANSWHITEWARN if any of the transmission wavelengths are low */ 863 i1pro_code i1pro_compute_white_cal( 864 i1pro *p, 865 double *cal_factor0, /* [nwav0] Calibration factor to compute */ 866 double *white_ref0, /* [nwav0] White reference to aim for, NULL for 1.0 */ 867 double *white_read0, /* [nwav0] The white that was read */ 868 double *cal_factor1, /* [nwav1] Calibration factor to compute */ 869 double *white_ref1, /* [nwav1] White reference to aim for, NULL for 1.0 */ 870 double *white_read1, /* [nwav1] The white that was read */ 871 int do_emis_ft /* Do emission hires fine tune with this info. */ 872 ); 873 874 /* For adaptive mode, compute a new integration time and gain mode */ 875 /* in order to optimise the sensor values. */ 876 i1pro_code i1pro_optimise_sensor( 877 i1pro *p, 878 double *pnew_int_time, 879 int *pnew_gain_mode, 880 double cur_int_time, 881 int cur_gain_mode, 882 int permithg, /* nz to permit switching to high gain mode */ 883 int permitclip, /* nz to permit clipping out of range int_time, else error */ 884 double targoscale, /* Optimising target scale ( <= 1.0) */ 885 double scale /* scale needed of current int time to reach optimum */ 886 ); 887 888 /* Compute the number of measurements needed, given the target */ 889 /* time and integration time. Will return 0 if target time is 0 */ 890 int i1pro_comp_nummeas( 891 i1pro *p, 892 double meas_time, 893 double int_time 894 ); 895 896 /* Convert the dark interpolation data to a useful state */ 897 void i1pro_prepare_idark(i1pro *p); 898 899 /* Create the dark reference for the given integration time and gain */ 900 /* by interpolating from the 4 readings taken earlier. */ 901 i1pro_code i1pro_interp_dark( 902 i1pro *p, 903 double *result, /* Put result of interpolation here */ 904 double inttime, 905 int gainmode 906 ); 907 908 /* Create or re-create high resolution mode references */ 909 i1pro_code i1pro_create_hr(i1pro *p); 910 911 /* Set the noinitcalib mode */ 912 void i1pro_set_noinitcalib(i1pro *p, int v, int losecs); 913 914 /* Set the trigger config */ 915 void i1pro_set_trig(i1pro *p, inst_opt_type trig); 916 917 /* Return the trigger config */ 918 inst_opt_type i1pro_get_trig(i1pro *p); 919 920 /* Set the trigger return */ 921 void i1pro_set_trigret(i1pro *p, int val); 922 923 /* Switch thread handler */ 924 int i1pro_switch_thread(void *pp); 925 926 /* ============================================================ */ 927 /* Low level i1pro commands */ 928 929 /* USB Commands */ 930 931 /* Reset the instrument */ 932 i1pro_code 933 i1pro_reset( 934 struct _i1pro *p, 935 int mask /* reset mask ?. Known values ar 0x1f, 0x07, 0x01 */ 936 ); 937 938 /* Read from the EEProm */ 939 i1pro_code 940 i1pro_readEEProm( 941 struct _i1pro *p, 942 unsigned char *buf, /* Where to read it to */ 943 int addr, /* Address in EEprom to read from */ 944 int size /* Number of bytes to read (max 65535) */ 945 ); 946 947 /* Write to the EEProm */ 948 i1pro_code 949 i1pro_writeEEProm( 950 i1pro *p, 951 unsigned char *buf, /* Where to write from */ 952 int addr, /* Address in EEprom to write to */ 953 int size /* Number of bytes to write (max 65535) */ 954 ); 955 956 /* Get the miscelanious status */ 957 /* return pointers may be NULL if not needed. */ 958 i1pro_code 959 i1pro_getmisc( 960 i1pro *p, 961 int *fwrev, /* Return the hardware version number */ 962 int *unkn1, /* Unknown status, set after doing a measurement */ 963 int *maxpve, /* Maximum positive value in sensor readings */ 964 int *unkn3, /* Unknown status, usually 1 */ 965 int *powmode /* 0 = high power mode, 8 = low power mode */ 966 ); 967 968 /* Get the current measurement parameters */ 969 /* return pointers may be NULL if not needed. */ 970 i1pro_code 971 i1pro_getmeasparams( 972 i1pro *p, 973 int *intclocks, /* Number of integration clocks (Up to 65535) */ 974 int *lampclocks, /* Number of lamp turn on sub-clocks (Up to 65535) */ 975 int *nummeas, /* Number of measurements (Up to 65535) */ 976 int *measmodeflags /* Measurement mode flags (4 bits, see below) */ 977 ); 978 979 /* These bits correspond with the instruction flags */ 980 #define I1PRO_MMF_SCAN 0x01 /* Scan mode bit, else spot mode */ 981 #define I1PRO_MMF_NOLAMP 0x02 /* No lamp mode, else use illumination lamp */ 982 #define I1PRO_MMF_LOWGAIN 0x04 /* Normal gain mode, else high gain */ 983 #define I1PRO_MMF_UNKN 0x08 /* Unknown. Not usually set */ 984 985 /* Scan mode continues measuring until the user releases the button. */ 986 /* (Does scan mode do the given number of readings as a minimum ???) */ 987 /* Spot mode does the given number of readings. */ 988 989 /* Set the measurement parameters */ 990 i1pro_code 991 i1pro_setmeasparams( 992 i1pro *p, 993 int intclocks, /* Number of integration clocks */ 994 int lampclocks, /* Number of lamp turn on sub-clocks */ 995 int nummeas, /* Number of measurements to make */ 996 int measmodeflags /* Measurement mode flags */ 997 ); 998 999 /* Trigger a measurement after the delay in msec. */ 1000 /* The actual return code will be in m->trig_rv after the delay */ 1001 i1pro_code 1002 i1pro_triggermeasure(i1pro *p, int delay); 1003 1004 1005 /* Read a measurements results */ 1006 static i1pro_code 1007 i1pro_readmeasurement( 1008 i1pro *p, 1009 int inummeas, /* Initial number of measurements to expect */ 1010 int scanflag, /* NZ if in scan mode to continue reading */ 1011 unsigned char *buf, /* Where to read it to */ 1012 int bsize, /* Bytes available in buffer */ 1013 int *nummeas, /* Return number of readings measured */ 1014 i1p_mmodif mmodif /* Measurement modifier enum */ 1015 ); 1016 1017 1018 /* Set the measurement clock mode */ 1019 /* Version >= 301 only */ 1020 i1pro_code 1021 i1pro_setmcmode( 1022 i1pro *p, 1023 int mcmode /* Measurement clock mode, 1..mxmcmode */ 1024 ); 1025 1026 1027 /* Get the current measurement clock mode */ 1028 /* Return pointers may be NULL if not needed. */ 1029 /* Version >= 301 only */ 1030 i1pro_code 1031 i1pro_getmcmode( 1032 i1pro *p, 1033 int *maxmcmode, /* mcmode must be < maxmcmode */ 1034 int *mcmode, /* readback current mcmode */ 1035 int *subclkdiv, /* Sub clock divider ratio */ 1036 int *intclkusec, /* Integration clock in usec */ 1037 int *subtmode /* Subtract mode on read using average of value 127 */ 1038 ); 1039 1040 /* ============================================================ */ 1041 /* Low level Rev E commands */ 1042 1043 /* Get the EEProm size */ 1044 i1pro_code 1045 i1pro2_geteesize( 1046 i1pro *p, 1047 int *eesize 1048 ); 1049 1050 /* Get the Chip ID (Also valid for Rev D) */ 1051 /* Only returns a valid result after reading the EEProm ! */ 1052 i1pro_code 1053 i1pro2_getchipid( 1054 i1pro *p, 1055 unsigned char chipid[8] 1056 ); 1057 1058 /* Get Extra Parameters */ 1059 i1pro_code 1060 i1pro2_getmeaschar( 1061 i1pro *p, 1062 int *clkusec, 1063 int *xraw, 1064 int *nraw, 1065 int *subdiv 1066 ); 1067 1068 /* These bits correspond with the instruction flags */ 1069 #define I1PRO2_MMF_LAMP 0x0100 /* Use the Incandescent Lamp as the illuminant */ 1070 #define I1PRO2_MMF_UV_LED 0x0200 /* Use the Ultra Violet LED as the illuminant */ 1071 #define I1PRO2_MMF_WL_LED 0x0300 /* Use the Wavelength Reference LED as the illuminant */ 1072 1073 //#define I1PRO2_MMF_HIGHGAIN 0x0000 /* Rev E mode has no high gain mode ? */ 1074 #define I1PRO2_MMF_SCAN 0x0001 /* Scan mode bit, else spot mode */ 1075 #define I1PRO2_MMF_RULER_START 0x0004 /* Start ruler tracking in scan mode */ 1076 #define I1PRO2_MMF_RULER_END 0x0008 /* End ruler tracking in scan mode */ 1077 1078 /* Delayed trigger implementation, called from thread */ 1079 /* We assume that the Rev E measurement parameters have been set in */ 1080 /* the i1proimp structure c_* values */ 1081 static int 1082 i1pro2_delayed_trigger(void *pp); 1083 1084 /* Trigger a measurement after the nominated delay */ 1085 /* The actual return code will be in m->trig_rv after the delay. */ 1086 /* This allows us to start the measurement read before the trigger, */ 1087 /* ensuring that process scheduling latency can't cause the read to fail. */ 1088 i1pro_code 1089 i1pro2_triggermeasure(i1pro *p, int delay); 1090 1091 1092 /* Get the UV before and after measurement voltage drop */ 1093 i1pro_code 1094 i1pro2_getUVvolts( 1095 i1pro *p, 1096 int *before, 1097 int *after 1098 ); 1099 1100 /* Terminate Ruler tracking (???) */ 1101 /* The parameter seems to be always 0 ? */ 1102 static int 1103 i1pro2_stop_ruler(void *pp, int parm); 1104 1105 1106 /* Send a LED sequence */ 1107 static int 1108 i1pro2_indLEDseq(void *pp, unsigned char *buf, int size); 1109 1110 /* Turn indicator LEDs off */ 1111 static int 1112 i1pro2_indLEDoff(void *pp); 1113 1114 // ~~~~9999 1115 1116 /* - - - - - - - - - - - - - - - - - - - - - - - - - - */ 1117 1118 /* Wait for a reply triggered by a button press */ 1119 i1pro_code i1pro_waitfor_switch(i1pro *p, double top); 1120 1121 /* Wait for a reply triggered by a button press (thread version) */ 1122 i1pro_code i1pro_waitfor_switch_th(i1pro *p, double top); 1123 1124 /* Terminate button handling ? */ 1125 i1pro_code i1pro_terminate_switch(i1pro *p); 1126 1127 /* -------------------------------------------------- */ 1128 /* Key/Value storage */ 1129 1130 /* Calibration data storage class */ 1131 /* The i1pro stores all it's calibration information */ 1132 /* using a key/values arrangement. */ 1133 /* We provide a place to store and retrieve that information here. */ 1134 1135 /* We haven't implemented a full set of functions - it's not possible */ 1136 /* to create the store from scratch, re-allocate key/value entries, */ 1137 /* resize entries or anything else of this sort. */ 1138 1139 1140 /* Data Key identifiers */ 1141 1142 /* Note that array sizes are nominal. They could change with */ 1143 /* driver and instrument changes. */ 1144 1145 /* "Log" data is keys 2710-2715, 271a-271d, 2724-2725 */ 1146 1147 /* The log data seems largly devoted to the last remission spot calibration */ 1148 /* or reading, and some general statistics. */ 1149 1150 typedef enum { 1151 1152 // Note 0x2710 = 10000 1153 key_meascount = 0x2715, /* int, Total Measure (Emis/Remis/Ambient/Trans/Cal) count */ 1154 /* but not the pre-Remission dark calibration. */ 1155 key_darkreading = 0x271a, /* int[128] Remspotcal Dark data */ 1156 key_whitereading= 0x271b, /* int[128] Remspotcal White data */ 1157 key_gainmode = 0x271c, /* int - Remspotcal gain mode, Values 1 (normal) or 0 (high) */ 1158 key_inttime = 0x271d, /* double - Remspotcal integration time */ 1159 key_caldate = 0x2724, /* int date - Remspotcal last calibration date */ 1160 key_calcount = 0x2725, /* int - Remission spot measure Count at last Remspotcal. */ 1161 key_checksum = 0x2710, /* int - Log checksum */ 1162 key_rpinttime = 0x2711, /* double - Last remision spot reading integration time */ 1163 key_rpcount = 0x2712, /* int - Remission spot measure Count */ 1164 key_acount = 0x2713, /* int - Remission scan measure Count (??) */ 1165 key_lampage = 0x2714, /* double - Total lamp usage time (??) */ 1166 1167 /* Duplicate of above, keys += 0x3E8 (+1000) */ 1168 // (0x2af8 = 11000) 1169 1170 key_2logoff = 0x03e8, /* Offset from first to second copy of log keys */ 1171 1172 1173 /* Calibration parameters are 3e8-3ec, 44c-44e, 4b4-4b5, 4b7-4b8, 4bb-4bd, */ 1174 /* 4c5-4c6, bb9-bba, bbf-bc6, fa0 */ 1175 1176 // Note 0x3e8 = 1000 1177 // 0x44c = 1100 1178 // 0x4b0 = 1200 1179 // 0xbb8 = 3000 1180 // 0xfa0 = 4000 1181 1182 /* Linearisation uses Polinomial equation, ie: y = c0 + c1 * x + c2 * x^2 + c3 * x^3 etc. */ 1183 /* and is applied to the raw (integer) sensor data. */ 1184 1185 key_ng_lin = 0x03e8, /* double[4] */ 1186 /* Normal gain polinomial linearisation coefficients */ 1187 1188 key_hg_lin = 0x03e9, /* double[4] */ 1189 /* High gain polinomial linearisation coefficients */ 1190 1191 key_min_int_time= 0x04c5, /* double - Minumum integration time */ 1192 /* default 8.84000025689601900e-003 in EEProm */ 1193 /* Overwritten in MinilinoLowLevelDriver constructor: */ 1194 /* Default to 8.84000025689601900e-003 if cpldrev == 101 Ver A */ 1195 /* Default to 4.71600005403161050e-003 if cpldrev == 301 Ver B+ */ 1196 1197 key_max_int_time= 0x04c6, /* double - Maximum integration time */ 1198 /* Typically 4.4563798904418945 */ 1199 1200 key_mtx_index = 0x03ea, /* int[36] */ 1201 /* Matrix CCD sample index for each out wavelength */ 1202 /* 380 - 730nm */ 1203 1204 key_mtx_nocoef = 0x03eb, /* int[36] */ 1205 /* Number of matrix cooeficients for each out wavelength */ 1206 1207 key_mtx_coef = 0x03ec, /* double[36 x 16] */ 1208 /* Matrix cooeficients to compute each wavelength */ 1209 1210 key_0bb9 = 0x0bb9, /* int - value typically -1*/ 1211 key_0bba = 0x0bba, /* int - value typically -1 */ 1212 1213 key_white_ref = 0x044c, /* double[36] */ 1214 /* White calibration tile reflectance values */ 1215 1216 key_emis_coef = 0x044d, /* double[36] */ 1217 /* Emission calibration coefficients */ 1218 1219 key_amb_coef = 0x044e, /* double[36] */ 1220 /* Ambient light calibration values (compound with Emission) */ 1221 /* May be < 36, values -1.0 if Ambient is not supported */ 1222 1223 key_0fa0 = 0x0fa0, /* int */ 1224 key_0bbf = 0x0bbf, /* int */ 1225 1226 key_cpldrev = 0x0bc0, /* int - Firmware revision number */ 1227 1228 key_0bc1 = 0x0bc1, /* int[5] */ 1229 1230 key_capabilities= 0x0bc2, /* int */ 1231 /* Capabilities flag ? */ 1232 /* ie. has Ambient capability if val & 0x6000 != 0 */ 1233 1234 key_0bc3 = 0x0bc3, /* int */ 1235 1236 key_physfilt = 0x0bc4, /* int - physical filter */ 1237 /* 0x80 == no filter */ 1238 /* 0x82 == UV filter */ 1239 1240 key_0bc5 = 0x0bc5, /* int */ 1241 1242 key_0bc6 = 0x0bc6, /* double */ 1243 1244 key_sens_target = 0x04b4, /* int - sensor optimal target value */ 1245 /* typical value 37000 */ 1246 1247 key_sens_dark = 0x04b5, /* int - sensor dark reference threshold */ 1248 /* typically value 150 */ 1249 1250 key_ng_sens_sat = 0x04b7, /* int */ 1251 /* Normal gain sensor saturated threshold */ 1252 /* typically value 45000 */ 1253 1254 key_hg_sens_sat = 0x04b8, /* int */ 1255 /* High gain sensor saturated threshold */ 1256 /* typically value 45000 */ 1257 1258 key_serno = 0x04bb, /* int - serial number */ 1259 1260 key_dom = 0x04bc, /* int - unknown */ 1261 /* Possibly date of manufacture DDMMYYYY ? */ 1262 /* ie., decimal 10072002 would be 10/7/2002 ? */ 1263 1264 key_hg_factor = 0x04bd, /* double */ 1265 /* High gain mode gain factor, ie 9.5572.. */ 1266 1267 1268 key2_chip_id = 0x2ee1, /* uchar[8], chip id */ 1269 1270 key2_capabilities = 0x2ee2, /* int, capabilities bits */ 1271 1272 key2_sens_target = 0x2eeb, /* int - sensor optimal target value ? */ 1273 /* typical value 30000 */ 1274 1275 key2_sens_sat = 0x2eec, /* int - sensor saturation value ? */ 1276 /* typical value 55000 */ 1277 1278 key2_uvcal_intt = 0x2ef9, /* double, UV calibration initial integration time */ 1279 1280 key2_wlcal_intt = 0x2efa, /* double, wavelength calibration initial integration time */ 1281 1282 key2_wlcal_minlev = 0x2efe, /* int, wavelength calibration normalized minimum peak level */ 1283 1284 key2_wlcal_spec = 0x2f44, /* double[50], wavelength calibration reference spectrum */ 1285 1286 key2_wlcal_ooff = 0x2f45, /* int, Reference WL Led spectral offset */ 1287 1288 key2_wlcal_fwhm = 0x2f4e, /* double, wavelength calibration nominal fwhm (nm) */ 1289 key2_wlcal_fwhm_tol = 0x2f4f, /* double, wavelength calibration fwhm tollerance (nm) */ 1290 1291 key2_wlcal_max = 0x2f46, /* double, wavelength calibration error limit, ie. 5.0 */ 1292 1293 key2_wlpoly_1 = 0x2f62, /* double[4], CCD bin to wavelength polinomial #1 (normal) */ 1294 key2_wlpoly_2 = 0x2f63, /* double[4], CCD bin to wavelength polinomial #2 ??? */ 1295 1296 key2_straylight = 0x2f58, /* int16[36][6] signed stray light values */ 1297 key2_straylight_scale = 0x2f59 /* double stray light scale factor */ 1298 1299 } i1key; 1300 1301 1302 /* Data type */ 1303 typedef enum { 1304 i1_dtype_unknown = 0, 1305 i1_dtype_char = 1, /* Array of bytes */ 1306 i1_dtype_short = 2, /* 16 bit int, date */ 1307 i1_dtype_int = 3, /* 32 bit int, date */ 1308 i1_dtype_double = 4, /* 64 bit double, serialized as 32 bit float */ 1309 i1_dtype_section = 5 /* End of section marker */ 1310 } i1_dtype; 1311 1312 /* A key/value entry */ 1313 struct _i1keyv { 1314 void *data; /* Array of data */ 1315 unsigned int count; /* Count of data */ 1316 i1_dtype type; /* Type of data */ 1317 int addr; /* EEProm address */ 1318 int size; /* Size in bytes */ 1319 int key; /* 16 bit key */ 1320 struct _i1keyv *next; /* Link to next keyv */ 1321 }; typedef struct _i1keyv i1keyv; 1322 1323 struct _i1data { 1324 /* private: */ 1325 i1pro *p; 1326 i1proimp *m; 1327 1328 a1log *log; /* reference to instrument log */ 1329 i1keyv *head; /* Pointer to first in chain of keyv */ 1330 i1keyv *last; /* Pointer to last in chain of keyv */ 1331 1332 /* public: */ 1333 1334 /* Search the linked list for the given key */ 1335 /* Return NULL if not found */ 1336 i1keyv *(* find_key)(struct _i1data *d, i1key key); 1337 1338 /* Search the linked list for the given key and */ 1339 /* return it, or create the key if it doesn't exist. */ 1340 /* Return NULL on error */ 1341 i1keyv *(* make_key)(struct _i1data *d, i1key key); 1342 1343 /* Return type of data associated with key. Return i1_dtype_unknown if not found */ 1344 i1_dtype (*get_type)(struct _i1data *d, i1key key); 1345 1346 /* Return the number of data items in a keyv. Return 0 if not found */ 1347 unsigned int (*get_count)(struct _i1data *d, i1key key); 1348 1349 /* Return a int pointer to the 16 bit int data for the key. */ 1350 /* Optionally return the number of items too. */ 1351 /* Return NULL if not found or wrong type */ 1352 int *(*get_shorts)(struct _i1data *d, unsigned int *count, i1key key); 1353 1354 /* Return a pointer to the 32 bit int data for the key. */ 1355 /* Optionally return the number of items too. */ 1356 /* Return NULL if not found or wrong type */ 1357 int *(*get_ints)(struct _i1data *d, unsigned int *count, i1key key); 1358 1359 /* Return a pointer to the double data for the key. */ 1360 /* Optionally return the number of items too. */ 1361 /* Return NULL if not found or wrong type */ 1362 double *(*get_doubles)(struct _i1data *d, unsigned int *count, i1key key); 1363 1364 1365 /* Return pointer to one of the int data for the key. */ 1366 /* Return NULL if not found or wrong type or out of range index. */ 1367 int *(*get_int)(struct _i1data *d, i1key key, unsigned int index); 1368 1369 /* Return pointer to one of the double data for the key. */ 1370 /* Return NULL if not found or wrong type or out of range index. */ 1371 double *(*get_double)(struct _i1data *d, i1key key, double *data, unsigned int index); 1372 1373 1374 /* Un-serialize a char buffer into an i1key keyv */ 1375 /* (Don't change addr if its is -1) */ 1376 i1pro_code (*unser_ints)(struct _i1data *d, i1key key, int addr, 1377 unsigned char *buf, unsigned int size); 1378 1379 /* Un-serialize a char buffer of floats into a double keyv */ 1380 /* (Don't change addr if its is -1) */ 1381 i1pro_code (*unser_doubles)(struct _i1data *d, i1key key, int addr, 1382 unsigned char *buf, unsigned int size); 1383 1384 1385 /* Serialize an i1key keyv into a char buffer. Error if it is outside the buffer */ 1386 i1pro_code (*ser_ints)(struct _i1data *d, i1keyv *k, unsigned char *buf, unsigned int size); 1387 1388 /* Serialize a double keyv as floats into a char buffer. Error if the buf is not big enough */ 1389 i1pro_code (*ser_doubles)(struct _i1data *d, i1keyv *k, unsigned char *buf, unsigned int size); 1390 1391 /* Initialise the data from the EEprom contents */ 1392 i1pro_code (*parse_eeprom)(struct _i1data *d, unsigned char *buf, unsigned int len, int extra); 1393 1394 1395 /* Serialise all the keys up to the first marker into a buffer. */ 1396 i1pro_code (*prep_section1)(struct _i1data *d, unsigned char **buf, unsigned int *len); 1397 1398 /* Copy an array full of ints to the key (must be same size as existing) */ 1399 i1pro_code (*add_ints)(struct _i1data *d, i1key key, int *data, unsigned int count); 1400 1401 /* Copy an array full of doubles to the key (must be same size as existing) */ 1402 i1pro_code (*add_doubles)(struct _i1data *d, i1key key, double *data, unsigned int count); 1403 1404 1405 /* Destroy ourselves */ 1406 void (*del)(struct _i1data *d); 1407 1408 /* Other utility methods */ 1409 1410 /* Return the data type for the given key identifier */ 1411 i1_dtype (*det_type)(struct _i1data *d, i1key key); 1412 1413 /* Given an index starting at 0, return the matching key code */ 1414 /* for keys that get checksummed. Return 0 if outside range. */ 1415 i1key (*chsum_keys)(struct _i1data *d, int index); 1416 1417 /* Compute a checksum. */ 1418 int (*checksum)(struct _i1data *d, i1key keyoffset); 1419 1420 }; typedef struct _i1data i1data; 1421 1422 /* Constructor. Construct from the EEprom contents */ 1423 extern i1data *new_i1data(i1proimp *m); 1424 1425 #ifdef __cplusplus 1426 } 1427 #endif 1428 1429 #define I1PRO_IMP 1430 #endif /* I1PRO_IMP */ 1431