diff options
Diffstat (limited to 'spectro/munki_imp.h')
-rw-r--r-- | spectro/munki_imp.h | 1029 |
1 files changed, 1029 insertions, 0 deletions
diff --git a/spectro/munki_imp.h b/spectro/munki_imp.h new file mode 100644 index 0000000..a9af3a9 --- /dev/null +++ b/spectro/munki_imp.h @@ -0,0 +1,1029 @@ + +#ifndef MUNKI_IMP_H + + /* X-Rite ColorMunki related defines */ + +/* + * Argyll Color Correction System + * + * Author: Graeme W. Gill + * Date: 12/1/2009 + * + * 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. + * + * (Base on i1pro_imp.h) + */ + +/* + 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. + */ + +#ifdef __cplusplus + extern "C" { +#endif + +/* Implementation resources for munki driver */ + +/* -------------------------------------------------- */ +/* Implementation class */ + +typedef int munki_code; /* Type to use for error codes */ + +/* MUNKI 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 { + mk_refl_spot = 0, + mk_refl_scan = 1, + mk_emiss_spot_na = 2, + mk_tele_spot_na = 3, + mk_emiss_spot = 4, + mk_tele_spot = 5, + mk_emiss_scan = 6, + mk_amb_spot = 7, + mk_amb_flash = 8, + mk_trans_spot = 9, + mk_trans_scan = 10, + mk_no_modes = 11 +} mk_mode; + +struct _munki_state { + mk_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 modify emiss */ + int ambient; /* flag - Ambient position mode */ + int projector; /* flag - Projector position (tele) mode */ + + /* The following can be added to any of the 3: */ + int scan; /* flag - Scanning mode */ + int adaptive; /* flag - adaptive mode (emiss - adapt for each measurement) */ + + /* 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 */ + 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 invsampt; /* Invalid sample time */ + + double dpretime; /* Target pre-read dark read time - sets no. of readings */ + double wpretime; /* Target pre-read white/sample read time - sets no. of readings */ + + double dcaltime; /* Target dark calibration time - sets number of readings */ + double wcaltime; /* Target white calibration time - sets number of readings (not used?) */ + + 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 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 and gain mode. */ + 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; /* [nwav] of calibration scale factor for this mode */ + double *cal_factor1, *cal_factor2; /* (Underlying tables for two resolutions) */ + double *white_data; /* [-1 nraw] linear absolute dark subtracted white data */ + /* used to compute cal_factors (at reftemp) */ + double **iwhite_data; /* [-1 nraw][2] LED temperature data to interpolate white_data from */ + double reftemp; /* Reference temperature to correct to */ + + /* 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, 1.0 norm, 0.01 high, 1.0 high */ + /* then it's converted to base + increment with inttime */ + + int want_calib; /* Initial White calibration wanted */ + int want_dcalib; /* Initial Dark Calibration wanted */ + + /* 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 _munki_state munki_state; + + + +/* MUNKI implementation class */ +struct _munkiimp { + munki *p; + + /* Misc. and top level */ + struct _mkdata *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; /* Thread terminate on error rather than retry */ + volatile int th_termed; /* Thread has terminated */ + inst_opt_type trig; /* Reading trigger mode */ + int noinitcalib; /* Disable initial calibration if not essential */ + int nosposcheck; /* Disable checking the sensor position */ + int highres; /* High resolution mode */ + int hr_inited; /* High resolution has been initialized */ + + /* Current settings */ + mk_mode mmode; /* Current measurement mode selected */ + munki_state ms[mk_no_modes]; /* Mode state */ + int spec_en; /* Enable reporting of spectral data */ + + double intclkp; /* Integration clock period (computed from tickdur) */ + + /* Current state of hardware (~~99 are all these used ??) */ + double c_inttime; /* Integration period (=inttime + deadtime) */ + int c_measmodeflags; /* Measurement mode flags (set by trigger() */ + + /* Information from the HW */ + int fwrev; /* int - Firmware revision number, from getfirm() */ + /* Typically 0120 = V1.32 */ + unsigned char chipid[8]; /* HW serial number */ + char vstring[37]; /* Asciiz version string */ + int tickdur; /* Tick duration (usec, converted to intclkp) */ + int minintcount; /* Minimum integration tick count */ + int noeeblocks; /* Number of EEPROM blocks */ + int eeblocksize; /* Size of each block */ + + /* Information from the EEProm */ + int calver; /* Effective calibration version number */ + int prodno; /* Production number */ + char serno[17]; /* serial number string */ + int adctype; /* A/D converter type */ + + double minsval; /* Minimum sensor value target */ + double optsval; /* Optimal sensor value target */ + double maxsval; /* Maximum sensor value target */ + double satlimit; /* Saturation limit */ + + int ledholdtempdc; /* LED Hold temparature duty cycle */ + /* Parameter used in measure instruction. [0] */ + double ledpreheattime; /* LED Pre-heat time, Seconds [1.0] */ + /* Time to turn LED on before determining */ + /* integration time that achieves optimal sensor value. */ + double cal_int_time; /* Calibration integration time in seconds. [0.018208] */ + /* Starting integration time use for achieving */ + /* the optimal sensor value. */ + double ledwaittime; /* LED Wait time, Seconds [1.0] */ + /* Time to wait for LED to cool down */ + /* before determining temperature/output characteristic. */ + double calscantime; /* Calibration scan time used for determining temp/output */ + /* characteristic of LED, Seconds. [3.0] */ + double refinvalidsampt; /* Reflection invalid sample time in seconds. [0.1] */ + /* This sets the number of extra samples to add to a */ + /* reflective read, and then to discard from */ + /* the start of the measurements. This allows for LED */ + /* thermal warmup. */ + + double min_int_time; /* Minimum integration time (secs) (set from minintcount) */ + /* (Typical value is 0.007168 = 139.5 times/sec) */ + double max_int_time; /* Maximum integration time (secs) (fixed in sw) */ + + /* Underlying calibration information */ + int nsen; /* There are 137 provided from the device, with */ + /* 6 skipped at the start, and 3 at the end. */ + /* The first 4 are photo shielded. */ + /* The last reading is the LED voltage drop */ + /* 2 at the start and 2 at the end are unused. */ + int nraw; /* Raw sample bands stored = 128 (Must be signed!) */ + int nwav; /* Current cooked spectrum bands stored, usually = 36 */ + double wl_short; /* Cooked spectrum bands short wavelength, usually 380 */ + double wl_long; /* Cooked spectrum bands short wavelength, usually 730 */ + + unsigned int nwav1, nwav2; /* Available bands for standard and high-res modes */ + double wl_short1, wl_short2, wl_long1, wl_long2; + + /* Reflection */ + int *rmtx_index; /* [nwav] Matrix CCD sample starting index for each out wavelength */ + int *rmtx_nocoef; /* [nwav] Number of matrix cooeficients for each out wavelength */ + double *rmtx_coef; /* [nwav * rmtx_nocoef] Matrix coeef's to compute each wavelength */ + int *rmtx_index1, *rmtx_index2; /* Underlying arrays for the two resolutions */ + int *rmtx_nocoef1, *rmtx_nocoef2; /* first [nwav1], second [nwav2] */ + double *rmtx_coef1, *rmtx_coef2; + + /* Emission */ + int *emtx_index; /* [nwav] Matrix CCD sample starting index for each out wavelength */ + int *emtx_nocoef; /* [nwav] Number of matrix cooeficients for each out wavelength */ + double *emtx_coef; /* [nwav * emtx_nocoef] Matrix coeef's to compute each wavelength */ + int *emtx_index1, *emtx_index2; /* Underlying arrays for the two resolutions */ + int *emtx_nocoef1, *emtx_nocoef2; /* first [nwav1], second [nwav2] */ + double *emtx_coef1, *emtx_coef2; + + 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 *white_ref; /* [nwav] White calibration tile reflectance values */ + double *emis_coef; /* [nwav] Emission calibration coefficients */ + double *amb_coef; /* [nwav] Ambient light cal values (compound with Emission) */ + double *proj_coef; /* [nwav] Projector light cal values (compound with Emission) */ + double *white_ref1, *white_ref2; /* Underlying tables for normal/high res modes */ + double *emis_coef1, *emis_coef2; + double *amb_coef1, *amb_coef2; + double *proj_coef1, *proj_coef2; + + double **straylight; /* [nwav][nwav] Stray light convolution matrix */ + double **straylight1, **straylight2; /* Underlying tables for normal/high res modes */ + + double highgain; /* High gain mode gain */ + double scan_toll_ratio; /* Modifier of scan tollerance */ + + /* Trigger houskeeping & diagnostics */ + int transwarn; /* Transmission calibration warning state */ + int lo_secs; /* Seconds since last opened (from calibration file mod time) */ + 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 */ + munki_code trig_rv; /* Delayed trigger result */ + +}; typedef struct _munkiimp munkiimp; + +/* Add an implementation structure */ +munki_code add_munkiimp(munki *p); + +/* Destroy implementation structure */ +void del_munkiimp(munki *p); + +/* ============================================================ */ +/* Error codes returned from munki_imp */ + +/* Note: update munki_interp_error() and munki_interp_code() in munki.c */ +/* if anything of these #defines are added or subtracted */ + +/* Fake Error codes */ +#define MUNKI_INTERNAL_ERROR 0x71 /* Internal software error */ +#define MUNKI_COMS_FAIL 0x72 /* Communication failure */ +#define MUNKI_UNKNOWN_MODEL 0x73 /* Not an munki */ +#define MUNKI_DATA_PARSE_ERROR 0x74 /* Read data parsing error */ + +#define MUNKI_USER_ABORT 0x75 /* uicallback returned abort */ +#define MUNKI_USER_TRIG 0x76 /* uicallback retuned trigger */ + +#define MUNKI_UNSUPPORTED 0x79 /* Unsupported function */ +#define MUNKI_CAL_SETUP 0x7A /* Cal. retry with correct setup is needed */ + +/* Real error code */ +#define MUNKI_OK 0x00 + +/* EEprop parsing errors */ +#define MUNKI_DATA_RANGE 0x02 /* out of range of buffer */ +#define MUNKI_DATA_MEMORY 0x03 /* memory alloc failure */ + +/* HW errors */ +#define MUNKI_HW_EE_SHORTREAD 0x21 /* Read fewer EEProm bytes than expected */ +#define MUNKI_HW_ME_SHORTREAD 0x22 /* Read measurement bytes than expected */ +#define MUNKI_HW_ME_ODDREAD 0x23 /* Read measurement bytes was not mult 274 */ +#define MUNKI_HW_CALIBVERSION 0x24 /* calibration version is unknown */ +#define MUNKI_HW_CALIBMATCH 0x25 /* calibration doesn't match device */ + +/* Sample read operation errors */ +#define MUNKI_RD_DARKREADINCONS 0x30 /* Dark calibration reading inconsistent */ +#define MUNKI_RD_SENSORSATURATED 0x31 /* Sensor is saturated */ +#define MUNKI_RD_DARKNOTVALID 0x32 /* Dark reading is not valid (too light) */ +#define MUNKI_RD_NEEDS_CAL 0x33 /* Mode needs calibration */ +#define MUNKI_RD_WHITEREADINCONS 0x34 /* White reference readings are inconsistent */ +#define MUNKI_RD_WHITEREFERROR 0x35 /* White reference reading error */ +#define MUNKI_RD_LIGHTTOOLOW 0x36 /* Light level is too low */ +#define MUNKI_RD_LIGHTTOOHIGH 0x37 /* Light level is too high */ +#define MUNKI_RD_SHORTMEAS 0x38 /* Measurment was too short */ +#define MUNKI_RD_READINCONS 0x39 /* Reading is inconsistent */ +#define MUNKI_RD_REFWHITENOCONV 0x3A /* White calibration didn't converge */ +#define MUNKI_RD_NOTENOUGHPATCHES 0x3B /* Not enough patches */ +#define MUNKI_RD_TOOMANYPATCHES 0x3C /* Too many patches */ +#define MUNKI_RD_NOTENOUGHSAMPLES 0x3D /* Not enough samples per patch */ +#define MUNKI_RD_NOFLASHES 0x3E /* No flashes recognized */ +#define MUNKI_RD_NOAMBB4FLASHES 0x3F /* No ambient before flashes found */ +#define MUNKI_RD_NOREFR_FOUND 0x40 /* Unable to measure refresh rate */ + +#define MUNKI_SPOS_PROJ 0x48 /* Sensor needs to be in projector position */ +#define MUNKI_SPOS_SURF 0x49 /* Sensor needs to be in surface position */ +#define MUNKI_SPOS_CALIB 0x4A /* Sensor needs to be in calibration position */ +#define MUNKI_SPOS_AMB 0x4B /* Sensor needs to be in ambient position */ + +/* Internal errors */ +#define MUNKI_INT_NO_COMS 0x50 +#define MUNKI_INT_EESIZE 0x51 /* EEProm read size is too big */ +#define MUNKI_INT_EEOUTOFRANGE 0x52 /* EEProm size is unexpected */ +#define MUNKI_INT_CALTOOSMALL 0x53 /* Calibration EEProm size is too small */ +#define MUNKI_INT_CALTOOBIG 0x54 /* Calibration EEProm size is too big */ +#define MUNKI_INT_CALBADCHSUM 0x55 /* Calibration has a bad checksum */ +#define MUNKI_INT_ODDREADBUF 0x56 /* Measurment read buffer is not mult 274 */ +#define MUNKI_INT_INTTOOBIG 0x57 /* Integration time is too big */ +#define MUNKI_INT_INTTOOSMALL 0x58 /* Integration time is too small */ +#define MUNKI_INT_ILLEGALMODE 0x59 /* Illegal measurement mode selected */ +#define MUNKI_INT_ZEROMEASURES 0x5A /* Number of measurements requested is zero */ +#define MUNKI_INT_WRONGPATCHES 0x5B /* Number of patches to match is wrong */ +#define MUNKI_INT_MEASBUFFTOOSMALL 0x5C /* Measurement read buffer is too small */ +#define MUNKI_INT_NOTIMPLEMENTED 0x5D /* Support not implemented */ +#define MUNKI_INT_NOTCALIBRATED 0x5E /* Unexpectedely invalid calibration */ +#define MUNKI_INT_THREADFAILED 0x5F /* Creation of thread failed */ +#define MUNKI_INT_BUTTONTIMEOUT 0x60 /* Switch status read timed out */ +#define MUNKI_INT_CIECONVFAIL 0x61 /* Creating spectral to CIE converted failed */ +#define MUNKI_INT_MALLOC 0x62 /* Error in mallocing memory */ +#define MUNKI_INT_CREATE_EEPROM_STORE 0x63 /* Error in creating EEProm store */ +#define MUNKI_INT_NEW_RSPL_FAILED 0x64 /* Creating RSPL object faild */ +#define MUNKI_INT_CAL_SAVE 0x65 /* Unable to save calibration to file */ +#define MUNKI_INT_CAL_RESTORE 0x66 /* Unable to restore calibration from file */ +#define MUNKI_INT_CAL_TOUCH 0x67 /* Unable to touch calibration file */ + + +#define MUNKI_INT_ASSERT 0x6F /* Internal assert */ + + +int icoms2munki_err(int se); + +/* ============================================================ */ +/* High level implementatation */ + +/* Initialise our software state from the hardware */ +munki_code munki_imp_init(munki *p); + +/* Return a pointer to the serial number */ +char *munki_imp_get_serial_no(munki *p); + +/* Set the measurement mode. It may need calibrating */ +munki_code munki_imp_set_mode( + munki *p, + mk_mode mmode, /* munki mode to use */ + int spec_en); /* nz to enable reporting spectral */ + +/* Implement get_n_a_cals */ +munki_code munki_imp_get_n_a_cals(munki *p, inst_cal_type *pn_cals, inst_cal_type *pa_cals); + +/* Calibrate for the current mode. */ +/* Request an instrument calibration of the current mode. */ +munki_code munki_imp_calibrate( +munki *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. */ +munki_code munki_imp_measure( + munki *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 */ +munki_code munki_imp_meas_refrate( + munki *p, + double *ref_rate +); + +/* return nz if high res is supported */ +int munki_imp_highres(munki *p); + +/* Set to high resolution mode */ +munki_code munki_set_highres(munki *p); + +/* Set to standard resolution mode */ +munki_code munki_set_stdres(munki *p); + +/* Modify the scan consistency tollerance */ +munki_code munki_set_scan_toll(munki *p, double toll_ratio); + + +/* Save the calibration for all modes, stored on local system */ +munki_code munki_save_calibration(munki *p); + +/* Restore the all modes calibration from the local system */ +munki_code munki_restore_calibration(munki *p); + + +/* ============================================================ */ +/* Intermediate routines - composite commands/processing */ + +/* Take a dark reference measurement - part 1 */ +munki_code munki_dark_measure_1( + munki *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 */ +munki_code munki_dark_measure_2( + munki *p, + double *sens, /* Return array [-1 nraw] of sens 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 */ +munki_code munki_dark_measure( + munki *p, + double *sens, /* Return array [-1 nraw] of sens 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 */ +/* (Subtracts black and processes into wavelenths) */ +munki_code munki_whitemeasure( + munki *p, + double *absraw, /* Return array [-1 nraw] of absraw values (may be NULL) */ + 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 */ +); + +/* Given an absraw white reference measurement, */ +/* compute the wavelength equivalents. */ +/* (absraw is usually ->white_data) */ +/* (abswav1 is usually ->cal_factor1) */ +/* (abswav2 is usually ->cal_factor2) */ +munki_code munki_compute_wav_whitemeas( + munki *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 /* Given array [-1 nraw] of absraw values */ +); + +/* Take a reflective white reference measurement, */ +/* subtracts black and decompose into base + LED temperature components */ +munki_code munki_ledtemp_whitemeasure( + munki *p, + double *white, /* Return [-1 nraw] of temperature compensated white reference */ + double **iwhite, /* Return array [-1 nraw][2] of absraw base and scale values */ + double *reftemp, /* Return a reference temperature to normalize to */ + int nummeas, /* Number of readings to take */ + double inttime, /* Integration time to use */ + int gainmode /* Gain mode to use, 0 = normal, 1 = high */ +); + +/* Given the ledtemp base and scale values, */ +/* return a raw reflective white reference for the */ +/* given temperature */ +munki_code munki_ledtemp_white( + munki *p, + double *absraw, /* Return array [-1 nraw] of absraw base and scale values */ + double **iwhite, /* ledtemp base and scale */ + double ledtemp /* LED temperature value */ +); + +/* Given a set of absraw sensor readings and the corresponding temperature, */ +/* compensate the readings to be at the nominated temperature. */ +munki_code munki_ledtemp_comp( + munki *p, + double **absraw, /* [nummeas][raw] measurements to compensate */ + double *ledtemp, /* LED temperature for each measurement */ + int nummeas, /* Number of measurements */ + double reftemp, /* LED reference temperature to compensate to */ + double **iwhite /* ledtemp base and scale information */ +); + +/* Heat the LED up for given number of seconds by taking a reading */ +munki_code munki_heatLED( + munki *p, + double htime /* Heat up time */ +); + +/* Process a single raw white reference measurement */ +/* (Subtracts black and processes into wavelenths) */ +munki_code munki_whitemeasure_buf( + munki *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 measurement reading using the current mode, part 1 */ +/* Converts to completely processed output readings. */ +munki_code munki_read_patches_1( + munki *p, + int ninvmeas, /* Number of extra invalid measurements at start */ + 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 (excluding ninvmeas) */ + 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. */ +munki_code munki_read_patches_2( + munki *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 ninvmeas, /* Number of extra invalid measurements at start */ + int nmeasuered, /* Number actually measured */ + unsigned char *buf, /* Raw USB reading buffer */ + unsigned int bsize +); + +/* Take a trial measurement reading using the current mode. */ +/* Used to determine if sensor is saturated, or not optimal */ +munki_code munki_trialmeasure( + munki *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 */ +); + +/* 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 munki_readmeasurement() */ +munki_code +munki_trigger_one_measure( + munki *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 */ + int calib_measure, /* flag - nz if this is a calibration measurement */ + int dark_measure /* flag - nz if this is a dark measurement */ +); + +/* ============================================================ */ +/* lower level reading processing */ + +/* Take a buffer full of sensor readings, and convert them to */ +/* directly to floating point raw values. */ +/* Return MUNKI_RD_SENSORSATURATED if any is saturated */ +munki_code munki_sens_to_raw( + munki *p, + double **raw, /* Array of [nummeas-ninvalid][-1 nraw] value to return */ + double *ledtemp, /* Optional array [nummeas-ninvalid] LED temperature values to return */ + unsigned char *buf, /* Sensor measurement data must be 274 * nummeas */ + int nummeas, /* Number of readings measured */ + int ninvalid, /* Number of initial invalid readings to skip */ + double satthresh, /* Sauration threshold in raw units */ + double *darkthresh /* Return a dark threshold value */ +); + +/* Subtract the black from raw values and convert to */ +/* absolute (integration & gain scaled), zero offset based, */ +/* linearized sensor values. */ +void munki_sub_raw_to_absraw( + munki *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, /* Value to subtract [-1 nraw] */ + double *trackmax, /* absraw values that should be offset the same as max */ + int ntrackmax, /* Number of trackmax values */ + double *maxv /* If not NULL, return the maximum value */ +); + +/* Average a set of sens or absens measurements into one. */ +/* (Make sure darkthresh is tracked if absens is being averaged!) */ +/* Return zero if readings are consistent and not saturated. */ +/* Return nz if the readings are not consistent */ +/* Return the overall average. */ +int munki_average_multimeas( + munki *p, + double *avg, /* return average [-1 nraw] */ + double **multimeas, /* Array of [nummeas][-1 nraw] value to average */ + int nummeas, /* number of readings to be averaged */ + double *poallavg, /* If not NULL, return overall average of bands and measurements */ + 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. */ +/* Return flags nz if the readings are not consistent */ +munki_code munki_extract_patches_multimeas( + munki *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 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 */ +munki_code munki_extract_patches_flash( + munki *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) */ +); + +/* Convert an absraw array from raw wavelengths to output wavelenths */ +/* for the current resolution */ +void munki_absraw_to_abswav( + munki *p, + int nummeas, /* Return number of readings measured */ + double **abswav, /* Desination array [nwav] */ + double **absraw /* Source array [-1 nraw] */ +); + +/* Convert an absraw array from raw wavelengths to output wavelenths */ +/* for the standard resolution */ +void munki_absraw_to_abswav1( + munki *p, + int nummeas, /* Return number of readings measured */ + double **abswav, /* Desination array [nwav1] */ + double **absraw /* Source array [-1 nraw] */ +); + +/* Convert an absraw array from raw wavelengths to output wavelenths */ +/* for the high resolution */ +void munki_absraw_to_abswav2( + munki *p, + int nummeas, /* Return number of readings measured */ + double **abswav, /* Desination array [nwav2] */ + double **absraw /* Source array [-1 nraw] */ +); + +/* Convert an abswav array of output wavelengths to scaled output readings. */ +void munki_scale_specrd( + munki *p, + double **outspecrd, /* Destination */ + int numpatches, /* Number of readings/patches */ + double **inspecrd /* Source */ +); + +/* Convert from spectral to XYZ, and transfer to the ipatch array */ +munki_code munki_conv2XYZ( + munki *p, + ipatch *vals, /* Values to return */ + int nvals, /* Number of values */ + double **specrd, /* Spectral readings */ + instClamping clamp /* Clamp XYZ/Lab to be +ve */ +); + +/* Compute a calibration factor given the reading of the white reference. */ +/* Return nz if any of the transmission wavelengths are low */ +int munki_compute_white_cal( + munki *p, + 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 */ + double *cal_factor2, /* [nwav2] Calibration factor to compute */ + double *white_ref2, /* [nwav2] White reference to aim for, NULL for 1.0 */ + double *white_read2 /* [nwav2] The white that was read */ +); + +/* For adaptive mode, compute a new integration time and gain mode */ +/* in order to optimise the sensor values. */ +munki_code munki_optimise_sensor( + munki *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) */ + /* (May be altered if integration time isn't possible) */ + double scale, /* scale needed of current int time to reach optimum */ + double deadtime /* Dead integration time (if any) */ +); + +/* Compute the number of measurements needed, given the target */ +/* time and integration time. Will return 0 if target time is 0 */ +int munki_comp_nummeas( + munki *p, + double meas_time, + double int_time +); + +/* Compute the rounded up number of measurements needed, */ +/* given the target time and integration time. */ +/* Will return 0 if target time is 0 */ +int munki_comp_ru_nummeas( + munki *p, + double meas_time, + double int_time +); + +/* Convert the dark interpolation data to a useful state */ +void munki_prepare_idark(munki *p); + +/* Create the dark reference for the given integration time and gain */ +/* by interpolating from the 4 readings taken earlier. */ +munki_code munki_interp_dark( + munki *p, + double *result, /* Put result of interpolation here */ + double inttime, + int gainmode +); + +/* Create high resolution mode references. */ +/* Create Reflective if ref nz, else create Emissive */ +munki_code munki_create_hr(munki *p, int ref); + +/* Set the noinitcalib mode */ +void munki_set_noinitcalib(munki *p, int v, int losecs); + +/* Set the trigger config */ +void munki_set_trig(munki *p, inst_opt_type trig); + +/* Return the trigger config */ +inst_opt_type munki_get_trig(munki *p); + +/* Set the trigger return */ +void munki_set_trigret(munki *p, int val); + +/* Switch thread handler */ +int munki_switch_thread(void *pp); + +/* ============================================================ */ +/* Low level commands */ + +/* USB Commands */ + +/* Read from the EEProm */ +munki_code +munki_readEEProm( + struct _munki *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) */ +); + + +/* Get the firmware parameters */ +/* return pointers may be NULL if not needed. */ +munki_code +munki_getfirm( + munki *p, + int *fwrev, /* Return the formware version number as 8.8 */ + int *tickdur, /* Tick duration */ + int *minintcount, /* Minimum integration tick count */ + int *noeeblocks, /* Number of EEPROM blocks */ + int *eeblocksize /* Size of each block */ +); + +/* Get the Chip ID */ +munki_code +munki_getchipid( + munki *p, + unsigned char chipid[8] +); + +/* Get the Version String */ +munki_code +munki_getversionstring( + munki *p, + char vstring[37] +); + +/* Get the measurement state */ +/* return pointers may be NULL if not needed. */ +munki_code +munki_getmeasstate( + munki *p, + int *ledtrange, /* LED temperature range */ + int *ledtemp, /* LED temperature */ + int *dutycycle, /* Duty Cycle */ + int *ADfeedback /* A/D converter feedback */ +); + +/* Munki sensor positions */ +typedef enum { + mk_spos_proj = 0x00, /* Projector/Between detents */ + mk_spos_surf = 0x01, /* Surface */ + mk_spos_calib = 0x02, /* Calibration tile */ + mk_spos_amb = 0x03 /* Ambient */ +} mk_spos; + +/* Munki switch state */ +typedef enum { + mk_but_switch_release = 0x00, /* Button is released */ + mk_but_switch_press = 0x01 /* Button is pressed */ +} mk_but; + +/* Get the device status */ +/* return pointers may be NULL if not needed. */ +munki_code +munki_getstatus( + munki *p, + mk_spos *spos, /* Return the sensor position */ + mk_but *but /* Return Button state */ +); + +/* Set the indicator LED state */ +munki_code +munki_setindled( + munki *p, + int ontime, /* On time (msec) */ + int offtrime, /* Off time (msec) */ + int transtime, /* Transition time (msec) */ + int nopulses, /* Number of pulses, -1 = max */ + int p5 /* Ignored ? */ +); + +/* Measuremend mode flags */ +#define MUNKI_MMF_LAMP 0x01 /* Lamp mode, else no illumination of sample */ +#define MUNKI_MMF_SCAN 0x02 /* Scan mode bit, else spot mode */ +#define MUNKI_MMF_HIGHGAIN 0x04 /* High gain, else normal gain. */ + +/* Trigger a measurement with the given measurement parameters */ +munki_code +munki_triggermeasure( + munki *p, + int intclocks, /* Number of integration clocks */ + int nummeas, /* Number of measurements to make */ + int measmodeflags, /* Measurement mode flags */ + int holdtempduty /* Hold temperature duty cycle */ +); + +/* Read a measurements results */ +munki_code +munki_readmeasurement( + munki *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 */ + int calib_measure, /* flag - nz if this is a calibration measurement */ + int dark_measure /* flag - nz if this is a dark measurement */ +); + +/* Set the measurement clock mode */ +/* Version >= 301 only */ +munki_code +munki_setmcmode( + munki *p, + int mcmode /* Measurement clock mode, 1..mxmcmode */ +); + +/* Munki event values, returned by event pipe, or */ +/* parameter to simulate event */ +typedef enum { + mk_eve_none = 0x0000, /* No event */ + mk_eve_switch_press = 0x0001, /* Button has been pressed */ + mk_eve_switch_release = 0x0002, /* Button has been released */ + mk_eve_spos_change = 0x0100 /* Sensor position is being changed */ +} mk_eve; + +/* Simulating an event (use to terminate event thread) */ +/* timestamp is msec since munki power up */ +munki_code munki_simulate_event(munki *p, mk_eve ecode, int timestamp); + +/* Wait for a reply triggered by a key press */ +munki_code munki_waitfor_switch(munki *p, mk_eve *ecode, int *timest, double top); + +/* Wait for a reply triggered by a key press (thread version) */ +munki_code munki_waitfor_switch_th(munki *p, mk_eve *ecode, int *timest, double top); + +/* -------------------------------------------------- */ +/* EEProm parsing support. */ + +/* Initialise the calibration from the EEProm contents. */ +/* (We're handed a buffer that's been rounded up to an even 32 bits by */ +/* padding with zero's) */ +munki_code munki_parse_eeprom(munki *p, unsigned char *buf, unsigned int len); + +struct _mkdata { + /* private: */ + munki *p; + + a1log *log; + unsigned char *buf; /* Buffer to parse */ + int len; /* Length of buffer */ + + /* public: */ + + /* Return a pointer to an array of chars containing data from 8 bits. */ + /* If rv is NULL, the returned value will have been allocated, othewise */ + /* the rv will be returned. Return NULL if out of range. */ + unsigned char *(*get_8_char)(struct _mkdata *d, unsigned char *rv, int offset, int count); + + /* Return a pointer to an nul terminated string containing data from 8 bits. */ + /* If rv is NULL, the returned value will have been allocated, othewise */ + /* the rv will be returned. Return NULL if out of range. */ + /* An extra space and a nul terminator will be added to the eeprom data */ + char *(*get_8_asciiz)(struct _mkdata *d, char *rv, int offset, int count); + + + /* Return a pointer to an array of ints containing data from 8 bits. */ + /* If rv is NULL, the returned value will have been allocated, othewise */ + /* the rv will be returned. Return NULL if out of range. */ + int *(*get_8_ints)(struct _mkdata *d, int *rv, int offset, int count); + + /* Return a pointer to an array of ints containing data from unsigned 8 bits. */ + /* If rv is NULL, the returned value will have been allocated, othewise */ + /* the rv will be returned. Return NULL if out of range. */ + int *(*get_u8_ints)(struct _mkdata *d, int *rv, int offset, int count); + + + /* Return a pointer to an array of ints containing data from 16 bits. */ + /* If rv is NULL, the returned value will have been allocated, othewise */ + /* the rv will be returned. Return NULL if out of range. */ + int *(*get_16_ints)(struct _mkdata *d, int *rv, int offset, int count); + + /* Return a pointer to an array of ints containing data from unsigned 16 bits. */ + /* If rv is NULL, the returned value will have been allocated, othewise */ + /* the rv will be returned. Return NULL if out of range. */ + int *(*get_u16_ints)(struct _mkdata *d, int *rv, int offset, int count); + + + /* Return a pointer to an array of ints containing data from 32 bits. */ + /* If rv is NULL, the returned value will have been allocated, othewise */ + /* the rv will be returned. Return NULL if out of range. */ + int *(*get_32_ints)(struct _mkdata *d, int *rv, int offset, int count); + + /* Return a pointer to an array of unsigned ints containing data from 32 bits. */ + /* If rv is NULL, the returned value will have been allocated, othewise */ + /* the rv will be returned. Return NULL if out of range. */ + unsigned int *(*get_u32_uints)(struct _mkdata *d, unsigned int *rv, int offset, int count); + + + /* Return a pointer to an array of doubles containing data from 32 bits. */ + /* If rv is NULL, the returned value will have been allocated, othewise */ + /* the rv will be returned. Return NULL if out of range. */ + double *(*get_32_doubles)(struct _mkdata *d, double *rv, int offset, int count); + + /* Return a pointer to an array of doubles containing data from 32 bits, */ + /* with the array filled in reverse order. */ + /* If rv is NULL, the returned value will have been allocated, othewise */ + /* the rv will be returned. Return NULL if out of range. */ + double *(*rget_32_doubles)(struct _mkdata *d, double *rv, int offset, int count); + + /* Destroy ourselves */ + void (*del)(struct _mkdata *d); + +}; typedef struct _mkdata mkdata; + +/* Constructor. Construct from the EEprom calibration contents */ +extern mkdata *new_mkdata(munki *p, unsigned char *buf, int len); + +#ifdef __cplusplus + } +#endif + +#define MUNKI_IMP +#endif /* MUNKI_IMP */ |