summaryrefslogtreecommitdiff
path: root/spectro/i1pro_imp.h
diff options
context:
space:
mode:
Diffstat (limited to 'spectro/i1pro_imp.h')
-rw-r--r--spectro/i1pro_imp.h1376
1 files changed, 1376 insertions, 0 deletions
diff --git a/spectro/i1pro_imp.h b/spectro/i1pro_imp.h
new file mode 100644
index 0000000..64296b2
--- /dev/null
+++ b/spectro/i1pro_imp.h
@@ -0,0 +1,1376 @@
+#ifndef I1PRO_IMP_H
+
+/*
+ * Argyll Color Correction System
+ *
+ * Gretag i1Pro implementation defines
+ *
+ * Author: Graeme W. Gill
+ * Date: 20/12/2006
+ *
+ * Copyright 2006 - 2013 Graeme W. Gill
+ * All rights reserved.
+ *
+ * This material is licenced under the GNU GENERAL PUBLIC LICENSE Version 2 or later :-
+ * see the License2.txt file for licencing details.
+ */
+
+/*
+ If you make use of the instrument driver code here, please note
+ that it is the author(s) of the code who take responsibility
+ for its operation. Any problems or queries regarding driving
+ instruments with the Argyll drivers, should be directed to
+ the Argyll's author(s), and not to any other party.
+
+ If there is some instrument feature or function that you
+ would like supported here, it is recommended that you
+ contact Argyll's author(s) first, rather than attempt to
+ modify the software yourself, if you don't have firm knowledge
+ of the instrument communicate protocols. There is a chance
+ that an instrument could be damaged by an incautious command
+ sequence, and the instrument companies generally cannot and
+ will not support developers that they have not qualified
+ and agreed to support.
+ */
+
+/* Implementation resources for i1pro driver */
+
+/* -------------------------------------------------- */
+/* Implementation class */
+
+typedef int i1pro_code; /* Type to use for error codes */
+
+/* I1PRO mode state. This is implementation data that */
+/* depends on the mode the instrument is in. */
+/* Each mode has a separate calibration, and configured instrument state. */
+
+typedef enum {
+ i1p_refl_spot = 0,
+ i1p_refl_scan = 1,
+ i1p_emiss_spot_na = 2,
+ i1p_emiss_spot = 3,
+ i1p_emiss_scan = 4,
+ i1p_amb_spot = 5,
+ i1p_amb_flash = 6,
+ i1p_trans_spot = 7,
+ i1p_trans_scan = 8,
+ i1p_no_modes = 9 /* Number of modes */
+} i1p_mode;
+
+struct _i1pro_state {
+ i1p_mode mode; /* Mode number */
+
+ /* Just one of the following 3 must always be set */
+ int emiss; /* flag - Emissive mode */
+ int trans; /* flag - Transmissive mode */
+ int reflective; /* flag - Reflective mode */
+
+ /* The following can be added to emiss */
+ int ambient; /* flag - Ambient mode */
+
+ /* The following can be added to any of the 3: */
+ int scan; /* flag - Scanning mode */
+ int adaptive; /* flag - adaptive mode */
+
+ /* The following can be added to scan: */
+ int flash; /* flag - Flash detection from scan mode */
+
+ /* Configuration & state information */
+ double targoscale; /* Optimal reading scale factor <= 1.0 */
+ /* Would determine scan sample rate, except we're not doing it that way! */
+ double targmaxitime;/* maximum integration time to aim for (ie. 2.0 sec) */
+ double targoscale2;/* Proportion of targoscale allowed to meed targmaxitime */
+ int gainmode; /* Gain mode, 0 = normal, 1 = high */
+ double inttime; /* Integration time */
+ double lamptime; /* Lamp turn on time */
+
+ double dadaptime; /* Target adaptive dark read time - sets number of readings */
+ double wadaptime; /* Target adaptive white/sample read time - sets number of readings */
+
+ double dcaltime; /* Target dark calibration time - sets number of readings */
+ double wcaltime; /* Target white calibration time - sets number of readings */
+
+ double dreadtime; /* Target dark on-the-fly cal time - sets number of readings */
+ double wreadtime; /* Target white/sample reading time - sets number of readings */
+
+ double maxscantime; /* Maximum scan time sets buffer size allocated */
+
+ double min_wl; /* Minimum wavelegth to report for this mode */
+
+ /* calibration information for this mode */
+ int wl_valid; /* wavelength calibration factor valid */
+ time_t wldate; /* Date/time of last wavelength calibration */
+ double wl_led_off; /* Wavelength LED reference spectrum current offset */
+
+ int dark_valid; /* dark calibration factor valid */
+ time_t ddate; /* Date/time of last dark calibration */
+ double dark_int_time; /* Integration time used for dark data */
+ double *dark_data; /* [-1 nraw] of dark level to subtract. Note that the dark value */
+ /* depends on integration time. */
+ int dark_gain_mode; /* Gain mode used for dark data */
+
+ int cal_valid; /* calibration factor valid */
+ time_t cfdate; /* Date/time of last cal factor calibration */
+ double *cal_factor[2]; /* [low res, high res][nwav] calibration scale factor for this mode */
+ double *white_data; /* [-1 nraw] linear absolute dark subtracted white data */
+ /* used to compute cal_factor */
+// double *cal_factor1, *cal_factor2; /* (Underlying tables for two resolutions) */
+
+ /* Adaptive emission/transparency black data */
+ int idark_valid; /* idark calibration factors valid */
+ time_t iddate; /* Date/time of last dark idark calibration */
+ double idark_int_time[4];
+ double **idark_data; /* [4][-1 nraw] of dark level for inttime/gains of : */
+ /* 0.01 norm, 4.0 norm, 0.01 high, 2.0 high */
+
+ int want_calib; /* Want White calibration at start */
+ int want_dcalib; /* Want Dark Calibration at start */
+
+ /* Display mode calibration state (emmis && !scan && !adaptive) */
+ int dispswap; /* 0 = default time, 1 = dark_int_time2, 2 = dark_int_time3 */
+ double done_dintsel; /* A display integration time selection has been done */
+ time_t diseldate; /* Date/time of last display integration time selection */
+ double dcaltime2; /* Target dark calibration time - sets number of readings */
+ double dark_int_time2; /* Integration time used for dark data 2 */
+ double *dark_data2; /* [-1 nraw] of dark level to subtract for dark_int_time2. */
+ double dcaltime3; /* Target dark calibration time - sets number of readings */
+ double dark_int_time3; /* Integration time used for dark data 3 */
+ double *dark_data3; /* [-1 nraw] of dark level to subtract for dark_int_time3. */
+
+}; typedef struct _i1pro_state i1pro_state;
+
+/* Pointers to the three tables that allow a raw to wave filter conversion */
+typedef struct {
+ int *index; /* [nwav] Matrix CCD sample starting index for each out wavelength */
+ int *nocoef; /* [nwav] Number of matrix cooeficients for each out wavelength */
+ double *coef; /* [nwav * mtx_nocoef] Matrix cooeficients to compute each wavelength */
+} i1pro_r2wtab;
+
+/* RevE capability bits */
+#define I1PRO_CAP2_AMBIENT 0x01 /* Has ambient measurement capability */
+#define I1PRO_CAP2_WL_LED 0x02 /* Has wavelenght LED */
+#define I1PRO_CAP2_UV_LED 0x04 /* Has Ultra Violet LED */
+#define I1PRO_CAP2_ZEB_RUL 0x08 /* Has zerbra ruler sensor */
+#define I1PRO_CAP2_IND_LED 0x10 /* Has indicator LEDs */
+#define I1PRO_CAP2_UV_FILT 0x20 /* Has Ultra Violet Filter */
+
+/* I1PRO implementation class */
+struct _i1proimp {
+ i1pro *p;
+
+ /* Misc. and top level */
+ struct _i1data *data; /* EEProm data container */
+ athread *th; /* Switch monitoring thread (NULL if not used) */
+ volatile int switch_count; /* Incremented in thread */
+ volatile int hide_switch; /* Set to supress switch event during read */
+ usb_cancelt cancelt; /* Token to allow cancelling an outstanding I/O */
+ volatile int th_term; /* Terminate thread on next return */
+ volatile int th_termed; /* Thread has terminated */
+ inst_opt_type trig; /* Reading trigger mode */
+ int noinitcalib; /* Disable initial calibration if not essential */
+ int highres; /* High resolution mode */
+ int hr_inited; /* High resolution has been initialized */
+
+ /* Current settings */
+ i1p_mode mmode; /* Current measurement mode selected */
+ i1pro_state ms[i1p_no_modes]; /* Mode state */
+ int spec_en; /* NZ to enable reporting of spectral data */
+ int uv_en; /* NZ to do UV reflective measurement */
+ /* ~~ change this to uv_mode of none, uv, strip1, 2pass */
+
+ double intclkp; /* Integration clock period (typically 68 usec) */
+ int subclkdiv; /* Sub clock divider ratio */
+ int subtmode; /* Reading 127 subtract mode (version 301 or greater) */
+
+ /* Current state of hardware, to avoid uncessary operations */
+ double c_inttime; /* Integration time */
+ double l_inttime; /* Last Integration time (for Rev A+/B quirk fix) */
+ double c_lamptime; /* Lamp turn on time */
+ int c_mcmode; /* special clock mode we're in (if rev >= 301) */
+ int c_intclocks; /* Number of integration clocks (set using setmeasparams() */
+ int c_lampclocks; /* Number of integration clocks (set using setmeasparams() */
+ int c_nummeas; /* Number of measurements (set using setmeasparams() */
+ int c_measmodeflags; /* Measurement mode flags (set using setmeasparams() */
+ int c_measmodeflags2; /* Measurement mode flags Rev E (set using setmeasparams() */
+ unsigned int slamponoff; /* The second last time the lamp was switched from on to off */
+ unsigned int llampoffon; /* The last time the lamp was switched from off to on, in msec */
+ unsigned int llamponoff; /* The last time the lamp was switched from on to off, in msec */
+
+
+ /* Values read from GetMisc() */
+ int fwrev; /* int - Firmware revision number, from getmisc() */
+ /* Used for internal switching ?? */
+ /* 101 = Rev A, 202 = Rev A update, 302 = Rev B, 502 = Rev D */
+ /* 629 = Rev E (i1pro2) */
+
+ int cpldrev; /* int - CPLD revision number in EEProm */
+ /* Not used internaly ???? */
+ /* 101 = Rev A, 2 = Rev A update, 301 = Rev B, 999 = Rev D */
+
+ unsigned char chipid[8]; /* HW serial number - Rev E */
+
+ int eesize; /* EEProm size in bytes */
+ int maxpve; /* Maximum +ve value of Sensor Data + 1 */
+ int powmode; /* Power mode status, 0 = high, 8 = low */
+
+ /* Values from i1pro2_getmeaschar() */
+ double intclkp2; /* Rev E Integration clock period (typically 36 usec) */
+ int subclkdiv2; /* Sub clock divider ratio (typically 136) */
+
+ /* Values read from GetMeasureParameters() - are these needed ? */
+ int r_intclocks; /* Number of integration clocks (read from instrument) */
+ int r_lampclocks; /* Number of lamp turn on sub-clocks (read from instrument) */
+ int r_nummeas; /* Number of measurements (read from instrument) */
+ int r_measmodeflags; /* Measurement mode flags (read from instrument) */
+
+
+ /* Information about the instrument from the EEprom */
+ int serno; /* serial number */
+ char sserno[14]; /* serial number as string */
+ int dom; /* Date of manufacture DDMMYYYY ? */
+ int capabilities; /* Capabilities flag */
+ /* Ambient capability if val & 0x6000 != 0 */
+ int physfilt; /* int - physical filter */
+ /* 0x80 == no filter */
+ /* 0x81 == emission only ?? */
+ /* 0x82 == UV filter */
+ int capabilities2; /* Rev E capabilities - set #defines above */
+ /* Also set for RevA-D */
+
+ /* Underlying calibration information */
+ int nsen; /* Raw + extra sample bands read = 128 for i1pro, 136 for Rev E */
+ /* Rev <= D have exactly 128 */
+ /* Rev E has 134, of which 128 are measurements. */
+ /* 5 are skipped at the start, and 1 at the end */
+ /* The first 4 are used as a dark consistency check. */
+ /* ie. 4 + 1 + 128 + 1 */
+ int nraw; /* Raw sample bands stored = 128 (Must be signed!) */
+ unsigned int nwav[2]; /* [low res, high res] cooked spectrum bands stored, ie = 36 */
+ double wl_short[2]; /* [low res, high res] cooked spectrum bands short wavelength, ie 380 */
+ double wl_long[2]; /* [low res, high res] cooked spectrum bands short wavelength, ie 730 */
+
+ unsigned int nlin0; /* Number in array */
+ double *lin0; /* Array of linearisation polinomial factors, normal gain. */
+
+ unsigned int nlin1; /* Number in array */
+ double *lin1; /* Array of linearisation polinomial factors, high gain. */
+
+ double min_int_time; /* Minimum integration time (secs) */
+ double max_int_time; /* Maximum integration time (secs) */
+
+ i1pro_r2wtab mtx[2][2]; /* Raw to wav filters [normal res, high res][emis/trans, reflective] */
+ /* These are all pointers to tables allocated below */
+
+ i1pro_r2wtab mtx_o; /* Underlying original filters from EEProm calibration info. */
+ i1pro_r2wtab mtx_c[2][2]; /* Underlying allocated for RevE wavelength and hi-res calibrated */
+
+ double *white_ref[2]; /* [low res, high res][nwav] White cal tile reflectance values */
+ double *emis_coef[2]; /* [low res, high res][nwav] Emission cal coefficients */
+ double *amb_coef[2]; /* [low res, high res][nwav] Ambient light cal values */
+ /* (compound with Emission), NULL if ambient not supported */
+
+ double **straylight[2]; /* [nwav][nwav] Stray light convolution matrix (Rev E) */
+
+ double highgain; /* High gain mode gain */
+ double scan_toll_ratio; /* Modifier of scan tollerance */
+
+ int sens_target; /* sensor optimal target value */
+ int sens_dark; /* sensor dark reference threshold */
+ int sens_sat0; /* Normal gain sensor saturated threshold */
+ int sens_sat1; /* High gain sensor saturated threshold */
+
+ /* RevA-D alternative to RevE calibration information */
+ rspl *raw2wav; /* Lookup from CCD index to wavelength, NULL until highres inited */
+
+ /* Rev E calibration information */
+ double wl_cal_inttime; /* Wavelength calibration integration time */
+ double wl_cal_min_level; /* Normalized wavelength calibration minumum peak level */
+ double wl_cal_fwhm; /* Wavelength cal expected FWHM (nm) */
+ double wl_cal_fwhm_tol; /* Wavelength cal expected FWHM tollerance (nm) */
+ double *wl_led_spec; /* Wavelength LED reference spectrum */
+ unsigned int wl_led_count; /* Wavelength LED reference spectrum number of entries */
+ double wl_led_ref_off; /* Wavelength LED reference spectrum ref. offset */
+ double wl_err_max; /* Wavelength error maximum value (ie. 5.0) */
+ double *wlpoly1, *wlpoly2; /* CCD bin to wavelength polinomial equations */
+ /* for reflective and emissive/transmissuce modes respectively. */
+
+ /* log variables */
+ int meascount; /* Total Measure (Emis/Remis/Ambient/Trans/Cal) count */
+ /* but not the pre-Remission dark calibration. */
+ time_t caldate; /* Remspotcal last calibration date */
+ int calcount; /* Remission spot measure count at last Remspotcal. */
+ double rpinttime; /* Last remision spot reading integration time */
+ int rpcount; /* Remission spot measure count */
+ int acount; /* Remission scan measure count (Or all scan ??) */
+ double lampage; /* Total lamp usage time in seconds (??) */
+
+ /* Trigger houskeeping & diagnostics */
+ int transwarn; /* Transmission calibration warning state */
+ int lo_secs; /* Seconds since last opened (from calibration file mod time) */
+ int msec; /* msec_time() at creation */
+ athread *trig_thread; /* Delayed trigger thread */
+ int trig_delay; /* Trigger delay in msec */
+ int tr_t1, tr_t2, tr_t3, tr_t4, tr_t5, tr_t6, tr_t7; /* Trigger/read timing diagnostics */
+ /* 1->2 = time to execute trigger */
+ /* 2->3 = time to between end trigger and start of first read */
+ /* 3->4 = time to exectute first read */
+ /* 6->5 = time between end of second last read and start of last read */
+ int trig_se; /* Delayed trigger icoms error */
+ i1pro_code trig_rv; /* Delayed trigger result */
+
+}; typedef struct _i1proimp i1proimp;
+
+/* Add an implementation structure */
+i1pro_code add_i1proimp(i1pro *p);
+
+/* Destroy implementation structure */
+void del_i1proimp(i1pro *p);
+
+/* ============================================================ */
+/* Error codes returned from i1pro_imp */
+
+/* Note: update i1pro_interp_error() and i1pro_interp_code() in i1pro.c */
+/* if anything of these #defines are added or subtracted */
+
+/* Fake Error codes */
+#define I1PRO_INTERNAL_ERROR 0x71 /* Internal software error */
+#define I1PRO_COMS_FAIL 0x72 /* Communication failure */
+#define I1PRO_UNKNOWN_MODEL 0x73 /* Not an i1pro */
+#define I1PRO_DATA_PARSE_ERROR 0x74 /* Read data parsing error */
+
+#define I1PRO_USER_ABORT 0x75 /* uicallback returned abort */
+#define I1PRO_USER_TRIG 0x76 /* uicallback retuned trigger */
+
+#define I1PRO_UNSUPPORTED 0x79 /* Unsupported function */
+#define I1PRO_CAL_SETUP 0x7A /* Cal. retry with correct setup is needed */
+
+/* Real error code */
+#define I1PRO_OK 0x00
+
+#define I1PRO_DATA_COUNT 0x01 /* count unexpectedly small */
+#define I1PRO_DATA_BUFSIZE 0x02 /* buffer too small */
+#define I1PRO_DATA_MAKE_KEY 0x03 /* creating key failed */
+#define I1PRO_DATA_MEMORY 0x04 /* memory alloc failure */
+#define I1PRO_DATA_KEYNOTFOUND 0x05 /* a key value wasn't found */
+#define I1PRO_DATA_WRONGTYPE 0x06 /* a key is the wrong type */
+#define I1PRO_DATA_KEY_CORRUPT 0x07 /* key table seems to be corrupted */
+#define I1PRO_DATA_KEY_COUNT 0x08 /* key table count is too big or small */
+#define I1PRO_DATA_KEY_UNKNOWN 0x09 /* unknown key type */
+#define I1PRO_DATA_KEY_MEMRANGE 0x0a /* key data is out of range of EEProm */
+#define I1PRO_DATA_KEY_ENDMARK 0x0b /* And end section marker was missing */
+
+/* HW errors */
+#define I1PRO_HW_HIGHPOWERFAIL 0x10 /* Switch to high power mode failed */
+#define I1PRO_HW_EE_SIZE 0x11 /* EEProm is too small */
+#define I1PRO_HW_EE_SHORTREAD 0x12 /* Read fewer EEProm bytes than expected */
+#define I1PRO_HW_EE_SHORTWRITE 0x13 /* Read fewer EEProm bytes than expected */
+#define I1PRO_HW_ME_SHORTREAD 0x14 /* Read measurement bytes than expected */
+#define I1PRO_HW_ME_ODDREAD 0x15 /* Read measurement bytes was not mult 256 */
+#define I1PRO_HW_SW_SHORTREAD 0x16 /* Read less bytes for Switch read than expected */
+#define I1PRO_HW_LED_SHORTWRITE 0x17 /* Wrote fewer LED sequence bytes than expected */
+#define I1PRO_HW_UNEX_SPECPARMS 0x18 /* Unexpacted spectral parameter values */
+#define I1PRO_HW_CALIBINFO 0x19 /* calibration info is missing or corrupted */
+#define I1PRO_WL_TOOLOW 0x1A /* WL calibration measurement too low */
+#define I1PRO_WL_SHAPE 0x1B /* WL calibration measurement shape is wrong */
+#define I1PRO_WL_ERR2BIG 0x1C /* WL calibration correction is too big */
+
+/* Sample read operation errors */
+#define I1PRO_RD_DARKREADINCONS 0x30 /* Dark calibration reading inconsistent */
+#define I1PRO_RD_SENSORSATURATED 0x31 /* Sensor is saturated */
+#define I1PRO_RD_DARKNOTVALID 0x32 /* Dark reading is not valid (too light) */
+#define I1PRO_RD_NEEDS_CAL 0x33 /* Mode needs calibration */
+#define I1PRO_RD_WHITEREADINCONS 0x34 /* White reference readings are inconsistent */
+#define I1PRO_RD_WHITEREFERROR 0x35 /* White reference reading error */
+#define I1PRO_RD_LIGHTTOOLOW 0x36 /* Light level is too low */
+#define I1PRO_RD_LIGHTTOOHIGH 0x37 /* Light level is too high */
+#define I1PRO_RD_SHORTMEAS 0x38 /* Measurment was too short */
+#define I1PRO_RD_READINCONS 0x39 /* Reading is inconsistent */
+#define I1PRO_RD_TRANSWHITERANGE 0x3A /* Transmission white reference is out of range */
+#define I1PRO_RD_NOTENOUGHPATCHES 0x3B /* Not enough patches */
+#define I1PRO_RD_TOOMANYPATCHES 0x3C /* Too many patches */
+#define I1PRO_RD_NOTENOUGHSAMPLES 0x3D /* Not enough samples per patch */
+#define I1PRO_RD_NOFLASHES 0x3E /* No flashes recognized */
+#define I1PRO_RD_NOAMBB4FLASHES 0x3F /* No ambient before flashes found */
+#define I1PRO_RD_NOREFR_FOUND 0x40 /* Unable to measure refresh rate */
+
+/* Internal errors */
+#define I1PRO_INT_NO_COMS 0x50
+#define I1PRO_INT_EETOOBIG 0x51 /* EEProm read size is too big */
+#define I1PRO_INT_ODDREADBUF 0x52 /* Measurment read buffer is not mult 256 */
+#define I1PRO_INT_SMALLREADBUF 0x53 /* Measurment read buffer too small */
+#define I1PRO_INT_INTTOOBIG 0x55 /* Integration time is too big */
+#define I1PRO_INT_INTTOOSMALL 0x56 /* Integration time is too small */
+#define I1PRO_INT_ILLEGALMODE 0x57 /* Illegal measurement mode selected */
+#define I1PRO_INT_WRONGMODE 0x58 /* In wrong mode for request */
+#define I1PRO_INT_ZEROMEASURES 0x59 /* Number of measurements requested is zero */
+#define I1PRO_INT_WRONGPATCHES 0x5A /* Number of patches to match is wrong */
+#define I1PRO_INT_MEASBUFFTOOSMALL 0x5B /* Measurement read buffer is too small */
+#define I1PRO_INT_NOTIMPLEMENTED 0x5C /* Support not implemented */
+#define I1PRO_INT_NOTCALIBRATED 0x5D /* Unexpectedely invalid calibration */
+#define I1PRO_INT_NOINTERPDARK 0x5E /* Need interpolated dark and don't have it */
+#define I1PRO_INT_THREADFAILED 0x5F /* Creation of thread failed */
+#define I1PRO_INT_BUTTONTIMEOUT 0x60 /* Switch status read timed out */
+#define I1PRO_INT_CIECONVFAIL 0x61 /* Creating spectral to CIE converted failed */
+#define I1PRO_INT_PREP_LOG_DATA 0x62 /* Error in preparing log data */
+#define I1PRO_INT_MALLOC 0x63 /* Error in mallocing memory */
+#define I1PRO_INT_CREATE_EEPROM_STORE 0x64 /* Error in creating EEProm store */
+#define I1PRO_INT_SAVE_SUBT_MODE 0x65 /* Can't save calibration if in subt mode */
+#define I1PRO_INT_NO_CAL_TO_SAVE 0x66 /* No calibration data to save */
+#define I1PRO_INT_EEPROM_DATA_MISSING 0x67 /* EEProm data is missing */
+#define I1PRO_INT_NEW_RSPL_FAILED 0x68 /* Creating RSPL object faild */
+#define I1PRO_INT_CAL_SAVE 0x69 /* Unable to save calibration to file */
+#define I1PRO_INT_CAL_RESTORE 0x6A /* Unable to restore calibration from file */
+#define I1PRO_INT_CAL_TOUCH 0x6B /* Unable to touch calibration file */
+#define I1PRO_INT_ADARK_INVALID 0x6C /* Adaptive dark calibration is invalid */
+#define I1PRO_INT_NO_HIGH_GAIN 0x6D /* Rev E mode doesn't support high gain mode */
+#define I1PRO_INT_ASSERT 0x6F /* Internal assert */
+
+int icoms2i1pro_err(int se);
+
+/* ============================================================ */
+/* High level implementatation */
+
+/* Initialise our software state from the hardware */
+i1pro_code i1pro_imp_init(i1pro *p);
+
+/* Return a pointer to the serial number */
+char *i1pro_imp_get_serial_no(i1pro *p);
+
+/* Return non-zero if capable of ambient mode */
+int i1pro_imp_ambient(i1pro *p);
+
+/* Set the measurement mode. It may need calibrating */
+i1pro_code i1pro_imp_set_mode(
+ i1pro *p,
+ i1p_mode mmode, /* i1pro mode to use */
+ inst_mode m); /* full mode mask */
+
+/* Implement get_n_a_cals */
+i1pro_code i1pro_imp_get_n_a_cals(i1pro *p, inst_cal_type *pn_cals, inst_cal_type *pa_cals);
+
+/* Calibrate for the current mode. */
+/* Request an instrument calibration of the current mode. */
+i1pro_code i1pro_imp_calibrate(
+ i1pro *p,
+ inst_cal_type *calt, /* Calibration type to do/remaining */
+ inst_cal_cond *calc, /* Current condition/desired condition */
+ char id[100] /* Condition identifier (ie. white reference ID) */
+);
+
+/* Measure a patch or strip in the current mode. */
+i1pro_code i1pro_imp_measure(
+ i1pro *p,
+ ipatch *val, /* Pointer to array of instrument patch value */
+ int nvals, /* Number of values */
+ instClamping clamp /* Clamp XYZ/Lab to be +ve */
+);
+
+/* Measure the emissive refresh rate */
+i1pro_code i1pro_imp_meas_refrate(
+ i1pro *p,
+ double *ref_rate
+);
+
+/* Given a raw measurement of the wavelength LED, */
+/* Compute the base offset that best fits it to the reference */
+i1pro_code i1pro2_match_wl_meas(i1pro *p, double *pled_off, double *wlraw);
+
+/* Compute standard res downsampling filters */
+/* mtx_index1, mtx_nocoef1, mtx_coef1 given the */
+/* current wl_led_off */
+i1pro_code i1pro2_compute_wav_filters(i1pro *p, int reflective);
+
+/* return nz if high res is supported */
+int i1pro_imp_highres(i1pro *p);
+
+/* Set to high resolution mode */
+i1pro_code i1pro_set_highres(i1pro *p);
+
+/* Set to standard resolution mode */
+i1pro_code i1pro_set_stdres(i1pro *p);
+
+/* Modify the scan consistency tollerance */
+i1pro_code i1pro_set_scan_toll(i1pro *p, double toll_ratio);
+
+
+/* Update the single remission calibration and instrument usage log */
+i1pro_code i1pro_update_log(i1pro *p);
+
+/* Save the reflective spot calibration information to the EEPRom data object. */
+/* Note we don't actually write to the EEProm here! */
+static i1pro_code i1pro_set_log_data(i1pro *p);
+
+/* Restore the reflective spot calibration information from the EEPRom */
+/* Always returns success, even if the restore fails */
+i1pro_code i1pro_restore_refspot_cal(i1pro *p);
+
+
+/* Save the calibration for all modes, stored on local system */
+i1pro_code i1pro_save_calibration(i1pro *p);
+
+/* Restore the all modes calibration from the local system */
+i1pro_code i1pro_restore_calibration(i1pro *p);
+
+/* Update the modification time on the file, so we can */
+/* track when the instrument was last open. */
+i1pro_code i1pro_touch_calibration(i1pro *p);
+
+/* ============================================================ */
+/* Intermediate routines - composite commands/processing */
+
+i1pro_code i1pro_establish_high_power(i1pro *p);
+
+/* Take a dark reference measurement - part 1 */
+i1pro_code i1pro_dark_measure_1(
+ i1pro *p,
+ int nummeas, /* Number of readings to take */
+ double *inttime, /* Integration time to use/used */
+ int gainmode, /* Gain mode to use, 0 = normal, 1 = high */
+ unsigned char *buf, /* USB reading buffer to use */
+ unsigned int bsize /* Size of buffer */
+);
+
+/* Take a dark reference measurement - part 2 */
+i1pro_code i1pro_dark_measure_2(
+ i1pro *p,
+ double *absraw, /* Return array [-1 nraw] of absraw values */
+ int nummeas, /* Number of readings to take */
+ double inttime, /* Integration time to use/used */
+ int gainmode, /* Gain mode to use, 0 = normal, 1 = high */
+ unsigned char *buf, /* raw USB reading buffer to process */
+ unsigned int bsize /* Buffer size to process */
+);
+
+/* Take a dark measurement */
+i1pro_code i1pro_dark_measure(
+ i1pro *p,
+ double *absraw, /* Return array [-1 nraw] of absraw values */
+ int nummeas, /* Number of readings to take */
+ double *inttime, /* Integration time to use/used */
+ int gainmode /* Gain mode to use, 0 = normal, 1 = high */
+);
+
+/* Take a white reference measurement - part 3 */
+/* Average, check, and convert to output wavelengths */
+i1pro_code i1pro_whitemeasure_3(
+ i1pro *p,
+ double *abswav1, /* Return array [nwav1] of abswav values (may be NULL) */
+ double *abswav2, /* Return array [nwav2] of abswav values (if hr_init, may be NULL) */
+ double *absraw, /* Return array [-1 nraw] of absraw values */
+ double *optscale, /* Factor to scale gain/int time by to make optimal (may be NULL) */
+ int nummeas, /* Number of readings to take */
+ double inttime, /* Integration time to use/used */
+ int gainmode, /* Gain mode to use, 0 = normal, 1 = high */
+ double targoscale, /* Optimal reading target scale factor */
+ double **multimes, /* Multiple measurement results */
+ double darkthresh /* Raw dark threshold */
+);
+
+/* Take a white reference measurement */
+/* (Subtracts black and processes into wavelenths) */
+i1pro_code i1pro_whitemeasure(
+ i1pro *p,
+ double *abswav1, /* Return array [nwav1] of abswav values (may be NULL) */
+ double *abswav2, /* Return array [nwav2] of abswav values (if hr_init, may be NULL) */
+ double *absraw, /* Return array [-1 nraw] of absraw values */
+ double *optscale, /* Factor to scale gain/int time by to make optimal (may be NULL) */
+ int nummeas, /* Number of readings to take */
+ double *inttime, /* Integration time to use/used */
+ int gainmode, /* Gain mode to use, 0 = normal, 1 = high */
+ double targoscale, /* Optimal reading scale factor */
+ int ltocmode /* 1 = Lamp turn on compensation mode */
+);
+
+/* Process a single raw white reference measurement */
+/* (Subtracts black and processes into wavelenths) */
+i1pro_code i1pro_whitemeasure_buf(
+ i1pro *p,
+ double *abswav1, /* Return array [nwav1] of abswav values (may be NULL) */
+ double *abswav2, /* Return array [nwav2] of abswav values (if hr_init, may be NULL) */
+ double *absraw, /* Return array [-1 nraw] of absraw values */
+ double inttime, /* Integration time to used */
+ int gainmode, /* Gain mode to use, 0 = normal, 1 = high */
+ unsigned char *buf /* Raw buffer */
+);
+
+/* Take a wavelength reference measurement */
+/* (Measure and subtracts black and convert to absraw) */
+i1pro_code i1pro2_wl_measure(
+ i1pro *p,
+ double *absraw, /* Return array [-1 nraw] of absraw values */
+ double *optscale, /* Factor to scale gain/int time by to make optimal (may be NULL) */
+ double *inttime, /* Integration time to use/used */
+ double targoscale /* Optimal reading scale factor */
+);
+
+/* Take a measurement reading using the current mode, part 1 */
+/* Converts to completely processed output readings. */
+i1pro_code i1pro_read_patches_1(
+ i1pro *p,
+ int minnummeas, /* Minimum number of measurements to take */
+ int maxnummeas, /* Maximum number of measurements to allow for */
+ double *inttime, /* Integration time to use/used */
+ int gainmode, /* Gain mode to use, 0 = normal, 1 = high */
+ int *nmeasuered, /* Number actually measured */
+ unsigned char *buf, /* Raw USB reading buffer */
+ unsigned int bsize
+);
+
+/* Take a measurement reading using the current mode, part 2 */
+/* Converts to completely processed output readings. */
+i1pro_code i1pro_read_patches_2(
+ i1pro *p,
+ double *duration, /* return flash duration (secs) */
+ double **specrd, /* Return array [numpatches][nwav] of spectral reading values */
+ int numpatches, /* Number of patches to return */
+ double inttime, /* Integration time to used */
+ int gainmode, /* Gain mode useed, 0 = normal, 1 = high */
+ int nmeasuered, /* Number actually measured */
+ unsigned char *buf, /* Raw USB reading buffer */
+ unsigned int bsize
+);
+
+/* Take a measurement reading using the current mode. */
+/* Converts to completely processed output readings. */
+i1pro_code i1pro_read_patches(
+ i1pro *p,
+ double *duration, /* Return flash duration */
+ double **specrd, /* Return array [numpatches][nwav] of spectral reading values */
+ int numpatches, /* Number of patches to return */
+ int minnummeas, /* Minimum number of measurements to take */
+ int maxnummeas, /* Maximum number of measurements to allow for */
+ double *inttime, /* Integration time to use/used */
+ int gainmode /* Gain mode to use, 0 = normal, 1 = high */
+);
+
+/* Take a trial measurement reading using the current mode. */
+/* Used to determine if sensor is saturated, or not optimal */
+i1pro_code i1pro_trialmeasure(
+ i1pro *p,
+ int *saturated, /* Return nz if sensor is saturated */
+ double *optscale, /* Factor to scale gain/int time by to make optimal */
+ int nummeas, /* Number of readings to take */
+ double *inttime, /* Integration time to use/used */
+ int gainmode, /* Gain mode to use, 0 = normal, 1 = high */
+ double targoscale /* Optimal reading scale factor */
+);
+
+/* Measurement modifier. Modifes the default current measurement mode */
+/* for the measurement. Bit 0x10 indicates that incandescent illumination */
+/* is possible, bit 0x20 indicates that any scan mode is to be ignored */
+typedef enum {
+ i1p_norm = 0x10, /* Normal measurement for current mode */
+ i1p2_UV = 0x01, /* Measurement using UV LED instead of incandescent (Rev E) */
+ i1p_cal = 0x32, /* No scan, with current mode illumination */
+ i1p_dark_cal = 0x23, /* No scan, no illumination */
+ i1p2_wl_cal = 0x24 /* No scan, wavelength reference LED illumination (Rev E) */
+} i1p_mmodif;
+
+/* Trigger a single measurement cycle. This could be a dark calibration, */
+/* a calibration, or a real measurement. Used to create the higher */
+/* level "calibrate" and "take reading" functions. */
+/* The setup for the operation is in the current mode state. */
+/* The called then needs to call i1pro_readmeasurement() */
+i1pro_code
+i1pro_trigger_one_measure(
+ i1pro *p,
+ int nummeas, /* Number of measurements to make */
+ double *inttime, /* Integration time to use/used */
+ int gainmode, /* Gain mode to use, 0 = normal, 1 = high */
+ i1p_mmodif mmodif /* Measurement modifier enum */
+);
+
+/* ============================================================ */
+/* lower level reading processing */
+
+/* Take a buffer full of sensor readings, and convert them to */
+/* absolute raw values. Linearise if Rev A..D */
+/* Note the rev E darkthresh returned has NOT been converted to an absolute raw value */
+i1pro_code i1pro_sens_to_absraw(
+ i1pro *p,
+ double **absraw, /* Array of [nummeas][-1 nraw] value to return */
+ unsigned char *buf, /* Raw measurement data must be 256 * nummeas */
+ int nummeas, /* Return number of readings measured */
+ double inttime, /* Integration time used */
+ int gainmode, /* Gain mode, 0 = normal, 1 = high */
+ double *pdarkthresh /* Return a dark threshold value (Rev E) */
+);
+
+/* Take a raw value, and convert it into an absolute raw value. */
+/* Note that linearisation is ignored, since it is assumed to be insignificant */
+/* to the black threshold and saturation values. */
+double i1pro_raw_to_absraw(
+ i1pro *p,
+ double raw, /* Input value */
+ double inttime, /* Integration time used */
+ int gainmode /* Gain mode, 0 = normal, 1 = high */
+);
+
+/* Take a single set of absolute linearised sensor values and */
+/* convert them back into i1pro Rev A..D raw reading values. */
+i1pro_code i1pro_absraw_to_meas(
+ i1pro *p,
+ int *meas, /* Return raw measurement data */
+ double *absraw, /* Array of [-1 nraw] value to process */
+ double inttime, /* Integration time used */
+ int gainmode /* Gain mode, 0 = normal, 1 = high */
+);
+
+/* Average a set of measurements into one. */
+/* Return zero if readings are consistent and not saturated. */
+/* Return nz with bit 1 set if the readings are not consistent */
+/* Return nz with bit 2 set if the readings are saturated */
+/* Return the highest individual element. */
+/* Return the overall average. */
+int i1pro_average_multimeas(
+ i1pro *p,
+ double *avg, /* return average [-1 nraw] */
+ double **multimeas, /* Array of [nummeas][-1 nraw] value to average */
+ int nummeas, /* Return number of readings measured */
+ double *phighest, /* If not NULL, return highest value from all bands and msrmts. */
+ double *poallavg, /* If not NULL, return overall average of bands and measurements */
+ double satthresh, /* Sauration threshold, 0 for none */
+ double darkthresh /* Dark threshold (used for consistency check scaling) */
+);
+
+/* Recognise the required number of ref/trans patch locations, */
+/* and average the measurements within each patch. */
+/* Return flags zero if readings are consistent and not saturated. */
+/* Return flags nz with bit 1 set if the readings are not consistent */
+/* Return flags nz with bit 2 set if the readings are saturated */
+/* Return the highest individual element. */
+i1pro_code i1pro_extract_patches_multimeas(
+ i1pro *p,
+ int *flags, /* return flags */
+ double **pavg, /* return patch average [naptch][-1 nraw] */
+ int npatch, /* number of patches to recognise */
+ double **multimeas, /* Array of [nummeas][-1 nraw] value to extract from */
+ int nummeas, /* number of readings to recognise them from */
+ double *phighest, /* If not NULL, return highest value from all bands and msrmts. */
+ double satthresh, /* Sauration threshold, 0 for none */
+ double inttime /* Integration time (used to adjust consistency threshold) */
+);
+
+/* Recognise any flashes in the readings, and */
+/* and average their values together as well as summing their duration. */
+/* Return nz on an error */
+i1pro_code i1pro_extract_patches_flash(
+ i1pro *p,
+ int *flags, /* return flags */
+ double *duration, /* return duration */
+ double *pavg, /* return patch average [-1 nraw] */
+ double **multimeas, /* Array of [nummeas][-1 nraw] value to extract from */
+ int nummeas, /* number of readings made */
+ double inttime /* Integration time (used to compute duration) */
+);
+
+/* Subtract one absraw array from another */
+/* If Rev E, also adjust according to shielded cells, and linearise. */
+void i1pro_sub_absraw(
+ i1pro *p,
+ int nummeas, /* Return number of readings measured */
+ double inttime, /* Integration time used */
+ int gainmode, /* Gain mode, 0 = normal, 1 = high */
+ double **absraw, /* Source/Desination array [-1 nraw] */
+ double *sub /* Black value to subtract [-1 nraw] */
+);
+
+/* Convert an absraw array from raw wavelengths to output wavelenths */
+/* for the current resolution */
+void i1pro_absraw_to_abswav(
+ i1pro *p,
+ int highres,
+ int reflective,
+ int nummeas, /* Return number of readings measured */
+ double **abswav, /* Desination array [nwav] */
+ double **absraw /* Source array [-1 nraw] */
+);
+
+/* Convert an abswav array of output wavelengths to scaled output readings. */
+void i1pro_scale_specrd(
+ i1pro *p,
+ double **outspecrd, /* Destination */
+ int numpatches, /* Number of readings/patches */
+ double **inspecrd /* Source */
+);
+
+/* Convert from spectral to XYZ, and transfer to the ipatch array */
+i1pro_code i1pro_conv2XYZ(
+ i1pro *p,
+ ipatch *vals, /* Values to return */
+ int nvals, /* Number of values */
+ double **specrd, /* Spectral readings */
+ instClamping clamp /* Clamp XYZ/Lab to be +ve */
+);
+
+/* Check a reflective white measurement, and check that */
+/* it seems reasonable. Return inst_ok if it is, error if not. */
+i1pro_code i1pro_check_white_reference1(
+ i1pro *p,
+ double *abswav /* Measurement to check */
+);
+
+/* Compute a calibration factor given the reading of the white reference. */
+/* Return nz if any of the transmission wavelengths are low */
+int i1pro_compute_white_cal(
+ i1pro *p,
+ double *cal_factor0, /* [nwav0] Calibration factor to compute */
+ double *white_ref0, /* [nwav0] White reference to aim for, NULL for 1.0 */
+ double *white_read0, /* [nwav0] The white that was read */
+ double *cal_factor1, /* [nwav1] Calibration factor to compute */
+ double *white_ref1, /* [nwav1] White reference to aim for, NULL for 1.0 */
+ double *white_read1 /* [nwav1] The white that was read */
+);
+
+/* For adaptive mode, compute a new integration time and gain mode */
+/* in order to optimise the sensor values. */
+i1pro_code i1pro_optimise_sensor(
+ i1pro *p,
+ double *pnew_int_time,
+ int *pnew_gain_mode,
+ double cur_int_time,
+ int cur_gain_mode,
+ int permithg, /* nz to permit switching to high gain mode */
+ int permitclip, /* nz to permit clipping out of range int_time, else error */
+ double targoscale, /* Optimising target scale ( <= 1.0) */
+ double scale /* scale needed of current int time to reach optimum */
+);
+
+/* Compute the number of measurements needed, given the target */
+/* time and integration time. Will return 0 if target time is 0 */
+int i1pro_comp_nummeas(
+ i1pro *p,
+ double meas_time,
+ double int_time
+);
+
+/* Convert the dark interpolation data to a useful state */
+void i1pro_prepare_idark(i1pro *p);
+
+/* Create the dark reference for the given integration time and gain */
+/* by interpolating from the 4 readings taken earlier. */
+i1pro_code i1pro_interp_dark(
+ i1pro *p,
+ double *result, /* Put result of interpolation here */
+ double inttime,
+ int gainmode
+);
+
+/* Create or re-create high resolution mode references */
+i1pro_code i1pro_create_hr(i1pro *p);
+
+/* Set the noinitcalib mode */
+void i1pro_set_noinitcalib(i1pro *p, int v, int losecs);
+
+/* Set the trigger config */
+void i1pro_set_trig(i1pro *p, inst_opt_type trig);
+
+/* Return the trigger config */
+inst_opt_type i1pro_get_trig(i1pro *p);
+
+/* Set the trigger return */
+void i1pro_set_trigret(i1pro *p, int val);
+
+/* Switch thread handler */
+int i1pro_switch_thread(void *pp);
+
+/* ============================================================ */
+/* Low level i1pro commands */
+
+/* USB Commands */
+
+/* Reset the instrument */
+i1pro_code
+i1pro_reset(
+ struct _i1pro *p,
+ int mask /* reset mask ?. Known values ar 0x1f, 0x07, 0x01 */
+);
+
+/* Read from the EEProm */
+i1pro_code
+i1pro_readEEProm(
+ struct _i1pro *p,
+ unsigned char *buf, /* Where to read it to */
+ int addr, /* Address in EEprom to read from */
+ int size /* Number of bytes to read (max 65535) */
+);
+
+/* Write to the EEProm */
+i1pro_code
+i1pro_writeEEProm(
+ i1pro *p,
+ unsigned char *buf, /* Where to write from */
+ int addr, /* Address in EEprom to write to */
+ int size /* Number of bytes to write (max 65535) */
+);
+
+/* Get the miscelanious status */
+/* return pointers may be NULL if not needed. */
+i1pro_code
+i1pro_getmisc(
+ i1pro *p,
+ int *fwrev, /* Return the hardware version number */
+ int *unkn1, /* Unknown status, set after doing a measurement */
+ int *maxpve, /* Maximum positive value in sensor readings */
+ int *unkn3, /* Unknown status, usually 1 */
+ int *powmode /* 0 = high power mode, 8 = low power mode */
+);
+
+/* Get the current measurement parameters */
+/* return pointers may be NULL if not needed. */
+i1pro_code
+i1pro_getmeasparams(
+ i1pro *p,
+ int *intclocks, /* Number of integration clocks (Up to 65535) */
+ int *lampclocks, /* Number of lamp turn on sub-clocks (Up to 65535) */
+ int *nummeas, /* Number of measurements (Up to 65535) */
+ int *measmodeflags /* Measurement mode flags (4 bits, see below) */
+);
+
+/* These bits correspond with the instruction flags */
+#define I1PRO_MMF_SCAN 0x01 /* Scan mode bit, else spot mode */
+#define I1PRO_MMF_NOLAMP 0x02 /* No lamp mode, else use illumination lamp */
+#define I1PRO_MMF_LOWGAIN 0x04 /* Normal gain mode, else high gain */
+#define I1PRO_MMF_UNKN 0x08 /* Unknown. Not usually set */
+
+/* Scan mode continues measuring until the user releases the button. */
+/* (Does scan mode do the given number of readings as a minimum ???) */
+/* Spot mode does the given number of readings. */
+
+/* Set the measurement parameters */
+i1pro_code
+i1pro_setmeasparams(
+ i1pro *p,
+ int intclocks, /* Number of integration clocks */
+ int lampclocks, /* Number of lamp turn on sub-clocks */
+ int nummeas, /* Number of measurements to make */
+ int measmodeflags /* Measurement mode flags */
+);
+
+/* Trigger a measurement after the delay in msec. */
+/* The actual return code will be in m->trig_rv after the delay */
+i1pro_code
+i1pro_triggermeasure(i1pro *p, int delay);
+
+
+/* Read a measurements results */
+i1pro_code
+i1pro_readmeasurement(
+ i1pro *p,
+ int inummeas, /* Initial number of measurements to expect */
+ int scanflag, /* NZ if in scan mode to continue reading */
+ unsigned char *buf, /* Where to read it to */
+ int bsize, /* Bytes available in buffer */
+ int *nummeas, /* Return number of readings measured */
+ i1p_mmodif mmodif /* Measurement modifier enum */
+);
+
+
+/* Set the measurement clock mode */
+/* Version >= 301 only */
+i1pro_code
+i1pro_setmcmode(
+ i1pro *p,
+ int mcmode /* Measurement clock mode, 1..mxmcmode */
+);
+
+
+/* Get the current measurement clock mode */
+/* Return pointers may be NULL if not needed. */
+/* Version >= 301 only */
+i1pro_code
+i1pro_getmcmode(
+ i1pro *p,
+ int *maxmcmode, /* mcmode must be < maxmcmode */
+ int *mcmode, /* readback current mcmode */
+ int *subclkdiv, /* Sub clock divider ratio */
+ int *intclkusec, /* Integration clock in usec */
+ int *subtmode /* Subtract mode on read using average of value 127 */
+);
+
+/* ============================================================ */
+/* Low level Rev E commands */
+
+/* Get the EEProm size */
+i1pro_code
+i1pro2_geteesize(
+ i1pro *p,
+ int *eesize
+);
+
+/* Get the Chip ID (Also valid for Rev D) */
+/* Only returns a valid result after reading the EEProm ! */
+i1pro_code
+i1pro2_getchipid(
+ i1pro *p,
+ unsigned char chipid[8]
+);
+
+/* Get Extra Parameters */
+i1pro_code
+i1pro2_getmeaschar(
+ i1pro *p,
+ int *clkusec,
+ int *xraw,
+ int *nraw,
+ int *subdiv
+);
+
+/* These bits correspond with the instruction flags */
+#define I1PRO2_MMF_LAMP 0x0100 /* Use the Incandescent Lamp as the illuminant */
+#define I1PRO2_MMF_UV_LED 0x0200 /* Use the Ultra Violet LED as the illuminant */
+#define I1PRO2_MMF_WL_LED 0x0300 /* Use the Wavelength Reference LED as the illuminant */
+//#define I1PRO2_MMF_HIGHGAIN 0x0000 /* Rev E mode has no high gain mode ? */
+#define I1PRO2_MMF_SCAN 0x0001 /* Scan mode bit, else spot mode */
+#define I1PRO2_MMF_RULER_START 0x0004 /* Start ruler tracking in scan mode */
+#define I1PRO2_MMF_RULER_END 0x0008 /* End ruler tracking in scan mode */
+
+/* Delayed trigger implementation, called from thread */
+/* We assume that the Rev E measurement parameters have been set in */
+/* the i1proimp structure c_* values */
+static int
+i1pro2_delayed_trigger(void *pp);
+
+/* Trigger a measurement after the nominated delay */
+/* The actual return code will be in m->trig_rv after the delay. */
+/* This allows us to start the measurement read before the trigger, */
+/* ensuring that process scheduling latency can't cause the read to fail. */
+i1pro_code
+i1pro2_triggermeasure(i1pro *p, int delay);
+
+
+/* Get the UV before and after measurement voltage drop */
+i1pro_code
+i1pro2_getUVvolts(
+ i1pro *p,
+ int *before,
+ int *after
+);
+
+/* Terminate Ruler tracking (???) */
+/* The parameter seems to be always 0 ? */
+static int
+i1pro2_stop_ruler(void *pp, int parm);
+
+
+/* Send a LED sequence */
+static int
+i1pro2_indLEDseq(void *pp, unsigned char *buf, int size);
+
+/* Turn indicator LEDs off */
+static int
+i1pro2_indLEDoff(void *pp);
+
+// ~~~~9999
+
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - */
+
+/* Wait for a reply triggered by a button press */
+i1pro_code i1pro_waitfor_switch(i1pro *p, double top);
+
+/* Wait for a reply triggered by a button press (thread version) */
+i1pro_code i1pro_waitfor_switch_th(i1pro *p, double top);
+
+/* Terminate button handling ? */
+i1pro_code i1pro_terminate_switch(i1pro *p);
+
+/* -------------------------------------------------- */
+/* Key/Value storage */
+
+/* Calibration data storage class */
+/* The i1pro stores all it's calibration information */
+/* using a key/values arrangement. */
+/* We provide a place to store and retrieve that information here. */
+
+/* We haven't implemented a full set of functions - it's not possible */
+/* to create the store from scratch, re-allocate key/value entries, */
+/* resize entries or anything else of this sort. */
+
+
+/* Data Key identifiers */
+
+/* Note that array sizes are nominal. They could change with */
+/* driver and instrument changes. */
+
+/* "Log" data is keys 2710-2715, 271a-271d, 2724-2725 */
+
+/* The log data seems largly devoted to the last remission spot calibration */
+/* or reading, and some general statistics. */
+
+typedef enum {
+
+// Note 0x2710 = 10000
+ key_meascount = 0x2715, /* int, Total Measure (Emis/Remis/Ambient/Trans/Cal) count */
+ /* but not the pre-Remission dark calibration. */
+ key_darkreading = 0x271a, /* int[128] Remspotcal Dark data */
+ key_whitereading= 0x271b, /* int[128] Remspotcal White data */
+ key_gainmode = 0x271c, /* int - Remspotcal gain mode, Values 1 (normal) or 0 (high) */
+ key_inttime = 0x271d, /* double - Remspotcal integration time */
+ key_caldate = 0x2724, /* int date - Remspotcal last calibration date */
+ key_calcount = 0x2725, /* int - Remission spot measure Count at last Remspotcal. */
+ key_checksum = 0x2710, /* int - Log checksum */
+ key_rpinttime = 0x2711, /* double - Last remision spot reading integration time */
+ key_rpcount = 0x2712, /* int - Remission spot measure Count */
+ key_acount = 0x2713, /* int - Remission scan measure Count (??) */
+ key_lampage = 0x2714, /* double - Total lamp usage time (??) */
+
+/* Duplicate of above, keys += 0x3E8 (+1000) */
+// (0x2af8 = 11000)
+
+ key_2logoff = 0x03e8, /* Offset from first to second copy of log keys */
+
+
+/* Calibration parameters are 3e8-3ec, 44c-44e, 4b4-4b5, 4b7-4b8, 4bb-4bd, */
+/* 4c5-4c6, bb9-bba, bbf-bc6, fa0 */
+
+// Note 0x3e8 = 1000
+// 0x44c = 1100
+// 0x4b0 = 1200
+// 0xbb8 = 3000
+// 0xfa0 = 4000
+
+/* Linearisation uses Polinomial equation, ie: y = c0 + c1 * x + c2 * x^2 + c3 * x^3 etc. */
+/* and is applied to the raw (integer) sensor data. */
+
+ key_ng_lin = 0x03e8, /* double[4] */
+ /* Normal gain polinomial linearisation coefficients */
+
+ key_hg_lin = 0x03e9, /* double[4] */
+ /* High gain polinomial linearisation coefficients */
+
+ key_min_int_time= 0x04c5, /* double - Minumum integration time */
+ /* default 8.84000025689601900e-003 in EEProm */
+ /* Overwritten in MinilinoLowLevelDriver constructor: */
+ /* Default to 8.84000025689601900e-003 if cpldrev == 101 Ver A */
+ /* Default to 4.71600005403161050e-003 if cpldrev == 301 Ver B+ */
+
+ key_max_int_time= 0x04c6, /* double - Maximum integration time */
+ /* Typically 4.4563798904418945 */
+
+ key_mtx_index = 0x03ea, /* int[36] */
+ /* Matrix CCD sample index for each out wavelength */
+ /* 380 - 730nm */
+
+ key_mtx_nocoef = 0x03eb, /* int[36] */
+ /* Number of matrix cooeficients for each out wavelength */
+
+ key_mtx_coef = 0x03ec, /* double[36 x 16] */
+ /* Matrix cooeficients to compute each wavelength */
+
+ key_0bb9 = 0x0bb9, /* int - value typically -1*/
+ key_0bba = 0x0bba, /* int - value typically -1 */
+
+ key_white_ref = 0x044c, /* double[36] */
+ /* White calibration tile reflectance values */
+
+ key_emis_coef = 0x044d, /* double[36] */
+ /* Emission calibration coefficients */
+
+ key_amb_coef = 0x044e, /* double[36] */
+ /* Ambient light calibration values (compound with Emission) */
+ /* May be < 36, values -1.0 if Ambient is not supported */
+
+ key_0fa0 = 0x0fa0, /* int */
+ key_0bbf = 0x0bbf, /* int */
+
+ key_cpldrev = 0x0bc0, /* int - Firmware revision number */
+
+ key_0bc1 = 0x0bc1, /* int[5] */
+
+ key_capabilities= 0x0bc2, /* int */
+ /* Capabilities flag ? */
+ /* ie. has Ambient capability if val & 0x6000 != 0 */
+
+ key_0bc3 = 0x0bc3, /* int */
+
+ key_physfilt = 0x0bc4, /* int - physical filter */
+ /* 0x80 == no filter */
+ /* 0x82 == UV filter */
+
+ key_0bc5 = 0x0bc5, /* int */
+
+ key_0bc6 = 0x0bc6, /* double */
+
+ key_sens_target = 0x04b4, /* int - sensor optimal target value */
+ /* typical value 37000 */
+
+ key_sens_dark = 0x04b5, /* int - sensor dark reference threshold */
+ /* typically value 150 */
+
+ key_ng_sens_sat = 0x04b7, /* int */
+ /* Normal gain sensor saturated threshold */
+ /* typically value 45000 */
+
+ key_hg_sens_sat = 0x04b8, /* int */
+ /* High gain sensor saturated threshold */
+ /* typically value 45000 */
+
+ key_serno = 0x04bb, /* int - serial number */
+
+ key_dom = 0x04bc, /* int - unknown */
+ /* Possibly date of manufacture DDMMYYYY ? */
+ /* ie., decimal 10072002 would be 10/7/2002 ? */
+
+ key_hg_factor = 0x04bd, /* double */
+ /* High gain mode gain factor, ie 9.5572.. */
+
+
+ key2_chip_id = 0x2ee1, /* uchar[8], chip id */
+
+ key2_capabilities = 0x2ee2, /* int, capabilities bits */
+
+ key2_sens_target = 0x2eeb, /* int - sensor optimal target value ? */
+ /* typical value 30000 */
+
+ key2_sens_sat = 0x2eec, /* int - sensor saturation value ? */
+ /* typical value 55000 */
+
+ key2_uvcal_intt = 0x2ef9, /* double, UV calibration initial integration time */
+
+ key2_wlcal_intt = 0x2efa, /* double, wavelength calibration initial integration time */
+
+ key2_wlcal_minlev = 0x2efe, /* int, wavelength calibration normalized minimum peak level */
+
+ key2_wlcal_spec = 0x2f44, /* double[50], wavelength calibration reference spectrum */
+
+ key2_wlcal_ooff = 0x2f45, /* int, Reference WL Led spectral offset */
+
+ key2_wlcal_fwhm = 0x2f4e, /* double, wavelength calibration nominal fwhm (nm) */
+ key2_wlcal_fwhm_tol = 0x2f4f, /* double, wavelength calibration fwhm tollerance (nm) */
+
+ key2_wlcal_max = 0x2f46, /* double, wavelength calibration error limit, ie. 5.0 */
+
+ key2_wlpoly_1 = 0x2f62, /* double[4], CCD bin to wavelength polinomial #1 (normal) */
+ key2_wlpoly_2 = 0x2f63, /* double[4], CCD bin to wavelength polinomial #2 ??? */
+
+ key2_straylight = 0x2f58, /* int16[36][6] signed stray light values */
+ key2_straylight_scale = 0x2f59 /* double stray light scale factor */
+
+} i1key;
+
+
+/* Data type */
+typedef enum {
+ i1_dtype_unknown = 0,
+ i1_dtype_char = 1, /* Array of bytes */
+ i1_dtype_short = 2, /* 16 bit int, date */
+ i1_dtype_int = 3, /* 32 bit int, date */
+ i1_dtype_double = 4, /* 64 bit double, serialized as 32 bit float */
+ i1_dtype_section = 5 /* End of section marker */
+} i1_dtype;
+
+/* A key/value entry */
+struct _i1keyv {
+ void *data; /* Array of data */
+ unsigned int count; /* Count of data */
+ i1_dtype type; /* Type of data */
+ int addr; /* EEProm address */
+ int size; /* Size in bytes */
+ int key; /* 16 bit key */
+ struct _i1keyv *next; /* Link to next keyv */
+}; typedef struct _i1keyv i1keyv;
+
+struct _i1data {
+ /* private: */
+ i1pro *p;
+ i1proimp *m;
+
+ a1log *log; /* reference to instrument log */
+ i1keyv *head; /* Pointer to first in chain of keyv */
+ i1keyv *last; /* Pointer to last in chain of keyv */
+
+ /* public: */
+
+ /* Search the linked list for the given key */
+ /* Return NULL if not found */
+ i1keyv *(* find_key)(struct _i1data *d, i1key key);
+
+ /* Search the linked list for the given key and */
+ /* return it, or create the key if it doesn't exist. */
+ /* Return NULL on error */
+ i1keyv *(* make_key)(struct _i1data *d, i1key key);
+
+ /* Return type of data associated with key. Return i1_dtype_unknown if not found */
+ i1_dtype (*get_type)(struct _i1data *d, i1key key);
+
+ /* Return the number of data items in a keyv. Return 0 if not found */
+ unsigned int (*get_count)(struct _i1data *d, i1key key);
+
+ /* Return a int pointer to the 16 bit int data for the key. */
+ /* Optionally return the number of items too. */
+ /* Return NULL if not found or wrong type */
+ int *(*get_shorts)(struct _i1data *d, unsigned int *count, i1key key);
+
+ /* Return a pointer to the 32 bit int data for the key. */
+ /* Optionally return the number of items too. */
+ /* Return NULL if not found or wrong type */
+ int *(*get_ints)(struct _i1data *d, unsigned int *count, i1key key);
+
+ /* Return a pointer to the double data for the key. */
+ /* Optionally return the number of items too. */
+ /* Return NULL if not found or wrong type */
+ double *(*get_doubles)(struct _i1data *d, unsigned int *count, i1key key);
+
+
+ /* Return pointer to one of the int data for the key. */
+ /* Return NULL if not found or wrong type or out of range index. */
+ int *(*get_int)(struct _i1data *d, i1key key, unsigned int index);
+
+ /* Return pointer to one of the double data for the key. */
+ /* Return NULL if not found or wrong type or out of range index. */
+ double *(*get_double)(struct _i1data *d, i1key key, double *data, unsigned int index);
+
+
+ /* Un-serialize a char buffer into an i1key keyv */
+ /* (Don't change addr if its is -1) */
+ i1pro_code (*unser_ints)(struct _i1data *d, i1key key, int addr,
+ unsigned char *buf, unsigned int size);
+
+ /* Un-serialize a char buffer of floats into a double keyv */
+ /* (Don't change addr if its is -1) */
+ i1pro_code (*unser_doubles)(struct _i1data *d, i1key key, int addr,
+ unsigned char *buf, unsigned int size);
+
+
+ /* Serialize an i1key keyv into a char buffer. Error if it is outside the buffer */
+ i1pro_code (*ser_ints)(struct _i1data *d, i1keyv *k, unsigned char *buf, unsigned int size);
+
+ /* Serialize a double keyv as floats into a char buffer. Error if the buf is not big enough */
+ i1pro_code (*ser_doubles)(struct _i1data *d, i1keyv *k, unsigned char *buf, unsigned int size);
+
+ /* Initialise the data from the EEprom contents */
+ i1pro_code (*parse_eeprom)(struct _i1data *d, unsigned char *buf, unsigned int len, int extra);
+
+
+ /* Serialise all the keys up to the first marker into a buffer. */
+ i1pro_code (*prep_section1)(struct _i1data *d, unsigned char **buf, unsigned int *len);
+
+ /* Copy an array full of ints to the key (must be same size as existing) */
+ i1pro_code (*add_ints)(struct _i1data *d, i1key key, int *data, unsigned int count);
+
+ /* Copy an array full of doubles to the key (must be same size as existing) */
+ i1pro_code (*add_doubles)(struct _i1data *d, i1key key, double *data, unsigned int count);
+
+
+ /* Destroy ourselves */
+ void (*del)(struct _i1data *d);
+
+ /* Other utility methods */
+
+ /* Return the data type for the given key identifier */
+ i1_dtype (*det_type)(struct _i1data *d, i1key key);
+
+ /* Given an index starting at 0, return the matching key code */
+ /* for keys that get checksummed. Return 0 if outside range. */
+ i1key (*chsum_keys)(struct _i1data *d, int index);
+
+ /* Compute a checksum. */
+ int (*checksum)(struct _i1data *d, i1key keyoffset);
+
+}; typedef struct _i1data i1data;
+
+/* Constructor. Construct from the EEprom contents */
+extern i1data *new_i1data(i1proimp *m);
+
+#define I1PRO_IMP
+#endif /* I1PRO_IMP */